summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2010-11-15 04:58:54 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2010-11-15 04:58:54 +0100
commitbe08c29dd5e18c41b5c2f05b7178bab90f04e026 (patch)
tree98ad4c1bb0884df8345fa2f6ef0426b0929f9a54 /common
parentc9b9d15a585df8f01b49510e4ff0dfb53ee7b9ef (diff)
Changed Message-API. Implemented Hello, Login, LoginResponse.
Diffstat (limited to 'common')
-rw-r--r--common/connectionbase.cpp77
-rw-r--r--common/connectionbase.h8
-rw-r--r--common/message.cpp76
-rw-r--r--common/message.h107
-rw-r--r--common/payload.h49
5 files changed, 190 insertions, 127 deletions
diff --git a/common/connectionbase.cpp b/common/connectionbase.cpp
index 23860d2..b399884 100644
--- a/common/connectionbase.cpp
+++ b/common/connectionbase.cpp
@@ -1,35 +1,88 @@
#include "connectionbase.h"
+#include <stdexcept>
+
#include <iostream>
void ConnectionBase::prepare_next_message() {
- next_message = Message::create();
+ //next_message = make_shared<Message::Hello>();
- request_data(next_message->deserialize(0, 0));
+ //request_data(next_message->deserialize(0, 0));
}
void ConnectionBase::connected() {
std::cout << "Connection established." << std::endl;
- prepare_next_message();
+ request_data(4);
}
void ConnectionBase::got_data(uint8_t* data, std::size_t bytes) {
- size_t remaining = next_message->deserialize(data, bytes);
+ if(pending_size == 0) {
+ if(bytes != 4) {
+ throw std::runtime_error("Deserialization header error.");
+ }
+
+ uint16_t* header = (uint16_t*)data;
+
+ pending_type = (Message::Type)header[0];
+ pending_size = (std::size_t)header[1];
+
+ if(pending_size) {
+ request_data(pending_size);
+ return;
+ }
+
+ bytes = 0;
+ }
- if(remaining) {
- request_data(remaining);
- } else {
- recv_queue.push(next_message);
+ if(bytes != pending_size) {
+ std::cout << "Bytes: " << bytes << " Pending size: " << pending_size << std::endl;
+ throw std::runtime_error("Deserialization attempted with incomplete data.");
+ // TODO: Calling got_data() with incomplete data should be allowed.
+ }
+
+ pending_size = 0;
+
+ Message::p m;
+
+ switch(pending_type) {
+ case Message::Types::Hello:
+ m = make_shared<Message::Hello>();
+ break;
+
+ case Message::Types::Login:
+ m = make_shared<Message::Login>();
+ break;
- prepare_next_message();
+ case Message::Types::LoginResponse:
+ m = make_shared<Message::LoginResponse>();
+ break;
+
+ default:
+ throw std::runtime_error("Deserialization attempted on unknown message type.");
+ }
+
+ if(bytes) {
+ m->deserialize(data, bytes);
}
+
+ recv_queue.push(m);
+
+ request_data(4);
}
void ConnectionBase::send(const Message::p& msg) {
+ uint16_t* header = new uint16_t[2];
+
std::pair<uint8_t*, std::size_t> smsg = msg->serialize();
- write_data(smsg.first, smsg.second);
+ header[0] = uint16_t(msg->type);
+ header[1] = uint16_t(smsg.second);
+
+ write_data((uint8_t*)header, 4);
+ if(smsg.second) {
+ write_data(smsg.first, smsg.second);
+ }
}
Message::p ConnectionBase::recv() {
@@ -43,6 +96,10 @@ Message::p ConnectionBase::recv() {
return msg;
}
+ConnectionBase::ConnectionBase() {
+ pending_size = 0;
+}
+
ConnectionBase::~ConnectionBase() {
std::cout << "Connection destroyed." << std::endl;
}
diff --git a/common/connectionbase.h b/common/connectionbase.h
index 13721dc..78e3fe4 100644
--- a/common/connectionbase.h
+++ b/common/connectionbase.h
@@ -11,7 +11,8 @@ class ConnectionBase {
private:
std::queue<Message::p> recv_queue;
- Message::p next_message;
+ Message::Type pending_type;
+ std::size_t pending_size;
//! Create a new message and initiate reception.
void prepare_next_message();
@@ -35,13 +36,14 @@ class ConnectionBase {
virtual void write_data(uint8_t* data, std::size_t bytes) = 0;
public:
+ ConnectionBase();
+ virtual ~ConnectionBase();
+
//! Send a message.
void send(const Message::p& msg);
//! Get received message or null if queue empty.
Message::p recv();
-
- virtual ~ConnectionBase();
};
#endif
diff --git a/common/message.cpp b/common/message.cpp
index ddfaaa7..6e1901d 100644
--- a/common/message.cpp
+++ b/common/message.cpp
@@ -5,54 +5,64 @@
#include <iostream>
-std::pair<uint8_t*, std::size_t> Message::serialize() {
- //std::size_t s = payload.size();
+Message::Hello::Hello() : Base(Types::Hello) {
- //uint8_t* buf = new uint8_t[4 + s];
+}
+
+Message::Hello::Hello(const std::string& v) : Base(Types::Hello), version(v) {
- //*(uint16_t*)buf = (uint16_t)s;
+}
+
+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 + 4, payload.c_str(), payload.size());
+ memcpy(buf, version.c_str(), version.size());
- //return std::pair<uint8_t*, std::size_t>(buf, 4 + s);
- return std::pair<uint8_t*, std::size_t>(0, 0);
+ return std::pair<uint8_t*, std::size_t>(buf, s);
}
-std::size_t Message::deserialize(uint8_t* data, std::size_t bytes) {
- if(deserialize_size == 0 && bytes == 0) {
- return 4;
- }
-
- if(deserialize_size == 0 && bytes == 4) {
- uint16_t* header = (uint16_t*)data;
-
- deserialize_size = (std::size_t)header[0];
- payload_type = (Payload::Type)header[1];
-
- return deserialize_size;
- }
+void Message::Hello::deserialize(uint8_t* data, std::size_t bytes) {
+ version = std::string((char*)data, bytes);
+}
+
+Message::Login::Login() : Base(Types::Login) {
- if(!deserialize_size) {
- throw std::runtime_error("Deserialization header error.");
- }
+}
+
+Message::Login::Login(const std::string& n) : Base(Types::Login), nick(n) {
- if(bytes != deserialize_size) {
- throw std::runtime_error("Deserialization attempted with incomplete data.");
- }
+}
+
+std::pair<uint8_t*, std::size_t> Message::Login::serialize() {
+ std::size_t s = nick.size();
+ uint8_t* buf = new uint8_t[s];
- //payload = std::string((char*)data, bytes);
+ memcpy(buf, nick.c_str(), nick.size());
- return 0;
+ return std::pair<uint8_t*, std::size_t>(buf, s);
}
-Message::Message() : deserialize_size(0) {
+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) {
}
-Message::p Message::create() {
- return Message::p(new Message);
+std::pair<uint8_t*, std::size_t> Message::LoginResponse::serialize() {
+ uint8_t* buf = new uint8_t[1];
+
+ buf[1] = uint8_t(login_ok);
+
+ return std::pair<uint8_t*, std::size_t>(buf, 1);
}
-Payload::Type Message::type() {
- return payload_type;
+void Message::LoginResponse::deserialize(uint8_t* data, std::size_t bytes) {
+ login_ok = bool(data[0]);
}
diff --git a/common/message.h b/common/message.h
index 44343ae..56096ed 100644
--- a/common/message.h
+++ b/common/message.h
@@ -1,43 +1,86 @@
#ifndef MESSAGE_H
#define MESSAGE_H
-#include "payload.h"
-
#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
+using boost::make_shared;
+using boost::dynamic_pointer_cast;
#include <stdint.h>
#include <string>
-class Message {
- private:
- Message();
-
- std::size_t deserialize_size;
-
- friend class ConnectionBase;
-
- //! Serialize message.
- std::pair<uint8_t*, std::size_t> serialize();
-
- //! Deserialize message.
- std::size_t deserialize(uint8_t* data, std::size_t bytes);
-
- Payload::Type payload_type;
- Payload::Base* payload_data;
-
- public:
- typedef boost::shared_ptr<Message> p;
-
- static p create();
-
- //! Return payload type.
- Payload::Type type();
-
- //! Return reference to payload.
- template <class T>
- T& payload() {
- return dynamic_cast<T&>(*payload_data);
- }
+namespace Message {
+ namespace Types {
+ //! Message types.
+ enum Type {
+ Undefined,
+ Hello,
+ Login,
+ LoginResponse,
+ LobbyStatus,
+ LobbyAction,
+ GameStart,
+ Ready,
+ RoundStart,
+ RoundState,
+ RoundAction,
+ RoundEnd,
+ GameEnd
+ };
+ }
+ using Types::Type;
+
+ class Base {
+ protected:
+ Base(Type t) : type(t) {}
+
+ 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 Hello : public Base {
+ public:
+ typedef boost::shared_ptr<Hello> p;
+
+ Hello();
+ Hello(const std::string& v);
+
+ std::string version;
+
+ virtual std::pair<uint8_t*, std::size_t> serialize();
+ virtual void deserialize(uint8_t* data, std::size_t bytes);
+ };
+
+ class Login : public Base {
+ public:
+ typedef boost::shared_ptr<Login> p;
+
+ Login();
+ Login(const std::string& n);
+
+ std::string nick;
+
+ virtual std::pair<uint8_t*, std::size_t> serialize();
+ virtual void deserialize(uint8_t* data, std::size_t bytes);
+ };
+
+ class LoginResponse : public Base {
+ public:
+ typedef boost::shared_ptr<LoginResponse> p;
+
+ LoginResponse();
+ LoginResponse(bool ok);
+
+ bool login_ok;
+
+ virtual std::pair<uint8_t*, std::size_t> serialize();
+ virtual void deserialize(uint8_t* data, std::size_t bytes);
+ };
+
+ typedef boost::shared_ptr<Base> p;
};
#endif
diff --git a/common/payload.h b/common/payload.h
deleted file mode 100644
index fbdcd1d..0000000
--- a/common/payload.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef PAYLOAD_H
-#define PAYLOAD_H
-
-#include <utility>
-#include <stdint.h>
-
-namespace Payload {
- namespace Types {
- //! Payload types.
- enum Type {
- Undefined,
- Hello,
- Login,
- LoginResponse,
- LobbyStatus,
- LobbyAction,
- GameStart,
- Ready,
- RoundStart,
- RoundState,
- RoundAction,
- RoundEnd,
- GameEnd
- };
- }
- using Types::Type;
-
- class Base {
- protected:
- friend class Message;
-
- virtual std::pair<uint8_t*, std::size_t> serialize() = 0;
-
- Base(Type t) : type(t) {}
-
- public:
- const Type type;
- };
-
- class Hello : public Base {
- protected:
- virtual std::pair<uint8_t*, std::size_t> serialize();
-
- public:
- Hello() : Base(Types::Hello) {}
- };
-};
-
-#endif