Kernel - Added a per-thread timer object to reduce malloc use
[tpg/acess2.git] / AcessNative / ld-acess_src / request.c
1 /*
2  */
3 #define DEBUG   0
4
5
6 #if DEBUG
7 # define DEBUG_S        printf
8 #else
9 # define DEBUG_S(...)
10 # define DONT_INCLUDE_SYSCALL_NAMES
11 #endif
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdio.h>
16 #ifdef __WIN32__
17 # include <windows.h>
18 # include <winsock.h>
19 #else
20 # include <unistd.h>
21 # include <sys/socket.h>
22 # include <netinet/in.h>
23 #endif
24 #include "request.h"
25 #include "../syscalls.h"
26
27 #define USE_TCP 0
28
29 // === PROTOTYPES ===
30 void    SendData(void *Data, int Length);
31  int    ReadData(void *Dest, int MaxLen, int Timeout);
32
33 // === GLOBALS ===
34 #ifdef __WIN32__
35 WSADATA gWinsock;
36 SOCKET  gSocket = INVALID_SOCKET;
37 #else
38 # define INVALID_SOCKET -1
39  int    gSocket = INVALID_SOCKET;
40 #endif
41 // Client ID to pass to server
42 // TODO: Implement such that each thread gets a different one
43  int    giSyscall_ClientID = 0;
44 struct sockaddr_in      gSyscall_ServerAddr;
45
46 // === CODE ===
47 void Request_Preinit(void)
48 {
49         // Set server address
50         memset((void *)&gSyscall_ServerAddr, '\0', sizeof(struct sockaddr_in));
51         gSyscall_ServerAddr.sin_family = AF_INET;
52         gSyscall_ServerAddr.sin_port = htons(SERVER_PORT);
53 }
54
55 int _InitSyscalls(void)
56 {
57         #ifdef __WIN32__
58         /* Open windows connection */
59         if (WSAStartup(0x0101, &gWinsock) != 0)
60         {
61                 fprintf(stderr, "Could not open Windows connection.\n");
62                 exit(0);
63         }
64         #endif
65         
66         #if USE_TCP
67         // Open TCP Connection
68         gSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
69         #else
70         // Open UDP Connection
71         gSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
72         #endif
73         if (gSocket == INVALID_SOCKET)
74         {
75                 fprintf(stderr, "Could not create socket.\n");
76                 #if __WIN32__
77                 WSACleanup();
78                 #endif
79                 exit(0);
80         }
81         
82         #if 0
83         // Set client address
84         memset((void *)&client, '\0', sizeof(struct sockaddr_in));
85         client.sin_family = AF_INET;
86         client.sin_port = htons(0);
87         client.sin_addr.s_addr = htonl(0x7F000001);
88         #endif
89         
90         #if USE_TCP
91         if( connect(gSocket, (struct sockaddr *)&gSyscall_ServerAddr, sizeof(struct sockaddr_in)) < 0 )
92         {
93                 fprintf(stderr, "[ERROR -] Cannot connect to server (localhost:%i)\n", SERVER_PORT);
94                 fprintf(stderr, "[ERROR -] ", giSyscall_ClientID);
95                 perror("_InitSyscalls");
96                 #if __WIN32__
97                 closesocket(gSocket);
98                 WSACleanup();
99                 #else
100                 close(gSocket);
101                 #endif
102                 exit(0);
103         }
104         #endif
105         
106         #if 0
107         // Bind
108         if( bind(gSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1 )
109         {
110                 fprintf(stderr, "Cannot bind address to socket.\n");
111                 #if __WIN32__
112                 closesocket(gSocket);
113                 WSACleanup();
114                 #else
115                 close(gSocket);
116                 #endif
117                 exit(0);
118         }
119         #endif
120         
121         #if !USE_TCP
122         // Ask server for a client ID
123         if( !giSyscall_ClientID )
124         {
125                 tRequestHeader  req;
126                  int    len;
127                 req.ClientID = 0;
128                 req.CallID = 0;
129                 req.NParams = 0;
130                 
131                 SendData(&req, sizeof(req));
132                 
133                 len = ReadData(&req, sizeof(req), 5);
134                 if( len == 0 ) {
135                         fprintf(stderr, "Unable to connect to server (localhost:%i)\n", SERVER_PORT);
136                         exit(-1);
137                 }
138                 
139                 giSyscall_ClientID = req.ClientID;
140         }
141         #endif
142         
143         return 0;
144 }
145
146 /**
147  * \brief Close the syscall socket
148  * \note Used in acess_fork to get a different port number
149  */
150 void _CloseSyscalls(void)
151 {
152         #if __WIN32__
153         closesocket(gSocket);
154         WSACleanup();
155         #else
156         close(gSocket);
157         #endif
158 }
159
160 int SendRequest(tRequestHeader *Request, int RequestSize, int ResponseSize)
161 {
162         if( gSocket == INVALID_SOCKET )
163         {
164                 _InitSyscalls();                
165         }
166         
167         // Set header
168         Request->ClientID = giSyscall_ClientID;
169         
170         #if 0
171         {
172                 for(i=0;i<RequestSize;i++)
173                 {
174                         printf("%02x ", ((uint8_t*)Request)[i]);
175                         if( i % 16 == 15 )      printf("\n");
176                 }
177                 printf("\n");
178         }
179         #endif
180         {
181                  int    i;
182                 char    *data = (char*)&Request->Params[Request->NParams];
183                 DEBUG_S("Request #%i (%s) -", Request->CallID, casSYSCALL_NAMES[Request->CallID]);
184                 for( i = 0; i < Request->NParams; i ++ )
185                 {
186                         switch(Request->Params[i].Type)
187                         {
188                         case ARG_TYPE_INT32:
189                                 DEBUG_S(" 0x%08x", *(uint32_t*)data);
190                                 data += sizeof(uint32_t);
191                                 break;
192                         case ARG_TYPE_INT64:
193                                 DEBUG_S(" 0x%016llx", *(uint64_t*)data);
194                                 data += sizeof(uint64_t);
195                                 break;
196                         case ARG_TYPE_STRING:
197                                 DEBUG_S(" '%s'", (char*)data);
198                                 data += Request->Params[i].Length;
199                                 break;
200                         case ARG_TYPE_DATA:
201                                 DEBUG_S(" %p:0x%x", (char*)data, Request->Params[i].Length);
202                                 if( !(Request->Params[i].Flags & ARG_FLAG_ZEROED) )
203                                         data += Request->Params[i].Length;
204                                 break;
205                         }
206                 }
207                 DEBUG_S("\n");
208         }
209         
210         // Send it off
211         SendData(Request, RequestSize);
212
213         if( Request->CallID == SYS_EXIT )       return 0;
214
215         // Wait for a response (no timeout)
216         return ReadData(Request, ResponseSize, 0);
217 }
218
219 void SendData(void *Data, int Length)
220 {
221          int    len;
222         
223         #if USE_TCP
224         len = send(Data, Length, 0);
225         #else
226         len = sendto(gSocket, Data, Length, 0,
227                 (struct sockaddr*)&gSyscall_ServerAddr, sizeof(gSyscall_ServerAddr));
228         #endif
229         
230         if( len != Length ) {
231                 fprintf(stderr, "[ERROR %i] ", giSyscall_ClientID);
232                 perror("SendData");
233                 exit(-1);
234         }
235 }
236
237 int ReadData(void *Dest, int MaxLength, int Timeout)
238 {
239          int    ret;
240         fd_set  fds;
241         struct timeval  tv;
242         struct timeval  *timeoutPtr;
243         
244         FD_ZERO(&fds);
245         FD_SET(gSocket, &fds);
246         
247         if( Timeout ) {
248                 tv.tv_sec = Timeout;
249                 tv.tv_usec = 0;
250                 timeoutPtr = &tv;
251         }
252         else {
253                 timeoutPtr = NULL;
254         }
255         
256         ret = select(gSocket+1, &fds, NULL, NULL, timeoutPtr);
257         if( ret == -1 ) {
258                 fprintf(stderr, "[ERROR %i] ", giSyscall_ClientID);
259                 perror("ReadData - select");
260                 exit(-1);
261         }
262         
263         if( !ret ) {
264                 printf("[ERROR %i] Timeout reading from socket\n", giSyscall_ClientID);
265                 return 0;       // Timeout
266         }
267         
268         #if USE_TCP
269         ret = recv(gSocket, Dest, MaxLength, 0);
270         #else
271         ret = recvfrom(gSocket, Dest, MaxLength, 0, NULL, 0);
272         #endif
273         
274         if( ret < 0 ) {
275                 fprintf(stderr, "[ERROR %i] ", giSyscall_ClientID);
276                 perror("ReadData");
277                 exit(-1);
278         }
279         
280         DEBUG_S("%i bytes read from socket\n", ret);
281         
282         return ret;
283 }

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