source: branches/profile/AISC_COM/C/server.c

Last change on this file was 12591, checked in by epruesse, 10 years ago

AISC now uses arb_open_socket, arb_socket_write and …_read.

  • SIGPIPE is disabled via setsockopt on mac and via MSG_NOSIGNAL on Linux.
  • No more usleep in write loop.
  • arb_socket_write returns -1 on failure (needed change to client.c as aisc_s_write and aisc_c_write differed in error handling)
  • common.[hc] are gone
  • fixes build failure in build 797
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.8 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <errno.h>
5#include <string.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <sys/un.h>
9#include <netinet/in.h>
10#include <netinet/tcp.h>
11#include <arpa/inet.h>
12#include <sys/stat.h>
13#include <limits.h>
14
15#include "trace.h"
16
17#define FD_SET_TYPE
18
19#if defined(DEBUG)
20// #define SERVER_TERMINATE_ON_CONNECTION_CLOSE
21#endif // DEBUG
22
23#include <signal.h>
24#include <sys/time.h>
25#include <netdb.h>
26#include <setjmp.h>
27
28#include <aisc_com.h>
29// AISC_MKPT_PROMOTE:#include <aisc_func_types.h>
30#include "server.h"
31
32#include <SigHandler.h>
33#include <arb_cs.h>
34#include <static_assert.h>
35
36// AISC_MKPT_PROMOTE:#ifndef _STDIO_H
37// AISC_MKPT_PROMOTE:#include <stdio.h>
38// AISC_MKPT_PROMOTE:#endif
39
40#define aisc_assert(cond) arb_assert(cond)
41
42#define AISC_SERVER_OK 1
43#define AISC_SERVER_FAULT 0
44#define MAX_QUEUE_LEN 5
45
46#define AISC_MAGIC_NUMBER_FILTER 0xffffff00
47
48// -------------------------
49//      some structures
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55    struct Socinf {
56        Socinf                *next;
57        int                    socket;
58        aisc_destroy_callback  destroy_callback;
59        long                   destroy_clientdata;
60        int                    lasttime;
61    };
62
63#ifdef __cplusplus
64}
65#endif
66
67struct pollfd;
68struct Hs_struct : virtual Noncopyable {
69    int            hso;
70    Socinf        *soci;
71    struct pollfd *fds;
72    unsigned long  nfds;
73    int            nsoc;
74    int            timeout;
75    int            fork;
76    char          *unix_name;
77
78    Hs_struct()
79        : hso(0),
80          soci(NULL),
81          fds(NULL),
82          nfds(0),
83          nsoc(0),
84          timeout(0),
85          fork(0),
86          unix_name(NULL)
87    {}
88    ~Hs_struct() { freenull(unix_name); }
89};
90
91struct aisc_bytes_list {
92    char            *data;
93    int              size;
94    aisc_bytes_list *next;
95};
96
97static aisc_bytes_list *aisc_server_bytes_first;
98static aisc_bytes_list *aisc_server_bytes_last;
99
100
101extern char  *aisc_object_names[];
102extern char **aisc_attribute_names_list[];
103
104extern aisc_talking_func_long  *aisc_talking_functions_get[];
105extern aisc_talking_func_long  *aisc_talking_functions_set[];
106extern aisc_talking_func_longp *aisc_talking_functions_copy[];
107extern aisc_talking_func_longp *aisc_talking_functions_find[];
108extern aisc_talking_func_longp *aisc_talking_functions_create[];
109extern aisc_talking_func_long   aisc_talking_functions_delete[];
110
111const char *aisc_server_error;
112
113const int   ERRORBUFSIZE = 256;
114static char error_buf[ERRORBUFSIZE];
115
116static int        aisc_server_con;
117static Hs_struct *aisc_server_hs;
118
119// -----------------------
120//      error handling
121
122void aisc_server_errorf(const char *templat, ...) {
123    // goes to header: __ATTR__FORMAT(1)
124    va_list parg;
125
126    va_start(parg, templat);
127    int printed = vsprintf(error_buf, templat, parg);
128
129    if (printed >= ERRORBUFSIZE) {
130        fprintf(stderr,
131                "Fatal: buffer overflow in aisc_server_errorf\n"
132                "Error was: ");
133        vfprintf(stderr, templat, parg);
134        fputs("\nTerminating..\n", stderr);
135        fflush(stderr);
136        exit(EXIT_FAILURE);
137    }
138    va_end(parg);
139
140    aisc_server_error = error_buf;
141}
142
143
144// -----------------------------
145//      valid memory tester
146
147static bool    sigsegv_occurred = false;
148static bool    catch_sigsegv    = 0;
149static jmp_buf return_after_segv;
150
151static const char *test_address_valid(void *address, long key)
152{
153    /* tests whether 'address' is a valid readable address
154     * if 'key' != 0 -> check if 'address' contains 'key'
155     *
156     * returns NULL or error string
157     */
158
159    static char  buf[256];
160    char        *result = buf;
161
162    sigsegv_occurred = false;
163    catch_sigsegv    = true;
164
165    // ----------------------------------------
166    // start of critical section
167    // (need volatile for modified local auto variables, see man longjump)
168    volatile long i       = 0;
169    volatile int  trapped = sigsetjmp(return_after_segv, 1);
170
171    if (trapped == 0) {       // normal execution
172        i = *(long *)address; // here a SIGSEGV may happen. Execution will continue in else-branch
173    }
174    else {                             // return after SEGV
175        aisc_assert(trapped == 666);   // oops - SEGV did not occur in mem access above!
176        aisc_assert(sigsegv_occurred); // oops - wrong handler installed ?
177    }
178    // end of critical section
179    // ----------------------------------------
180
181    catch_sigsegv = false;
182
183    if (sigsegv_occurred) {
184        sprintf(buf, "AISC memory manager error: can't access memory at address %p", address);
185    }
186    else {
187        if (key && i != key) {
188            sprintf(buf, "AISC memory manager error: object at address %p has wrong type (found: 0x%lx, expected: 0x%lx)",
189                    address, i, key);
190        }
191        else {
192            result = NULL;  // ok, address (and key) valid
193        }
194    }
195
196    return result;
197}
198
199static SigHandler old_sigsegv_handler;
200
201__ATTR__NORETURN static void aisc_server_sigsegv(int sig) {
202    sigsegv_occurred = true;
203    if (catch_sigsegv) {
204        siglongjmp(return_after_segv, 666); // never returns
205    }
206    // unexpected SEGV
207
208    UNINSTALL_SIGHANDLER(SIGSEGV, aisc_server_sigsegv, old_sigsegv_handler, "aisc_server_sigsegv");
209    old_sigsegv_handler(sig);
210    aisc_assert(0); // oops - old handler returned
211    abort();
212}
213
214
215// ----------------------------------------------
216//      object+attr_names for error messages
217
218
219const char *aisc_get_object_names(long i)
220{
221    if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_object_names[i])) {
222        return "<unknown object>";
223    }
224    return aisc_object_names[i];
225}
226
227static const char *aisc_get_object_attribute(long i, long j)
228{
229    if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_attribute_names_list[i])) {
230        return "<null>";
231    }
232    if ((j<0) || (j>=AISC_MAX_ATTR) || (!aisc_attribute_names_list[i][j])) {
233        return "<unknown attribute>";
234    }
235    return aisc_attribute_names_list[i][j];
236}
237
238Hs_struct *open_aisc_server(const char *path, int timeout, int fork) {
239    Hs_struct *hs = new Hs_struct;
240    if (hs) {
241        hs->timeout = timeout;
242        hs->fork    = fork;
243
244        static int  so;
245        const char *err = arb_open_socket(path, false, &so, &hs->unix_name);
246
247        if (err) {
248            if (*err) printf("Error in open_aisc_server: %s\n", err);
249            shutdown(so, SHUT_RDWR);
250            close(so);
251            delete hs; hs = NULL;
252        }
253        else {
254            // install signal handlers
255            fprintf(stderr, "Installing signal handler from open_aisc_server\n"); fflush(stderr);
256            old_sigsegv_handler = INSTALL_SIGHANDLER(SIGSEGV, aisc_server_sigsegv, "open_aisc_server");
257
258            aisc_server_bytes_first = 0;
259            aisc_server_bytes_last  = 0;
260            // simply take first address
261            if (listen(so, MAX_QUEUE_LEN) < 0) {
262                printf("Error in open_aisc_server: could not listen (errno=%i)\n", errno);
263                delete hs; hs = NULL;
264            }
265            else {
266                hs->hso = so;
267            }
268        }
269    }
270    return hs;
271}
272
273static void aisc_s_add_to_bytes_queue(char *data, int size) {
274    aisc_bytes_list *bl;
275    bl = (aisc_bytes_list *)calloc(sizeof(aisc_bytes_list), 1);
276    bl->data = data;
277    bl->size = size;
278
279    if (aisc_server_bytes_first) {
280        aisc_server_bytes_last->next = bl;
281        aisc_server_bytes_last = bl;
282    }
283    else {
284        aisc_server_bytes_first = bl;
285        aisc_server_bytes_last = bl;
286    }
287}
288
289static int aisc_s_send_bytes_queue(int socket) {
290    aisc_bytes_list *bl, *bl_next;
291    for (bl = aisc_server_bytes_first; bl; bl=bl_next) {
292        bl_next = bl->next;
293        if (arb_socket_write(socket, (char *)bl->data, bl->size)) return 1;
294        free(bl);
295    };
296    aisc_server_bytes_first = aisc_server_bytes_last = NULL;
297    return 0;
298}
299
300static long aisc_talking_get(long *in_buf, int size, long *out_buf, int) { // handles AISC_GET
301    aisc_server_error = NULL;
302
303    long in_pos      = 0;
304    long out_pos     = 0;
305    long object      = in_buf[in_pos++];
306    long object_type = (in_buf[in_pos] & AISC_OBJ_TYPE_MASK);
307   
308
309    if (object_type > (AISC_MAX_OBJECT*0x10000)) {
310        aisc_server_error = "UNKNOWN OBJECT";
311        object = 0;
312    }
313    else {
314        aisc_server_error = test_address_valid((void *)object, object_type);
315    }
316    object_type = object_type >> (16);
317
318    AISC_DUMP_SEP();
319    AISC_DUMP(aisc_talking_get, int, object_type);
320
321    long attribute = 0;
322    long erg       = 0;
323    while (!aisc_server_error && (in_pos < size)) {
324        long code = in_buf[in_pos];
325        long type = (code & AISC_VAR_TYPE_MASK);
326        attribute = (code & AISC_ATTR_MASK);
327
328        aisc_talking_func_long *functions = aisc_talking_functions_get[object_type];
329
330        if (!functions) {
331            aisc_server_error = "OBJECT HAS NO ATTRIBUTES";
332            attribute = 0;
333            break;
334        }
335        if (attribute > AISC_MAX_ATTR) {
336            sprintf(error_buf, "ATTRIBUTE %lx OUT of RANGE", attribute);
337            aisc_server_error = error_buf;
338            attribute = 0;
339            break;
340        }
341        aisc_talking_func_long function = functions[attribute];
342        if (!function) {
343            sprintf(error_buf, "DON'T KNOW ATTRIBUTE %li",
344                    attribute);
345            aisc_server_error = error_buf;
346            break;
347        }
348
349        AISC_DUMP(aisc_talking_get, int, attribute);
350        AISC_DUMP(aisc_talking_get, int, type);
351
352        double_xfer derg;
353        STATIC_ASSERT(sizeof(derg.as_double) <= sizeof(derg.as_int));
354       
355        if (type == AISC_TYPE_DOUBLE) {
356            aisc_talking_func_double dfunction = (aisc_talking_func_double) function;
357            derg.as_double = dfunction(object);
358        }
359        else {
360            erg = function(object);
361        }
362        if (aisc_server_error) {
363            break;
364        }
365        switch (type) {
366            case AISC_TYPE_INT:
367            case AISC_TYPE_COMMON:
368                AISC_DUMP(aisc_talking_get, int, erg);
369                out_buf[out_pos++] = erg;
370                break;
371
372            case AISC_TYPE_DOUBLE:
373                AISC_DUMP(aisc_talking_get, double, derg.as_double);
374                out_buf[out_pos++] = derg.as_int[0];
375                out_buf[out_pos++] = derg.as_int[1];
376                break;
377
378            case AISC_TYPE_STRING: {
379                if (!erg) erg = (long) "(null)";
380                long len = strlen((char *)erg);
381                if (len > AISC_MAX_STRING_LEN) {
382                    erg = (long) "(string too long)";
383                    len = strlen((char *)erg);
384                }
385
386                AISC_DUMP(aisc_talking_get, charPtr, (char*)erg);
387
388                len += 1;
389                len /= sizeof(long);
390                len++;
391                out_buf[out_pos++] = len;
392                strcpy((char *)&out_buf[out_pos], (char *)erg);
393                out_pos += len;
394                break;
395            }
396            case AISC_TYPE_BYTES:
397                {
398                    bytestring *bs = (bytestring *)erg;
399
400                    AISC_DUMP(aisc_talking_get, int, bs->size);
401#if defined(DUMP_COMMUNICATION)
402                    aisc_dump_hex("aisc_talking_get bytestring: ", bs->data, bs->size);
403#endif // DUMP_COMMUNICATION
404
405                    if (bs->data && bs->size)
406                        aisc_s_add_to_bytes_queue(bs->data, bs->size);
407                    out_buf[out_pos++] = bs->size;              // size
408                    break;
409                }
410            default:
411                aisc_server_error = "UNKNOWN TYPE";
412                break;
413        }
414        in_pos++;
415    }
416    if (aisc_server_error) {
417        sprintf((char *) out_buf, "AISC_GET_SERVER_ERROR %s: OBJECT:%s   ATTRIBUTE:%s",
418                aisc_server_error,
419                aisc_get_object_names(object_type),
420                aisc_get_object_attribute(object_type, attribute));
421        return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
422    }
423    return out_pos;
424}
425
426static int aisc_server_index = -1;
427
428static void aisc_talking_set_index(int */*obj*/, int i) {
429    aisc_server_index = i;
430}
431
432int aisc_talking_get_index(int u, int o)
433{
434    if (aisc_server_index==-1) {
435        aisc_server_error = "AISC_SERVER_ERROR MISSING AN AISC_INDEX";
436        return -1;
437    }
438    if ((aisc_server_index<u) || (aisc_server_index>=o)) {
439        sprintf(error_buf, "AISC_SET_SERVER_ERROR: INDEX %i IS OUT OF RANGE [%i,%i]",
440                aisc_server_index, u, o);
441        aisc_server_error = error_buf;
442    }
443
444    AISC_DUMP(aisc_talking_get_index, int, aisc_server_index);
445
446    return aisc_server_index;
447}
448
449static long aisc_talking_sets(long *in_buf, int size, long *out_buf, long *object, int object_type) {
450    int   blen, bsize;
451    long  in_pos, out_pos;
452    long  code, attribute, type;
453
454    aisc_talking_func_long function;
455    aisc_talking_func_long *functions;
456    in_pos = out_pos = 0;
457    aisc_server_index = -1;
458    aisc_server_error   = NULL;
459    object_type         = (object_type & AISC_OBJ_TYPE_MASK);
460
461    attribute = 0;
462    if (object_type > (AISC_MAX_OBJECT*0x10000)) {
463        object_type = 0;
464        aisc_server_error = "UNKNOWN OBJECT";
465    }
466    else {
467        aisc_server_error = test_address_valid((void *)object, object_type);
468    }
469    object_type = object_type>>(16);
470    functions   = aisc_talking_functions_set[object_type];
471    if (!functions) {
472        sprintf(error_buf, "OBJECT %x HAS NO ATTRIBUTES",
473                object_type);
474        aisc_server_error = error_buf;
475    }
476
477    AISC_DUMP_SEP();
478    AISC_DUMP(aisc_talking_sets, int, object_type);
479
480    while (!aisc_server_error && (in_pos<size)) {
481        code      = in_buf[in_pos++];
482        attribute = code & AISC_ATTR_MASK;
483        type      = code & AISC_VAR_TYPE_MASK;
484        if (attribute > AISC_MAX_ATTR) {
485            sprintf(error_buf, "ATTRIBUTE %li DOESN'T EXIST",
486                    attribute);
487            aisc_server_error = error_buf;
488            attribute = 0;
489            break;
490        }
491        if (code == AISC_INDEX) {
492            function = (aisc_talking_func_long)aisc_talking_set_index;
493        }
494        else {
495            function = functions[attribute];
496        }
497        if (!function) {
498            sprintf(error_buf, "ATTRIBUTE %li DOESN'T EXIST",
499                    attribute);
500            aisc_server_error = error_buf;
501            break;
502        }
503
504        AISC_DUMP(aisc_talking_sets, int, attribute);
505        AISC_DUMP(aisc_talking_sets, int, type);
506
507        switch (type) {
508            case AISC_TYPE_INT:
509            case AISC_TYPE_COMMON:
510
511                AISC_DUMP(aisc_talking_sets, long, in_buf[in_pos]);
512
513                function((long)object, in_buf[in_pos++]);
514                break;
515            case AISC_TYPE_DOUBLE:
516                {
517                    double_xfer derg;
518                    derg.as_int[0] = in_buf[in_pos++];
519                    derg.as_int[1] = in_buf[in_pos++];
520                   
521                    AISC_DUMP(aisc_talking_sets, double, derg.as_double);
522
523                    function((long)object, derg.as_double);
524                    break;
525                }
526            case AISC_TYPE_STRING:
527                {
528                    char *str = strdup((char *)&(in_buf[in_pos+1]));
529
530                    AISC_DUMP(aisc_talking_sets, charPtr, str);
531
532                    function((long)object, str);
533                    in_pos    += in_buf[in_pos]+1;
534                    break;
535                }
536            case AISC_TYPE_BYTES:
537                bsize = (int)in_buf[in_pos++];
538
539                AISC_DUMP(aisc_talking_sets, int, bsize);
540
541                if (bsize) {
542                    long *ptr = (long*)calloc(sizeof(char), bsize);
543                    blen = arb_socket_read(aisc_server_con, (char *)ptr, bsize);
544                    if (bsize!=blen) {
545                        aisc_server_error = "CONNECTION PROBLEMS IN BYTESTRING";
546                        free(ptr);
547                    }
548                    else {
549                        bytestring bs;
550                        bs.data = (char *)ptr;
551                        bs.size = bsize;
552
553#if defined(DUMP_COMMUNICATION)
554                        aisc_dump_hex("aisc_talking_sets bytestring: ", (char*)ptr, bsize);
555#endif // DUMP_COMMUNICATION
556
557                        function((long)object, &bs);
558                    }
559                }
560                else {
561                    function((long)object, 0);
562                }
563                break;
564            default:
565                aisc_server_error = "UNKNOWN TYPE";
566                break;
567        }
568    }
569    if (aisc_server_error) {
570        sprintf((char *) out_buf, "AISC_SET_SERVER_ERROR %s: OBJECT:%s   ATTRIBUTE:%s",
571                aisc_server_error,
572                aisc_get_object_names(object_type),
573                aisc_get_object_attribute(object_type, attribute));
574        return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
575    }
576    return 0;
577}
578
579static long aisc_talking_set(long *in_buf, int size, long *out_buf, int) { // handles AISC_SET
580    aisc_server_error = NULL;
581
582    int  in_pos      = 0;
583    long object      = in_buf[in_pos++];
584    int  object_type = ((int)in_buf[in_pos++]) & AISC_OBJ_TYPE_MASK;
585
586    return aisc_talking_sets(&(in_buf[in_pos]), size-in_pos, out_buf, (long *)object, object_type);
587}
588
589static long aisc_talking_nset(long *in_buf, int size, long *out_buf, int) { // handles AISC_NSET
590    aisc_server_error = NULL;
591
592    int  in_pos      = 0;
593    long object      = in_buf[in_pos++];
594    int  object_type = (int)(in_buf[in_pos++] & AISC_OBJ_TYPE_MASK);
595
596    aisc_talking_sets(&(in_buf[in_pos]), size-in_pos, out_buf, (long *)object, object_type);
597    return AISC_NO_ANSWER;
598}
599
600static struct aisc_static_set_mem {
601    long *ibuf, *obuf;
602    int size, type;
603} md;
604
605long aisc_make_sets(long *obj)
606{
607    if (md.size>0) {
608        return aisc_talking_sets(md.ibuf, md.size, md.obuf, obj, md.type);
609    }
610    else {
611        return 0;
612    }
613}
614
615static long aisc_talking_create(long *in_buf, int size, long *out_buf, int) { // handles AISC_CREATE
616    aisc_server_error = NULL;
617
618    int  in_pos      = 0;
619    long father_type = in_buf[in_pos++];
620    long father      = in_buf[in_pos++];
621
622    long *erg = 0;
623    for (int i=0; i<1; i++) {
624        if ((father_type&0xff00ffff) ||
625            (((unsigned int)father_type& 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
626            aisc_server_error = "AISC_CREATE_SERVER_ERROR: FATHER UNKNOWN";
627            break;
628        }
629        aisc_server_error = test_address_valid((void *)father, father_type);
630        if (aisc_server_error) break;
631
632        father_type                        = father_type>>16;
633        aisc_talking_func_longp *functions = aisc_talking_functions_create[father_type];
634
635        long code        = in_buf[in_pos++];
636        long attribute   = code & AISC_ATTR_MASK;
637        long object_type = in_buf[in_pos++];
638
639        if (!functions) {
640            sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s DOESN'T HAVE TARGET-ATTRIBUTE %s",
641                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
642            aisc_server_error = error_buf;
643            break;
644        }
645        if (attribute > AISC_MAX_ATTR) {
646            aisc_server_error = "AISC_CREATE_SERVER_ERROR: UNKNOWN ATTRIBUTE";
647            break;
648        }
649        aisc_talking_func_longp function = functions[attribute];
650        if (!function) {
651            sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s FATHER DOESN'T HAVE TARGET-ATTRIBUTE %s",
652                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
653            aisc_server_error = error_buf;
654            break;
655        }
656        md.ibuf = &(in_buf[in_pos]);
657        md.obuf = out_buf;
658        md.size = size - in_pos;
659        md.type = (int)object_type;
660        erg = function(father);
661    }
662    if (aisc_server_error) {
663        sprintf((char *) out_buf, "%s", aisc_server_error);
664        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
665    }
666    else {
667        out_buf[0] = (long)erg;
668        return 1;
669    }
670}
671
672static long aisc_talking_copy(long *in_buf, int size, long *out_buf, int /*max_size*/) { // handles AISC_COPY
673    aisc_server_error = NULL;
674
675    int  in_pos      = 0;
676    long object      = in_buf[in_pos++];
677    int  father_type = (int)in_buf[in_pos++];
678    long father      = in_buf[in_pos++];
679
680    long *erg = 0;
681    for (int i=0; i<1; i++) {
682        if ((father_type&0xff00ffff) ||
683             (((unsigned int)father_type& 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
684            aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER UNKNOWN";
685            break;
686        }
687        aisc_server_error = test_address_valid((void *)father, father_type);
688        if (aisc_server_error) break;
689
690        father_type                        = father_type>>16;
691        aisc_talking_func_longp *functions = aisc_talking_functions_copy[father_type];
692
693        if (!functions) {
694            aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER DOESN'T HAVE TARGET-ATTRIBUTES";
695            break;
696        }
697
698        int code        = (int)in_buf[in_pos++];
699        int object_type = (int)in_buf[in_pos++];
700        int attribute   = code & AISC_ATTR_MASK;
701
702        if (attribute > AISC_MAX_ATTR) {
703            aisc_server_error = "AISC_COPY_SERVER_ERROR: UNKNOWN ATTRIBUTE";
704            break;
705        }
706        aisc_talking_func_longp function = functions[attribute];
707        if (!function) {
708            sprintf(error_buf, "AISC_COPY_SERVER_ERROR: FATHER %s DOESN'T HAVE TARGET-ATTRIBUTE %s",
709                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
710            aisc_server_error = error_buf;
711            break;
712        }
713        aisc_server_error = test_address_valid((void *)object, object_type);
714        if (aisc_server_error) break;
715
716        md.ibuf = &(in_buf[in_pos]);
717        md.obuf = out_buf;
718        md.size = size - in_pos;
719        md.type = object_type;
720        erg = function(father, object);
721    }
722    if (aisc_server_error) {
723        sprintf((char *) out_buf, "%s", aisc_server_error);
724        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
725    }
726    else {
727        out_buf[0] = (long)erg;
728        return 1;
729    }
730}
731
732static long aisc_talking_find(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_FIND
733    aisc_server_error = NULL;
734
735    int  in_pos      = 0;
736    long father_type = in_buf[in_pos++];
737    long father      = in_buf[in_pos++];
738
739    long *erg = 0;
740    for (int i = 0; i < 1; i++) {
741        if ((father_type & 0xff00ffff) ||
742            (((unsigned int) father_type & 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
743            aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER UNKNOWN";
744            break;
745        }
746        aisc_server_error = test_address_valid((void *)father, father_type);
747        if (aisc_server_error)
748            break;
749
750        father_type = father_type>>16;
751        aisc_talking_func_longp *functions   = aisc_talking_functions_find[father_type];
752
753        long code      = in_buf[in_pos++];
754        long attribute = code & AISC_ATTR_MASK;
755
756        if (!functions) {
757            aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER DON'T KNOW ATTRIBUTES FOR SEARCH";
758            break;
759        }
760        if (attribute > AISC_MAX_ATTR) {
761            aisc_server_error = "AISC_FIND_SERVER_ERROR: UNKNOWN ATTRIBUTE";
762            break;
763        }
764        aisc_talking_func_longp function = functions[attribute];
765        if (!function) {
766            sprintf(error_buf, "AISC_FIND_SERVER_ERROR: FATHER %s DON'T KNOW ATTRIBUTE %s FOR SEARCH",
767                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
768            aisc_server_error = error_buf;
769            break;
770        }
771        if (in_buf[in_pos++]<=0) {
772            aisc_server_error = " AISC_FIND_SERVER_ERROR: CANNOT FIND EMPTY IDENT";
773            break;
774        }
775        erg = function(father, &(in_buf[in_pos]));
776    }
777    if (aisc_server_error) {
778        sprintf((char *) out_buf, "%s", aisc_server_error);
779        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
780    }
781    else {
782        out_buf[0] = (long) erg;
783        return 1;
784    }
785}
786
787extern int *aisc_main;
788
789static long aisc_talking_init(long */*in_buf*/, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_INIT
790    aisc_server_error = NULL;
791    out_buf[0]        = (long)aisc_main;
792    return 1;
793}
794
795static long aisc_fork_server(long */*in_buf*/, int /*size*/, long */*out_buf*/, int /*max_size*/) { // handles AISC_FORK_SERVER
796    pid_t pid = fork();
797    return pid<0 ? 0 : pid; // return OK(=0) when fork does not work
798}
799
800static long aisc_talking_delete(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_DELETE
801    int             in_pos, out_pos;
802    long             object_type;
803
804    aisc_talking_func_long function;
805
806    int             i;
807    long             object;
808    in_pos = out_pos = 0;
809    aisc_server_error = NULL;
810    object_type = in_buf[in_pos++];
811    object_type = (object_type & AISC_OBJ_TYPE_MASK);
812    object = in_buf[in_pos++];
813    for (i = 0; i < 1; i++) {
814        if (object_type > (AISC_MAX_OBJECT*0x10000)) {
815            aisc_server_error = "AISC_GET_SERVER_ERROR: UNKNOWN OBJECT";
816        }
817        else {
818            aisc_server_error = test_address_valid((void *)object, object_type);
819        }
820        if (aisc_server_error)
821            break;
822        object_type = object_type >> (16);
823        function = aisc_talking_functions_delete[object_type];
824        if (!function) {
825            sprintf(error_buf, "AISC_SET_SERVER_ERROR: OBJECT %s cannot be deleted",
826                    aisc_object_names[object_type]);
827            aisc_server_error = error_buf;
828            break;
829        }
830        else {
831            function(object);
832        }
833    }
834    if (aisc_server_error) {
835        sprintf((char *) out_buf, "%s", aisc_server_error);
836        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
837    }
838    return 0;
839}
840
841static long aisc_talking_debug_info(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_DEBUG_INFO
842    int  in_pos, out_pos;
843    long object_type, attribute;
844
845    aisc_talking_func_long *functionsg;
846    aisc_talking_func_long *functionss;
847    aisc_talking_func_longp *functions;
848
849    int   i;
850    long *object;
851
852    in_pos            = out_pos = 0;
853    aisc_server_error = NULL;
854
855    for (i=0; i<256; i++) out_buf[i] = 0;
856    for (i = 0; i < 1; i++) {
857        object            = (long *)in_buf[in_pos++];
858        attribute         = in_buf[in_pos++];
859        aisc_server_error = test_address_valid((void *)object, 0);
860
861        if (aisc_server_error)
862            break;
863
864        object_type = *object;
865        if ((object_type > (AISC_MAX_OBJECT*0x10000)) || (object_type&0xff00ffff) || (object_type<0x00010000)) {
866            aisc_server_error = "AISC_DEBUGINFO_SERVER_ERROR: UNKNOWN OBJECT";
867            break;
868        }
869        attribute   &= AISC_ATTR_MASK;
870        object_type  = object_type>>16;
871
872        if (!aisc_talking_functions_delete[object_type]) { out_buf[0] = 1; };
873
874        if (!(functionsg=aisc_talking_functions_get[object_type])) {
875            out_buf[1] = 2;
876        }
877        else {
878            if (!functionsg[attribute])         out_buf[1] = 1;
879        };
880
881        if (!(functionss=aisc_talking_functions_set[object_type])) {
882            out_buf[2] = 2;
883        }
884        else {
885            if (!functionss[attribute])         out_buf[2] = 1;
886        };
887
888        if (!(functions=aisc_talking_functions_find[object_type])) {
889            out_buf[3] = 2;
890        }
891        else {
892            if (!functions[attribute])  out_buf[3] = 1;
893        };
894
895        if (!(functions=aisc_talking_functions_create[object_type])) {
896            out_buf[4] = 2;
897        }
898        else {
899            if (!functions[attribute])  out_buf[4] = 1;
900        };
901
902        if (!(functions=aisc_talking_functions_copy[object_type])) {
903            out_buf[5] = 2;
904        }
905        else {
906            if (!functions[attribute])  out_buf[5] = 1;
907        };
908
909    }
910    if (aisc_server_error) {
911        sprintf((char *) out_buf, "%s", aisc_server_error);
912        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
913    }
914    else {
915        return 20;
916    }
917}
918
919int aisc_broadcast(Hs_struct *hs, int message_type, const char *message)
920{
921    Socinf *si;
922    int     size    = message ? strlen(message) : 0;
923    int     sizeL   = (size+1+sizeof(long)-1) / sizeof(long); // number of longs needed to safely store string
924    long   *out_buf = (long *)calloc(sizeL+3, sizeof(long));
925
926    if (!message) {
927        out_buf[3] = 0;
928    }
929    else {
930        char *strStart = (char*)(out_buf+3);
931        int   pad      = sizeL*sizeof(long)-(size+1);
932
933        aisc_assert(pad >= 0);
934
935        memcpy(strStart, message, size+1);
936        if (pad) memset(strStart+size+1, 0, pad); // avoid to send uninitialized bytes
937    }
938
939    aisc_assert(sizeL >= 1);
940
941    out_buf[0] = sizeL+1;
942    out_buf[1] = AISC_CCOM_MESSAGE;
943    out_buf[2] = message_type;
944
945    for (si=hs->soci; si; si=si->next) {
946        arb_socket_write(si->socket, (char *)out_buf, (sizeL + 3) * sizeof(long));
947    }
948    free(out_buf);
949    return 0;
950}
951
952#ifdef __cplusplus
953extern "C" {
954#endif
955
956    typedef long (*aisc_talking_function_type)(long*, int, long*, int);
957
958#ifdef __cplusplus
959}
960#endif
961
962static aisc_talking_function_type aisc_talking_functions[] = {
963    aisc_talking_get,        // AISC_GET
964    aisc_talking_set,        // AISC_SET
965    aisc_talking_nset,       // AISC_NSET
966    aisc_talking_create,     // AISC_CREATE
967    aisc_talking_find,       // AISC_FIND
968    aisc_talking_copy,       // AISC_COPY
969    aisc_talking_delete,     // AISC_DELETE
970    aisc_talking_init,       // AISC_INIT
971    aisc_talking_debug_info, // AISC_DEBUG_INFO
972    aisc_fork_server         // AISC_FORK_SERVER
973};
974
975static int aisc_talking(int con) {
976    static long      buf[AISC_MESSAGE_BUFFER_LEN];
977    static long      out_buf[AISC_MESSAGE_BUFFER_LEN];
978    unsigned long    len;
979    static long      size;
980    long             magic_number;
981    len = arb_socket_read(con, (char *)buf, 2* sizeof(long));
982    if (len == 2*sizeof(long)) {
983        aisc_server_con = con;
984        if (buf[0] >= AISC_MESSAGE_BUFFER_LEN)
985            return AISC_SERVER_FAULT;
986        magic_number = buf[1];
987        if ((unsigned long)(magic_number & AISC_MAGIC_NUMBER_FILTER) != (unsigned long)(AISC_MAGIC_NUMBER & AISC_MAGIC_NUMBER_FILTER)) {
988            return AISC_SERVER_FAULT;
989        }
990        size = buf[0];
991
992        {
993            long expect = size*sizeof(long);
994            aisc_assert(expect >= 0);
995            aisc_assert(expect <= INT_MAX);
996
997            len = arb_socket_read(con, (char *)buf, (int)expect);
998            aisc_assert(len <= LONG_MAX);
999
1000            if ((long)len != expect) {
1001                printf(" ERROR in AISC_SERVER: Expected to get %li bytes from client (got %lu)\n", expect, len);
1002                return AISC_SERVER_OK;
1003            }
1004        }
1005        magic_number &= ~AISC_MAGIC_NUMBER_FILTER;
1006        size          = (aisc_talking_functions[magic_number])
1007            (buf, (int)size, out_buf + 2, AISC_MESSAGE_BUFFER_LEN - 2);
1008        if (size >= 0) {
1009            out_buf[1] = AISC_CCOM_OK;
1010        }
1011        else {
1012            if (size == (long)AISC_NO_ANSWER) {
1013                return AISC_SERVER_OK;
1014            }
1015            out_buf[1] = AISC_CCOM_ERROR;
1016            size *= -1;
1017        }
1018        out_buf[0] = size;
1019        if (arb_socket_write(con, (char *)out_buf, (int)(size + 2) * sizeof(long))) {
1020            return AISC_SERVER_FAULT;
1021        }
1022        if (aisc_server_bytes_first) {
1023            if (aisc_s_send_bytes_queue(con)) {
1024                return AISC_SERVER_FAULT;
1025            }
1026        }
1027        return AISC_SERVER_OK;
1028    }
1029    else {
1030        return AISC_SERVER_FAULT;
1031    }
1032}
1033
1034Hs_struct *aisc_accept_calls(Hs_struct *hs)
1035{
1036    int             con;
1037    int             anz, i;
1038    Socinf         *si, *si_last = NULL, *sinext, *sptr;
1039    fd_set          set, setex;
1040    struct timeval  timeout;
1041
1042    if (!hs) {
1043        fprintf(stderr, "AISC_SERVER_ERROR socket error (==0)\n");
1044    }
1045
1046    timeout.tv_sec  = hs->timeout / 1000;
1047    timeout.tv_usec = (hs->timeout % 1000) * 1000;
1048
1049    aisc_server_hs = hs;
1050
1051    while (hs) {
1052        FD_ZERO(&set);
1053        FD_ZERO(&setex);
1054        FD_SET(hs->hso, &set);
1055        FD_SET(hs->hso, &setex);
1056
1057        for (si=hs->soci, i=1; si; si=si->next, i++)
1058        {
1059            FD_SET(si->socket, &set);
1060            FD_SET(si->socket, &setex);
1061        }
1062        if (hs->timeout >= 0) {
1063            anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, &timeout);
1064        }
1065        else {
1066            anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, 0);
1067        }
1068
1069        if (anz==-1) {
1070            printf("ERROR: poll in aisc_accept_calls\n");
1071            return 0;
1072        }
1073        if (!anz) { // timed out
1074            return hs;
1075        }
1076        // an event has occurred
1077        if ((timeout.tv_usec>=0)&&(timeout.tv_usec<100000)) timeout.tv_usec = 100000;
1078
1079        if (FD_ISSET(hs->hso, &set)) {
1080            con = accept(hs->hso, NULL, 0);
1081            if (hs->fork) {
1082                long id = fork();
1083                if (!id) {
1084                    return hs;
1085                }
1086            }
1087
1088            if (con>0) {
1089                static int optval;
1090                sptr = (Socinf *)calloc(sizeof(Socinf), 1);
1091                if (!sptr) return 0;
1092                sptr->next = hs->soci;
1093                sptr->socket = con;
1094                hs->soci=sptr;
1095                hs->nsoc++;
1096                optval = 1;
1097                setsockopt(con, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, 4);
1098            }
1099        }
1100        else {
1101            si_last = 0;
1102
1103            for (si=hs->soci; si; si_last=si, si=sinext) {
1104                sinext = si->next;
1105
1106                if (FD_ISSET(si->socket, &set)) {
1107                    if (AISC_SERVER_OK == aisc_talking(si->socket)) continue;
1108                } else if (!FD_ISSET(si->socket, &setex)) continue;
1109
1110                if (close(si->socket) != 0) {
1111                    printf("aisc_accept_calls: ");
1112                    printf("couldn't close socket!\n");
1113                }
1114
1115                hs->nsoc--;
1116                if (si == hs->soci) {   // first one
1117                    hs->soci = si->next;
1118                }
1119                else {
1120                    si_last->next = si->next;
1121                }
1122                if (si->destroy_callback) {
1123                    si->destroy_callback(si->destroy_clientdata);
1124                }
1125                free(si);
1126#ifdef SERVER_TERMINATE_ON_CONNECTION_CLOSE
1127                if (hs->nsoc == 0) { // no clients left
1128                    if (hs->fork) exit(EXIT_SUCCESS); // child exits
1129                    return hs; // parent exits
1130                }
1131                break;
1132#else
1133                // normal behavior
1134                if (hs->nsoc == 0 && hs->fork) exit(EXIT_SUCCESS);
1135                break;
1136#endif
1137            }
1138        }
1139    } // while main loop
1140
1141    return hs;
1142}
1143
1144void aisc_server_shutdown(Hs_struct*& hs) {
1145    Socinf *si;
1146
1147    for (si=hs->soci; si; si=si->next) {
1148        shutdown(si->socket, SHUT_RDWR);
1149        close(si->socket);
1150    }
1151    shutdown(hs->hso, SHUT_RDWR);
1152    close(hs->hso);
1153    if (hs->unix_name) unlink(hs->unix_name);
1154    delete hs; hs = NULL;
1155}
1156
1157void aisc_server_shutdown_and_exit(Hs_struct *hs, int exitcode) {
1158    /* goes to header:
1159     * __ATTR__NORETURN
1160     * __ATTR__DEPRECATED_TODO("cause it hides a call to exit() inside a library")
1161     */
1162
1163    aisc_server_shutdown(hs);
1164    printf("Server terminates with code %i.\n", exitcode);
1165    exit(exitcode);
1166}
1167
1168
1169// ---------------------------
1170//      special functions
1171
1172
1173int aisc_add_destroy_callback(aisc_destroy_callback callback, long clientdata) {        // call from server function
1174    Socinf    *si;
1175    int        socket = aisc_server_con;
1176    Hs_struct *hs     = aisc_server_hs;
1177    if (!hs)
1178        return socket;
1179    for (si = hs->soci; si; si = si->next) {
1180        if (si->socket == socket) {
1181            if (si->destroy_callback) {
1182                fputs("Error: destroy_callback already bound (did you open two connections in client?)\n", stderr);
1183                fputs("Note: calling bound and installing new destroy_callback\n", stderr);
1184                si->destroy_callback(si->destroy_clientdata);
1185            }
1186
1187            si->destroy_callback   = callback;
1188            si->destroy_clientdata = clientdata;
1189        }
1190    }
1191    return socket;
1192}
1193
1194void aisc_remove_destroy_callback() {   // call from server function
1195    Socinf    *si;
1196    int        socket = aisc_server_con;
1197    Hs_struct *hs     = aisc_server_hs;
1198    if (!hs)
1199        return;
1200    for (si = hs->soci; si; si = si->next) {
1201        if (si->socket == socket) {
1202            si->destroy_callback = 0;
1203            si->destroy_clientdata = 0;
1204        }
1205    }
1206}
1207
1208int aisc_server_save_token(FILE *fd, const char *buffer, int maxsize) {
1209    putc('{',fd);
1210    const char *p = buffer;
1211    while (maxsize-->0) {
1212        int c = *(p++);
1213        if (!c) break;
1214        if (c=='}' || c == '\\') putc('\\',fd);
1215        putc(c,fd);
1216    }
1217    putc('}',fd);
1218    return 0;
1219}
1220
1221int aisc_server_load_token(FILE *fd, char *buffer, int maxsize) {
1222    int   in_brackets = 0;
1223    char *p           = buffer;
1224    int   result      = EOF;
1225
1226    while (maxsize-- > 0) {
1227        int c = getc(fd);
1228        if (c==EOF) break;
1229        if (in_brackets) {
1230            if (c=='\\') {
1231                c = getc(fd);
1232                *(p++) = c;
1233            }
1234            else if (c!='}') {
1235                *(p++) = c;
1236            }
1237            else {
1238                result = 0;
1239                break;
1240            }
1241        }
1242        else if (c=='{') { 
1243            if (p!=buffer) {
1244                *(p++) = '{';
1245                *p=0;
1246                return 0;
1247            }
1248            else {
1249                in_brackets = 1; 
1250            }
1251        }
1252        else if (c==' ' || c=='\n') {
1253            if (p!=buffer) {
1254                result = 0;
1255                break;
1256            }
1257        }
1258        else if (c=='}') {
1259            *(p++) = '}';
1260            result = 0;
1261            break;
1262        }
1263        else {
1264            *(p++) = c;
1265        }
1266    }
1267   
1268    *p = 0;
1269    return result; // read error maxsize reached
1270}
Note: See TracBrowser for help on using the repository browser.