diff options
Diffstat (limited to 'common/connectionbase.cpp')
-rw-r--r-- | common/connectionbase.cpp | 184 |
1 files changed, 133 insertions, 51 deletions
diff --git a/common/connectionbase.cpp b/common/connectionbase.cpp index a113e6a..75a9a9a 100644 --- a/common/connectionbase.cpp +++ b/common/connectionbase.cpp @@ -1,6 +1,15 @@ #include "connectionbase.h" +#include <boost/serialization/vector.hpp> +#include <boost/serialization/string.hpp> +#include <boost/serialization/shared_ptr.hpp> +#include <boost/archive/binary_oarchive.hpp> +#include <boost/archive/binary_iarchive.hpp> + +#include <cstring> +#include <sstream> #include <exception> +#include <stdexcept> #include <iostream> @@ -35,73 +44,146 @@ void ConnectionBase::got_data(uint8_t* data, std::size_t bytes) { pending_size = 0; - Message::p m; + try { + // Create Boost.Serialization archive of data. + std::istringstream is(std::string((char*)data, bytes)); + boost::archive::binary_iarchive ia(is); + + switch(pending_type) { + case Message::Types::Hello: { + Message::Hello::p m = make_shared<Message::Hello>(); + ia & m; + got_message(m); + } break; + + case Message::Types::Login: { + Message::Login::p m = make_shared<Message::Login>(); + ia & m; + got_message(m); + } break; + + case Message::Types::LoginResponse: { + Message::LoginResponse::p m = make_shared<Message::LoginResponse>(); + ia & m; + got_message(m); + } break; + + case Message::Types::GameStart: { + Message::GameStart::p m = make_shared<Message::GameStart>(); + ia & m; + got_message(m); + } break; + + case Message::Types::Ready: { + Message::Ready::p m = make_shared<Message::Ready>(); + ia & m; + got_message(m); + } break; + + case Message::Types::RoundStart: { + Message::RoundStart::p m = make_shared<Message::RoundStart>(); + ia & m; + got_message(m); + } break; + + case Message::Types::RoundState: { + Message::RoundState::p m = make_shared<Message::RoundState>(); + ia & m; + got_message(m); + } break; + + case Message::Types::RoundAction: { + Message::RoundAction::p m = make_shared<Message::RoundAction>(); + ia & m; + got_message(m); + } break; + + case Message::Types::RoundEnd: { + Message::RoundEnd::p m = make_shared<Message::RoundEnd>(); + ia & m; + got_message(m); + } break; + + default: + throw std::runtime_error("Deserialization attempted on unknown message type."); + } + + } catch(std::exception& e) { + error(std::string("Deserialization failed: ") + e.what()); + } +} + +void ConnectionBase::send(const Message::p& msg) { + // Create Boost.Serialization archive. + std::ostringstream os; + boost::archive::binary_oarchive oa(os); - switch(pending_type) { - case Message::Types::Hello: - m = make_shared<Message::Hello>(); - break; + switch(msg->type) { + case Message::Types::Hello: { + Message::Hello::p m = dynamic_pointer_cast<Message::Hello>(msg); + oa & m; + } break; - case Message::Types::Login: - m = make_shared<Message::Login>(); - break; + case Message::Types::Login: { + Message::Login::p m = dynamic_pointer_cast<Message::Login>(msg); + oa & m; + } break; - case Message::Types::LoginResponse: - m = make_shared<Message::LoginResponse>(); - break; + case Message::Types::LoginResponse: { + Message::LoginResponse::p m = dynamic_pointer_cast<Message::LoginResponse>(msg); + oa & m; + } break; - case Message::Types::GameStart: - m = make_shared<Message::GameStart>(); - break; + case Message::Types::GameStart: { + Message::GameStart::p m = dynamic_pointer_cast<Message::GameStart>(msg); + oa & m; + } break; - case Message::Types::Ready: - m = make_shared<Message::Ready>(); - break; + case Message::Types::Ready: { + Message::Ready::p m = dynamic_pointer_cast<Message::Ready>(msg); + oa & m; + } break; - case Message::Types::RoundStart: - m = make_shared<Message::RoundStart>(); - break; + case Message::Types::RoundStart: { + Message::RoundStart::p m = dynamic_pointer_cast<Message::RoundStart>(msg); + oa & m; + } break; - case Message::Types::RoundState: - m = make_shared<Message::RoundState>(); - break; + case Message::Types::RoundState: { + Message::RoundState::p m = dynamic_pointer_cast<Message::RoundState>(msg); + oa & m; + } break; - case Message::Types::RoundAction: - m = make_shared<Message::RoundAction>(); - break; - - case Message::Types::RoundEnd: - m = make_shared<Message::RoundEnd>(); - break; + case Message::Types::RoundAction: { + Message::RoundAction::p m = dynamic_pointer_cast<Message::RoundAction>(msg); + oa & m; + } break; - default: - error("Deserialization attempted on unknown message type."); - } - - if(bytes) { - try { - m->deserialize(data, bytes); + case Message::Types::RoundEnd: { + Message::RoundEnd::p m = dynamic_pointer_cast<Message::RoundEnd>(msg); + oa & m; + } break; - } catch(std::exception& e) { - error(std::string("Deserialization failed: ") + e.what()); - } + default: + throw std::runtime_error("Serialization attempted on unknown message type."); } - got_message(m); -} - -void ConnectionBase::send(const Message::p& msg) { - uint16_t* header = new uint16_t[2]; + // Extract data. + std::string s = os.str(); - std::pair<uint8_t*, std::size_t> smsg = msg->serialize(); + // Allocate buffer. + uint8_t* buf = new uint8_t[4 + s.size()]; + // Write header. + uint16_t* header = (uint16_t*)buf; header[0] = uint16_t(msg->type); - header[1] = uint16_t(smsg.second); + header[1] = uint16_t(s.size()); - write_data((uint8_t*)header, 4); - if(smsg.second) { - write_data(smsg.first, smsg.second); - } + // Copy data. + memcpy(buf + 4, s.c_str(), s.size()); + + // Send buffer. + write_data(buf, 4 + s.size()); } ConnectionBase::ConnectionBase() { |