#pragma once #include "client.hpp" #include "logging.hpp" #include #include #include #include /*! * \file */ /*! * \brief A wrapper around Client that accepts a Functor that can turn specific protobuf messages. * 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 class ProtobufClient : private Client { public: using Client::Client; using Client::operator=; using Client::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 void async_send(V value, F on_sent) { typename T::proto_type m = T()(value); Client::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 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 void async_receive(F message_handler) { auto f = [message_handler](std::vector 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); }; Client::async_receive(f); } using Client::close; using Client::on_done; using Client::is_open; }; template 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 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 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 void async_receive(F message_handler) { auto f = [message_handler](std::vector 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; };