Commit 4fb55d2d authored by AdamSimpson's avatar AdamSimpson
Browse files

Add very basic message type

parent 1f03f805
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -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 {

@@ -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);
@@ -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
+49 −40
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -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);
@@ -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));
@@ -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;
@@ -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;
@@ -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)),
@@ -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)),
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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) {
@@ -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