2 #include "communicator.h"
3 #include "streamsocket.h"
9 using namespace Msp::Net;
17 class HandshakeProtocol: public Protocol
23 HandshakeProtocol::HandshakeProtocol():
26 add<Handshake>()(&Handshake::hash);
30 class HandshakeReceiver: public PacketReceiver<Handshake>
37 uint64_t get_hash() const { return hash; }
38 virtual void receive(const Handshake &);
41 HandshakeReceiver::HandshakeReceiver():
45 void HandshakeReceiver::receive(const Handshake &shake)
56 Communicator::Communicator(StreamSocket &s, const Protocol &p, ReceiverBase &r):
62 in_buf(new char[buf_size]),
65 out_buf(new char[buf_size]),
68 socket.signal_data_available.connect(sigc::mem_fun(this, &Communicator::data_available));
71 Communicator::~Communicator()
77 void Communicator::initiate_handshake()
79 if(handshake_status!=0)
80 throw sequence_error("handshaking already done");
86 void Communicator::send_data(size_t size)
89 throw sequence_error("connection aborted");
90 if(handshake_status!=2)
91 throw sequence_error("handshake incomplete");
95 socket.write(out_buf, size);
97 catch(const std::exception &e)
100 if(signal_error.empty())
102 signal_error.emit(e);
106 void Communicator::data_available()
113 in_end += socket.read(in_end, in_buf+buf_size-in_end);
118 if(handshake_status==2)
119 more = receive_packet(protocol, receiver);
122 HandshakeProtocol hsproto;
123 HandshakeReceiver hsrecv;
124 if((more = receive_packet(hsproto, hsrecv)))
126 if(handshake_status==0)
129 if(hsrecv.get_hash()==protocol.get_hash())
131 handshake_status = 2;
132 signal_handshake_done.emit();
135 throw incompatible_protocol("hash mismatch");
140 catch(const exception &e)
143 if(signal_error.empty())
145 signal_error.emit(e);
149 bool Communicator::receive_packet(const Protocol &proto, ReceiverBase &recv)
151 int psz = proto.get_packet_size(in_begin, in_end-in_begin);
152 if(psz && psz<=in_end-in_begin)
154 char *pkt = in_begin;
156 proto.dispatch(recv, pkt, psz);
161 if(in_end==in_buf+buf_size)
163 size_t used = in_end-in_begin;
164 memmove(in_buf, in_begin, used);
166 in_end = in_begin+used;
172 void Communicator::send_handshake()
175 shake.hash = protocol.get_hash();
177 HandshakeProtocol hsproto;
178 size_t size = hsproto.serialize(shake, out_buf, buf_size);
179 socket.write(out_buf, size);