# HG changeset patch # User Tero Marttila # Date 1231874052 -7200 # Node ID 59c2499fe7bb572b3eda2d141e7c6b0e08e1ed79 # Parent 3c8078b96469c7195375f9b49ef187ec669d9a15 add compressed read/write NetworkPacket API and move zlib stuff out of NetworkServer/Client diff -r 3c8078b96469 -r 59c2499fe7bb .hgignore --- a/.hgignore Tue Jan 13 20:21:28 2009 +0200 +++ b/.hgignore Tue Jan 13 21:14:12 2009 +0200 @@ -2,3 +2,4 @@ ^build/(CMake|cmake|Makefile|data|doc|src|install_manifest\.txt) \.[^/]+\.sw[op]$ +^doc/kishna.(aux|log|pdf|toc)$ diff -r 3c8078b96469 -r 59c2499fe7bb src/Network/Client.cc --- a/src/Network/Client.cc Tue Jan 13 20:21:28 2009 +0200 +++ b/src/Network/Client.cc Tue Jan 13 21:14:12 2009 +0200 @@ -6,7 +6,6 @@ #include "../Logger.hh" #include -#include NetworkClient::NetworkClient (Engine &engine, GameState &state, const NetworkEndpoint &connect_to) : engine(engine), state(state), netsession(NETWORK_MAGIC_ID), server(netsession.connect(connect_to)), @@ -36,16 +35,10 @@ // the terrain byte array size_t terrain_size = map_w * map_h; uint8_t terrain_buf[map_w][map_h]; + + // read uncompressed terrain data + size_t inflate_size = pkt.read_uncompressed(terrain_buf, terrain_size); - // compressed packet data - unsigned long inflate_size = terrain_size; - unsigned long deflate_size = pkt.tell_remaining(); - const uint8_t *deflate_ptr = (const uint8_t *) pkt.read_ptr(deflate_size); - - // uncompress the rest of the packet data - if (uncompress((uint8_t *) terrain_buf, &inflate_size, deflate_ptr, deflate_size) != Z_OK) - throw Error("uncompress"); - // invalid data? if (inflate_size != terrain_size) throw Error("Corrupt terrain data"); diff -r 3c8078b96469 -r 59c2499fe7bb src/Network/Packet.cc --- a/src/Network/Packet.cc Tue Jan 13 20:21:28 2009 +0200 +++ b/src/Network/Packet.cc Tue Jan 13 21:14:12 2009 +0200 @@ -4,6 +4,8 @@ #include "Packet.hh" +#include + // XXX: assumes that sizeof(float32) == sizeof(int32); /* @@ -60,6 +62,24 @@ return Vector(fx, fy); } + +size_t NetworkPacketInput::read_uncompressed (void *buf, size_t len) { + // given len + unsigned long inflate_size = len; + + // read deflate size + unsigned long deflate_size = read_uint32(); + + // pointer to packet data + const void *deflate_ptr = read_ptr(deflate_size); + + // uncompress the rest of the packet data + if (uncompress((uint8_t *) buf, &inflate_size, (const uint8_t *) deflate_ptr, deflate_size) != Z_OK) + throw Error("uncompress"); + + // return inflated size + return inflate_size; +} /* * NetworkPacketOutput @@ -113,6 +133,31 @@ // just write() it write(pkt.get_buf(), pkt.get_data_size()); } + +void NetworkPacketOutput::write_compressed (const void *ptr, uint32_t len) { + // full compression buffer size, including header + unsigned long deflate_buf_size = write_compressed_size(len); + + // size of compressed data area after header + unsigned long deflate_size = deflate_buf_size - sizeof(uint32_t); + + // packet buffer + void *deflate_buf = write_ptr(deflate_buf_size); + + // compress + if (compress((uint8_t *) deflate_buf + sizeof(uint32_t), &deflate_size, (const uint8_t *) ptr, len) != Z_OK) + throw Error("compress failed"); + + // write data size + *((uint32_t *) deflate_buf) = htonl(deflate_size); + + // adjust final area + write_ptr_adjust(deflate_buf_size, sizeof(uint32_t) + deflate_size); +} + +size_t NetworkPacketOutput::write_compressed_size (uint32_t len) { + return sizeof(uint32_t) + compressBound(len); +} /* * NetworkPacketBuffer @@ -138,7 +183,7 @@ const void* NetworkPacketBuffer::read_ptr (size_t len) { // check buffer overflow - check_write_size(len); + check_read_size(len); // pointer value... const void *ptr = buf_ptr + offset; @@ -181,6 +226,14 @@ memcpy(output_ptr, ptr, len); } +void NetworkPacketBuffer::write_ptr_adjust (size_t buf_len, size_t data_len) { + assert(data_len <= buf_len); + + // adjust offset backwards + offset -= (buf_len - data_len); + data_size -= (buf_len - data_len); +} + size_t NetworkPacketBuffer::tell_remaining (void) { // number of bytes in total - number of bytes read return data_size - offset; diff -r 3c8078b96469 -r 59c2499fe7bb src/Network/Packet.hh --- a/src/Network/Packet.hh Tue Jan 13 20:21:28 2009 +0200 +++ b/src/Network/Packet.hh Tue Jan 13 21:14:12 2009 +0200 @@ -35,6 +35,13 @@ void *ptr, //<<< where to copy size_t len //<<< number of bytes to copy ) = 0; + + /** + * Abstract method to get the number of input bytes remaining. + * + * @return number of input bytes still readable + */ + virtual size_t tell_remaining (void) = 0; /** * Convenience function to read() and return the value of the given type @@ -81,17 +88,22 @@ Vector read_vector (void); /** - * Abstract method to get the number of input bytes remaining. - * - * @return number of input bytes still readable + * Read compressed data written with write_compressed. The given buffer must be the same size as passed to + * write_compressed. Returns the number of bytes that were decompressed into buf. */ - virtual size_t tell_remaining (void) = 0; + size_t read_uncompressed (void *buf, size_t len); }; /** * Write-interface for network packets */ class NetworkPacketOutput { + protected: + /** + * Adjust size of the most recent write_ptr area of buf_len bytes to data_len bytes. + */ + virtual void write_ptr_adjust (size_t buf_len, size_t data_len) = 0; + public: /** * Abstract method to get a pointer to \a len bytes of raw in-memory binary data, advancing the write offset @@ -144,6 +156,17 @@ * @param pkt the sub-packet to write() */ void write_packet (const NetworkPacketBuffer &pkt); + + /** + * This will compress the given data buffer into this packet for reading with read_compressed. The compressed + * data will use at most write_compressed_size(len) bytes of data. + */ + void write_compressed (const void *ptr, uint32_t len); + + /** + * Return upper bound on packet size of compressed data, including header. + */ + static size_t write_compressed_size (uint32_t len); }; /** @@ -231,6 +254,8 @@ */ virtual void write (const void *ptr, size_t len); + virtual void write_ptr_adjust (size_t buf_len, size_t data_len); + /** * Returns our data_size - read-offset */ diff -r 3c8078b96469 -r 59c2499fe7bb src/Network/Server.cc --- a/src/Network/Server.cc Tue Jan 13 20:21:28 2009 +0200 +++ b/src/Network/Server.cc Tue Jan 13 21:14:12 2009 +0200 @@ -6,7 +6,6 @@ #include "../Logger.hh" #include -#include NetworkServer::NetworkServer (GameState &state, const NetworkEndpoint &listen_addr) : state(state), netsession(NETWORK_MAGIC_ID), controller(netsession, NETCHAN_CORE) { @@ -250,19 +249,16 @@ } } - // compress the terrain buffer - unsigned long deflate_size = compressBound(terrain_size); - uint8_t deflate_buf[deflate_size]; - - // and compress - if (compress(deflate_buf, &deflate_size, (const uint8_t *) terrain_buf, terrain_size) != Z_OK) - throw Error("compress failed"); - // allocate our packet... BigNetworkPacket pkt ( - NETWORK_SESSION_HEADER_SIZE // NetworkChannel header - + 3 * sizeof(uint32_t) // our own header - + deflate_size // compressed terrain buffer + // NetworkChannel header + NETWORK_SESSION_HEADER_SIZE + + // our own header + + 2 * sizeof(uint32_t) + + // compressed terrain buffer + + NetworkPacketOutput::write_compressed_size(terrain_size) ); // write netsession header @@ -272,8 +268,8 @@ pkt.write_uint32(map.x); pkt.write_uint32(map.y); - // write compressed data - pkt.write(deflate_buf, deflate_size); + // write compressed terrain data + pkt.write_compressed(terrain_buf, terrain_size); // send node->send_raw(pkt, true);