Loading Common/include/Messenger.h +22 −10 Original line number Diff line number Diff line Loading @@ -11,7 +11,19 @@ namespace asio = boost::asio; using asio::ip::tcp; using header_t = std::size_t; // Enum to handle message type, used to ensure enum class MessageType : unsigned char { string, builder, file, error }; // Message header struct Header { std::size_t size; MessageType type; }; class Messenger { Loading @@ -19,14 +31,14 @@ public: explicit Messenger(tcp::socket &socket) : socket(socket) {} // Send a string as a message void send(const std::string &message); void send(const std::string &message, MessageType type=MessageType::string); void async_send(const std::string &message, asio::yield_context yield); void async_send(const std::string &message, asio::yield_context yield, MessageType type=MessageType::string); // Receive message as a string std::string receive(); std::string receive(MessageType type=MessageType::string); std::string async_receive(asio::yield_context yield); std::string async_receive(asio::yield_context yield, MessageType type=MessageType::string); // Send entire contents of streambuf void async_send(asio::streambuf &message_body, asio::yield_context yield); Loading @@ -51,15 +63,15 @@ public: private: tcp::socket &socket; void send_header(std::size_t message_size); void send_header(std::size_t message_size, MessageType type); void async_send_header(std::size_t message_size, asio::yield_context yield); void async_send_header(std::size_t message_size, MessageType type, asio::yield_context yield); std::size_t receive_header(); Header receive_header(const MessageType& type); std::size_t async_receive_header(asio::yield_context yield); Header async_receive_header(const MessageType& type, asio::yield_context yield); static constexpr std::size_t header_size() { return sizeof(header_t); return sizeof(Header); } }; No newline at end of file Common/src/Messenger.cpp +49 −40 Original line number Diff line number Diff line Loading @@ -4,40 +4,49 @@ #include <iostream> #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <system_error> // Send the header, which is the size of the message that will immediately follow void Messenger::send_header(header_t message_size) { auto header = asio::buffer(&message_size, header_size()); asio::write(socket, header, asio::transfer_exactly(header_size())); // Send the header, which is the size and type of the message that will immediately follow void Messenger::send_header(std::size_t message_size, MessageType type) { Header header = {message_size, type}; auto header_buffer = asio::buffer(&header, header_size()); asio::write(socket, header_buffer, asio::transfer_exactly(header_size())); } // Send the header asynchrnously, which is the size of the message that will immediately follow void Messenger::async_send_header(header_t message_size, asio::yield_context yield) { auto header = asio::buffer(&message_size, header_size()); asio::async_write(socket, header, asio::transfer_exactly(header_size()), yield); // Send the header, which is the size and type of the message that will immediately follow, asynchronously void Messenger::async_send_header(std::size_t message_size, MessageType type, asio::yield_context yield) { Header header = {message_size, type}; auto header_buffer = asio::buffer(&header, header_size()); asio::async_write(socket, header_buffer, asio::transfer_exactly(header_size()), yield); } // Receive the message header header_t Messenger::receive_header() { header_t message_size; auto header = asio::buffer(&message_size, header_size()); asio::read(socket, header, asio::transfer_exactly(header_size())); return message_size; Header Messenger::receive_header(const MessageType& type) { Header header; auto header_buffer = asio::buffer(&header, header_size()); asio::read(socket, header_buffer, asio::transfer_exactly(header_size())); if(type != header.type) { throw std::system_error(EBADMSG, std::generic_category(), "received bad message type"); } return header; } // Receive the message header header_t Messenger::async_receive_header(asio::yield_context yield) { header_t message_size; auto header = asio::buffer(&message_size, header_size()); asio::async_read(socket, header, asio::transfer_exactly(header_size()), yield); return message_size; Header Messenger::async_receive_header(const MessageType& type, asio::yield_context yield) { Header header; auto header_buffer = asio::buffer(&header, header_size()); asio::async_read(socket, header_buffer, asio::transfer_exactly(header_size()), yield); if(type != header.type) { throw std::system_error(EBADMSG, std::generic_category(), "received bad message type"); } return header; } // Send a string message void Messenger::send(const std::string &message) { void Messenger::send(const std::string &message, MessageType type) { auto message_size = message.size(); send_header(message_size); send_header(message_size, MessageType::string); // Write the message body auto body = asio::buffer(message.data(), message_size); Loading @@ -45,10 +54,10 @@ void Messenger::send(const std::string &message) { } // Send a string message asynchronously void Messenger::async_send(const std::string &message, asio::yield_context yield) { void Messenger::async_send(const std::string &message, asio::yield_context yield, MessageType type) { auto message_size = message.size(); async_send_header(message_size, yield); async_send_header(message_size, MessageType::string, yield); // Write the message body auto body = asio::buffer(message.data(), message_size); Loading @@ -59,7 +68,7 @@ void Messenger::async_send(const std::string &message, asio::yield_context yield void Messenger::async_send(asio::streambuf &message_body, asio::yield_context yield) { auto message_size = message_body.size(); async_send_header(message_size, yield); async_send_header(message_size, MessageType::string, yield); // Write the message body asio::async_write(socket, message_body, asio::transfer_exactly(message_size), yield); Loading @@ -69,7 +78,7 @@ void Messenger::async_send(asio::streambuf &message_body, asio::yield_context yi void Messenger::send(asio::streambuf &message_body) { auto message_size = message_body.size(); send_header(message_size); send_header(message_size, MessageType::string); // Write the message body asio::write(socket, message_body, asio::transfer_exactly(message_size)); Loading @@ -88,7 +97,7 @@ void Messenger::send_file(boost::filesystem::path file_path, std::size_t chunk_s auto file_size = boost::filesystem::file_size(file_path); // Send message header send_header(file_size); send_header(file_size, MessageType::file); // Send file as message body, in chunk_size sections auto bytes_remaining = file_size; Loading Loading @@ -118,7 +127,7 @@ void Messenger::async_send_file(boost::filesystem::path file_path, asio::yield_c file.open(file_path.string(), std::fstream::in | std::fstream::binary); auto file_size = boost::filesystem::file_size(file_path); async_send_header(file_size, yield); async_send_header(file_size, MessageType::file, yield); // Send file in chunk_size bits auto bytes_remaining = file_size; Loading @@ -138,13 +147,12 @@ void Messenger::async_send_file(boost::filesystem::path file_path, asio::yield_c } // Receive a string message std::string Messenger::receive() { // Read message size from header auto message_size = receive_header(); std::string Messenger::receive(MessageType type) { auto header = receive_header(MessageType::string); // Read the message body asio::streambuf buffer; asio::read(socket, buffer, asio::transfer_exactly(message_size)); asio::read(socket, buffer, asio::transfer_exactly(header.size)); // Construct a string from the message body std::string body((std::istreambuf_iterator<char>(&buffer)), Loading @@ -154,13 +162,12 @@ std::string Messenger::receive() { } // Receive a string message asynchronously std::string Messenger::async_receive(asio::yield_context yield) { // Read message size from header auto message_size = async_receive_header(yield); std::string Messenger::async_receive(asio::yield_context yield, MessageType type) { auto header = async_receive_header(MessageType::string, yield); // Read the message body asio::streambuf buffer; asio::async_read(socket, buffer, asio::transfer_exactly(message_size), yield); asio::async_read(socket, buffer, asio::transfer_exactly(header.size), yield); // Construct a string from the message body std::string body((std::istreambuf_iterator<char>(&buffer)), Loading @@ -178,7 +185,8 @@ void Messenger::receive_file(boost::filesystem::path file_path, std::size_t chun // Openfile for writing file.open(file_path.string(), std::fstream::out | std::fstream::binary | std::fstream::trunc); auto total_size = receive_header(); auto header = receive_header(MessageType::file); auto total_size = header.size; // Receive file in chunk_size messages auto bytes_remaining = total_size; Loading Loading @@ -208,7 +216,8 @@ void Messenger::async_receive_file(boost::filesystem::path file_path, asio::yiel // Openfile for writing file.open(file_path.string(), std::fstream::out | std::fstream::binary | std::fstream::trunc); auto total_size = async_receive_header(yield); auto header = async_receive_header(MessageType::file, yield); auto total_size = header.size; // Receive file in chunk_size messages auto bytes_remaining = total_size; Loading @@ -233,7 +242,7 @@ Builder Messenger::receive_builder() { Messenger messenger(socket); // Read in the serialized builder as a string auto serialized_builder = messenger.receive(); auto serialized_builder = messenger.receive(MessageType::builder); // de-serialize Builder Builder builder; Loading @@ -248,7 +257,7 @@ Builder Messenger::async_receive_builder(asio::yield_context yield) { Messenger messenger(socket); // Read in the serialized builder as a string auto serialized_builder = messenger.async_receive(yield); auto serialized_builder = messenger.async_receive(yield, MessageType::builder); // de-serialize Builder Builder builder; Loading @@ -268,7 +277,7 @@ void Messenger::async_send(Builder builder, asio::yield_context yield) { archive << builder; auto serialized_builder = archive_stream.str(); messenger.async_send(serialized_builder, yield); messenger.async_send(serialized_builder, yield, MessageType::builder); } void Messenger::send(Builder builder) { Loading @@ -280,5 +289,5 @@ void Messenger::send(Builder builder) { archive << builder; auto serialized_builder = archive_stream.str(); messenger.send(serialized_builder); messenger.send(serialized_builder, MessageType::builder); } No newline at end of file Loading
Common/include/Messenger.h +22 −10 Original line number Diff line number Diff line Loading @@ -11,7 +11,19 @@ namespace asio = boost::asio; using asio::ip::tcp; using header_t = std::size_t; // Enum to handle message type, used to ensure enum class MessageType : unsigned char { string, builder, file, error }; // Message header struct Header { std::size_t size; MessageType type; }; class Messenger { Loading @@ -19,14 +31,14 @@ public: explicit Messenger(tcp::socket &socket) : socket(socket) {} // Send a string as a message void send(const std::string &message); void send(const std::string &message, MessageType type=MessageType::string); void async_send(const std::string &message, asio::yield_context yield); void async_send(const std::string &message, asio::yield_context yield, MessageType type=MessageType::string); // Receive message as a string std::string receive(); std::string receive(MessageType type=MessageType::string); std::string async_receive(asio::yield_context yield); std::string async_receive(asio::yield_context yield, MessageType type=MessageType::string); // Send entire contents of streambuf void async_send(asio::streambuf &message_body, asio::yield_context yield); Loading @@ -51,15 +63,15 @@ public: private: tcp::socket &socket; void send_header(std::size_t message_size); void send_header(std::size_t message_size, MessageType type); void async_send_header(std::size_t message_size, asio::yield_context yield); void async_send_header(std::size_t message_size, MessageType type, asio::yield_context yield); std::size_t receive_header(); Header receive_header(const MessageType& type); std::size_t async_receive_header(asio::yield_context yield); Header async_receive_header(const MessageType& type, asio::yield_context yield); static constexpr std::size_t header_size() { return sizeof(header_t); return sizeof(Header); } }; No newline at end of file
Common/src/Messenger.cpp +49 −40 Original line number Diff line number Diff line Loading @@ -4,40 +4,49 @@ #include <iostream> #include <boost/archive/text_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <system_error> // Send the header, which is the size of the message that will immediately follow void Messenger::send_header(header_t message_size) { auto header = asio::buffer(&message_size, header_size()); asio::write(socket, header, asio::transfer_exactly(header_size())); // Send the header, which is the size and type of the message that will immediately follow void Messenger::send_header(std::size_t message_size, MessageType type) { Header header = {message_size, type}; auto header_buffer = asio::buffer(&header, header_size()); asio::write(socket, header_buffer, asio::transfer_exactly(header_size())); } // Send the header asynchrnously, which is the size of the message that will immediately follow void Messenger::async_send_header(header_t message_size, asio::yield_context yield) { auto header = asio::buffer(&message_size, header_size()); asio::async_write(socket, header, asio::transfer_exactly(header_size()), yield); // Send the header, which is the size and type of the message that will immediately follow, asynchronously void Messenger::async_send_header(std::size_t message_size, MessageType type, asio::yield_context yield) { Header header = {message_size, type}; auto header_buffer = asio::buffer(&header, header_size()); asio::async_write(socket, header_buffer, asio::transfer_exactly(header_size()), yield); } // Receive the message header header_t Messenger::receive_header() { header_t message_size; auto header = asio::buffer(&message_size, header_size()); asio::read(socket, header, asio::transfer_exactly(header_size())); return message_size; Header Messenger::receive_header(const MessageType& type) { Header header; auto header_buffer = asio::buffer(&header, header_size()); asio::read(socket, header_buffer, asio::transfer_exactly(header_size())); if(type != header.type) { throw std::system_error(EBADMSG, std::generic_category(), "received bad message type"); } return header; } // Receive the message header header_t Messenger::async_receive_header(asio::yield_context yield) { header_t message_size; auto header = asio::buffer(&message_size, header_size()); asio::async_read(socket, header, asio::transfer_exactly(header_size()), yield); return message_size; Header Messenger::async_receive_header(const MessageType& type, asio::yield_context yield) { Header header; auto header_buffer = asio::buffer(&header, header_size()); asio::async_read(socket, header_buffer, asio::transfer_exactly(header_size()), yield); if(type != header.type) { throw std::system_error(EBADMSG, std::generic_category(), "received bad message type"); } return header; } // Send a string message void Messenger::send(const std::string &message) { void Messenger::send(const std::string &message, MessageType type) { auto message_size = message.size(); send_header(message_size); send_header(message_size, MessageType::string); // Write the message body auto body = asio::buffer(message.data(), message_size); Loading @@ -45,10 +54,10 @@ void Messenger::send(const std::string &message) { } // Send a string message asynchronously void Messenger::async_send(const std::string &message, asio::yield_context yield) { void Messenger::async_send(const std::string &message, asio::yield_context yield, MessageType type) { auto message_size = message.size(); async_send_header(message_size, yield); async_send_header(message_size, MessageType::string, yield); // Write the message body auto body = asio::buffer(message.data(), message_size); Loading @@ -59,7 +68,7 @@ void Messenger::async_send(const std::string &message, asio::yield_context yield void Messenger::async_send(asio::streambuf &message_body, asio::yield_context yield) { auto message_size = message_body.size(); async_send_header(message_size, yield); async_send_header(message_size, MessageType::string, yield); // Write the message body asio::async_write(socket, message_body, asio::transfer_exactly(message_size), yield); Loading @@ -69,7 +78,7 @@ void Messenger::async_send(asio::streambuf &message_body, asio::yield_context yi void Messenger::send(asio::streambuf &message_body) { auto message_size = message_body.size(); send_header(message_size); send_header(message_size, MessageType::string); // Write the message body asio::write(socket, message_body, asio::transfer_exactly(message_size)); Loading @@ -88,7 +97,7 @@ void Messenger::send_file(boost::filesystem::path file_path, std::size_t chunk_s auto file_size = boost::filesystem::file_size(file_path); // Send message header send_header(file_size); send_header(file_size, MessageType::file); // Send file as message body, in chunk_size sections auto bytes_remaining = file_size; Loading Loading @@ -118,7 +127,7 @@ void Messenger::async_send_file(boost::filesystem::path file_path, asio::yield_c file.open(file_path.string(), std::fstream::in | std::fstream::binary); auto file_size = boost::filesystem::file_size(file_path); async_send_header(file_size, yield); async_send_header(file_size, MessageType::file, yield); // Send file in chunk_size bits auto bytes_remaining = file_size; Loading @@ -138,13 +147,12 @@ void Messenger::async_send_file(boost::filesystem::path file_path, asio::yield_c } // Receive a string message std::string Messenger::receive() { // Read message size from header auto message_size = receive_header(); std::string Messenger::receive(MessageType type) { auto header = receive_header(MessageType::string); // Read the message body asio::streambuf buffer; asio::read(socket, buffer, asio::transfer_exactly(message_size)); asio::read(socket, buffer, asio::transfer_exactly(header.size)); // Construct a string from the message body std::string body((std::istreambuf_iterator<char>(&buffer)), Loading @@ -154,13 +162,12 @@ std::string Messenger::receive() { } // Receive a string message asynchronously std::string Messenger::async_receive(asio::yield_context yield) { // Read message size from header auto message_size = async_receive_header(yield); std::string Messenger::async_receive(asio::yield_context yield, MessageType type) { auto header = async_receive_header(MessageType::string, yield); // Read the message body asio::streambuf buffer; asio::async_read(socket, buffer, asio::transfer_exactly(message_size), yield); asio::async_read(socket, buffer, asio::transfer_exactly(header.size), yield); // Construct a string from the message body std::string body((std::istreambuf_iterator<char>(&buffer)), Loading @@ -178,7 +185,8 @@ void Messenger::receive_file(boost::filesystem::path file_path, std::size_t chun // Openfile for writing file.open(file_path.string(), std::fstream::out | std::fstream::binary | std::fstream::trunc); auto total_size = receive_header(); auto header = receive_header(MessageType::file); auto total_size = header.size; // Receive file in chunk_size messages auto bytes_remaining = total_size; Loading Loading @@ -208,7 +216,8 @@ void Messenger::async_receive_file(boost::filesystem::path file_path, asio::yiel // Openfile for writing file.open(file_path.string(), std::fstream::out | std::fstream::binary | std::fstream::trunc); auto total_size = async_receive_header(yield); auto header = async_receive_header(MessageType::file, yield); auto total_size = header.size; // Receive file in chunk_size messages auto bytes_remaining = total_size; Loading @@ -233,7 +242,7 @@ Builder Messenger::receive_builder() { Messenger messenger(socket); // Read in the serialized builder as a string auto serialized_builder = messenger.receive(); auto serialized_builder = messenger.receive(MessageType::builder); // de-serialize Builder Builder builder; Loading @@ -248,7 +257,7 @@ Builder Messenger::async_receive_builder(asio::yield_context yield) { Messenger messenger(socket); // Read in the serialized builder as a string auto serialized_builder = messenger.async_receive(yield); auto serialized_builder = messenger.async_receive(yield, MessageType::builder); // de-serialize Builder Builder builder; Loading @@ -268,7 +277,7 @@ void Messenger::async_send(Builder builder, asio::yield_context yield) { archive << builder; auto serialized_builder = archive_stream.str(); messenger.async_send(serialized_builder, yield); messenger.async_send(serialized_builder, yield, MessageType::builder); } void Messenger::send(Builder builder) { Loading @@ -280,5 +289,5 @@ void Messenger::send(Builder builder) { archive << builder; auto serialized_builder = archive_stream.str(); messenger.send(serialized_builder); messenger.send(serialized_builder, MessageType::builder); } No newline at end of file