X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fnet%2Fcommunicator.cpp;h=51202b5f659c07b733e5e93dbb3750142b4b884e;hb=cc2e643d6ec3025db3fb6f0a4c1f77af05cf1026;hp=c9b277d3748de137381b0df792d5230b0e8e0c62;hpb=50e9f9ea7f7385a2c5931fca2b8fb1103078e67c;p=libs%2Fnet.git diff --git a/source/net/communicator.cpp b/source/net/communicator.cpp index c9b277d..51202b5 100644 --- a/source/net/communicator.cpp +++ b/source/net/communicator.cpp @@ -1,5 +1,8 @@ -#include #include "communicator.h" +#include +#include "streamsocket.h" + +using namespace std; namespace { @@ -7,7 +10,7 @@ using namespace Msp::Net; struct Handshake { - unsigned hash; + uint64_t hash; }; @@ -20,25 +23,20 @@ public: HandshakeProtocol::HandshakeProtocol(): Protocol(0x7F00) { - add()(&Handshake::hash); + add(&Handshake::hash); } class HandshakeReceiver: public PacketReceiver { private: - unsigned hash; + uint64_t hash = 0; public: - HandshakeReceiver(); - unsigned get_hash() const { return hash; } - virtual void receive(const Handshake &); + uint64_t get_hash() const { return hash; } + void receive(const Handshake &) override; }; -HandshakeReceiver::HandshakeReceiver(): - hash(0) -{ } - void HandshakeReceiver::receive(const Handshake &shake) { hash = shake.hash; @@ -54,13 +52,10 @@ Communicator::Communicator(StreamSocket &s, const Protocol &p, ReceiverBase &r): socket(s), protocol(p), receiver(r), - handshake_status(0), - buf_size(1024), in_buf(new char[buf_size]), in_begin(in_buf), in_end(in_buf), - out_buf(new char[buf_size]), - good(true) + out_buf(new char[buf_size]) { socket.signal_data_available.connect(sigc::mem_fun(this, &Communicator::data_available)); } @@ -80,44 +75,66 @@ void Communicator::initiate_handshake() handshake_status = 1; } +void Communicator::send_data(size_t size) +{ + if(!good) + throw sequence_error("connection aborted"); + if(handshake_status!=2) + throw sequence_error("handshake incomplete"); + + try + { + socket.write(out_buf, size); + } + catch(const std::exception &e) + { + good = false; + if(signal_error.empty()) + throw; + signal_error.emit(e); + } +} + void Communicator::data_available() { if(!good) return; - in_end += socket.read(in_end, in_buf+buf_size-in_end); try { + in_end += socket.read(in_end, in_buf+buf_size-in_end); + bool more = true; while(more) { if(handshake_status==2) - { more = receive_packet(protocol, receiver); - } else { HandshakeProtocol hsproto; HandshakeReceiver hsrecv; if((more = receive_packet(hsproto, hsrecv))) { + if(handshake_status==0) + send_handshake(); + if(hsrecv.get_hash()==protocol.get_hash()) { - if(handshake_status==0) - send_handshake(); handshake_status = 2; signal_handshake_done.emit(); } else - good = false; + throw incompatible_protocol("hash mismatch"); } } } } - catch(...) + catch(const exception &e) { good = false; - throw; + if(signal_error.empty()) + throw; + signal_error.emit(e); } } @@ -128,14 +145,14 @@ bool Communicator::receive_packet(const Protocol &proto, ReceiverBase &recv) { char *pkt = in_begin; in_begin += psz; - proto.disassemble(recv, pkt, psz); + proto.dispatch(recv, pkt, psz); return true; } else { if(in_end==in_buf+buf_size) { - unsigned used = in_end-in_begin; + size_t used = in_end-in_begin; memmove(in_buf, in_begin, used); in_begin = in_buf; in_end = in_begin+used; @@ -150,7 +167,7 @@ void Communicator::send_handshake() shake.hash = protocol.get_hash(); HandshakeProtocol hsproto; - unsigned size = hsproto.assemble(shake, out_buf, buf_size); + size_t size = hsproto.serialize(shake, out_buf, buf_size); socket.write(out_buf, size); }