[med-svn] [Git][med-team/libarb][upstream] 2 commits: New upstream version 6.0.6
Andreas Tille
gitlab at salsa.debian.org
Fri Jun 7 11:03:41 BST 2019
Andreas Tille pushed to branch upstream at Debian Med / libarb
Commits:
dd8562c5 by Andreas Tille at 2019-06-07T09:46:45Z
New upstream version 6.0.6
- - - - -
8f7aae39 by Andreas Tille at 2019-06-07T10:01:42Z
New upstream version 6.0.6
- - - - -
18 changed files:
- + AISC_COM/AISC/Makefile
- + AISC_COM/C/Makefile
- + AISC_COM/C/aisc_extern.c
- + AISC_COM/C/aisc_extern_privat.h
- + AISC_COM/C/aisc_func_types.h
- + AISC_COM/C/aisc_global.h
- + AISC_COM/C/aisc_server.h
- + AISC_COM/C/client.c
- + AISC_COM/C/client.h
- + AISC_COM/C/client_privat.h
- + AISC_COM/C/client_types.h
- + AISC_COM/C/common.c
- + AISC_COM/C/common.h
- + AISC_COM/C/server.c
- + AISC_COM/C/server.h
- + AISC_COM/C/struct_man.c
- + AISC_COM/C/struct_man.h
- + AISC_COM/C/trace.h
Changes:
=====================================
AISC_COM/AISC/Makefile
=====================================
@@ -0,0 +1,179 @@
+THIS=AISC/Makefile
+MAKETHIS=$(MAKE) -f $(THIS)
+#MAKETHIS=$(MAKE) -d -f $(THIS)
+SED:=$(ARBHOME)/SH/arb_sed
+READLINK:=$(ARBHOME)/SH/arb_readlink
+
+.SUFFIXES: .o .c .h .aisc
+
+#where to find the creator files
+AISC=../AISC/aisc
+AISC_MKPT = ../AISC_MKPTPS/aisc_mkpt
+
+RUN_AISC:=$(AISC)
+# valgrinding like this breaks the build process (due to wrong exitcode)
+#RUN_AISC:=arb_valgrind -c 15 $(AISC)
+#RUN_AISC:=arb_valgrind -c 15 -l $(AISC)
+#RUN_AISC:=arb_valgrind -c 15 -l -r $(AISC)
+
+GEN_INCLUDES = GENH/aisc.h GENH/aisc_com.h
+INCLUDE_INCLUDES = aisc_include.header
+
+SERVER_OBJECTS = O/server.o O/struct_man.o O/aisc_extern.o
+
+GEN_SERVER_PROTO_OBJECTS = GENC/aisc_server.o
+GEN_SERVER_OTHER_OBJECTS = GENC/aisc_global.o
+GEN_SERVER_OBJECTS = $(GEN_SERVER_PROTO_OBJECTS) $(GEN_SERVER_OTHER_OBJECTS)
+
+GEN_SERVER_PROTO_SOURCES = $(GEN_SERVER_PROTO_OBJECTS:.o=.c)
+GEN_SERVER_SOURCES = $(GEN_SERVER_OBJECTS:.o=.c)
+
+GEN_SERVER_INCLUDES = C/aisc_server.h C/common.h
+GEN_SERVER_PROTO = GENH/aisc_server_proto.h
+GEN_SERVER_EXTERN_PROTO = GENH/aisc_server_extern.h
+
+SERVER_INCLUDES = $(GEN_INCLUDES) $(GEN_SERVER_INCLUDES) $(GEN_SERVER_PROTO) $(GEN_SERVER_EXTERN_PROTO)
+
+CLIENT_OBJECTS = O/client.o
+CLIENT_INCLUDES = $(GEN_INCLUDES) C/client_privat.h C/client.h C/common.h
+
+COMMON_OBJECTS = O/common.o
+COMMON_INCLUDES = C/common.h
+
+AISC_EXTERNALS = C/aisc_extern.c $(PRIVATE_SERVER_OBJECTS:.o=.c)
+GLOBALS_AISC = GENH/global.aisc
+
+AISC_DEPENDS = AISC/*.pa $(MAIN_SOURCE) $(AISC) $(DUMPDIR) $(GLOBALS_AISC)
+
+IMPORT_PROTO = GENH/import_proto.h
+
+SERVER = server.a
+CLIENT = client.a
+COMMON = common.a
+
+AISC_SERVER_EXTERN = GENH/aisc_server_extern.aisc
+
+DUMPDIR=DUMP
+
+LINK_TO_OTHER_ARB=~/ARB.aisc_regression_test_vs# create this as symlink to other ARB checkout to activate regression test
+FAIL_ON_CHANGE=1# 0=continue on change, 1=fail on change
+
+# ----------------------------------------
+
+COMPARE_WITH_OTHER_ARB:=$(shell $(READLINK) $(LINK_TO_OTHER_ARB))
+ifneq ($(COMPARE_WITH_OTHER_ARB),)
+THIS__COMDIR=$(shell pwd)
+COMDIRNAME=$(subst $(ARBHOME),,$(THIS__COMDIR))
+OTHER_COMDIR=$(subst //,/,$(COMPARE_WITH_OTHER_ARB)/$(COMDIRNAME))
+ifeq ($(FAIL_ON_CHANGE),0)
+REGR_FAILURE=(echo "$(THIS):57: Warning: regression on generated code (ignored)" || true)
+else
+REGR_FAILURE=( echo "$(THIS):59: Error: regression on generated AISC code"; \
+ rm $(SERVER) $(CLIENT) $(COMMON); \
+ false)
+endif
+endif
+
+# ----------------------------------------
+
+ifeq ($(AUTODEPENDS),1)
+all:
+ +test -f .depends || $(MAKETHIS) "AUTODEPENDS=0" .depends
+ +$(MAKETHIS) "AUTODEPENDS=2" all
+else
+all: directories
+ +$(MAKETHIS) realall
+
+endif
+
+realall: $(CLIENT) $(SERVER) $(COMMON) Makefile $(THIS)
+ifeq ($(COMPARE_WITH_OTHER_ARB),)
+ @echo "AISC regression tests are disabled ($(LINK_TO_OTHER_ARB) not found from AISC_COM/$(THIS))"
+else
+ ifeq ($(THIS__COMDIR),$(OTHER_COMDIR))
+ @echo "$(THIS):63: Warning: Skipping AISC regression tests (test versus self always ok)"
+ else
+ @echo "Running AISC regression tests (versus $(COMPARE_WITH_OTHER_ARB))"
+# compare generated code using ../../SOURCE_TOOLS/check_dirs_equal.sh
+ @( \
+ ../SOURCE_TOOLS/check_dirs_equal.sh $(THIS__COMDIR)/GENC $(OTHER_COMDIR)/GENC '*.c' && \
+ ../SOURCE_TOOLS/check_dirs_equal.sh $(THIS__COMDIR)/GENH $(OTHER_COMDIR)/GENH '*.h' && \
+ ../SOURCE_TOOLS/check_dirs_equal.sh $(THIS__COMDIR)/DUMP $(OTHER_COMDIR)/DUMP '*.dump' && \
+ echo "No change in generated code" \
+ ) || $(REGR_FAILURE)
+ endif
+endif
+
+pregenerate: $(GEN_SERVER_SOURCES) $(SERVER_INCLUDES) $(CLIENT_INCLUDES) $(AISC_EXTERNALS)
+
+directories:
+ @mkdir -p GENH GENC O DUMP
+
+GENH: directories
+GENC: directories
+O: directories
+DUMP: directories
+
+$(SERVER): $(SERVER_OBJECTS) $(GEN_SERVER_OBJECTS) $(PRIVATE_SERVER_OBJECTS)
+ $(LINK_STATIC_LIB) $@ $^
+
+$(CLIENT): $(CLIENT_OBJECTS) $(GEN_CLIENT_OBJECTS)
+ $(LINK_STATIC_LIB) $@ $^
+
+$(COMMON): $(COMMON_OBJECTS)
+ $(LINK_STATIC_LIB) $@ $^
+
+$(GEN_SERVER_OBJECTS) $(PRIVATE_SERVER_OBJECTS): $(SERVER_INCLUDES) $(GEN_SERVER_SOURCES) $(PRIVATE_SERVER_OBJECTS:.o=.c)
+ $(COMPILER) -c -o $@ $(@:.o=.c) -IGENH -I. -IC -DAISC_SAVE_$(AISC_SAVE) $(POST_COMPILE)
+
+O/%.o: C/%.c $(GEN_INCLUDES) $(CLIENT_INCLUDES) C/server.h
+ $(COMPILER) -c -o $@ $< -IGENH -I. -IC $(POST_COMPILE)
+
+$(CLIENT_OBJECTS): $(CLIENT_OBJECTS:O/%.o=C/%.c) $(GEN_INCLUDES) $(CLIENT_INCLUDES)
+ $(CLIENTCOMPILER) -c -o $@ C/$(@F:.o=.c) -IGENH -I. -IC $(POST_COMPILE)
+
+$(DUMPDIR):
+ mkdir -p $(DUMPDIR)
+
+$(GLOBALS_AISC).tmp:
+ @echo "AISC_SAVE $(AISC_SAVE);" > $@
+
+$(GLOBALS_AISC): $(GLOBALS_AISC).tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $(GLOBALS_AISC).tmp $(GLOBALS_AISC)
+
+GENH/%.h: AISC/%.pa $(AISC_DEPENDS) $(INCLUDE_INCLUDES)
+ $(RUN_AISC) $< $(MAIN_SOURCE) $@
+
+GENC/%.c: AISC/%.pa $(AISC_DEPENDS) $(AISC_SERVER_EXTERN) $(GEN_SERVER_INCLUDES)
+ $(RUN_AISC) $< $(MAIN_SOURCE) $@ $(AISC_SERVER_EXTERN) $(IMPORT_PROTO) $(GLOBALS_AISC)
+
+$(IMPORT_PROTO): $(GEN_SERVER_PROTO_SOURCES)
+ echo $@
+
+$(AISC_SERVER_EXTERN): $(AISC_EXTERNALS) $(AISC_MKPT) $(THIS)
+ rm -f $(AISC_SERVER_EXTERN)
+ $(AISC_MKPT) -a $(AISC_EXTERNALS) >$@
+
+$(GEN_SERVER_EXTERN_PROTO): $(AISC_EXTERNALS) $(AISC_MKPT) $(THIS)
+ rm -f $(GEN_SERVER_EXTERN_PROTO)
+ $(AISC_MKPT) -w $(subst GENH/,,$@) $(AISC_EXTERNALS) >$@
+
+$(GEN_SERVER_PROTO): $(GEN_SERVER_PROTO_SOURCES) $(AISC_MKPT) $(THIS)
+ rm -f $@
+ $(AISC_MKPT) -w $(subst GENH/,,$@) $(GEN_SERVER_PROTO_SOURCES) >$@
+
+clean:
+ @rm -f *.[ao] */*.[ao]
+ @rm -rf GENH GENC DUMP O
+ @rm -f .depends
+
+.depends:
+ $(MAKEDEPEND) $(MAKEDEPENDFLAGS) C/*.c GENC/*.c -I GENH -I C -f- -w1 2>/dev/null \
+ | grep -v ' /usr' \
+ | $(SED) -e 's/^C/O/ig' \
+ > .depends_new
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff .depends_new .depends
+
+ifeq ($(AUTODEPENDS),2)
+include .depends
+endif
=====================================
AISC_COM/C/Makefile
=====================================
@@ -0,0 +1,41 @@
+
+all:
+ echo "Available targets: proto"
+
+GENERATED_HEADERS= \
+ aisc_extern_privat.h \
+ client.h \
+ common.h \
+ server.h \
+ struct_man.h \
+
+AISC_MKPT_FLAGS=-P -G
+MKPT_DEP=../../AISC_MKPTPS/aisc_mkpt Makefile
+
+proto:
+ $(MAKE) $(GENERATED_HEADERS)
+
+clean:
+ rm $(GENERATED_HEADERS)
+
+aisc_extern_privat.h: aisc_extern.c $(MKPT_DEP)
+ $(ARBHOME)/AISC_MKPTPS/aisc_mkpt $(AISC_MKPT_FLAGS) -w $@ $< >$@.tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $@.tmp $@
+
+client.h: client.c $(MKPT_DEP)
+ $(ARBHOME)/AISC_MKPTPS/aisc_mkpt $(AISC_MKPT_FLAGS) -w $@ $< >$@.tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $@.tmp $@
+
+common.h: common.c $(MKPT_DEP)
+ $(ARBHOME)/AISC_MKPTPS/aisc_mkpt $(AISC_MKPT_FLAGS) -w $@ $< >$@.tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $@.tmp $@
+
+struct_man.h: struct_man.c $(MKPT_DEP)
+ $(ARBHOME)/AISC_MKPTPS/aisc_mkpt $(AISC_MKPT_FLAGS) -w $@ $< >$@.tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $@.tmp $@
+
+server.h: server.c $(MKPT_DEP)
+ $(ARBHOME)/AISC_MKPTPS/aisc_mkpt $(AISC_MKPT_FLAGS) -w $@ $< >$@.tmp
+ $(ARBHOME)/SOURCE_TOOLS/mv_if_diff $@.tmp $@
+
+
=====================================
AISC_COM/C/aisc_extern.c
=====================================
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <string.h>
+#include <aisc.h>
+#include <server.h>
+#include "aisc_extern_privat.h"
+
+extern int aisc_d_flags[];
+
+dll_public *create_dll_public() {
+ return 0;
+}
+
+int move_dll_header(const dll_header *sobj, dll_header *dobj) {
+ dobj->ident = strdup(sobj->ident);
+ return 0;
+}
+
+int get_COMMON_CNT(dll_header *THIS) {
+ int key = (int)(THIS->key) >> 16;
+ if (aisc_d_flags[key] == 0) return -1;
+ if (!((THIS->parent))) { return 0; }
+ return THIS->parent->cnt;
+}
+
+dllheader_ext *get_COMMON_PARENT(dll_header *THIS) {
+ int key = (int)(THIS->key) >> 16;
+ if (aisc_d_flags[key] == 0) return 0;
+ if (!THIS->parent) { return 0; }
+ return THIS->parent->parent;
+}
+
+dllheader_ext *get_COMMON_LAST(dll_header *THIS) {
+ int key = (int)(THIS->key) >> 16;
+ if (aisc_d_flags[key] == 0) return 0;
+ if (!THIS->parent) { return 0; }
+ return THIS->parent->last;
+}
+
+aisc_cstring aisc_get_keystring(int *obj) {
+ int i;
+ i = *obj>>16;
+ return aisc_get_object_names(i);
+}
+
+aisc_cstring aisc_get_keystring_dll_header(dll_header *x) {
+ return aisc_get_keystring((int*)x);
+}
=====================================
AISC_COM/C/aisc_extern_privat.h
=====================================
@@ -0,0 +1,25 @@
+/* This file is generated by aisc_mkpt.
+ * Any changes you make here will be overwritten later!
+ */
+
+#ifndef AISC_EXTERN_PRIVAT_H
+#define AISC_EXTERN_PRIVAT_H
+
+/* define ARB attributes: */
+#ifndef ATTRIBUTES_H
+# include <attributes.h>
+#endif
+
+
+/* aisc_extern.c */
+dll_public *create_dll_public(void);
+int move_dll_header(const dll_header *sobj, dll_header *dobj);
+int get_COMMON_CNT(dll_header *THIS);
+dllheader_ext *get_COMMON_PARENT(dll_header *THIS);
+dllheader_ext *get_COMMON_LAST(dll_header *THIS);
+aisc_cstring aisc_get_keystring(int *obj);
+aisc_cstring aisc_get_keystring_dll_header(dll_header *x);
+
+#else
+#error aisc_extern_privat.h included twice
+#endif /* AISC_EXTERN_PRIVAT_H */
=====================================
AISC_COM/C/aisc_func_types.h
=====================================
@@ -0,0 +1,30 @@
+// =============================================================== //
+// //
+// File : aisc_func_types.h //
+// Purpose : //
+// //
+// Coded by Ralf Westram (coder at reallysoft.de) in 2000 //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// =============================================================== //
+
+#ifndef AISC_FUNC_TYPES_H
+#define AISC_FUNC_TYPES_H
+
+struct sigcontext;
+struct Hs_struct;
+
+#define aisc_talking_func_proto_void(func_name) void func_name(long arg1, ...)
+#define aisc_talking_func_proto_long(func_name) long func_name(long arg1, ...)
+#define aisc_talking_func_proto_longp(func_name) long* func_name(long arg1, ...)
+#define aisc_talking_func_proto_double(func_name) double func_name(long arg1, ...)
+
+typedef aisc_talking_func_proto_void((*aisc_destroy_callback));
+typedef aisc_talking_func_proto_long((*aisc_talking_func_long));
+typedef aisc_talking_func_proto_longp((*aisc_talking_func_longp));
+typedef aisc_talking_func_proto_double((*aisc_talking_func_double));
+
+#else
+#error aisc_func_types.h included twice
+#endif // AISC_FUNC_TYPES_H
=====================================
AISC_COM/C/aisc_global.h
=====================================
@@ -0,0 +1,78 @@
+// =============================================================== //
+// //
+// File : aisc_global.h //
+// Purpose : //
+// //
+// Coded by Ralf Westram (coder at reallysoft.de) in May 2007 //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// =============================================================== //
+#ifndef AISC_GLOBAL_H
+#define AISC_GLOBAL_H
+
+#ifndef BYTESTRING_H
+#include <bytestring.h>
+#endif
+#ifndef ARBTOOLS_H
+#include <arbtools.h>
+#endif
+#ifndef ATTRIBUTES_H
+#include <attributes.h>
+#endif
+#ifndef ARB_ASSERT_H
+#include <arb_assert.h>
+#endif
+
+#define aisc_assert(cond) arb_assert(cond)
+
+// type mask
+#define AISC_TYPE_NONE 0x00000000
+#define AISC_TYPE_INT 0x01000000
+#define AISC_TYPE_DOUBLE 0x02000000
+#define AISC_TYPE_STRING 0x03000000
+#define AISC_TYPE_COMMON 0x04000000
+#define AISC_TYPE_BYTES 0x05000000
+
+#define AISC_VAR_TYPE_MASK 0xff000000
+#define AISC_OBJ_TYPE_MASK 0x00ff0000
+#define AISC_ATTR_MASK 0x0000ffff
+
+#define AISC_INDEX 0x1ff0000
+#define AISC_NO_ANSWER -0x7fffffff
+
+#define AISC_COMMON 0
+
+union double_xfer { // workaround aliasing problems
+ double as_double;
+ int as_int[2];
+};
+
+class AISC_Object : public Noncopyable {
+ int type_id;
+ long remote_ptr; // this is a pointer to client-data in server-address-space (casted to long)
+
+ void *operator&() { return 0; } // forbid error-prone idiom (AISC_Object just was 'long' in the past). Instead use as_result_param()
+
+protected:
+
+ void set(int IF_ASSERTION_USED(remoteType), long remotePtr) { aisc_assert(remoteType == type_id); remote_ptr = remotePtr; }
+
+public:
+ AISC_Object(int type_) : type_id(type_), remote_ptr(0) {}
+
+ bool exists() const { return remote_ptr; }
+ long get() const { return remote_ptr; }
+ int type() const { return type_id; }
+
+ void clear() { remote_ptr = 0; }
+ void init(long remotePtr) { aisc_assert(!exists()); set(type_id, remotePtr); }
+
+ long *as_result_param() { return &remote_ptr; }
+
+};
+
+#else
+#error aisc_global.h included twice
+#endif // AISC_GLOBAL_H
+
=====================================
AISC_COM/C/aisc_server.h
=====================================
@@ -0,0 +1,25 @@
+// --------------------------------------------------------------------------------
+// start ../../AISC_COM/C/aisc_server.h
+//
+// [Note: This header isn't included directly, it's merged into generated code by AISC]
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dupstr.h>
+#include <aisc.h>
+#include <aisc_com.h>
+
+#ifndef ATTRIBUTES_H
+#include <attributes.h>
+#endif
+#include <server.h>
+#include <aisc_server_proto.h>
+#include <aisc_server_extern.h>
+#include <import_proto.h>
+
+#include <struct_man.h>
+
+// end ../../AISC_COM/C/aisc_server.h
+// --------------------------------------------------------------------------------
=====================================
AISC_COM/C/client.c
=====================================
@@ -0,0 +1,677 @@
+// ===============================================================
+/* */
+// File : client.c
+// Purpose :
+/* */
+// Institute of Microbiology (Technical University Munich)
+// http://www.arb-home.de/
+/* */
+// ===============================================================
+
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+
+#include <unistd.h>
+#include <cstdarg>
+
+#include <arb_cs.h>
+
+#include "client_privat.h"
+#include "client.h"
+#include "common.h"
+
+#include "trace.h"
+
+#define aisc_assert(cond) arb_assert(cond)
+
+// AISC_MKPT_PROMOTE:#include <client_types.h>
+
+#define AISC_MAGIC_NUMBER_FILTER 0xffffff00
+
+static const char *err_connection_problems = "CONNECTION PROBLEMS";
+
+int aisc_core_on_error = 1;
+
+#define CORE() \
+ do { \
+ if (aisc_core_on_error) { \
+ ARB_SIGSEGV(true); \
+ } \
+ } while (0)
+
+aisc_com *aisc_client_link;
+
+static int aisc_print_error_to_stderr = 1;
+static char errbuf[300];
+
+#define PRTERR(msg) if (aisc_print_error_to_stderr) fprintf(stderr, "%s: %s\n", msg, link->error);
+
+
+static int aisc_c_read(int socket, char *ptr, long size) {
+ long leftsize = size;
+ while (leftsize) {
+ long readsize = read(socket, ptr, (size_t)leftsize);
+ if (readsize<=0) return 0;
+ ptr += readsize;
+ leftsize -= readsize;
+ }
+ return size;
+}
+
+static int aisc_c_write(int socket, const char *ptr, int size) {
+ int leftsize = size;
+ while (leftsize) {
+ int writesize = write(socket, ptr, leftsize);
+ if (writesize<=0) return 0;
+ ptr += writesize;
+ leftsize -= writesize;
+ }
+ return size;
+}
+
+// -----------------------------
+// bytestring handling
+
+
+static void aisc_c_add_to_bytes_queue(aisc_com *link, char *data, int size)
+{
+ aisc_bytes_list *bl = (aisc_bytes_list *)calloc(sizeof(*bl), 1);
+#ifndef NDEBUG
+ memset(bl, 0, sizeof(*bl)); // @@@ clear mem needed to avoid (rui's)
+#endif
+ bl->data = data;
+ bl->size = size;
+
+ if (link->aisc_client_bytes_first) {
+ link->aisc_client_bytes_last->next = bl;
+ link->aisc_client_bytes_last = bl;
+ }
+ else {
+ link->aisc_client_bytes_first = bl;
+ link->aisc_client_bytes_last = bl;
+ }
+}
+
+static int aisc_c_send_bytes_queue(aisc_com *link) {
+ int len;
+ aisc_bytes_list *bl, *bl_next;
+ for (bl = link->aisc_client_bytes_first; bl; bl=bl_next) {
+ bl_next = bl->next;
+ len = aisc_c_write(link->socket, bl->data, bl->size);
+ free(bl);
+ if (len<0)return 1;
+ };
+ link->aisc_client_bytes_first = link->aisc_client_bytes_last = NULL;
+ return 0;
+}
+
+// --------------------------
+// message handling
+
+struct client_msg_queue {
+ client_msg_queue *next;
+ int message_type;
+ char *message;
+};
+
+static int aisc_add_message_queue(aisc_com *link, long size)
+{
+ client_msg_queue *msg = (client_msg_queue *) calloc(sizeof(client_msg_queue), 1);
+ char *buffer = (char *)calloc(sizeof(char), (size_t)size);
+ long len = aisc_c_read(link->socket, buffer, size);
+
+ if (len != size) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_ERROR");
+ return 1;
+ }
+ msg->message = strdup(buffer+sizeof(long));
+ msg->message_type = (int)*(long *)buffer;
+ free(buffer);
+
+ if (link->message_queue == 0) {
+ link->message_queue = (int *)msg;
+ }
+ else {
+ client_msg_queue *mp;
+ for (mp = (client_msg_queue *)link->message_queue; mp->next; mp=mp->next) ;
+ mp->next = msg;
+ }
+ return 0;
+}
+
+static int aisc_check_error(aisc_com * link)
+{
+ int len;
+ long magic_number;
+ long size;
+
+ aisc_check_next :
+
+ link->error = 0; // @@@ avoid (rui)
+ len = aisc_c_read(link->socket, (char *)(link->aisc_mes_buffer), 2*sizeof(long));
+ if (len != 2*sizeof(long)) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_ERROR");
+ return 1;
+ }
+ if (link->aisc_mes_buffer[0] >= AISC_MESSAGE_BUFFER_LEN) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_ERROR");
+ return 1;
+ }
+ magic_number = link->aisc_mes_buffer[1];
+ if ((unsigned long)(magic_number & AISC_MAGIC_NUMBER_FILTER) != (unsigned long)(link->magic & AISC_MAGIC_NUMBER_FILTER)) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_ERROR");
+ return 1;
+ }
+ size = link->aisc_mes_buffer[0];
+ if (size) {
+ if (magic_number-link->magic == AISC_CCOM_MESSAGE) {
+ if (aisc_add_message_queue(link, size*sizeof(long))) return 1;
+ goto aisc_check_next;
+
+ }
+ len = aisc_c_read(link->socket, (char *)(link->aisc_mes_buffer), size * sizeof(long));
+ if (len != (long)(size*sizeof(long))) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_ERROR");
+ return 1;
+ }
+ switch (magic_number-link->magic) {
+ case AISC_CCOM_OK:
+ return 0;
+ case AISC_CCOM_ERROR:
+ sprintf(errbuf, "SERVER_ERROR: %s", (char *)(link->aisc_mes_buffer));
+ link->error = errbuf;
+ PRTERR("AISC_ERROR");
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+
+
+static long aisc_init_client(aisc_com *link)
+{
+ int len, mes_cnt;
+ mes_cnt = 2;
+ link->aisc_mes_buffer[0] = mes_cnt-2;
+ link->aisc_mes_buffer[1] = AISC_INIT+link->magic;
+ len = aisc_c_write(link->socket, (const char *)link->aisc_mes_buffer, mes_cnt * sizeof(long));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_CONN_ERROR");
+ return 0;
+ }
+ aisc_check_error(link);
+ return link->aisc_mes_buffer[0];
+}
+
+static void ignore_sigpipe(int) {
+}
+
+static void aisc_free_link(aisc_com *link) {
+ if (link->old_sigpipe_handler != SIG_ERR) { // failed to install -> do not uninstall
+ UNINSTALL_SIGHANDLER(SIGPIPE, ignore_sigpipe, link->old_sigpipe_handler, "aisc_free_link");
+ }
+ free(link);
+}
+
+aisc_com *aisc_open(const char *path, AISC_Object& main_obj, long magic, GB_ERROR *error) {
+ aisc_com *link;
+ const char *err;
+
+ aisc_assert(error && !*error);
+ aisc_assert(!main_obj.exists()); // already initialized
+
+ link = (aisc_com *) calloc(sizeof(aisc_com), 1);
+ link->aisc_client_bytes_first = link->aisc_client_bytes_last = NULL;
+ link->magic = magic;
+ {
+ static char *unix_name = 0;
+ err = aisc_client_open_socket(path, TCP_NODELAY, 1, &link->socket, &unix_name);
+ freenull(unix_name);
+ }
+ if (err) {
+ if (*err) {
+ link->error = err;
+ PRTERR("ARB_DB_CLIENT_OPEN");
+ }
+ if (link->socket) {
+ shutdown(link->socket, SHUT_RDWR);
+ close(link->socket);
+ }
+ *error = link->error;
+ free(link);
+ aisc_assert(!(*error && main_obj.exists()));
+ return 0;
+ }
+
+ link->old_sigpipe_handler = INSTALL_SIGHANDLER(SIGPIPE, ignore_sigpipe, "aisc_open");
+
+ main_obj.init(aisc_init_client(link));
+ if (!main_obj.exists() || link->error) {
+ *error = link->error;
+ main_obj.clear();
+ aisc_free_link(link);
+ aisc_assert(!(*error && main_obj.exists()));
+ return 0;
+ }
+ aisc_client_link = link;
+ aisc_assert(!*error);
+ return link;
+}
+
+int aisc_close(aisc_com *link, AISC_Object& object) {
+ if (link) {
+ if (link->socket) {
+ link->aisc_mes_buffer[0] = 0;
+ link->aisc_mes_buffer[1] = 0;
+ link->aisc_mes_buffer[2] = 0;
+ aisc_c_write(link->socket, (const char *)link->aisc_mes_buffer, 3 * sizeof(long));
+ shutdown(link->socket, SHUT_RDWR);
+ close(link->socket);
+ link->socket = 0;
+ }
+ aisc_free_link(link);
+ }
+ object.clear();
+ return 0;
+}
+
+int aisc_get(aisc_com *link, int o_type, const AISC_Object& object, ...)
+{
+ // goes to header: __ATTR__SENTINEL
+ long *arg_pntr[MAX_AISC_SET_GET];
+ long arg_types[MAX_AISC_SET_GET];
+ long mes_cnt;
+ long arg_cnt;
+ va_list parg;
+ long type, o_t;
+ long attribute, code;
+ long count;
+ long i, len;
+ long size;
+
+ AISC_DUMP_SEP();
+
+ mes_cnt = 2;
+ arg_cnt = 0;
+ count = 4;
+
+ link->aisc_mes_buffer[mes_cnt++] = object.get();
+ aisc_assert(object.type() == o_type);
+
+ va_start(parg, object);
+ while ((code=va_arg(parg, long))) {
+ attribute = code & AISC_ATTR_MASK;
+ type = code & AISC_VAR_TYPE_MASK;
+ o_t = code & AISC_OBJ_TYPE_MASK;
+
+ if ((o_t != (int)o_type)) {
+ sprintf(errbuf, "ARG NR %li DON'T FIT OBJECT", count);
+ link->error = errbuf;
+ PRTERR("AISC_GET_ERROR");
+ CORE();
+ return 1;
+ };
+
+ if ((attribute > AISC_MAX_ATTR)) {
+ sprintf(errbuf, "ARG %li IS NOT AN ATTRIBUTE_TYPE", count);
+ link->error = errbuf;
+ PRTERR("AISC_GET_ERROR");
+ CORE();
+ return 1;
+ };
+ link->aisc_mes_buffer[mes_cnt++] = code;
+ arg_pntr[arg_cnt] = va_arg(parg, long *);
+ arg_types[arg_cnt++] = type;
+ count += 2;
+ if (arg_cnt>=MAX_AISC_SET_GET) {
+ sprintf(errbuf, "TOO MANY ARGS (>%i)", MAX_AISC_SET_GET);
+ link->error = errbuf;
+ PRTERR("AISC_GET_ERROR");
+ CORE();
+ return 1;
+ }
+ }
+ va_end(parg);
+ if (mes_cnt > 3) {
+ link->aisc_mes_buffer[0] = mes_cnt - 2;
+ link->aisc_mes_buffer[1] = AISC_GET+link->magic;
+ len = aisc_c_write(link->socket, (const char *)(link->aisc_mes_buffer), (size_t)(mes_cnt * sizeof(long)));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_GET_ERROR");
+ return 1;
+ }
+
+ if (aisc_check_error(link)) return 1;
+ mes_cnt = 0;
+ for (i=0; i<arg_cnt; i++) {
+ switch (arg_types[i]) {
+ case AISC_TYPE_INT:
+ case AISC_TYPE_COMMON:
+ AISC_DUMP(aisc_get, int, link->aisc_mes_buffer[mes_cnt]);
+ arg_pntr[i][0] = link->aisc_mes_buffer[mes_cnt++];
+ break;
+ case AISC_TYPE_DOUBLE:
+ AISC_DUMP(aisc_get, double, *(double*)(char*)/*avoid aliasing problems*/&(link->aisc_mes_buffer[mes_cnt]));
+ ((int*)arg_pntr[i])[0] = (int)(link->aisc_mes_buffer[mes_cnt++]);
+ ((int*)arg_pntr[i])[1] = (int)(link->aisc_mes_buffer[mes_cnt++]);
+ break;
+ case AISC_TYPE_STRING: {
+ char *str = strdup((char *)(&(link->aisc_mes_buffer[mes_cnt+1])));
+ AISC_DUMP(aisc_get, charPtr, str);
+ arg_pntr[i][0] = (long)str;
+ mes_cnt += link->aisc_mes_buffer[mes_cnt] + 1;
+ break;
+ }
+ case AISC_TYPE_BYTES:
+ size = arg_pntr[i][1] = link->aisc_mes_buffer[mes_cnt++];
+ AISC_DUMP(aisc_get, int, size);
+ if (size) {
+ arg_pntr[i][0] = (long)calloc(sizeof(char), (size_t)size);
+ len = aisc_c_read(link->socket, (char *)(arg_pntr[i][0]), size);
+ if (size!=len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_GET_ERROR");
+ }
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_get bytestring: ", (char *)(arg_pntr[i][0]), size);
+#endif // DUMP_COMMUNICATION
+ }
+ else {
+ arg_pntr[i][0] = 0;
+ }
+ break;
+
+ default:
+ link->error = "UNKNOWN TYPE";
+ PRTERR("AISC_GET_ERROR");
+ CORE();
+ return 1;
+ }
+ }
+
+ }
+ return 0;
+}
+
+long *aisc_debug_info(aisc_com *link, int o_type, const AISC_Object& object, int attribute)
+{
+ int mes_cnt;
+ int o_t;
+ int len;
+
+ mes_cnt = 2;
+ o_t = attribute & AISC_OBJ_TYPE_MASK;
+ if ((o_t != (int)o_type)) {
+ link->error = "ATTRIBUTE DON'T FIT OBJECT";
+ PRTERR("AISC_DEBUG_ERROR");
+ CORE();
+ return 0;
+ };
+ attribute = attribute&0xffff;
+ if ((attribute > AISC_MAX_ATTR)) {
+ link->error = "CLIENT DEBUG NOT CORRECT TYPE";
+ PRTERR("AISC_DEBUG_ERROR");
+ CORE();
+ return 0;
+ };
+ aisc_assert(object.type() == o_type);
+ link->aisc_mes_buffer[mes_cnt++] = object.get();
+ link->aisc_mes_buffer[mes_cnt++] = attribute;
+ link->aisc_mes_buffer[0] = mes_cnt - 2;
+ link->aisc_mes_buffer[1] = AISC_DEBUG_INFO+link->magic;
+ len = aisc_c_write(link->socket, (const char *)(link->aisc_mes_buffer), mes_cnt * sizeof(long));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_GET_ERROR");
+ return 0;
+ }
+ if (aisc_check_error(link)) return 0;
+ return &(link->aisc_mes_buffer[0]);
+}
+
+
+inline char *part_of(const char *str, size_t max_len, size_t str_len) {
+ aisc_assert(strlen(str) == str_len);
+ char *part;
+ if (str_len <= max_len) {
+ part = strdup(str);
+ }
+ else {
+ const int DOTS = 3;
+ int copy = max_len-DOTS;
+
+ part = (char*)malloc(max_len+1);
+ memcpy(part, str, copy);
+ memset(part+copy, '.', DOTS);
+
+ part[max_len] = 0;
+ }
+ return part;
+}
+
+static int aisc_collect_sets(aisc_com *link, int mes_cnt, va_list parg, int o_type, int count) {
+ int type, o_t; // @@@ fix locals
+ int attribute, code;
+ int len, ilen;
+ char *str;
+ int arg_cnt = 0;
+
+ AISC_DUMP_SEP();
+
+ while ((code=va_arg(parg, int))) {
+ attribute = code & AISC_ATTR_MASK;
+ type = code & AISC_VAR_TYPE_MASK;
+ o_t = code & AISC_OBJ_TYPE_MASK;
+
+ if (code != AISC_INDEX) {
+ if ((o_t != (int)o_type)) {
+ sprintf(errbuf, "ATTRIBUTE ARG NR %i DON'T FIT OBJECT", count);
+ link->error = errbuf;
+ PRTERR("AISC_SET_ERROR");
+ CORE();
+ return 0;
+ }
+ if ((attribute > AISC_MAX_ATTR)) {
+ sprintf(errbuf, "ARG %i IS NOT AN ATTRIBUTE_TYPE", count);
+ link->error = errbuf;
+ PRTERR("AISC_SET_ERROR");
+ CORE();
+ return 0;
+ }
+ }
+ link->aisc_mes_buffer[mes_cnt++] = code;
+ switch (type) {
+ case AISC_TYPE_INT:
+ case AISC_TYPE_COMMON:
+ link->aisc_mes_buffer[mes_cnt++] = va_arg(parg, long);
+ AISC_DUMP(aisc_collect_sets, int, link->aisc_mes_buffer[mes_cnt-1]);
+ break;
+ case AISC_TYPE_DOUBLE: {
+ double_xfer darg;
+
+ darg.as_double = va_arg(parg, double);
+ AISC_DUMP(aisc_collect_sets, double, darg.as_double);
+
+ link->aisc_mes_buffer[mes_cnt++] = darg.as_int[0];
+ link->aisc_mes_buffer[mes_cnt++] = darg.as_int[1];
+ break;
+ }
+ case AISC_TYPE_STRING:
+ str = va_arg(parg, char *);
+ AISC_DUMP(aisc_collect_sets, charPtr, str);
+ len = strlen(str)+1;
+ if (len > AISC_MAX_STRING_LEN) {
+ char *strpart = part_of(str, AISC_MAX_STRING_LEN-40, len-1);
+ sprintf(errbuf, "ARG %i: STRING \'%s\' TOO LONG", count+2, strpart);
+ free(strpart);
+
+ link->error = errbuf;
+ PRTERR("AISC_SET_ERROR");
+ CORE();
+
+ return 0;
+ }
+ ilen = (len)/sizeof(long) + 1;
+ link->aisc_mes_buffer[mes_cnt++] = ilen;
+ memcpy((char *)(&(link->aisc_mes_buffer[mes_cnt])), str, len);
+ mes_cnt += ilen;
+ break;
+
+ case AISC_TYPE_BYTES:
+ {
+ bytestring *bs;
+ bs = va_arg(parg, bytestring *);
+ AISC_DUMP(aisc_collect_sets, int, bs->size);
+ if (bs->data && bs->size) {
+ aisc_c_add_to_bytes_queue(link, bs->data, bs->size);
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_collect_sets bytestring: ", bs->data, bs->size);
+#endif // DUMP_COMMUNICATION
+ }
+ link->aisc_mes_buffer[mes_cnt++] = bs->size; // size
+ break;
+ }
+ default:
+ link->error = "UNKNOWN TYPE";
+ PRTERR("AISC_SET_ERROR");
+ CORE();
+ return 0;
+ }
+
+ count += 2;
+ if ((arg_cnt++) >= MAX_AISC_SET_GET) {
+ sprintf(errbuf, "TOO MANY ARGS (>%i)", MAX_AISC_SET_GET);
+ link->error = errbuf;
+ PRTERR("AISC_SET_ERROR");
+ CORE();
+ return 0;
+ }
+ }
+ return mes_cnt;
+}
+
+ // @@@ DRY aisc_put vs aisc_nput
+ // @@@ the difference between aisc_put and aisc_nput is: aisc_put may return an error from server
+
+int aisc_put(aisc_com *link, int o_type, const AISC_Object& object, ...) { // goes to header: __ATTR__SENTINEL
+ aisc_assert(object.type() == o_type);
+
+ int mes_cnt = 2;
+ link->aisc_mes_buffer[mes_cnt++] = object.get();
+ link->aisc_mes_buffer[mes_cnt++] = o_type;
+
+ va_list parg;
+ va_start(parg, object);
+ if (!(mes_cnt = aisc_collect_sets(link, mes_cnt, parg, o_type, 4))) return 1;
+
+ if (mes_cnt > 3) {
+ link->aisc_mes_buffer[0] = mes_cnt - 2;
+ link->aisc_mes_buffer[1] = AISC_SET+link->magic;
+ int len = aisc_c_write(link->socket, (const char *)(link->aisc_mes_buffer), mes_cnt * sizeof(long));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_SET_ERROR");
+ return 1;
+ }
+ if (aisc_c_send_bytes_queue(link)) return 1;
+ if (aisc_check_error(link)) return 1;
+ }
+ return 0;
+}
+
+int aisc_nput(aisc_com *link, int o_type, const AISC_Object& object, ...) { // goes to header: __ATTR__SENTINEL
+ aisc_assert(object.type() == o_type);
+
+ int mes_cnt = 2;
+ link->aisc_mes_buffer[mes_cnt++] = object.get();
+ link->aisc_mes_buffer[mes_cnt++] = o_type;
+
+ va_list parg;
+ va_start(parg, object);
+ if (!(mes_cnt = aisc_collect_sets(link, mes_cnt, parg, o_type, 4))) {
+ return 1;
+ }
+
+ if (mes_cnt > 3) {
+ link->aisc_mes_buffer[0] = mes_cnt - 2;
+ link->aisc_mes_buffer[1] = AISC_NSET+link->magic;
+ int len = aisc_c_write(link->socket, (const char *)(link->aisc_mes_buffer), mes_cnt * sizeof(long));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_SET_ERROR");
+ return 1;
+ }
+ if (aisc_c_send_bytes_queue(link)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int aisc_create(aisc_com *link, int father_type, const AISC_Object& father,
+ int attribute, int object_type, AISC_Object& object, ...)
+{
+ // goes to header: __ATTR__SENTINEL
+ // arguments in '...' set elements of CREATED object (not of father)
+ int mes_cnt;
+ int len;
+ va_list parg;
+ mes_cnt = 2;
+ if ((father_type&0xff00ffff)) {
+ link->error = "FATHER_TYPE UNKNOWN";
+ PRTERR("AISC_CREATE_ERROR");
+ CORE();
+ return 1;
+ }
+ if ((object_type&0xff00ffff)) {
+ link->error = "OBJECT_TYPE UNKNOWN";
+ PRTERR("AISC_CREATE_ERROR");
+ CORE();
+ return 1;
+ }
+ aisc_assert(father.type() == father_type);
+ aisc_assert(object.type() == object_type);
+ link->aisc_mes_buffer[mes_cnt++] = father_type;
+ link->aisc_mes_buffer[mes_cnt++] = father.get();
+ link->aisc_mes_buffer[mes_cnt++] = attribute;
+ link->aisc_mes_buffer[mes_cnt++] = object_type;
+ if (father_type != (attribute & AISC_OBJ_TYPE_MASK)) {
+ link->error = "ATTRIBUTE TYPE DON'T FIT OBJECT";
+ PRTERR("AISC_CREATE_ERROR");
+ CORE();
+ return 1;
+ }
+ va_start(parg, object);
+ if (!(mes_cnt = aisc_collect_sets(link, mes_cnt, parg, object_type, 7))) return 1;
+ link->aisc_mes_buffer[0] = mes_cnt - 2;
+ link->aisc_mes_buffer[1] = AISC_CREATE+link->magic;
+ len = aisc_c_write(link->socket, (const char *)(link->aisc_mes_buffer), mes_cnt * sizeof(long));
+ if (!len) {
+ link->error = err_connection_problems;
+ PRTERR("AISC_CREATE_ERROR");
+ return 1;
+ }
+ if (aisc_c_send_bytes_queue(link)) return 1;
+ if (aisc_check_error(link)) return 1;
+ object.init(link->aisc_mes_buffer[0]);
+ return 0;
+}
+
+/* --------------------------------------------------------------------------------
+ * Note: it's not possible to define unit tests here - they won't execute
+ * Instead put your tests into ../../SERVERCNTRL/servercntrl.cxx at UNIT_TESTS
+ */
+
+
=====================================
AISC_COM/C/client.h
=====================================
@@ -0,0 +1,28 @@
+/* This file is generated by aisc_mkpt.
+ * Any changes you make here will be overwritten later!
+ */
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+/* define ARB attributes: */
+#ifndef ATTRIBUTES_H
+# include <attributes.h>
+#endif
+
+
+/* client.c */
+
+#include <client_types.h>
+
+aisc_com *aisc_open(const char *path, AISC_Object& main_obj, long magic, GB_ERROR *error);
+int aisc_close(aisc_com *link, AISC_Object& object);
+int aisc_get(aisc_com *link, int o_type, const AISC_Object& object, ...) __ATTR__SENTINEL;
+long *aisc_debug_info(aisc_com *link, int o_type, const AISC_Object& object, int attribute);
+int aisc_put(aisc_com *link, int o_type, const AISC_Object& object, ...) __ATTR__SENTINEL;
+int aisc_nput(aisc_com *link, int o_type, const AISC_Object& object, ...) __ATTR__SENTINEL;
+int aisc_create(aisc_com *link, int father_type, const AISC_Object& father, int attribute, int object_type, AISC_Object& object, ...) __ATTR__SENTINEL;
+
+#else
+#error client.h included twice
+#endif /* CLIENT_H */
=====================================
AISC_COM/C/client_privat.h
=====================================
@@ -0,0 +1,74 @@
+// =============================================================== //
+// //
+// File : client_privat.h //
+// Purpose : //
+// //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// =============================================================== //
+
+#ifndef CLIENT_PRIVAT_H
+#define CLIENT_PRIVAT_H
+
+#ifndef AISC_GLOBAL_H
+#include "aisc_global.h"
+#endif
+
+
+#ifndef ARB_ASSERT_H
+#include <arb_assert.h>
+#endif
+#ifndef SIGHANDLER_H
+#include <SigHandler.h>
+#endif
+
+#define AISC_MAX_ATTR 4095
+#define MAX_AISC_SET_GET 16
+#define AISC_MAX_STRING_LEN 1024
+#define AISC_MESSAGE_BUFFER_LEN ((AISC_MAX_STRING_LEN/4+3)*(16+2))
+
+struct aisc_bytes_list {
+ char *data;
+ int size;
+ aisc_bytes_list *next;
+};
+
+struct aisc_com {
+ int socket;
+ int message_type;
+ char *message;
+ int *message_queue;
+ long magic;
+ const char *error;
+
+ long aisc_mes_buffer[AISC_MESSAGE_BUFFER_LEN];
+ aisc_bytes_list *aisc_client_bytes_first;
+ aisc_bytes_list *aisc_client_bytes_last;
+ SigHandler old_sigpipe_handler;
+};
+
+#define AISC_MAGIC_NUMBER 0
+
+enum aisc_command_list {
+ AISC_GET = AISC_MAGIC_NUMBER + 0,
+ AISC_SET = AISC_MAGIC_NUMBER + 1,
+ AISC_NSET = AISC_MAGIC_NUMBER + 2,
+ AISC_CREATE = AISC_MAGIC_NUMBER + 3,
+ AISC_FIND = AISC_MAGIC_NUMBER + 4,
+ AISC_COPY = AISC_MAGIC_NUMBER + 5,
+ AISC_DELETE = AISC_MAGIC_NUMBER + 6,
+ AISC_INIT = AISC_MAGIC_NUMBER + 7,
+ AISC_DEBUG_INFO = AISC_MAGIC_NUMBER + 8,
+ AISC_FORK_SERVER = AISC_MAGIC_NUMBER + 9
+};
+
+enum aisc_client_command_list {
+ AISC_CCOM_OK = AISC_MAGIC_NUMBER + 0,
+ AISC_CCOM_ERROR = AISC_MAGIC_NUMBER + 1,
+ AISC_CCOM_MESSAGE = AISC_MAGIC_NUMBER + 2
+};
+
+#else
+#error client_privat.h included twice
+#endif // CLIENT_PRIVAT_H
=====================================
AISC_COM/C/client_types.h
=====================================
@@ -0,0 +1,28 @@
+// ============================================================== //
+// //
+// File : client_types.h //
+// Purpose : AISC types used by clients //
+// //
+// Coded by Ralf Westram (coder at reallysoft.de) in August 2010 //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// ============================================================== //
+
+#ifndef CLIENT_TYPES_H
+#define CLIENT_TYPES_H
+
+#ifndef __cplusplus
+#error AISC clients no longer work in plain C
+#endif
+
+#ifndef AISC_GLOBAL_H
+#include <aisc_global.h>
+#endif
+#ifndef ARB_ASSERT_H
+#include <arb_assert.h>
+#endif
+
+#else
+#error client_types.h included twice
+#endif // CLIENT_TYPES_H
=====================================
AISC_COM/C/common.c
=====================================
@@ -0,0 +1,206 @@
+// ================================================================ //
+// //
+// File : common.c //
+// Purpose : Common code for server and client //
+// //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// ================================================================ //
+
+#include "common.h"
+
+#include <dupstr.h>
+#include <arb_cs.h>
+#include <arb_msg.h>
+#include <arb_assert.h>
+
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+enum ClientOrServer { AISC_SERVER, AISC_CLIENT };
+
+inline const char *who(ClientOrServer cos) {
+ switch (cos) {
+ case AISC_SERVER: return "AISC_SERVER";
+ case AISC_CLIENT: return "AISC_CLIENT";
+ }
+ arb_assert(0);
+ return "<unknown>";
+}
+
+static GB_ERROR common_get_m_id(const char *path, char **m_name, int *id) {
+ GB_ERROR error = NULL;
+ if (!path) {
+ error = "missing hostname:socketid";
+ }
+ else {
+ if (strcmp(path, ":") == 0) {
+ path = getenv("SOCKET");
+ if (!path) {
+ error = "expected environment variable 'SOCKET' (needed to connect to ':')";
+ }
+ }
+
+ if (!error) {
+ const char *p = strchr(path, ':');
+ if (path[0] == '*' || path[0] == ':') { // UNIX MODE
+ char buffer[128];
+ if (!p) {
+ error = "missing ':' in *:socketid";
+ }
+ else {
+ if (p[1] == '~') {
+ sprintf(buffer, "%s%s", getenv("HOME"), p+2);
+ *m_name = (char *)strdup(buffer);
+ }
+ else {
+ *m_name = (char *)strdup(p+1);
+ }
+ *id = -1;
+ }
+ }
+ else {
+ if (!p) {
+ error = "missing ':' in netname:socketid";
+ }
+ else {
+ char *mn = (char *) calloc(sizeof(char), p - path + 1);
+ strncpy(mn, path, p - path);
+
+ /* @@@ falls hier in mn ein der Bereich von path bis p stehen soll, fehlt eine abschliesende 0 am String-Ende
+ auf jeden Fall erzeugt der folgende strcmp einen (rui) */
+
+ if (strcmp(mn, "localhost") == 0) freedup(mn, arb_gethostname());
+
+ *m_name = mn;
+ int i = atoi(p + 1);
+ if ((i < 1024) || (i > 32000)) {
+ error = "socketnumber is not in range [1024..32000]";
+ }
+ else {
+ *id = i;
+ }
+ }
+ }
+ }
+ }
+ return error;
+}
+
+#define SOCKET_EXISTS_AND_CONNECT_WORKED ""
+
+static GB_ERROR common_open_socket(ClientOrServer cos, const char *path, int delay, int do_connect, int *psocket, char **unix_name) {
+ char *mach_name = NULL;
+ int socket_id;
+ GB_ERROR error = common_get_m_id(path, &mach_name, &socket_id);
+
+ if (!error) {
+ const char one = 1;
+ if (socket_id >= 0) { // UNIX
+ sockaddr_in so_ad;
+ memset((char *)&so_ad, 0, sizeof(sockaddr_in));
+ *psocket = socket(PF_INET, SOCK_STREAM, 0);
+ if (*psocket <= 0) {
+ error = "failed to create socket"; // @@@ reason why
+ }
+ else {
+ struct hostent *he;
+ arb_gethostbyname(mach_name, he, error);
+ if (!error) {
+ // simply take first address
+ struct in_addr addr;
+ addr.s_addr = *(int *) (he->h_addr);
+ so_ad.sin_addr = addr;
+ so_ad.sin_family = AF_INET;
+ so_ad.sin_port = htons(socket_id); // @@@ = pb_socket
+ if (do_connect) {
+ if (connect(*psocket, (struct sockaddr*)&so_ad, 16)) {
+ error = SOCKET_EXISTS_AND_CONNECT_WORKED;
+ }
+ }
+ else {
+ setsockopt(*psocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ if (bind(*psocket, (struct sockaddr*)&so_ad, 16)) {
+ error = "Could not open socket on Server (1)";
+ }
+ }
+ if (!error) {
+ if (delay == TCP_NODELAY) {
+ static int optval;
+ optval = 1;
+ setsockopt(*psocket, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, 4);
+ }
+ *unix_name = 0;
+ }
+ }
+ }
+ }
+ else {
+ struct sockaddr_un so_ad;
+ *psocket = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (*psocket <= 0) {
+ error = "cannot create socket"; // @@@ reason why
+ }
+ else {
+ so_ad.sun_family = AF_UNIX;
+ strcpy(so_ad.sun_path, mach_name);
+ if (do_connect) {
+ if (connect(*psocket, (struct sockaddr*)&so_ad, strlen(mach_name)+2)) {
+ error = SOCKET_EXISTS_AND_CONNECT_WORKED;
+ }
+ }
+ else {
+ FILE *test = fopen(mach_name, "r");
+ if (test) {
+ struct stat stt;
+ if (!stat(path, &stt)) {
+ if (S_ISREG(stt.st_mode)) {
+ fprintf(stderr, "%X\n", stt.st_mode);
+ error = "Socket already exists as a file";
+ }
+ }
+ fclose(test);
+ }
+
+ if (!error) {
+ if (unlink(mach_name) != 0) {
+ printf("Warning: old socket file '%s' failed to unlink\n", mach_name);
+ }
+ if (cos == AISC_SERVER) {
+ setsockopt(*psocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+ }
+ if (bind(*psocket, (struct sockaddr*)&so_ad, strlen(mach_name)+2)) {
+ error = "Could not open socket on Server (2)"; // @@@ reasons ?
+ }
+ if (!error && cos == AISC_SERVER) {
+ if (chmod(mach_name, 0777)) {
+ error = "Cannot change mode of socket"; // @@@ reasons!
+ }
+ }
+ }
+ }
+
+ if (!error) reassign(*unix_name, mach_name);
+ }
+ }
+ }
+
+ free(mach_name);
+
+ if (error && *error) { // real error (see SOCKET_EXISTS_AND_CONNECT_WORKED)
+ error = GBS_global_string("%s-Error: %s", who(cos), error);
+ }
+ return error;
+}
+
+const char *aisc_client_open_socket(const char *path, int delay, int do_connect, int *psocket, char **unix_name) {
+ return common_open_socket(AISC_CLIENT, path, delay, do_connect, psocket, unix_name);
+}
+const char *aisc_server_open_socket(const char *path, int delay, int do_connect, int *psocket, char **unix_name) { // @@@ rename into aisc_server_open_socket
+ return common_open_socket(AISC_SERVER, path, delay, do_connect, psocket, unix_name);
+}
+
=====================================
AISC_COM/C/common.h
=====================================
@@ -0,0 +1,20 @@
+/* This file is generated by aisc_mkpt.
+ * Any changes you make here will be overwritten later!
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+/* define ARB attributes: */
+#ifndef ATTRIBUTES_H
+# include <attributes.h>
+#endif
+
+
+/* common.c */
+const char *aisc_client_open_socket(const char *path, int delay, int do_connect, int *psocket, char **unix_name);
+const char *aisc_server_open_socket(const char *path, int delay, int do_connect, int *psocket, char **unix_name);
+
+#else
+#error common.h included twice
+#endif /* COMMON_H */
=====================================
AISC_COM/C/server.c
=====================================
@@ -0,0 +1,1322 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <limits.h>
+
+#include "trace.h"
+
+#define FD_SET_TYPE
+
+#if defined(DEBUG)
+// #define SERVER_TERMINATE_ON_CONNECTION_CLOSE
+#endif // DEBUG
+
+#include <signal.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <setjmp.h>
+
+#include <aisc_com.h>
+// AISC_MKPT_PROMOTE:#include <aisc_func_types.h>
+#include "server.h"
+
+#include <SigHandler.h>
+#include <arb_cs.h>
+#include <static_assert.h>
+#include "common.h"
+
+// AISC_MKPT_PROMOTE:#ifndef _STDIO_H
+// AISC_MKPT_PROMOTE:#include <stdio.h>
+// AISC_MKPT_PROMOTE:#endif
+
+#define aisc_assert(cond) arb_assert(cond)
+
+#define AISC_SERVER_OK 1
+#define AISC_SERVER_FAULT 0
+#define MAX_QUEUE_LEN 5
+
+#define AISC_MAGIC_NUMBER_FILTER 0xffffff00
+
+// -------------------------
+// some structures
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ struct Socinf {
+ Socinf *next;
+ int socket;
+ aisc_destroy_callback destroy_callback;
+ long destroy_clientdata;
+ int lasttime;
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+struct pollfd;
+struct Hs_struct : virtual Noncopyable {
+ int hso;
+ Socinf *soci;
+ struct pollfd *fds;
+ unsigned long nfds;
+ int nsoc;
+ int timeout;
+ int fork;
+ char *unix_name;
+
+ Hs_struct()
+ : hso(0),
+ soci(NULL),
+ fds(NULL),
+ nfds(0),
+ nsoc(0),
+ timeout(0),
+ fork(0),
+ unix_name(NULL)
+ {}
+ ~Hs_struct() { freenull(unix_name); }
+};
+
+struct aisc_bytes_list {
+ char *data;
+ int size;
+ aisc_bytes_list *next;
+};
+
+static aisc_bytes_list *aisc_server_bytes_first;
+static aisc_bytes_list *aisc_server_bytes_last;
+
+
+extern char *aisc_object_names[];
+extern char **aisc_attribute_names_list[];
+
+extern aisc_talking_func_long *aisc_talking_functions_get[];
+extern aisc_talking_func_long *aisc_talking_functions_set[];
+extern aisc_talking_func_longp *aisc_talking_functions_copy[];
+extern aisc_talking_func_longp *aisc_talking_functions_find[];
+extern aisc_talking_func_longp *aisc_talking_functions_create[];
+extern aisc_talking_func_long aisc_talking_functions_delete[];
+
+const char *aisc_server_error;
+
+const int ERRORBUFSIZE = 256;
+static char error_buf[ERRORBUFSIZE];
+
+static int aisc_server_con;
+static Hs_struct *aisc_server_hs;
+
+// -----------------------
+// error handling
+
+void aisc_server_errorf(const char *templat, ...) {
+ // goes to header: __ATTR__FORMAT(1)
+ va_list parg;
+
+ va_start(parg, templat);
+ int printed = vsprintf(error_buf, templat, parg);
+
+ if (printed >= ERRORBUFSIZE) {
+ fprintf(stderr,
+ "Fatal: buffer overflow in aisc_server_errorf\n"
+ "Error was: ");
+ vfprintf(stderr, templat, parg);
+ fputs("\nTerminating..\n", stderr);
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ }
+ va_end(parg);
+
+ aisc_server_error = error_buf;
+}
+
+
+// -----------------------------
+// valid memory tester
+
+static bool sigsegv_occurred = false;
+static bool catch_sigsegv = 0;
+static jmp_buf return_after_segv;
+
+static const char *test_address_valid(void *address, long key)
+{
+ /* tests whether 'address' is a valid readable address
+ * if 'key' != 0 -> check if 'address' contains 'key'
+ *
+ * returns NULL or error string
+ */
+
+ static char buf[256];
+ char *result = buf;
+
+ sigsegv_occurred = false;
+ catch_sigsegv = true;
+
+ // ----------------------------------------
+ // start of critical section
+ // (need volatile for modified local auto variables, see man longjump)
+ volatile long i = 0;
+ volatile int trapped = sigsetjmp(return_after_segv, 1);
+
+ if (trapped == 0) { // normal execution
+ i = *(long *)address; // here a SIGSEGV may happen. Execution will continue in else-branch
+ }
+ else { // return after SEGV
+ aisc_assert(trapped == 666); // oops - SEGV did not occur in mem access above!
+ aisc_assert(sigsegv_occurred); // oops - wrong handler installed ?
+ }
+ // end of critical section
+ // ----------------------------------------
+
+ catch_sigsegv = false;
+
+ if (sigsegv_occurred) {
+ sprintf(buf, "AISC memory manager error: can't access memory at address %p", address);
+ }
+ else {
+ if (key && i != key) {
+ sprintf(buf, "AISC memory manager error: object at address %p has wrong type (found: 0x%lx, expected: 0x%lx)",
+ address, i, key);
+ }
+ else {
+ result = NULL; // ok, address (and key) valid
+ }
+ }
+
+ return result;
+}
+
+static SigHandler old_sigsegv_handler;
+
+__ATTR__NORETURN static void aisc_server_sigsegv(int sig) {
+ sigsegv_occurred = true;
+ if (catch_sigsegv) {
+ siglongjmp(return_after_segv, 666); // never returns
+ }
+ // unexpected SEGV
+
+ UNINSTALL_SIGHANDLER(SIGSEGV, aisc_server_sigsegv, old_sigsegv_handler, "aisc_server_sigsegv");
+ old_sigsegv_handler(sig);
+ aisc_assert(0); // oops - old handler returned
+ abort();
+}
+
+// -----------------------------
+// broken pipe handler
+
+static int pipe_broken;
+
+static void aisc_server_sigpipe(int) {
+ pipe_broken = 1;
+}
+
+// --------------------------
+// new read command
+
+static int aisc_s_read(int socket, char *ptr, int size) {
+ int leftsize = size;
+ while (leftsize) {
+ int readsize = read(socket, ptr, leftsize);
+ if (readsize<=0) return 0;
+ ptr += readsize;
+ leftsize -= readsize;
+ }
+
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_s_read: ", ptr-size, size);
+#endif // DUMP_COMMUNICATION
+
+ return size;
+}
+
+static int aisc_s_write(int socket, char *ptr, int size) {
+ int leftsize = size;
+ pipe_broken = 0;
+ while (leftsize) {
+ int writesize = write(socket, ptr, leftsize);
+ if (pipe_broken) {
+ fputs("AISC server: pipe broken\n", stderr);
+ return -1;
+ }
+ if (writesize<0) return -1;
+ ptr += writesize;
+ leftsize -= writesize;
+ if (leftsize) usleep(10000); // 10 ms
+ }
+
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_s_write: ", ptr-size, size);
+#endif // DUMP_COMMUNICATION
+
+ return 0;
+}
+
+
+// ----------------------------------------------
+// object+attr_names for error messages
+
+
+const char *aisc_get_object_names(long i)
+{
+ if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_object_names[i])) {
+ return "<unknown object>";
+ }
+ return aisc_object_names[i];
+}
+
+static const char *aisc_get_object_attribute(long i, long j)
+{
+ if ((i<0) || (i>=AISC_MAX_OBJECT) || (!aisc_attribute_names_list[i])) {
+ return "<null>";
+ }
+ if ((j<0) || (j>=AISC_MAX_ATTR) || (!aisc_attribute_names_list[i][j])) {
+ return "<unknown attribute>";
+ }
+ return aisc_attribute_names_list[i][j];
+}
+
+Hs_struct *open_aisc_server(const char *path, int timeout, int fork) {
+ Hs_struct *hs = new Hs_struct;
+ if (hs) {
+ hs->timeout = timeout;
+ hs->fork = fork;
+
+ static int so;
+ const char *err = aisc_server_open_socket(path, TCP_NODELAY, 0, &so, &hs->unix_name);
+
+ if (err) {
+ if (*err) printf("Error in open_aisc_server: %s\n", err);
+ shutdown(so, SHUT_RDWR);
+ close(so);
+ delete hs; hs = NULL;
+ }
+ else {
+ // install signal handlers
+ fprintf(stderr, "Installing signal handler from open_aisc_server\n"); fflush(stderr);
+ old_sigsegv_handler = INSTALL_SIGHANDLER(SIGSEGV, aisc_server_sigsegv, "open_aisc_server");
+ ASSERT_RESULT_PREDICATE(is_default_or_ignore_sighandler, INSTALL_SIGHANDLER(SIGPIPE, aisc_server_sigpipe, "open_aisc_server"));
+
+ aisc_server_bytes_first = 0;
+ aisc_server_bytes_last = 0;
+ // simply take first address
+ if (listen(so, MAX_QUEUE_LEN) < 0) {
+ printf("Error in open_aisc_server: could not listen (errno=%i)\n", errno);
+ delete hs; hs = NULL;
+ }
+ else {
+ hs->hso = so;
+ }
+ }
+ }
+ return hs;
+}
+
+static void aisc_s_add_to_bytes_queue(char *data, int size) {
+ aisc_bytes_list *bl;
+ bl = (aisc_bytes_list *)calloc(sizeof(aisc_bytes_list), 1);
+ bl->data = data;
+ bl->size = size;
+
+ if (aisc_server_bytes_first) {
+ aisc_server_bytes_last->next = bl;
+ aisc_server_bytes_last = bl;
+ }
+ else {
+ aisc_server_bytes_first = bl;
+ aisc_server_bytes_last = bl;
+ }
+}
+
+static int aisc_s_send_bytes_queue(int socket) {
+ aisc_bytes_list *bl, *bl_next;
+ for (bl = aisc_server_bytes_first; bl; bl=bl_next) {
+ bl_next = bl->next;
+ if (aisc_s_write(socket, (char *)bl->data, bl->size)) return 1;
+ free(bl);
+ };
+ aisc_server_bytes_first = aisc_server_bytes_last = NULL;
+ return 0;
+}
+
+static long aisc_talking_get(long *in_buf, int size, long *out_buf, int) { // handles AISC_GET
+ aisc_server_error = NULL;
+
+ long in_pos = 0;
+ long out_pos = 0;
+ long object = in_buf[in_pos++];
+ long object_type = (in_buf[in_pos] & AISC_OBJ_TYPE_MASK);
+
+
+ if (object_type > (AISC_MAX_OBJECT*0x10000)) {
+ aisc_server_error = "UNKNOWN OBJECT";
+ object = 0;
+ }
+ else {
+ aisc_server_error = test_address_valid((void *)object, object_type);
+ }
+ object_type = object_type >> (16);
+
+ AISC_DUMP_SEP();
+ AISC_DUMP(aisc_talking_get, int, object_type);
+
+ long attribute = 0;
+ long erg = 0;
+ while (!aisc_server_error && (in_pos < size)) {
+ long code = in_buf[in_pos];
+ long type = (code & AISC_VAR_TYPE_MASK);
+ attribute = (code & AISC_ATTR_MASK);
+
+ aisc_talking_func_long *functions = aisc_talking_functions_get[object_type];
+
+ if (!functions) {
+ aisc_server_error = "OBJECT HAS NO ATTRIBUTES";
+ attribute = 0;
+ break;
+ }
+ if (attribute > AISC_MAX_ATTR) {
+ sprintf(error_buf, "ATTRIBUTE %lx OUT of RANGE", attribute);
+ aisc_server_error = error_buf;
+ attribute = 0;
+ break;
+ }
+ aisc_talking_func_long function = functions[attribute];
+ if (!function) {
+ sprintf(error_buf, "DON'T KNOW ATTRIBUTE %li",
+ attribute);
+ aisc_server_error = error_buf;
+ break;
+ }
+
+ AISC_DUMP(aisc_talking_get, int, attribute);
+ AISC_DUMP(aisc_talking_get, int, type);
+
+ double_xfer derg;
+ STATIC_ASSERT(sizeof(derg.as_double) <= sizeof(derg.as_int));
+
+ if (type == AISC_TYPE_DOUBLE) {
+ aisc_talking_func_double dfunction = (aisc_talking_func_double) function;
+ derg.as_double = dfunction(object);
+ }
+ else {
+ erg = function(object);
+ }
+ if (aisc_server_error) {
+ break;
+ }
+ switch (type) {
+ case AISC_TYPE_INT:
+ case AISC_TYPE_COMMON:
+ AISC_DUMP(aisc_talking_get, int, erg);
+ out_buf[out_pos++] = erg;
+ break;
+
+ case AISC_TYPE_DOUBLE:
+ AISC_DUMP(aisc_talking_get, double, derg.as_double);
+ out_buf[out_pos++] = derg.as_int[0];
+ out_buf[out_pos++] = derg.as_int[1];
+ break;
+
+ case AISC_TYPE_STRING: {
+ if (!erg) erg = (long) "(null)";
+ long len = strlen((char *)erg);
+ if (len > AISC_MAX_STRING_LEN) {
+ erg = (long) "(string too long)";
+ len = strlen((char *)erg);
+ }
+
+ AISC_DUMP(aisc_talking_get, charPtr, (char*)erg);
+
+ len += 1;
+ len /= sizeof(long);
+ len++;
+ out_buf[out_pos++] = len;
+ strcpy((char *)&out_buf[out_pos], (char *)erg);
+ out_pos += len;
+ break;
+ }
+ case AISC_TYPE_BYTES:
+ {
+ bytestring *bs = (bytestring *)erg;
+
+ AISC_DUMP(aisc_talking_get, int, bs->size);
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_talking_get bytestring: ", bs->data, bs->size);
+#endif // DUMP_COMMUNICATION
+
+ if (bs->data && bs->size)
+ aisc_s_add_to_bytes_queue(bs->data, bs->size);
+ out_buf[out_pos++] = bs->size; // size
+ break;
+ }
+ default:
+ aisc_server_error = "UNKNOWN TYPE";
+ break;
+ }
+ in_pos++;
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "AISC_GET_SERVER_ERROR %s: OBJECT:%s ATTRIBUTE:%s",
+ aisc_server_error,
+ aisc_get_object_names(object_type),
+ aisc_get_object_attribute(object_type, attribute));
+ return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
+ }
+ return out_pos;
+}
+
+static int aisc_server_index = -1;
+
+static void aisc_talking_set_index(int */*obj*/, int i) {
+ aisc_server_index = i;
+}
+
+int aisc_talking_get_index(int u, int o)
+{
+ if (aisc_server_index==-1) {
+ aisc_server_error = "AISC_SERVER_ERROR MISSING AN AISC_INDEX";
+ return -1;
+ }
+ if ((aisc_server_index<u) || (aisc_server_index>=o)) {
+ sprintf(error_buf, "AISC_SET_SERVER_ERROR: INDEX %i IS OUT OF RANGE [%i,%i]",
+ aisc_server_index, u, o);
+ aisc_server_error = error_buf;
+ }
+
+ AISC_DUMP(aisc_talking_get_index, int, aisc_server_index);
+
+ return aisc_server_index;
+}
+
+static long aisc_talking_sets(long *in_buf, int size, long *out_buf, long *object, int object_type) {
+ int blen, bsize;
+ long in_pos, out_pos;
+ long code, attribute, type;
+
+ aisc_talking_func_long function;
+ aisc_talking_func_long *functions;
+ in_pos = out_pos = 0;
+ aisc_server_index = -1;
+ aisc_server_error = NULL;
+ object_type = (object_type & AISC_OBJ_TYPE_MASK);
+
+ attribute = 0;
+ if (object_type > (AISC_MAX_OBJECT*0x10000)) {
+ object_type = 0;
+ aisc_server_error = "UNKNOWN OBJECT";
+ }
+ else {
+ aisc_server_error = test_address_valid((void *)object, object_type);
+ }
+ object_type = object_type>>(16);
+ functions = aisc_talking_functions_set[object_type];
+ if (!functions) {
+ sprintf(error_buf, "OBJECT %x HAS NO ATTRIBUTES",
+ object_type);
+ aisc_server_error = error_buf;
+ }
+
+ AISC_DUMP_SEP();
+ AISC_DUMP(aisc_talking_sets, int, object_type);
+
+ while (!aisc_server_error && (in_pos<size)) {
+ code = in_buf[in_pos++];
+ attribute = code & AISC_ATTR_MASK;
+ type = code & AISC_VAR_TYPE_MASK;
+ if (attribute > AISC_MAX_ATTR) {
+ sprintf(error_buf, "ATTRIBUTE %li DOESN'T EXIST",
+ attribute);
+ aisc_server_error = error_buf;
+ attribute = 0;
+ break;
+ }
+ if (code == AISC_INDEX) {
+ function = (aisc_talking_func_long)aisc_talking_set_index;
+ }
+ else {
+ function = functions[attribute];
+ }
+ if (!function) {
+ sprintf(error_buf, "ATTRIBUTE %li DOESN'T EXIST",
+ attribute);
+ aisc_server_error = error_buf;
+ break;
+ }
+
+ AISC_DUMP(aisc_talking_sets, int, attribute);
+ AISC_DUMP(aisc_talking_sets, int, type);
+
+ switch (type) {
+ case AISC_TYPE_INT:
+ case AISC_TYPE_COMMON:
+
+ AISC_DUMP(aisc_talking_sets, long, in_buf[in_pos]);
+
+ function((long)object, in_buf[in_pos++]);
+ break;
+ case AISC_TYPE_DOUBLE:
+ {
+ double_xfer derg;
+ derg.as_int[0] = in_buf[in_pos++];
+ derg.as_int[1] = in_buf[in_pos++];
+
+ AISC_DUMP(aisc_talking_sets, double, derg.as_double);
+
+ function((long)object, derg.as_double);
+ break;
+ }
+ case AISC_TYPE_STRING:
+ {
+ char *str = strdup((char *)&(in_buf[in_pos+1]));
+
+ AISC_DUMP(aisc_talking_sets, charPtr, str);
+
+ function((long)object, str);
+ in_pos += in_buf[in_pos]+1;
+ break;
+ }
+ case AISC_TYPE_BYTES:
+ bsize = (int)in_buf[in_pos++];
+
+ AISC_DUMP(aisc_talking_sets, int, bsize);
+
+ if (bsize) {
+ long *ptr = (long*)calloc(sizeof(char), bsize);
+ blen = aisc_s_read(aisc_server_con, (char *)ptr, bsize);
+ if (bsize!=blen) {
+ aisc_server_error = "CONNECTION PROBLEMS IN BYTESTRING";
+ free(ptr);
+ }
+ else {
+ bytestring bs;
+ bs.data = (char *)ptr;
+ bs.size = bsize;
+
+#if defined(DUMP_COMMUNICATION)
+ aisc_dump_hex("aisc_talking_sets bytestring: ", (char*)ptr, bsize);
+#endif // DUMP_COMMUNICATION
+
+ function((long)object, &bs);
+ }
+ }
+ else {
+ function((long)object, 0);
+ }
+ break;
+ default:
+ aisc_server_error = "UNKNOWN TYPE";
+ break;
+ }
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "AISC_SET_SERVER_ERROR %s: OBJECT:%s ATTRIBUTE:%s",
+ aisc_server_error,
+ aisc_get_object_names(object_type),
+ aisc_get_object_attribute(object_type, attribute));
+ return -((strlen((char *)out_buf) + 1) / sizeof(long) + 1);
+ }
+ return 0;
+}
+
+static long aisc_talking_set(long *in_buf, int size, long *out_buf, int) { // handles AISC_SET
+ aisc_server_error = NULL;
+
+ int in_pos = 0;
+ long object = in_buf[in_pos++];
+ int object_type = ((int)in_buf[in_pos++]) & AISC_OBJ_TYPE_MASK;
+
+ return aisc_talking_sets(&(in_buf[in_pos]), size-in_pos, out_buf, (long *)object, object_type);
+}
+
+static long aisc_talking_nset(long *in_buf, int size, long *out_buf, int) { // handles AISC_NSET
+ aisc_server_error = NULL;
+
+ int in_pos = 0;
+ long object = in_buf[in_pos++];
+ int object_type = (int)(in_buf[in_pos++] & AISC_OBJ_TYPE_MASK);
+
+ aisc_talking_sets(&(in_buf[in_pos]), size-in_pos, out_buf, (long *)object, object_type);
+ return AISC_NO_ANSWER;
+}
+
+static struct aisc_static_set_mem {
+ long *ibuf, *obuf;
+ int size, type;
+} md;
+
+long aisc_make_sets(long *obj)
+{
+ if (md.size>0) {
+ return aisc_talking_sets(md.ibuf, md.size, md.obuf, obj, md.type);
+ }
+ else {
+ return 0;
+ }
+}
+
+static long aisc_talking_create(long *in_buf, int size, long *out_buf, int) { // handles AISC_CREATE
+ aisc_server_error = NULL;
+
+ int in_pos = 0;
+ long father_type = in_buf[in_pos++];
+ long father = in_buf[in_pos++];
+
+ long *erg = 0;
+ for (int i=0; i<1; i++) {
+ if ((father_type&0xff00ffff) ||
+ (((unsigned int)father_type& 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
+ aisc_server_error = "AISC_CREATE_SERVER_ERROR: FATHER UNKNOWN";
+ break;
+ }
+ aisc_server_error = test_address_valid((void *)father, father_type);
+ if (aisc_server_error) break;
+
+ father_type = father_type>>16;
+ aisc_talking_func_longp *functions = aisc_talking_functions_create[father_type];
+
+ long code = in_buf[in_pos++];
+ long attribute = code & AISC_ATTR_MASK;
+ long object_type = in_buf[in_pos++];
+
+ if (!functions) {
+ sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s DOESN'T HAVE TARGET-ATTRIBUTE %s",
+ aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
+ aisc_server_error = error_buf;
+ break;
+ }
+ if (attribute > AISC_MAX_ATTR) {
+ aisc_server_error = "AISC_CREATE_SERVER_ERROR: UNKNOWN ATTRIBUTE";
+ break;
+ }
+ aisc_talking_func_longp function = functions[attribute];
+ if (!function) {
+ sprintf(error_buf, "AISC_CREATE_SERVER_ERROR: FATHER %s FATHER DOESN'T HAVE TARGET-ATTRIBUTE %s",
+ aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
+ aisc_server_error = error_buf;
+ break;
+ }
+ md.ibuf = &(in_buf[in_pos]);
+ md.obuf = out_buf;
+ md.size = size - in_pos;
+ md.type = (int)object_type;
+ erg = function(father);
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "%s", aisc_server_error);
+ return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
+ }
+ else {
+ out_buf[0] = (long)erg;
+ return 1;
+ }
+}
+
+static long aisc_talking_copy(long *in_buf, int size, long *out_buf, int /*max_size*/) { // handles AISC_COPY
+ aisc_server_error = NULL;
+
+ int in_pos = 0;
+ long object = in_buf[in_pos++];
+ int father_type = (int)in_buf[in_pos++];
+ long father = in_buf[in_pos++];
+
+ long *erg = 0;
+ for (int i=0; i<1; i++) {
+ if ((father_type&0xff00ffff) ||
+ (((unsigned int)father_type& 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
+ aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER UNKNOWN";
+ break;
+ }
+ aisc_server_error = test_address_valid((void *)father, father_type);
+ if (aisc_server_error) break;
+
+ father_type = father_type>>16;
+ aisc_talking_func_longp *functions = aisc_talking_functions_copy[father_type];
+
+ if (!functions) {
+ aisc_server_error = "AISC_COPY_SERVER_ERROR: FATHER DOESN'T HAVE TARGET-ATTRIBUTES";
+ break;
+ }
+
+ int code = (int)in_buf[in_pos++];
+ int object_type = (int)in_buf[in_pos++];
+ int attribute = code & AISC_ATTR_MASK;
+
+ if (attribute > AISC_MAX_ATTR) {
+ aisc_server_error = "AISC_COPY_SERVER_ERROR: UNKNOWN ATTRIBUTE";
+ break;
+ }
+ aisc_talking_func_longp function = functions[attribute];
+ if (!function) {
+ sprintf(error_buf, "AISC_COPY_SERVER_ERROR: FATHER %s DOESN'T HAVE TARGET-ATTRIBUTE %s",
+ aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
+ aisc_server_error = error_buf;
+ break;
+ }
+ aisc_server_error = test_address_valid((void *)object, object_type);
+ if (aisc_server_error) break;
+
+ md.ibuf = &(in_buf[in_pos]);
+ md.obuf = out_buf;
+ md.size = size - in_pos;
+ md.type = object_type;
+ erg = function(father, object);
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "%s", aisc_server_error);
+ return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
+ }
+ else {
+ out_buf[0] = (long)erg;
+ return 1;
+ }
+}
+
+static long aisc_talking_find(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_FIND
+ aisc_server_error = NULL;
+
+ int in_pos = 0;
+ long father_type = in_buf[in_pos++];
+ long father = in_buf[in_pos++];
+
+ long *erg = 0;
+ for (int i = 0; i < 1; i++) {
+ if ((father_type & 0xff00ffff) ||
+ (((unsigned int) father_type & 0xff0000) >= (AISC_MAX_OBJECT*0x10000))) {
+ aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER UNKNOWN";
+ break;
+ }
+ aisc_server_error = test_address_valid((void *)father, father_type);
+ if (aisc_server_error)
+ break;
+
+ father_type = father_type>>16;
+ aisc_talking_func_longp *functions = aisc_talking_functions_find[father_type];
+
+ long code = in_buf[in_pos++];
+ long attribute = code & AISC_ATTR_MASK;
+
+ if (!functions) {
+ aisc_server_error = "AISC_FIND_SERVER_ERROR: FATHER DON'T KNOW ATTRIBUTES FOR SEARCH";
+ break;
+ }
+ if (attribute > AISC_MAX_ATTR) {
+ aisc_server_error = "AISC_FIND_SERVER_ERROR: UNKNOWN ATTRIBUTE";
+ break;
+ }
+ aisc_talking_func_longp function = functions[attribute];
+ if (!function) {
+ sprintf(error_buf, "AISC_FIND_SERVER_ERROR: FATHER %s DON'T KNOW ATTRIBUTE %s FOR SEARCH",
+ aisc_get_object_names(father_type), aisc_get_object_attribute(father_type, attribute));
+ aisc_server_error = error_buf;
+ break;
+ }
+ if (in_buf[in_pos++]<=0) {
+ aisc_server_error = " AISC_FIND_SERVER_ERROR: CANNOT FIND EMPTY IDENT";
+ break;
+ }
+ erg = function(father, &(in_buf[in_pos]));
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "%s", aisc_server_error);
+ return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
+ }
+ else {
+ out_buf[0] = (long) erg;
+ return 1;
+ }
+}
+
+extern int *aisc_main;
+
+static long aisc_talking_init(long */*in_buf*/, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_INIT
+ aisc_server_error = NULL;
+ out_buf[0] = (long)aisc_main;
+ return 1;
+}
+
+static long aisc_fork_server(long */*in_buf*/, int /*size*/, long */*out_buf*/, int /*max_size*/) { // handles AISC_FORK_SERVER
+ pid_t pid = fork();
+ return pid<0 ? 0 : pid; // return OK(=0) when fork does not work
+}
+
+static long aisc_talking_delete(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_DELETE
+ int in_pos, out_pos;
+ long object_type;
+
+ aisc_talking_func_long function;
+
+ int i;
+ long object;
+ in_pos = out_pos = 0;
+ aisc_server_error = NULL;
+ object_type = in_buf[in_pos++];
+ object_type = (object_type & AISC_OBJ_TYPE_MASK);
+ object = in_buf[in_pos++];
+ for (i = 0; i < 1; i++) {
+ if (object_type > (AISC_MAX_OBJECT*0x10000)) {
+ aisc_server_error = "AISC_GET_SERVER_ERROR: UNKNOWN OBJECT";
+ }
+ else {
+ aisc_server_error = test_address_valid((void *)object, object_type);
+ }
+ if (aisc_server_error)
+ break;
+ object_type = object_type >> (16);
+ function = aisc_talking_functions_delete[object_type];
+ if (!function) {
+ sprintf(error_buf, "AISC_SET_SERVER_ERROR: OBJECT %s cannot be deleted",
+ aisc_object_names[object_type]);
+ aisc_server_error = error_buf;
+ break;
+ }
+ else {
+ function(object);
+ }
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "%s", aisc_server_error);
+ return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
+ }
+ return 0;
+}
+
+static long aisc_talking_debug_info(long *in_buf, int /*size*/, long *out_buf, int /*max_size*/) { // handles AISC_DEBUG_INFO
+ int in_pos, out_pos;
+ long object_type, attribute;
+
+ aisc_talking_func_long *functionsg;
+ aisc_talking_func_long *functionss;
+ aisc_talking_func_longp *functions;
+
+ int i;
+ long *object;
+
+ in_pos = out_pos = 0;
+ aisc_server_error = NULL;
+
+ for (i=0; i<256; i++) out_buf[i] = 0;
+ for (i = 0; i < 1; i++) {
+ object = (long *)in_buf[in_pos++];
+ attribute = in_buf[in_pos++];
+ aisc_server_error = test_address_valid((void *)object, 0);
+
+ if (aisc_server_error)
+ break;
+
+ object_type = *object;
+ if ((object_type > (AISC_MAX_OBJECT*0x10000)) || (object_type&0xff00ffff) || (object_type<0x00010000)) {
+ aisc_server_error = "AISC_DEBUGINFO_SERVER_ERROR: UNKNOWN OBJECT";
+ break;
+ }
+ attribute &= AISC_ATTR_MASK;
+ object_type = object_type>>16;
+
+ if (!aisc_talking_functions_delete[object_type]) { out_buf[0] = 1; };
+
+ if (!(functionsg=aisc_talking_functions_get[object_type])) {
+ out_buf[1] = 2;
+ }
+ else {
+ if (!functionsg[attribute]) out_buf[1] = 1;
+ };
+
+ if (!(functionss=aisc_talking_functions_set[object_type])) {
+ out_buf[2] = 2;
+ }
+ else {
+ if (!functionss[attribute]) out_buf[2] = 1;
+ };
+
+ if (!(functions=aisc_talking_functions_find[object_type])) {
+ out_buf[3] = 2;
+ }
+ else {
+ if (!functions[attribute]) out_buf[3] = 1;
+ };
+
+ if (!(functions=aisc_talking_functions_create[object_type])) {
+ out_buf[4] = 2;
+ }
+ else {
+ if (!functions[attribute]) out_buf[4] = 1;
+ };
+
+ if (!(functions=aisc_talking_functions_copy[object_type])) {
+ out_buf[5] = 2;
+ }
+ else {
+ if (!functions[attribute]) out_buf[5] = 1;
+ };
+
+ }
+ if (aisc_server_error) {
+ sprintf((char *) out_buf, "%s", aisc_server_error);
+ return -((strlen(aisc_server_error) + 1) / sizeof(long) + 1);
+ }
+ else {
+ return 20;
+ }
+}
+
+int aisc_broadcast(Hs_struct *hs, int message_type, const char *message)
+{
+ Socinf *si;
+ int size = message ? strlen(message) : 0;
+ int sizeL = (size+1+sizeof(long)-1) / sizeof(long); // number of longs needed to safely store string
+ long *out_buf = (long *)calloc(sizeL+3, sizeof(long));
+
+ if (!message) {
+ out_buf[3] = 0;
+ }
+ else {
+ char *strStart = (char*)(out_buf+3);
+ int pad = sizeL*sizeof(long)-(size+1);
+
+ aisc_assert(pad >= 0);
+
+ memcpy(strStart, message, size+1);
+ if (pad) memset(strStart+size+1, 0, pad); // avoid to send uninitialized bytes
+ }
+
+ aisc_assert(sizeL >= 1);
+
+ out_buf[0] = sizeL+1;
+ out_buf[1] = AISC_CCOM_MESSAGE;
+ out_buf[2] = message_type;
+
+ for (si=hs->soci; si; si=si->next) {
+ aisc_s_write(si->socket, (char *)out_buf, (sizeL + 3) * sizeof(long));
+ }
+ free(out_buf);
+ return 0;
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef long (*aisc_talking_function_type)(long*, int, long*, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+static aisc_talking_function_type aisc_talking_functions[] = {
+ aisc_talking_get, // AISC_GET
+ aisc_talking_set, // AISC_SET
+ aisc_talking_nset, // AISC_NSET
+ aisc_talking_create, // AISC_CREATE
+ aisc_talking_find, // AISC_FIND
+ aisc_talking_copy, // AISC_COPY
+ aisc_talking_delete, // AISC_DELETE
+ aisc_talking_init, // AISC_INIT
+ aisc_talking_debug_info, // AISC_DEBUG_INFO
+ aisc_fork_server // AISC_FORK_SERVER
+};
+
+static int aisc_talking(int con) {
+ static long buf[AISC_MESSAGE_BUFFER_LEN];
+ static long out_buf[AISC_MESSAGE_BUFFER_LEN];
+ unsigned long len;
+ static long size;
+ long magic_number;
+ len = aisc_s_read(con, (char *)buf, 2* sizeof(long));
+ if (len == 2*sizeof(long)) {
+ aisc_server_con = con;
+ if (buf[0] >= AISC_MESSAGE_BUFFER_LEN)
+ return AISC_SERVER_FAULT;
+ magic_number = buf[1];
+ if ((unsigned long)(magic_number & AISC_MAGIC_NUMBER_FILTER) != (unsigned long)(AISC_MAGIC_NUMBER & AISC_MAGIC_NUMBER_FILTER)) {
+ return AISC_SERVER_FAULT;
+ }
+ size = buf[0];
+
+ {
+ long expect = size*sizeof(long);
+ aisc_assert(expect >= 0);
+ aisc_assert(expect <= INT_MAX);
+
+ len = aisc_s_read(con, (char *)buf, (int)expect);
+ aisc_assert(len <= LONG_MAX);
+
+ if ((long)len != expect) {
+ printf(" ERROR in AISC_SERVER: Expected to get %li bytes from client (got %lu)\n", expect, len);
+ return AISC_SERVER_OK;
+ }
+ }
+ magic_number &= ~AISC_MAGIC_NUMBER_FILTER;
+ size = (aisc_talking_functions[magic_number])
+ (buf, (int)size, out_buf + 2, AISC_MESSAGE_BUFFER_LEN - 2);
+ if (size >= 0) {
+ out_buf[1] = AISC_CCOM_OK;
+ }
+ else {
+ if (size == (long)AISC_NO_ANSWER) {
+ return AISC_SERVER_OK;
+ }
+ out_buf[1] = AISC_CCOM_ERROR;
+ size *= -1;
+ }
+ out_buf[0] = size;
+ if (aisc_s_write(con, (char *)out_buf, (int)(size + 2) * sizeof(long))) {
+ return AISC_SERVER_FAULT;
+ }
+ if (aisc_server_bytes_first) {
+ if (aisc_s_send_bytes_queue(con)) {
+ return AISC_SERVER_FAULT;
+ }
+ }
+ return AISC_SERVER_OK;
+ }
+ else {
+ return AISC_SERVER_FAULT;
+ }
+}
+
+Hs_struct *aisc_accept_calls(Hs_struct *hs)
+{
+ int con;
+ int anz, i;
+ Socinf *si, *si_last = NULL, *sinext, *sptr;
+ fd_set set, setex;
+ struct timeval timeout;
+
+ if (!hs) {
+ fprintf(stderr, "AISC_SERVER_ERROR socket error (==0)\n");
+ }
+
+ timeout.tv_sec = hs->timeout / 1000;
+ timeout.tv_usec = (hs->timeout % 1000) * 1000;
+
+ aisc_server_hs = hs;
+
+ while (hs) {
+ FD_ZERO(&set);
+ FD_ZERO(&setex);
+ FD_SET(hs->hso, &set);
+ FD_SET(hs->hso, &setex);
+
+ for (si=hs->soci, i=1; si; si=si->next, i++)
+ {
+ FD_SET(si->socket, &set);
+ FD_SET(si->socket, &setex);
+ }
+ if (hs->timeout >= 0) {
+ anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, &timeout);
+ }
+ else {
+ anz = select(FD_SETSIZE, FD_SET_TYPE &set, NULL, FD_SET_TYPE &setex, 0);
+ }
+
+ if (anz==-1) {
+ printf("ERROR: poll in aisc_accept_calls\n");
+ return 0;
+ }
+ if (!anz) { // timed out
+ return hs;
+ }
+ // an event has occurred
+ if ((timeout.tv_usec>=0)&&(timeout.tv_usec<100000)) timeout.tv_usec = 100000;
+
+ if (FD_ISSET(hs->hso, &set)) {
+ con = accept(hs->hso, NULL, 0);
+ if (hs->fork) {
+ long id = fork();
+ if (!id) {
+ return hs;
+ }
+ }
+
+ if (con>0) {
+ static int optval;
+ sptr = (Socinf *)calloc(sizeof(Socinf), 1);
+ if (!sptr) return 0;
+ sptr->next = hs->soci;
+ sptr->socket = con;
+ hs->soci=sptr;
+ hs->nsoc++;
+ optval = 1;
+ setsockopt(con, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, 4);
+ }
+ }
+ else {
+ si_last = 0;
+
+ for (si=hs->soci; si; si_last=si, si=sinext) {
+ sinext = si->next;
+
+ if (FD_ISSET(si->socket, &set)) {
+ if (AISC_SERVER_OK == aisc_talking(si->socket)) continue;
+ } else if (!FD_ISSET(si->socket, &setex)) continue;
+
+ if (close(si->socket) != 0) {
+ printf("aisc_accept_calls: ");
+ printf("couldn't close socket!\n");
+ }
+
+ hs->nsoc--;
+ if (si == hs->soci) { // first one
+ hs->soci = si->next;
+ }
+ else {
+ si_last->next = si->next;
+ }
+ if (si->destroy_callback) {
+ si->destroy_callback(si->destroy_clientdata);
+ }
+ free(si);
+#ifdef SERVER_TERMINATE_ON_CONNECTION_CLOSE
+ if (hs->nsoc == 0) { // no clients left
+ if (hs->fork) exit(EXIT_SUCCESS); // child exits
+ return hs; // parent exits
+ }
+ break;
+#else
+ // normal behavior
+ if (hs->nsoc == 0 && hs->fork) exit(EXIT_SUCCESS);
+ break;
+#endif
+ }
+ }
+ } // while main loop
+
+ return hs;
+}
+
+void aisc_server_shutdown(Hs_struct*& hs) {
+ Socinf *si;
+
+ for (si=hs->soci; si; si=si->next) {
+ shutdown(si->socket, SHUT_RDWR);
+ close(si->socket);
+ }
+ shutdown(hs->hso, SHUT_RDWR);
+ close(hs->hso);
+ if (hs->unix_name) unlink(hs->unix_name);
+ delete hs; hs = NULL;
+}
+
+void aisc_server_shutdown_and_exit(Hs_struct *hs, int exitcode) {
+ /* goes to header:
+ * __ATTR__NORETURN
+ * __ATTR__DEPRECATED_TODO("cause it hides a call to exit() inside a library")
+ */
+
+ aisc_server_shutdown(hs);
+ printf("Server terminates with code %i.\n", exitcode);
+ exit(exitcode);
+}
+
+
+// ---------------------------
+// special functions
+
+
+int aisc_add_destroy_callback(aisc_destroy_callback callback, long clientdata) { // call from server function
+ Socinf *si;
+ int socket = aisc_server_con;
+ Hs_struct *hs = aisc_server_hs;
+ if (!hs)
+ return socket;
+ for (si = hs->soci; si; si = si->next) {
+ if (si->socket == socket) {
+ if (si->destroy_callback) {
+ fputs("Error: destroy_callback already bound (did you open two connections in client?)\n", stderr);
+ fputs("Note: calling bound and installing new destroy_callback\n", stderr);
+ si->destroy_callback(si->destroy_clientdata);
+ }
+
+ si->destroy_callback = callback;
+ si->destroy_clientdata = clientdata;
+ }
+ }
+ return socket;
+}
+
+void aisc_remove_destroy_callback() { // call from server function
+ Socinf *si;
+ int socket = aisc_server_con;
+ Hs_struct *hs = aisc_server_hs;
+ if (!hs)
+ return;
+ for (si = hs->soci; si; si = si->next) {
+ if (si->socket == socket) {
+ si->destroy_callback = 0;
+ si->destroy_clientdata = 0;
+ }
+ }
+}
+
+int aisc_server_save_token(FILE *fd, const char *buffer, int maxsize) {
+ putc('{',fd);
+ const char *p = buffer;
+ while (maxsize-->0) {
+ int c = *(p++);
+ if (!c) break;
+ if (c=='}' || c == '\\') putc('\\',fd);
+ putc(c,fd);
+ }
+ putc('}',fd);
+ return 0;
+}
+
+int aisc_server_load_token(FILE *fd, char *buffer, int maxsize) {
+ int in_brackets = 0;
+ char *p = buffer;
+ int result = EOF;
+
+ while (maxsize-- > 0) {
+ int c = getc(fd);
+ if (c==EOF) break;
+ if (in_brackets) {
+ if (c=='\\') {
+ c = getc(fd);
+ *(p++) = c;
+ }
+ else if (c!='}') {
+ *(p++) = c;
+ }
+ else {
+ result = 0;
+ break;
+ }
+ }
+ else if (c=='{') {
+ if (p!=buffer) {
+ *(p++) = '{';
+ *p=0;
+ return 0;
+ }
+ else {
+ in_brackets = 1;
+ }
+ }
+ else if (c==' ' || c=='\n') {
+ if (p!=buffer) {
+ result = 0;
+ break;
+ }
+ }
+ else if (c=='}') {
+ *(p++) = '}';
+ result = 0;
+ break;
+ }
+ else {
+ *(p++) = c;
+ }
+ }
+
+ *p = 0;
+ return result; // read error maxsize reached
+}
=====================================
AISC_COM/C/server.h
=====================================
@@ -0,0 +1,37 @@
+/* This file is generated by aisc_mkpt.
+ * Any changes you make here will be overwritten later!
+ */
+
+#ifndef SERVER_H
+#define SERVER_H
+
+/* define ARB attributes: */
+#ifndef ATTRIBUTES_H
+# include <attributes.h>
+#endif
+
+
+/* server.c */
+
+#include <aisc_func_types.h>
+#ifndef _STDIO_H
+#include <stdio.h>
+#endif
+
+void aisc_server_errorf(const char *templat, ...) __ATTR__FORMAT(1);
+const char *aisc_get_object_names(long i);
+Hs_struct *open_aisc_server(const char *path, int timeout, int fork);
+int aisc_talking_get_index(int u, int o);
+long aisc_make_sets(long *obj);
+int aisc_broadcast(Hs_struct *hs, int message_type, const char *message);
+Hs_struct *aisc_accept_calls(Hs_struct *hs);
+void aisc_server_shutdown(Hs_struct*& hs);
+void aisc_server_shutdown_and_exit(Hs_struct *hs, int exitcode) __ATTR__NORETURN __ATTR__DEPRECATED_TODO("cause it hides a call to exit() inside a library");
+int aisc_add_destroy_callback(aisc_destroy_callback callback, long clientdata);
+void aisc_remove_destroy_callback(void);
+int aisc_server_save_token(FILE *fd, const char *buffer, int maxsize);
+int aisc_server_load_token(FILE *fd, char *buffer, int maxsize);
+
+#else
+#error server.h included twice
+#endif /* SERVER_H */
=====================================
AISC_COM/C/struct_man.c
=====================================
@@ -0,0 +1,344 @@
+// ==============================================================
+/* */
+// File : struct_man.c
+// Purpose :
+/* */
+// Institute of Microbiology (Technical University Munich)
+// http://www.arb-home.de/
+ /* */
+ // ==============================================================
+
+
+#include <aisc.h>
+#include <struct_man.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// AISC_MKPT_PROMOTE:struct aisc_hash_node;
+
+// ---------------------
+// hash tables
+
+
+#define CORE
+#define HASH_SIZE 103123
+#define TRF_HASH_SIZE 103123
+
+struct aisc_hash_node {
+ char *key;
+ long data;
+ aisc_hash_node *next;
+};
+
+
+static aisc_hash_node **aisc_init_hash(int size) {
+ struct aisc_hash_node **tab;
+ tab = (aisc_hash_node **) calloc(sizeof(aisc_hash_node *), size);
+ tab[0] = (aisc_hash_node *) calloc(sizeof(aisc_hash_node), 1);
+ tab[0]->data = size;
+ tab[0]->key = (char *)strdup("len_of_hash_table_(c) oliver_strunk 1.3.93");
+ return tab;
+}
+
+static int aisc_hash(const char *key, int size) {
+ unsigned int i, len, x;
+ len = strlen(key);
+ x = 0;
+ for (i=0; i<len; i++) {
+ x = x<<2 ^ key[i];
+ }
+ x = x%size;
+ return x;
+}
+
+static void aisc_free_key(aisc_hash_node **table, char *key) {
+ if (table && table[0]) {
+ long size = table[0]->data;
+ long i = aisc_hash(key, (int)size);
+
+ aisc_hash_node *hn, *hhn;
+ for (hn = hhn = table[i]; hn; hn = hn->next) {
+ if (strcmp(key, hn->key)) {
+ hhn = hn;
+ continue;
+ }
+ if (hn != hhn)
+ hhn->next = hn->next;
+ else {
+ table[i] = hhn->next;
+ }
+ free(hn->key);
+ free(hn);
+ break;
+ }
+ }
+}
+
+static void aisc_free_hash(aisc_hash_node **table) {
+ long end = table[0]->data;
+ for (long i=0; i<end; i++) {
+ aisc_hash_node *hn, *hnn;
+ for (hn = table[i]; hn; hn=hnn) {
+ hnn = hn->next;
+ free(hn->key);
+ free(hn);
+ }
+ }
+ free(table);
+}
+
+
+static void aisc_insert_hash(aisc_hash_node **table, char *key, long data) {
+ long size = table[0]->data;
+ long i = aisc_hash(key, (int)size);
+
+ aisc_hash_node *hnl = 0;
+ aisc_hash_node *hn;
+ for (hn=table[i]; hn; hn=hn->next) {
+ hnl = hn;
+ if (strcmp(key, hn->key) == 0) {
+ hn->data = data;
+ return;
+ }
+ }
+ hn = (aisc_hash_node *)calloc(sizeof(aisc_hash_node), 1);
+ hn->key = (char *)strdup(key);
+ hn->data = data;
+ if (hnl) {
+ hnl->next = hn;
+ }
+ else {
+ table[i] = hn;
+ }
+}
+
+long aisc_read_hash(aisc_hash_node **table, const char *key) {
+ if (table && table[0]) {
+ long size = table[0]->data;
+ long i = aisc_hash(key, (int)size);
+ for (aisc_hash_node *hn=table[i]; hn; hn=hn->next) {
+ if (strcmp(key, hn->key) == 0) return hn->data;
+ }
+ }
+ return 0;
+}
+
+// ----------------------
+// link control
+
+const char *aisc_link(dllpublic_ext *father, dllheader_ext *object) {
+ if (!object) {
+ CORE;
+ return "Object is (NULL)";
+ }
+ if (object->mh.parent) {
+ CORE;
+ return "Object already linked";
+ }
+ if (!father) {
+ CORE;
+ return "Parent is (NULL)";
+ }
+ if (father->key != object->mh.key) {
+ CORE;
+ return "Parent key doesn't match Object key";
+ }
+ if (object->mh.ident) {
+ if (strlen(object->mh.ident) <= 0) {
+ CORE;
+ return "Too short ident";
+ }
+ if (father->hash) {
+ if (aisc_read_hash((aisc_hash_node **)father->hash, object->mh.ident)) {
+ CORE;
+ return "Object already in list";
+ }
+ else {
+ aisc_insert_hash((aisc_hash_node **)father->hash, object->mh.ident, (long)object);
+ }
+ }
+ else {
+ father->hash = (long)aisc_init_hash(HASH_SIZE);
+ aisc_insert_hash((aisc_hash_node **)father->hash, object->mh.ident, (long)object);
+ }
+ }
+ object->next = object->previous = NULL;
+ if (!father->first) {
+ father->cnt = 1;
+ father->first = object;
+ father->last = object;
+ }
+ else {
+ father->cnt++;
+ object->previous = father->last;
+ father->last->next = object;
+ father->last = object;
+ }
+ object->mh.parent = father;
+ return 0;
+}
+
+
+
+const char *aisc_unlink(dllheader_ext *object) {
+ dllpublic_ext *father = (dllpublic_ext *)object->mh.parent;
+
+ if (!father) {
+ CORE;
+ return "Object not linked";
+ }
+ if (father->hash) {
+ aisc_free_key((aisc_hash_node **)father->hash, object->mh.ident);
+ }
+ if (father->cnt <= 0) {
+ CORE;
+ return "Parent count is 0";
+ }
+ if (object->previous) {
+ if (object->previous->next != object) {
+ CORE;
+ return "Fatal Error: Object is a copy, not original";
+ }
+ object->previous->next = object->next;
+ }
+ else {
+ father->first = object->next;
+ }
+ if (object->next) {
+ object->next->previous = object->previous;
+ }
+ else {
+ father->last = object->previous;
+ }
+ object->mh.parent = NULL;
+ object->previous = NULL;
+ object->next = NULL;
+
+ father->cnt--;
+ if (!father->cnt) {
+ if (father->hash) {
+ aisc_free_hash((aisc_hash_node **)father->hash);
+ father->hash = 0;
+ }
+ }
+ return 0;
+}
+
+long aisc_find_lib(dllpublic_ext *parent, char *ident)
+{
+ if (!parent->hash) return 0;
+ if (!ident) return 0;
+ return aisc_read_hash((aisc_hash_node **)parent->hash, ident);
+}
+
+
+struct trf_dest_struct {
+ struct trf_dest_struct *next;
+ long *dest;
+};
+
+struct trf_struct {
+ struct trf_struct *next;
+ long new_item;
+ long old;
+ struct trf_dest_struct *dests;
+};
+
+static int trf_hash(long p)
+{
+ return (p+(p>>8))&(TRF_HASH_SIZE-1);
+}
+
+static int trf_level = 0;
+static struct trf_struct **trf_sp = 0;
+
+void trf_create(long old, long new_item) {
+ long i;
+ struct trf_struct *ts;
+ struct trf_dest_struct *tds, *ntds;
+ if (!trf_sp) return;
+ i = trf_hash(old);
+ for (ts = trf_sp[i]; ts; ts = ts->next) {
+ if (ts->old == old) {
+ if (ts->new_item && (ts->new_item != new_item)) {
+ GBK_terminate("ERROR IN trf_create");
+ }
+ else {
+ ts->new_item = new_item;
+ for (tds = ts->dests; tds; tds = ntds) {
+ *tds->dest = new_item;
+ ntds = tds->next;
+ free(tds);
+ }
+ }
+ return;
+ }
+ }
+ ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
+ ts->next = trf_sp[i];
+ trf_sp[i] = ts;
+ ts->new_item = new_item;
+ ts->old = old;
+}
+
+void trf_link(long old, long *dest)
+{
+ long i;
+ struct trf_struct *ts, *fts;
+ struct trf_dest_struct *tds;
+ if (!trf_sp) return;
+ i = trf_hash(old);
+ fts = 0;
+ for (ts = trf_sp[i]; ts; ts = ts->next) {
+ if (ts->old == old) { fts = ts; break; }
+ }
+ if (!fts) {
+ ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
+ ts->next = trf_sp[i];
+ trf_sp[i] = ts;
+ ts->old = old;
+ fts = ts;
+ }
+ tds = (struct trf_dest_struct *)calloc(sizeof(struct trf_dest_struct), 1);
+ tds->next = fts->dests;
+ fts->dests = tds;
+ tds->dest = dest;
+}
+
+void trf_begin() {
+ if (trf_level==0) {
+ trf_sp = (struct trf_struct **)calloc(sizeof(struct trf_struct *), TRF_HASH_SIZE);
+ }
+ trf_level ++;
+}
+
+void trf_commit(int errors) {
+ // if errors == 1 then print errors and CORE
+ struct trf_dest_struct *tds, *ntds;
+ struct trf_struct *ts, *nts;
+ trf_level--;
+ if (!trf_level) {
+ for (int i = 0; i < TRF_HASH_SIZE; i++) {
+ for (ts = trf_sp[i]; ts; ts = nts) {
+ if (errors) {
+ if (ts->dests) {
+ GBK_terminate("ERROR IN trf_commit");
+ }
+ }
+ else {
+ for (tds = ts->dests; tds; tds = ntds) {
+ ntds = tds->next;
+ free(tds);
+ }
+ }
+ nts = ts->next;
+ free(ts);
+ }
+ }
+ free(trf_sp);
+ trf_sp = 0;
+ }
+}
+
=====================================
AISC_COM/C/struct_man.h
=====================================
@@ -0,0 +1,29 @@
+/* This file is generated by aisc_mkpt.
+ * Any changes you make here will be overwritten later!
+ */
+
+#ifndef STRUCT_MAN_H
+#define STRUCT_MAN_H
+
+/* define ARB attributes: */
+#ifndef ATTRIBUTES_H
+# include <attributes.h>
+#endif
+
+
+/* struct_man.c */
+
+struct aisc_hash_node;
+
+long aisc_read_hash(aisc_hash_node **table, const char *key);
+const char *aisc_link(dllpublic_ext *father, dllheader_ext *object);
+const char *aisc_unlink(dllheader_ext *object);
+long aisc_find_lib(dllpublic_ext *parent, char *ident);
+void trf_create(long old, long new_item);
+void trf_link(long old, long *dest);
+void trf_begin(void);
+void trf_commit(int errors);
+
+#else
+#error struct_man.h included twice
+#endif /* STRUCT_MAN_H */
=====================================
AISC_COM/C/trace.h
=====================================
@@ -0,0 +1,67 @@
+// =============================================================== //
+// //
+// File : trace.h //
+// Purpose : //
+// //
+// Coded by Ralf Westram (coder at reallysoft.de) in May 2007 //
+// Institute of Microbiology (Technical University Munich) //
+// http://www.arb-home.de/ //
+// //
+// =============================================================== //
+#ifndef TRACE_H
+#define TRACE_H
+
+#if defined(DEBUG)
+// #define DUMP_COMMUNICATION
+#endif // DEBUG
+
+// --------------------------------------------------------------------------------
+
+#if defined(DUMP_COMMUNICATION)
+
+static void aisc_dump_hex(const char *title, const char *data, int datasize) {
+ const unsigned char *udata = (const unsigned char *)data;
+ int d;
+
+ fprintf(stderr, "%s", title);
+ for (d = 0; d<datasize; d++) {
+ fprintf(stderr, "%02X", udata[d]);
+ }
+ fprintf(stderr, "\n");
+}
+
+static void aisc_dump_int(const char *where, const char *varname, int var) {
+ fprintf(stderr, "AISC_DUMP: %s: int %s=%i ", where, varname, var);
+ aisc_dump_hex("Hex: ", (const char*)&var, sizeof(var));
+}
+static void aisc_dump_long(const char *where, const char *varname, long var) {
+ fprintf(stderr, "AISC_DUMP: %s: long %s=%li ", where, varname, var);
+ aisc_dump_hex("Hex: ", (const char*)&var, sizeof(var));
+}
+static void aisc_dump_double(const char *where, const char *varname, double var) {
+ fprintf(stderr, "AISC_DUMP: %s: double %s=%f ", where, varname, (float)var);
+ aisc_dump_hex("Hex: ", (const char*)&var, sizeof(var));
+}
+static void aisc_dump_charPtr(const char *where, const char *varname, const char *var) {
+ fprintf(stderr, "AISC_DUMP: %s: cPtr %s='%s' ", where, varname, var);
+ aisc_dump_hex("Hex: ", var, strlen(var)+1);
+}
+static void aisc_dump_voidPtr2(const char *where, const char *varname, void *var) {
+ fprintf(stderr, "AISC_DUMP: %s: ptr %s=%p\n", where, varname, var);
+}
+
+#define aisc_dump_voidPtr(w, n, v) aisc_dump_voidPtr2(w, n, (void*)v)
+#define AISC_DUMP(where, type, var) aisc_dump_##type(#where, #var, var)
+#define AISC_DUMP_SEP() fprintf(stderr, "-----------------------------\n")
+
+#else
+#define AISC_DUMP(where, type, var)
+#define AISC_DUMP_SEP()
+#endif // DUMP_COMMUNICATION
+
+// --------------------------------------------------------------------------------
+
+#else
+#error trace.h included twice
+#endif // TRACE_H
+
View it on GitLab: https://salsa.debian.org/med-team/libarb/compare/030a422d48f58956f8e03a32db2aa60123db74c8...8f7aae391183c4a07623f5d68101d5c8d8a5e91a
--
View it on GitLab: https://salsa.debian.org/med-team/libarb/compare/030a422d48f58956f8e03a32db2aa60123db74c8...8f7aae391183c4a07623f5d68101d5c8d8a5e91a
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20190607/99eb67ac/attachment-0001.html>
More information about the debian-med-commit
mailing list