Skip to content

Commit

Permalink
Update Boost library version and add JSON submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardodebenedictis committed Apr 17, 2024
1 parent b3378cf commit 3afdfe8
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 15 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
cmake_minimum_required(VERSION 3.5.0)
project(ratioNet VERSION 0.2.0 LANGUAGES CXX)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined")

include(CTest)
enable_testing()

find_package(Boost REQUIRED COMPONENTS system)

add_subdirectory(extern/json)

option(USE_SSL "Use Secure Sockets Layer (SSL) for secure communication" OFF)
set(SERVER_ADDRESS "0.0.0.0" CACHE STRING "The address the server listens on")
set(SERVER_PORT "8080" CACHE STRING "The port the server listens on")
Expand All @@ -28,7 +31,7 @@ endif()


add_library(ratioNet src/server.cpp)
target_link_libraries(ratioNet PUBLIC Boost::system)
target_link_libraries(ratioNet PUBLIC Boost::system json)
target_include_directories(ratioNet PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_compile_definitions(ratioNet PUBLIC SERVER_ADDRESS="${SERVER_ADDRESS}" SERVER_PORT="${SERVER_PORT}")

Expand Down
2 changes: 1 addition & 1 deletion extern/json
49 changes: 46 additions & 3 deletions include/server.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <boost/asio.hpp>
#include "json.hpp"

namespace network
{
Expand Down Expand Up @@ -40,17 +41,22 @@ namespace network

private:
void on_read(const boost::system::error_code &ec, std::size_t bytes_transferred);
void on_body(const boost::system::error_code &ec, std::size_t bytes_transferred);

private:
server &srv;
boost::asio::ip::tcp::socket socket;
boost::asio::streambuf buffer;
verb v;
std::string target, version;
std::map<std::string, std::string> headers;
};

class request
{
public:
request(std::shared_ptr<session> s, verb v, std::string &&trgt, std::string &&ver, std::map<std::string, std::string> &&hdrs) : s(s), v(v), target(trgt), version(ver), headers(hdrs) {}
~request() = default;

verb get_verb() const { return v; }
const std::string &get_target() const { return target; }
Expand All @@ -65,14 +71,51 @@ namespace network
return os;
}

private:
protected:
std::shared_ptr<session> s;
verb v;
std::string target;
std::string version;
std::string target, version;
std::map<std::string, std::string> headers;
};

class string_request : public request
{
public:
string_request(std::shared_ptr<session> s, verb v, std::string &&trgt, std::string &&ver, std::map<std::string, std::string> &&hdrs, std::string &&b) : request(s, v, std::move(trgt), std::move(ver), std::move(hdrs)), body(std::move(b)) {}
~string_request() = default;

const std::string &get_body() const { return body; }

friend std::ostream &operator<<(std::ostream &os, const string_request &req)
{
os << static_cast<const request &>(req);
os << req.body;
return os;
}

private:
std::string body;
};

class json_request : public request
{
public:
json_request(std::shared_ptr<session> s, verb v, std::string &&trgt, std::string &&ver, std::map<std::string, std::string> &&hdrs, json::json &&b) : request(s, v, std::move(trgt), std::move(ver), std::move(hdrs)), body(std::move(b)) {}
~json_request() = default;

const json::json &get_body() const { return body; }

friend std::ostream &operator<<(std::ostream &os, const json_request &req)
{
os << static_cast<const request &>(req);
os << req.body;
return os;
}

private:
json::json body;
};

class server
{
friend class session;
Expand Down
50 changes: 40 additions & 10 deletions src/server.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <iostream>
#include "server.hpp"
#include "logging.hpp"

namespace network
{
Expand All @@ -12,13 +13,12 @@ namespace network
{
if (ec)
{
std::cerr << ec.message() << std::endl;
LOG_ERR(ec.message());
return;
}

std::istream is(&buffer);

verb v;
switch (is.get())
{
case 'D':
Expand All @@ -45,18 +45,15 @@ namespace network
}
is.get(); // consume space

std::string target;
while (is.peek() != ' ')
target += is.get();
is.get(); // consume space

std::string version;
while (is.peek() != '\r')
version += is.get();
is.get(); // consume '\r'
is.get(); // consume '\n'

std::map<std::string, std::string> headers;
while (is.peek() != '\r')
{
std::string header, value;
Expand All @@ -73,38 +70,71 @@ namespace network
is.get(); // consume '\r'
is.get(); // consume '\n'

if (headers.find("Upgrade") != headers.end())
{ // handle websocket
LOG_DEBUG("Websocket not implemented");
return;
}

if (headers.find("Content-Length") != headers.end())
{ // read body
std::size_t content_length = std::stoul(headers["Content-Length"]);
boost::asio::async_read(socket, buffer, boost::asio::transfer_exactly(content_length), std::bind(&session::on_body, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
else
srv.handle_request(request(shared_from_this(), v, std::move(target), std::move(version), std::move(headers)));
}

void session::on_body(const boost::system::error_code &ec, std::size_t bytes_transferred)
{
if (ec)
{
LOG_ERR(ec.message());
return;
}

std::istream is(&buffer);
if (headers.find("Content-Type") != headers.end())
{
if (headers["Content-Type"] == "application/json")
return srv.handle_request(json_request(shared_from_this(), v, std::move(target), std::move(version), std::move(headers), json::load(is)));
std::string body;
while (is.peek() != EOF)
body += is.get();
return srv.handle_request(string_request(shared_from_this(), v, std::move(target), std::move(version), std::move(headers), std::move(body)));
}
srv.handle_request(request(shared_from_this(), v, std::move(target), std::move(version), std::move(headers)));
}

server::server(const std::string &address, unsigned short port, std::size_t concurrency_hint) : io_ctx(concurrency_hint), endpoint(boost::asio::ip::make_address(address), port), acceptor(boost::asio::make_strand(io_ctx)) { threads.reserve(concurrency_hint); }

void server::start()
{
std::cout << "Starting server on " << endpoint << std::endl;
LOG_INFO("Starting server on " + endpoint.address().to_string() + ":" + std::to_string(endpoint.port()));

boost::system::error_code ec;
acceptor.open(endpoint.protocol(), ec);
if (ec)
{
std::cerr << ec.message() << std::endl;
LOG_ERR(ec.message());
return;
}
acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec);
if (ec)
{
std::cerr << ec.message() << std::endl;
LOG_ERR(ec.message());
return;
}
acceptor.bind(endpoint, ec);
if (ec)
{
std::cerr << ec.message() << std::endl;
LOG_ERR(ec.message());
return;
}
acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
if (ec)
{
std::cerr << ec.message() << std::endl;
LOG_ERR(ec.message());
return;
}

Expand Down

0 comments on commit 3afdfe8

Please sign in to comment.