+ struct NetworkBuffer *new = checked_calloc(sizeof(struct NetworkBuffer));
+
+ new->max_size = MAX_BUFFER_SIZE;
+ new->size = 0;
+ new->pos = 0;
+
+ new->buffer = checked_calloc(new->max_size);
+
+ return new;
+}
+
+static void resetNetworkBufferForReading(struct NetworkBuffer *nb)
+{
+ nb->pos = 0;
+}
+
+static void resetNetworkBufferForWriting(struct NetworkBuffer *nb)
+{
+ nb->size = 0;
+ nb->pos = 0;
+}
+
+void initNetworkBufferForReceiving(struct NetworkBuffer *nb)
+{
+ resetNetworkBufferForWriting(nb);
+}
+
+void initNetworkBufferForReading(struct NetworkBuffer *nb)
+{
+ resetNetworkBufferForReading(nb);
+
+ /* skip message length header */
+ getNetworkBuffer32BitInteger(nb);
+}
+
+void initNetworkBufferForWriting(struct NetworkBuffer *nb, int message_type,
+ int player_nr)
+{
+ resetNetworkBufferForWriting(nb);
+
+ /* will be replaced with message length before sending */
+ putNetworkBuffer32BitInteger(nb, 0);
+
+ putNetworkBuffer8BitInteger(nb, message_type);
+ putNetworkBuffer8BitInteger(nb, player_nr);
+}
+
+static void copyNetworkBufferForWriting(struct NetworkBuffer *nb_from,
+ struct NetworkBuffer *nb_to,
+ int player_nr)
+{
+ initNetworkBufferForReading(nb_from);
+
+ int message_type = getNetworkBuffer8BitInteger(nb_from);
+
+ /* skip player number */
+ getNetworkBuffer8BitInteger(nb_from);
+
+ initNetworkBufferForWriting(nb_to, message_type, player_nr);
+
+ while (nb_from->pos < nb_from->size)
+ {
+ int b = getNetworkBuffer8BitInteger(nb_from);
+
+ putNetworkBuffer8BitInteger(nb_to, b);
+ }
+}
+
+static void increaseNetworkBuffer(struct NetworkBuffer *nb, int additional_size)
+{
+ /* add some more buffer size than is really required this time */
+ nb->max_size += additional_size + MAX_BUFFER_SIZE;
+ nb->buffer = checked_realloc(nb->buffer, nb->max_size);
+}
+
+int receiveNetworkBufferBytes(struct NetworkBuffer *nb, TCPsocket socket,
+ int num_bytes)
+{
+ if (num_bytes > MAX_PACKET_SIZE)
+ {
+ Error(ERR_NETWORK_SERVER, "protocol error: invalid packet size %d",
+ num_bytes);
+
+ return -1;
+ }
+
+ if (nb->pos + num_bytes > nb->max_size)
+ increaseNetworkBuffer(nb, num_bytes);
+
+ int result = SDLNet_TCP_Recv(socket, &nb->buffer[nb->pos], num_bytes);
+
+ if (result != num_bytes)
+ return result;
+
+ nb->pos += num_bytes;
+ nb->size = nb->pos;
+
+ return num_bytes;
+}
+
+int receiveNetworkBufferPacket(struct NetworkBuffer *nb, TCPsocket socket)
+{
+ int num_bytes, num_bytes_head, num_bytes_body;
+
+ num_bytes_head = 4;
+ num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_head);
+
+ if (num_bytes != num_bytes_head)
+ return num_bytes;
+
+ num_bytes_body = getNetwork32BitInteger(nb->buffer);
+ num_bytes = receiveNetworkBufferBytes(nb, socket, num_bytes_body);
+
+ return num_bytes;
+}
+
+int getNetworkBuffer8BitInteger(struct NetworkBuffer *nb)
+{
+ int num_bytes = 1;
+
+ if (nb->pos + num_bytes > nb->size)
+ return 0;
+
+ int value = getNetwork8BitInteger(&nb->buffer[nb->pos]);
+
+ nb->pos += num_bytes;
+
+ return value;
+}
+
+void putNetworkBuffer8BitInteger(struct NetworkBuffer *nb, int value)
+{
+ int num_bytes = 1;
+
+ if (nb->pos + num_bytes > nb->max_size)
+ increaseNetworkBuffer(nb, num_bytes);
+
+ nb->pos += putNetwork8BitInteger(&nb->buffer[nb->pos], value);
+ nb->size = nb->pos;
+}
+
+int getNetworkBuffer16BitInteger(struct NetworkBuffer *nb)
+{
+ int num_bytes = 2;
+
+ if (nb->pos + num_bytes > nb->size)
+ return 0;
+
+ int value = getNetwork16BitInteger(&nb->buffer[nb->pos]);
+
+ nb->pos += num_bytes;
+
+ return value;
+}
+
+void putNetworkBuffer16BitInteger(struct NetworkBuffer *nb, int value)
+{
+ int num_bytes = 2;
+
+ if (nb->pos + num_bytes > nb->max_size)
+ increaseNetworkBuffer(nb, num_bytes);
+
+ nb->pos += putNetwork16BitInteger(&nb->buffer[nb->pos], value);
+ nb->size = nb->pos;
+}
+
+int getNetworkBuffer32BitInteger(struct NetworkBuffer *nb)
+{
+ int num_bytes = 4;
+
+ if (nb->pos + num_bytes > nb->size)
+ return 0;
+
+ int value = getNetwork32BitInteger(&nb->buffer[nb->pos]);
+
+ nb->pos += num_bytes;
+
+ return value;
+}
+
+void putNetworkBuffer32BitInteger(struct NetworkBuffer *nb, int value)
+{
+ int num_bytes = 4;
+
+ if (nb->pos + num_bytes > nb->max_size)
+ increaseNetworkBuffer(nb, num_bytes);
+
+ nb->pos += putNetwork32BitInteger(&nb->buffer[nb->pos], value);
+ nb->size = nb->pos;
+}
+
+char *getNetworkBufferString(struct NetworkBuffer *nb)
+{
+ char *s = getNetworkString(&nb->buffer[nb->pos]);
+
+ nb->pos += strlen(s) + 1;
+
+ return s;
+}
+
+void putNetworkBufferString(struct NetworkBuffer *nb, char *s)
+{
+ int num_bytes = strlen(s) + 1;
+
+ if (nb->pos + num_bytes > nb->max_size)
+ increaseNetworkBuffer(nb, num_bytes);
+
+ nb->pos += putNetworkString(&nb->buffer[nb->pos], s);
+ nb->size = nb->pos;
+}
+
+int getNetworkBufferFile(struct NetworkBuffer *nb, char *filename)
+{
+ FILE *file;
+ int num_bytes = getNetworkBuffer32BitInteger(nb);
+ int i;
+
+ if (!(file = fopen(filename, MODE_WRITE)))
+ {
+ Error(ERR_WARN, "cannot write file '%s' from network buffer", filename);
+
+ return 0;
+ }
+
+ for (i = 0; i < num_bytes; i++)
+ {
+ int b = getNetworkBuffer8BitInteger(nb);
+
+ putFile8Bit(file, b);
+ }
+
+ fclose(file);
+
+ return num_bytes;
+}
+
+int putNetworkBufferFile(struct NetworkBuffer *nb, char *filename)
+{
+ File *file;
+ int filesize_pos = nb->pos;
+ int num_bytes = 0;
+
+ /* will be replaced with file size */
+ putNetworkBuffer32BitInteger(nb, 0);
+
+ if (!(file = openFile(filename, MODE_READ)))
+ {
+ Error(ERR_WARN, "cannot read file '%s' to network buffer", filename);
+
+ return 0;
+ }
+
+ while (1)
+ {
+ int b = getFile8Bit(file);