source: tags/arb_5.0/AISC_COM/C/server.c

Last change on this file was 5630, checked in by westram, 15 years ago
  • fixed a few gcc 4.3.2 warnings
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.7 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3/* #include <malloc.h> */
4#include <unistd.h>
5#include <errno.h>
6#include <string.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <sys/un.h>
10#include <netinet/in.h>
11#include <netinet/tcp.h>
12#include <arpa/inet.h>
13#include <sys/stat.h>
14#include <limits.h>
15
16#if defined(SUN4) || defined(SUN5)
17# include <sys/filio.h>
18#endif
19
20#include "trace.h"
21
22#define FD_SET_TYPE
23
24#if defined(DEBUG)
25/* #define SERVER_TERMINATE_ON_CONNECTION_CLOSE */
26#endif /* DEBUG */
27
28
29#include <signal.h>
30#include <sys/time.h>
31#include <netdb.h>
32
33#include "aisc_com.h"
34/* AISC_MKPT_PROMOTE:#include <aisc_func_types.h>*/
35#include "server.h"
36#include "aisc_global.h"
37/* #include <SIG_PF.h> */
38
39#include "../INCLUDE/SIG_PF.h"
40#include "../INCLUDE/arb_assert.h"
41#define aisc_assert(cond) arb_assert(cond)
42
43#define AISC_SERVER_OK 1
44#define AISC_SERVER_FAULT 0
45#define MAX_QUEUE_LEN 5
46
47#define AISC_MAGIC_NUMBER_FILTER 0xffffff00
48
49/******************************************* some structures *******************************************/
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55    struct Socinf {
56        struct Socinf      *next;
57        int                 socket;
58        aisc_callback_func  destroy_callback;
59        long                destroy_clientdata;
60        int                 lasttime;
61    };
62
63#ifdef __cplusplus
64}
65#endif
66
67struct pollfd;
68struct Hs_struct {
69    int            hso;
70    struct 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
79struct aisc_bytes_list {
80    char *data;
81    int   size;
82   
83    struct aisc_bytes_list *next;
84} *aisc_server_bytes_first,*aisc_server_bytes_last;
85
86
87extern char  *aisc_object_names[];
88extern char **aisc_attribut_names_list[];
89
90extern aisc_talking_func_long  *aisc_talking_functions_get[];
91extern aisc_talking_func_long  *aisc_talking_functions_set[];
92extern aisc_talking_func_longp *aisc_talking_functions_copy[];
93extern aisc_talking_func_longp *aisc_talking_functions_find[];
94extern aisc_talking_func_longp *aisc_talking_functions_create[];
95extern aisc_talking_func_long   aisc_talking_functions_delete[];
96
97/* extern long ((**(aisc_talking_functions_get[]))(...)); */
98/* extern long ((**(aisc_talking_functions_set[]))(...)); */
99/* extern long *((**(aisc_talking_functions_copy[]))(...)); */
100/* extern long *((**(aisc_talking_functions_find[]))(...)); */
101/* extern long *((**(aisc_talking_functions_create[]))(...)); */
102/* extern long ((*(aisc_talking_functions_delete[]))(...)); */
103
104const char *aisc_server_error;
105int         mdba_make_core = 1;
106
107static char              error_buf[256];
108static int               aisc_server_con;
109static struct Hs_struct *aisc_server_hs;
110
111/******************************************* valid memory tester *******************************************/
112
113static int my_sig_violation_flag;
114static int my_pipe_violation_flag;
115/* int my_sig_violation_end(); */
116
117char    *test_address_valid(void *address,long key)
118{
119    /* tested ob die Addresse address erlaubt ist,
120       falls ja, dann return NULL, sonst Fehlerstring */
121    /* Falls key != NULL, tested ob *address == key */
122    long i;
123    static char buf[256];
124    my_sig_violation_flag = 0;
125    if ((long)address & (sizeof(long)-1) ) {
126        sprintf(buf,"MEMORY MANAGER ERROR: SIGNAL BUS_ERROR;    ADDRESS 0x%lx",(long)address);
127        return buf;
128    }
129    i = *(long *)address;
130    if (my_sig_violation_flag) {
131        sprintf(buf,"MEMORY MANAGER ERROR: SIGNAL SEGV;      ADDRESS 0x%lx",(long)address);
132        return buf;
133    }
134    if (key){
135        if (i!=key) {
136            sprintf(buf,"MEMORY MANAGER ERROR: OBJECT KEY (0x%lx) IS NOT OF TYPE 0x%lx",i,key);
137            return buf;
138        }
139    }
140    return NULL;
141}
142
143
144int test_address_valid_end()
145{
146    return 1;
147}
148
149
150void *my_sig_violation(int sig, int code, struct sigcontext *scp,char * addr)
151{
152    sig = sig;
153    code = code;
154    addr = addr;
155    scp = scp;
156#if defined(SUN4)
157    long a,e;
158    my_sig_violation_flag =1;
159    a = (long)test_address_valid;
160    e = (long)test_address_valid_end;
161
162    if ( (scp->sc_pc<a) || (scp->sc_pc>e) ){
163        signal(SIGSEGV,SIG_DFL);                /* make core */
164        return 0;
165    }
166    scp->sc_pc = scp->sc_npc;
167#endif
168    return 0;
169}
170/***************************    valid memory tester (end) *******************/
171
172/******************************************* signal handling *******************************************/
173void *aisc_server_sigpipe()
174{
175    printf("Sig pipe broken\n");
176    my_pipe_violation_flag = 1;
177    return 0;
178}
179
180/******************************************* new read command *******************************************/
181
182int aisc_s_read(int socket,char *ptr,int size)
183{
184    int leftsize,readsize;
185    leftsize = size;
186    readsize = 0;
187    while (leftsize) {
188        readsize = read(socket,ptr,leftsize);
189        if (readsize<=0) return 0;
190        ptr += readsize;
191        leftsize -= readsize;
192    }
193
194#if defined(DUMP_COMMUNICATION)
195    aisc_dump_hex("aisc_s_read: ", ptr-size, size);
196#endif /* DUMP_COMMUNICATION */
197
198    return size;
199}
200
201int aisc_s_write(int socket,char *ptr,int size)
202{
203    int leftsize,writesize;
204    leftsize = size;
205    writesize = 0;
206    my_pipe_violation_flag = 0;
207    while (leftsize) {
208        writesize = write(socket,ptr,leftsize);
209        if (my_pipe_violation_flag) return -1;
210        if (writesize<0) return -1;
211        ptr += writesize;
212        leftsize -= writesize;
213#ifndef SUN4
214        if (leftsize) sleep(1);
215#else
216        if (leftsize) usleep(10000);
217#endif
218    }
219
220#if defined(DUMP_COMMUNICATION)
221    aisc_dump_hex("aisc_s_write: ", ptr-size, size);
222#endif /* DUMP_COMMUNICATION */
223
224    return 0;
225}
226
227
228/******************************** object+attr_names for error messages ********************************/
229
230const char *aisc_get_object_names(long i)
231{
232    if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_object_names[i])) {
233        return "<unknown object>";
234    }
235    return aisc_object_names[i];
236}
237
238const char *aisc_get_object_attribute(long i,long j)
239{
240    if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_attribut_names_list[i])) {
241        return "<null>";
242    }
243    if ((j<0) || (j>=AISC_MAX_ATTR) || (!aisc_attribut_names_list[i][j])){
244        return "<unknown attribute>";
245    }
246    return aisc_attribut_names_list[i][j];
247}
248
249/************************************* find the mach name and id *************************************/
250
251char *aisc_get_hostname(void){
252    static char *hn = 0;
253    if (!hn){
254        char buffer[4096];
255        gethostname(buffer,4095);
256        hn = strdup(buffer);
257    }
258    return hn;
259}
260
261const char *aisc_get_m_id(const char *path, char **m_name, int *id)
262{
263    char           *p;
264    char           *mn;
265    int             i;
266    if (!path) {
267        return "OPEN_ARB_DB_CLIENT ERROR: missing hostname:socketid";
268    }
269    if (!strcmp(path,":")) {
270        path = (char *)getenv("SOCKET");
271        if (!path) return "ENVIROMENT SOCKET NOT FOUNT";
272    }
273    p = (char *) strchr(path, ':');
274    if (path[0] == '*' || path[0] == ':'){      /* UNIX MODE */
275        char buffer[128];
276        if (!p) {
277            return "OPEN_ARB_DB_CLIENT ERROR: missing ':' in *:socketid";
278        }
279        if (p[1] == '~') {
280            sprintf(buffer,"%s%s",getenv("HOME"),p+2);
281            *m_name = (char *)strdup(buffer);
282        }else{
283            *m_name = (char *)strdup(p+1);
284        }
285        *id = -1;
286        return 0;
287    }
288    if (!p) {
289        return "OPEN_ARB_DB_CLIENT ERROR: missing ':' in netname:socketid";
290    }
291    mn = (char *) calloc(sizeof(char), p - path + 1);
292    strncpy(mn, path, p - path);
293    if (!strcmp(mn,"localhost")){
294        free(mn);
295        mn = strdup(aisc_get_hostname());
296    }
297
298    *m_name = mn;
299    i = atoi(p + 1);
300    if ((i < 1024) || (i > 4096)) {
301        return "OPEN_ARB_DB_CLIENT ERROR: socketnumber not in [1024..4095]";
302    }
303    *id = i;
304    return 0;
305}
306
307
308const char *aisc_open_socket(const char *path, int delay, int do_connect, int *psocket, char **unix_name) {
309
310    char buffer[128];
311    struct in_addr addr;        /* union -> u_long  */
312    struct hostent *he;
313    const char *err;
314    static int socket_id;
315    static char *mach_name;
316    FILE *test;
317
318    err = aisc_get_m_id(path, &mach_name, &socket_id);
319    if (err) {
320        return err;
321    }
322    if (socket_id >= 0) {       /* UNIX */
323        struct sockaddr_in so_ad;
324        memset((char *)&so_ad,0,sizeof(struct sockaddr_in));
325        *psocket = socket(PF_INET, SOCK_STREAM, 0);
326        if (*psocket <= 0) {
327            return "CANNOT CREATE SOCKET";
328        }
329        if (!(he = gethostbyname(mach_name))) {
330            sprintf(buffer, "Unknown host: %s", mach_name);
331            return (char *)strdup(buffer);
332        }
333        /** simply take first address **/
334        addr.s_addr = *(int *) (he->h_addr);
335        so_ad.sin_addr = addr;
336        so_ad.sin_family = AF_INET;
337        so_ad.sin_port = htons(socket_id);      /* @@@ = pb_socket  */
338        if (do_connect){
339            if (connect(*psocket, (struct sockaddr*)&so_ad, 16)) {
340                return "";
341            }
342        }else{
343            static int one = 1;
344            setsockopt(*psocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&one,sizeof(one));
345            if (bind(*psocket,(struct sockaddr*)&so_ad,16)){
346                return "Could not open socket on Server (1)";
347            }
348        }
349        if (delay == TCP_NODELAY) {
350            static int      optval;
351            optval = 1;
352            setsockopt(*psocket, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, 4);
353        }
354        *unix_name = 0;
355        return 0;
356    } else {
357        struct sockaddr_un so_ad;
358        *psocket = socket(PF_UNIX, SOCK_STREAM, 0);
359        if (*psocket <= 0) {
360            return "CANNOT CREATE SOCKET";
361        }
362        so_ad.sun_family = AF_UNIX;
363        strcpy(so_ad.sun_path,mach_name);
364        if (do_connect){
365            if (connect(*psocket, (struct sockaddr*)&so_ad, strlen(mach_name)+2)) {
366                return "";
367            }
368        }else{
369            static int one = 1;
370            test = fopen(mach_name,"r");
371            if (test) {
372                struct stat stt;
373                fclose(test);
374                if (!stat(path, &stt)){
375                    if (S_ISREG(stt.st_mode)){
376                        fprintf(stderr,"%X\n",stt.st_mode);
377                        return "Socket already exists as a file";
378                    }
379                }
380            }
381            if (unlink(mach_name)) {
382                ;
383            }else{
384                printf("old socket found\n");
385            }
386            setsockopt(*psocket,SOL_SOCKET,SO_REUSEADDR,(const char *)&one,sizeof(one));
387            if (bind(*psocket,(struct sockaddr*)&so_ad,strlen(mach_name)+2)){
388                return "Could not open socket on Server (2)";
389            }
390            if (chmod(mach_name, 0777 )) return "Cannot change mode of socket";
391        }
392        *unix_name = mach_name;
393        return 0;
394    }
395}
396
397/******************************************* open the server *******************************************/
398
399struct Hs_struct *open_aisc_server(const char *path,int timeout,int fork)
400{
401    struct Hs_struct *hs;
402    static int      so;
403    static int      i;
404    const char *err;
405
406    hs = (struct Hs_struct *)calloc(sizeof(struct Hs_struct),1);
407    if(!hs) return 0;
408    hs->timeout = timeout;
409    hs->fork = fork;
410    err = aisc_open_socket(path,TCP_NODELAY, 0, &so,&hs->unix_name);
411    if (err) {
412        if (*err)
413            printf("%s\n",err);
414        return 0;
415    }
416
417    signal(SIGSEGV,(SIG_PF) my_sig_violation);
418    signal(SIGPIPE,(SIG_PF)aisc_server_sigpipe);
419    aisc_server_bytes_first = 0;
420    aisc_server_bytes_last = 0;
421    /** simply take first address **/
422    if (listen(so, MAX_QUEUE_LEN) < 0) {
423        printf("AISC_SERVER_ERROR could not listen (server) %i\n", errno);
424        return NULL;
425    }
426    i = 0;
427    hs->hso = so;
428    return hs;
429}
430
431void aisc_s_add_to_bytes_queue(char *data,int size)
432{
433    struct aisc_bytes_list *bl;
434    bl = (struct aisc_bytes_list *)calloc(sizeof(struct aisc_bytes_list),1);
435    bl->data = data;
436    bl->size = size;
437
438    if (aisc_server_bytes_first){
439        aisc_server_bytes_last->next = bl;
440        aisc_server_bytes_last = bl;
441    }else{
442        aisc_server_bytes_first = bl;
443        aisc_server_bytes_last = bl;
444    }
445}
446
447int aisc_s_send_bytes_queue(int socket)
448{
449    struct aisc_bytes_list *bl,*bl_next;
450    for (bl = aisc_server_bytes_first;bl;bl=bl_next){
451        bl_next = bl->next;
452        if (aisc_s_write(socket,(char *)bl->data,bl->size)) return 1;
453        free((char *)bl);
454    };
455    aisc_server_bytes_first = aisc_server_bytes_last = NULL;
456    return 0;
457}
458
459
460long
461aisc_talking_get(long *in_buf, int size, long *out_buf, int max_size)
462
463{
464    long             in_pos, out_pos;
465    long             code, object_type, attribute, type;
466
467    aisc_talking_func_long function;
468    aisc_talking_func_long *functions;
469    aisc_talking_func_double dfunction;
470    /*     long             (*function)(...); */
471    /*     typedef          long (*tfunction)(...); */
472    /*     tfunction       *functions; */
473    /*      double          (*dfunction)(...);  */
474
475    long             len;
476    long             erg = 0;
477    static double   derg;
478    long             object;
479
480    in_pos = out_pos = 0;
481    aisc_server_error = NULL;
482    object = in_buf[in_pos++];
483    object_type = (in_buf[in_pos] & 0x00ff0000);
484    attribute = 0;
485    max_size = 0;
486
487    if (object_type > (AISC_MAX_OBJECT*0x10000)) {
488        aisc_server_error = "UNKNOWN OBJECT";
489        object = 0;
490    } else {
491        aisc_server_error = test_address_valid((void *)object, object_type);
492    }
493    object_type = object_type >> (16);
494
495    AISC_DUMP_SEP();
496    AISC_DUMP(aisc_talking_get, int, object_type);
497
498    while (!aisc_server_error && (in_pos < size)) {
499        code = in_buf[in_pos];
500        attribute = code & 0x0000ffff;
501        type = code & 0xff000000;
502        functions = aisc_talking_functions_get[object_type];
503        if (!functions) {
504            aisc_server_error = "OBJECT HAS NO ATTRIBUTES";
505            attribute = 0;
506            break;
507        }
508        if (attribute > AISC_MAX_ATTR) {
509            sprintf(error_buf, "ATTRIBUTE %lx OUT of RANGE", attribute);
510            aisc_server_error = error_buf;
511            attribute = 0;
512            break;
513        }
514        function = functions[attribute];
515        if (!function) {
516            sprintf(error_buf, "DONT KNOW ATTRIBUTE %li",
517                    attribute);
518            aisc_server_error = error_buf;
519            break;
520        }
521
522        AISC_DUMP(aisc_talking_get, int, attribute);
523        AISC_DUMP(aisc_talking_get, int, type);
524
525        if (type == AISC_ATTR_DOUBLE) {
526            dfunction = (aisc_talking_func_double) function;
527            derg = dfunction(object);
528        } else {
529            erg = function(object);
530        }
531        if (aisc_server_error) {
532            break;
533        }
534        switch (type) {
535            case AISC_ATTR_INT:
536            case AISC_ATTR_COMMON:
537                AISC_DUMP(aisc_talking_get, int, erg);
538                out_buf[out_pos++] = erg;
539                break;
540
541            case AISC_ATTR_DOUBLE:
542                AISC_DUMP(aisc_talking_get, double, derg);
543                out_buf[out_pos++] = ((int *) &derg)[0];
544                out_buf[out_pos++] = ((int *) &derg)[1];
545                break;
546
547            case AISC_ATTR_STRING:
548                if (!erg) erg = (long) "(null)";
549                len           = strlen((char *)erg);
550                if (len > AISC_MAX_STRING_LEN) {
551                    erg = (long) "(string too long)";
552                    len = strlen((char *)erg);
553                }
554
555                AISC_DUMP(aisc_talking_get, charPtr, (char*)erg);
556
557                len += 1;
558                len /= sizeof(long);
559                len++;
560                out_buf[out_pos++] = len;
561                strcpy((char *)&out_buf[out_pos], (char *)erg);
562                out_pos += len;
563                break;
564            case AISC_ATTR_BYTES:
565                {
566                    bytestring *bs = (bytestring *)erg;
567
568                    AISC_DUMP(aisc_talking_get, int, bs->size);
569#if defined(DUMP_COMMUNICATION)
570                    aisc_dump_hex("aisc_talking_get bytestring: ", bs->data, bs->size);
571#endif /* DUMP_COMMUNICATION */
572
573                    if (bs->data && bs->size)
574                        aisc_s_add_to_bytes_queue(bs->data,bs->size);
575                    out_buf[out_pos++] = bs->size;              /* size */
576                    break;
577                }
578            default:
579                aisc_server_error = "UNKNOWN TYPE";
580                break;
581        }
582        in_pos++;
583    }
584    if (aisc_server_error) {
585        sprintf((char *) out_buf, "AISC_GET_SERVER_ERROR %s: OBJECT:%s   ATTRIBUTE:%s",
586                aisc_server_error,
587                aisc_get_object_names(object_type),
588                aisc_get_object_attribute(object_type,attribute));
589        return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
590    }
591    return out_pos;
592}
593
594int aisc_server_index = -1;
595
596void aisc_talking_set_index(int *obj,int i)
597{
598    obj = obj;
599    aisc_server_index = i;
600}
601
602int aisc_talking_get_index(int u,int o)
603{
604    if (aisc_server_index==-1) {
605        aisc_server_error = "AISC_SERVER_ERROR MISSING AN AISC_INDEX";
606        return -1;
607    }
608    if ((aisc_server_index<u) || (aisc_server_index>=o) ){
609        sprintf(error_buf,"AISC_SET_SERVER_ERROR: INDEX %i IS OUT OF RANGE [%i,%i]",
610                aisc_server_index,u,o);
611        aisc_server_error = error_buf;
612    }
613
614    AISC_DUMP(aisc_talking_get_index, int, aisc_server_index);
615
616    return aisc_server_index;
617}
618
619long aisc_talking_sets(long *in_buf,int size, long *out_buf,long *object, int object_type)
620{
621    int   blen,bsize;
622    long  in_pos,out_pos;
623    long  code,attribute,type;
624
625    aisc_talking_func_long function;
626    aisc_talking_func_long *functions;
627    /*     long     (*function)(...); */
628    /*     typedef          long (*tfunction)(...); */
629    /*     tfunction       *functions; */
630    in_pos = out_pos = 0;
631    aisc_server_index = -1;
632    aisc_server_error   = NULL;
633    object_type         = (object_type &0x00ff0000);
634
635    attribute = 0;
636    if (object_type > (AISC_MAX_OBJECT*0x10000)) {
637        object_type = 0;
638        aisc_server_error = "UNKNOWN OBJECT";
639    }else{
640        aisc_server_error = test_address_valid((void *)object,object_type);
641    }
642    object_type = object_type>>(16);
643    functions   = aisc_talking_functions_set[object_type];
644    if (!functions)     {
645        sprintf(error_buf,"OBJECT %x HAS NO ATTRIBUTES",
646                object_type);
647        aisc_server_error = error_buf;
648    }
649
650    AISC_DUMP_SEP();
651    AISC_DUMP(aisc_talking_sets, int, object_type);
652
653    while (!aisc_server_error &&(in_pos<size)) {
654        code            = in_buf[in_pos++];
655        attribute       = code &0x0000ffff;
656        type            = code &0xff000000;
657        if (attribute > AISC_MAX_ATTR) {
658            sprintf(error_buf,"ATTRIBUTE %li DOESNT EXIST",
659                    attribute);
660            aisc_server_error = error_buf;
661            attribute = 0;
662            break;
663        }
664        if (code == AISC_INDEX) {
665            function = (aisc_talking_func_long)aisc_talking_set_index;
666        }else{
667            function = functions[attribute];
668        }
669        if (!function){
670            sprintf(error_buf,"ATTRIBUTE %li DOESNT EXIST",
671                    attribute);
672            aisc_server_error = error_buf;
673            break;
674        }
675
676        AISC_DUMP(aisc_talking_sets, int, attribute);
677        AISC_DUMP(aisc_talking_sets, int, type);
678
679        switch(type){
680            case        AISC_ATTR_INT:
681            case        AISC_ATTR_COMMON:
682
683                AISC_DUMP(aisc_talking_sets, long, in_buf[in_pos]);
684
685                function((long)object,in_buf[in_pos++]);
686                break;
687            case        AISC_ATTR_DOUBLE:
688                {
689                    double dummy;
690                    int *ptr;
691                    ptr = (int*)&dummy;
692                    *ptr++ = (int)in_buf[in_pos++];
693                    *ptr++ = (int)in_buf[in_pos++];
694
695                    AISC_DUMP(aisc_talking_sets, double, dummy);
696
697                    function((long)object, dummy );
698                    break;
699                }
700            case        AISC_ATTR_STRING:
701                {
702                    char *str = strdup((char *)&(in_buf[in_pos+1]));
703
704                    AISC_DUMP(aisc_talking_sets, charPtr, str);
705
706                    function((long)object, str);
707                    in_pos    += in_buf[in_pos]+1;
708                    break;
709                }
710            case        AISC_ATTR_BYTES:
711                bsize = (int)in_buf[in_pos++];
712
713                AISC_DUMP(aisc_talking_sets, int, bsize);
714
715                if (bsize){
716                    long *ptr;
717                    ptr = (long*)calloc(sizeof(char),bsize);
718                    blen = aisc_s_read(aisc_server_con,(char *)ptr,bsize);
719                    if (bsize!=blen) {
720                        aisc_server_error ="CONNECTION PROBLEMS IN BYTESTRING";
721                    }else{
722                        bytestring bs;
723                        bs.data = (char *)ptr;
724                        bs.size = bsize;
725
726#if defined(DUMP_COMMUNICATION)
727                        aisc_dump_hex("aisc_talking_sets bytestring: ", (char*)ptr, bsize);
728#endif /* DUMP_COMMUNICATION */
729
730                        function((long)object,&bs);
731                    }
732                }else{
733                    function((long)object,0);
734                }
735                break;
736            default:
737                aisc_server_error = "UNKNOWN TYPE";
738                break;
739        }
740    }
741    if(aisc_server_error) {
742        sprintf((char *) out_buf, "AISC_SET_SERVER_ERROR %s: OBJECT:%s   ATTRIBUTE:%s",
743                aisc_server_error,
744                aisc_get_object_names(object_type),
745                aisc_get_object_attribute(object_type,attribute));
746        return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
747    }
748    return 0;
749}
750
751long aisc_talking_set(long *in_buf,int size, long *out_buf,int max_size)
752{       int in_pos,out_pos;
753    int    object_type;
754    long   object;
755    in_pos = out_pos = 0;
756    aisc_server_error      = NULL;
757    max_size = 0;
758    object = in_buf[in_pos++];
759    object_type    = ((int)in_buf[in_pos++])& 0x00ff0000;
760    return aisc_talking_sets(&(in_buf[in_pos]),
761                             size-in_pos,out_buf,(long *)object,object_type);
762}
763
764long aisc_talking_nset(long *in_buf,int size, long *out_buf,int max_size)
765{       int in_pos,out_pos;
766    long   error;
767    int    object_type;
768    long   object;
769    in_pos = out_pos = 0;
770    aisc_server_error      = NULL;
771    max_size = 0;
772    object = in_buf[in_pos++];
773    object_type    = (int)(in_buf[in_pos++]& 0x00ff0000);
774    error =  aisc_talking_sets(&(in_buf[in_pos]),
775                               size-in_pos,out_buf,(long *)object,object_type);
776    return AISC_NO_ANSWER;
777}
778
779static struct aisc_static_set_mem {
780    long *ibuf,*obuf;
781    int size,type;
782} md;
783
784long aisc_make_sets(long *obj)
785{
786    if (md.size>0) {
787        return aisc_talking_sets(md.ibuf,md.size,md.obuf,obj,md.type);
788    }else{
789        return 0;
790    }
791}
792
793long
794aisc_talking_create(long *in_buf, int size, long *out_buf, int max_size)
795{
796    int             in_pos, out_pos;
797    long             code, father_type, object_type, attribute, type;
798
799    aisc_talking_func_longp function;
800    aisc_talking_func_longp *functions;
801    /*     long             *(**functions) (...), *(*function) (...); */
802
803    int             i;
804    long            *erg = 0;
805    long             father;
806    in_pos = out_pos = 0;
807    aisc_server_error = NULL;
808    father_type = in_buf[in_pos++];
809    father = in_buf[in_pos++];
810    max_size = 0;
811    for (i=0;i<1;i++){
812        if ( (father_type&0xff00ffff) ||
813             (((unsigned int)father_type& 0xff0000)>= (AISC_MAX_OBJECT*0x10000)) ){
814            aisc_server_error = "AISC_CREATE_SERVER_ERROR: FATHER UNKNOWN";
815            break;
816        }
817        aisc_server_error = test_address_valid((void *)father,father_type);
818        if (aisc_server_error) break;
819
820        father_type = father_type>>16;
821        functions = aisc_talking_functions_create[father_type];
822        code = in_buf[in_pos++];
823        attribute = code & 0x0000ffff;
824        type = code & 0xff000000;
825        object_type = in_buf[in_pos++];
826        if (!functions) {
827            sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s DOESNT HAVE TARGET-ATTRIBUTE %s",
828                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type,attribute));
829            aisc_server_error = error_buf;
830            break;
831        }
832        if (attribute > AISC_MAX_ATTR) {
833            aisc_server_error = "AISC_CREATE_SERVER_ERROR: UNKNOWN ATTRIBUTE";
834            break;
835        }
836        function = functions[attribute];
837        if (!function) {
838            sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s FATHER DOESNT HAVE TARGET-ATTRIBUTE %s",
839                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type,attribute));
840            aisc_server_error = error_buf;
841            break;
842        }
843        md.ibuf = &(in_buf[in_pos]);
844        md.obuf = out_buf;
845        md.size = size - in_pos;
846        md.type = (int)object_type;
847        erg = function(father);
848    }
849    if (aisc_server_error) {
850        sprintf((char *) out_buf, "%s", aisc_server_error);
851        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
852    }else{
853        out_buf[0] = (long)erg;
854        return 1;
855    }
856}
857
858long
859aisc_talking_copy(long *in_buf, int size, long *out_buf, int max_size)
860{
861    int             in_pos, out_pos;
862    int             code, father_type, object_type,attribute, type;
863
864    aisc_talking_func_longp function;
865    aisc_talking_func_longp *functions;
866    /*     long             *(**functions)(...), *(*function)(...); */
867
868    int             i;
869    long            *erg =0 ;
870    long             father;
871    long             object;
872    in_pos = out_pos = 0;
873    aisc_server_error = NULL;
874    object = in_buf[in_pos++];
875    father_type = (int)in_buf[in_pos++];
876    father = in_buf[in_pos++];
877    for (i=0;i<1;i++){
878        if ( (father_type&0xff00ffff) ||
879             (((unsigned int)father_type& 0xff0000)>= (AISC_MAX_OBJECT*0x10000)) ){
880            aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER UNKNOWN";
881            break;
882        }
883        aisc_server_error = test_address_valid((void *)father,father_type);
884        if (aisc_server_error) break;
885
886        father_type = father_type>>16;
887        functions = aisc_talking_functions_copy[father_type];
888        code = (int)in_buf[in_pos++];
889        object_type = (int)in_buf[in_pos++];
890        attribute = code & 0x0000ffff;
891        type = code & 0xff000000;
892        if (!functions) {
893            aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER DOESNT HAVE TARGET-ATTRIBUTES";
894            break;
895        }
896        if (attribute > AISC_MAX_ATTR) {
897            aisc_server_error = "AISC_COPY_SERVER_ERROR: UNKNOWN ATTRIBUTE";
898            break;
899        }
900        function = functions[attribute];
901        if (!function) {
902            sprintf(error_buf, "AISC_COPY_SERVER_ERROR: FATHER %s DOESNT HAVE TARGET-ATTRIBUTE %s",
903                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type,attribute));
904            aisc_server_error = error_buf;
905            break;
906        }
907        aisc_server_error = test_address_valid((void *)object,object_type);
908        if (aisc_server_error) break;
909
910        md.ibuf = &(in_buf[in_pos]);
911        md.obuf = out_buf;
912        md.size = size - in_pos;
913        md.type = object_type;
914        erg = function(father,object);
915    }
916    max_size = max_size;
917    if (aisc_server_error) {
918        sprintf((char *) out_buf, "%s", aisc_server_error);
919        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
920    }else{
921        out_buf[0] = (long)erg;
922        return 1;
923    }
924}
925
926long
927aisc_talking_find(long *in_buf, int size, long *out_buf, int max_size)
928{
929    int             in_pos, out_pos;
930    long             code, father_type, attribute, type;
931
932    aisc_talking_func_longp function;
933    aisc_talking_func_longp *functions;
934    /*     long            *(**functions)(...),*(*function)(...); */
935
936    int             i;
937    long            *erg= 0;
938    long             father;
939    in_pos = out_pos = 0;
940    aisc_server_error = NULL;
941    father_type = in_buf[in_pos++];
942    father = in_buf[in_pos++];
943    size = size;
944    max_size = max_size;
945    for (i = 0; i < 1; i++) {
946        if ((father_type & 0xff00ffff) ||
947            (((unsigned int) father_type & 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
948            aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER UNKNOWN";
949            break;
950        }
951        aisc_server_error = test_address_valid((void *)father, father_type);
952        if (aisc_server_error)
953            break;
954        father_type = father_type>>16;
955        functions = aisc_talking_functions_find[father_type];
956        code = in_buf[in_pos++];
957        attribute = code & 0x0000ffff;
958        type = code & 0xff000000;
959        if (!functions) {
960            aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER DONT KNOW ATTRIBUTES FOR SEARCH";
961            break;
962        }
963        if (attribute > AISC_MAX_ATTR) {
964            aisc_server_error = "AISC_FIND_SERVER_ERROR: UNKNOWN ATTRIBUTE";
965            break;
966        }
967        function = functions[attribute];
968        if (!function) {
969            sprintf(error_buf, "AISC_FIND_SERVER_ERROR: FATHER %s DONT KNOW ATTRIBUTE %s FOR SEARCH",
970                    aisc_get_object_names(father_type), aisc_get_object_attribute(father_type,attribute));
971            aisc_server_error = error_buf;
972            break;
973        }
974        if (in_buf[in_pos++]<=0) {
975            aisc_server_error = " AISC_FIND_SERVER_ERROR: CANNOT FIND EMPTY IDENT";
976            break;
977        }
978        erg = function(father, &(in_buf[in_pos]));
979    }
980    if (aisc_server_error) {
981        sprintf((char *) out_buf, "%s", aisc_server_error);
982        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
983    } else {
984        out_buf[0] = (long) erg;
985        return 1;
986    }
987}
988
989extern int       *aisc_main;
990
991long
992aisc_talking_init(long *in_buf, int size, long *out_buf, int max_size)
993{
994    in_buf = in_buf; size = size; max_size = max_size;
995    aisc_server_error = NULL;
996    out_buf[0] = (long)aisc_main;
997    return 1;
998}
999
1000long aisc_fork_server(long *in_buf, int size, long *out_buf, int max_size){
1001    pid_t pid;
1002
1003    in_buf = in_buf;
1004    size = size;
1005    out_buf = out_buf;
1006    max_size = max_size;
1007    pid = fork();
1008    if (pid<0) return 0;/* return OK because fork does not work*/
1009    return pid;
1010}
1011
1012long
1013aisc_talking_delete(long *in_buf, int size, long *out_buf, int max_size)
1014{
1015    int             in_pos, out_pos;
1016    long             object_type;
1017
1018    aisc_talking_func_long function;
1019    /*     long             (*function)(...); */
1020
1021    int             i;
1022    long             object;
1023    in_pos = out_pos = 0;
1024    aisc_server_error = NULL;
1025    object_type = in_buf[in_pos++];
1026    object_type = (object_type & 0x00ff0000);
1027    object = in_buf[in_pos++];
1028    for (i = 0; i < 1; i++) {
1029        if (object_type > (AISC_MAX_OBJECT*0x10000)) {
1030            aisc_server_error = "AISC_GET_SERVER_ERROR: UNKNOWN OBJECT";
1031        } else {
1032            aisc_server_error = test_address_valid((void *)object, object_type);
1033        }
1034        if (aisc_server_error)
1035            break;
1036        object_type = object_type >> (16);
1037        function = aisc_talking_functions_delete[object_type];
1038        if (!function) {
1039            sprintf(error_buf, "AISC_SET_SERVER_ERROR: OBJECT %s cannot be deleted",
1040                    aisc_object_names[object_type]);
1041            aisc_server_error = error_buf;
1042            break;
1043        } else {
1044            function(object);
1045        }
1046    }
1047    if (aisc_server_error) {
1048        size = size; max_size = max_size;
1049        sprintf((char *) out_buf, "%s", aisc_server_error);
1050        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
1051    }
1052    return 0;
1053}
1054
1055long
1056aisc_talking_debug_info(long *in_buf,int  size,long *out_buf,int  max_size)
1057{
1058    int             in_pos, out_pos;
1059    long                object_type, attribute;
1060
1061    aisc_talking_func_long *functionsg;
1062    aisc_talking_func_long *functionss;
1063    aisc_talking_func_longp *functions;
1064
1065    /*     typedef          long (*tfunction)(...); */
1066    /*     typedef          long *(*tfunction2)(...); */
1067    /*     tfunction       *functionsg; */
1068    /*     tfunction       *functionss; */
1069    /*     tfunction2      *functions; */
1070
1071    int             i;
1072    long             *object;
1073    size = size;
1074    max_size = max_size;
1075    in_pos = out_pos = 0;
1076    aisc_server_error = NULL;
1077    for (i=0;i<256;i++) out_buf[i] = 0;
1078    for (i = 0; i < 1; i++) {
1079        object = (long *)in_buf[in_pos++];
1080        attribute = in_buf[in_pos++];
1081        aisc_server_error = test_address_valid((void *)object, 0);
1082        if (aisc_server_error)
1083            break;
1084        object_type = *object;
1085        if ( (object_type > (AISC_MAX_OBJECT*0x10000)) || (object_type&0xff00ffff) || (object_type<0x00010000) ) {
1086            aisc_server_error = "AISC_DEBUGINFO_SERVER_ERROR: UNKNOWN OBJECT";
1087            break;
1088        }
1089        attribute &= 0x0000ffff;
1090        object_type = object_type>>16;
1091        if (!aisc_talking_functions_delete[object_type]) { out_buf[0] = 1;};
1092
1093        if (!(functionsg=aisc_talking_functions_get[object_type])) {
1094            out_buf[1] = 2;
1095        }else{
1096            if (!functionsg[attribute])         out_buf[1] = 1;
1097        };
1098
1099        if (!(functionss=aisc_talking_functions_set[object_type])) {
1100            out_buf[2] = 2;
1101        }else{
1102            if (!functionss[attribute])         out_buf[2] = 1;
1103        };
1104
1105        if (!(functions=aisc_talking_functions_find[object_type])) {
1106            out_buf[3] = 2;
1107        }else{
1108            if (!functions[attribute])  out_buf[3] = 1;
1109        };
1110
1111        if (!(functions=aisc_talking_functions_create[object_type])) {
1112            out_buf[4] = 2;
1113        }else{
1114            if (!functions[attribute])  out_buf[4] = 1;
1115        };
1116
1117        if (!(functions=aisc_talking_functions_copy[object_type])) {
1118            out_buf[5] = 2;
1119        }else{
1120            if (!functions[attribute])  out_buf[5] = 1;
1121        };
1122
1123    }
1124    if (aisc_server_error) {
1125        sprintf((char *) out_buf, "%s", aisc_server_error);
1126        return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
1127    } else {
1128        return 20;
1129    }
1130}
1131
1132/********************* broadcast message *************************/
1133
1134int aisc_broadcast(struct Hs_struct *hs, int message_type, const char *message)
1135{
1136    struct Socinf *si;
1137    int            size    = message ? strlen(message) : 0;
1138    int            sizeL   = (size+1+sizeof(long)-1) / sizeof(long); // number of longs needed to safely store string
1139    long          *out_buf = (long *)calloc(sizeL+3, sizeof(long));
1140
1141    if (!message) {
1142        out_buf[3] = 0;
1143    }
1144    else {
1145        char *strStart = (char*)(out_buf+3);
1146        int   pad      = sizeL*sizeof(long)-(size+1);
1147
1148        arb_assert(pad >= 0);
1149
1150        memcpy(strStart, message, size+1);
1151        if (pad) memset(strStart+size+1, 0, pad); // avoid to send uninitialized bytes
1152    }
1153
1154    arb_assert(sizeL >= 1);
1155
1156    out_buf[0] = sizeL+1;
1157    out_buf[1] = AISC_CCOM_MESSAGE;
1158    out_buf[2] = message_type;
1159
1160    for(si=hs->soci; si; si=si->next){
1161        aisc_s_write(si->socket, (char *)out_buf, (sizeL + 3) * sizeof(long));
1162    }
1163    free(out_buf);
1164    return 0;
1165}
1166
1167int aisc_private_message(int socket, int message_type, char *message)
1168{
1169    int len;
1170    int size;
1171    long *out_buf;
1172    len = 1;
1173    if (!message) size = 0; else size = strlen(message);
1174    out_buf = (long *)malloc(size+64);
1175    if (!message) {
1176        out_buf[3] = 0;
1177        len += 1;
1178    }else{
1179        sprintf((char *) (out_buf+3), "%s", message);
1180        len += (size + 1) / sizeof(long) + 1;
1181    }
1182    out_buf[0] = len;
1183    out_buf[1] = AISC_CCOM_MESSAGE;
1184    out_buf[2] = message_type;
1185
1186    if (aisc_s_write(socket, (char *)out_buf, (len + 2) * sizeof(long))) {
1187        aisc_server_error = "Pipe broken";
1188        return 0;
1189    }
1190    free((char *)out_buf);
1191    return 0;
1192}
1193
1194
1195
1196int aisc_talking_count;
1197
1198#ifdef __cplusplus
1199extern "C" {
1200#endif
1201
1202    typedef long (*aisc_talking_function_type)(long*, int, long*, int);
1203
1204#ifdef __cplusplus
1205}
1206#endif
1207
1208static aisc_talking_function_type aisc_talking_functions[]= {
1209    aisc_talking_get,
1210    aisc_talking_set,
1211    aisc_talking_nset,
1212    aisc_talking_create,
1213    aisc_talking_find,
1214    aisc_talking_copy,
1215    aisc_talking_delete,
1216    aisc_talking_init,
1217    aisc_talking_debug_info,
1218    aisc_fork_server
1219};
1220
1221int aisc_talking(int con)
1222{
1223    static long      buf[AISC_MESSAGE_BUFFER_LEN];
1224    static long      out_buf[AISC_MESSAGE_BUFFER_LEN];
1225    unsigned long    len;
1226    static long      size;
1227    long             magic_number;
1228    len = aisc_s_read(con, (char *)buf, 2* sizeof(long));
1229    if (len == 2*sizeof(long)) {
1230        aisc_server_con = con;
1231        if (buf[0] >= AISC_MESSAGE_BUFFER_LEN)
1232            return AISC_SERVER_FAULT;
1233        magic_number = buf[1];
1234        if ( (unsigned long)(magic_number & AISC_MAGIC_NUMBER_FILTER) != (unsigned long)(AISC_MAGIC_NUMBER & AISC_MAGIC_NUMBER_FILTER)) {
1235            return AISC_SERVER_FAULT;
1236        }
1237        size = buf[0];
1238
1239        {
1240            long expect = size*sizeof(long);
1241            aisc_assert(expect >= 0);
1242            aisc_assert(expect <= INT_MAX);
1243
1244            len = aisc_s_read(con, (char *)buf, (int)expect);
1245            aisc_assert(len <= LONG_MAX);
1246
1247            if ((long)len != expect) {
1248                printf(" ERROR in AISC_SERVER: Expected to get %li bytes from client (got %lu)\n", expect, len);
1249                return AISC_SERVER_OK;
1250            }
1251        }
1252        magic_number &= ~AISC_MAGIC_NUMBER_FILTER;
1253        size          = (aisc_talking_functions[magic_number])
1254            (buf, (int)size, out_buf + 2, AISC_MESSAGE_BUFFER_LEN - 2);
1255        if (size >= 0) {
1256            out_buf[1] = AISC_CCOM_OK;
1257        } else {
1258            if (size == (long)AISC_NO_ANSWER) {
1259                return AISC_SERVER_OK;
1260            }
1261            out_buf[1] = AISC_CCOM_ERROR;
1262            size *= -1;
1263        }
1264        out_buf[0] = size;
1265        if (aisc_s_write(con, (char *)out_buf, (int)(size + 2) * sizeof(long))){
1266            return AISC_SERVER_FAULT;
1267        }
1268        if (aisc_server_bytes_first) {
1269            if (aisc_s_send_bytes_queue(con)){
1270                return AISC_SERVER_FAULT;
1271            }
1272        }
1273        return AISC_SERVER_OK;
1274    } else {
1275        return AISC_SERVER_FAULT;
1276    }
1277}
1278
1279struct Hs_struct *aisc_accept_calls(struct Hs_struct *hs)
1280{
1281    int con;
1282    int anz, i;
1283    struct Socinf *si, *si_last = NULL, *sinext, *sptr;
1284    fd_set set,setex;
1285    struct timeval timeout;
1286
1287    if(!hs){
1288        fprintf(stderr,"AISC_SERVER_ERROR socket error (==0)\n");
1289    }
1290
1291    timeout.tv_sec  = hs->timeout / 1000;
1292    timeout.tv_usec = (hs->timeout % 1000) * 1000;
1293
1294    aisc_server_hs = hs;
1295
1296    while (hs){
1297        FD_ZERO(&set);
1298        FD_ZERO(&setex);
1299        FD_SET(hs->hso,&set);
1300        FD_SET(hs->hso,&setex);
1301
1302        for(si=hs->soci, i=1; si; si=si->next, i++)
1303        {
1304            FD_SET(si->socket,&set);
1305            FD_SET(si->socket,&setex);
1306        }
1307        if (hs->timeout >= 0) {
1308            anz = select(FD_SETSIZE,FD_SET_TYPE &set,NULL,FD_SET_TYPE &setex,&timeout);
1309        }else{
1310            anz = select(FD_SETSIZE,FD_SET_TYPE &set,NULL,FD_SET_TYPE &setex,0);
1311        }
1312
1313        if(anz==-1){
1314            printf("ERROR: poll in aisc_accept_calls\n");
1315            return 0;
1316        }
1317        if(!anz){ /* timed out */
1318            return hs;
1319        }
1320        /*** an event has occured! ***/
1321        if( (timeout.tv_usec>=0)&&(timeout.tv_usec<100000)) timeout.tv_usec = 100000;
1322
1323        if(FD_ISSET(hs->hso,&set)){
1324            con = accept(hs->hso,NULL,0);
1325            if (hs->fork){
1326                long id = fork();
1327                if (!id){
1328                    return hs;
1329                }
1330            }
1331
1332            if(con>0){
1333                static int optval;
1334                sptr = (struct Socinf *)calloc(sizeof(struct Socinf),1);
1335                if(!sptr) return 0;
1336                sptr->next = hs->soci;
1337                sptr->socket = con;
1338                hs->soci=sptr;
1339                hs->nsoc++;
1340                optval = 1;
1341                setsockopt(con,IPPROTO_TCP,TCP_NODELAY,(char *)&optval,4);
1342            }
1343        }else{
1344            si_last = 0;
1345
1346            for(si=hs->soci; si; si_last=si, si=sinext){
1347                sinext = si->next;
1348
1349                if (FD_ISSET(si->socket,&set)){
1350                    if( AISC_SERVER_OK == aisc_talking(si->socket) ) continue;
1351                }else if (!FD_ISSET(si->socket,&setex)) continue;
1352
1353                if (close(si->socket) != 0) {
1354                    printf("aisc_accept_calls: ");
1355                    printf("couldn't close socket!\n");
1356                }
1357
1358                hs->nsoc--;
1359                if (si == hs->soci) {   /* first one */
1360                    hs->soci = si->next;
1361                } else {
1362                    si_last->next = si->next;
1363                }
1364                if (si->destroy_callback) {
1365                    si->destroy_callback(si->destroy_clientdata);
1366                }
1367                free((char *)si);
1368#ifdef SERVER_TERMINATE_ON_CONNECTION_CLOSE
1369                if (hs->nsoc == 0) { /* no clients left */
1370                    if (hs->fork) exit(0); /* child exits */
1371                    return hs; /* parent exits */
1372                }
1373                break;
1374#else
1375                /* normal behavior */
1376                if (hs->nsoc == 0 && hs->fork) exit(0);
1377                break;
1378#endif
1379            }
1380        }
1381    } /* while main loop */
1382
1383    return hs;
1384}
1385
1386/************************** aisc_server_shutdown_and_exit *********************/
1387
1388void aisc_server_shutdown_and_exit(struct Hs_struct *hs, int exitcode) {
1389    /* goes to header: __ATTR__NORETURN  */
1390    struct Socinf *si;
1391
1392    for(si=hs->soci; si; si=si->next){
1393        shutdown(si->socket, 2); /* 2 = both dir */
1394        close(si->socket);
1395    }
1396    shutdown(hs->hso, 2);
1397    close(hs->hso);
1398    if (hs->unix_name) unlink(hs->unix_name);
1399
1400    printf("Server terminates with code %i.\n", exitcode);
1401
1402    exit(exitcode);
1403}
1404
1405
1406/************************** special functions *********************/
1407
1408
1409int aisc_get_key(int *obj)
1410{
1411    return *obj;
1412}
1413
1414extern "C" int aisc_add_destroy_callback(aisc_callback_func callback, long clientdata) {        /* call from server function */
1415    struct Socinf  *si;
1416    int             socket = aisc_server_con;
1417    struct Hs_struct *hs = aisc_server_hs;
1418    if (!hs)
1419        return socket;
1420    for (si = hs->soci; si; si = si->next) {
1421        if (si->socket == socket) {
1422            si->destroy_callback = callback;
1423            si->destroy_clientdata = clientdata;
1424        }
1425    }
1426    return socket;
1427}
1428
1429void aisc_remove_destroy_callback() {   /* call from server
1430                                         * function */
1431    struct Socinf  *si;
1432    int             socket = aisc_server_con;
1433    struct Hs_struct *hs = aisc_server_hs;
1434    if (!hs)
1435        return;
1436    for (si = hs->soci; si; si = si->next) {
1437        if (si->socket == socket) {
1438            si->destroy_callback = 0;
1439            si->destroy_clientdata = 0;
1440        }
1441    }
1442}
Note: See TracBrowser for help on using the repository browser.