Line data Source code
1 : /********************************************************************\
2 :
3 : Name: MRPC.C
4 : Created by: Stefan Ritt
5 :
6 : Contents: List of MSCB RPC functions with parameters
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 :
12 : #include "mscb.h"
13 :
14 : #ifdef OS_WINNT
15 :
16 : #pragma warning(disable:4996)
17 :
18 : #include <windows.h>
19 : #include <io.h>
20 : #include <fcntl.h>
21 : #include <time.h>
22 : #include <sys/timeb.h>
23 :
24 : #elif defined(OS_LINUX)
25 :
26 : #include <unistd.h>
27 : #include <stdarg.h>
28 : #include <stdlib.h>
29 : #include <sys/types.h>
30 : #include <sys/time.h>
31 : #include <sys/socket.h>
32 : #include <sys/timeb.h>
33 : #include <netdb.h>
34 : #include <netinet/in.h>
35 : #include <arpa/inet.h>
36 : #include <string.h>
37 : #include <fcntl.h>
38 : #include <time.h>
39 : #include <errno.h>
40 :
41 : #define closesocket(s) close(s)
42 :
43 : #endif
44 :
45 : #include <stdio.h>
46 : #include <assert.h>
47 : #include "mscbrpc.h"
48 :
49 : #ifdef HAVE_USB
50 : #include "musbstd.h"
51 : #endif
52 :
53 : typedef int INT;
54 :
55 : /* functions defined in mscb.c */
56 : extern int _debug_flag;
57 : extern void debug_log(const char *format, int start, ...);
58 :
59 : /*------------------------------------------------------------------*/
60 :
61 : static RPC_LIST rpc_list[] = {
62 :
63 : /* common functions */
64 : {RPC_MSCB_INIT, "mscb_init",
65 : {{TID_STRING, RPC_IN | RPC_OUT},
66 : {TID_INT, RPC_IN},
67 : {TID_STRING, RPC_IN},
68 : {TID_INT, RPC_IN},
69 : {0}}},
70 :
71 : {RPC_MSCB_EXIT, "mscb_exit",
72 : {{TID_INT, RPC_IN},
73 : {0}}},
74 :
75 : {RPC_MSCB_GET_DEVICE, "mscb_get_device",
76 : {{TID_INT, RPC_IN},
77 : {TID_STRING, RPC_OUT},
78 : {TID_INT, RPC_IN},
79 : {0}}},
80 :
81 : {RPC_MSCB_REBOOT, "mscb_reboot",
82 : {{TID_INT, RPC_IN},
83 : {TID_INT, RPC_IN},
84 : {TID_INT, RPC_IN},
85 : {TID_INT, RPC_IN},
86 : {0}}},
87 :
88 : {RPC_MSCB_SUBM_RESET, "mscb_subm_reset",
89 : {{TID_INT, RPC_IN},
90 : {0}}},
91 :
92 : {RPC_MSCB_PING, "mscb_ping",
93 : {{TID_INT, RPC_IN},
94 : {TID_INT, RPC_IN},
95 : {TID_INT, RPC_IN},
96 : {0}}},
97 :
98 : {RPC_MSCB_INFO, "mscb_info",
99 : {{TID_INT, RPC_IN},
100 : {TID_INT, RPC_IN},
101 : {TID_STRUCT, RPC_OUT, sizeof(MSCB_INFO)},
102 : {0}}},
103 :
104 : {RPC_MSCB_UPTIME, "mscb_uptime",
105 : {{TID_INT, RPC_IN},
106 : {TID_INT, RPC_IN},
107 : {TID_DWORD, RPC_OUT},
108 : {0}}},
109 :
110 : {RPC_MSCB_INFO_VARIABLE, "mscb_info_variable",
111 : {{TID_INT, RPC_IN},
112 : {TID_INT, RPC_IN},
113 : {TID_INT, RPC_IN},
114 : {TID_STRUCT, RPC_OUT, sizeof(MSCB_INFO_VAR)},
115 : {0}}},
116 :
117 : {RPC_MSCB_SET_NODE_ADDR, "mscb_set_node_addr",
118 : {{TID_INT, RPC_IN},
119 : {TID_INT, RPC_IN},
120 : {TID_INT, RPC_IN},
121 : {TID_INT, RPC_IN},
122 : {TID_SHORT, RPC_IN},
123 : {0}}},
124 :
125 : {RPC_MSCB_SET_GROUP_ADDR, "mscb_set_group_addr",
126 : {{TID_INT, RPC_IN},
127 : {TID_INT, RPC_IN},
128 : {TID_INT, RPC_IN},
129 : {TID_INT, RPC_IN},
130 : {TID_SHORT, RPC_IN},
131 : {0}}},
132 :
133 : {RPC_MSCB_SET_NAME, "mscb_set_name",
134 : {{TID_INT, RPC_IN},
135 : {TID_INT, RPC_IN},
136 : {TID_STRING, RPC_IN},
137 : {0}}},
138 :
139 : {RPC_MSCB_WRITE_GROUP, "mscb_write_group",
140 : {{TID_INT, RPC_IN},
141 : {TID_INT, RPC_IN},
142 : {TID_BYTE, RPC_IN},
143 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
144 : {TID_INT, RPC_IN},
145 : {TID_INT, RPC_IN},
146 : {0}}},
147 :
148 : {RPC_MSCB_WRITE, "mscb_write",
149 : {{TID_INT, RPC_IN},
150 : {TID_INT, RPC_IN},
151 : {TID_BYTE, RPC_IN},
152 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
153 : {TID_INT, RPC_IN},
154 : {0}}},
155 :
156 : {RPC_MSCB_WRITE_RANGE, "mscb_write_range",
157 : {{TID_INT, RPC_IN},
158 : {TID_INT, RPC_IN},
159 : {TID_BYTE, RPC_IN},
160 : {TID_BYTE, RPC_IN},
161 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
162 : {TID_INT, RPC_IN},
163 : {0}}},
164 :
165 : {RPC_MSCB_FLASH, "mscb_flash",
166 : {{TID_INT, RPC_IN},
167 : {TID_INT, RPC_IN},
168 : {TID_INT, RPC_IN},
169 : {TID_INT, RPC_IN},
170 : {0}}},
171 :
172 : {RPC_MSCB_UPLOAD, "mscb_upload",
173 : {{TID_INT, RPC_IN},
174 : {TID_INT, RPC_IN},
175 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
176 : {TID_INT, RPC_IN},
177 : {TID_INT, RPC_IN},
178 : {0}}},
179 :
180 : {RPC_MSCB_VERIFY, "mscb_verify",
181 : {{TID_INT, RPC_IN},
182 : {TID_INT, RPC_IN},
183 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
184 : {TID_INT, RPC_IN},
185 : {0}}},
186 :
187 : {RPC_MSCB_READ, "mscb_read",
188 : {{TID_INT, RPC_IN},
189 : {TID_INT, RPC_IN},
190 : {TID_BYTE, RPC_IN},
191 : {TID_ARRAY, RPC_OUT | RPC_VARARRAY},
192 : {TID_INT, RPC_IN | RPC_OUT},
193 : {TID_INT, RPC_IN},
194 : {0}}},
195 :
196 : {RPC_MSCB_READ_RANGE, "mscb_read_range",
197 : {{TID_INT, RPC_IN},
198 : {TID_INT, RPC_IN},
199 : {TID_BYTE, RPC_IN},
200 : {TID_BYTE, RPC_IN},
201 : {TID_ARRAY, RPC_OUT | RPC_VARARRAY},
202 : {TID_INT, RPC_IN | RPC_OUT},
203 : {0}}},
204 :
205 : {RPC_MSCB_USER, "mscb_user",
206 : {{TID_INT, RPC_IN},
207 : {TID_INT, RPC_IN},
208 : {TID_ARRAY, RPC_IN | RPC_VARARRAY},
209 : {TID_INT, RPC_IN},
210 : {TID_ARRAY, RPC_OUT | RPC_VARARRAY},
211 : {TID_INT, RPC_IN | RPC_OUT},
212 : {0}}},
213 :
214 : {RPC_MSCB_ECHO, "mscb_echo",
215 : {{TID_INT, RPC_IN},
216 : {TID_INT, RPC_IN},
217 : {TID_BYTE, RPC_IN},
218 : {TID_BYTE, RPC_OUT},
219 : {0}}},
220 :
221 : {RPC_MSCB_ADDR, "mscb_addr",
222 : {{TID_INT, RPC_IN},
223 : {TID_INT, RPC_IN},
224 : {TID_INT, RPC_IN},
225 : {TID_INT, RPC_IN},
226 : {0}}},
227 :
228 : {RPC_MSCB_SET_TIME, "mscb_set_time",
229 : {{TID_INT, RPC_IN},
230 : {TID_INT, RPC_IN},
231 : {TID_INT, RPC_IN},
232 : {TID_INT, RPC_IN},
233 : {0}}},
234 :
235 : {0}
236 :
237 : };
238 :
239 : /*------------------------------------------------------------------*/
240 :
241 : /* data type sizes */
242 : INT mtid_size[] = {
243 : 0, /* tid == 0 not defined */
244 : 1, /* TID_BYTE unsigned byte 0 255 */
245 : 1, /* TID_SBYTE signed byte -128 127 */
246 : 1, /* TID_CHAR single character 0 255 */
247 : 2, /* TID_WORD two bytes 0 65535 */
248 : 2, /* TID_SHORT signed word -32768 32767 */
249 : 4, /* TID_DWORD four bytes 0 2^32-1 */
250 : 4, /* TID_INT signed dword -2^31 2^31-1 */
251 : 4, /* TID_BOOL four bytes bool 0 1 */
252 : 4, /* TID_FLOAT 4 Byte float format */
253 : 8, /* TID_DOUBLE 8 Byte float format */
254 : 1, /* TID_BITFIELD 8 Bits Bitfield 00000000 11111111 */
255 : 0, /* TID_STRING zero terminated string */
256 : 0, /* TID_ARRAY variable length array of unkown type */
257 : 0, /* TID_STRUCT C structure */
258 : 0, /* TID_KEY key in online database */
259 : 0 /* TID_LINK link in online database */
260 : };
261 :
262 : /*------------------------------------------------------------------*/
263 :
264 : #define N_MAX_CONNECTION 10
265 : #define NET_BUFFER_SIZE 100000
266 :
267 : static int rpc_sock[N_MAX_CONNECTION];
268 : static char rpc_net_buffer[NET_BUFFER_SIZE];
269 :
270 : /*------------------------------------------------------------------*/
271 :
272 0 : void mdrain_tcp(int sock)
273 : /* drain socket connection from any old data */
274 : {
275 : char buffer[100];
276 :
277 : fd_set readfds;
278 : struct timeval timeout;
279 : int status;
280 :
281 :
282 : /* first receive header */
283 : do {
284 0 : FD_ZERO(&readfds);
285 0 : FD_SET(sock, &readfds);
286 :
287 0 : timeout.tv_sec = 0;
288 0 : timeout.tv_usec = 0;
289 :
290 : do {
291 0 : status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
292 0 : } while (status == -1); /* dont return if an alarm signal was cought */
293 :
294 0 : if (!FD_ISSET(sock, &readfds))
295 0 : return;
296 :
297 0 : status = recv(sock, buffer, sizeof(buffer), 0);
298 :
299 0 : if (status <= 0)
300 0 : return ;
301 :
302 0 : } while (1);
303 : }
304 :
305 : /*------------------------------------------------------------------*/
306 :
307 0 : int mrecv_tcp(int sock, char *buffer, int buffer_size)
308 : {
309 : INT param_size, n_received, n;
310 : NET_COMMAND *nc;
311 :
312 : fd_set readfds;
313 : struct timeval timeout;
314 : int status;
315 : int millisec;
316 :
317 0 : if (buffer_size < (int)sizeof(NET_COMMAND_HEADER)) {
318 0 : printf("mrecv_tcp_server: buffer too small\n");
319 0 : return -1;
320 : }
321 :
322 : /* fixed timeout of 2 sec for the moment */
323 0 : millisec = 2000;
324 :
325 : /* first receive header */
326 0 : n_received = 0;
327 : do {
328 0 : FD_ZERO(&readfds);
329 0 : FD_SET(sock, &readfds);
330 :
331 0 : timeout.tv_sec = millisec / 1000;
332 0 : timeout.tv_usec = (millisec % 1000) * 1000;
333 :
334 : do {
335 0 : status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
336 0 : } while (status == -1); /* dont return if an alarm signal was cought */
337 :
338 0 : if (!FD_ISSET(sock, &readfds))
339 0 : return n_received;
340 :
341 0 : n = recv(sock, buffer + n_received, sizeof(NET_COMMAND_HEADER), 0);
342 :
343 0 : if (n <= 0)
344 0 : return n;
345 :
346 0 : n_received += n;
347 :
348 0 : } while (n_received < (int)sizeof(NET_COMMAND_HEADER));
349 :
350 : /* now receive parameters */
351 :
352 0 : nc = (NET_COMMAND *) buffer;
353 0 : param_size = nc->header.param_size;
354 0 : n_received = 0;
355 :
356 0 : if (param_size == 0)
357 0 : return sizeof(NET_COMMAND_HEADER);
358 :
359 : do {
360 0 : FD_ZERO(&readfds);
361 0 : FD_SET(sock, &readfds);
362 :
363 0 : timeout.tv_sec = millisec / 1000;
364 0 : timeout.tv_usec = (millisec % 1000) * 1000;
365 :
366 : do {
367 0 : status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
368 0 : } while (status == -1); /* dont return if an alarm signal was cought */
369 :
370 0 : if (!FD_ISSET(sock, &readfds))
371 0 : return n_received;
372 :
373 0 : n = recv(sock, buffer + sizeof(NET_COMMAND_HEADER) + n_received,
374 0 : param_size - n_received, 0);
375 :
376 0 : if (n <= 0)
377 0 : return n;
378 :
379 0 : n_received += n;
380 0 : } while (n_received < param_size);
381 :
382 0 : return sizeof(NET_COMMAND_HEADER) + param_size;
383 : }
384 :
385 : /*------------------------------------------------------------------*/
386 :
387 0 : int msend_tcp(int sock, char *buffer, int buffer_size)
388 : {
389 : int count, status;
390 :
391 : /* drain receive queue if any late packet arrived in meantime */
392 0 : mdrain_tcp(sock);
393 :
394 : /* transfer fragments until complete buffer is transferred */
395 :
396 0 : for (count = 0; (int) count < (int) buffer_size - NET_TCP_SIZE;) {
397 0 : status = send(sock, buffer + count, NET_TCP_SIZE, 0);
398 0 : if (status != -1)
399 0 : count += status;
400 : else
401 0 : return status;
402 : }
403 :
404 0 : while (count < buffer_size) {
405 0 : status = send(sock, buffer + count, buffer_size - count, 0);
406 0 : if (status != -1)
407 0 : count += status;
408 : else
409 0 : return status;
410 : }
411 :
412 0 : return count;
413 : }
414 :
415 : /*------------------------------------------------------------------*/
416 :
417 0 : int server_execute(int index, void *prpc_param[])
418 : {
419 : int status;
420 :
421 0 : switch (index) {
422 0 : default:
423 0 : abort();
424 : break;
425 :
426 0 : case RPC_MSCB_INIT:
427 0 : status = mscb_init(CSTRING(0), CINT(1), CSTRING(2), CINT(3));
428 0 : break;
429 :
430 0 : case RPC_MSCB_EXIT:
431 0 : status = mscb_exit(CINT(0));
432 0 : break;
433 :
434 0 : case RPC_MSCB_REBOOT:
435 0 : status = mscb_reboot(CINT(0), CINT(1), CINT(2), CINT(3));
436 0 : break;
437 :
438 0 : case RPC_MSCB_SUBM_RESET:
439 0 : status = mscb_subm_reset(CINT(0));
440 0 : break;
441 :
442 0 : case RPC_MSCB_PING:
443 0 : status = mscb_ping(CINT(0), CWORD(1), CINT(2), CINT(3));
444 0 : break;
445 :
446 0 : case RPC_MSCB_INFO:
447 0 : status = mscb_info(CINT(0), CWORD(1), (MSCB_INFO*)CARRAY(2));
448 0 : break;
449 :
450 0 : case RPC_MSCB_INFO_VARIABLE:
451 0 : status = mscb_info_variable(CINT(0), CSHORT(1), CBYTE(2), (MSCB_INFO_VAR*)CARRAY(3));
452 0 : break;
453 :
454 0 : case RPC_MSCB_UPTIME:
455 0 : status = mscb_uptime(CINT(0), CWORD(1), CPDWORD(2));
456 0 : break;
457 :
458 0 : case RPC_MSCB_SET_NODE_ADDR:
459 0 : status = mscb_set_node_addr(CINT(0), CINT(1), CINT(2), CINT(3), CSHORT(4));
460 0 : break;
461 :
462 0 : case RPC_MSCB_SET_GROUP_ADDR:
463 0 : status = mscb_set_group_addr(CINT(0), CINT(1), CINT(2), CINT(3), CSHORT(4));
464 0 : break;
465 :
466 0 : case RPC_MSCB_SET_NAME:
467 0 : status = mscb_set_name(CINT(0), CSHORT(1), CSTRING(2));
468 0 : break;
469 :
470 0 : case RPC_MSCB_WRITE_GROUP:
471 0 : status = mscb_write_group(CINT(0), CSHORT(1), CBYTE(2), CARRAY(3), CINT(4));
472 0 : break;
473 :
474 0 : case RPC_MSCB_WRITE:
475 0 : status = mscb_write(CINT(0), CSHORT(1), CBYTE(2), CARRAY(3), CINT(4));
476 0 : break;
477 :
478 0 : case RPC_MSCB_WRITE_NO_RETRIES:
479 0 : status = mscb_write(CINT(0), CSHORT(1), CBYTE(2), CARRAY(3), CINT(4));
480 0 : break;
481 :
482 0 : case RPC_MSCB_WRITE_RANGE:
483 0 : status = mscb_write_range(CINT(0), CSHORT(1), CBYTE(2), CBYTE(3), CARRAY(4), CINT(5));
484 0 : break;
485 :
486 0 : case RPC_MSCB_FLASH:
487 0 : status = mscb_flash(CINT(0), CINT(1), CINT(2), CINT(3));
488 0 : break;
489 :
490 0 : case RPC_MSCB_SET_BAUD:
491 0 : status = mscb_set_baud(CINT(0), CINT(1));
492 0 : break;
493 :
494 0 : case RPC_MSCB_UPLOAD:
495 0 : status = mscb_upload(CINT(0), CSHORT(1), CSHORT(2), CSTRING(3), CINT(4));
496 0 : break;
497 :
498 0 : case RPC_MSCB_READ:
499 0 : status = mscb_read(CINT(0), CSHORT(1), CBYTE(2), CARRAY(3), CPINT(4));
500 0 : break;
501 :
502 0 : case RPC_MSCB_READ_NO_RETRIES:
503 0 : status = mscb_read_no_retries(CINT(0), CSHORT(1), CBYTE(2), CARRAY(3), CPINT(4));
504 0 : break;
505 :
506 0 : case RPC_MSCB_READ_RANGE:
507 : status =
508 0 : mscb_read_range(CINT(0), CSHORT(1), CBYTE(2), CBYTE(3), CARRAY(4), CPINT(5));
509 0 : break;
510 :
511 0 : case RPC_MSCB_ECHO:
512 0 : status = mscb_echo(CINT(0), CSHORT(1), CBYTE(2), CPBYTE(3));
513 0 : break;
514 :
515 0 : case RPC_MSCB_USER:
516 0 : status = mscb_user(CINT(0), CSHORT(1), CARRAY(2), CINT(3), CARRAY(4), CPINT(5));
517 0 : break;
518 :
519 0 : case RPC_MSCB_ADDR:
520 0 : status = mscb_addr(CINT(0), CINT(1), CSHORT(2), CINT(3), CINT(4));
521 0 : break;
522 :
523 0 : case RPC_MSCB_SET_TIME:
524 0 : status = mscb_set_time(CINT(0), CINT(1), CINT(2), CINT(3));
525 0 : break;
526 : }
527 :
528 0 : return status;
529 : }
530 :
531 : /*------------------------------------------------------------------*/
532 :
533 0 : int mrpc_execute(int sock, char *buffer)
534 : {
535 : INT i, index, routine_id, status;
536 : char *in_param_ptr, *out_param_ptr, *last_param_ptr;
537 : INT tid, flags;
538 : NET_COMMAND *nc_in, *nc_out;
539 : INT param_size, max_size;
540 : void *prpc_param[20];
541 : char return_buffer[NET_BUFFER_SIZE];
542 :
543 : /* extract pointer array to parameters */
544 0 : nc_in = (NET_COMMAND *) buffer;
545 0 : nc_out = (NET_COMMAND *) return_buffer;
546 :
547 : /* find entry in rpc_list */
548 0 : routine_id = nc_in->header.routine_id;
549 :
550 0 : for (i = 0;; i++)
551 0 : if (rpc_list[i].id == 0 || rpc_list[i].id == routine_id)
552 : break;
553 0 : index = i;
554 0 : if (rpc_list[i].id == 0) {
555 0 : printf("mrpc_execute: Invalid rpc ID (%d)\n", routine_id);
556 0 : return RPC_INVALID_ID;
557 : }
558 :
559 0 : in_param_ptr = nc_in->param;
560 0 : out_param_ptr = nc_out->param;
561 :
562 0 : for (i = 0; rpc_list[index].param[i].tid != 0; i++) {
563 0 : tid = rpc_list[index].param[i].tid;
564 0 : flags = rpc_list[index].param[i].flags;
565 :
566 0 : if (flags & RPC_IN) {
567 0 : param_size = ALIGN8(mtid_size[tid]);
568 :
569 0 : if (tid == TID_STRING || tid == TID_LINK)
570 0 : param_size = ALIGN8(1 + strlen((char *) (in_param_ptr)));
571 :
572 0 : if (flags & RPC_VARARRAY) {
573 : /* for arrays, the size is stored as a INT in front of the array */
574 0 : param_size = *((INT *) in_param_ptr);
575 0 : param_size = ALIGN8(param_size);
576 :
577 0 : in_param_ptr += ALIGN8(sizeof(INT));
578 : }
579 :
580 0 : if (tid == TID_STRUCT)
581 0 : param_size = ALIGN8(rpc_list[index].param[i].n);
582 :
583 0 : prpc_param[i] = in_param_ptr;
584 :
585 0 : in_param_ptr += param_size;
586 : }
587 :
588 0 : if (flags & RPC_OUT) {
589 0 : param_size = ALIGN8(mtid_size[tid]);
590 :
591 0 : if (flags & RPC_VARARRAY || tid == TID_STRING) {
592 : /* save maximum array length */
593 0 : max_size = *((INT *) in_param_ptr);
594 0 : max_size = ALIGN8(max_size);
595 :
596 0 : *((INT *) out_param_ptr) = max_size;
597 :
598 : /* save space for return array length */
599 0 : out_param_ptr += ALIGN8(sizeof(INT));
600 :
601 : /* use maximum array length from input */
602 0 : param_size += max_size;
603 : }
604 :
605 0 : if (rpc_list[index].param[i].tid == TID_STRUCT)
606 0 : param_size = ALIGN8(rpc_list[index].param[i].n);
607 :
608 0 : if ((POINTER_T) out_param_ptr - (POINTER_T) nc_out + param_size > NET_BUFFER_SIZE) {
609 : printf
610 0 : ("mrpc_execute: return parameters (%d) too large for network buffer (%d)\n",
611 0 : (int)((POINTER_T) out_param_ptr - (POINTER_T) nc_out + param_size), NET_BUFFER_SIZE);
612 0 : return RPC_EXCEED_BUFFER;
613 : }
614 :
615 : /* if parameter goes both directions, copy input to output */
616 0 : if (rpc_list[index].param[i].flags & RPC_IN)
617 0 : memcpy(out_param_ptr, prpc_param[i], param_size);
618 :
619 0 : prpc_param[i] = out_param_ptr;
620 0 : out_param_ptr += param_size;
621 : }
622 :
623 : }
624 :
625 0 : last_param_ptr = out_param_ptr;
626 :
627 : /*********************************\
628 : * call dispatch function *
629 : \*********************************/
630 0 : status = server_execute(routine_id, prpc_param);
631 :
632 : /* compress variable length arrays */
633 0 : out_param_ptr = nc_out->param;
634 0 : for (i = 0; rpc_list[index].param[i].tid != 0; i++)
635 0 : if (rpc_list[index].param[i].flags & RPC_OUT) {
636 0 : tid = rpc_list[index].param[i].tid;
637 0 : flags = rpc_list[index].param[i].flags;
638 0 : param_size = ALIGN8(mtid_size[tid]);
639 :
640 0 : if (tid == TID_STRING) {
641 0 : max_size = *((INT *) out_param_ptr);
642 0 : param_size = strlen((char *) prpc_param[i]) + 1;
643 0 : param_size = ALIGN8(param_size);
644 :
645 : /* move string ALIGN8(sizeof(INT)) left */
646 0 : memcpy(out_param_ptr, out_param_ptr + ALIGN8(sizeof(INT)), param_size);
647 :
648 : /* move remaining parameters to end of string */
649 0 : memcpy(out_param_ptr + param_size,
650 0 : out_param_ptr + max_size + ALIGN8(sizeof(INT)),
651 0 : (POINTER_T) last_param_ptr -
652 0 : ((POINTER_T) out_param_ptr + max_size + ALIGN8(sizeof(INT))));
653 : }
654 :
655 0 : if (flags & RPC_VARARRAY) {
656 : /* store array length at current out_param_ptr */
657 0 : max_size = *((INT *) out_param_ptr);
658 0 : param_size = *((INT *) prpc_param[i + 1]);
659 0 : *((INT *) out_param_ptr) = param_size;
660 :
661 0 : out_param_ptr += ALIGN8(sizeof(INT));
662 :
663 0 : param_size = ALIGN8(param_size);
664 :
665 : /* move remaining parameters to end of array */
666 0 : memcpy(out_param_ptr + param_size,
667 0 : out_param_ptr + max_size + ALIGN8(sizeof(INT)),
668 0 : (POINTER_T) last_param_ptr -
669 0 : ((POINTER_T) out_param_ptr + max_size + ALIGN8(sizeof(INT))));
670 : }
671 :
672 0 : if (tid == TID_STRUCT)
673 0 : param_size = ALIGN8(rpc_list[index].param[i].n);
674 :
675 0 : out_param_ptr += param_size;
676 : }
677 :
678 : /* send return parameters */
679 0 : param_size = (POINTER_T) out_param_ptr - (POINTER_T) nc_out->param;
680 0 : nc_out->header.routine_id = status;
681 0 : nc_out->header.param_size = param_size;
682 :
683 0 : status = msend_tcp(sock, return_buffer, sizeof(NET_COMMAND_HEADER) + param_size);
684 :
685 0 : if (status < 0) {
686 0 : printf("mrpc_execute: msend_tcp() failed\n");
687 0 : return RPC_NET_ERROR;
688 : }
689 :
690 0 : return RPC_SUCCESS;
691 : }
692 :
693 : /*------------------------------------------------------------------*/
694 :
695 0 : int mrpc_connect(char *host_name, int port)
696 : {
697 : INT status, sock;
698 : struct sockaddr_in bind_addr;
699 : struct hostent *phe;
700 :
701 : #ifdef _MSC_VER
702 : {
703 : WSADATA WSAData;
704 :
705 : /* Start windows sockets */
706 : if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
707 : return -1;
708 : }
709 : #endif
710 :
711 : /* create a new socket for connecting to remote server */
712 0 : sock = socket(AF_INET, SOCK_STREAM, 0);
713 0 : if (sock == -1) {
714 0 : perror("mrpc_connect,socket");
715 0 : return -1;
716 : }
717 :
718 : /* let OS choose any port number */
719 0 : memset(&bind_addr, 0, sizeof(bind_addr));
720 0 : bind_addr.sin_family = AF_INET;
721 0 : bind_addr.sin_addr.s_addr = 0;
722 0 : bind_addr.sin_port = 0;
723 :
724 0 : status = bind(sock, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
725 0 : if (status < 0) {
726 0 : perror("mrpc_connect,bind");
727 0 : return -1;
728 : }
729 :
730 : /* connect to remote node */
731 0 : memset(&bind_addr, 0, sizeof(bind_addr));
732 0 : bind_addr.sin_family = AF_INET;
733 0 : bind_addr.sin_addr.s_addr = 0;
734 0 : bind_addr.sin_port = htons((short) port);
735 :
736 0 : phe = gethostbyname(host_name);
737 0 : if (phe == NULL) {
738 0 : printf("Cannot find host name \"%s\"\n", host_name);
739 0 : return -1;
740 : }
741 :
742 0 : memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
743 :
744 0 : status = connect(sock, (const struct sockaddr *)&bind_addr, sizeof(bind_addr));
745 0 : if (status != 0) {
746 0 : if (errno)
747 0 : perror("mrpc_connect,connect");
748 0 : return -1;
749 : }
750 :
751 0 : return sock;
752 : }
753 :
754 : /*------------------------------------------------------------------*/
755 :
756 0 : int mrpc_disconnect(int sock)
757 : {
758 0 : closesocket(sock);
759 0 : return RPC_SUCCESS;
760 : }
761 :
762 : /*------------------------------------------------------------------*/
763 :
764 0 : void mrpc_va_arg(va_list * arg_ptr, int arg_type, void *arg)
765 : {
766 0 : switch (arg_type) {
767 : /* On the stack, the minimum parameter size is sizeof(int).
768 : To avoid problems on little endian systems, treat all
769 : smaller parameters as int's */
770 0 : case TID_BYTE:
771 : case TID_SBYTE:
772 : case TID_CHAR:
773 : case TID_WORD:
774 : case TID_SHORT:
775 0 : *((int *) arg) = va_arg(*arg_ptr, int);
776 0 : break;
777 :
778 0 : case TID_INT:
779 : case TID_BOOL:
780 0 : *((INT *) arg) = va_arg(*arg_ptr, INT);
781 0 : break;
782 :
783 0 : case TID_DWORD:
784 0 : *((unsigned int *) arg) = va_arg(*arg_ptr, unsigned int);
785 0 : break;
786 :
787 : /* float variables are passed as double by the compiler */
788 0 : case TID_FLOAT:
789 0 : *((float *) arg) = (float) va_arg(*arg_ptr, double);
790 0 : break;
791 :
792 0 : case TID_DOUBLE:
793 0 : *((double *) arg) = va_arg(*arg_ptr, double);
794 0 : break;
795 :
796 0 : case TID_ARRAY:
797 0 : *((char **) arg) = va_arg(*arg_ptr, char *);
798 0 : break;
799 : }
800 0 : }
801 :
802 : /*------------------------------------------------------------------*/
803 :
804 0 : int mrpc_call(int sock, const int routine_id, ...)
805 : {
806 : va_list ap, aptmp;
807 : char str[256], arg[8], arg_tmp[8];
808 : INT arg_type;
809 : INT i, index, status;
810 : INT param_size, arg_size, send_size;
811 : INT tid, flags;
812 : fd_set readfds;
813 : struct timeval timeout;
814 : char *param_ptr;
815 : int bpointer;
816 : NET_COMMAND *nc;
817 : time_t now;
818 :
819 0 : nc = (NET_COMMAND *) rpc_net_buffer;
820 0 : nc->header.routine_id = routine_id;
821 :
822 0 : for (i = 0;; i++)
823 0 : if (rpc_list[i].id == routine_id || rpc_list[i].id == 0)
824 : break;
825 0 : index = i;
826 0 : if (rpc_list[i].id == 0) {
827 0 : printf("mrpc_call: invalid rpc ID (%d)\n", routine_id);
828 0 : return RPC_INVALID_ID;
829 : }
830 :
831 0 : time(&now);
832 0 : strcpy(str, ctime(&now));
833 0 : str[19] = 0;
834 0 : debug_log("%s %s (", 0, str + 4, rpc_list[i].name);
835 :
836 : /* examine variable argument list and convert it to parameter array */
837 0 : va_start(ap, routine_id);
838 :
839 0 : for (i = 0, param_ptr = nc->param; rpc_list[index].param[i].tid != 0; i++) {
840 0 : tid = rpc_list[index].param[i].tid;
841 0 : flags = rpc_list[index].param[i].flags;
842 :
843 0 : bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
844 0 : (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
845 0 : tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
846 :
847 0 : if (bpointer)
848 0 : arg_type = TID_ARRAY;
849 : else
850 0 : arg_type = tid;
851 :
852 : /* floats are passed as doubles, at least under NT */
853 0 : if (tid == TID_FLOAT && !bpointer)
854 0 : arg_type = TID_DOUBLE;
855 :
856 : /* get pointer to argument */
857 0 : mrpc_va_arg(&ap, arg_type, arg);
858 :
859 0 : if (flags & RPC_IN) {
860 0 : if (bpointer)
861 0 : arg_size = mtid_size[tid];
862 : else
863 0 : arg_size = mtid_size[arg_type];
864 :
865 : /* for strings, the argument size depends on the string length */
866 0 : if (tid == TID_STRING || tid == TID_LINK)
867 0 : arg_size = 1 + strlen((char *) *((char **) arg));
868 :
869 : /* for varibale length arrays, the size is given by
870 : the next parameter on the stack */
871 0 : if (flags & RPC_VARARRAY) {
872 0 : memcpy(&aptmp, &ap, sizeof(ap));
873 0 : mrpc_va_arg(&aptmp, TID_ARRAY, arg_tmp);
874 :
875 0 : if (flags & RPC_OUT)
876 0 : arg_size = *((INT *) * ((void **) arg_tmp));
877 : else
878 0 : arg_size = *((INT *) arg_tmp);
879 :
880 0 : *((INT *) param_ptr) = ALIGN8(arg_size);
881 0 : param_ptr += ALIGN8(sizeof(INT));
882 : }
883 :
884 0 : if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
885 0 : arg_size = rpc_list[index].param[i].n;
886 :
887 : /* always align parameter size */
888 0 : param_size = ALIGN8(arg_size);
889 :
890 0 : if ((POINTER_T) param_ptr - (POINTER_T) nc + param_size > NET_BUFFER_SIZE) {
891 : printf
892 0 : ("mrpc_call: parameters (%d) too large for network buffer (%d)\n",
893 0 : (int)((POINTER_T) param_ptr - (POINTER_T) nc + param_size), NET_BUFFER_SIZE);
894 0 : return RPC_EXCEED_BUFFER;
895 : }
896 :
897 0 : if (bpointer)
898 0 : memcpy(param_ptr, (void *) *((void **) arg), arg_size);
899 : else {
900 : /* floats are passed as doubles on most systems */
901 0 : if (tid != TID_FLOAT)
902 0 : memcpy(param_ptr, arg, arg_size);
903 : else
904 0 : *((float *) param_ptr) = (float) *((double *) arg);
905 : }
906 :
907 0 : switch (tid) {
908 0 : case TID_BYTE:
909 0 : debug_log(" %d", 0, *((unsigned char *) param_ptr));
910 0 : break;
911 0 : case TID_SBYTE:
912 0 : debug_log(" %d", 0, *((char *) param_ptr));
913 0 : break;
914 0 : case TID_CHAR:
915 0 : debug_log(" %c", 0, *((char *) param_ptr));
916 0 : break;
917 0 : case TID_WORD:
918 0 : debug_log(" %d", 0, *((unsigned short *) param_ptr));
919 0 : break;
920 0 : case TID_SHORT:
921 0 : debug_log(" %d", 0, *((short *) param_ptr));
922 0 : break;
923 0 : case TID_DWORD:
924 0 : debug_log(" %d", 0, *((unsigned int *) param_ptr));
925 0 : break;
926 0 : case TID_INT:
927 0 : debug_log(" %d", 0, *((int *) param_ptr));
928 0 : break;
929 0 : case TID_BOOL:
930 0 : debug_log(" %d", 0, *((int *) param_ptr));
931 0 : break;
932 0 : case TID_FLOAT:
933 0 : debug_log(" %f", 0, *((float *) param_ptr));
934 0 : break;
935 0 : case TID_DOUBLE:
936 0 : debug_log(" %lf", 0, *((double *) param_ptr));
937 0 : break;
938 0 : case TID_STRING:
939 0 : debug_log(" %s", 0, (char *) param_ptr);
940 0 : break;
941 :
942 0 : default:
943 0 : debug_log(" *", 0);
944 0 : break;
945 : }
946 :
947 0 : param_ptr += param_size;
948 :
949 : }
950 : }
951 :
952 0 : debug_log(" ) : (", 0);
953 :
954 0 : va_end(ap);
955 :
956 0 : nc->header.param_size = (POINTER_T) param_ptr - (POINTER_T) nc->param;
957 :
958 0 : send_size = nc->header.param_size + sizeof(NET_COMMAND_HEADER);
959 :
960 : /* send and wait for reply on send socket */
961 0 : i = msend_tcp(sock, (char *) nc, send_size);
962 0 : if (i != send_size) {
963 0 : printf("mrpc_call: msend_tcp() failed\n");
964 0 : return RPC_NET_ERROR;
965 : }
966 :
967 : /* make some timeout checking */
968 0 : FD_ZERO(&readfds);
969 0 : FD_SET(sock, &readfds);
970 :
971 0 : timeout.tv_sec = RPC_TIMEOUT / 1000;
972 0 : timeout.tv_usec = (RPC_TIMEOUT % 1000) * 1000;
973 :
974 0 : select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
975 :
976 0 : if (!FD_ISSET(sock, &readfds)) {
977 0 : printf("mrpc_call: rpc timeout, routine = \"%s\"\n", rpc_list[index].name);
978 :
979 : /* disconnect to avoid that the reply to this mrpc_call comes at
980 : the next mrpc_call */
981 0 : closesocket(sock);
982 :
983 0 : return RPC_ERR_TIMEOUT;
984 : }
985 :
986 : /* receive result on send socket */
987 0 : i = mrecv_tcp(sock, rpc_net_buffer, NET_BUFFER_SIZE);
988 :
989 0 : if (i <= 0) {
990 0 : printf("mrpc_call: mrecv_tcp() failed, routine = \"%s\"\n", rpc_list[index].name);
991 0 : return RPC_NET_ERROR;
992 : }
993 :
994 : /* extract result variables and place it to argument list */
995 0 : status = nc->header.routine_id;
996 :
997 0 : va_start(ap, routine_id);
998 :
999 0 : for (i = 0, param_ptr = nc->param; rpc_list[index].param[i].tid != 0; i++) {
1000 0 : tid = rpc_list[index].param[i].tid;
1001 0 : flags = rpc_list[index].param[i].flags;
1002 :
1003 0 : bpointer = (flags & RPC_POINTER) || (flags & RPC_OUT) ||
1004 0 : (flags & RPC_FIXARRAY) || (flags & RPC_VARARRAY) ||
1005 0 : tid == TID_STRING || tid == TID_ARRAY || tid == TID_STRUCT || tid == TID_LINK;
1006 :
1007 0 : if (bpointer)
1008 0 : arg_type = TID_ARRAY;
1009 : else
1010 0 : arg_type = rpc_list[index].param[i].tid;
1011 :
1012 0 : if (tid == TID_FLOAT && !bpointer)
1013 0 : arg_type = TID_DOUBLE;
1014 :
1015 0 : mrpc_va_arg(&ap, arg_type, arg);
1016 :
1017 0 : if (rpc_list[index].param[i].flags & RPC_OUT) {
1018 0 : tid = rpc_list[index].param[i].tid;
1019 0 : arg_size = mtid_size[tid];
1020 :
1021 0 : if (tid == TID_STRING || tid == TID_LINK)
1022 0 : arg_size = strlen((char *) (param_ptr)) + 1;
1023 :
1024 0 : if (flags & RPC_VARARRAY) {
1025 0 : arg_size = *((INT *) param_ptr);
1026 0 : param_ptr += ALIGN8(sizeof(INT));
1027 : }
1028 :
1029 0 : if (tid == TID_STRUCT || (flags & RPC_FIXARRAY))
1030 0 : arg_size = rpc_list[index].param[i].n;
1031 :
1032 : /* return parameters are always pointers */
1033 0 : if (*((char **) arg))
1034 0 : memcpy((void *) *((char **) arg), param_ptr, arg_size);
1035 :
1036 : /* parameter size is always aligned */
1037 0 : param_size = ALIGN8(arg_size);
1038 :
1039 0 : switch (tid) {
1040 0 : case TID_BYTE:
1041 0 : debug_log(" %d", 0, *((unsigned char *) param_ptr));
1042 0 : break;
1043 0 : case TID_SBYTE:
1044 0 : debug_log(" %d", 0, *((char *) param_ptr));
1045 0 : break;
1046 0 : case TID_CHAR:
1047 0 : debug_log(" %c", 0, *((char *) param_ptr));
1048 0 : break;
1049 0 : case TID_WORD:
1050 0 : debug_log(" %d", 0, *((unsigned short *) param_ptr));
1051 0 : break;
1052 0 : case TID_SHORT:
1053 0 : debug_log(" %d", 0, *((short *) param_ptr));
1054 0 : break;
1055 0 : case TID_DWORD:
1056 0 : debug_log(" %d", 0, *((unsigned int *) param_ptr));
1057 0 : break;
1058 0 : case TID_INT:
1059 0 : debug_log(" %d", 0, *((int *) param_ptr));
1060 0 : break;
1061 0 : case TID_BOOL:
1062 0 : debug_log(" %d", 0, *((int *) param_ptr));
1063 0 : break;
1064 0 : case TID_FLOAT:
1065 0 : debug_log(" %f", 0, *((float *) param_ptr));
1066 0 : break;
1067 0 : case TID_DOUBLE:
1068 0 : debug_log(" %lf", 0, *((double *) param_ptr));
1069 0 : break;
1070 0 : case TID_STRING:
1071 0 : debug_log(" %s", 0, (char *) param_ptr);
1072 0 : break;
1073 :
1074 0 : default:
1075 0 : debug_log(" *", 0);
1076 0 : break;
1077 : }
1078 :
1079 0 : param_ptr += param_size;
1080 : }
1081 : }
1082 :
1083 0 : debug_log(" ) : %d\n", 0, status);
1084 :
1085 0 : va_end(ap);
1086 :
1087 0 : return status;
1088 : }
1089 :
1090 : /*------------------------------------------------------------------*/
1091 :
1092 : extern void mscb_cleanup(int sock);
1093 : int _server_sock = 0;
1094 :
1095 0 : void mrpc_server_loop(void)
1096 : {
1097 : int i, status, sock, lsock, len, flag;
1098 : struct sockaddr_in serv_addr, acc_addr;
1099 : char str[256];
1100 : struct hostent *phe;
1101 : fd_set readfds;
1102 : struct timeval timeout;
1103 :
1104 : #ifdef _MSC_VER
1105 : {
1106 : WSADATA WSAData;
1107 :
1108 : /* Start windows sockets */
1109 : if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
1110 : return;
1111 : }
1112 : #endif
1113 :
1114 : /* create a new socket */
1115 0 : lsock = socket(AF_INET, SOCK_STREAM, 0);
1116 :
1117 0 : if (lsock == -1) {
1118 0 : perror("mrpc_server_loop");
1119 0 : return;
1120 : }
1121 :
1122 : /* bind local node name and port to socket */
1123 0 : memset(&serv_addr, 0, sizeof(serv_addr));
1124 0 : serv_addr.sin_family = AF_INET;
1125 :
1126 0 : serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
1127 0 : serv_addr.sin_port = htons((short) MSCB_RPC_PORT);
1128 :
1129 : /* try reusing address */
1130 0 : flag = 1;
1131 0 : setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof(INT));
1132 :
1133 0 : status = bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
1134 0 : if (status < 0) {
1135 0 : perror("mrpc_server_loop");
1136 0 : return;
1137 : }
1138 :
1139 : /* listen for connection */
1140 0 : status = listen(lsock, SOMAXCONN);
1141 0 : if (status < 0) {
1142 0 : perror("mrpc_server_loop");
1143 0 : return;
1144 : }
1145 :
1146 0 : printf("Server listening...\n");
1147 : do {
1148 0 : FD_ZERO(&readfds);
1149 0 : FD_SET(lsock, &readfds);
1150 :
1151 0 : for (i = 0; i < N_MAX_CONNECTION; i++)
1152 0 : if (rpc_sock[i] > 0)
1153 0 : FD_SET(rpc_sock[i], &readfds);
1154 :
1155 0 : timeout.tv_sec = 0;
1156 0 : timeout.tv_usec = 100000;
1157 :
1158 0 : status = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
1159 :
1160 0 : if (FD_ISSET(lsock, &readfds)) {
1161 0 : len = sizeof(acc_addr);
1162 : #ifdef _MSC_VER
1163 : sock = accept(lsock, (struct sockaddr *) &acc_addr, (int *) &len);
1164 : #else
1165 0 : sock = accept(lsock, (struct sockaddr *) &acc_addr, (socklen_t *) &len);
1166 : #endif
1167 :
1168 : /* find new entry in socket table */
1169 0 : for (i = 0; i < N_MAX_CONNECTION; i++)
1170 0 : if (rpc_sock[i] == 0)
1171 0 : break;
1172 :
1173 0 : if (i == N_MAX_CONNECTION) {
1174 0 : printf("Maximum number of connections exceeded\n");
1175 0 : closesocket(sock);
1176 : } else {
1177 0 : rpc_sock[i] = sock;
1178 :
1179 0 : phe = gethostbyaddr((char *) &acc_addr.sin_addr, 4, AF_INET);
1180 0 : if (phe != NULL)
1181 0 : strcpy(str, phe->h_name);
1182 : else
1183 0 : strcpy(str, (char *) inet_ntoa(acc_addr.sin_addr));
1184 :
1185 0 : printf("Open new connection from %s\n", str);
1186 : }
1187 : } else {
1188 : /* check if open connection received data */
1189 0 : for (i = 0; i < N_MAX_CONNECTION; i++)
1190 0 : if (rpc_sock[i] > 0 && FD_ISSET(rpc_sock[i], &readfds)) {
1191 0 : len = mrecv_tcp(rpc_sock[i], rpc_net_buffer, NET_BUFFER_SIZE);
1192 0 : if (len < 0) {
1193 : /* remove stale fd */
1194 0 : mscb_cleanup(rpc_sock[i]);
1195 :
1196 : /* close broken connection */
1197 0 : printf("Close connection\n");
1198 0 : closesocket(rpc_sock[i]);
1199 0 : rpc_sock[i] = 0;
1200 : } else {
1201 0 : _server_sock = rpc_sock[i];
1202 0 : mrpc_execute(rpc_sock[i], rpc_net_buffer);
1203 : }
1204 : }
1205 : }
1206 :
1207 0 : } while (1);
1208 : }
|