X-Git-Url: http://git.tdb.fi/?p=libs%2Fnet.git;a=blobdiff_plain;f=source%2Fnet%2Fcommunicator.h;h=eb9893d861a2ca8eaa3679aeedcddcd6fde24ea4;hp=af5ff58791ce1ad72a1d97c07591264927bfae64;hb=HEAD;hpb=400f3e031834eee9d96dbd5cda25655102b75805 diff --git a/source/net/communicator.h b/source/net/communicator.h index af5ff58..eb9893d 100644 --- a/source/net/communicator.h +++ b/source/net/communicator.h @@ -1,7 +1,10 @@ #ifndef MSP_NET_COMMUNICATOR_H_ #define MSP_NET_COMMUNICATOR_H_ +#include +#include #include +#include "mspnet_api.h" #include "protocol.h" namespace Msp { @@ -9,54 +12,83 @@ namespace Net { class StreamSocket; -class sequence_error: public std::logic_error +class MSPNET_API sequence_error: public invalid_state { public: - sequence_error(const std::string &w): std::logic_error(w) { } - virtual ~sequence_error() throw() { } + sequence_error(const std::string &w): invalid_state(w) { } +}; + +class MSPNET_API incompatible_protocol: public std::runtime_error +{ +public: + incompatible_protocol(const std::string &w): std::runtime_error(w) { } }; -class Communicator +class MSPNET_API Communicator: public NonCopyable { public: - sigc::signal signal_handshake_done; + sigc::signal signal_protocol_ready; sigc::signal signal_error; private: + struct ActiveProtocol + { + std::uint64_t hash = 0; + std::uint16_t base = 0; + std::uint16_t last = 0; + bool accepted = false; + bool ready = false; + const Protocol *protocol = nullptr; + ReceiverBase *receiver = nullptr; + + ActiveProtocol(std::uint16_t, const Protocol &, ReceiverBase &); + ActiveProtocol(std::uint16_t, std::uint64_t); + }; + + struct Handshake; + StreamSocket &socket; - const Protocol &protocol; - ReceiverBase &receiver; - int handshake_status; - unsigned buf_size; - char *in_buf; - char *in_begin; - char *in_end; - char *out_buf; - bool good; + std::vector protocols; + Handshake *handshake = nullptr; + std::size_t buf_size = 65536; + char *in_buf = nullptr; + char *in_begin = nullptr; + char *in_end = nullptr; + char *out_buf = nullptr; + bool good = true; public: + Communicator(StreamSocket &); Communicator(StreamSocket &, const Protocol &, ReceiverBase &); ~Communicator(); - void initiate_handshake(); - bool is_handshake_done() const { return handshake_status==2; } + void add_protocol(const Protocol &, ReceiverBase &); + bool is_protocol_ready(const Protocol &) const; template void send(const P &); private: - void send_data(unsigned); + void send_data(std::size_t); + void connect_finished(const std::exception *); void data_available(); - bool receive_packet(const Protocol &, ReceiverBase &); - void send_handshake(); + bool receive_packet(); + + void prepare_protocol(const ActiveProtocol &); + void accept_protocol(ActiveProtocol &); }; template void Communicator::send(const P &pkt) { - send_data(protocol.serialize(pkt, out_buf, buf_size)); + auto i = find_if(protocols, [](const ActiveProtocol &p){ return p.protocol && p.protocol->has_packet

(); }); + if(i==protocols.end()) + throw key_error(typeid(P).name()); + else if(!i->ready) + throw sequence_error("protocol not ready"); + send_data(i->protocol->serialize(pkt, out_buf, buf_size, i->base)); } } // namespace Net