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

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