diff options
Diffstat (limited to 'common/connectionbase.cpp')
-rw-r--r-- | common/connectionbase.cpp | 77 |
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; } |