3 * - Acess kernel emulation on another OS using SDL and UDP
16 # include <sys/socket.h>
17 # include <netinet/in.h>
19 #include "../syscalls.h"
22 #define MAX_CLIENTS 16
27 SDL_Thread *WorkerThread;
30 tRequestHeader *CurrentRequest;
31 struct sockaddr_in ClientAddr;
38 extern tRequestHeader *SyscallRecieve(tRequestHeader *Request, int *ReturnLength);
41 tClient *Server_GetClient(int ClientID);
42 int Server_WorkerThread(void *ClientPtr);
43 int SyscallServer(void);
48 SOCKET gSocket = INVALID_SOCKET;
50 # define INVALID_SOCKET -1
51 int gSocket = INVALID_SOCKET;
53 int giServer_NextClientID = 1;
54 tClient gaServer_Clients[MAX_CLIENTS];
57 tClient *Server_GetClient(int ClientID)
62 for( i = 0; i < MAX_CLIENTS; i ++ )
64 if( gaServer_Clients[i].ClientID == ClientID ) {
65 ret = &gaServer_Clients[i];
70 // Uh oh, no free slots
71 // TODO: Dynamic allocation
77 ret->ClientID = giServer_NextClientID ++;
78 ret->CurrentRequest = NULL;
80 if( !ret->WorkerThread ) {
81 ret->WorkerThread = SDL_CreateThread( Server_WorkerThread, ret );
82 ret->WaitFlag = SDL_CreateCond();
83 ret->Mutex = SDL_CreateMutex();
84 SDL_mutexP( ret->Mutex );
88 return &gaServer_Clients[i];
91 int Server_WorkerThread(void *ClientPtr)
93 tClient *Client = ClientPtr;
94 tRequestHeader *retHeader;
102 // Wait for something to do
103 while( !Client->CurrentRequest ) ;
106 retHeader = SyscallRecieve(Client->CurrentRequest, &retSize);
109 // Return an error to the client
110 printf("Error returned by SyscallRecieve\n");
114 sentSize = sendto(gSocket, retHeader, retSize, 0,
115 (struct sockaddr*)&Client->ClientAddr, sizeof(Client->ClientAddr)
117 if( sentSize != retSize ) {
118 perror("Server_WorkerThread - send");
121 // Free allocated header
124 Client->CurrentRequest = 0;
126 // Wait for something else
127 SDL_CondWait(Client->WaitFlag, Client->Mutex);
132 int SyscallServer(void)
134 struct sockaddr_in server;
137 /* Open windows connection */
138 if (WSAStartup(0x0101, &gWinsock) != 0)
140 fprintf(stderr, "Could not open Windows connection.\n");
146 // Open TCP Connection
147 gSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
149 // Open UDP Connection
150 gSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
152 if (gSocket == INVALID_SOCKET)
154 fprintf(stderr, "Could not create socket.\n");
161 // Set server address
162 memset(&server, 0, sizeof(struct sockaddr_in));
163 server.sin_family = AF_INET;
164 server.sin_port = htons(SERVER_PORT);
165 server.sin_addr.s_addr = htonl(INADDR_ANY);
168 if( bind(gSocket, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) == -1 )
170 fprintf(stderr, "Cannot bind address to socket.\n");
171 perror("SyscallServer - bind");
173 closesocket(gSocket);
185 Log_Notice("Syscall", "Listening on 0.0.0.0:%i\n", SERVER_PORT);
187 // Wait for something to do :)
191 struct sockaddr_in client;
192 uint clientSize = sizeof(client);
193 int clientSock = accept(gSocket, (struct sockaddr*)&client, &clientSize);
194 if( clientSock < 0 ) {
195 perror("SyscallServer - accept");
199 printf("Client connection %x:%i",
200 ntohl(client.sin_addr), ntohs(client.sin_port)
205 tRequestHeader *req = (void*)data;
206 struct sockaddr_in addr;
207 uint clientSize = sizeof(addr);
208 int length = recvfrom(gSocket, data, BUFSIZ, 0, (struct sockaddr*)&addr, &clientSize);
212 perror("SyscallServer - recv");
216 // Hand off to a worker thread
217 // - TODO: Actually have worker threads
218 printf("%i bytes from %x:%i\n", length,
219 ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
221 client = Server_GetClient(req->ClientID);
222 if( req->ClientID == 0 )
224 memcpy(&client->ClientAddr, &addr, sizeof(addr));
226 else if( memcmp(&client->ClientAddr, &addr, sizeof(addr)) != 0 )
228 printf("ClientID %i used by %x:%i\n",
229 client->ClientID, ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port));
230 printf(" actually owned by %x:%i\n",
231 ntohl(client->ClientAddr.sin_addr.s_addr), ntohs(client->ClientAddr.sin_port));
235 if( client->CurrentRequest ) {
236 printf("Worker thread for %x:%i is busy\n",
237 ntohl(client->ClientAddr.sin_addr.s_addr), ntohs(client->ClientAddr.sin_port));
241 client->CurrentRequest = req;
242 SDL_CondSignal(client->WaitFlag);