# include <netinet/in.h>
#endif
#include "../syscalls.h"
+//#include <debug.h>
#define USE_TCP 0
#define MAX_CLIENTS 16
// === IMPORTS ===
extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
+extern int Threads_CreateRootProcess(void);
+extern void Threads_SetThread(int TID);
+// HACK: Should have these in a header
+extern void Log_Debug(const char *Subsys, const char *Message, ...);
+extern void Log_Notice(const char *Subsys, const char *Message, ...);
// === PROTOTYPES ===
tClient *Server_GetClient(int ClientID);
int Server_WorkerThread(void *ClientPtr);
int SyscallServer(void);
+ int Server_ListenThread(void *Unused);
// === GLOBALS ===
#ifdef __WIN32__
# define INVALID_SOCKET -1
int gSocket = INVALID_SOCKET;
#endif
- int giServer_NextClientID = 1;
tClient gaServer_Clients[MAX_CLIENTS];
+SDL_Thread *gpServer_ListenThread;
// === CODE ===
+int Server_GetClientID(void)
+{
+ int i;
+ Uint32 thisId = SDL_ThreadID();
+
+ for( i = 0; i < MAX_CLIENTS; i ++ )
+ {
+ if( SDL_GetThreadID(gaServer_Clients[i].WorkerThread) == thisId )
+ return gaServer_Clients[i].ClientID;
+ }
+
+ fprintf(stderr, "ERROR: Server_GetClientID - Thread is not allocated\n");
+
+ return 0;
+}
+
tClient *Server_GetClient(int ClientID)
{
tClient *ret = NULL;
int i;
+ // Allocate an ID if needed
+ if(ClientID == 0)
+ ClientID = Threads_CreateRootProcess();
+
for( i = 0; i < MAX_CLIENTS; i ++ )
{
if( gaServer_Clients[i].ClientID == ClientID ) {
- ret = &gaServer_Clients[i];
- break;
+ return &gaServer_Clients[i];
}
+ if(!ret && gaServer_Clients[i].ClientID == 0)
+ ret = &gaServer_Clients[i];
}
// Uh oh, no free slots
if( !ret )
return NULL;
- if( ClientID == 0 )
- {
- ret->ClientID = giServer_NextClientID ++;
- ret->CurrentRequest = NULL;
-
- if( !ret->WorkerThread ) {
- ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
- ret->WaitFlag = SDL_CreateCond();
- ret->Mutex = SDL_CreateMutex();
- SDL_mutexP( ret->Mutex );
- }
+ // Allocate a thread for the process
+ ret->ClientID = ClientID;
+ ret->CurrentRequest = NULL;
+
+ if( !ret->WorkerThread ) {
+ ret->WaitFlag = SDL_CreateCond();
+ ret->Mutex = SDL_CreateMutex();
+ SDL_mutexP( ret->Mutex );
+ ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
}
- return &gaServer_Clients[i];
+ return ret;
}
int Server_WorkerThread(void *ClientPtr)
{
tClient *Client = ClientPtr;
tRequestHeader *retHeader;
+ tRequestHeader errorHeader;
int retSize = 0;
int sentSize;
+ int cur_client_id = 0;
#if USE_TCP
#else
for( ;; )
{
// Wait for something to do
- while( !Client->CurrentRequest ) ;
+ while( Client->CurrentRequest == NULL )
+ SDL_CondWait(Client->WaitFlag, Client->Mutex);
+
+ if(Client->ClientID != cur_client_id) {
+ Threads_SetThread( Client->ClientID );
+ cur_client_id = Client->ClientID;
+ }
// Get the response
retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
+
+ Log_Debug("AcessSrv", "Client %i request %i",
+ Client->ClientID, Client->CurrentRequest->CallID);
+
if( !retHeader ) {
// Return an error to the client
- printf("Error returned by SyscallRecieve\n");
+ printf("ERROR: SyscallRecieve failed\n");
+ errorHeader.CallID = Client->CurrentRequest->CallID;
+ errorHeader.NParams = 0;
+ retHeader = &errorHeader;
+ retSize = sizeof(errorHeader);
}
+ // Set ID
+ retHeader->ClientID = Client->ClientID;
+
+ // Mark the thread as ready for another job
+ Client->CurrentRequest = 0;
+
+ Log_Debug("AcessSrv", "Sending %i to %x:%i (Client %i)",
+ retSize, ntohl(Client->ClientAddr.sin_addr.s_addr),
+ ntohs(Client->ClientAddr.sin_port),
+ Client->ClientID
+ );
+
// Return the data
sentSize = sendto(gSocket, retHeader, retSize, 0,
(struct sockaddr*)&Client->ClientAddr, sizeof(Client->ClientAddr)
}
// Free allocated header
- free( retHeader );
-
- Client->CurrentRequest = 0;
-
- // Wait for something else
- SDL_CondWait(Client->WaitFlag, Client->Mutex);
+ if( retHeader != &errorHeader )
+ free( retHeader );
}
#endif
}
listen(gSocket, 5);
#endif
- Log_Notice("Syscall", "Listening on 0.0.0.0:%i\n", SERVER_PORT);
-
+ Log_Notice("AcessSrv", "Listening on 0.0.0.0:%i", SERVER_PORT);
+ gpServer_ListenThread = SDL_CreateThread( Server_ListenThread, NULL );
+ return 0;
+}
+
+int Server_ListenThread(void *Unused)
+{
// Wait for something to do :)
for( ;; )
{
break ;
}
- printf("Client connection %x:%i",
+ Log("Client connection %x:%i\n",
ntohl(client.sin_addr), ntohs(client.sin_port)
);
tRequestHeader *req = (void*)data;
struct sockaddr_in addr;
uint clientSize = sizeof(addr);
- int length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
+ int length;
tClient *client;
+ length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
+
if( length == -1 ) {
perror("SyscallServer - recv");
break;
ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
client = Server_GetClient(req->ClientID);
- if( req->ClientID == 0 )
+ // NOTE: Hack - Should check if all zero
+ if( req->ClientID == 0 || client->ClientAddr.sin_port == 0 )
{
memcpy(&client->ClientAddr, &addr, sizeof(addr));
}
continue;
}
+ Log_Debug("AcessSrv", "Message from Client %i (%p)",
+ client->ClientID, client);
+
client->CurrentRequest = req;
SDL_CondSignal(client->WaitFlag);
#endif
}
-
return -1;
}