]> git.tdb.fi Git - libs/net.git/blobdiff - source/net/communicator.h
Redesign Communicator to support multiple protocols
[libs/net.git] / source / net / communicator.h
index e9f646a59a62ba1f0796a36cf57f2d27454d849d..eb9893d861a2ca8eaa3679aeedcddcd6fde24ea4 100644 (file)
@@ -28,14 +28,29 @@ public:
 class MSPNET_API Communicator: public NonCopyable
 {
 public:
-       sigc::signal<void> signal_handshake_done;
+       sigc::signal<void, const Protocol &> signal_protocol_ready;
        sigc::signal<void, const std::exception &> 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 = 0;
+       std::vector<ActiveProtocol> protocols;
+       Handshake *handshake = nullptr;
        std::size_t buf_size = 65536;
        char *in_buf = nullptr;
        char *in_begin = nullptr;
@@ -44,11 +59,12 @@ private:
        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<typename P>
        void send(const P &);
@@ -56,15 +72,23 @@ public:
 private:
        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<typename P>
 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<P>(); });
+       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