+/* TODO: peer address */
+static TCPsocket lfd; /* listening TCP socket */
+static UDPsocket udp; /* listening UDP socket */
+static SDLNet_SocketSet fds; /* socket set */
+
+static struct NetworkBuffer *read_buffer = NULL;
+static struct NetworkBuffer *write_buffer = NULL;
+
+static unsigned int ServerFrameCounter = 0;
+
+
+int getNetwork8BitInteger(byte *ptr)
+{
+ return ptr[0];
+}
+
+int putNetwork8BitInteger(byte *ptr, int value)
+{
+ ptr[0] = value;
+
+ return 1;
+}
+
+int getNetwork16BitInteger(byte *ptr)
+{
+ return ((ptr[0] << 8) |
+ (ptr[1] << 0));
+}
+
+int putNetwork16BitInteger(byte *ptr, int value)
+{
+ ptr[0] = (value >> 8) & 0xff;
+ ptr[1] = (value >> 0) & 0xff;
+
+ return 2;
+}
+
+int getNetwork32BitInteger(byte *ptr)
+{
+ return ((ptr[0] << 24) |
+ (ptr[1] << 16) |
+ (ptr[2] << 8) |
+ (ptr[3] << 0));
+}
+
+int putNetwork32BitInteger(byte *ptr, int value)
+{
+ ptr[0] = (value >> 24) & 0xff;
+ ptr[1] = (value >> 16) & 0xff;
+ ptr[2] = (value >> 8) & 0xff;
+ ptr[3] = (value >> 0) & 0xff;
+
+ return 4;
+}
+
+char *getNetworkString(byte *ptr)
+{
+ return (char *)ptr;
+}
+
+int putNetworkString(byte *ptr, char *s)
+{
+ strcpy((char *)ptr, s);
+
+ return strlen(s) + 1;
+}
+
+struct NetworkBuffer *newNetworkBuffer(void)
+{
+ 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;