From 88c5130eccd06e63ffca732626c0fb59426743a7 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Wed, 5 Oct 2016 12:56:52 +0200 Subject: Seperates Nodes and Clients for incoming connections. Created a PrevNode class to reflect the seperation. Made Client movable. Added 2 empty protobuf message that declare what each connecting client is, sent when connected to a node. --- node/CMakeLists.txt | 1 + node/main.cpp | 2 ++ node/nextnode.hpp | 9 ++--- node/node.cpp | 99 +++++++++++++++++++++++++++++++++++++++-------------- node/node.hpp | 10 +++++- node/prevnode.cpp | 14 ++++++++ node/prevnode.hpp | 42 +++++++++++++++++++++++ 7 files changed, 146 insertions(+), 31 deletions(-) create mode 100644 node/prevnode.cpp create mode 100644 node/prevnode.hpp (limited to 'node') diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 9151cbc..53ca12e 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -3,6 +3,7 @@ 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 ) diff --git a/node/main.cpp b/node/main.cpp index 1327ac5..031e0d0 100644 --- a/node/main.cpp +++ b/node/main.cpp @@ -12,6 +12,8 @@ int main(int argc, char* argv[]) { init_logging(boost::log::trivial::severity_level::trace); + BOOST_LOG_TRIVIAL(info) << "Started node"; + po::options_description desc("Allowed options"); desc.add_options() ("help,h", "produce help message.") diff --git a/node/nextnode.hpp b/node/nextnode.hpp index 9601ab5..862ca5c 100644 --- a/node/nextnode.hpp +++ b/node/nextnode.hpp @@ -15,12 +15,13 @@ * 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(T,F,NAME) \ -inline void message_setter(cmix_proto::CMixMessage& m, cmix_proto::T##NAME const& v) { \ - *m.mutable_##F##NAME() = v; \ +#define MESSAGE_SETTER(TYPE, NAME) \ +inline void message_setter(cmix_proto::CMixMessage& m, cmix_proto::TYPE const& v) { \ + *m.mutable_##NAME() = v; \ } \ -MESSAGE_SETTER(I,i,nitialization) +MESSAGE_SETTER(Initialization, initialization) +MESSAGE_SETTER(ImANode, imanode) #undef MESSAGE_SETTER diff --git a/node/node.cpp b/node/node.cpp index fb5b875..c02e5e6 100644 --- a/node/node.cpp +++ b/node/node.cpp @@ -13,6 +13,7 @@ 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)) , api(get_curve25519_implementation()) , keypair(api.create_key_pair()) @@ -21,6 +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()); if(network_settings.is_first) { start_initialisation(); } @@ -39,16 +41,18 @@ void Node::run() { void Node::accept_handler(boost::asio::ip::tcp::socket&& socket) { - clients.emplace_back(std::move(socket)); + purgatory.emplace_back(std::move(socket)); - auto it = --clients.end(); - clients.back().on_done( + std::list::iterator it = --purgatory.end(); + purgatory.back().on_done( [this, it]() { - clients.erase(it); + purgatory.erase(it); } ); - it->receive(std::bind(&Node::handle_message, this, std::placeholders::_1)); + it->receive([this, it](std::vector const& message_buffer) { + handle_message(decltype(it)(it), message_buffer); + }); } void Node::start_initialisation() { @@ -58,27 +62,6 @@ void Node::start_initialisation() { next_node.send(init); } -void Node::handle_message(const std::vector& message_buffer) -{ - cmix_proto::CMixMessage message; - if(!message.ParseFromArray(message_buffer.data(), message_buffer.size())) { - BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; - clients.clear(); - io_service.stop(); - return; - } - - switch(message.contents_case()) { - case cmix_proto::CMixMessage::ContentsCase::kInitialization: { - handle_initialization(message.initialization()); - break; - } - default: { - BOOST_LOG_TRIVIAL(error) << "CMixMessage contains unknown contents."; - } - } -} - void Node::handle_initialization(const cmix_proto::Initialization& init) { if(network_settings.is_first) { @@ -114,6 +97,70 @@ void Node::handle_initialization(const cmix_proto::Initialization& init) } } +void Node::handle_message(const std::vector& message_buffer) +{ + cmix_proto::CMixMessage message; + if(!message.ParseFromArray(message_buffer.data(), message_buffer.size())) { + BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; + clients.clear(); + io_service.stop(); + return; + } + + switch(message.contents_case()) { + case cmix_proto::CMixMessage::ContentsCase::kInitialization: { + handle_initialization(message.initialization()); + break; + } + default: { + BOOST_LOG_TRIVIAL(error) << "CMixMessage contains unknown contents."; + } + } +} + +void Node::handle_imanode(std::list::iterator handle) { + handle->on_done([]{}); + prev_node = PrevNode(std::move(*handle)); + purgatory.erase(handle); + prev_node.receive([this](std::vector const& message_buffer){ + handle_message(message_buffer); + }); +} + +void Node::handle_imaclient(std::list::iterator handle) { + clients.emplace_back(std::move(*handle)); + std::list::iterator it = clients.end()--; + it->on_done([this, it]{ + clients.erase(it); + }); + purgatory.erase(handle); +} + +void Node::handle_message(std::list::iterator handle, const std::vector& message_buffer) +{ + cmix_proto::CMixMessage message; + if(!message.ParseFromArray(message_buffer.data(), message_buffer.size())) { + BOOST_LOG_TRIVIAL(error) << "Received something which was not a CMixMessage"; + clients.clear(); + io_service.stop(); + return; + } + + switch(message.contents_case()) { + case cmix_proto::CMixMessage::ContentsCase::kImanode: { + handle_imanode(handle); + break; + } + case cmix_proto::CMixMessage::ContentsCase::kImaclient: { + handle_imaclient(handle); + break; + } + default: { + BOOST_LOG_TRIVIAL(error) << "CMixMessage contains unknown contents."; + } + } +} + void Node::start_precomputation() { clients.clear(); io_service.stop(); diff --git a/node/node.hpp b/node/node.hpp index a481c70..a4e21b3 100644 --- a/node/node.hpp +++ b/node/node.hpp @@ -2,6 +2,7 @@ #include "server.hpp" #include "nodeclient.hpp" +#include "prevnode.hpp" #include "nextnode.hpp" #include "api.h" @@ -33,10 +34,12 @@ class Node { boost::asio::io_service io_service; Server server; + std::list purgatory; std::list clients; NodeNetworkSettings network_settings; + PrevNode prev_node; NextNode next_node; Api api; @@ -48,8 +51,13 @@ class Node void start_precomputation(); void start_initialisation(); - void handle_message(std::vector const& message_buffer); void handle_initialization(cmix_proto::Initialization const& init); + void handle_message(std::vector const& message_buffer); + + void handle_imanode(std::list::iterator handle); + void handle_imaclient(std::list::iterator handle); + void handle_message(std::list::iterator handle, std::vector const& message_buffer); + public: /*! diff --git a/node/prevnode.cpp b/node/prevnode.cpp new file mode 100644 index 0000000..6af2242 --- /dev/null +++ b/node/prevnode.cpp @@ -0,0 +1,14 @@ +#include "prevnode.hpp" + +PrevNode::PrevNode(Client&& client) +: client(std::move(client)) +{} + +void PrevNode::receive(std::function&)> receive_handler) { + client.receive(receive_handler); +} + +void PrevNode::close() +{ + client.close(); +} diff --git a/node/prevnode.hpp b/node/prevnode.hpp new file mode 100644 index 0000000..6a6b431 --- /dev/null +++ b/node/prevnode.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "client.hpp" + +#include "cmix.pb.h" + +#include + +/*! + * \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 const&)> receive_handler); + + /*! + * \brief close This function closes the underlying socket connection. + */ + void close(); +}; + -- cgit v1.2.3-70-g09d2