more untested, uncompiled code no-netsession
authorterom
Mon, 10 Nov 2008 19:57:57 +0000
branchno-netsession
changeset 33 e53f09b378f4
parent 32 2ff929186c90
child 34 1ea6554d703e
more untested, uncompiled code
src/proto2/NetworkConfig.hh
src/proto2/NetworkNode.cc
src/proto2/NetworkNode.hh
src/proto2/NetworkPacket.cc
src/proto2/NetworkPacket.hh
src/proto2/NetworkSession.cc
src/proto2/NetworkSession.hh
src/proto2/NetworkTCP.cc
src/proto2/NetworkTCP.hh
src/proto2/NetworkUDP.cc
--- 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 */
--- /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;
+}
--- /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 &copy) { }
+        ~NetworkNode (void);
+        NetworkNode& operator= (const NetworkNode &copy) { }
+
+    public:
+        void send (NetworkChannelID channel_id, const NetworkPacket &pkt, bool reliable = true);
+
+        const NetworkAddress& getRemoteAddress (void);
+};
+
+#endif /* NETWORK_NODE_HH */
--- 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 <typename T> 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 <typename T> 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<uint32_t>());
 }
 
-uint16_t NetworkPacket::read_uint16 (void) {
+uint16_t NetworkPacket::read_uint16 (void) const {
     return ntohs(read_val<uint16_t>());
 }
 
-uint8_t NetworkPacket::read_uint8 (void) {
+uint8_t NetworkPacket::read_uint8 (void) const {
     return read_val<uint8_t>();
 }
 
-int32_t NetworkPacket::read_int32 (void) {
+int32_t NetworkPacket::read_int32 (void) const {
     return ntohl(read_val<int32_t>());
 }
 
-int16_t NetworkPacket::read_int16 (void) {
+int16_t NetworkPacket::read_int16 (void) const {
     return ntohs(read_val<int16_t>());
 }
 
-int8_t NetworkPacket::read_int8 (void) {
+int8_t NetworkPacket::read_int8 (void) const {
     return read_val<int8_t>();
 }
 
@@ -86,3 +95,14 @@
     write_val<int8_t>(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();
+}
--- 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 <typename T> T read_val (void);
         template <typename T> 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 */
--- /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<NetworkAddress, NetworkNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
+        if (it->second == node)
+            continue;
+
+        it->second->send(channel_id, pkt, reliable);
+    }
+}
--- /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 <map>
+
+/*
+ * 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<NetworkAddress, NetworkNode*> 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<NetworkNode*> sig_node_connected;
+        CL_Signal_v1<NetworkNode*> sig_node_disconnected;
+};
+
+#endif /* NETWORK_SESSION_HH */
--- 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)) {
 
--- 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<const NetworkPacket&> sig_packet;
@@ -75,6 +77,9 @@
     private:
         void on_accept (void);
 
+    protected:
+        virtual NetworkTCPTransport buildTransport (CL_Socket &socket);
+
     public:
         CL_Signal_v1<NetworkTCPTransport *> sig_client;
 };
--- /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;
+}
+