# HG changeset patch # User terom # Date 1226347077 0 # Node ID e53f09b378f4d7d3a4a3abe6c29d4a0af312a8d6 # Parent 2ff929186c900014493c678283a781779c3d30cc more untested, uncompiled code diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkConfig.hh --- a/src/proto2/NetworkConfig.hh Mon Nov 10 18:21:23 2008 +0000 +++ b/src/proto2/NetworkConfig.hh Mon Nov 10 19:57:57 2008 +0000 @@ -21,5 +21,6 @@ const std::string NETWORK_PORT_STR = "9338"; const size_t NETWORK_PACKET_SIZE = 1280; +const int NETWORK_LISTEN_BACKLOG = 5; #endif /* NETWORK_CONFIG_HH */ diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkNode.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proto2/NetworkNode.cc Mon Nov 10 19:57:57 2008 +0000 @@ -0,0 +1,36 @@ + +#include "NetworkNode.hh" + +NetworkNode::NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP &udp, const NetworkAddress &address) : + session(session), tcp(tcp), udp(udp), address(address) { + + // connect signals + +} + +NetworkNode::~NetworkNode (void) { + delete tcp; +} + +void NetworkNode::send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true) { + assert(channel_id > 0); + + // add our header + NetworkPacket pkt2; + pkt2.write_uint16(channel_id); + pkt2.write_packet(pkt); + + // either tcp or udp + if (reliable) { + assert(tcp); + + tcp->write_packet(pkt2); + + } else { + udp.sendto(pkt2, address); + } +} + +const NetworkAddress& NetworkNode::getRemoteAddress (void) { + return address; +} diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkNode.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proto2/NetworkNode.hh Mon Nov 10 19:57:57 2008 +0000 @@ -0,0 +1,28 @@ +#ifndef NETWORK_NODE_HH +#define NETWORK_NODE_HH + +#include "NetworkTCP.hh" + +class NetworkNode { + private: + NetworkSession &session; + NetworkTCPTransport *tcp; + NetworkUDP &udp; + const NetworkAddress address; + + CL_SlotContainer slots; + + private: + NetworkNode (NetworkSession &session, NetworkTCPTransport *tcp, NetworkUDP &udp, const NetworkAddress &address); + + NetworkNode (const NetworkNode ©) { } + ~NetworkNode (void); + NetworkNode& operator= (const NetworkNode ©) { } + + public: + void send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true); + + const NetworkAddress& getRemoteAddress (void); +}; + +#endif /* NETWORK_NODE_HH */ diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkPacket.cc --- a/src/proto2/NetworkPacket.cc Mon Nov 10 18:21:23 2008 +0000 +++ b/src/proto2/NetworkPacket.cc Mon Nov 10 19:57:57 2008 +0000 @@ -3,17 +3,27 @@ NetworkPacket::NetworkPacket (void) : - size(NETWORK_PACKET_SIZE), offset(0) { + buf_size(NETWORK_PACKET_SIZE), data_size(0), offset(0) { // nothing } +void NetworkPacket::check_write_size (size_t item_size) { + if (offset + item_size > buf_size) + throw CL_Error("not enough space to write"); + +} + +void NetworkPacket::check_read_size (size_t item_size) { + if (offset + item_size > data_size) + throw CL_Error("not enough data to read"); +} + template T NetworkPacket::read_val (void) { T val; // check size - if (offset + sizeof(T) > size) - throw CL_Error("not enough data to read"); + check_read_size(sizeof(T)); // set value val = *((T*) (buf + offset)); @@ -27,38 +37,37 @@ template void NetworkPacket::write_val (const T &val) { // check max size - if (offset + sizeof(T) > NETWORK_PACKET_SIZE) - throw CL_Error("not enough space to write"); + check_write_size(sizeof(T)); // set value *((T*) (buf + offset)) = val; // update offset and size offset += sizeof(T); - size += sizeof(T); + data_size += sizeof(T); } -uint32_t NetworkPacket::read_uint32 (void) { +uint32_t NetworkPacket::read_uint32 (void) const { return ntohl(read_val()); } -uint16_t NetworkPacket::read_uint16 (void) { +uint16_t NetworkPacket::read_uint16 (void) const { return ntohs(read_val()); } -uint8_t NetworkPacket::read_uint8 (void) { +uint8_t NetworkPacket::read_uint8 (void) const { return read_val(); } -int32_t NetworkPacket::read_int32 (void) { +int32_t NetworkPacket::read_int32 (void) const { return ntohl(read_val()); } -int16_t NetworkPacket::read_int16 (void) { +int16_t NetworkPacket::read_int16 (void) const { return ntohs(read_val()); } -int8_t NetworkPacket::read_int8 (void) { +int8_t NetworkPacket::read_int8 (void) const { return read_val(); } @@ -86,3 +95,14 @@ write_val(val); } +void write_packet (const NetworkPacket &pkt) { + // check buffer size + check_write_size(pkt.get_data_size()); + + // copy + memcpy(buf + offset, pkt.get_buf(), pkt.get_data_size()); + + // update offset/data_size + offset += pkt.get_data_size(); + data_size += pkt.get_data_size(); +} diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkPacket.hh --- a/src/proto2/NetworkPacket.hh Mon Nov 10 18:21:23 2008 +0000 +++ b/src/proto2/NetworkPacket.hh Mon Nov 10 19:57:57 2008 +0000 @@ -6,7 +6,10 @@ class NetworkPacket { private: char buf[NETWORK_PACKET_SIZE]; - size_t size, offset; + size_t buf_size, data_size, offset; + + void check_write_size (size_t item_size); + void check_read_size (size_t item_size); template T read_val (void); template void write_val (const T &val); @@ -15,19 +18,20 @@ NetworkPacket (void); char* get_buf (void) { return buf; } - size_t get_data_size (void) { return offset; } - size_t get_buf_size (void) { return size; } + const char* get_buf (void) const { return buf; } + size_t get_data_size (void) const { return data_size; } + size_t get_buf_size (void) const { return buf_size; } - void set_data_size (size_t size) { offset = size; } + void set_data_size (size_t size) { offset = 0; data_size = size; } // type-reads, handle network-endianlness - uint32_t read_uint32 (void); - uint16_t read_uint16 (void); - uint8_t read_uint8 (void); + uint32_t read_uint32 (void) const; + uint16_t read_uint16 (void) const; + uint8_t read_uint8 (void) const; - int32_t read_int32 (void); - int16_t read_int16 (void); - int8_t read_int8 (void); + int32_t read_int32 (void) const; + int16_t read_int16 (void) const; + int8_t read_int8 (void) const; void write_uint32 (uint32_t val); void write_uint16 (uint16_t val); @@ -37,7 +41,7 @@ void write_int16 (int16_t val); void write_int8 (int8_t val); - + void write_packet (const NetworkPacket &pkt); }; #endif /* NETWORK_PACKET_HH */ diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkSession.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proto2/NetworkSession.cc Mon Nov 10 19:57:57 2008 +0000 @@ -0,0 +1,78 @@ + +#include "NetworkSession.hh" + +NetworkSession::NetworkSession (NetworkSessionMagic magic) : + magic(magic), tcp_srv(NULL), udp_srv(NULL), udp_client(NULL) { + + // nothing +} + +void NetworkSession::listen (const NetworkAddress &addr) { + assert(tcp_srv == NULL && udp_srv == NULL); + + // create TCP/UDP servers + tcp_srv = new NetworkTCPServer(addr); + udp_srv = new NetworkUDP(addr); + + // connect signals + slots.connect(tcp->sig_client, this, &NetworkSession::on_tcp_client); +} + +NetworkNode* NetworkSession::connect (const NetworkAddress &addr) { + // create new UDP client if needed + if (udp_client == NULL) + udp_client = new NetworkUDP(); + + // connect + NetworkTCPClient *tcp_client = new NetworkTCPClient(addr); + + // create node + NetworkNode *client_node = new NetworkNode(*this, tcp_client, udp_client, addr); + + // add to nodes + nodes[addr] = client_node; + + // bind signals + slots.connect(tcp_client->sig_disconnected, this, &NetworkSession::on_disconnect, client_node); +} + +void NetworkSession::on_tcp_client (const NetworkTCPTransport *tcp_client) { + // get remote address manually, because NetworkTCPServer doesn't pass it in to us + NetworkAddress addr = tcp_client->getRemoteAddress(); + + // create node + NetworkNode *client_node = new NetworkNode(*this, tcp_client, udp_server, addr); + + // add to nodes + nodes[addr] = client_node; + + // bind signals + slots.connect(tcp_client->sig_disconnected, this, &NetworkSession::on_disconnect, client_node); + + // fire signals + sig_node_connected(node); +} + +void NetworkSession::on_disconnect (NetworkNode *node) { + // remove from nodes + nodes.erase(node->getRemoteAddress()); + + // fire signal + sig_node_disconnected(node); + + // delete + delete node; +} + +void NetworkSession::send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable) { + send_all_except(NULL, reliable); +} + +void NetworkSession::send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable) { + for (std::map::iterator it = nodes.begin(); it != nodes.end(); it++) { + if (it->second == node) + continue; + + it->second->send(channel_id, pkt, reliable); + } +} diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkSession.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proto2/NetworkSession.hh Mon Nov 10 19:57:57 2008 +0000 @@ -0,0 +1,47 @@ +#ifndef NETWORK_SESSION_HH +#define NETWORK_SESSION_HH + +#include "NetworkTCP.hh" +#include "NetworkUDP.hh" + +#include + +/* + * Should be set to some 8-char magic value to identify the application + */ +typedef char[8] NetworkSessionMagic; + +/* + * Used to separate packets, ID zero is reserved for NetworkSession use + */ +typedef uint16_t NetworkChannelID; + +class NetworkSession { + private: + NetworkSessionMagic magic; + NetworkTCPServer *tcp_srv; + NetworkUDP *udp_srv, *udp_client; + + CL_SlotContainer slots; + + std::map nodes; + + public: + NetworkSession (NetworkSessionMagic magic); + + void listen (const NetworkAddress &addr); + NetworkNode* connect (const NetworkAddress &addr); + + private: + void on_tcp_client (const NetworkTCPTransport *client); + void on_disconnect (NetworkNode *node); + + public: + void send_all (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true); + void send_all_except (NetworkChannelID channel_id, const NetworkPacket &pkt, const NetworkNode *node, bool reliable = true); + + CL_Signal_v1 sig_node_connected; + CL_Signal_v1 sig_node_disconnected; +}; + +#endif /* NETWORK_SESSION_HH */ diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkTCP.cc --- a/src/proto2/NetworkTCP.cc Mon Nov 10 18:21:23 2008 +0000 +++ b/src/proto2/NetworkTCP.cc Mon Nov 10 19:57:57 2008 +0000 @@ -249,6 +249,10 @@ sig_disconnect(); } +NetworkAddress NetworkTCPTransport::getRemoteAddress (void) { + return socket.get_dest_address(); +} + void NetworkTCPTransport::write_packet (const NetworkPacket &packet) { uint16_t prefix = packet.get_data_size(); @@ -278,12 +282,16 @@ NetworkSocket client_sock = socket.accept(); // create a new NetworkTCPTransport - NetworkTCPTransport *client = new NetworkTCPTransport(client_sock); - + NetworkTCPTransport *client = buildTransport(client_sock); + // let our user handle it sig_client(client); } +virtual NetworkTCPTransport NetworkTCPServer::buildTransport (CL_Socket &socket) { + return new NetworkTCPTransport(client_sock); +} + NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) : NetworkTCPTransport(NetworkSocket(tcp, ipv4)) { diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkTCP.hh --- a/src/proto2/NetworkTCP.hh Mon Nov 10 18:21:23 2008 +0000 +++ b/src/proto2/NetworkTCP.hh Mon Nov 10 19:57:57 2008 +0000 @@ -51,7 +51,7 @@ CL_SlotContainer slots; public: - NetworkTCPTransport (CL_Socket socket); + NetworkTCPTransport (CL_Socket &socket); private: void on_read (void); @@ -59,6 +59,8 @@ void on_disconnected (void); public: + NetworkAddress getRemoteAddress (void); + void write_packet (const NetworkPacket &packet); CL_Signal_v1 sig_packet; @@ -75,6 +77,9 @@ private: void on_accept (void); + protected: + virtual NetworkTCPTransport buildTransport (CL_Socket &socket); + public: CL_Signal_v1 sig_client; }; diff -r 2ff929186c90 -r e53f09b378f4 src/proto2/NetworkUDP.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/proto2/NetworkUDP.cc Mon Nov 10 19:57:57 2008 +0000 @@ -0,0 +1,64 @@ + +#include "NetworkUDP.hh" + +NetworkUDP::NetworkUDP (void) : + socket(udp, ipv4) { + + // do not bind + + // connect signal + slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv); +} + +NetworkUDP::NetworkUDP (const NetworkAddress &bind_addr) : + socket(udp, ipv4) { + + // bind socket + socket.bind(bind_addr); + + // connect signal + slots.connect(socket.sig_read_triggered(), this, &NetworkUDP::on_recv); +} + +void NetworkUDP::on_recv (void) { + int ret; + NetworkPacket pkt; + NetworkAddress src; + + // attempt to recv + try { + ret = socket.recv(pkt.get_buf(), pkt.get_buf_size()); + + } catch (CL_Error &e) { + if (errno == EAGAIN) + return; + else + throw; + } + + // set packet data size + pkt.set_data_size(ret); + + // handle packet + sig_packet(pkt, src); +} + +bool NetworkUDP::sendto (const NetworkPacket &packet, const NetworkAddress &dst) { + int ret; + + // XXX: shouldn't get trimmed + try { + ret =socket.send(packet.get_buf(), packet.get_data_size(), dst); + + } catch (CL_Error &e) { + // XXX: catch some errors, but not others? + return false; + } + + // UDP shouldn't trim packets + assert(ret == packet.get_data_size()); + + // good + return true; +} +