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

Last change on this file was 16986, checked in by westram, 7 years ago

Update: continued by [17178]

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