diff options
| -rw-r--r-- | network-handler/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | network-handler/acceptor.cpp | 59 | ||||
| -rw-r--r-- | network-handler/acceptor.hpp | 18 | ||||
| -rw-r--r-- | network-handler/client.cpp | 39 | ||||
| -rw-r--r-- | network-handler/client.hpp | 23 | ||||
| -rw-r--r-- | network-handler/networkhandler.cpp | 72 | ||||
| -rw-r--r-- | network-handler/networkhandler.hpp | 17 |
7 files changed, 182 insertions, 59 deletions
diff --git a/network-handler/CMakeLists.txt b/network-handler/CMakeLists.txt index 9f3366c..12898dc 100644 --- a/network-handler/CMakeLists.txt +++ b/network-handler/CMakeLists.txt @@ -4,14 +4,23 @@ find_package(Boost COMPONENTS system program_options REQUIRED) add_executable(network-handler main.cpp networkhandler.hpp networkhandler.cpp + acceptor.hpp acceptor.cpp + client.hpp client.cpp ) target_compile_options(network-handler - PRIVATE "-std=c++11" + PRIVATE "-std=c++14" ) target_link_libraries(network-handler PRIVATE Boost::boost PRIVATE Boost::program_options PRIVATE Boost::system -)
\ No newline at end of file +) + +if(WIN32) + target_link_libraries(network-handler + PRIVATE wsock32 + PRIVATE ws2_32 + ) +endif() diff --git a/network-handler/acceptor.cpp b/network-handler/acceptor.cpp new file mode 100644 index 0000000..34b5f0e --- /dev/null +++ b/network-handler/acceptor.cpp @@ -0,0 +1,59 @@ +#include "acceptor.hpp" + +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ip/v6_only.hpp> +#include <boost/asio/placeholders.hpp> +#include <boost/bind.hpp> + + +using namespace boost::asio; +using namespace boost::asio::ip; + +void accept_loop(tcp::acceptor& acceptor, std::function<void(tcp::socket&&)> f); + +void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<tcp::socket> socket, boost::system::error_code ec, std::function<void(boost::asio::ip::tcp::socket&&)> f) +{ + if(!bool(ec)) + { + f(std::move(*socket)); + accept_loop(acceptor, f); + } else { + std::stringstream ss; + ss << ec; + throw std::runtime_error(ss.str()); + } + +} + +void accept_loop(tcp::acceptor& acceptor, std::function<void(tcp::socket&&)> f) +{ + std::shared_ptr<tcp::socket> new_socket = std::make_shared<tcp::socket>(acceptor.get_io_service()); + + acceptor.async_accept(*new_socket, boost::bind(accept_connection, boost::ref(acceptor), new_socket, boost::asio::placeholders::error, f)); +} + +Acceptor::Acceptor(boost::asio::io_service &io_service, boost::asio::ip::address address, uint16_t port) +: acceptor(io_service) +, endpoint(address, port) +{} + +void Acceptor::bind_v6_and_v4_any(std::function<void(tcp::socket&&)> accept_handler) { + acceptor.open(endpoint.protocol()); + + v6_only option(false); + acceptor.set_option(option); + + acceptor.bind(endpoint); + acceptor.listen(); + + accept_loop(acceptor, accept_handler); +} + +void Acceptor::setup_listen_socket(std::function<void (tcp::socket &&)> accept_handler) +{ + acceptor.open(endpoint.protocol()); + acceptor.bind(endpoint); + acceptor.listen(); + + accept_loop(acceptor, accept_handler); +} diff --git a/network-handler/acceptor.hpp b/network-handler/acceptor.hpp new file mode 100644 index 0000000..7d8e0a2 --- /dev/null +++ b/network-handler/acceptor.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include <boost/asio/ip/tcp.hpp> + +#include <functional> + +class Acceptor{ + boost::asio::ip::tcp::acceptor acceptor; + boost::asio::ip::tcp::endpoint endpoint; + +public: + Acceptor(boost::asio::io_service& io_service, boost::asio::ip::address address, uint16_t port); + + boost::asio::ip::address get_address() { return endpoint.address(); } + + void bind_v6_and_v4_any(std::function<void(boost::asio::ip::tcp::socket&&)> accept_handler); + void setup_listen_socket(std::function<void(boost::asio::ip::tcp::socket&&)> accept_handler); +}; diff --git a/network-handler/client.cpp b/network-handler/client.cpp new file mode 100644 index 0000000..816753c --- /dev/null +++ b/network-handler/client.cpp @@ -0,0 +1,39 @@ +#include "client.hpp" + +#include <boost/asio/placeholders.hpp> +#include <boost/bind.hpp> + +#include <iostream> + +using namespace boost::asio::ip; +using namespace boost::system; + +Client::Client(tcp::socket &&socket) +: socket(std::move(socket)) +, buffer() +{} + +void Client::handle_receive(const error_code &ec, size_t read_bytes) +{ + if(!ec) { + std::string str(buffer.begin(), buffer.end()); + std::cout << "Received: " << str << std::endl; + receive(); + } else { + on_done(); + } +} + +void Client::receive() { + using namespace boost::asio::placeholders; + + memset(buffer.data(), 0, buffer.size()); + socket.async_receive( + boost::asio::buffer(buffer), + boost::bind(&Client::handle_receive, this, error(), bytes_transferred()) + ); +} + +void Client::set_on_done(Client::OnDoneFT f) { + on_done = f; +} diff --git a/network-handler/client.hpp b/network-handler/client.hpp new file mode 100644 index 0000000..878c5be --- /dev/null +++ b/network-handler/client.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include <boost/asio/ip/tcp.hpp> + +#include <array> + +class Client { +public: + typedef std::function<void(void)> OnDoneFT; + +private: + boost::asio::ip::tcp::socket socket; + std::array<uint8_t, 20> buffer; + OnDoneFT on_done; + + +public: + Client(boost::asio::ip::tcp::socket&& socket); + + void handle_receive(boost::system::error_code const& ec, size_t read_bytes); + void receive(); + void set_on_done(OnDoneFT f); +}; diff --git a/network-handler/networkhandler.cpp b/network-handler/networkhandler.cpp index 987d2a1..8c5997f 100644 --- a/network-handler/networkhandler.cpp +++ b/network-handler/networkhandler.cpp @@ -1,6 +1,7 @@ #include "networkhandler.hpp" #include <boost/bind.hpp> +#include <boost/asio/placeholders.hpp> #include <memory> #include <iostream> @@ -8,48 +9,25 @@ using namespace boost::asio::ip; using namespace boost::asio; -void accept_loop(tcp::acceptor& acceptor, std::function<void(tcp::socket&&)> f); - -void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<tcp::socket> socket, boost::system::error_code ec, std::function<void(boost::asio::ip::tcp::socket&&)> f) -{ - if(!bool(ec)) - { - f(std::move(*socket)); - accept_loop(acceptor, f); - } else { - std::stringstream ss; - ss << ec; - throw std::runtime_error(ss.str()); - } - -} - -void accept_loop(tcp::acceptor& acceptor, std::function<void(tcp::socket&&)> f) -{ - std::shared_ptr<tcp::socket> new_socket = std::make_shared<tcp::socket>(acceptor.get_io_service()); - - acceptor.async_accept(*new_socket, boost::bind(accept_connection, boost::ref(acceptor), new_socket, boost::asio::placeholders::error, f)); -} - -void setup_listen_socket(tcp::acceptor& acceptor, tcp::endpoint& endpoint, std::function<void(tcp::socket&& socket)> f) { - acceptor.open(endpoint.protocol()); - acceptor.bind(endpoint); - acceptor.listen(); - - accept_loop(acceptor, f); -} - NetworkHandler::NetworkHandler(const ListenSettings& listen_settings) : listen_settings(listen_settings) , io_service() -, v4_acceptor(io_service) -, v6_acceptor(io_service) -, v4_endpoint(address_v4::from_string(listen_settings.ipv4_inaddr), listen_settings.port) -, v6_endpoint(address_v6::from_string(listen_settings.ipv6_inaddr), listen_settings.port) +, v4_acceptor(io_service, address_v4::from_string(listen_settings.ipv4_inaddr), listen_settings.port) +, v6_acceptor(io_service, address_v6::from_string(listen_settings.ipv6_inaddr), listen_settings.port) +, stdin_buffer() +, clients() { auto accept_handler = [this](tcp::socket&& socket) { - accepted_connections.push_back(std::move(socket)); - std::cout << "Yippie" << std::endl; + clients.push_back(Client(std::move(socket))); + auto it = --clients.end(); + + clients.back().set_on_done( + [this, it]() { + clients.erase(it); + } + ); + + clients.back().receive(); }; /* @@ -58,28 +36,22 @@ NetworkHandler::NetworkHandler(const ListenSettings& listen_settings) * respective inaddr_any we need to bind to v6 any and disable ipv6 only on * the acceptor socket, else we can just bind to the interfaces normally. */ - bool bind_v4_any = v4_endpoint.address().to_v4() == address_v4::any() && listen_settings.enable_ipv4; - bool bind_v6_any = v6_endpoint.address().to_v6() == address_v6::any() && listen_settings.enable_ipv6; + bool bind_v4_any = v4_acceptor.get_address().to_v4() == address_v4::any() && listen_settings.enable_ipv4; + bool bind_v6_any = v6_acceptor.get_address().to_v6() == address_v6::any() && listen_settings.enable_ipv6; if(bind_v4_any && bind_v6_any) { - v6_acceptor.open(v6_endpoint.protocol()); - - v6_only option(false); - v6_acceptor.set_option(option); - - v6_acceptor.bind(v6_endpoint); - v6_acceptor.listen(); - - accept_loop(v6_acceptor, accept_handler); + v6_acceptor.bind_v6_and_v4_any(accept_handler); } else if(bind_v4_any || bind_v6_any) { throw std::runtime_error("Cannot bind an INADDR_ANY and a non INADDR_ANY address on ipv4 and ipv6"); } else { if(listen_settings.enable_ipv4) { - setup_listen_socket(v4_acceptor, v4_endpoint, accept_handler); + v4_acceptor.setup_listen_socket(accept_handler); } if(listen_settings.enable_ipv6) { - setup_listen_socket(v6_acceptor, v6_endpoint, accept_handler); + v6_acceptor.setup_listen_socket(accept_handler); } } + + //read_stdin(); } void NetworkHandler::run() { diff --git a/network-handler/networkhandler.hpp b/network-handler/networkhandler.hpp index d0eab6f..c4930ca 100644 --- a/network-handler/networkhandler.hpp +++ b/network-handler/networkhandler.hpp @@ -1,7 +1,10 @@ #pragma once +#include "acceptor.hpp" +#include "client.hpp" + #include <boost/asio/io_service.hpp> -#include <boost/asio.hpp> +#include <boost/asio/streambuf.hpp> #include <string> #include <cstdint> @@ -20,12 +23,12 @@ class NetworkHandler ListenSettings const& listen_settings; boost::asio::io_service io_service; - boost::asio::ip::tcp::acceptor v4_acceptor; - boost::asio::ip::tcp::acceptor v6_acceptor; - boost::asio::ip::tcp::endpoint v4_endpoint; - boost::asio::ip::tcp::endpoint v6_endpoint; - - std::list<boost::asio::ip::tcp::socket> accepted_connections; + Acceptor v4_acceptor; + Acceptor v6_acceptor; + + boost::asio::streambuf stdin_buffer; + + std::list<Client> clients; public: NetworkHandler(ListenSettings const& listen_settings); |
