2 #include "communicator.h"
3 #include "protocol_impl.h"
4 #include "streamsocket.h"
10 using namespace Msp::Net;
18 class HandshakeProtocol: public Protocol
24 HandshakeProtocol::HandshakeProtocol():
27 add<Handshake>()(&Handshake::hash);
31 class HandshakeReceiver: public PacketReceiver<Handshake>
38 Msp::UInt64 get_hash() const { return hash; }
39 virtual void receive(const Handshake &);
42 HandshakeReceiver::HandshakeReceiver():
46 void HandshakeReceiver::receive(const Handshake &shake)
57 Communicator::Communicator(StreamSocket &s, const Protocol &p, ReceiverBase &r):
63 in_buf(new char[buf_size]),
66 out_buf(new char[buf_size]),
69 socket.signal_data_available.connect(sigc::mem_fun(this, &Communicator::data_available));
72 Communicator::~Communicator()
78 void Communicator::initiate_handshake()
80 if(handshake_status!=0)
81 throw sequence_error("handshaking already done");
87 void Communicator::send_data(unsigned size)
90 throw sequence_error("connection aborted");
91 if(handshake_status!=2)
92 throw sequence_error("handshake incomplete");
96 socket.write(out_buf, size);
98 catch(const std::exception &e)
101 if(signal_error.empty())
103 signal_error.emit(e);
107 void Communicator::data_available()
114 in_end += socket.read(in_end, in_buf+buf_size-in_end);
119 if(handshake_status==2)
120 more = receive_packet(protocol, receiver);
123 HandshakeProtocol hsproto;
124 HandshakeReceiver hsrecv;
125 if((more = receive_packet(hsproto, hsrecv)))
127 if(handshake_status==0)
130 if(hsrecv.get_hash()==protocol.get_hash())
132 handshake_status = 2;
133 signal_handshake_done.emit();
136 throw incompatible_protocol("hash mismatch");
141 catch(const exception &e)
144 if(signal_error.empty())
146 signal_error.emit(e);
150 bool Communicator::receive_packet(const Protocol &proto, ReceiverBase &recv)
152 int psz = proto.get_packet_size(in_begin, in_end-in_begin);
153 if(psz && psz<=in_end-in_begin)
155 char *pkt = in_begin;
157 proto.dispatch(recv, pkt, psz);
162 if(in_end==in_buf+buf_size)
164 unsigned used = in_end-in_begin;
165 memmove(in_buf, in_begin, used);
167 in_end = in_begin+used;
173 void Communicator::send_handshake()
176 shake.hash = protocol.get_hash();
178 HandshakeProtocol hsproto;
179 unsigned size = hsproto.serialize(shake, out_buf, buf_size);
180 socket.write(out_buf, size);