aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-10-05 12:56:52 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-05 14:12:28 +0200
commit88c5130eccd06e63ffca732626c0fb59426743a7 (patch)
treef9c7c4536bfa50057269c3636baedea3cb859ac1
parentedc3690d62890449df3ae4c14636019bce4833f1 (diff)
downloadcmix-88c5130eccd06e63ffca732626c0fb59426743a7.tar.gz
cmix-88c5130eccd06e63ffca732626c0fb59426743a7.tar.bz2
cmix-88c5130eccd06e63ffca732626c0fb59426743a7.zip
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.
-rw-r--r--libcmix-network/client.cpp10
-rw-r--r--libcmix-network/client.hpp12
-rw-r--r--libcmix-protobuf/cmix.proto10
-rw-r--r--node/CMakeLists.txt1
-rw-r--r--node/main.cpp2
-rw-r--r--node/nextnode.hpp9
-rw-r--r--node/node.cpp99
-rw-r--r--node/node.hpp10
-rw-r--r--node/prevnode.cpp14
-rw-r--r--node/prevnode.hpp42
10 files changed, 172 insertions, 37 deletions
diff --git a/libcmix-network/client.cpp b/libcmix-network/client.cpp
index 7c95234..9293bd1 100644
--- a/libcmix-network/client.cpp
+++ b/libcmix-network/client.cpp
@@ -16,7 +16,7 @@ using namespace boost::system;
Client::Client(tcp::socket &&socket)
: socket(std::move(socket))
-, buffer()
+, buffer(new boost::asio::streambuf())
, done()
{}
@@ -61,8 +61,8 @@ void Client::send(std::string message) {
std::vector<uint8_t> Client::received_bytes_to_vector(size_t read_bytes)
{
- buffer.commit(read_bytes);
- std::istream is(&buffer);
+ buffer->commit(read_bytes);
+ std::istream is(buffer.get());
is.unsetf(std::ios::skipws);
return std::vector<uint8_t>(std::istream_iterator<uint8_t>(is), {});
@@ -92,7 +92,7 @@ void Client::handle_receive_size(Client::MessageHandler message_handler, const e
size = ntohl(size);
socket.async_receive(
- buffer.prepare(size),
+ buffer->prepare(size),
boost::bind(&Client::handle_receive_message, this, message_handler, error(), bytes_transferred())
);
} else {
@@ -107,7 +107,7 @@ void Client::receive(MessageHandler message_handler) {
using namespace boost::asio::placeholders;
socket.async_receive(
- buffer.prepare(4),
+ buffer->prepare(4),
boost::bind(&Client::handle_receive_size, this, message_handler, error(), bytes_transferred())
);
}
diff --git a/libcmix-network/client.hpp b/libcmix-network/client.hpp
index 51dfa6f..dc3787d 100644
--- a/libcmix-network/client.hpp
+++ b/libcmix-network/client.hpp
@@ -31,7 +31,7 @@ protected:
boost::asio::ip::tcp::socket socket;
private:
- boost::asio::streambuf buffer;
+ std::unique_ptr<boost::asio::streambuf> buffer;
OnDoneFT done;
@@ -52,6 +52,16 @@ public:
~Client();
/*!
+ * \brief Move constructor for Client.
+ */
+ Client(Client&&) = default;
+
+ /*!
+ * \brief Move assignment for Client.
+ */
+ Client& operator=(Client&&) = 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
diff --git a/libcmix-protobuf/cmix.proto b/libcmix-protobuf/cmix.proto
index 3068291..6e653f1 100644
--- a/libcmix-protobuf/cmix.proto
+++ b/libcmix-protobuf/cmix.proto
@@ -4,8 +4,18 @@ message Initialization {
required bytes public_share = 1;
}
+message ImANode {
+
+}
+
+message ImAClient {
+
+}
+
message CMixMessage {
oneof contents {
Initialization initialization = 1;
+ ImANode imanode = 2;
+ ImAClient imaclient = 3;
}
}
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<Client>::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<uint8_t> 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<uint8_t>& 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<uint8_t>& 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<Client>::iterator handle) {
+ handle->on_done([]{});
+ prev_node = PrevNode(std::move(*handle));
+ purgatory.erase(handle);
+ prev_node.receive([this](std::vector<uint8_t> const& message_buffer){
+ handle_message(message_buffer);
+ });
+}
+
+void Node::handle_imaclient(std::list<Client>::iterator handle) {
+ clients.emplace_back(std::move(*handle));
+ std::list<Client>::iterator it = clients.end()--;
+ it->on_done([this, it]{
+ clients.erase(it);
+ });
+ purgatory.erase(handle);
+}
+
+void Node::handle_message(std::list<Client>::iterator handle, const std::vector<uint8_t>& 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<Client> purgatory;
std::list<Client> 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<uint8_t> const& message_buffer);
void handle_initialization(cmix_proto::Initialization const& init);
+ void handle_message(std::vector<uint8_t> const& message_buffer);
+
+ 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);
+
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<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
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 <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();
+};
+