# HG changeset patch # User terom # Date 1226341283 0 # Node ID 2ff929186c900014493c678283a781779c3d30cc # Parent d0d7489d4e8b731592f663d6eab4d04e0a8701a9 write some mode code... diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/Network.hh --- a/src/proto2/Network.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/Network.hh Mon Nov 10 18:21:23 2008 +0000 @@ -12,12 +12,8 @@ CL_SlotContainer slots; - CL_NetSession netsession; - - CL_NetObject_Controller netobjs; - // constructor - NetworkCore (GameState &state) : state(state), netsession(NETWORK_APP_NAME), netobjs(&netsession, NETWORK_NETOBJ_CHAN) { } + NetworkCore (GameState &state) : state(state) { } }; enum NetworkMessage { diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkConfig.hh --- a/src/proto2/NetworkConfig.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkConfig.hh Mon Nov 10 18:21:23 2008 +0000 @@ -18,10 +18,8 @@ #include -const std::string NETWORK_APP_NAME = "KisnaGlista"; - const std::string NETWORK_PORT_STR = "9338"; -const std::string NETWORK_NETOBJ_CHAN = "_netobj"; +const size_t NETWORK_PACKET_SIZE = 1280; #endif /* NETWORK_CONFIG_HH */ diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkPacket.cc --- a/src/proto2/NetworkPacket.cc Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkPacket.cc Mon Nov 10 18:21:23 2008 +0000 @@ -3,7 +3,7 @@ NetworkPacket::NetworkPacket (void) : - size(0), offset(0) { + size(NETWORK_PACKET_SIZE), offset(0) { // nothing } diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkPacket.hh --- a/src/proto2/NetworkPacket.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkPacket.hh Mon Nov 10 18:21:23 2008 +0000 @@ -15,7 +15,10 @@ NetworkPacket (void); char* get_buf (void) { return buf; } - size_t get_size (void) { return size; } + size_t get_data_size (void) { return offset; } + size_t get_buf_size (void) { return size; } + + void set_data_size (size_t size) { offset = size; } // type-reads, handle network-endianlness uint32_t read_uint32 (void); diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkServer.hh --- a/src/proto2/NetworkServer.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkServer.hh Mon Nov 10 18:21:23 2008 +0000 @@ -3,6 +3,8 @@ #include "Network.hh" #include "GameState.hh" +#include "NetworkTCP.hh" +#include "NetworkUDP.hh" #include #include @@ -15,38 +17,38 @@ friend class NetworkServerPlayer; private: + NetworkTCPServer tcp_server; + NetworkUDP udp; + uint16_t pid_pool; - - public: - std::map players; + + std::map players; public: - NetworkServer (GameState &state, const std::string &listen_port); + NetworkServer (GameState &state, const NetworkAddress &listen_addr); private: - void on_connect (CL_NetComputer &computer); - void on_disconnect (CL_NetComputer &computer); - - + void on_client (NetworkTCPTransport *client); + void on_packet_udp (const NetworkPacket &pkt, const NetworkAddress &src); }; class NetworkServerPlayer : public RemotePlayer { private: NetworkServer &server; - CL_NetComputer &computer; - CL_NetObject_Server obj; + NetworkTCPTransport *tcp; CL_SlotContainer slots; uint16_t pid; public: - NetworkServerPlayer (NetworkServer &server, CL_NetComputer &computer, uint16_t pid); - - void disconnected (void); + NetworkServerPlayer (NetworkServer &server, NetworkTCPTransport *tcp, uint16_t pid); private: - void on_move (CL_NetComputer &from, CL_NetPacket &pkt); + void on_disconnected (void); + void on_packet_tcp (const NetworkPacket &pkt); + + void on_move (const NetworkPacket &pkt); void send_position_update (void); }; diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkTCP.cc --- a/src/proto2/NetworkTCP.cc Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkTCP.cc Mon Nov 10 18:21:23 2008 +0000 @@ -14,17 +14,140 @@ // remember size size = size_hint; } + +~NetworkBuffer::NetworkBuffer (void) { + free(buf); +} -void NetworkBuffer::resize (size_t new_size) { - // realloc buffer - if ((buf = (char *) realloc((void *) buf, new_size)) == NULL) - throw CL_Error("realloc failed"); +void NetworkBuffer::resize (size_t suffix_size) { + size_t new_size = size; + + // grow new_size until item_size fits + while (offset + item_size > new_size) + new_size *= 2; - // update size - size = new_size; + // grow if needed + if (new_size != size) { + // realloc buffer + if ((buf = (char *) realloc((void *) buf, new_size)) == NULL) + throw CL_Error("realloc failed"); + + // update size + size = new_size; + + } else if (new_size > (offset + item_size) * 4) { + // XXX: shrink? + } } -void NetworkBuffer::write (const char *buf_ptr, size_t buf_size) { +void NetworkBuffer::trim (size_t prefix_size) { + // update offset + offset -= prefix; + + // shift the buffer forwards from (buf + prefix) -> (buf), copying (old_offset - prefix) bytes + memmove(buf, buf + ret, offset); +} + +bool try_read (size_t item_size) { + int ret; + size_t to_read = item_size; + + // keept reads at at least NETWORK_CHUNK_SIZE bytes + if (to_read < NETWORK_TCP_CHUNK_SIZE) + to_read = NETWORK_TCP_CHUNK_SIZE; + + // resize buffer if needed + resize(to_read); + + // read once + try { + ret = socket.recv(buf + offset, to_read); + + } catch (CL_Error &e) { + if (errno == EAGAIN) + return false; + else + throw; + } + + // update offset + offset += ret; + + // did we get enough? + if (ret < item_size) + return false; + else + return true; +} + +bool peek_prefix (uint16_t &ref) { + if (offset < sizeof(uint16_t)) + return false; + + ret = ntohs(*((uint16_t *) (buf))); + + return true; +} + +bool peek_prefix (uint32_t &ref) { + if (offset < sizeof(uint32_t)) + return false; + + ret = ntohl(*((uint32_t *) (buf))); + + return true; +} + +template PrefixType read_prefix (char *buf_ptr, size_t buf_max) { + PrefixType prefix = 0; + size_t missing = 0; + + do { + // do we have the prefix? + if (peek_prefix(prefix)) { + // do we already have the payload? + if (offset >= sizeof(PrefixType) + prefix) { + break; + + } else { + missing = (sizeof(PrefixType) + prefix) - offset; + } + + } else { + missing = sizeof(PrefixType); + } + + // sanity-check + assert(missing); + + // try and read the missing data + if (try_read(missing) == false) { + // if unable to read what we need, return zero. + return 0; + } + + // assess the situation again + } while (true); + + // copy the data over, unless it's too large + if (prefix <= buf_max) { + memcpy(buf_ptr, buf, prefix); + + // trim the bytes out + trim(prefix); + + // return + return prefix; + + } else { + // trim the bytes out + trim(prefix); + + throw CL_Error("recv prefix overflow"); + } +} + +void NetworkBuffer::push_write (char *buf_ptr, size_t buf_size) { int ret; // try and short-circuit writes unless we have already buffered data @@ -55,16 +178,9 @@ } } - size_t new_size = size; + // resize to fit buf_size more bytes + resize(buf_size); - // calcluate new buffer size - while (offset + buf_size > new_size) - new_size *= 2; - - // grow internal buffer if needed - if (new_size != size) - resize(new_size); - // copy into our internal buffer memcpy(buf + offset, buf_ptr, buf_size); } @@ -89,12 +205,15 @@ throw; } - // update offset - offset -= ret; + // trim the buffer + trim(ret); +} + +template void NetworkBuffer::write_prefix (char *buf, PrefixType prefix) { + push_write(&prefix, sizeof(PrefixType)); + push_write(buf, prefix); +} - // shift the buffer forwards from (buf + ret) -> (buf), copying (old_offset - ret) bytes - memmove(buf, buf + ret, offset); -} NetworkTCPTransport::NetworkTCPTransport (CL_Socket socket) : socket(socket), in(NETWORK_TCP_INITIAL_IN_BUF), out(NETWORK_TCP_INITIAL_OUT_BUF) { @@ -110,23 +229,14 @@ void NetworkTCPTransport::on_read (void) { + uint16_t prefix; NetworkPacket packet; - - do { - size_t to_read = 0; - - // guess how much data to receive based on either the given length prefix or our minimim chunk size - if (in.read_prefix(to_read) == false || to_read < NETWORK_TCP_CHUNK_SIZE) - to_read = NETWORK_TCP_CHUNK_SIZE - - // do the recv - if (in.recv(socket, to_read) == -1) - - // read out any packets - while (in.read_prefix_packet(packet)) { - handle_packet(packet); - } - } while (...); + + // let the in stream read length-prefixed packets and pass them on to handle_packet + while ((prefix = in.read_prefix(packet.get_buf(), packet.get_buf_size)) > 0) { + packet.set_data_size(prefix); + sig_packet(packet); + } } void NetworkTCPTransport::on_write (void) { @@ -135,12 +245,18 @@ } void NetworkTCPTransport::on_disconnected (void) { - + // pass right through + sig_disconnect(); } void NetworkTCPTransport::write_packet (const NetworkPacket &packet) { + uint16_t prefix = packet.get_data_size(); + + if (prefix != packet.get_data_size()) + throw CL_Error("send prefix overflow"); + // just write to the output buffer - out.write(packet.get_buf(), packet.get_size()); + out.write_prefix(packet.get_buf(), prefix); } NetworkTCPServer::NetworkTCPServer (const NetworkAddress &listen_addr) : @@ -165,7 +281,7 @@ NetworkTCPTransport *client = new NetworkTCPTransport(client_sock); // let our user handle it - handle_client(client); + sig_client(client); } NetworkTCPClient::NetworkTCPClient (const NetworkAddress &connect_addr) : diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkTCP.hh --- a/src/proto2/NetworkTCP.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkTCP.hh Mon Nov 10 18:21:23 2008 +0000 @@ -18,20 +18,27 @@ size_t size, off; NetworkSocket &socket; - + public: NetworkBuffer (NetworkSocket &socket, size_t size_hint); - + private: - void resize (size_t new_size); + NetworkBuffer (const NetworkBuffer ©) { }; + ~NetworkBuffer (void); + NetworkBuffer& operator= (const NetworkBuffer ©) { }; + + void resize (size_t suffix_size); + void trim (size_t prefix_size); public: - void write (const char *buf, size_t size); - void read (char *buf, size_t size); - + void push_write (char *buf_ptr, size_t buf_size); void flush_write (void); - - template bool read_prefix (T &val_ref); + template void write_prefix (char *buf, PrefixType prefix); + + void try_read (size_t item_size); + bool peek_prefix (uint16_t &ref); + bool peek_prefix (uint32_t &ref); + template PrefixType read_prefix (char *buf_ptr, size_t buf_max); }; class NetworkTCPTransport { @@ -51,11 +58,11 @@ void on_write (void); void on_disconnected (void); - protected: + public: void write_packet (const NetworkPacket &packet); - virtual void handle_packet (const NetworkPacket &packet) = 0; - virtual void handle_disconnect (void) = 0; + CL_Signal_v1 sig_packet; + CL_Signal_v0 sig_disconnect; }; class NetworkTCPServer { @@ -68,8 +75,8 @@ private: void on_accept (void); - protected: - virtual void handle_client (NetworkTCPTransport *client) = 0; + public: + CL_Signal_v1 sig_client; }; class NetworkTCPClient : public NetworkTCPTransport { diff -r d0d7489d4e8b -r 2ff929186c90 src/proto2/NetworkUDP.hh --- a/src/proto2/NetworkUDP.hh Mon Nov 10 16:49:09 2008 +0000 +++ b/src/proto2/NetworkUDP.hh Mon Nov 10 18:21:23 2008 +0000 @@ -7,6 +7,8 @@ private: NetworkSocket socket; + CL_SlotContainer slots; + public: NetworkUDP (void); NetworkUDP (const NetworkAddress &bind_addr); @@ -14,10 +16,10 @@ private: void on_recv (void); - protected: + public: bool sendto (const NetworkPacket &packet, const NetworkAddress &dst); - - void handle_packet (NetworkPacket &packet, const NetworkAddress &src); + + CL_Signal_v2 sig_packet; }; #endif /* NETWORK_UDP_HH */