+ gpServer_ListenThread = SDL_CreateThread( Server_ListenThread, NULL );
+ return 0;
+}
+
+int Server_Shutdown(void)
+{
+ close(gSocket);
+ for( int i = 0; i < MAX_CLIENTS; i ++ )
+ {
+ if( gaServer_Clients[i].ClientID == 0 )
+ continue ;
+ Threads_PostEvent( Threads_GetThread(gaServer_Clients[i].ClientID), 0 );
+ gaServer_Clients[i].ClientID = -1;
+ #if USE_TCP
+ close(gaServer_Clients[i].Socket);
+ #else
+ SDL_CondSignal(gaServer_Clients[i].WaitFlag);
+ #endif
+ }
+ return 0;
+}
+
+#if USE_TCP
+int Server_int_HandleRx(tClient *Client)
+{
+ const int ciMaxParamCount = 6;
+ char lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
+ tRequestHeader *hdr = (void*)lbuf;
+ size_t len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
+ if( len == 0 ) {
+ Log_Notice("Server", "Zero RX on %i (worker %p)", Client->Socket, Client);
+ return 1;
+ }
+ if( len == -1 ) {
+ perror("recv header");
+ return 2;
+ }
+ if( len != sizeof(*hdr) ) {
+ // Oops?
+ Log_Warning("Server", "FD%i bad sized (%i != exp %i)",
+ Client->Socket, len, sizeof(*hdr));
+ return 0;
+ }
+
+ if( hdr->NParams > ciMaxParamCount ) {
+ // Oops.
+ Log_Warning("Server", "FD%i too many params (%i > max %i)",
+ Client->Socket, hdr->NParams, ciMaxParamCount);
+ return 0;
+ }
+
+ if( hdr->NParams > 0 )
+ {
+ len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
+ if( len != hdr->NParams*sizeof(tRequestValue) ) {
+ // Oops.
+ perror("recv params");
+ Log_Warning("Sever", "Recieving params failed");
+ return 0;
+ }
+ }
+ else
+ {
+ //Log_Debug("Server", "No params?");
+ }
+
+ // Get buffer size
+ size_t hdrsize = sizeof(tRequestHeader) + hdr->NParams*sizeof(tRequestValue);
+ size_t bufsize = hdrsize;
+ for( int i = 0; i < hdr->NParams; i ++ )
+ {
+ if( hdr->Params[i].Flags & ARG_FLAG_ZEROED )
+ ;
+ else {
+ bufsize += hdr->Params[i].Length;
+ }
+ }
+
+ // Allocate full buffer
+ hdr = malloc(bufsize);
+ memcpy(hdr, lbuf, hdrsize);
+ if( bufsize > hdrsize )
+ {
+ size_t rem = bufsize - hdrsize;
+ char *ptr = (void*)( hdr->Params + hdr->NParams );
+ while( rem )
+ {
+ len = recv(Client->Socket, ptr, rem, 0);
+ if( len == -1 ) {
+ // Oops?
+ perror("recv data");
+ Log_Warning("Sever", "Recieving data failed");
+ return 2;
+ }
+ rem -= len;
+ ptr += len;
+ }
+ if( rem ) {
+ // Extra data?
+ return 0;
+ }
+ }
+ else {
+ //Log_Debug("Server", "no data");
+ }
+
+ // Dispatch to worker
+ if( Client->CurrentRequest ) {
+ printf("Worker thread for client ID %i is busy\n", Client->ClientID);
+ return 1;
+ }
+
+ // Give to worker
+ Log_Debug("Server", "Message from Client %i (%p)", Client->ClientID, Client);
+ Client->CurrentRequest = hdr;
+ SDL_CondSignal(Client->WaitFlag);
+
+ return 0;
+}
+
+int Server_int_HandshakeClient(int Socket, struct sockaddr_in *addr, socklen_t addr_size)
+{
+ ENTER("iSocket paddr iaddr_size",
+ Socket, addr, addr_size);
+ unsigned short port = ntohs(addr->sin_port);
+ char addrstr[4*8+8+1];
+ getnameinfo((struct sockaddr*)addr, addr_size, addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+ Log_Debug("Server", "Client connection %s:%i", addrstr, port);