diff options
| author | Dennis Brentjes <d.brentjes@gmail.com> | 2016-10-13 14:35:32 +0200 |
|---|---|---|
| committer | Dennis Brentjes <d.brentjes@gmail.com> | 2016-10-13 14:35:32 +0200 |
| commit | 366bae00016bfbfdd354ab010555c2927505b2b2 (patch) | |
| tree | e329c2ff179f62f093c6c53f84fb8faf4f5fccce | |
| parent | d9587cfd27aa5ef26170ec1983b47f1e26dc8136 (diff) | |
| download | cmix-366bae00016bfbfdd354ab010555c2927505b2b2.tar.gz cmix-366bae00016bfbfdd354ab010555c2927505b2b2.tar.bz2 cmix-366bae00016bfbfdd354ab010555c2927505b2b2.zip | |
Second big network rewrite.
This time without the ugly SFINAE hack to restrict sending and receiving
on Senders and Receivers respectively. Replaced this hack with private
inheritance and using declerations.
Also renamed receive to async_receive to better reflect the behaviour.
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | client/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | client/cmixclient.hpp | 4 | ||||
| -rw-r--r-- | libcmix-common/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | libcmix-common/cmixprotofunctor.cpp | 16 | ||||
| -rw-r--r-- | libcmix-common/cmixprotofunctor.hpp | 19 | ||||
| -rw-r--r-- | libcmix-common/receiver.hpp | 24 | ||||
| -rw-r--r-- | libcmix-common/sender.hpp | 24 | ||||
| -rw-r--r-- | libcmix-common/senderreceiver.cpp | 10 | ||||
| -rw-r--r-- | libcmix-common/senderreceiver.hpp | 28 | ||||
| -rw-r--r-- | libcmix-network/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | libcmix-network/client.hpp | 4 | ||||
| -rw-r--r-- | libcmix-network/protobufclient.hpp | 141 | ||||
| -rw-r--r-- | node/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | node/node.cpp | 24 | ||||
| -rw-r--r-- | node/node.hpp | 6 |
16 files changed, 178 insertions, 144 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5056777..f30c66e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(liblog) add_subdirectory(libcmix-protobuf) add_subdirectory(libcmix-network) +add_subdirectory(libcmix-common) add_subdirectory(node) add_subdirectory(client) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 489a136..68a37da 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -25,4 +25,5 @@ target_link_libraries(client PRIVATE cmix-bignum PRIVATE cmix-network PRIVATE cmix-protobuf + PRIVATE cmix-common ) diff --git a/client/cmixclient.hpp b/client/cmixclient.hpp index 056e2b3..71be7c9 100644 --- a/client/cmixclient.hpp +++ b/client/cmixclient.hpp @@ -1,6 +1,6 @@ #pragma once -#include "protobufclient.hpp" +#include "senderreceiver.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<ProtobufClient<SendReceive>> network_connections; + std::vector<SenderReceiver> network_connections; Api api; KeyPair keypair; diff --git a/libcmix-common/CMakeLists.txt b/libcmix-common/CMakeLists.txt new file mode 100644 index 0000000..0861e95 --- /dev/null +++ b/libcmix-common/CMakeLists.txt @@ -0,0 +1,16 @@ + +add_library(cmix-common + cmixprotofunctor.hpp cmixprotofunctor.cpp + receiver.hpp + sender.hpp + senderreceiver.hpp senderreceiver.cpp +) + +target_include_directories(cmix-common + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(cmix-common + PRIVATE cmix-protobuf + PRIVATE cmix-network +)
\ No newline at end of file diff --git a/libcmix-common/cmixprotofunctor.cpp b/libcmix-common/cmixprotofunctor.cpp new file mode 100644 index 0000000..a026628 --- /dev/null +++ b/libcmix-common/cmixprotofunctor.cpp @@ -0,0 +1,16 @@ +#include "cmixprotofunctor.hpp" + +#define MESSAGE_SETTER_DEF(TYPE, NAME) \ + CMixProtoFunctor::proto_type CMixProtoFunctor::operator()(cmix_proto::TYPE const& v) { \ + proto_type m; \ + *m.mutable_##NAME() = v; \ + return m; \ + } \ + +MESSAGE_SETTER_DEF(Initialization, initialization) +MESSAGE_SETTER_DEF(ImANode, imanode) +MESSAGE_SETTER_DEF(ImAClient, imaclient) +MESSAGE_SETTER_DEF(Bye, bye) +MESSAGE_SETTER_DEF(KeyExchange, keyexchange) + +#undef MESSAGE_SETTER_DEF
\ No newline at end of file diff --git a/libcmix-common/cmixprotofunctor.hpp b/libcmix-common/cmixprotofunctor.hpp new file mode 100644 index 0000000..c15f218 --- /dev/null +++ b/libcmix-common/cmixprotofunctor.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "cmix.pb.h" + +struct CMixProtoFunctor { + + typedef cmix_proto::CMixMessage proto_type; + + #define MESSAGE_SETTER_DECL(TYPE) \ + proto_type operator()(cmix_proto::TYPE const& v) + + MESSAGE_SETTER_DECL(Initialization); + MESSAGE_SETTER_DECL(ImANode); + MESSAGE_SETTER_DECL(ImAClient); + MESSAGE_SETTER_DECL(Bye); + MESSAGE_SETTER_DECL(KeyExchange); + + #undef MESSAGE_SETTER +}; diff --git a/libcmix-common/receiver.hpp b/libcmix-common/receiver.hpp new file mode 100644 index 0000000..a70cde0 --- /dev/null +++ b/libcmix-common/receiver.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "cmixprotofunctor.hpp" + +#include "protobufclient.hpp" + +struct SenderReceiver; + +struct Receiver : private ProtobufClient<CMixProtoFunctor> +{ + friend SenderReceiver; + + using ProtobufClient::ProtobufClient; + + using ProtobufClient::async_receive; + + using ProtobufClient::async_connect; + + using ProtobufClient::close; + + using ProtobufClient::on_done; + + using ProtobufClient::is_open; +}; diff --git a/libcmix-common/sender.hpp b/libcmix-common/sender.hpp new file mode 100644 index 0000000..72f0b3d --- /dev/null +++ b/libcmix-common/sender.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "cmixprotofunctor.hpp" + +#include "protobufclient.hpp" + +struct SenderReceiver; + +struct Sender : private ProtobufClient<CMixProtoFunctor> +{ + friend SenderReceiver; + + using ProtobufClient::ProtobufClient; + + using ProtobufClient::async_send; + + using ProtobufClient::async_connect; + + using ProtobufClient::close; + + using ProtobufClient::on_done; + + using ProtobufClient::is_open; +}; diff --git a/libcmix-common/senderreceiver.cpp b/libcmix-common/senderreceiver.cpp new file mode 100644 index 0000000..eafa8a5 --- /dev/null +++ b/libcmix-common/senderreceiver.cpp @@ -0,0 +1,10 @@ + +#include "senderreceiver.hpp" + +SenderReceiver::SenderReceiver(Receiver&& r) +: ProtobufClient(std::move(r)) +{} + +SenderReceiver::SenderReceiver(Sender&& s) +: ProtobufClient(std::move(s)) +{} diff --git a/libcmix-common/senderreceiver.hpp b/libcmix-common/senderreceiver.hpp new file mode 100644 index 0000000..9a07f78 --- /dev/null +++ b/libcmix-common/senderreceiver.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "cmixprotofunctor.hpp" +#include "receiver.hpp" +#include "sender.hpp" + +#include "protobufclient.hpp" + +struct SenderReceiver : private ProtobufClient<CMixProtoFunctor> +{ + explicit SenderReceiver(Receiver&& r); + + explicit SenderReceiver(Sender&& s); + + using ProtobufClient::ProtobufClient; + + using ProtobufClient::async_receive; + + using ProtobufClient::async_send; + + using ProtobufClient::async_connect; + + using ProtobufClient::close; + + using ProtobufClient::on_done; + + using ProtobufClient::is_open; +};
\ No newline at end of file diff --git a/libcmix-network/CMakeLists.txt b/libcmix-network/CMakeLists.txt index c64c8b7..ee0f6e9 100644 --- a/libcmix-network/CMakeLists.txt +++ b/libcmix-network/CMakeLists.txt @@ -26,8 +26,7 @@ target_link_libraries(cmix-network PUBLIC Boost::system PUBLIC ${CMAKE_THREAD_LIBS_INIT} PRIVATE cmix - PRIVATE log - PRIVATE cmix-protobuf + PUBLIC log ) if(WIN32) diff --git a/libcmix-network/client.hpp b/libcmix-network/client.hpp index 7b88282..4990667 100644 --- a/libcmix-network/client.hpp +++ b/libcmix-network/client.hpp @@ -102,10 +102,10 @@ public: } /*! - * \brief receive + * \brief async_receive * \param message_handler The function to call when a message has been received. */ - void receive(MessageHandler message_handler) { + void async_receive(MessageHandler message_handler) { using namespace boost::asio::placeholders; socket.async_receive( diff --git a/libcmix-network/protobufclient.hpp b/libcmix-network/protobufclient.hpp index 077ce62..c28c347 100644 --- a/libcmix-network/protobufclient.hpp +++ b/libcmix-network/protobufclient.hpp @@ -3,150 +3,43 @@ #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 +template <typename T> +class ProtobufClient : private Client { - 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); - } + using Client::Client; + using Client::operator=; + using Client::async_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> + template<typename V, typename F> void async_send(V value, F on_sent) { - cmix_proto::CMixMessage m; - message_setter(m, value); - client.async_send(m.SerializeAsString(), on_sent); + typename T::proto_type m = T()(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> + template<typename V> void async_send(V value) { - cmix_proto::CMixMessage m; - message_setter(m, value); - client.async_send(m.SerializeAsString(), []{}); + async_send(value, []{}); } - /*! - * \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) { + template <typename F> + void async_receive(F message_handler) { auto f = [message_handler](std::vector<uint8_t> const& buffer) { - cmix_proto::CMixMessage message; + typename T::proto_type 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(); + Client::async_receive(f); } - /*! - * \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); - } - - bool is_open() const{ - return client.is_open(); - } - - friend Receiver make_receiver(Receiver&& r); - - friend SenderReceiver make_sender_receiver(SenderReceiver&& r); - friend SenderReceiver make_sender_receiver(Receiver&& r); + using Client::close; + using Client::on_done; + using Client::is_open; }; - -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/node/CMakeLists.txt b/node/CMakeLists.txt index c5ec53f..05468bd 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -25,4 +25,5 @@ target_link_libraries(node PRIVATE cmix-bignum PRIVATE cmix-network PRIVATE cmix-protobuf + PRIVATE cmix-common ) diff --git a/node/node.cpp b/node/node.cpp index f06e389..5487299 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(ProtobufClient<Receive>(tcp::socket(io_service))) -, next_node(ProtobufClient<Send>(tcp::socket(io_service))) +, prev_node(Receiver(tcp::socket(io_service))) +, next_node(Sender(tcp::socket(io_service))) , api(get_implementation()) , keypair(api.create_key_pair()) , network_pub_key() @@ -42,14 +42,14 @@ void Node::run() { void Node::accept_handler(boost::asio::ip::tcp::socket&& socket) { - std::list<ProtobufClient<Receive>>::iterator it = purgatory.emplace(purgatory.end(), std::move(socket)); + std::list<Receiver>::iterator it = purgatory.emplace(purgatory.end(), std::move(socket)); purgatory.back().on_done( [this, it]() { purgatory.erase(it); } ); - it->receive([this, it](cmix_proto::CMixMessage message) { + it->async_receive([this, it](cmix_proto::CMixMessage message) { handle_message(it, message); }); } @@ -109,7 +109,7 @@ void Node::handle_node_message(cmix_proto::CMixMessage message) prev_node.close(); if (!shutting_down) { send_bye(); - prev_node.receive([this](cmix_proto::CMixMessage message){ + prev_node.async_receive([this](cmix_proto::CMixMessage message){ handle_node_message(message); }); } @@ -119,7 +119,7 @@ void Node::handle_node_message(cmix_proto::CMixMessage message) BOOST_LOG_TRIVIAL(error) << "handle_node_message: CMixMessage contains unknown contents."; } } - prev_node.receive([this](cmix_proto::CMixMessage message) { + prev_node.async_receive([this](cmix_proto::CMixMessage message) { handle_node_message(message); }); } @@ -131,7 +131,7 @@ void Node::handle_client_message(ClientMap::key_type handle, cmix_proto::CMixMes BOOST_LOG_TRIVIAL(trace) << "Deriving shared key"; api.derive_shared_key(keypair, reinterpret_cast<uint8_t const*>(message.keyexchange().public_key().c_str()), true); - clients.at(handle).receive([this, handle](cmix_proto::CMixMessage message){ + clients.at(handle).async_receive([this, handle](cmix_proto::CMixMessage message){ handle_client_message(handle, message); }); return; @@ -154,9 +154,9 @@ void Node::handle_client_message(ClientMap::key_type handle, cmix_proto::CMixMes void Node::handle_imanode(std::list<Receiver>::iterator handle) { handle->on_done([]{}); - prev_node = make_receiver(std::move(*handle)); + prev_node = Receiver(std::move(*handle)); purgatory.erase(handle); - prev_node.receive([this](cmix_proto::CMixMessage message){ + prev_node.async_receive([this](cmix_proto::CMixMessage message){ handle_node_message(message); }); } @@ -164,17 +164,17 @@ void Node::handle_imanode(std::list<Receiver>::iterator handle) { void Node::handle_imaclient(std::list<Receiver>::iterator handle, cmix_proto::ImAClient c) { BOOST_LOG_TRIVIAL(trace) << "Handling imaclient"; std::string client_id = c.id(); - clients.emplace(c.id(), make_sender_receiver(std::move(*handle))); + clients.emplace(c.id(), SenderReceiver(std::move(*handle))); clients.at(c.id()).on_done([this, client_id]{ clients.erase(client_id); }); purgatory.erase(handle); - clients.at(c.id()).receive([this, client_id](cmix_proto::CMixMessage message) { + clients.at(c.id()).async_receive([this, client_id](cmix_proto::CMixMessage message) { handle_client_message(client_id, message); }); } -void Node::handle_message(std::list<ProtobufClient<Receive>>::iterator handle, cmix_proto::CMixMessage message) +void Node::handle_message(std::list<Receiver>::iterator handle, cmix_proto::CMixMessage message) { switch(message.contents_case()) { case cmix_proto::CMixMessage::ContentsCase::kImanode: { diff --git a/node/node.hpp b/node/node.hpp index 868c4b8..9423860 100644 --- a/node/node.hpp +++ b/node/node.hpp @@ -1,7 +1,9 @@ #pragma once #include "server.hpp" -#include "protobufclient.hpp" +#include "receiver.hpp" +#include "senderreceiver.hpp" +#include "sender.hpp" #include "api.h" @@ -61,7 +63,7 @@ class Node void handle_imanode(std::list<Receiver>::iterator handle); void handle_imaclient(std::list<Receiver>::iterator handle, cmix_proto::ImAClient c); - void handle_message(std::list<ProtobufClient<Receive>>::iterator handle, cmix_proto::CMixMessage message); + void handle_message(std::list<Receiver>::iterator handle, cmix_proto::CMixMessage message); public: /*! |
