terom@185: #ifndef NETWORK_SESSION_HH terom@185: #define NETWORK_SESSION_HH terom@185: terom@185: #include terom@185: #include terom@185: terom@185: // forward-declare terom@185: class NetworkSession; terom@185: terom@286: /** terom@286: * A NetworkSession puts each packet onto a specific channel, which can the be used to run multiple different modules terom@286: * on top of a single session. terom@286: * terom@286: * NetworkChannelID zero is reserved for internal NetworkSession use terom@185: */ terom@185: typedef uint16_t NetworkChannelID; terom@185: terom@286: /** terom@286: * Size of a NetworkSession's packet header: terom@286: * uint16 channel_id terom@203: */ terom@203: const size_t NETWORK_SESSION_HEADER_SIZE = sizeof(uint16_t); terom@203: terom@186: #include "TCP.hh" terom@186: #include "UDP.hh" terom@186: #include "Node.hh" terom@185: terom@286: /** terom@286: * A NetworkSession provides TCP/UDP Server and Client functionality, representing remote NetworkSessions with terom@286: * NetworkNodes. A NetworkSession can then communicate with its NetworkNodes using TCP or UDP NetworkPackets. terom@286: */ terom@185: class NetworkSession { terom@185: friend class NetworkNode; terom@185: terom@185: private: terom@286: /** terom@286: * The application's magic ID terom@286: */ terom@185: uint64_t magic; terom@286: terom@286: /** terom@286: * Our TCP server, if we're in listen() mode terom@286: */ terom@185: NetworkTCPServer *tcp_srv; terom@185: terom@286: /** terom@286: * Our UDP server, if we're in listen() mode terom@286: */ terom@286: NetworkUDP *udp_srv; terom@286: terom@286: /** terom@286: * Our UDP client, if we're in connect() mode terom@286: */ terom@286: NetworkUDP *udp_client; terom@286: terom@185: CL_SlotContainer slots; terom@286: terom@286: /** terom@286: * A map of NetworkAddress -> NetworkNode, manipulated when TCP connections are established/broken down, terom@286: * and used to map UDP packets to their NetworkNode terom@286: */ terom@286: std::map nodes; terom@185: terom@286: /** terom@286: * A map of NetworkChannelID -> signal, used to signal our users when we receieve packets terom@286: */ terom@200: std::map > _map_sig_chan_message; terom@185: terom@185: public: terom@286: /** terom@286: * Construct an idle NetworkSession using the given application magic, which should be unique to tell different terom@286: * applications apart from each other. terom@286: * terom@286: * @param magic unique application magic terom@286: */ terom@185: NetworkSession (uint64_t magic); terom@286: terom@286: /** terom@286: * Have the NetworkSession enter server mode, listening on the given address using both TCP and UDP terom@286: * terom@286: * @param addr local address to listen on terom@286: */ terom@286: void listen (const NetworkAddress &addr); terom@185: terom@286: /** terom@286: * Have the NetworkSession enter client mode, establishing a TCP connection to the server, and then allocating terom@286: * an UDP socket on the same local address as the TCP connection. terom@286: * terom@286: * @param addr remote address to connect to terom@286: */ terom@185: NetworkNode* connect (const NetworkAddress &addr); terom@185: terom@185: protected: terom@286: /** terom@286: * Used to build a new NetworkNode by connect/on_tcp_client. Can be used to override what kind of NetworkNodes terom@286: * get created. Type tells what kind of node this is. terom@286: * terom@286: * @param tcp the TCP transport for this node terom@286: * @param udp the UDP socket to use for this node terom@286: * @param addr the remote address terom@286: * @param type the type of node terom@286: * @see NetworkNodeType terom@286: */ terom@185: virtual NetworkNode *build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type); terom@185: terom@286: /** terom@286: * A NetworkNode's TCP connection has failed. Removes the node from our nodes-map (using node->getRemoteAddress) terom@286: * terom@286: * @param node the node that has disconnected terom@286: */ terom@185: void handle_disconnect (NetworkNode *node); terom@286: terom@286: /** terom@286: * We have received a NetworkPacket from the given node (either TCP or UDP, we don't know) terom@286: * terom@286: * @param pkt the NetworkPacket that we received terom@286: * @param node the node that sent it terom@286: */ terom@200: void handle_message (NetworkPacketInput &pkt, NetworkNode *node); terom@185: terom@185: private: terom@286: /** terom@286: * Our tcp_srv has accept()'d a new client. terom@286: * terom@286: * Create a NetworkNode using build_node and udp_srv, add it to our node-map, and trigger sig_node_connected terom@286: */ terom@185: void on_tcp_client (NetworkTCPTransport *client); terom@286: terom@286: /** terom@286: * Our udp_srv has recv()'d a NetworkPacket. terom@286: * terom@286: * Map it to a NetworkNode using our node-map and call handle_message terom@286: */ terom@200: void on_udp_packet (NetworkPacketInput &pkt, const NetworkAddress &addr); terom@286: terom@286: /** terom@286: * New-client signal terom@286: */ terom@185: CL_Signal_v1 _sig_node_connected; terom@185: terom@185: public: terom@286: /** terom@286: * Send the given NetworkPacket to all our nodes using the given NetworkChannelID, using TCP if reliable, UDP otherwise. terom@286: * terom@286: * @param channel_id the NetworkChannelID to use terom@286: * @param pkt the NetworkPacket to send terom@286: * @param reliable Whether to use TCP or UDP terom@286: */ terom@200: void send_all (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable = true); terom@286: terom@286: /** terom@286: * Like send_all, but do not send the packet to the specified node. If node is NULL, this behaves like terom@286: * send_all. terom@286: * terom@286: * @see send_all terom@286: */ terom@200: void send_all_except (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, const NetworkNode *node, bool reliable = true); terom@185: terom@286: /** terom@286: * A new node has connected to us terom@286: */ terom@286: CL_Signal_v1& sig_node_connected (void) { return _sig_node_connected; } terom@202: terom@286: /** terom@286: * We have received a NetworkPacket from a NetworkNode on the given NetworkChannelID terom@286: */ terom@200: CL_Signal_v2& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; } terom@185: }; terom@185: terom@185: #endif /* NETWORK_SESSION_HH */