#pragma once #include #include #include #include #include #include #include #include #include "IpAddress.hpp" #include "../types.hpp" #include "../utils.hpp" #include "Socket.hpp" #include "Message.hpp" #include namespace sibs { class SocketCreateException : public std::runtime_error { public: SocketCreateException(const std::string &errMsg) : std::runtime_error(errMsg) {} }; enum class PubSubResult { RESULT_OK, RESULT_ERROR }; struct DirectConnectionPeer; struct PubSubConnectResult { std::shared_ptr peer; PubSubResult result; std::string resultStr; }; using PubSubConnectCallback = std::function peer, PubSubResult result, const std::string &resultStr)>; using PubSubReceiveDataCallback = std::function peer, MessageType messageType, const void *data, const usize size)>; using PubSubSendDataCallback = std::function; using PubSubOnRemoveDisconnectedPeerCallback = std::function peer)>; enum class PeerType { SERVER, CLIENT }; struct DirectConnectionPeer { std::unique_ptr socket; Ipv4 address; PubSubReceiveDataCallback receiveDataCallbackFunc; int sharedKeys = 0; PeerType type = PeerType::CLIENT; bool routed = false; bool operator == (const DirectConnectionPeer &other) const; bool operator != (const DirectConnectionPeer &other) const; }; class DirectConnections { DISABLE_COPY(DirectConnections) friend class BootstrapNode; public: DirectConnections(u16 port = 0); ~DirectConnections(); // Throws ConnectionException on error void connectServer(const Ipv4 &address, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc); // Throws ConnectionException on error void connect(const Ipv4 &address, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc); // Returns false if data is larger than 800kb bool send(const std::shared_ptr peer, std::shared_ptr data, PubSubSendDataCallback sendDataCallbackFunc = nullptr); void onRemoveDisconnectedPeer(PubSubOnRemoveDisconnectedPeerCallback callbackFunc); bool removePeer(int peerSocket); std::vector> getPeers(); protected: std::unique_ptr createSocket(const Ipv4 &addressToBind, bool rendezvous, bool reuseAddr, bool bind = true); private: void connect(const Ipv4 &address, bool rendezvous, bool reuseAddr, PubSubConnectCallback connectCallbackFunc, PubSubReceiveDataCallback receiveDataCallbackFunc, bool bind, bool server); void removeDisconnectedPeers(); void receiveData(); int receiveDataFromPeer(const int socket, char *output, usize *receivedTotalSize); private: u16 port; int eid; std::unordered_map> peers; std::thread receiveDataThread; std::mutex peersMutex; bool alive; PubSubOnRemoveDisconnectedPeerCallback removeDisconnectedPeerCallback; Ipv4Map> connectionResults; std::mutex connectionResultsMutex; }; struct DirectConnectionsUtils { static std::vector serializePeers(const std::vector> &peers); // Throws DeserializeException on error static std::vector> deserializePeers(const u8 *data, const usize size); }; }