diff options
-rw-r--r-- | common/connectionbase.cpp | 184 | ||||
-rw-r--r-- | common/message.cpp | 148 | ||||
-rw-r--r-- | common/message.h | 113 |
3 files changed, 189 insertions, 256 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() { diff --git a/common/message.cpp b/common/message.cpp deleted file mode 100644 index 5c5ab50..0000000 --- a/common/message.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "message.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> - -Message::Base::Base(Type t) : type(t) { - -} - -Message::NullBase::NullBase(Type t) : Base(t) { - -} - -std::pair<uint8_t*, std::size_t> Message::NullBase::serialize() { - return std::pair<uint8_t*, std::size_t>(0, 0); -} - -void Message::NullBase::deserialize(uint8_t* data, std::size_t bytes) { - -} - -template<class Sub> -Message::BoostBase<Sub>::BoostBase(Type t) : Base(t) { - -} - -template<class Sub> -std::pair<uint8_t*, std::size_t> Message::BoostBase<Sub>::serialize() { - std::ostringstream os; - boost::archive::binary_oarchive oa(os); - - oa & *this; - - std::size_t s = os.str().size(); - uint8_t* buf = new uint8_t[s]; - - memcpy(buf, os.str().c_str(), s); - - return std::pair<uint8_t*, std::size_t>(buf, s); -} - -template<class Sub> -void Message::BoostBase<Sub>::deserialize(uint8_t* data, std::size_t bytes) { - std::istringstream is(std::string((char*)data, bytes)); - boost::archive::binary_iarchive ia(is); - - ia & *this; -} - -Message::Hello::Hello() : Base(Types::Hello) { - -} - -Message::Hello::Hello(const std::string& v) : Base(Types::Hello), version(v) { - -} - -std::pair<uint8_t*, std::size_t> Message::Hello::serialize() { - std::size_t s = version.size(); - uint8_t* buf = new uint8_t[s]; - - memcpy(buf, version.c_str(), version.size()); - - return std::pair<uint8_t*, std::size_t>(buf, s); -} - -void Message::Hello::deserialize(uint8_t* data, std::size_t bytes) { - version = std::string((char*)data, bytes); -} - -Message::Login::Login() : Base(Types::Login) { - -} - -Message::Login::Login(const std::string& n) : Base(Types::Login), nick(n) { - -} - -std::pair<uint8_t*, std::size_t> Message::Login::serialize() { - std::size_t s = nick.size(); - uint8_t* buf = new uint8_t[s]; - - memcpy(buf, nick.c_str(), nick.size()); - - return std::pair<uint8_t*, std::size_t>(buf, s); -} - -void Message::Login::deserialize(uint8_t* data, std::size_t bytes) { - nick = std::string((char*)data, bytes); -} - -Message::LoginResponse::LoginResponse() : Base(Types::LoginResponse) { - -} - -Message::LoginResponse::LoginResponse(bool ok) : Base(Types::LoginResponse), login_ok(ok) { - -} - -std::pair<uint8_t*, std::size_t> Message::LoginResponse::serialize() { - uint8_t* buf = new uint8_t[1]; - - buf[0] = uint8_t(login_ok); - - return std::pair<uint8_t*, std::size_t>(buf, 1); -} - -void Message::LoginResponse::deserialize(uint8_t* data, std::size_t bytes) { - login_ok = bool(data[0]); -} - -Message::GameStart::GameStart() : BoostBase<GameStart>(Types::GameStart) { - -} - -Message::Ready::Ready() : NullBase(Types::Ready) { - -} - -Message::RoundStart::RoundStart() : NullBase(Types::RoundStart) { - -} - -Message::RoundState::RoundState() : BoostBase<RoundState>(Types::RoundState) { - -} - -Message::RoundState::RoundState(const Player& pl_d, const Player& pl_r, const Player& pl_u, const Player& pl_l, const Tiles& d, const Actions& a) - : BoostBase<RoundState>(Types::RoundState), dora(d), possible_actions(a) { - players[0] = pl_d; - players[1] = pl_r; - players[2] = pl_u; - players[3] = pl_l; -} - -Message::RoundAction::RoundAction() : BoostBase<RoundAction>(Types::RoundAction) { - -} - -Message::RoundEnd::RoundEnd() : NullBase(Types::RoundEnd) { - -} diff --git a/common/message.h b/common/message.h index 1c9276d..d2eb5d7 100644 --- a/common/message.h +++ b/common/message.h @@ -36,109 +36,96 @@ namespace Message { class Base { protected: - Base(Type t); + Base(Type t) : type(t) {} + virtual ~Base() {} public: const Type type; - - virtual std::pair<uint8_t*, std::size_t> serialize() = 0; - virtual void deserialize(uint8_t* data, std::size_t bytes) = 0; - }; - - class NullBase : public Base { - protected: - NullBase(Type t); - - public: - virtual std::pair<uint8_t*, std::size_t> serialize(); - virtual void deserialize(uint8_t* data, std::size_t bytes); - }; - - template<class Sub> - class BoostBase : public Base { - protected: - BoostBase(Type t); - - public: - virtual std::pair<uint8_t*, std::size_t> serialize(); - virtual void deserialize(uint8_t* data, std::size_t bytes); - - template<class Archive> - void serialize(Archive & ar, const unsigned int version) { - ar & dynamic_cast<Sub&>(*this); - } }; class Hello : public Base { public: typedef boost::shared_ptr<Hello> p; - Hello(); - Hello(const std::string& v); + Hello(const std::string& v = "") : Base(Types::Hello), version(v) {} std::string version; - virtual std::pair<uint8_t*, std::size_t> serialize(); - virtual void deserialize(uint8_t* data, std::size_t bytes); + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + ar & version; + } }; class Login : public Base { public: typedef boost::shared_ptr<Login> p; - Login(); - Login(const std::string& n); + Login(const std::string& n = "") : Base(Types::Login), nick(n) {} std::string nick; - virtual std::pair<uint8_t*, std::size_t> serialize(); - virtual void deserialize(uint8_t* data, std::size_t bytes); + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + ar & nick; + } }; class LoginResponse : public Base { public: typedef boost::shared_ptr<LoginResponse> p; - LoginResponse(); - LoginResponse(bool ok); + LoginResponse(bool ok = false) : Base(Types::LoginResponse), login_ok(ok) {} bool login_ok; - virtual std::pair<uint8_t*, std::size_t> serialize(); - virtual void deserialize(uint8_t* data, std::size_t bytes); + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + ar & login_ok; + } }; - class GameStart : public BoostBase<GameStart> { + class GameStart : public Base { public: typedef boost::shared_ptr<GameStart> p; - GameStart(); + GameStart() : Base(Types::GameStart) {} std::vector<std::string> players; int player_id; template<class Archive> - void serialize(Archive & ar, const unsigned int version) { + void serialize(Archive & ar, const unsigned int v) { ar & players; ar & player_id; } }; - class Ready : public NullBase { + class Ready : public Base { public: typedef boost::shared_ptr<Ready> p; - Ready(); + Ready() : Base(Types::Ready) {} + + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + + } }; - class RoundStart : public NullBase { + class RoundStart : public Base { public: typedef boost::shared_ptr<RoundStart> p; - RoundStart(); + RoundStart() : Base(Types::RoundStart) {} + + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + + } }; - class RoundState : public BoostBase<RoundState> { + class RoundState : public Base { public: typedef boost::shared_ptr<RoundState> p; @@ -152,15 +139,21 @@ namespace Message { Tiles pond; template<class Archive> - void serialize(Archive & ar, const unsigned int version) { + void serialize(Archive & ar, const unsigned int v) { ar & hand; ar & open; ar & pond; } }; - RoundState(); - RoundState(const Player& pl_d, const Player& pl_r, const Player& pl_u, const Player& pl_l, const Tiles& d, const Actions& a); + RoundState() : Base(Types::RoundState) {} + RoundState(const Player& pl_d, const Player& pl_r, const Player& pl_u, const Player& pl_l, const Tiles& d, const Actions& a) + : Base(Types::RoundState), dora(d), possible_actions(a) { + players[0] = pl_d; + players[1] = pl_r; + players[2] = pl_u; + players[3] = pl_l; + } Player players[4]; @@ -169,33 +162,39 @@ namespace Message { Actions possible_actions; template<class Archive> - void serialize(Archive & ar, const unsigned int version) { + void serialize(Archive & ar, const unsigned int v) { ar & players; ar & dora; ar & possible_actions; } }; - class RoundAction : public BoostBase<RoundAction> { + class RoundAction : public Base { public: typedef boost::shared_ptr<RoundAction> p; - RoundAction(); + RoundAction() : Base(Types::RoundAction) {} Action action; template<class Archive> - void serialize(Archive & ar, const unsigned int version) { + void serialize(Archive & ar, const unsigned int v) { ar & action; } }; - class RoundEnd : public NullBase { + class RoundEnd : public Base { public: typedef boost::shared_ptr<RoundEnd> p; - RoundEnd(); + RoundEnd() : Base(Types::RoundEnd) {} + + template<class Archive> + void serialize(Archive & ar, const unsigned int v) { + + } }; + typedef boost::shared_ptr<Base> p; }; |