# HG changeset patch # User terom # Date 1228750908 0 # Node ID 2a8f20a53ff2d23e31fbf2d17e025a0d463c5c53 # Parent c080c8c703333226011a621dcb7aee4f32e3a20b more network documentation diff -r c080c8c70333 -r 2a8f20a53ff2 src/Network/Node.hh --- a/src/Network/Node.hh Mon Dec 08 15:37:34 2008 +0000 +++ b/src/Network/Node.hh Mon Dec 08 15:41:48 2008 +0000 @@ -4,44 +4,125 @@ // forward-declare class NetworkNode; +/** + * Used to differentiate between different kinds of nodes in NetworkSession::build_node + * + * @see NetworkSession::build_node + */ enum NetworkNodeType { - NETWORK_NODE_SERVER_CLIENT, - NETWORK_NODE_CLIENT_SERVER + NETWORK_NODE_SERVER_CLIENT, //<<< A server's client + NETWORK_NODE_CLIENT_SERVER //<<< A client's server }; #include "TCP.hh" #include "UDP.hh" #include "Session.hh" +/** + * A NetworkNode represents a remote NetworkSession connected to our NetworkSession. + * + * A NetworkNode has a tcp connection, plus an udp socket to us (either NetworkSession's udp_srv or udp_client) + */ class NetworkNode { private: + /** + * Our local NetworkSession + */ NetworkSession &session; + + /** + * The TCP connection + */ NetworkTCPTransport *tcp; + + /** + * Our NetworkSession's UDP socket that we should use to send UDP packets to this node + */ NetworkUDP *udp; + + /** + * This address that the node connected from using TCP, used to associate received UDP packets with this node + */ const NetworkAddress address; CL_SlotContainer slots; public: + /** + * Construct a new NetworkNode from the given tcp/udp sockets and address + * + * @param session our NetworkSession + * @param tcp this node's TCP socket + * @param udp the UDP socket to use for outgoing packets + * @param address the remote address + */ NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &address); private: + /** + * Node should not be copied + */ NetworkNode (const NetworkNode ©); ~NetworkNode (void); NetworkNode& operator= (const NetworkNode ©); + /** + * Our TCP socket indicates disconnect, tell NetworkSession and trigger sig_disconnect + */ void on_disconnect (void); + /** + * Our disconnect signal + */ CL_Signal_v0 _sig_disconnected; public: + /** + * Write to appropriate NetworkSession header to the given packet. Can be used to prepare packets for use with + * send_raw. The size of the header is equal to NETWORK_SESSION_HEADER_SIZE + * + * @param pkt the packet to write the header to + * @param channel_id the NetworkChannelID to use + * + * @see send_raw + * @see NETWORK_SESSION_HEADER_SIZE + */ void write_packet_header (NetworkPacketOutput &pkt, NetworkChannelID channel_id); + + /** + * Send a raw packet prepared using write_packet_header. This does not need to copy the packet data around. + * + * @param pkt the NetworkPacket prepared using write_packet_header + * @param reliable Whether to use TCP or UDP + * + * @see write_packet_header + */ + void send_raw (const NetworkPacketBuffer &pkt, bool reliable = true); - void send_raw (const NetworkPacketBuffer &pkt, bool reliable = true); + /** + * Send the given packet to this node on the given channel. + * + * Note that this constructs a new *NetworkPacket* containing our header and the given packet, so there + * given packet must be small enough to fit. + * + * @param channel_id the NetworkChannelID to use + * @param pkt the NetworkPacket to send on the given channel + * @param reliable Whether to use TCP or UDP + */ void send (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable = true); - + + /** + * Get this node's remote address (both TCP and UDP). + * + * @return NetworkAddress the remote address + */ const NetworkAddress& getRemoteAddress (void); + /** + * This node's TCP connection was lost, and the node has been removed from the NetworkSession's nodes list. + * + * Once this completes, the node will be destructed + */ CL_Signal_v0& sig_disconnected (void) { return _sig_disconnected; } }; diff -r c080c8c70333 -r 2a8f20a53ff2 src/Network/Session.hh --- a/src/Network/Session.hh Mon Dec 08 15:37:34 2008 +0000 +++ b/src/Network/Session.hh Mon Dec 08 15:41:48 2008 +0000 @@ -7,13 +7,17 @@ // forward-declare class NetworkSession; -/* - * Used to separate packets, ID zero is reserved for NetworkSession use +/** + * A NetworkSession puts each packet onto a specific channel, which can the be used to run multiple different modules + * on top of a single session. + * + * NetworkChannelID zero is reserved for internal NetworkSession use */ typedef uint16_t NetworkChannelID; -/* - * Size of a packet header +/** + * Size of a NetworkSession's packet header: + * uint16 channel_id */ const size_t NETWORK_SESSION_HEADER_SIZE = sizeof(uint16_t); @@ -21,43 +25,145 @@ #include "UDP.hh" #include "Node.hh" +/** + * A NetworkSession provides TCP/UDP Server and Client functionality, representing remote NetworkSessions with + * NetworkNodes. A NetworkSession can then communicate with its NetworkNodes using TCP or UDP NetworkPackets. + */ class NetworkSession { friend class NetworkNode; private: + /** + * The application's magic ID + */ uint64_t magic; + + /** + * Our TCP server, if we're in listen() mode + */ NetworkTCPServer *tcp_srv; - NetworkUDP *udp_srv, *udp_client; + /** + * Our UDP server, if we're in listen() mode + */ + NetworkUDP *udp_srv; + + /** + * Our UDP client, if we're in connect() mode + */ + NetworkUDP *udp_client; + CL_SlotContainer slots; + + /** + * A map of NetworkAddress -> NetworkNode, manipulated when TCP connections are established/broken down, + * and used to map UDP packets to their NetworkNode + */ + std::map nodes; - std::map nodes; + /** + * A map of NetworkChannelID -> signal, used to signal our users when we receieve packets + */ std::map > _map_sig_chan_message; public: + /** + * Construct an idle NetworkSession using the given application magic, which should be unique to tell different + * applications apart from each other. + * + * @param magic unique application magic + */ NetworkSession (uint64_t magic); + + /** + * Have the NetworkSession enter server mode, listening on the given address using both TCP and UDP + * + * @param addr local address to listen on + */ + void listen (const NetworkAddress &addr); - void listen (const NetworkAddress &addr); + /** + * Have the NetworkSession enter client mode, establishing a TCP connection to the server, and then allocating + * an UDP socket on the same local address as the TCP connection. + * + * @param addr remote address to connect to + */ NetworkNode* connect (const NetworkAddress &addr); protected: + /** + * Used to build a new NetworkNode by connect/on_tcp_client. Can be used to override what kind of NetworkNodes + * get created. Type tells what kind of node this is. + * + * @param tcp the TCP transport for this node + * @param udp the UDP socket to use for this node + * @param addr the remote address + * @param type the type of node + * @see NetworkNodeType + */ virtual NetworkNode *build_node (NetworkTCPTransport *tcp, NetworkUDP *udp, const NetworkAddress &addr, enum NetworkNodeType type); + /** + * A NetworkNode's TCP connection has failed. Removes the node from our nodes-map (using node->getRemoteAddress) + * + * @param node the node that has disconnected + */ void handle_disconnect (NetworkNode *node); + + /** + * We have received a NetworkPacket from the given node (either TCP or UDP, we don't know) + * + * @param pkt the NetworkPacket that we received + * @param node the node that sent it + */ void handle_message (NetworkPacketInput &pkt, NetworkNode *node); private: + /** + * Our tcp_srv has accept()'d a new client. + * + * Create a NetworkNode using build_node and udp_srv, add it to our node-map, and trigger sig_node_connected + */ void on_tcp_client (NetworkTCPTransport *client); + + /** + * Our udp_srv has recv()'d a NetworkPacket. + * + * Map it to a NetworkNode using our node-map and call handle_message + */ void on_udp_packet (NetworkPacketInput &pkt, const NetworkAddress &addr); - + + /** + * New-client signal + */ CL_Signal_v1 _sig_node_connected; public: + /** + * Send the given NetworkPacket to all our nodes using the given NetworkChannelID, using TCP if reliable, UDP otherwise. + * + * @param channel_id the NetworkChannelID to use + * @param pkt the NetworkPacket to send + * @param reliable Whether to use TCP or UDP + */ void send_all (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, bool reliable = true); + + /** + * Like send_all, but do not send the packet to the specified node. If node is NULL, this behaves like + * send_all. + * + * @see send_all + */ void send_all_except (NetworkChannelID channel_id, const NetworkPacketBuffer &pkt, const NetworkNode *node, bool reliable = true); + /** + * A new node has connected to us + */ + CL_Signal_v1& sig_node_connected (void) { return _sig_node_connected; } - CL_Signal_v1& sig_node_connected (void) { return _sig_node_connected; } + /** + * We have received a NetworkPacket from a NetworkNode on the given NetworkChannelID + */ CL_Signal_v2& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; } }; diff -r c080c8c70333 -r 2a8f20a53ff2 src/Network/TCP.hh --- a/src/Network/TCP.hh Mon Dec 08 15:37:34 2008 +0000 +++ b/src/Network/TCP.hh Mon Dec 08 15:41:48 2008 +0000 @@ -8,62 +8,155 @@ #include "Packet.hh" #include "Buffer.hh" +// @{ +/** + * Initial input/output buffer size given to NetworkTCPTransport::in/out constructor + * + * @see NetworkBufferBase + */ const size_t NETWORK_TCP_INITIAL_IN_BUF = 4096; const size_t NETWORK_TCP_INITIAL_OUT_BUF = 0; +// @} +/** + * A connected TCP socket, so either a client or a server-accept socket + */ class NetworkTCPTransport { protected: + /** + * The SOCK_STREAM socket + */ NetworkSocket socket; + + /** + * Our input buffer associated with socket + */ + NetworkBufferInput in; - NetworkBufferInput in; + /** + * Our output buffer associated with socket + */ NetworkBufferOutput out; CL_SlotContainer slots; public: + /** + * Construct this using the given socket + */ NetworkTCPTransport (NetworkSocket socket); private: + /** + * Triggered when the socket is read for recv + */ void on_read (void); + + /** + * Triggered when the socket is read for send + */ void on_write (void); + + /** + * Triggered when the socket is disconnected (?) + */ void on_disconnected (void); + + /** + * The packet-read signal + */ + CL_Signal_v1 _sig_packet; - CL_Signal_v1 _sig_packet; + /** + * The disconnected-signal + */ CL_Signal_v0 _sig_disconnect; public: + /** + * Get this TCP socket's local ddress + */ NetworkAddress getLocalAddress (void) { return socket.get_source_address(); } + + /** + * Get this TCP socket's remote address + */ NetworkAddress getRemoteAddress (void) { return socket.get_dest_address(); } - + + /** + * Write the given packet to this socket output, buffering the data if need be + * + * @param packet the packet to send + */ void write_packet (const NetworkPacketBuffer &packet); + /** + * A full packet has been received from the remote end + */ CL_Signal_v1& sig_packet (void) { return _sig_packet; } + + /** + * The connection has been lost (no specific error code given) + */ CL_Signal_v0& sig_disconnect (void) { return _sig_disconnect; } }; +/** + * A TCP server, listening on the given address, creating NetworkTCPTransports for clients that connect + */ class NetworkTCPServer { private: + /** + * The listen() socket + */ NetworkSocket socket; CL_SlotContainer slots; public: + /** + * Listen on the specific address. + */ NetworkTCPServer (const NetworkAddress &listen_addr); private: + /** + * The socket is read for read() + */ void on_accept (void); - + + /** + * The on_accept signal + */ CL_Signal_v1 _sig_client; protected: + /** + * Called by on_accept to build the NetworkTCPTransport, can be used to override what class gets used. + * + * By default, this just constructs a new NetworkTCPTransport and returns it + * + * @param socket the socket returned by accept() + */ virtual NetworkTCPTransport* buildTransport (CL_Socket &socket); public: + /** + * A new client has connected, and a NetworkTCPTransport has been connected for it + */ CL_Signal_v1& sig_client (void) { return _sig_client; } }; +/** + * A TCP Client that connects to the given address + */ class NetworkTCPClient : public NetworkTCPTransport { public: + /** + * Create a NetworkTCPTransport, and then connect our socket to the given address. + * + * @param connect_addr the address to connect to + */ NetworkTCPClient (const NetworkAddress &connect_addr); }; diff -r c080c8c70333 -r 2a8f20a53ff2 src/Network/UDP.hh --- a/src/Network/UDP.hh Mon Dec 08 15:37:34 2008 +0000 +++ b/src/Network/UDP.hh Mon Dec 08 15:41:48 2008 +0000 @@ -5,24 +5,51 @@ #include "Address.hh" #include "Packet.hh" +/** + * A UDP socket that can send and receive NetworkPackets + */ class NetworkUDP { private: + /** + * The socket itself + */ NetworkSocket socket; CL_SlotContainer slots; public: + /** + * Allocate an UDP socket on an ephemeral port (random port chosen by OS) + */ NetworkUDP (void); + + /** + * Allocate an UDP socket on a specific local port/interface + * + * @param bind_addr the local address to bind to + */ NetworkUDP (const NetworkAddress &bind_addr); private: + /** + * Socket is ready for recv, read as many packets as available, calling sig_packet on each + */ void on_recv (void); - + + /** + * The signal called by on_recv + */ CL_Signal_v2 _sig_packet; public: + /** + * Send the given packet on this UDP socket to the given destination address + */ bool sendto (const NetworkPacketBuffer &packet, const NetworkAddress &dst); + /** + * Triggered whenever a packet has been received, giving the NetworkPacketInput and the source address + */ CL_Signal_v2& sig_packet (void) { return _sig_packet; } };