aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-10-12 14:26:12 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-12 14:26:12 +0200
commit7bca48bc5b5e37a3a8b0b23e57b88d069fa50589 (patch)
tree47cd62512e631a064852015c65bb1965bc72414a
parent0fb433690c0ca5f9561fe9e2e973e2cd61b873ba (diff)
downloadcmix-7bca48bc5b5e37a3a8b0b23e57b88d069fa50589.tar.gz
cmix-7bca48bc5b5e37a3a8b0b23e57b88d069fa50589.tar.bz2
cmix-7bca48bc5b5e37a3a8b0b23e57b88d069fa50589.zip
Major network rewrite.
One generic class has been introduced to handle all connection types. Typedefs provide Sender Receiver and SenderReceiver types, which limit the functionality of the types. As to not accidentally communicate with the wrong node about things.
-rw-r--r--CMakeLists.txt3
-rw-r--r--client/CMakeLists.txt1
-rw-r--r--client/cmixclient.cpp38
-rw-r--r--client/cmixclient.hpp9
-rw-r--r--client/node.cpp23
-rw-r--r--client/node.hpp72
-rw-r--r--libcmix-network/CMakeLists.txt3
-rw-r--r--libcmix-network/client.cpp36
-rw-r--r--libcmix-network/client.hpp37
-rw-r--r--libcmix-network/nodeclient.cpp22
-rw-r--r--libcmix-network/nodeclient.hpp49
-rw-r--r--libcmix-network/protobufclient.cpp0
-rw-r--r--libcmix-network/protobufclient.hpp148
-rw-r--r--libcmix-protobuf/cmix.proto2
-rw-r--r--network-handler/CMakeLists.txt21
-rw-r--r--network-handler/main.cpp49
-rw-r--r--network-handler/networkhandler.cpp32
-rw-r--r--network-handler/networkhandler.hpp51
-rw-r--r--network-handler/nodemanager.cpp14
-rw-r--r--network-handler/nodemanager.hpp56
-rw-r--r--network-handler/userclient.cpp21
-rw-r--r--network-handler/userclient.hpp46
-rw-r--r--node/CMakeLists.txt2
-rw-r--r--node/nextnode.cpp19
-rw-r--r--node/nextnode.hpp66
-rw-r--r--node/node.cpp82
-rw-r--r--node/node.hpp24
-rw-r--r--node/prevnode.cpp14
-rw-r--r--node/prevnode.hpp42
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();
-};
-