From e483f468085379a986cbc48bb13a7983315475cf Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Sun, 12 Jun 2011 20:26:46 +0200 Subject: Reworked the message classes to be more coder-friendly. --- messages.cpp | 217 ++++++++++++++++++++++++----------------------------------- messages.h | 71 ++++++++++++++----- 2 files changed, 142 insertions(+), 146 deletions(-) diff --git a/messages.cpp b/messages.cpp index 68e46d2..b7b7b38 100644 --- a/messages.cpp +++ b/messages.cpp @@ -8,26 +8,38 @@ MessageBase::MessageBase() { type = MSG_TYPE_NONE; } +uint8_t MessageBase::read_type(boost::asio::ip::tcp::socket& socket) { + uint8_t type; + boost::asio::read(socket, boost::asio::buffer(&type, sizeof(uint8_t))); + + return type; +} + void MessageBase::send(boost::asio::ip::tcp::socket& socket) { boost::asio::write(socket, boost::asio::buffer(&type, sizeof(type))); - boost::asio::write(socket, b); + do_send(socket); } -std::size_t MessageBase::payload_size() { - return 0; -} +std::string MessageBase::read_string(boost::asio::ip::tcp::socket& socket) { + uint16_t str_len; + read(socket, str_len); -void MessageBase::read(boost::asio::ip::tcp::socket& socket) { - boost::asio::streambuf::mutable_buffers_type buf = b.prepare(payload_size()); - std::size_t size = boost::asio::read(socket, buf); - b.commit(size); + std::string s; + + char *buf = new char[str_len]; + boost::asio::read(socket, boost::asio::buffer(buf, str_len)); + + s.assign(buf, str_len); + delete[] buf; + + return s; } -uint8_t MessageBase::read_type(boost::asio::ip::tcp::socket& socket) { - uint8_t type; - boost::asio::read(socket, boost::asio::buffer(&type, sizeof(uint8_t))); +void MessageBase::write_string(boost::asio::ip::tcp::socket& socket, std::string str) { + uint16_t str_len = str.size(); + write(socket, str_len); - return type; + boost::asio::write(socket, boost::asio::buffer(str)); } /* Hello */ @@ -39,20 +51,18 @@ Hello::Hello() { Hello::Hello(uint8_t version) { type = MSG_TYPE_HELLO; - std::ostream os(&b); - os.write((const char*)&version, sizeof(version)); + this->version = version; } -std::size_t Hello::payload_size() { - return sizeof(uint8_t); +void Hello::do_send(boost::asio::ip::tcp::socket& socket) { + write(socket, version); } -uint8_t Hello::read_version() { - std::istream is(&b); - uint8_t version; - is.read((char*)&version, sizeof(version)); - b.consume(sizeof(version)); +void Hello::recv(boost::asio::ip::tcp::socket& socket) { + read(socket, version); +} +uint8_t Hello::get_version() { return version; } @@ -62,186 +72,137 @@ Pos::Pos() { type = MSG_TYPE_POS; } -Pos::Pos(float x, float y, float z) { +Pos::Pos(Vector3 pos) { type = MSG_TYPE_POS; - std::ostream os(&b); - os.write((const char*)&x, sizeof(x)); - os.write((const char*)&y, sizeof(y)); - os.write((const char*)&z, sizeof(z)); + this->pos = pos; +} + +void Pos::do_send(boost::asio::ip::tcp::socket& socket) { + write(socket, pos.x); + write(socket, pos.y); + write(socket, pos.z); } -std::size_t Pos::payload_size() { - return sizeof(float)*3; +void Pos::recv(boost::asio::ip::tcp::socket& socket) { + read(socket, pos.x); + read(socket, pos.y); + read(socket, pos.z); } -void Pos::get_pos(float& x, float& y, float& z) { - std::istream is(&b); - is.read((char*)&x, sizeof(x)); - is.read((char*)&y, sizeof(y)); - is.read((char*)&z, sizeof(z)); +Vector3 Pos::get_pos() { + return pos; } /* Chunk */ Chunk::Chunk() { type = MSG_TYPE_CHUNK; - - got_coords = false; } Chunk::Chunk(int64_t x, int64_t y) { type = MSG_TYPE_CHUNK; - std::ostream os(&b); - os.write((const char*)&x, sizeof(x)); - os.write((const char*)&y, sizeof(y)); - - got_coords = true; + this->x = x; + this->y = y; } // TODO: move this elsewhere const int chunk_size = 32; const int chunk_size_total = chunk_size + 3; -std::size_t Chunk::payload_size() { - return (got_coords ? sizeof(float)*chunk_size_total*chunk_size_total : sizeof(int64_t)*2); +void Chunk::do_send(boost::asio::ip::tcp::socket& socket) { + write(socket, x); + write(socket, y); + + boost::asio::write(socket, boost::asio::buffer(data, sizeof(float)*chunk_size_total*chunk_size_total)); +} + +void Chunk::recv(boost::asio::ip::tcp::socket& socket) { + read(socket, x); + read(socket, y); + + // do not free, caller takes ownership + data = new float[chunk_size_total*chunk_size_total]; + boost::asio::read(socket, boost::asio::buffer(data, sizeof(float)*chunk_size_total*chunk_size_total)); } void Chunk::set_data(float *data) { - std::ostream os(&b); - os.write((const char*)data, sizeof(float)*chunk_size_total*chunk_size_total); + // caller owns data + this->data = data; } float* Chunk::get_data() { - float *data = new float[chunk_size_total*chunk_size_total]; - std::istream is(&b); - is.read((char*)data, sizeof(float)*chunk_size_total*chunk_size_total); - return data; } void Chunk::get_coords(int64_t& x, int64_t& y) { - std::istream is(&b); - is.read((char*)&x, sizeof(x)); - is.read((char*)&y, sizeof(y)); - got_coords = true; + x = this->x; + y = this->y; } /* Message */ Message::Message() { type = MSG_TYPE_MSG; - - str_len = 0; - got_len = false; } Message::Message(std::string msg) { type = MSG_TYPE_MSG; - str_len = msg.size(); - - std::ostream os(&b); - os.write((const char*)&str_len, sizeof(str_len)); - os.write(msg.c_str(), str_len); - - got_len = true; + this->msg = msg; } -std::size_t Message::payload_size() { - return (got_len ? str_len : sizeof(uint16_t)); +void Message::do_send(boost::asio::ip::tcp::socket& socket) { + write_string(socket, msg); } -uint16_t Message::get_len() { - std::istream is(&b); - is.read((char*)&str_len, sizeof(str_len)); - - got_len = true; - - return str_len; +void Message::recv(boost::asio::ip::tcp::socket& socket) { + msg = read_string(socket); } std::string Message::get_str() { - std::string s; - - char *buf = new char[str_len]; - std::istream is(&b); - is.read(buf, str_len); - - s.assign(buf, str_len); - delete[] buf; - - return s; + return msg; } /* Player */ Player::Player() { type = MSG_TYPE_PLAYER; - - str_len = 0; - got_len = false; } Player::Player(uint32_t id, Vector3 pos, std::string name) { type = MSG_TYPE_PLAYER; - str_len = name.size(); - - std::ostream os(&b); - os.write((const char*)&id, sizeof(id)); - - os.write((const char*)&pos.x, sizeof(pos.x)); - os.write((const char*)&pos.y, sizeof(pos.y)); - os.write((const char*)&pos.z, sizeof(pos.z)); - - os.write((const char*)&str_len, sizeof(str_len)); - os.write(name.c_str(), str_len); + this->id = id; + this->pos = pos; + this->name = name; +} - got_len = true; +void Player::do_send(boost::asio::ip::tcp::socket& socket) { + write(socket, id); + write(socket, pos.x); + write(socket, pos.y); + write(socket, pos.z); + write_string(socket, name); } -std::size_t Player::payload_size() { - return (got_len ? str_len : (sizeof(uint32_t) + sizeof(float)*3 + sizeof(uint16_t))); +void Player::recv(boost::asio::ip::tcp::socket& socket) { + read(socket, id); + read(socket, pos.x); + read(socket, pos.y); + read(socket, pos.z); + name = read_string(socket); } uint32_t Player::get_id() { - std::istream is(&b); - is.read((char*)&id, sizeof(id)); - return id; } -uint16_t Player::get_len() { - std::istream is(&b); - is.read((char*)&str_len, sizeof(str_len)); - - got_len = true; - - return str_len; -} - Vector3 Player::get_pos() { - Vector3 pos; - - std::istream is(&b); - is.read((char*)&pos.x, sizeof(pos.x)); - is.read((char*)&pos.y, sizeof(pos.y)); - is.read((char*)&pos.z, sizeof(pos.z)); - return pos; } -std::string Player::get_str() { - std::string s; - - char *buf = new char[str_len]; - std::istream is(&b); - is.read(buf, str_len); - - s.assign(buf, str_len); - delete[] buf; - - return s; +std::string Player::get_name() { + return name; } diff --git a/messages.h b/messages.h index d521fef..62f5a03 100644 --- a/messages.h +++ b/messages.h @@ -19,46 +19,77 @@ enum MessageType { class MessageBase { protected: uint8_t type; - boost::asio::streambuf b; + + template + static inline void read(boost::asio::ip::tcp::socket& socket, T& v) { + boost::asio::read(socket, boost::asio::buffer(&v, sizeof(T))); + } + static std::string read_string(boost::asio::ip::tcp::socket& socket); + + template + static inline void write(boost::asio::ip::tcp::socket& socket, T& v) { + boost::asio::write(socket, boost::asio::buffer(&v, sizeof(T))); + } + + static void write_string(boost::asio::ip::tcp::socket& socket, std::string str); + + //! Does the actual sending of data per packet type. + virtual void do_send(boost::asio::ip::tcp::socket& socket) = 0; public: MessageBase(); virtual ~MessageBase() {}; + //! Sends the packet type and calls do_send(). void send(boost::asio::ip::tcp::socket& socket); - virtual std::size_t payload_size(); - virtual void read(boost::asio::ip::tcp::socket& socket); + virtual void recv(boost::asio::ip::tcp::socket& socket) = 0; static uint8_t read_type(boost::asio::ip::tcp::socket& socket); }; class Hello : public MessageBase { + protected: + uint8_t version; + + virtual void do_send(boost::asio::ip::tcp::socket& socket); + public: Hello(); Hello(uint8_t version); - virtual std::size_t payload_size(); - uint8_t read_version(); + virtual void recv(boost::asio::ip::tcp::socket& socket); + + uint8_t get_version(); }; class Pos : public MessageBase { + protected: + Vector3 pos; + + virtual void do_send(boost::asio::ip::tcp::socket& socket); + public: Pos(); - Pos(float x, float y, float z); + Pos(Vector3 pos); - virtual std::size_t payload_size(); - void get_pos(float& x, float& y, float& z); + virtual void recv(boost::asio::ip::tcp::socket& socket); + + Vector3 get_pos(); }; class Chunk : public MessageBase { protected: - bool got_coords; + int64_t x, y; + float *data; + + virtual void do_send(boost::asio::ip::tcp::socket& socket); public: Chunk(); Chunk(int64_t x, int64_t y); - virtual std::size_t payload_size(); + virtual void recv(boost::asio::ip::tcp::socket& socket); + void set_data(float *data); float* get_data(); void get_coords(int64_t& x, int64_t& y); @@ -66,14 +97,16 @@ class Chunk : public MessageBase { class Message : public MessageBase { protected: - uint16_t str_len; - bool got_len; + std::string msg; + + virtual void do_send(boost::asio::ip::tcp::socket& socket); public: Message(); Message(std::string msg); - virtual std::size_t payload_size(); + virtual void recv(boost::asio::ip::tcp::socket& socket); + uint16_t get_len(); std::string get_str(); }; @@ -81,18 +114,20 @@ class Message : public MessageBase { class Player : public MessageBase { protected: uint32_t id; - uint16_t str_len; - bool got_len; + Vector3 pos; + std::string name; + + virtual void do_send(boost::asio::ip::tcp::socket& socket); public: Player(); Player(uint32_t id, Vector3 pos, std::string name); - virtual std::size_t payload_size(); + virtual void recv(boost::asio::ip::tcp::socket& socket); + uint32_t get_id(); Vector3 get_pos(); - uint16_t get_len(); - std::string get_str(); + std::string get_name(); }; } -- cgit v1.2.3