--- 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; }
};
--- 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<NetworkAddress, NetworkNode*> nodes;
- std::map<NetworkAddress, NetworkNode*> nodes;
+ /**
+ * A map of NetworkChannelID -> signal, used to signal our users when we receieve packets
+ */
std::map<NetworkChannelID, CL_Signal_v2<NetworkPacketInput&, NetworkNode *> > _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<NetworkNode*> _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<NetworkNode*>& sig_node_connected (void) { return _sig_node_connected; }
- CL_Signal_v1<NetworkNode*>& sig_node_connected (void) { return _sig_node_connected; }
+ /**
+ * We have received a NetworkPacket from a NetworkNode on the given NetworkChannelID
+ */
CL_Signal_v2<NetworkPacketInput&, NetworkNode *>& sig_chan_message (NetworkChannelID cid) { return _map_sig_chan_message[cid]; }
};
--- 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<NetworkPacketInput&> _sig_packet;
- CL_Signal_v1<NetworkPacketInput&> _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<NetworkPacketInput&>& 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<NetworkTCPTransport *> _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<NetworkTCPTransport *>& 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);
};
--- 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<NetworkPacketInput&, const NetworkAddress&> _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<NetworkPacketInput&, const NetworkAddress&>& sig_packet (void) { return _sig_packet; }
};