AcessNative - Mouse implimented, woot!
[tpg/acess2.git] / AcessNative / acesskernel_src / server.c
index 2e3f3a9..5ee6967 100644 (file)
@@ -9,16 +9,22 @@
 #include <string.h>
 #include <SDL/SDL.h>
 #ifdef __WIN32__
+# define _WIN32_WINNT 0x0501
 # include <windows.h>
-# include <winsock.h>
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# define close(fd)     closesocket(fd)
+typedef int    socklen_t;
 #else
 # include <unistd.h>
 # include <sys/socket.h>
 # include <netinet/in.h>
-# include <arpa/inet.h>        // inet_ntop
+# include <netdb.h>    // getaddrinfo
 #endif
+#define DONT_INCLUDE_SYSCALL_NAMES
 #include "../syscalls.h"
-//#include <debug.h>
+#include <logdebug.h>  // acess but std
+#include <errno.h>
 
 #define        USE_TCP 1
 #define MAX_CLIENTS    16
@@ -41,10 +47,8 @@ typedef struct {
 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, ...);
-extern void    Log_Warning(const char *Subsys, const char *Message, ...);
+extern void    *Threads_GetThread(int TID);
+extern void    Threads_PostEvent(void *Thread, uint32_t Event);
 
 // === PROTOTYPES ===
 tClient        *Server_GetClient(int ClientID);
@@ -118,6 +122,7 @@ tClient *Server_GetClient(int ClientID)
                ret->Mutex = SDL_CreateMutex();
                SDL_mutexP( ret->Mutex );
                #endif
+               Log_Debug("Server", "Creating worker for %p", ret);
                ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
        }
        
