X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Facesskernel_src%2Fserver.c;h=78f7fa13dfcf8566716d933c3ba91e2cbd58ecd1;hb=e4342ad9de52043cb8f820643794dc44076f9bd9;hp=7491d74ac5622d0b1e54819a3e959c59e287e720;hpb=d599a063b3b453b705925c58180c93e1f9cb3d79;p=tpg%2Facess2.git diff --git a/AcessNative/acesskernel_src/server.c b/AcessNative/acesskernel_src/server.c index 7491d74a..78f7fa13 100644 --- a/AcessNative/acesskernel_src/server.c +++ b/AcessNative/acesskernel_src/server.c @@ -17,6 +17,7 @@ # include #endif #include "../syscalls.h" +//#include #define USE_TCP 0 #define MAX_CLIENTS 16 @@ -36,11 +37,17 @@ typedef struct { // === 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__ @@ -50,21 +57,42 @@ SOCKET gSocket = INVALID_SOCKET; # 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 @@ -72,44 +100,80 @@ tClient *Server_GetClient(int ClientID) 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); + +// Log_Debug("AcessSrv", "Worker got message %p", Client->CurrentRequest); + + if(Client->ClientID != cur_client_id) { +// Log_Debug("AcessSrv", "Client thread ID changed from %i to %i", +// cur_client_id, Client->ClientID); + Threads_SetThread( Client->ClientID ); + cur_client_id = Client->ClientID; + } + + // Debug + { + int callid = Client->CurrentRequest->CallID; + Log_Debug("AcessSrv", "Client %i request %i %s", + Client->ClientID, callid, + callid < N_SYSCALLS ? casSYSCALL_NAMES[callid] : "UNK" + ); + } // Get the response retHeader = SyscallRecieve(Client->CurrentRequest, &retSize); - + 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 + free(Client->CurrentRequest); + 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) @@ -119,12 +183,8 @@ int Server_WorkerThread(void *ClientPtr) } // Free allocated header - free( retHeader ); - - Client->CurrentRequest = 0; - - // Wait for something else - SDL_CondWait(Client->WaitFlag, Client->Mutex); + if( retHeader != &errorHeader ) + free( retHeader ); } #endif } @@ -182,8 +242,13 @@ int SyscallServer(void) 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( ;; ) { @@ -196,7 +261,7 @@ int SyscallServer(void) break ; } - printf("Client connection %x:%i", + Log("Client connection %x:%i\n", ntohl(client.sin_addr), ntohs(client.sin_port) ); @@ -205,9 +270,11 @@ int SyscallServer(void) 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; @@ -215,11 +282,12 @@ int SyscallServer(void) // Hand off to a worker thread // - TODO: Actually have worker threads - printf("%i bytes from %x:%i\n", length, - ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port)); +// Log_Debug("Server", "%i bytes from %x:%i", length, +// 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)); } @@ -238,10 +306,15 @@ int SyscallServer(void) continue; } +// Log_Debug("AcessSrv", "Message from Client %i (%p)", +// client->ClientID, client); + + // Make a copy of the request data + req = malloc(length); + memcpy(req, data, length); client->CurrentRequest = req; SDL_CondSignal(client->WaitFlag); #endif } - return -1; }