add compressed read/write NetworkPacket API and move zlib stuff out of NetworkServer/Client
--- 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)$
--- 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 <cassert>
-#include <zlib.h>
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");
--- 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 <zlib.h>
+
// 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;
--- 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
*/
--- 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 <cassert>
-#include <zlib.h>
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);