@@ -127,34 +132,69 @@ tClient *Server_GetClient(int ClientID)
 int Server_WorkerThread(void *ClientPtr)
 {
        tClient *Client = ClientPtr;
-       
+
+       Log_Debug("Server", "Worker %p", ClientPtr);    
+
        #if USE_TCP
-       for( ;; )
+       while( *((volatile typeof(Client->Socket)*)&Client->Socket) == 0 )
+               ;
+       Threads_SetThread( Client->ClientID );
+       
+       while( Client->ClientID != -1 )
        {
                fd_set  fds;
-                int    nfd = Client->Socket;
+                int    nfd = Client->Socket+1;
                FD_ZERO(&fds);
                FD_SET(Client->Socket, &fds);
                
-               select(nfd, &fds, NULL, NULL, NULL);    // TODO: Timeouts?
-               
+               int rv = select(nfd, &fds, NULL, NULL, NULL);   // TODO: Timeouts?
+               if(rv < 0) {
+                       perror("select");
+                       continue ;
+               }
+               Log_Debug("Server", "%p: rv=%i", Client, rv);           
+
                if( FD_ISSET(Client->Socket, &fds) )
                {
                        const int       ciMaxParamCount = 6;
                        char    lbuf[sizeof(tRequestHeader) + ciMaxParamCount*sizeof(tRequestValue)];
                        tRequestHeader  *hdr = (void*)lbuf;
-                       size_t  len = recv(Client->Socket, hdr, sizeof(*hdr), 0);
-                       if( len != sizeof(hdr) ) {
+                       size_t  len = recv(Client->Socket, (void*)hdr, sizeof(*hdr), 0);
+//                     Log_Debug("Server", "%i bytes of header", len);
+                       if( len == 0 )  break;
+                       if( len == -1 ) {
+                               perror("recv header");
+//                             Log_Warning("Server", "recv() error - %s", strerror(errno));
+                               break;
+                       }
+                       if( len != sizeof(*hdr) ) {
                                // Oops?
+                               Log_Warning("Server", "FD%i bad sized (%i != exp %i)",
+                                       Client->Socket, len, sizeof(*hdr));
+                               continue ;
                        }
 
                        if( hdr->NParams > ciMaxParamCount ) {
                                // Oops.
+                               Log_Warning("Server", "FD%i too many params (%i > max %i)",
+                                       Client->Socket, hdr->NParams, ciMaxParamCount);
+                               break ;
                        }
 
-                       len = recv(Client->Socket, hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
-                       if( len != hdr->NParams*sizeof(tRequestValue) ) {
-                               // Oops.
+                       if( hdr->NParams > 0 )
+                       {
+                               len = recv(Client->Socket, (void*)hdr->Params, hdr->NParams*sizeof(tRequestValue), 0);
+//                             Log_Debug("Server", "%i bytes of params", len);
+                               if( len != hdr->NParams*sizeof(tRequestValue) ) {
+                                       // Oops.
+                                       perror("recv params");
+                                       Log_Warning("Sever", "Recieving params failed");
+                                       break ;
+                               }
+                       }
+                       else
+                       {
+//                             Log_Debug("Server", "No params?");
                        }
 
                        // Get buffer size
@@ -173,19 +213,40 @@ int Server_WorkerThread(void *ClientPtr)
                        // Allocate full buffer
                        hdr = malloc(bufsize);
                        memcpy(hdr, lbuf, hdrsize);
-                       len = recv(Client->Socket, hdr->Params + hdr->NParams, bufsize - hdrsize, 0);
-                       if( len != bufsize - hdrsize ) {
-                               // Oops?
+                       if( bufsize > hdrsize )
+                       {
+                               size_t  rem = bufsize - hdrsize;
+                               char    *ptr = (void*)( hdr->Params + hdr->NParams );
+                               while( rem )
+                               {
+                                       len = recv(Client->Socket, ptr, rem, 0);
+//                                     Log_Debug("Server", "%i bytes of data", len);
+                                       if( len == -1 ) {
+                                               // Oops?
+                                               perror("recv data");
+                                               Log_Warning("Sever", "Recieving data failed");
+                                               break ;
+                                       }
+                                       rem -= len;
+                                       ptr += len;
+                               }
+                               if( rem ) {
+                                       break;
+                               }
                        }
+//                     else
+//                             Log_Debug("Server", "no data");
 
                         int    retlen;
                        tRequestHeader  *retHeader;
                        retHeader = SyscallRecieve(hdr, &retlen);
                        if( !retHeader ) {
                                // Some sort of error
+                               Log_Warning("Server", "SyscallRecieve failed?");
+                               continue ;
                        }
                        
-                       send(Client->Socket, retHeader, retlen, 0); 
+                       send(Client->Socket, (void*)retHeader, retlen, 0); 
 
                        // Clean up
                        free(hdr);
@@ -197,11 +258,13 @@ int Server_WorkerThread(void *ClientPtr)
         int    retSize = 0;
         int    sentSize;
         int    cur_client_id = 0;
-       for( ;; )
+       while( Client->ClientID != -1 )
        {
                // Wait for something to do
-               while( Client->CurrentRequest == NULL )
+               if( Client->CurrentRequest == NULL )
                        SDL_CondWait(Client->WaitFlag, Client->Mutex);
+               if( Client->CurrentRequest == NULL )
+                       continue ;
                
 //             Log_Debug("AcessSrv", "Worker got message %p", Client->CurrentRequest);
                
@@ -259,6 +322,8 @@ int Server_WorkerThread(void *ClientPtr)
                        free( retHeader );
        }
        #endif
+       Log_Notice("Server", "Terminated Worker %p", ClientPtr);        
+       return 0;
 }
 
 int SyscallServer(void)
@@ -319,6 +384,24 @@ int SyscallServer(void)
        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;
+}
+
 int Server_ListenThread(void *Unused)
 {      
        // Wait for something to do :)
@@ -334,17 +417,24 @@ int Server_ListenThread(void *Unused)
                }
 
                char    addrstr[4*8+8+1];
-               inet_ntop(clientaddr.sin_family, &clientaddr.sin_addr, addrstr, sizeof(addrstr));
-               Log_Debug("Server", "Client connection %s:%i\n", addrstr, ntohs(clientaddr.sin_port));
+               getnameinfo((struct sockaddr*)&clientaddr, sizeof(clientaddr),
+                       addrstr, sizeof(addrstr), NULL, 0, NI_NUMERICHOST);
+               Log_Debug("Server", "Client connection %s:%i", addrstr, ntohs(clientaddr.sin_port));
                
                // Perform auth
                size_t  len;
                tRequestAuthHdr authhdr;
-               len = recv(clientSock, &authhdr, sizeof(authhdr), 0);
+               len = recv(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
                if( len != sizeof(authhdr) ) {
                        // Some form of error?
+                       Log_Warning("Server", "Client auth block bad size (%i != exp %i)",
+                               len, sizeof(authhdr));
+                       close(clientSock);
+                       continue ;
                }
                
+               Log_Debug("Server", "Client assumed PID %i", authhdr.pid);
+
                tClient *client;
                if( authhdr.pid == 0 ) {
                        // Allocate PID and client structure/thread
@@ -356,17 +446,25 @@ int Server_ListenThread(void *Unused)
                        // Get client structure and make sure it's unused
                        // - Auth token / verifcation?
                        client = Server_GetClient(authhdr.pid);
+                       if( !client ) {
+                               Log_Warning("Server", "Can't allocate a client struct for %s:%i",
+                                       addrstr, clientaddr.sin_port);
+                               close(clientSock);
+                               continue ;
+                       }
                        if( client->Socket != 0 ) {
                                Log_Warning("Server", "Client (%i)%p owned by FD%i but %s:%i tried to use it",
                                        authhdr.pid, client, addrstr, clientaddr.sin_port);
-                               authhdr.pid = 0;
+                               close(clientSock);
+                               continue;
                        }
                        else {
                                client->Socket = clientSock;
                        }
                }
+               Log_Debug("Server", "Client given PID %i - info %p", authhdr.pid, client);
                
-               len = send(clientSock, &authhdr, sizeof(authhdr), 0);
+               len = send(clientSock, (void*)&authhdr, sizeof(authhdr), 0);
                if( len != sizeof(authhdr) ) {
                        // Ok, this is an error
                        perror("Sending auth reply");

UCC git Repository :: git.ucc.asn.au