diff options
29 files changed, 236 insertions, 746 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 92b61d9..5056777 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,11 +27,10 @@ add_subdirectory(libcmix-crypto) add_subdirectory(libcmix) add_subdirectory(liblog) -add_subdirectory(libcmix-network) add_subdirectory(libcmix-protobuf) +add_subdirectory(libcmix-network) -add_subdirectory(network-handler) add_subdirectory(node) add_subdirectory(client) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index e04bf6a..489a136 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -3,7 +3,6 @@ find_package(Boost COMPONENTS system program_options REQUIRED) add_executable(client main.cpp cmixclient.hpp cmixclient.cpp - node.hpp node.cpp ) if(WIN32) diff --git a/client/cmixclient.cpp b/client/cmixclient.cpp index 195c5e0..1ffd904 100644 --- a/client/cmixclient.cpp +++ b/client/cmixclient.cpp @@ -2,15 +2,16 @@ #include "cmixclient.hpp" void CMixClient::key_exchange(int i) { - shared_keys.resize(network_connections.size()); + BOOST_LOG_TRIVIAL(trace) << "Sending KeyExchange for node: " << i; + shared_keys.resize(network_details.size()); cmix_proto::KeyExchange ke; ke.set_public_key(keypair.pub, keypair.pub_len); - network_connections[i].send(ke); + network_connections[i].async_send(ke); cmix_proto::Bye bye; - network_connections[i].send(bye); + network_connections[i].async_send(bye); } void CMixClient::initialize_connections() { @@ -20,25 +21,14 @@ void CMixClient::initialize_connections() { auto handler = [this, i]() mutable { cmix_proto::ImAClient imaclient; BOOST_LOG_TRIVIAL(trace) << "sending imaclient to node: " << i; - network_connections.at(i).send(imaclient); + network_connections.at(i).async_send(imaclient); key_exchange(i); }; network_connections.emplace_back(boost::asio::ip::tcp::socket(io_service)); network_connections.back().async_connect(network_details[i].host, network_details[i].port, handler); - - } -} - -cmix_proto::CMixMessage CMixClient::parse_cmix_message(std::vector<uint8_t> const& buffer) -{ - cmix_proto::CMixMessage message; - if(!message.ParseFromArray(buffer.data(), buffer.size())) { - BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; - throw std::runtime_error("Network communication was disrupted in a unrecoverable way."); } - return message; } void CMixClient::handle_key_exchange(int node_id, cmix_proto::KeyExchange const& ke) @@ -46,19 +36,8 @@ void CMixClient::handle_key_exchange(int node_id, cmix_proto::KeyExchange const& shared_keys[node_id] = api.derive_shared_key(keypair, reinterpret_cast<uint8_t const*>(ke.public_key().c_str()), false); } -void CMixClient::handle_message(int node_id, std::vector<uint8_t> const& message_buffer) +void CMixClient::handle_message(int node_id, cmix_proto::CMixMessage message) { - cmix_proto::CMixMessage message; - try { - message = parse_cmix_message(message_buffer); - } catch(std::runtime_error const& e) { - for(auto&& connection : network_connections) { - connection.close(); - } - io_service.stop(); - return; - } - switch(message.contents_case()) { case cmix_proto::CMixMessage::ContentsCase::kKeyexchange: { handle_key_exchange(node_id, *message.mutable_keyexchange()); @@ -85,6 +64,11 @@ CMixClient::CMixClient(std::vector<NodeDetails> details) initialize_connections(); } +CMixClient::~CMixClient() +{ + api.free_key_pair(keypair); +} + void CMixClient::run() { io_service.run(); } diff --git a/client/cmixclient.hpp b/client/cmixclient.hpp index 5c6405a..056e2b3 100644 --- a/client/cmixclient.hpp +++ b/client/cmixclient.hpp @@ -1,6 +1,6 @@ #pragma once -#include "node.hpp" +#include "protobufclient.hpp" #include "api.h" #include "logging.hpp" @@ -21,7 +21,7 @@ class CMixClient { boost::asio::io_service io_service; std::vector<NodeDetails> network_details; - std::vector<Node> network_connections; + std::vector<ProtobufClient<SendReceive>> network_connections; Api api; KeyPair keypair; @@ -31,14 +31,13 @@ class CMixClient { void initialize_connections(); - cmix_proto::CMixMessage parse_cmix_message(std::vector<uint8_t> const& buffer); - void handle_key_exchange(int node_id, cmix_proto::KeyExchange const& ke); - void handle_message(int node_id, std::vector<uint8_t> const& message_buffer); + void handle_message(int node_id, cmix_proto::CMixMessage message); public: CMixClient(std::vector<NodeDetails> details); + ~CMixClient(); void run(); };
\ No newline at end of file diff --git a/client/node.cpp b/client/node.cpp deleted file mode 100644 index 46375f4..0000000 --- a/client/node.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "node.hpp" - -#include "logging.hpp" - -using namespace boost::asio::ip; - -Node::Node(tcp::socket&& socket) -: client(std::move(socket)) -{} - -void Node::async_connect(std::string next_host, std::string next_port, std::function<void ()> on_connect) -{ - client.async_connect(next_host, next_port, on_connect); -} - -void Node::receive(std::function<void (const std::vector<uint8_t>&)> receive_handler) { - client.receive(receive_handler); -} - -void Node::close() -{ - client.close(); -} diff --git a/client/node.hpp b/client/node.hpp deleted file mode 100644 index afcf56a..0000000 --- a/client/node.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "client.hpp" - -#include "cmix.pb.h" - -#include <boost/asio/ip/tcp.hpp> - -/*! - * \file - */ - -/*! - * MESSAGE_SETTER is a boilerplate macro that generates a setter function for our CMix - * protobuf messages, This because there are seperate functions for each to type to use. - * And there seems no way to solve this using templates. - */ -#define MESSAGE_SETTER(TYPE, NAME) \ -inline void message_setter(cmix_proto::CMixMessage& m, cmix_proto::TYPE const& v) { \ - *m.mutable_##NAME() = v; \ -} \ - -MESSAGE_SETTER(ImAClient, imaclient) -MESSAGE_SETTER(Bye, bye) -MESSAGE_SETTER(KeyExchange, keyexchange) - -#undef MESSAGE_SETTER - -/*! - * \brief The Node class represents a node in the network. - */ -class Node -{ - Client client; -public: - /*! - * \brief Node - * \param socket an rvalue reference to the socket it takes ownership and uses to communicate with the next node in the network. - */ - Node(boost::asio::ip::tcp::socket&& socket); - - /*! - * \brief send - * \param v The CMixMessage type we try to send and first have to wrap in a CMixMessage. - */ - template <typename T> - void send(T v) { - cmix_proto::CMixMessage m; - message_setter(m, v); - client.send(m.SerializeAsString()); - } - - /*! - * \brief receive - * \param receive_handler - */ - void receive(std::function<void(std::vector<uint8_t> const&)> receive_handler); - - /*! - * \brief async_connect - * \param next_host The host of the next node. - * \param next_port The port of the next node. - * \param on_connect The callback to call when the connect was succesfull. - */ - void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect); - - /*! - * \brief close This function closes the underlying socket connection. - */ - void close(); -}; - diff --git a/libcmix-network/CMakeLists.txt b/libcmix-network/CMakeLists.txt index 5891254..c64c8b7 100644 --- a/libcmix-network/CMakeLists.txt +++ b/libcmix-network/CMakeLists.txt @@ -9,7 +9,7 @@ add_library(cmix-network connect.hpp connect.cpp server.hpp server.cpp client.hpp client.cpp - nodeclient.hpp nodeclient.cpp + protobufclient.hpp protobufclient.cpp uriparser.hpp uriparser.cpp ) @@ -27,6 +27,7 @@ target_link_libraries(cmix-network PUBLIC ${CMAKE_THREAD_LIBS_INIT} PRIVATE cmix PRIVATE log + PRIVATE cmix-protobuf ) if(WIN32) diff --git a/libcmix-network/client.cpp b/libcmix-network/client.cpp index f693afa..755989b 100644 --- a/libcmix-network/client.cpp +++ b/libcmix-network/client.cpp @@ -2,13 +2,6 @@ #include "connect.hpp" -#include "logging.hpp" - -#include <boost/asio/placeholders.hpp> -#include <boost/bind.hpp> -#include <boost/asio/buffer.hpp> -#include <boost/array.hpp> - #include <iostream> using namespace boost::asio::ip; @@ -39,26 +32,6 @@ std::array<uint8_t, 4> Client::prepare_length_prefix(uint32_t length) return buf; } -void Client::send(std::string message) { - - auto length_buffer = prepare_length_prefix(message.size()); - - boost::array<boost::asio::const_buffer, 2> package = { - boost::asio::buffer(length_buffer.data(), length_buffer.size()), - boost::asio::buffer(message) - }; - - auto handler = [](boost::system::error_code const& ec, std::size_t bytes_transferred) { - if(ec) { - BOOST_LOG_TRIVIAL(fatal) << ec; - throw std::runtime_error("unable to send message"); - } - }; - - socket.async_send(package, 0, handler); - -} - std::vector<uint8_t> Client::received_bytes_to_vector(size_t read_bytes) { buffer->commit(read_bytes); @@ -103,15 +76,6 @@ void Client::handle_receive_size(Client::MessageHandler message_handler, error_c } } -void Client::receive(MessageHandler message_handler) { - using namespace boost::asio::placeholders; - - socket.async_receive( - buffer->prepare(4), - boost::bind(&Client::handle_receive_size, this, message_handler, error(), bytes_transferred()) - ); -} - void Client::close() { socket.close(); diff --git a/libcmix-network/client.hpp b/libcmix-network/client.hpp index dc3787d..7bfea7d 100644 --- a/libcmix-network/client.hpp +++ b/libcmix-network/client.hpp @@ -1,7 +1,13 @@ #pragma once +#include "logging.hpp" + #include <boost/asio/ip/tcp.hpp> #include <boost/asio/streambuf.hpp> +#include <boost/asio/placeholders.hpp> +#include <boost/bind.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/array.hpp> #include <array> @@ -69,17 +75,44 @@ public: */ void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect); + inline static void foo() {} + /*! * \brief send sends the string prefixed with it's length over the socket. * \param message The string to be sent. */ - void send(std::string message); + template <typename F> + void async_send(std::string message, F on_sent) { + auto length_buffer = prepare_length_prefix(message.size()); + + boost::array<boost::asio::const_buffer, 2> package = { + boost::asio::buffer(length_buffer.data(), length_buffer.size()), + boost::asio::buffer(message) + }; + + auto handler = [on_sent](boost::system::error_code const& ec, std::size_t bytes_transferred) { + if(ec) { + BOOST_LOG_TRIVIAL(fatal) << ec; + throw std::runtime_error("unable to send message"); + } + on_sent(); + }; + + socket.async_send(package, 0, handler); + } /*! * \brief receive * \param message_handler The function to call when a message has been received. */ - void receive(MessageHandler message_handler); + void receive(MessageHandler message_handler) { + using namespace boost::asio::placeholders; + + socket.async_receive( + buffer->prepare(4), + boost::bind(&Client::handle_receive_size, this, message_handler, error(), bytes_transferred()) + ); + } /*! * \brief close Closes the underlying socket. diff --git a/libcmix-network/nodeclient.cpp b/libcmix-network/nodeclient.cpp deleted file mode 100644 index 9b026ba..0000000 --- a/libcmix-network/nodeclient.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "nodeclient.hpp" - -#include <iostream> - -NodeClient::NodeClient(boost::asio::ip::tcp::socket &&socket) -: client(std::move(socket)) -{} - -void NodeClient::handle_message(std::vector<uint8_t> message) -{ - std::cout << std::string(message.begin(), message.end()) << std::endl; -} - -void NodeClient::receive() -{ - client.receive(std::bind(&NodeClient::handle_message, this, std::placeholders::_1)); -} - -void NodeClient::on_done(Client::OnDoneFT done) { - client.on_done(done); -} - diff --git a/libcmix-network/nodeclient.hpp b/libcmix-network/nodeclient.hpp deleted file mode 100644 index ca1ee67..0000000 --- a/libcmix-network/nodeclient.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "client.hpp" - -#include <boost/asio/ip/tcp.hpp> - -#include <vector> - -/*! - * \file - */ - -/*! - * \brief The NodeClient class - */ -class NodeClient -{ - /*! - * \brief client - */ - Client client; - - /*! - * \brief handle_message - * \param message - */ - void handle_message(std::vector<uint8_t> message); - -public: - - /*! - * \brief NodeClient - * \param socket - */ - NodeClient(boost::asio::ip::tcp::socket&& socket); - - virtual ~NodeClient() = default; - - /*! - * \brief receive - */ - void receive(); - - /*! - * \brief on_done - * \param done - */ - void on_done(Client::OnDoneFT done); -}; diff --git a/libcmix-network/protobufclient.cpp b/libcmix-network/protobufclient.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libcmix-network/protobufclient.cpp diff --git a/libcmix-network/protobufclient.hpp b/libcmix-network/protobufclient.hpp new file mode 100644 index 0000000..1c97cfa --- /dev/null +++ b/libcmix-network/protobufclient.hpp @@ -0,0 +1,148 @@ +#pragma once + +#include "client.hpp" + +#include "logging.hpp" +#include "cmix.pb.h" + +#include <type_traits> + +struct Send; +struct Receive; +struct SendReceive; + +template<typename T> +class ProtobufClient; + +typedef ProtobufClient<Receive> Receiver; +typedef ProtobufClient<Send> Sender; +typedef ProtobufClient<SendReceive> SenderReceiver; + +template<typename T = SendReceive> +class ProtobufClient +{ + Client client; + + + #define MESSAGE_SETTER(TYPE, NAME) \ + void message_setter(cmix_proto::CMixMessage& m, cmix_proto::TYPE const& v) { \ + *m.mutable_##NAME() = v; \ + } \ + + MESSAGE_SETTER(Initialization, initialization) + MESSAGE_SETTER(ImANode, imanode) + MESSAGE_SETTER(ImAClient, imaclient) + MESSAGE_SETTER(Bye, bye) + MESSAGE_SETTER(KeyExchange, keyexchange) + + #undef MESSAGE_SETTER + +public: + /*! + * \brief ProtobufClient + * \param socket An rvalue reference to a socket it will now own and receive from. + */ + ProtobufClient(boost::asio::ip::tcp::socket&& socket) + : client(std::move(socket)) + {} + + /*! + * \brief Move constructor for ProtobufClient. + */ + ProtobufClient(ProtobufClient&& c) = default; + + ProtobufClient(Client&& c) + : client(std::move(c)) + {} + + template<typename Ty> + ProtobufClient(ProtobufClient<Ty>&& r) + : client(std::move(r.client)) + {} + + /*! + * \brief Move assignment for ProtobufClient. + */ + ProtobufClient& operator=(ProtobufClient&&) = default; + + /*! + * \brief async_connect Asynchronously connects to next_host:port and calls on_connect + * \param next_host The host to connect to + * \param next_port The port to connect to + * \param on_connect The callback to call on a succes. + */ + template<typename F> + void async_connect(std::string next_host, std::string next_port, F on_connect) { + client.async_connect(next_host, next_port, on_connect); + } + + + template<typename V, typename F, typename std::enable_if<(sizeof(V), std::is_same<T, Send>::value || std::is_same<T, SendReceive>::value), void>::type* = nullptr> + void async_send(V value, F on_sent) { + cmix_proto::CMixMessage m; + message_setter(m, value); + client.async_send(m.SerializeAsString(), on_sent); + } + + /*! + * \brief send sends the string prefixed with it's length over the socket asynchronously. + * \param message The string to be sent. + */ + template<typename V, typename std::enable_if<(sizeof(V), std::is_same<T, Send>::value || std::is_same<T, SendReceive>::value)>::type* = nullptr> + void async_send(V value) { + cmix_proto::CMixMessage m; + message_setter(m, value); + client.async_send(m.SerializeAsString(), []{}); + } + + /*! + * \brief receive + * \param message_handler The function to call when a message has been received. + */ + template <typename F, typename std::enable_if<(sizeof(F), std::is_same<T, Receive>::value || std::is_same<T, SendReceive>::value)>::type* = nullptr> + void receive(F message_handler) { + auto f = [message_handler](std::vector<uint8_t> const& buffer) { + cmix_proto::CMixMessage message; + if(!message.ParseFromArray(buffer.data(), buffer.size())) { + BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; + throw std::runtime_error("Network communication was disrupted in a unrecoverable way."); + } + message_handler(message); + }; + client.receive(f); + } + + /*! + * \brief close Closes the underlying socket. + */ + void close(){ + client.close(); + } + + /*! + * \brief on_done sets the done callback. + * \param f The new done callback function. + */ + template <typename F> + void on_done(F f) { + client.on_done(f); + } + + friend Receiver make_receiver(Receiver&& r); + + friend SenderReceiver make_sender_receiver(SenderReceiver&& r); + friend SenderReceiver make_sender_receiver(Receiver&& r); +}; + +inline Receiver make_receiver(Receiver&& r) { + return Receiver(std::move(r.client)); +} + +inline SenderReceiver make_sender_receiver(SenderReceiver&& r) { + return SenderReceiver(std::move(r.client)); +} + +inline SenderReceiver make_sender_receiver(Receiver&& r) +{ + return SenderReceiver(std::move(r.client)); +} diff --git a/libcmix-protobuf/cmix.proto b/libcmix-protobuf/cmix.proto index 8bbc303..e098cdf 100644 --- a/libcmix-protobuf/cmix.proto +++ b/libcmix-protobuf/cmix.proto @@ -26,6 +26,6 @@ message CMixMessage { ImANode imanode = 2; ImAClient imaclient = 3; Bye bye = 4; - KeyExchange keyexchange= 5; + KeyExchange keyexchange = 5; } } diff --git a/network-handler/CMakeLists.txt b/network-handler/CMakeLists.txt deleted file mode 100644 index 072172e..0000000 --- a/network-handler/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -find_package(Boost COMPONENTS system program_options REQUIRED) - -add_executable(network-handler - main.cpp - networkhandler.hpp networkhandler.cpp - userclient.hpp userclient.cpp - nodemanager.hpp nodemanager.cpp -) - -target_compile_options(network-handler - PRIVATE "-std=c++11" -) - -target_link_libraries(network-handler - PRIVATE Boost::boost - PRIVATE Boost::program_options - PRIVATE Boost::system - PRIVATE cmix - PRIVATE cmix-network -) diff --git a/network-handler/main.cpp b/network-handler/main.cpp deleted file mode 100644 index 84de894..0000000 --- a/network-handler/main.cpp +++ /dev/null @@ -1,49 +0,0 @@ - -#include "networkhandler.hpp" -#include "nodemanager.hpp" - -#include <boost/program_options.hpp> - -#include <string> -#include <iostream> -#include <cstdint> - -NodeManager key_exchange_phase(); - -int main(int argc, char* argv[]) { - namespace po = boost::program_options; - - po::options_description desc("Allowed options"); - desc.add_options() - ("help,h", "produce help message.") - ("port,p", po::value<uint16_t>()->default_value(9200), "Set listening port.") - ("enable_v4", po::value<bool>()->default_value(true), "Enable/disable ipv4 accept support.") - ("interface4,4", po::value<std::string>()->default_value("0.0.0.0"), "Set the ipv4 address to listen on.") - ("enable_v6", po::value<bool>()->default_value(true), "Enable/disable ipv6 accept support.") - ("interface6,6", po::value<std::string>()->default_value("::"), "Set the ipv6 address to listen on.") - ("nodes,n", po::value<std::string>(), "Set the node addreses to use in the cmix network.") - ; - - po::variables_map vm; - po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); - - if (vm.count("help")) { - std::cout << desc << "\n"; - return 0; - } - - bool en4 = vm["enable_v4"].as<bool>(); - std::string if4 = vm["interface4"].as<std::string>(); - bool en6 = vm["enable_v6"].as<bool>(); - std::string if6 = vm["interface6"].as<std::string>(); - uint16_t port = vm["port"].as<uint16_t>(); - - NodeManager node_manager({}); - - ListenSettings lsettings{en4, if4, en6, if6, port}; - - NetworkHandler handler(lsettings); - handler.run(); -} - diff --git a/network-handler/networkhandler.cpp b/network-handler/networkhandler.cpp deleted file mode 100644 index 614d270..0000000 --- a/network-handler/networkhandler.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "networkhandler.hpp" - -#include <boost/bind.hpp> -#include <boost/asio/placeholders.hpp> - -#include <memory> -#include <iostream> - -NetworkHandler::NetworkHandler(const ListenSettings& listen_settings) -: io_service() -, server(io_service, listen_settings, [this](boost::asio::ip::tcp::socket&& socket){accept_handler(std::move(socket));}) -, clients() -{} - -void NetworkHandler::accept_handler(boost::asio::ip::tcp::socket&& socket) -{ - std::list<UserClient>::iterator it = clients.emplace(clients.end(), std::move(socket)); - clients.back().on_done( - [this, it]() { - clients.erase(it); - } - ); - - clients.back().receive(); -} - -void NetworkHandler::run() -{ - io_service.run(); -} - - diff --git a/network-handler/networkhandler.hpp b/network-handler/networkhandler.hpp deleted file mode 100644 index e9bb7fa..0000000 --- a/network-handler/networkhandler.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "server.hpp" -#include "userclient.hpp" - -#include <boost/asio/io_service.hpp> - -#include <list> - -/*! - * \file - */ - -/*! - * \brief The NetworkHandler class - */ -class NetworkHandler -{ - /*! - * \brief io_service - */ - boost::asio::io_service io_service; - - /*! - * \brief server - */ - Server server; - - /*! - * \brief clients - */ - std::list<UserClient> clients; - - /*! - * \brief accept_handler - * \param socket - */ - void accept_handler(boost::asio::ip::tcp::socket&& socket); - -public: - /*! - * \brief NetworkHandler - * \param listen_settings - */ - NetworkHandler(ListenSettings const& listen_settings); - - /*! - * \brief run - */ - void run(); -}; diff --git a/network-handler/nodemanager.cpp b/network-handler/nodemanager.cpp deleted file mode 100644 index 165cb3b..0000000 --- a/network-handler/nodemanager.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "nodemanager.hpp" - -#include "connect.hpp" - -NodeManager::NodeManager(std::vector<ConnectionInfo> connections) -: io_service() -, api(get_curve25519_implementation()) -, key_pair(api.create_key_pair()) -, nodes() -{ - for(auto&& ci : connections) { - nodes.emplace_back(connect(ci.host, ci.port, io_service)); - } -} diff --git a/network-handler/nodemanager.hpp b/network-handler/nodemanager.hpp deleted file mode 100644 index 91d7160..0000000 --- a/network-handler/nodemanager.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "nodeclient.hpp" -#include "api.h" -#include "curve25519.h" - -#include <list> - -/*! - * \file - */ - -/*! - * \brief The ConnectionInfo struct - */ -struct ConnectionInfo { - std::string host; ///< The host - std::string port; ///< The port -}; - -/*! - * \brief The NodeManager class - * - * This class will probably never be fleshed out. - */ -class NodeManager -{ - /*! - * \brief io_service - */ - boost::asio::io_service io_service; - - /*! - * \brief api - */ - Api api; - - /*! - * \brief key_pair - */ - KeyPair key_pair; - - /*! - * \brief nodes - */ - std::list<NodeClient> nodes; -public: - - /*! - * \brief NodeManager - * \param connections - */ - NodeManager(std::vector<ConnectionInfo> connections); - - -}; diff --git a/network-handler/userclient.cpp b/network-handler/userclient.cpp deleted file mode 100644 index bf4eaa4..0000000 --- a/network-handler/userclient.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "userclient.hpp" - -#include <iostream> - -void UserClient::handle_message(std::vector<uint8_t> message) -{ - std::cout << std::string(message.begin(), message.end()); -} - -UserClient::UserClient(boost::asio::ip::tcp::socket&& socket) -: client(std::move(socket)) -{} - -void UserClient::receive() -{ - client.receive(std::bind(&UserClient::handle_message, this, std::placeholders::_1)); -} - -void UserClient::on_done(Client::OnDoneFT done) { - client.on_done(done); -} diff --git a/network-handler/userclient.hpp b/network-handler/userclient.hpp deleted file mode 100644 index af810a7..0000000 --- a/network-handler/userclient.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include <boost/asio/ip/tcp.hpp> - -#include "client.hpp" - -/*! - * \file - */ - -/*! - * \brief The UserClient class - */ -class UserClient -{ - /*! - * \brief client - */ - Client client; - - /*! - * \brief handle_message - * \param message - */ - void handle_message(std::vector<uint8_t> message); - -public: - /*! - * \brief UserClient - * \param socket - */ - UserClient(boost::asio::ip::tcp::socket&& socket); - virtual ~UserClient() = default; - - /*! - * \brief receive - */ - void receive(); - - /*! - * \brief on_done - * \param done - */ - void on_done(Client::OnDoneFT done); - -}; diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 53ca12e..c5ec53f 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -3,8 +3,6 @@ find_package(Boost COMPONENTS system program_options REQUIRED) add_executable(node main.cpp node.hpp node.cpp - prevnode.hpp prevnode.cpp - nextnode.hpp nextnode.cpp ) if(WIN32) diff --git a/node/nextnode.cpp b/node/nextnode.cpp deleted file mode 100644 index 8c5b7eb..0000000 --- a/node/nextnode.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "nextnode.hpp" - -#include "logging.hpp" - -using namespace boost::asio::ip; - -NextNode::NextNode(tcp::socket&& socket) -: client(std::move(socket)) -{} - -void NextNode::async_connect(std::string next_host, std::string next_port, std::function<void ()> on_connect) -{ - client.async_connect(next_host, next_port, on_connect); -} - -void NextNode::close() -{ - client.close(); -} diff --git a/node/nextnode.hpp b/node/nextnode.hpp deleted file mode 100644 index c2e064c..0000000 --- a/node/nextnode.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "client.hpp" - -#include "cmix.pb.h" - -#include <boost/asio/ip/tcp.hpp> - -/*! - * \file - */ - -/*! - * MESSAGE_SETTER is a boilerplate macro that generates a setter function for our CMix - * protobuf messages, This because there are seperate functions for each to type to use. - * And there seems no way to solve this using templates. - */ -#define MESSAGE_SETTER(TYPE, NAME) \ -inline void message_setter(cmix_proto::CMixMessage& m, cmix_proto::TYPE const& v) { \ - *m.mutable_##NAME() = v; \ -} \ - -MESSAGE_SETTER(Initialization, initialization) -MESSAGE_SETTER(ImANode, imanode) -MESSAGE_SETTER(Bye, bye) - -#undef MESSAGE_SETTER - -/*! - * \brief The NextNode class represents the next node in the network, will only be sent to. - */ -class NextNode -{ - Client client; -public: - /*! - * \brief NextNode - * \param socket an rvalue reference to the socket it takes ownership and uses to communicate with the next node in the network. - */ - NextNode(boost::asio::ip::tcp::socket&& socket); - - /*! - * \brief send - * \param v The CMixMessage type we try to send and first have to wrap in a CMixMessage. - */ - template <typename T> - void send(T v) { - cmix_proto::CMixMessage m; - message_setter(m, v); - client.send(m.SerializeAsString()); - } - - /*! - * \brief async_connect - * \param next_host The host of the next node. - * \param next_port The port of the next node. - * \param on_connect The callback to call when the connect was succesfull. - */ - void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect); - - /*! - * \brief close This function closes the underlying socket connection. - */ - void close(); -}; - diff --git a/node/node.cpp b/node/node.cpp index db18253..1fd83c2 100644 --- a/node/node.cpp +++ b/node/node.cpp @@ -13,8 +13,8 @@ Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_se , server(io_service, listen_settings, [this](boost::asio::ip::tcp::socket&& socket){accept_handler(std::move(socket));}) , clients() , network_settings(network_settings) -, prev_node(Client(tcp::socket(io_service))) -, next_node(tcp::socket(io_service)) +, prev_node(ProtobufClient<Receive>(tcp::socket(io_service))) +, next_node(ProtobufClient<Send>(tcp::socket(io_service))) , api(get_implementation()) , keypair(api.create_key_pair()) , network_pub_key() @@ -22,7 +22,7 @@ Node::Node(ListenSettings const& listen_settings, NodeNetworkSettings network_se GOOGLE_PROTOBUF_VERIFY_VERSION; auto on_connect = [this, network_settings](){ - next_node.send(cmix_proto::ImANode()); + next_node.async_send(cmix_proto::ImANode()); if(network_settings.is_first) { start_initialisation(); } @@ -41,17 +41,15 @@ void Node::run() { void Node::accept_handler(boost::asio::ip::tcp::socket&& socket) { - purgatory.emplace_back(std::move(socket)); - - std::list<Client>::iterator it = --purgatory.end(); + std::list<ProtobufClient<Receive>>::iterator it = purgatory.emplace(purgatory.end(), std::move(socket)); purgatory.back().on_done( [this, it]() { purgatory.erase(it); } ); - it->receive([this, it](std::vector<uint8_t> const& message_buffer) { - handle_message(it, message_buffer); + it->receive([this, it](cmix_proto::CMixMessage message) { + handle_message(it, message); }); } @@ -59,18 +57,7 @@ void Node::start_initialisation() { cmix_proto::Initialization init; init.set_public_share(keypair.pub, keypair.pub_len); - next_node.send(init); -} - -cmix_proto::CMixMessage Node::parse_cmix_message(const std::vector<uint8_t>& buffer) -{ - cmix_proto::CMixMessage message; - if(!message.ParseFromArray(buffer.data(), buffer.size())) { - BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; - io_service.stop(); - throw std::runtime_error("Network communication was disrupted in a unrecoverable way."); - } - return message; + next_node.async_send(init); } void Node::handle_initialization(const cmix_proto::Initialization& init) @@ -95,7 +82,7 @@ void Node::handle_initialization(const cmix_proto::Initialization& init) cmix_proto::Initialization init; init.set_public_share(new_shared.data, new_shared.len); - next_node.send(init); + next_node.async_send(init); free_bignum(&shared); free_bignum(&mod); @@ -103,9 +90,8 @@ void Node::handle_initialization(const cmix_proto::Initialization& init) } } -void Node::handle_node_message(const std::vector<uint8_t>& message_buffer) +void Node::handle_node_message(cmix_proto::CMixMessage message) { - cmix_proto::CMixMessage message = parse_cmix_message(message_buffer); switch(message.contents_case()) { case cmix_proto::CMixMessage::ContentsCase::kInitialization: { handle_initialization(message.initialization()); @@ -119,22 +105,20 @@ void Node::handle_node_message(const std::vector<uint8_t>& message_buffer) BOOST_LOG_TRIVIAL(error) << "handle_node_message: CMixMessage contains unknown contents."; } } - prev_node.receive([this](std::vector<uint8_t> const& buffer) { - handle_node_message(buffer); + prev_node.receive([this](cmix_proto::CMixMessage message) { + handle_node_message(message); }); } -void Node::handle_client_message(std::list<Client>::iterator handle, const std::vector<uint8_t>& message_buffer) +void Node::handle_client_message(std::list<SenderReceiver>::iterator handle, cmix_proto::CMixMessage message) { - cmix_proto::CMixMessage message = parse_cmix_message(message_buffer); - BOOST_LOG_TRIVIAL(trace) << "case: " << message.contents_case(); switch(message.contents_case()) { case cmix_proto::CMixMessage::ContentsCase::kKeyexchange: { BOOST_LOG_TRIVIAL(trace) << "Deriving shared key"; api.derive_shared_key(keypair, reinterpret_cast<uint8_t const*>(message.keyexchange().public_key().c_str()), true); - handle->receive([this, handle](std::vector<uint8_t> const& buffer){ - handle_client_message(handle, buffer); + handle->receive([this, handle](cmix_proto::CMixMessage message){ + handle_client_message(handle, message); }); return; } @@ -144,17 +128,6 @@ void Node::handle_client_message(std::list<Client>::iterator handle, const std:: handle->close(); clients.erase(handle); - if(clients.size() == 0) { - cmix_proto::Bye bye; - next_node.send(bye); - - io_service.post([this]{ - BOOST_LOG_TRIVIAL(trace) << "Shutting down"; - io_service.stop(); - }); - - } - return; } default: { @@ -165,36 +138,29 @@ void Node::handle_client_message(std::list<Client>::iterator handle, const std:: clients.erase(handle); } -void Node::handle_imanode(std::list<Client>::iterator handle) { +void Node::handle_imanode(std::list<Receiver>::iterator handle) { handle->on_done([]{}); - prev_node = PrevNode(std::move(*handle)); + prev_node = make_receiver(std::move(*handle)); purgatory.erase(handle); - prev_node.receive([this](std::vector<uint8_t> const& message_buffer){ - handle_node_message(message_buffer); + prev_node.receive([this](cmix_proto::CMixMessage message){ + handle_node_message(message); }); } -void Node::handle_imaclient(std::list<Client>::iterator handle) { - std::list<Client>::iterator it = clients.emplace(clients.end(), std::move(*handle)); +void Node::handle_imaclient(std::list<Receiver>::iterator handle) { + BOOST_LOG_TRIVIAL(trace) << "Handling imaclient"; + std::list<SenderReceiver>::iterator it = clients.emplace(clients.end(), make_sender_receiver(std::move(*handle))); it->on_done([this, it]{ clients.erase(it); }); purgatory.erase(handle); - it->receive([this, it](std::vector<uint8_t> buffer) { - handle_client_message(it, buffer); + it->receive([this, it](cmix_proto::CMixMessage message) { + handle_client_message(it, message); }); } -void Node::handle_message(std::list<Client>::iterator handle, const std::vector<uint8_t>& message_buffer) +void Node::handle_message(std::list<ProtobufClient<Receive>>::iterator handle, cmix_proto::CMixMessage message) { - cmix_proto::CMixMessage message; - try { - message = parse_cmix_message(message_buffer); - } catch(std::runtime_error const& e) { - purgatory.erase(handle); - return; - } - switch(message.contents_case()) { case cmix_proto::CMixMessage::ContentsCase::kImanode: { handle_imanode(handle); diff --git a/node/node.hpp b/node/node.hpp index 44e379f..9f1f3a2 100644 --- a/node/node.hpp +++ b/node/node.hpp @@ -1,9 +1,7 @@ #pragma once #include "server.hpp" -#include "nodeclient.hpp" -#include "prevnode.hpp" -#include "nextnode.hpp" +#include "protobufclient.hpp" #include "api.h" @@ -33,13 +31,13 @@ class Node { boost::asio::io_service io_service; Server server; - std::list<Client> purgatory; - std::list<Client> clients; + std::list<Receiver> purgatory; + std::list<SenderReceiver> clients; NodeNetworkSettings network_settings; - PrevNode prev_node; - NextNode next_node; + Receiver prev_node; + Sender next_node; Api api; KeyPair keypair; @@ -50,16 +48,14 @@ class Node void start_precomputation(); void start_initialisation(); - cmix_proto::CMixMessage parse_cmix_message(std::vector<uint8_t> const& buffer); - void handle_initialization(cmix_proto::Initialization const& init); - void handle_node_message(std::vector<uint8_t> const& message_buffer); + void handle_node_message(cmix_proto::CMixMessage message); - void handle_client_message(std::list<Client>::iterator handle, std::vector<uint8_t> const& message_buffer); + void handle_client_message(std::list<SenderReceiver>::iterator handle, cmix_proto::CMixMessage message); - void handle_imanode(std::list<Client>::iterator handle); - void handle_imaclient(std::list<Client>::iterator handle); - void handle_message(std::list<Client>::iterator handle, std::vector<uint8_t> const& message_buffer); + void handle_imanode(std::list<Receiver>::iterator handle); + void handle_imaclient(std::list<Receiver>::iterator handle); + void handle_message(std::list<ProtobufClient<Receive>>::iterator handle, cmix_proto::CMixMessage message); public: diff --git a/node/prevnode.cpp b/node/prevnode.cpp deleted file mode 100644 index 6af2242..0000000 --- a/node/prevnode.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "prevnode.hpp" - -PrevNode::PrevNode(Client&& client) -: client(std::move(client)) -{} - -void PrevNode::receive(std::function<void (const std::vector<uint8_t>&)> receive_handler) { - client.receive(receive_handler); -} - -void PrevNode::close() -{ - client.close(); -} diff --git a/node/prevnode.hpp b/node/prevnode.hpp deleted file mode 100644 index 6a6b431..0000000 --- a/node/prevnode.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "client.hpp" - -#include "cmix.pb.h" - -#include <boost/asio/ip/tcp.hpp> - -/*! - * \file - */ - -/*! - * \brief The PrevNode class represents the previous node in the network, will only be received from. - */ -class PrevNode -{ - Client client; -public: - /*! - * \brief PrevNode - * \param socket an rvalue reference to the socket it takes ownership and uses to communicate with the previous node in the network. - */ - PrevNode(Client&& socket); - - /*! - * \brief PrevNode move assignment operator. - */ - PrevNode& operator=(PrevNode&&) = default; - - /*! - * \brief receive Forwards a receive request to the client. - * \param receive_handler The function to call with the received data. - */ - void receive(std::function<void(std::vector<uint8_t> const&)> receive_handler); - - /*! - * \brief close This function closes the underlying socket connection. - */ - void close(); -}; - |
