#pragma once #include #include #include #include #include #include #include #include namespace erebos { using std::mutex; using std::optional; using std::unique_ptr; using std::variant; using std::vector; class NetworkProtocol { public: NetworkProtocol(); explicit NetworkProtocol(int sock); NetworkProtocol(const NetworkProtocol &) = delete; NetworkProtocol(NetworkProtocol &&); NetworkProtocol & operator=(const NetworkProtocol &) = delete; NetworkProtocol & operator=(NetworkProtocol &&); ~NetworkProtocol(); class Connection; struct Header; struct NewConnection; struct ConnectionReadReady; struct ProtocolClosed {}; using PollResult = variant< NewConnection, ConnectionReadReady, ProtocolClosed>; PollResult poll(); Connection connect(sockaddr_in6 addr); bool recvfrom(vector & buffer, sockaddr_in6 & addr); void sendto(const vector & buffer, sockaddr_in addr); void sendto(const vector & buffer, sockaddr_in6 addr); void shutdown(); private: int sock; mutex protocolMutex; vector buffer; struct ConnectionPriv; vector connections; }; class NetworkProtocol::Connection { friend class NetworkProtocol; Connection(unique_ptr p); public: Connection(const Connection &) = delete; Connection(Connection &&); Connection & operator=(const Connection &) = delete; Connection & operator=(Connection &&); ~Connection(); using Id = uintptr_t; Id id() const; const sockaddr_in6 & peerAddress() const; bool receive(vector & buffer); bool send(const vector & buffer); void close(); private: unique_ptr p; }; struct NetworkProtocol::NewConnection { Connection conn; }; struct NetworkProtocol::ConnectionReadReady { Connection::Id id; }; struct NetworkProtocol::Header { enum class Type { Acknowledged, DataRequest, DataResponse, AnnounceSelf, AnnounceUpdate, ChannelRequest, ChannelAccept, ServiceType, ServiceRef, }; struct Item { const Type type; const variant value; bool operator==(const Item &) const; bool operator!=(const Item & other) const { return !(*this == other); } }; Header(const vector & items): items(items) {} static optional
load(const PartialRef &); static optional
load(const PartialObject &); PartialObject toObject() const; const vector items; }; }