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

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