summaryrefslogtreecommitdiff
path: root/common/connectionbase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/connectionbase.cpp')
-rw-r--r--common/connectionbase.cpp77
1 files changed, 67 insertions, 10 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;
}