aboutsummaryrefslogtreecommitdiff
path: root/libcmix-network
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-10-21 14:01:26 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-21 18:15:46 +0200
commit510ce3bec7915a790fbf75ace5521e437d9d416a (patch)
tree7b9286875652b677a110287d11d024f85879cc7a /libcmix-network
parent640e0ad7a762d0473581c2114c2c945961bea80f (diff)
downloadcmix-510ce3bec7915a790fbf75ace5521e437d9d416a.tar.gz
cmix-510ce3bec7915a790fbf75ace5521e437d9d416a.tar.bz2
cmix-510ce3bec7915a790fbf75ace5521e437d9d416a.zip
Adds SSL connections between nodes.
Diffstat (limited to 'libcmix-network')
-rw-r--r--libcmix-network/CMakeLists.txt4
-rw-r--r--libcmix-network/accept.cpp47
-rw-r--r--libcmix-network/accept.hpp4
-rw-r--r--libcmix-network/acceptor.cpp5
-rw-r--r--libcmix-network/acceptor.hpp2
-rw-r--r--libcmix-network/client.cpp91
-rw-r--r--libcmix-network/client.hpp207
-rw-r--r--libcmix-network/connect.cpp14
-rw-r--r--libcmix-network/connect.hpp3
-rw-r--r--libcmix-network/protobufclient.cpp0
-rw-r--r--libcmix-network/protobufclient.hpp58
-rw-r--r--libcmix-network/server.cpp17
-rw-r--r--libcmix-network/server.hpp5
13 files changed, 312 insertions, 145 deletions
diff --git a/libcmix-network/CMakeLists.txt b/libcmix-network/CMakeLists.txt
index b58cef1..057061c 100644
--- a/libcmix-network/CMakeLists.txt
+++ b/libcmix-network/CMakeLists.txt
@@ -8,8 +8,8 @@ add_library(cmix-network
accept.hpp accept.cpp
connect.hpp connect.cpp
server.hpp server.cpp
- client.hpp client.cpp
- protobufclient.hpp protobufclient.cpp
+ client.hpp
+ protobufclient.hpp
uriparser.hpp uriparser.cpp
)
diff --git a/libcmix-network/accept.cpp b/libcmix-network/accept.cpp
index 3fa4314..1ec26fe 100644
--- a/libcmix-network/accept.cpp
+++ b/libcmix-network/accept.cpp
@@ -7,42 +7,61 @@
using namespace boost::asio::ip;
using namespace boost::asio;
-void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<tcp::socket> socket, boost::system::error_code ec, std::function<void (tcp::socket&&)> f)
+void accept_connection(tcp::acceptor& acceptor, tcp::socket* socket, boost::system::error_code ec, AcceptHandler f)
{
if(!bool(ec))
{
- f(std::move(*socket));
+ f(std::unique_ptr<tcp::socket>(socket));
accept_loop(acceptor, f);
} else {
- std::stringstream ss;
- ss << ec;
- throw std::runtime_error(ss.str());
+ if(ec != boost::system::errc::operation_canceled) {
+ std::stringstream ss;
+ ss << ec.message();
+ delete socket;
+ throw std::runtime_error(ss.str());
+ } else {
+ delete socket;
+ }
}
}
-void accept_loop(tcp::acceptor& acceptor, std::function<void (tcp::socket&&)> f)
+void accept_loop(tcp::acceptor& acceptor, AcceptHandler f)
{
- std::shared_ptr<tcp::socket> new_socket = std::make_shared<tcp::socket>(acceptor.get_io_service());
+ tcp::socket* new_socket = new tcp::socket(acceptor.get_io_service());
acceptor.async_accept(*new_socket, boost::bind(accept_connection, boost::ref(acceptor), new_socket, placeholders::error, f));
}
-void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<ssl::context> ctx, std::shared_ptr<ssl::stream<tcp::socket>> socket, boost::system::error_code ec, std::function<void (ssl::stream<tcp::socket>&&)> f)
+void accept_connection(tcp::acceptor& acceptor, std::shared_ptr<ssl::context> ctx, ssl::stream<tcp::socket>* socket, boost::system::error_code ec, SSLAcceptHandler f)
{
if(!bool(ec))
{
- f(std::move(*socket));
+ socket->async_handshake(boost::asio::ssl::stream_base::server, [&acceptor, ctx, socket, f](boost::system::error_code const& ec) {
+ if(!bool(ec)) {
+ f(std::unique_ptr<ssl::stream<tcp::socket>>(socket), ctx);
+ } else {
+ std::stringstream ss;
+ ss << ec.message();
+ delete socket;
+ throw std::runtime_error(ss.str());
+ }
+ });
accept_loop(acceptor, ctx, f);
} else {
- std::stringstream ss;
- ss << ec;
- throw std::runtime_error(ss.str());
+ if(ec != boost::system::errc::operation_canceled) {
+ std::stringstream ss;
+ ss << ec;
+ delete socket;
+ throw std::runtime_error(ss.str());
+ } else {
+ delete socket;
+ }
}
}
-void accept_loop(tcp::acceptor& acceptor, std::shared_ptr<ssl::context> ctx, std::function<void(ssl::stream<tcp::socket>&& socket)> f) {
+void accept_loop(tcp::acceptor& acceptor, std::shared_ptr<ssl::context> ctx, SSLAcceptHandler f) {
- std::shared_ptr<ssl::stream<tcp::socket>> new_socket = std::make_shared<ssl::stream<tcp::socket>>(acceptor.get_io_service(), *ctx);
+ ssl::stream<tcp::socket>* new_socket = new ssl::stream<tcp::socket>(acceptor.get_io_service(), *ctx);
acceptor.async_accept(new_socket->lowest_layer(), boost::bind(accept_connection, boost::ref(acceptor), ctx, new_socket, placeholders::error, f));
}
diff --git a/libcmix-network/accept.hpp b/libcmix-network/accept.hpp
index dde98a3..f7d068a 100644
--- a/libcmix-network/accept.hpp
+++ b/libcmix-network/accept.hpp
@@ -12,11 +12,11 @@
/*!
* \brief AcceptHandler Handy typedef for a function taking an tcp::socket.
*/
-typedef std::function<void(boost::asio::ip::tcp::socket&&)> AcceptHandler;
+typedef std::function<void(std::unique_ptr<boost::asio::ip::tcp::socket>&&)> AcceptHandler;
/*!
* \brief SSLAcceptHandler Handy typedef for a function taking an "SSLSocket"
*/
-typedef std::function<void(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>&&)> SSLAcceptHandler;
+typedef std::function<void(std::unique_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>&&, std::shared_ptr<boost::asio::ssl::context>)> SSLAcceptHandler;
/*!
* \brief accept_loop Keeps accepting connections on the specified acceptor
diff --git a/libcmix-network/acceptor.cpp b/libcmix-network/acceptor.cpp
index 83406db..ee8833a 100644
--- a/libcmix-network/acceptor.cpp
+++ b/libcmix-network/acceptor.cpp
@@ -53,3 +53,8 @@ void Acceptor::start_accepting(std::shared_ptr<ssl::context> ctx, SSLAcceptHandl
{
accept_loop(acceptor, ctx, accept_handler);
}
+
+void Acceptor::close()
+{
+ acceptor.close();
+}
diff --git a/libcmix-network/acceptor.hpp b/libcmix-network/acceptor.hpp
index 6e4de63..0ee9294 100644
--- a/libcmix-network/acceptor.hpp
+++ b/libcmix-network/acceptor.hpp
@@ -74,4 +74,6 @@ public:
*/
void start_accepting(std::shared_ptr<boost::asio::ssl::context> ctx, SSLAcceptHandler accept_handler);
+ void close();
+
};
diff --git a/libcmix-network/client.cpp b/libcmix-network/client.cpp
deleted file mode 100644
index 09ea98c..0000000
--- a/libcmix-network/client.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-#include "client.hpp"
-
-#include "connect.hpp"
-
-#include <iostream>
-
-using namespace boost::asio::ip;
-using namespace boost::system;
-
-Client::Client(tcp::socket &&socket)
-: socket(std::move(socket))
-, buffer(new boost::asio::streambuf())
-, done()
-{}
-
-Client::~Client()
-{
- close();
-}
-
-void Client::async_connect(std::string next_host, std::string next_port, std::function<void ()> on_connect)
-{
- ::async_connect(socket, next_host, next_port, on_connect);
-}
-
-std::array<uint8_t, 4> Client::prepare_length_prefix(uint32_t length)
-{
- length = htonl(length);
- std::array<uint8_t, 4> buf;
-
- std::copy(reinterpret_cast<uint8_t*>(&length), reinterpret_cast<uint8_t*>(&length) + 4, buf.data());
- return buf;
-}
-
-std::vector<uint8_t> Client::received_bytes_to_vector(size_t read_bytes)
-{
- 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), {});
-}
-
-void Client::handle_receive_message(MessageHandler message_handler, const error_code &ec, size_t read_bytes)
-{
- if(!ec) {
- std::vector<uint8_t> data = received_bytes_to_vector(read_bytes);
- message_handler(data);
- } else {
- BOOST_LOG_TRIVIAL(error) << ec;
- if(done) {
- done();
- }
- }
-}
-
-void Client::handle_receive_size(Client::MessageHandler message_handler, error_code const& ec, size_t read_bytes)
-{
- using namespace boost::asio::placeholders;
-
- if(!ec) {
- std::vector<uint8_t> data = received_bytes_to_vector(read_bytes);
- uint32_t size;
- std::copy(data.begin(), data.end(), reinterpret_cast<uint8_t*>(&size));
- size = ntohl(size);
-
- socket.async_receive(
- buffer->prepare(size),
- boost::bind(&Client::handle_receive_message, this, message_handler, error(), bytes_transferred())
- );
- } else {
- BOOST_LOG_TRIVIAL(error) << ec;
- if(done) {
- done();
- }
- }
-}
-
-void Client::close()
-{
- socket.close();
-}
-
-void Client::on_done(Client::OnDoneFT f) {
- done = f;
-}
-
-bool Client::is_open() const
-{
- return socket.is_open();
-}
diff --git a/libcmix-network/client.hpp b/libcmix-network/client.hpp
index bd66b98..0b98c1c 100644
--- a/libcmix-network/client.hpp
+++ b/libcmix-network/client.hpp
@@ -1,8 +1,13 @@
#pragma once
+#include "connect.hpp"
+
#include "logging.hpp"
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/placeholders.hpp>
#include <boost/bind.hpp>
@@ -11,6 +16,8 @@
#include <array>
+#include <iostream>
+
/*!
* \file
*/
@@ -18,8 +25,15 @@
/*!
* \brief The Client class
*/
-class Client {
-public:
+
+struct SSLClient;
+
+template <typename T>
+class BaseClient {
+ friend SSLClient;
+
+ std::unique_ptr<T> socket;
+
/*!
* \brief OnDoneFT Function type of the function being called when this instance is done operating.
*/
@@ -30,42 +44,88 @@ public:
*/
typedef std::function<void(std::vector<uint8_t>)> MessageHandler;
-protected:
/*!
* \brief socket The socket connection this instance handles.
*/
- boost::asio::ip::tcp::socket socket;
-
-private:
- std::unique_ptr<boost::asio::streambuf> buffer;
+ std::unique_ptr<boost::asio::streambuf> receive_buffer;
+ std::unique_ptr<boost::asio::streambuf> send_buffer;
OnDoneFT done;
- std::vector<uint8_t> received_bytes_to_vector(size_t read_bytes);
+ std::vector<uint8_t> received_bytes_to_vector(size_t read_bytes) {
+ receive_buffer->commit(read_bytes);
+ std::istream is(receive_buffer.get());
+ is.unsetf(std::ios::skipws);
+
+ return std::vector<uint8_t>(std::istream_iterator<uint8_t>(is), {});
+ }
- void handle_receive_size(MessageHandler message_handler, boost::system::error_code const& ec, size_t read_bytes);
+ void handle_receive_size(MessageHandler message_handler, boost::system::error_code const& ec, size_t read_bytes) {
+ using namespace boost::asio::placeholders;
+
+ if(!ec) {
+ std::vector<uint8_t> data = received_bytes_to_vector(read_bytes);
+ uint32_t size;
+ std::copy(data.begin(), data.end(), reinterpret_cast<uint8_t*>(&size));
+ size = ntohl(size);
+
+ boost::asio::async_read(
+ *socket,
+ receive_buffer->prepare(size),
+ [this, message_handler](boost::system::error_code const& ec, size_t read_bytes) {
+ handle_receive_message(message_handler, ec, read_bytes);
+ }
+ );
+ } else {
+ BOOST_LOG_TRIVIAL(error) << ec.message();
+ if(done) {
+ done();
+ }
+ }
+ }
- void handle_receive_message(MessageHandler message_handler, boost::system::error_code const& ec, size_t read_bytes);
+ void handle_receive_message(MessageHandler message_handler, boost::system::error_code const& ec, size_t read_bytes) {
+ if(!ec) {
+ std::vector<uint8_t> data = received_bytes_to_vector(read_bytes);
+ message_handler(data);
+ } else {
+ BOOST_LOG_TRIVIAL(error) << ec.message();
+ if(done) {
+ done();
+ }
+ }
+ }
+
+ std::array<uint8_t, 4> prepare_length_prefix(uint32_t length) {
+ length = htonl(length);
+ std::array<uint8_t, 4> buf;
+
+ std::copy(reinterpret_cast<uint8_t*>(&length), reinterpret_cast<uint8_t*>(&length) + 4, buf.data());
+ return buf;
+ }
- std::array<uint8_t, 4> prepare_length_prefix(uint32_t length);
public:
/*!
* \brief Client
* \param socket An rvalue reference to a socket it will now own and receive from.
*/
- Client(boost::asio::ip::tcp::socket&& socket);
- ~Client();
+ BaseClient(std::unique_ptr<T>&& socket)
+ : socket(std::move(socket))
+ , receive_buffer(new boost::asio::streambuf)
+ , send_buffer(new boost::asio::streambuf)
+ , done()
+ {}
/*!
* \brief Move constructor for Client.
*/
- Client(Client&&) = default;
+ BaseClient(BaseClient&&) = default;
/*!
* \brief Move assignment for Client.
*/
- Client& operator=(Client&&) = default;
+ BaseClient& operator=(BaseClient&&) = default;
/*!
* \brief async_connect Asynchronously connects to next_host:port and calls on_connect
@@ -73,8 +133,10 @@ public:
* \param next_port The port to connect to
* \param on_connect The callback to call on a succes.
*/
- void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect);
-
+ void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect) {
+ ::async_connect(*socket, next_host, next_port, on_connect);
+ }
+
/*!
* \brief send sends the string prefixed with it's length over the socket.
* \param message The string to be sent.
@@ -84,20 +146,25 @@ public:
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)
- };
+ std::ostream os(send_buffer.get());
+ os.unsetf(std::ios::skipws);
+
+ os.write(reinterpret_cast<char*>(length_buffer.data()), length_buffer.size());
+ os.write(message.data(), message.size());
auto handler = [on_sent](boost::system::error_code const& ec, std::size_t bytes_transferred) {
if(ec) {
- BOOST_LOG_TRIVIAL(fatal) << ec;
+ BOOST_LOG_TRIVIAL(fatal) << ec.message();
throw std::runtime_error("unable to send message");
}
on_sent();
};
- socket.async_send(package, 0, handler);
+ boost::asio::async_write(
+ *socket,
+ *send_buffer,
+ handler
+ );
}
/*!
@@ -107,28 +174,110 @@ public:
void async_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())
+ boost::asio::async_read(
+ *socket,
+ receive_buffer->prepare(4),
+ [this, message_handler](boost::system::error_code const& ec, size_t read_bytes) {
+ handle_receive_size(message_handler, ec, read_bytes);
+ }
);
}
/*!
* \brief close Closes the underlying socket.
*/
- void close();
+ void close() {
+ socket->close();
+ }
/*!
* \brief on_done sets the done callback.
* \param f The new done callback function.
*/
- void on_done(OnDoneFT f);
+ void on_done(OnDoneFT f) {
+ done = f;
+ }
/*!
* \brief is_open
* \return returns true if the underlying socket is opened.
*/
- bool is_open() const;
+ bool is_open() const {
+ return socket->is_open();
+ }
+};
+
+struct Client : private BaseClient<boost::asio::ip::tcp::socket> {
+
+ using BaseClient::BaseClient;
+ using BaseClient::operator=;
+
+ using BaseClient::async_receive;
+
+ using BaseClient::async_send;
+ using BaseClient::async_connect;
+ using BaseClient::close;
+
+ using BaseClient::on_done;
+
+ using BaseClient::is_open;
+
+};
+
+struct SSLClient : private BaseClient<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> {
+
+ using BaseClient::BaseClient;
+ using BaseClient::operator=;
+
+ /*!
+ * \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.
+ */
+ void async_connect(std::string next_host, std::string next_port, std::function<void()> on_connect) {
+
+ auto new_on_connect = [this, next_host, on_connect](){
+
+ socket->set_verify_mode(boost::asio::ssl::verify_peer);
+ socket->set_verify_callback(boost::asio::ssl::rfc2818_verification(next_host));
+
+ socket->async_handshake(boost::asio::ssl::stream_base::client, [this, on_connect](boost::system::error_code const& ec) {
+ if(!ec) {
+ on_connect();
+ } else {
+ BOOST_LOG_TRIVIAL(error) << ec.message();
+ if(done) {
+ done();
+ }
+ }
+ });
+ };
+
+ ::async_connect(socket->lowest_layer(), next_host, next_port, new_on_connect);
+ }
+
+ using BaseClient::async_send;
+ using BaseClient::async_receive;
+
+ /*!
+ * \brief close Closes the underlying socket.
+ */
+ void close() {
+ socket->lowest_layer().close();
+ }
+
+ using BaseClient::on_done;
+
+ /*!
+ * \brief is_open
+ * \return returns true if the underlying socket is opened.
+ */
+ bool is_open() const {
+ return socket->lowest_layer().is_open();
+ }
};
+
+
diff --git a/libcmix-network/connect.cpp b/libcmix-network/connect.cpp
index 01e72de..9df9b56 100644
--- a/libcmix-network/connect.cpp
+++ b/libcmix-network/connect.cpp
@@ -4,8 +4,10 @@
#include <boost/asio/ip/basic_resolver.hpp>
#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ssl.hpp>
using namespace boost::asio::ip;
+using namespace boost::asio;
using boost::asio::io_service;
boost::asio::ip::tcp::socket connect(std::string host, std::string port, io_service& io_service) {
@@ -50,7 +52,7 @@ struct IterationInfo {
{}
};
-void async_connect_iteration(tcp::socket& socket, std::shared_ptr<IterationInfo> info, std::function<void()> on_connect) {
+void async_connect_iteration(basic_socket<tcp, stream_socket_service<tcp>>& socket, std::shared_ptr<IterationInfo> info, std::function<void()> on_connect) {
if(info->it == boost::asio::ip::tcp::resolver::iterator()) {
throw std::runtime_error("None of the supplied endpoints responded");
@@ -91,16 +93,16 @@ void async_connect_iteration(tcp::socket& socket, std::shared_ptr<IterationInfo>
socket.async_connect(*(info->it), handler);
}
-void async_connect(tcp::socket& socket, std::string host, std::string next_port, std::function<void()> on_connect)
+void async_connect(basic_socket<tcp, stream_socket_service<tcp>>& socket, std::string host, std::string port, std::function<void()> on_connect)
{
boost::asio::ip::basic_resolver<tcp> resolver(socket.get_io_service());
- boost::asio::ip::basic_resolver_query<tcp> query(host, next_port);
+ boost::asio::ip::basic_resolver_query<tcp> query(host, port);
- BOOST_LOG_TRIVIAL(trace) << "connecting to: \"" << host << ":" << next_port << "\"";
+ BOOST_LOG_TRIVIAL(trace) << "connecting to: \"" << host << ":" << port << "\"";
auto it = resolver.resolve(query);
std::shared_ptr<IterationInfo> info = std::make_shared<IterationInfo>(0, it, socket.get_io_service());
-
+
async_connect_iteration(socket, info, on_connect);
-}
+} \ No newline at end of file
diff --git a/libcmix-network/connect.hpp b/libcmix-network/connect.hpp
index 0a58115..f58c3e1 100644
--- a/libcmix-network/connect.hpp
+++ b/libcmix-network/connect.hpp
@@ -2,6 +2,7 @@
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/io_service.hpp>
+#include <boost/asio/ssl.hpp>
/*!
* \file
@@ -23,4 +24,4 @@ boost::asio::ip::tcp::socket connect(std::string host, std::string port, boost::
* \param next_port The port
* \param on_connect The function to call when the connect has succeeded.
*/
-void async_connect(boost::asio::ip::tcp::socket& socket, std::string host, std::string next_port, std::function<void()> on_connect);
+void async_connect(boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp>>& socket, std::string host, std::string port, std::function<void()> on_connect); \ No newline at end of file
diff --git a/libcmix-network/protobufclient.cpp b/libcmix-network/protobufclient.cpp
deleted file mode 100644
index e69de29..0000000
--- a/libcmix-network/protobufclient.cpp
+++ /dev/null
diff --git a/libcmix-network/protobufclient.hpp b/libcmix-network/protobufclient.hpp
index 247b71f..df84152 100644
--- a/libcmix-network/protobufclient.hpp
+++ b/libcmix-network/protobufclient.hpp
@@ -4,8 +4,13 @@
#include "logging.hpp"
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ssl.hpp>
+
#include <type_traits>
+#include <iostream>
+
/*!
* \file
*/
@@ -15,6 +20,7 @@
* in to a desired wireformat to serialize and send or receive via the Client.
* \tparam T The Protobuf functor to use when transforming messages.
*/
+
template <typename T>
class ProtobufClient : private Client
{
@@ -31,6 +37,7 @@ public:
template<typename V, typename F>
void async_send(V value, F on_sent) {
typename T::proto_type m = T()(value);
+
Client::async_send(m.SerializeAsString(), on_sent);
}
@@ -65,3 +72,54 @@ public:
using Client::on_done;
using Client::is_open;
};
+
+template <typename T>
+class SSLProtobufClient : private SSLClient
+{
+public:
+ using SSLClient::SSLClient;
+ using SSLClient::operator=;
+ using SSLClient::async_connect;
+
+ /*!
+ * \brief an async_send wrapper that transforms a specific message to the container message an sends it
+ * \param value The specific message to send.
+ * \param on_sent The function to call after succesfully sending the message.
+ */
+ template<typename V, typename F>
+ void async_send(V value, F on_sent) {
+ typename T::proto_type m = T()(value);
+ SSLClient::async_send(m.SerializeAsString(), on_sent);
+ }
+
+ /*!
+ * \brief an async_send wrapper, like the above but without the on_sent callback.
+ * \param value The specific message to send.
+ */
+ template<typename V>
+ void async_send(V value) {
+ async_send(value, []{});
+ }
+
+ /*!
+ * \brief An async_receive wrapper that transforms the wireformat to the protobuf
+ * container message type.
+ * \param message_handler The callback to call after receiving a message.
+ */
+ template <typename F>
+ void async_receive(F message_handler) {
+ auto f = [message_handler](std::vector<uint8_t> const& buffer) {
+ 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);
+ };
+ SSLClient::async_receive(f);
+ }
+
+ using SSLClient::close;
+ using SSLClient::on_done;
+ using SSLClient::is_open;
+};
diff --git a/libcmix-network/server.cpp b/libcmix-network/server.cpp
index 34e3183..195c5a0 100644
--- a/libcmix-network/server.cpp
+++ b/libcmix-network/server.cpp
@@ -45,10 +45,27 @@ Server::Server(io_service& io_service, const ListenSettings& listen_settings, Ac
Server::Server(io_service& io_service, const ListenSettings& listen_settings, std::shared_ptr<ssl::context> ctx, SSLAcceptHandler accept_handler)
: Server(io_service, listen_settings)
{
+ ctx->set_options(
+ boost::asio::ssl::context::default_workarounds
+ | boost::asio::ssl::context::no_sslv2
+ | boost::asio::ssl::context::single_dh_use
+ );
+
+ ctx->use_certificate_chain_file(listen_settings.cert);
+ ctx->use_private_key_file(listen_settings.key, boost::asio::ssl::context::pem);
+ ctx->use_tmp_dh_file(listen_settings.dhparam);
+ ctx->set_default_verify_paths();
+
if(v4_acceptor.is_open()) {
v4_acceptor.start_accepting(ctx, accept_handler);
}
if(v6_acceptor.is_open()) {
v6_acceptor.start_accepting(ctx, accept_handler);
}
+}
+
+void Server::close()
+{
+ v4_acceptor.close();
+ v6_acceptor.close();
} \ No newline at end of file
diff --git a/libcmix-network/server.hpp b/libcmix-network/server.hpp
index fad7c71..6976f04 100644
--- a/libcmix-network/server.hpp
+++ b/libcmix-network/server.hpp
@@ -19,6 +19,9 @@ struct ListenSettings {
std::string ipv6_inaddr; ///< Listen on this ipv6 address
uint16_t port; ///< Listen on this port.
bool use_ssl; ///< Should we use ssl
+ std::string cert; ///< The cert to use in pem format.
+ std::string key; ///< The corresponding key in pem format.
+ std::string dhparam; ///< The diffie helman parameters.
};
/*!
@@ -50,4 +53,6 @@ public:
*/
Server(boost::asio::io_service& io_service, ListenSettings const& listen_settings, std::shared_ptr<boost::asio::ssl::context> ctx, SSLAcceptHandler accept_handler);
+ void close();
+
};