#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
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);
ret->Mutex = SDL_CreateMutex();
SDL_mutexP( ret->Mutex );
#endif
+ Log_Debug("Server", "Creating worker for %p", ret);
ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
}
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
// 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);
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);
free( retHeader );
}
#endif
+ Log_Notice("Server", "Terminated Worker %p", ClientPtr);
+ return 0;
}
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 :)
}
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
// 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");