/* * DIS (Delphi Information Server) Package implements a library of * routines to be used by servers. * * Started on : 10-11-91 * Last modification : 28-07-94 * Written by : C. Gaspar * Adjusted by : G.C. Ballintijn * */ #ifdef VMS # include # include # include # include #endif /* #define DEBUG */ #include #ifdef VAX #include #else #include #endif #define DIMLIB #include #include #define ALL 0 #define MORE 1 #define NONE 2 typedef struct dis_dns_ent { struct dis_dns_ent *next; struct dis_dns_ent *prev; long dnsid; char task_name[MAX_NAME]; TIMR_ENT *dns_timr_ent; DIS_DNS_PACKET dis_dns_packet; int dis_n_services; int dns_dis_conn_id; int dis_first_time; int serving; unsigned int dis_service_id; unsigned int dis_client_id; int updating_service_list; } DIS_DNS_CONN; typedef struct req_ent { struct req_ent *next; struct req_ent *prev; int conn_id; int service_id; int req_id; int type; struct serv *service_ptr; int timeout; int format; int first_time; int delay_delete; int to_delete; TIMR_ENT *timr_ent; struct reqp_ent *reqpp; } REQUEST; typedef struct serv { struct serv *next; struct serv *prev; char name[MAX_NAME]; int id; int type; char def[MAX_NAME]; FORMAT_STR format_data[MAX_NAME/4]; int *address; int size; void (*user_routine)(); long tag; int registered; int quality; int user_secs; int user_millisecs; int tid; REQUEST *request_head; DIS_DNS_CONN *dnsp; int delay_delete; int to_delete; } SERVICE; typedef struct reqp_ent { struct reqp_ent *next; struct reqp_ent *prev; REQUEST *reqp; } REQUEST_PTR; typedef struct cli_ent { struct cli_ent *next; struct cli_ent *prev; int conn_id; REQUEST_PTR *requestp_head; DIS_DNS_CONN *dnsp; } CLIENT; static CLIENT *Client_head = (CLIENT *)0; static DIS_DNS_CONN *DNS_head = (DIS_DNS_CONN *)0; /* static char Task_name[MAX_NAME]; static TIMR_ENT *Dns_timr_ent = (TIMR_ENT *)0; static DIS_DNS_PACKET Dis_dns_packet = {0, 0, {0}}; static int Dis_n_services = 0; */ static int Dis_first_time = 1; /* static int Dns_dis_conn_id = 0; */ static int Protocol; static int Port_number; static int Dis_conn_id = 0; static int Curr_conn_id = 0; static int Serving = 0; static void (*Client_exit_user_routine)() = 0; static void (*Exit_user_routine)() = 0; static void (*Error_user_routine)() = 0; static int Error_conn_id = 0; DIS_DNS_CONN *Default_DNS = 0; typedef struct exit_ent { struct exit_ent *next; int conn_id; int exit_id; } EXIT_H; static EXIT_H *Exit_h_head = (EXIT_H *)0; /* Do not forget to increase when this file is modified */ static int Version_number = DIM_VERSION_NUMBER; static int Dis_timer_q = 0; static int Threads_off = 0; /* static unsigned int Dis_service_id, Dis_client_id; static int Updating_service_list = 0; */ static int Last_client; #ifdef DEBUG static int Debug_on = 1; #else static int Debug_on = 0; #endif _DIM_PROTO( static void dis_insert_request, (int conn_id, DIC_PACKET *dic_packet, int size, int status ) ); _DIM_PROTO( int execute_service, (int req_id) ); _DIM_PROTO( void execute_command, (SERVICE *servp, DIC_PACKET *packet) ); _DIM_PROTO( void register_dns_services, (int flag) ); _DIM_PROTO( void register_services, (DIS_DNS_CONN *dnsp, int flag, int dns_flag) ); _DIM_PROTO( void std_cmnd_handler, (long *tag, int *cmnd_buff, int *size) ); _DIM_PROTO( void client_info, (long *tag, int **bufp, int *size) ); _DIM_PROTO( void service_info, (long *tag, int **bufp, int *size) ); _DIM_PROTO( void add_exit_handler, (int *tag, int *bufp, int *size) ); _DIM_PROTO( static void exit_handler, (int *tag, int *bufp, int *size) ); _DIM_PROTO( static void error_handler, (int conn_id, int severity, int errcode, char *reason) ); _DIM_PROTO( SERVICE *find_service, (char *name) ); _DIM_PROTO( CLIENT *find_client, (int conn_id) ); _DIM_PROTO( static int get_format_data, (FORMAT_STR *format_data, char *def) ); _DIM_PROTO( static int release_conn, (int conn_id, int print_flag, int dns_flag) ); _DIM_PROTO( SERVICE *dis_hash_service_exists, (char *name) ); _DIM_PROTO( SERVICE *dis_hash_service_get_next, (int *start, SERVICE *prev, int flag) ); _DIM_PROTO( static unsigned do_dis_add_service_dns, (char *name, char *type, void *address, int size, void (*user_routine)(), long tag, long dnsid ) ); _DIM_PROTO( static DIS_DNS_CONN *create_dns, (long dnsid) ); void dis_set_debug_on() { Debug_on = 1; } void dis_set_debug_off() { Debug_on = 0; } void dis_no_threads() { Threads_off = 1; } static DIS_STAMPED_PACKET *Dis_packet = 0; static int Dis_packet_size = 0; int dis_set_buffer_size(int size) { if(Dis_packet_size) free(Dis_packet); Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size); if(Dis_packet) { Dis_packet_size = DIS_STAMPED_HEADER + size; return(1); } else return(0); } static int check_service_name(char *name) { if(strlen(name) > (MAX_NAME - 1)) return(0); return(1); } static void dis_init() { int dis_hash_service_init(); void dis_dns_init(); dis_dns_init(); { DISABLE_AST dis_hash_service_init(); ENABLE_AST } } static unsigned do_dis_add_service_dns( char *name, char *type, void *address, int size, void (*user_routine)(), long tag, long dnsid ) { register SERVICE *new_serv; register int service_id; char str[512]; int dis_hash_service_insert(); DIS_DNS_CONN *dnsp; extern DIS_DNS_CONN *dis_find_dns(long); dis_init(); { DISABLE_AST if(!check_service_name(name)) { strcpy(str,"Service name too long: "); strcat(str,name); error_handler(0, DIM_ERROR, DIMSVCTOOLG, str); ENABLE_AST return((unsigned) 0); } if( find_service(name) ) { strcpy(str,"Duplicate Service: "); strcat(str,name); error_handler(0, DIM_ERROR, DIMSVCDUPLC, str); ENABLE_AST return((unsigned) 0); } new_serv = (SERVICE *)malloc( sizeof(SERVICE) ); strncpy( new_serv->name, name, MAX_NAME ); if(type != (char *)0) { if (strlen(type) >= MAX_NAME) { strcpy(str,"Format String Too Long: "); strcat(str,name); error_handler(0, DIM_ERROR, DIMSVCFORMT, str); free(new_serv); ENABLE_AST return((unsigned) 0); } if (! get_format_data(new_serv->format_data, type)) { strcpy(str,"Bad Format String: "); strcat(str,name); error_handler(0, DIM_ERROR, DIMSVCFORMT, str); free(new_serv); ENABLE_AST return((unsigned) 0); } strcpy(new_serv->def,type); } else { new_serv->format_data[0].par_bytes = 0; new_serv->def[0] = '\0'; } new_serv->type = 0; new_serv->address = (int *)address; new_serv->size = size; new_serv->user_routine = user_routine; new_serv->tag = tag; new_serv->registered = 0; new_serv->quality = 0; new_serv->user_secs = 0; new_serv->tid = 0; new_serv->delay_delete = 0; new_serv->to_delete = 0; dnsp = dis_find_dns(dnsid); if(!dnsp) dnsp = create_dns(dnsid); new_serv->dnsp = dnsp; service_id = id_get((void *)new_serv, SRC_DIS); new_serv->id = service_id; new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST)); dll_init( (DLL *) (new_serv->request_head) ); dis_hash_service_insert(new_serv); /* Dis_n_services++; */ dnsp->dis_n_services++; ENABLE_AST } return((unsigned)service_id); } static unsigned do_dis_add_service( char *name, char *type, void *address, int size, void (*user_routine)(), long tag ) { return do_dis_add_service_dns( name, type, address, size, user_routine, tag, 0 ); } #ifdef VxWorks void dis_destroy(int tid) { register SERVICE *servp, *prevp; int n_left = 0; prevp = 0; while( servp = dis_hash_service_get_next(prevp)) { if(servp->tid == tid) { dis_remove_service(servp->id); } else { prevp = servp; n_left++; } } if(n_left == 5) { prevp = 0; while( servp = dis_hash_service_get_next(prevp)) { dis_remove_service(servp->id); } dna_close(Dis_conn_id); dna_close(Dns_dis_conn_id); Dns_dis_conn_id = 0; Dis_first_time = 1; dtq_rem_entry(Dis_timer_q, Dns_timr_ent); Dns_timr_ent = NULL; } } #endif unsigned dis_add_service( char *name, char *type, void *address, int size, void (*user_routine)(), long tag) { unsigned ret; #ifdef VxWorks register SERVICE *servp; #endif /* DISABLE_AST */ ret = do_dis_add_service( name, type, address, size, user_routine, tag); #ifdef VxWorks servp = (SERVICE *)id_get_ptr(ret, SRC_DIS); servp->tid = taskIdSelf(); #endif /* ENABLE_AST */ return(ret); } unsigned dis_add_service_dns( long dnsid, char *name, char *type, void *address, int size, void (*user_routine)(), long tag) { unsigned ret; #ifdef VxWorks register SERVICE *servp; #endif /* DISABLE_AST */ ret = do_dis_add_service_dns( name, type, address, size, user_routine, tag, dnsid); #ifdef VxWorks servp = (SERVICE *)id_get_ptr(ret, SRC_DIS); servp->tid = taskIdSelf(); #endif /* ENABLE_AST */ return(ret); } static unsigned do_dis_add_cmnd_dns( char *name, char *type, void (*user_routine)(), long tag, long dnsid ) { register SERVICE *new_serv; register int service_id; char str[512]; int dis_hash_service_insert(); DIS_DNS_CONN *dnsp; extern DIS_DNS_CONN *dis_find_dns(long); dis_init(); { DISABLE_AST if(!check_service_name(name)) { strcpy(str,"Command name too long: "); strcat(str,name); error_handler(0, DIM_ERROR, DIMSVCTOOLG, str); ENABLE_AST return((unsigned) 0); } if( find_service(name) ) { ENABLE_AST return((unsigned) 0); } new_serv = (SERVICE *)malloc(sizeof(SERVICE)); strncpy(new_serv->name, name, MAX_NAME); if(type != (char *)0) { if( !get_format_data(new_serv->format_data, type)) { ENABLE_AST return((unsigned) 0); } strcpy(new_serv->def,type); } else { new_serv->format_data[0].par_bytes = 0; new_serv->def[0] = '\0'; } new_serv->type = COMMAND; new_serv->address = 0; new_serv->size = 0; if(user_routine) new_serv->user_routine = user_routine; else new_serv->user_routine = std_cmnd_handler; new_serv->tag = tag; new_serv->tid = 0; new_serv->registered = 0; new_serv->quality = 0; new_serv->user_secs = 0; new_serv->delay_delete = 0; new_serv->to_delete = 0; service_id = id_get((void *)new_serv, SRC_DIS); new_serv->id = service_id; dnsp = dis_find_dns(dnsid); if(!dnsp) dnsp = create_dns(dnsid); new_serv->dnsp = dnsp; new_serv->request_head = (REQUEST *)malloc(sizeof(REQUEST)); dll_init( (DLL *) (new_serv->request_head) ); dis_hash_service_insert(new_serv); /* Dis_n_services++; */ dnsp->dis_n_services++; ENABLE_AST } return((unsigned) service_id); } static unsigned do_dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag) { return do_dis_add_cmnd_dns(name, type, user_routine, tag, 0); } unsigned dis_add_cmnd( char *name, char *type, void (*user_routine)(), long tag ) { unsigned ret; /* DISABLE_AST */ ret = do_dis_add_cmnd( name, type, user_routine, tag ); /* ENABLE_AST */ return(ret); } unsigned dis_add_cmnd_dns( long dnsid, char *name, char *type, void (*user_routine)(), long tag ) { unsigned ret; /* DISABLE_AST */ ret = do_dis_add_cmnd_dns( name, type, user_routine, tag, dnsid ); /* ENABLE_AST */ return(ret); } void dis_add_client_exit_handler( void (*user_routine)()) { DISABLE_AST Client_exit_user_routine = user_routine; ENABLE_AST } void dis_add_exit_handler( void (*user_routine)()) { DISABLE_AST Exit_user_routine = user_routine; ENABLE_AST } void dis_add_error_handler( void (*user_routine)()) { DISABLE_AST Error_user_routine = user_routine; ENABLE_AST } static int get_format_data(FORMAT_STR *format_data, char *def) { register char code, last_code = 0; int num; code = *def; while(*def) { if(code != last_code) { format_data->par_num = 0; format_data->flags = 0; switch(code) { case 'i': case 'I': case 'l': case 'L': format_data->par_bytes = SIZEOF_LONG; format_data->flags |= SWAPL; break; case 'x': case 'X': format_data->par_bytes = SIZEOF_DOUBLE; format_data->flags |= SWAPD; break; case 's': case 'S': format_data->par_bytes = SIZEOF_SHORT; format_data->flags |= SWAPS; break; case 'f': case 'F': format_data->par_bytes = SIZEOF_FLOAT; format_data->flags |= SWAPL; #ifdef vms format_data->flags |= IT_IS_FLOAT; #endif break; case 'd': case 'D': format_data->par_bytes = SIZEOF_DOUBLE; format_data->flags |= SWAPD; #ifdef vms format_data->flags |= IT_IS_FLOAT; #endif break; case 'c': case 'C': format_data->par_bytes = SIZEOF_CHAR; format_data->flags |= NOSWAP; break; } } def++; if(*def != ':') { if(*def) { /* printf("Bad service definition parsing\n"); fflush(stdout); error_handler("Bad service definition parsing",2); */ return(0); } else format_data->par_num = 0; } else { def++; sscanf(def,"%d",&num); format_data->par_num += num; while((*def != ';') && (*def != '\0')) def++; if(*def) def++; } last_code = code; code = *def; if(code != last_code) format_data++; } format_data->par_bytes = 0; return(1); } void recv_dns_dis_rout( int conn_id, DNS_DIS_PACKET *packet, int size, int status ) { char str[128]; int dns_timr_time; extern int rand_tmout(int, int); extern int open_dns(long, void (*)(), void (*)(), int, int, int); extern DIS_DNS_CONN *find_dns_by_conn_id(int); extern void do_register_services(DIS_DNS_CONN *); extern void do_dis_stop_serving_dns(DIS_DNS_CONN *); DIS_DNS_CONN *dnsp; if(size){} dnsp = find_dns_by_conn_id(conn_id); if(!dnsp) { return; } switch(status) { case STA_DISC: /* connection broken */ if( dnsp->dns_timr_ent ) { dtq_rem_entry( Dis_timer_q, dnsp->dns_timr_ent ); dnsp->dns_timr_ent = NULL; } if(dnsp->dns_dis_conn_id > 0) dna_close(dnsp->dns_dis_conn_id); if(dnsp->serving) { dnsp->dns_dis_conn_id = open_dns(dnsp->dnsid, recv_dns_dis_rout, error_handler, DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS ); if(dnsp->dns_dis_conn_id == -2) error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined"); } break; case STA_CONN: /* connection received */ if(dnsp->serving) { dnsp->dns_dis_conn_id = conn_id; register_services(dnsp, ALL, 0); dns_timr_time = rand_tmout(WATCHDOG_TMOUT_MIN, WATCHDOG_TMOUT_MAX); dnsp->dns_timr_ent = dtq_add_entry( Dis_timer_q, dns_timr_time, do_register_services, dnsp ); } else { dna_close(conn_id); } break; default : /* normal packet */ if(vtohl(packet->size) != DNS_DIS_HEADER) break; switch( vtohl(packet->type) ) { case DNS_DIS_REGISTER : sprintf(str, "%s: Watchdog Timeout, DNS requests registration", dnsp->task_name); error_handler(0, DIM_WARNING, DIMDNSTMOUT, str); register_services(dnsp, ALL, 0); break; case DNS_DIS_KILL : sprintf(str, "%s: Some Services already known to DNS", dnsp->task_name); /* exit(2); */ error_handler(0, DIM_FATAL, DIMDNSDUPLC, str); do_dis_stop_serving_dns(dnsp); dis_stop_serving(); /* exit_tag = 0; exit_code = 2; exit_size = sizeof(int); exit_handler(&exit_tag, &exit_code, &exit_size); */ break; case DNS_DIS_STOP : sprintf(str, "%s: DNS refuses connection",dnsp->task_name); /* exit(2); */ error_handler(0, DIM_FATAL, DIMDNSREFUS, str); do_dis_stop_serving_dns(dnsp); dis_stop_serving(); /* exit_tag = 0; exit_code = 2; exit_size = sizeof(int); exit_handler(&exit_tag, &exit_code, &exit_size); */ break; case DNS_DIS_EXIT : sprintf(str, "%s: DNS requests Exit",dnsp->task_name); error_handler(0, DIM_FATAL, DIMDNSEXIT, str); break; } break; } } /* register services within the name server * * Send services uses the DNA package. services is a linked list of services * stored by add_service. */ int send_dns_update_packet(DIS_DNS_CONN *dnsp) { DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet); int n_services; SERVICE_REG *serv_regp; n_services = 1; dis_dns_p->n_services = htovl(n_services); dis_dns_p->size = htovl(DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)); serv_regp = dis_dns_p->services; strcpy( serv_regp->service_name, "DUMMY_UPDATE_PACKET" ); if(dnsp->dns_dis_conn_id > 0) { if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG))) { release_conn(dnsp->dns_dis_conn_id, 0, 1); } } return(1); } void do_register_services(DIS_DNS_CONN *dnsp) { register_services(dnsp, NONE, 0); } void register_services(DIS_DNS_CONN *dnsp, int flag, int dns_flag) { register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet); register int n_services, tot_n_services; register SERVICE *servp; register SERVICE_REG *serv_regp; int hash_index, new_entries; extern int get_node_addr(); int dis_hash_service_registered(); if(!dis_dns_p->src_type) { get_node_name( dis_dns_p->node_name ); /* strcpy( dis_dns_p->task_name, Task_name ); */ strncpy( dis_dns_p->task_name, dnsp->task_name, MAX_TASK_NAME-4 ); dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0'; get_node_addr( dis_dns_p->node_addr ); /* dis_dns_p->port = htovl(Port_number); */ dis_dns_p->pid = htovl(getpid()); dis_dns_p->protocol = htovl(Protocol); dis_dns_p->src_type = htovl(SRC_DIS); dis_dns_p->format = htovl(MY_FORMAT); } dis_dns_p->port = htovl(Port_number); serv_regp = dis_dns_p->services; n_services = 0; tot_n_services = 0; if( flag == NONE ) { dis_dns_p->n_services = htovl(n_services); dis_dns_p->size = htovl( DIS_DNS_HEADER + (n_services*sizeof(SERVICE_REG))); if(dnsp->dns_dis_conn_id > 0) { if(!dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), DIS_DNS_HEADER + n_services*sizeof(SERVICE_REG))) { release_conn(dnsp->dns_dis_conn_id, 0, 1); } } return; } if(flag == ALL) { servp = 0; hash_index = -1; while( (servp = dis_hash_service_get_next(&hash_index, servp, 0))) { if(servp->dnsp == dnsp) servp->registered = 0; } } servp = 0; hash_index = -1; new_entries = 0; if(flag == MORE) new_entries = 1; while( (servp = dis_hash_service_get_next(&hash_index, servp, new_entries))) { if( flag == MORE ) { if( servp->registered ) { continue; } } if(servp->dnsp != dnsp) continue; strcpy( serv_regp->service_name, servp->name ); strcpy( serv_regp->service_def, servp->def ); if(servp->type == COMMAND) serv_regp->service_id = htovl( servp->id | 0x10000000); else serv_regp->service_id = htovl( servp->id ); serv_regp++; n_services++; dis_hash_service_registered(hash_index, servp); if( n_services == MAX_SERVICE_UNIT ) { dis_dns_p->n_services = htovl(n_services); dis_dns_p->size = htovl(DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)); if(dnsp->dns_dis_conn_id > 0) { if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)) ) { release_conn(dnsp->dns_dis_conn_id, 0, 1); } } serv_regp = dis_dns_p->services; tot_n_services += MAX_SERVICE_UNIT; n_services = 0; continue; } } if( n_services ) { dis_dns_p->n_services = htovl(n_services); dis_dns_p->size = htovl(DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)); if(dnsp->dns_dis_conn_id > 0) { if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG))) { release_conn(dnsp->dns_dis_conn_id, 0, 1); } } tot_n_services += n_services; } if(!dns_flag) { if(tot_n_services >= MAX_REGISTRATION_UNIT) { send_dns_update_packet(dnsp); } } } void unregister_service(DIS_DNS_CONN *dnsp, SERVICE *servp) { register DIS_DNS_PACKET *dis_dns_p = &(dnsp->dis_dns_packet); register int n_services; register SERVICE_REG *serv_regp; extern int get_node_addr(); if(dnsp->dns_dis_conn_id > 0) { if(!dis_dns_p->src_type) { get_node_name( dis_dns_p->node_name ); /* strcpy( dis_dns_p->task_name, Task_name ); */ strncpy( dis_dns_p->task_name, dnsp->task_name, MAX_TASK_NAME-4 ); dis_dns_p->task_name[MAX_TASK_NAME-4-1] = '\0'; get_node_addr( dis_dns_p->node_addr ); dis_dns_p->port = htovl(Port_number); dis_dns_p->protocol = htovl(Protocol); dis_dns_p->src_type = htovl(SRC_DIS); dis_dns_p->format = htovl(MY_FORMAT); } serv_regp = dis_dns_p->services; strcpy( serv_regp->service_name, servp->name ); strcpy( serv_regp->service_def, servp->def ); serv_regp->service_id = htovl( servp->id | 0x80000000); serv_regp++; n_services = 1; servp->registered = 0; dis_dns_p->n_services = htovl(n_services); dis_dns_p->size = htovl(DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)); if( !dna_write(dnsp->dns_dis_conn_id, &(dnsp->dis_dns_packet), DIS_DNS_HEADER + n_services * sizeof(SERVICE_REG)) ) { release_conn(dnsp->dns_dis_conn_id, 0, 1); } if(dnsp->dis_service_id) dis_update_service(dnsp->dis_service_id); } } void do_update_service_list(DIS_DNS_CONN *dnsp) { dnsp->updating_service_list = 0; dis_update_service(dnsp->dis_service_id); } /* start serving client requests * * Using the DNA package start accepting requests from clients. * When a request arrives the routine "dis_insert_request" will be executed. */ int dis_start_serving(char *task) { return dis_start_serving_dns(0, task); } static DIS_DNS_CONN *create_dns(long dnsid) { DIS_DNS_CONN *dnsp; dnsp = malloc(sizeof(DIS_DNS_CONN)); dnsp->dns_timr_ent = (TIMR_ENT *)0; dnsp->dis_n_services = 0; dnsp->dns_dis_conn_id = 0; dnsp->dis_first_time = 1; dnsp->serving = 0; dnsp->dis_dns_packet.size = 0; dnsp->dis_dns_packet.src_type = 0; dnsp->dis_dns_packet.node_name[0] = 0; dnsp->updating_service_list = 0; dnsp->dnsid = dnsid; dll_insert_queue( (DLL *) DNS_head, (DLL *) dnsp ); return dnsp; } void dis_dns_init() { static int done = 0; DIS_DNS_CONN *dnsp; void dim_init_threads(void); if(!done) { if(!Threads_off) { dim_init_threads(); } { DISABLE_AST if(!DNS_head) { DNS_head = (DIS_DNS_CONN *)malloc(sizeof(DIS_DNS_CONN)); dll_init( (DLL *) DNS_head ); } dnsp = create_dns(0); Default_DNS = dnsp; done = 1; ENABLE_AST } } } int dis_start_serving_dns(long dnsid, char *task/*, int *idlist*/) { char str0[MAX_NAME], str1[MAX_NAME],str2[MAX_NAME], str3[MAX_NAME],str4[MAX_NAME]; char task_name_aux[MAX_TASK_NAME]; extern int open_dns(); extern DIS_DNS_CONN *dis_find_dns(long); DIS_DNS_CONN *dnsp; int more_ids[10] = {0}; dis_init(); { DISABLE_AST /* #ifdef VxWorks taskDeleteHookAdd(remove_all_services); printf("Adding delete hook\n"); #endif */ if(!Client_head) { Client_head = (CLIENT *)malloc(sizeof(CLIENT)); dll_init( (DLL *) Client_head ); } if(dnsid == 0) { dnsp = Default_DNS; } else if(!(dnsp = dis_find_dns(dnsid))) { dnsp = create_dns(dnsid); } dnsp->serving = 1; Serving = 1; if(Dis_first_time) { strncpy( task_name_aux, task, MAX_TASK_NAME ); task_name_aux[MAX_TASK_NAME-1] = '\0'; Port_number = SEEK_PORT; if( !(Dis_conn_id = dna_open_server( task_name_aux, dis_insert_request, &Protocol, &Port_number, error_handler) )) { ENABLE_AST return(0); } Dis_first_time = 0; } if(dnsp->dis_first_time) { dnsp->dis_first_time = 0; sprintf(str0, "%s/VERSION_NUMBER", task); sprintf(str1, "%s/CLIENT_LIST", task); sprintf(str2, "%s/SERVICE_LIST", task); sprintf(str3, "%s/SET_EXIT_HANDLER", task); sprintf(str4, "%s/EXIT", task); more_ids[0] = do_dis_add_service_dns( str0, "L", &Version_number, sizeof(Version_number), 0, 0, dnsid ); more_ids[1] = do_dis_add_service_dns( str1, "C", 0, 0, client_info, (long)dnsp, dnsid ); dnsp->dis_client_id = more_ids[1]; more_ids[2] = do_dis_add_service_dns( str2, "C", 0, 0, service_info, (long)dnsp, dnsid ); dnsp->dis_service_id = more_ids[2]; more_ids[3] = do_dis_add_cmnd_dns( str3, "L:1", add_exit_handler, 0, dnsid ); more_ids[4] = do_dis_add_cmnd_dns( str4, "L:1", exit_handler, 0, dnsid ); more_ids[5] = 0; strcpy( dnsp->task_name, task ); } /* if(idlist) { for(i = 0; idlist[i]; i++) { servp = (SERVICE *)id_get_ptr(idlist[i], SRC_DIS); if(servp) { servp->dnsp = dnsp; n_services++; } } } if(dnsp != Default_DNS) { for(i = 0; more_ids[i]; i++) { servp = (SERVICE *)id_get_ptr(more_ids[i], SRC_DIS); if(servp) { servp->dnsp = dnsp; n_services++; } } dnsp->dis_n_services += n_services; Dis_n_services -= n_services; } */ if(!Dis_timer_q) Dis_timer_q = dtq_create(); if( !dnsp->dns_dis_conn_id ) { if(!strcmp(task,"DIS_DNS")) { register_services(dnsp, ALL, 1); ENABLE_AST return(id_get(&(dnsp->dis_dns_packet), SRC_DIS)); } else { dnsp->dns_dis_conn_id = open_dns(dnsid, recv_dns_dis_rout, error_handler, DIS_DNS_TMOUT_MIN, DIS_DNS_TMOUT_MAX, SRC_DIS ); if(dnsp->dns_dis_conn_id == -2) error_handler(0, DIM_FATAL, DIMDNSUNDEF, "DIM_DNS_NODE undefined"); } } else { register_services(dnsp, MORE, 0); if(dnsp->dis_service_id) { /* dis_update_service(Dis_service_id); */ if(!dnsp->updating_service_list) { dtq_start_timer(1, do_update_service_list, dnsp); dnsp->updating_service_list = 1; } } } ENABLE_AST } return(1); } /* asynchrounous reception of requests */ /* Called by DNA package. A request has arrived, queue it to process later - dis_ins_request */ static void dis_insert_request(int conn_id, DIC_PACKET *dic_packet, int size, int status) { register SERVICE *servp; register REQUEST *newp, *reqp; CLIENT *clip; REQUEST_PTR *reqpp; int type, new_client = 0, found = 0; int find_release_request(); DIS_DNS_CONN *dnsp; if(size){} /* status = 1 => new connection, status = -1 => conn. lost */ if(!Client_head) { Client_head = (CLIENT *)malloc(sizeof(CLIENT)); dll_init( (DLL *) Client_head ); } if(status != 0) { if(status == -1) /* release all requests from conn_id */ { release_conn(conn_id, 0, 0); } } else { if(!(servp = find_service(dic_packet->service_name))) { release_conn(conn_id, 0, 0); return; } dic_packet->type = vtohl(dic_packet->type); type = dic_packet->type & 0xFFF; /* if(type == COMMAND) { Curr_conn_id = conn_id; execute_command(servp, dic_packet); Curr_conn_id = 0; return; } */ if(type == DIM_DELETE) { find_release_request(conn_id, vtohl(dic_packet->service_id)); return; } newp = (REQUEST *)/*my_*/malloc(sizeof(REQUEST)); newp->service_ptr = servp; newp->service_id = vtohl(dic_packet->service_id); newp->type = dic_packet->type; newp->timeout = vtohl(dic_packet->timeout); newp->format = vtohl(dic_packet->format); newp->conn_id = conn_id; newp->first_time = 1; newp->delay_delete = 0; newp->to_delete = 0; newp->timr_ent = 0; newp->req_id = id_get((void *)newp, SRC_DIS); newp->reqpp = 0; if(type == ONCE_ONLY) { execute_service(newp->req_id); id_free(newp->req_id, SRC_DIS); free(newp); return; } if(type == COMMAND) { Curr_conn_id = conn_id; execute_command(servp, dic_packet); Curr_conn_id = 0; reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(reqp->conn_id == conn_id) { id_free(newp->req_id, SRC_DIS); free(newp); found = 1; break; } } if(!found) dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp ); return; } dll_insert_queue( (DLL *) servp->request_head, (DLL *) newp ); if(!(clip = find_client(conn_id))) { clip = (CLIENT *)malloc(sizeof(CLIENT)); clip->conn_id = conn_id; clip->dnsp = servp->dnsp; clip->requestp_head = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR)); dll_init( (DLL *) clip->requestp_head ); dll_insert_queue( (DLL *) Client_head, (DLL *) clip ); new_client = 1; } reqpp = (REQUEST_PTR *)malloc(sizeof(REQUEST_PTR)); reqpp->reqp = newp; dll_insert_queue( (DLL *) clip->requestp_head, (DLL *) reqpp ); newp->reqpp = reqpp; if((type != MONIT_ONLY) && (type != UPDATE)) { execute_service(newp->req_id); } if((type != MONIT_ONLY) && (type != MONIT_FIRST)) { if(newp->timeout != 0) { newp->timr_ent = dtq_add_entry( Dis_timer_q, newp->timeout, execute_service, newp->req_id ); } } if(new_client) { Last_client = conn_id; dnsp = clip->dnsp; if(dnsp->dis_client_id) dis_update_service(dnsp->dis_client_id); } } } /* A timeout for a timed or monitored service occured, serve it. */ int execute_service( int req_id ) { int *buffp, size; register REQUEST *reqp; register SERVICE *servp; char str[80], def[MAX_NAME]; register char *ptr; int last_conn_id; int *pkt_buffer, header_size, aux; #ifdef WIN32 struct timeb timebuf; #else struct timeval tv; struct timezone *tz; #endif FORMAT_STR format_data_cp[MAX_NAME/4]; reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS); if(!reqp) return(0); if(reqp->to_delete) return(0); reqp->delay_delete++; servp = reqp->service_ptr; last_conn_id = Curr_conn_id; Curr_conn_id = reqp->conn_id; ptr = servp->def; if(servp->type == COMMAND) { sprintf(str,"This is a COMMAND Service"); buffp = (int *)str; size = 26; sprintf(def,"c:26"); ptr = def; } else if( servp->user_routine != 0 ) { (servp->user_routine)( &servp->tag, &buffp, &size, &reqp->first_time ); reqp->first_time = 0; } else { buffp = servp->address; size = servp->size; } Curr_conn_id = last_conn_id; /* send even if no data but not if negative */ if( size < 0) { reqp->delay_delete--; return(0); } if( DIS_STAMPED_HEADER + size > Dis_packet_size ) { if( Dis_packet_size ) free( Dis_packet ); Dis_packet = (DIS_STAMPED_PACKET *)malloc(DIS_STAMPED_HEADER + size); if(!Dis_packet) { reqp->delay_delete--; return(0); } Dis_packet_size = DIS_STAMPED_HEADER + size; } Dis_packet->service_id = htovl(reqp->service_id); if((reqp->type & 0xFF000) == STAMPED) { pkt_buffer = ((DIS_STAMPED_PACKET *)Dis_packet)->buffer; header_size = DIS_STAMPED_HEADER; if(!servp->user_secs) { #ifdef WIN32 ftime(&timebuf); aux = timebuf.millitm; Dis_packet->time_stamp[0] = htovl(aux); Dis_packet->time_stamp[1] = htovl((int)timebuf.time); #else tz = 0; gettimeofday(&tv, tz); aux = tv.tv_usec / 1000; Dis_packet->time_stamp[0] = htovl(aux); Dis_packet->time_stamp[1] = htovl(tv.tv_sec); #endif } else { aux = /*0xc0de0000 |*/ servp->user_millisecs; Dis_packet->time_stamp[0] = htovl(aux); Dis_packet->time_stamp[1] = htovl(servp->user_secs); } Dis_packet->reserved[0] = htovl(0xc0dec0de); Dis_packet->quality = htovl(servp->quality); } else { pkt_buffer = ((DIS_PACKET *)Dis_packet)->buffer; header_size = DIS_HEADER; } memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp)); size = copy_swap_buffer_out(reqp->format, format_data_cp, pkt_buffer, buffp, size); Dis_packet->size = htovl(header_size + size); if( !dna_write_nowait(reqp->conn_id, Dis_packet, header_size + size) ) { reqp->to_delete = 1; } /* else { if((reqp->type & 0xFFF) == MONITORED) { if(reqp->timr_ent) dtq_clear_entry(reqp->timr_ent); } } */ reqp->delay_delete--; return(1); } void remove_service( int req_id ) { register REQUEST *reqp; register SERVICE *servp; static DIS_PACKET *dis_packet; static int packet_size = 0; int service_id; reqp = (REQUEST *)id_get_ptr(req_id, SRC_DIS); servp = reqp->service_ptr; if( !packet_size ) { dis_packet = (DIS_PACKET *)malloc(DIS_HEADER); packet_size = DIS_HEADER; } service_id = (reqp->service_id | 0x80000000); dis_packet->service_id = htovl(service_id); dis_packet->size = htovl(DIS_HEADER); if( !dna_write(reqp->conn_id, dis_packet, DIS_HEADER) ) { release_conn(reqp->conn_id, 0, 0); } } void execute_command(SERVICE *servp, DIC_PACKET *packet) { int size; int format; FORMAT_STR format_data_cp[MAX_NAME/4], *formatp; static int *buffer; static int buffer_size = 0; int add_size; size = vtohl(packet->size) - DIC_HEADER; add_size = size + (size/2); if(!buffer_size) { buffer = (int *)malloc(add_size); buffer_size = add_size; } else { if( add_size > buffer_size ) { free(buffer); buffer = (int *)malloc(add_size); buffer_size = add_size; } } dis_set_timestamp(servp->id, 0, 0); if(servp->user_routine != 0) { format = vtohl(packet->format); memcpy(format_data_cp, servp->format_data, sizeof(format_data_cp)); if((format & 0xF) == ((MY_FORMAT) & 0xF)) { for(formatp = format_data_cp; formatp->par_bytes; formatp++) { if(formatp->flags & IT_IS_FLOAT) formatp->flags |= (format & 0xf0); formatp->flags &= 0xFFF0; /* NOSWAP */ } } else { for(formatp = format_data_cp; formatp->par_bytes; formatp++) { if(formatp->flags & IT_IS_FLOAT) formatp->flags |= (format & 0xf0); } } size = copy_swap_buffer_in(format_data_cp, buffer, packet->buffer, size); (servp->user_routine)(&servp->tag, buffer, &size); } } void dis_report_service(char *serv_name) { register SERVICE *servp; register REQUEST *reqp; int to_delete = 0, more; DISABLE_AST servp = find_service(serv_name); reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if((reqp->type & 0xFFF) != TIMED_ONLY) { execute_service(reqp->req_id); if(reqp->to_delete) to_delete = 1; } } if(to_delete) { do { more = 0; reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(reqp->to_delete) { more = 1; release_conn(reqp->conn_id, 1, 0); break; } } }while(more); } ENABLE_AST } int dis_update_service(unsigned service_id) { int do_update_service(); return(do_update_service(service_id,0)); } int dis_selective_update_service(unsigned service_id, int *client_ids) { int do_update_service(); return(do_update_service(service_id, client_ids)); } int check_client(REQUEST *reqp, int *client_ids) { if(!client_ids) return(1); while(*client_ids) { if(reqp->conn_id == *client_ids) { return(1); } client_ids++; } return(0); } int do_update_service(unsigned service_id, int *client_ids) { register REQUEST *reqp; register SERVICE *servp; REQUEST_PTR *reqpp; CLIENT *clip; register int found = 0; int to_delete = 0, more, conn_id; char str[128]; int release_request(); DISABLE_AST if(!service_id) { sprintf(str, "Update Service - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return(found); } servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS); if(!servp) { ENABLE_AST return(found); } if(servp->id != (int)service_id) { ENABLE_AST return(found); } servp->delay_delete = 1; reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(Debug_on) { dim_print_date_time_millis(); printf("Updating %s (id = %ld, ptr = %08lX) for %s@%s (req_id = %d, req_ptr = %08lX)\n", servp->name, (long)service_id, (long)servp, Net_conns[reqp->conn_id].task, Net_conns[reqp->conn_id].node, reqp->req_id, (long)reqp); } if(check_client(reqp, client_ids)) reqp->delay_delete = 1; } ENABLE_AST { DISABLE_AST reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(reqp->delay_delete && ((reqp->type & 0xFFF) != COMMAND)) { if(check_client(reqp, client_ids)) { if( (reqp->type & 0xFFF) != TIMED_ONLY ) { /* DISABLE_AST */ execute_service(reqp->req_id); found++; ENABLE_AST { DISABLE_AST } } } } } ENABLE_AST } { DISABLE_AST reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(check_client(reqp, client_ids)) { reqp->delay_delete = 0; if(reqp->to_delete) to_delete = 1; } } ENABLE_AST } if(to_delete) { DISABLE_AST do { more = 0; reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(reqp->to_delete & 0x1) { more = 1; reqp->to_delete = 0; release_conn(reqp->conn_id, 1, 0); break; } else if(reqp->to_delete & 0x2) { more = 1; reqp->to_delete = 0; reqpp = reqp->reqpp; conn_id = reqp->conn_id; release_request(reqp, reqpp, 1); clip = find_client(conn_id); if(clip) { if( dll_empty((DLL *)clip->requestp_head) ) { release_conn( conn_id, 0, 0); } } break; } } }while(more); ENABLE_AST } { DISABLE_AST servp->delay_delete = 0; if(servp->to_delete) { dis_remove_service(servp->id); } ENABLE_AST } return(found); } int dis_get_n_clients(unsigned service_id) { register REQUEST *reqp; register SERVICE *servp; register int found = 0; char str[128]; DISABLE_AST if(!service_id) { sprintf(str, "Service Has Clients- Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return(found); } servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS); if(!servp) { ENABLE_AST return(found); } if(servp->id != (int)service_id) { ENABLE_AST return(found); } reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { found++; } ENABLE_AST return found; } int dis_get_timeout(unsigned service_id, int client_id) { register REQUEST *reqp; register SERVICE *servp; char str[128]; if(!service_id) { sprintf(str,"Get Timeout - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); return(-1); } servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS); if(!servp) { return(-1); } reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { if(reqp->conn_id == client_id) return(reqp->timeout); } return(-1); } void dis_set_quality( unsigned serv_id, int quality ) { register SERVICE *servp; char str[128]; DISABLE_AST if(!serv_id) { sprintf(str,"Set Quality - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return; } servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS); if(!servp) { ENABLE_AST return; } if(servp->id != (int)serv_id) { ENABLE_AST return; } servp->quality = quality; ENABLE_AST } int dis_set_timestamp( unsigned serv_id, int secs, int millisecs ) { register SERVICE *servp; char str[128]; #ifdef WIN32 struct timeb timebuf; #else struct timeval tv; struct timezone *tz; #endif DISABLE_AST if(!serv_id) { sprintf(str,"Set Timestamp - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return(0); } servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS); if(!servp) { ENABLE_AST return(0); } if(servp->id != (int)serv_id) { ENABLE_AST return(0); } if(secs == 0) { #ifdef WIN32 ftime(&timebuf); servp->user_secs = (int)timebuf.time; servp->user_millisecs = timebuf.millitm; #else tz = 0; gettimeofday(&tv, tz); servp->user_secs = tv.tv_sec; servp->user_millisecs = tv.tv_usec / 1000; #endif } else { servp->user_secs = secs; /* servp->user_millisecs = (millisecs & 0xffff); */ servp->user_millisecs = millisecs; } ENABLE_AST return(1); } int dis_get_timestamp( unsigned serv_id, int *secs, int *millisecs ) { register SERVICE *servp; char str[128]; DISABLE_AST if(!serv_id) { sprintf(str,"Get Timestamp - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return(0); } servp = (SERVICE *)id_get_ptr(serv_id, SRC_DIS); if(!servp) { ENABLE_AST return(0); } if(servp->id != (int)serv_id) { ENABLE_AST return(0); } if(servp->user_secs) { *secs = servp->user_secs; *millisecs = servp->user_millisecs; } else { *secs = 0; *millisecs = 0; } ENABLE_AST return(1); } void dis_send_service(unsigned service_id, int *buffer, int size) { register REQUEST *reqp, *prevp; register SERVICE *servp; static DIS_PACKET *dis_packet; static int packet_size = 0; int conn_id; char str[128]; DISABLE_AST if( !service_id ) { sprintf(str,"Send Service - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return; } servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS); if(!packet_size) { dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size); packet_size = DIS_HEADER + size; } else { if( DIS_HEADER+size > packet_size ) { free(dis_packet); dis_packet = (DIS_PACKET *)malloc(DIS_HEADER+size); packet_size = DIS_HEADER+size; } } prevp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) prevp)) ) { dis_packet->service_id = htovl(reqp->service_id); memcpy(dis_packet->buffer, buffer, size); dis_packet->size = htovl(DIS_HEADER + size); conn_id = reqp->conn_id; if( !dna_write_nowait(conn_id, dis_packet, size + DIS_HEADER) ) { release_conn(conn_id, 1, 0); } else prevp = reqp; } ENABLE_AST } int dis_remove_service(unsigned service_id) { register REQUEST *reqp, *auxp; register SERVICE *servp; REQUEST_PTR *reqpp; int found = 0; char str[128]; int release_request(); int dis_hash_service_remove(); DIS_DNS_CONN *dnsp; int n_services; void do_dis_stop_serving_dns(DIS_DNS_CONN *); DISABLE_AST if(!service_id) { sprintf(str,"Remove Service - Invalid service id"); error_handler(0, DIM_ERROR, DIMSVCINVAL, str); ENABLE_AST return(found); } servp = (SERVICE *)id_get_ptr(service_id, SRC_DIS); if(!servp) { ENABLE_AST return(found); } if(servp->id != (int)service_id) { ENABLE_AST return(found); } if(servp->delay_delete) { servp->to_delete = 1; ENABLE_AST return(found); } /* remove from name server */ dnsp = servp->dnsp; unregister_service(dnsp, servp); /* Release client requests and remove from actual clients */ reqp = servp->request_head; while( (reqp = (REQUEST *) dll_get_next((DLL *)servp->request_head, (DLL *) reqp)) ) { remove_service(reqp->req_id); auxp = reqp->prev; reqpp = (REQUEST_PTR *) reqp->reqpp; release_request(reqp, reqpp, 1); found = 1; reqp = auxp; } if(servp->id == (int)dnsp->dis_service_id) dnsp->dis_service_id = 0; if(servp->id == (int)dnsp->dis_client_id) dnsp->dis_client_id = 0; dis_hash_service_remove(servp); id_free(servp->id, SRC_DIS); free(servp->request_head); free(servp); /* if(dnsp != Default_DNS) { dnsp->dis_n_services--; n_services = dnsp->dis_n_services; } else { Dis_n_services--; n_services = Dis_n_services; } */ dnsp->dis_n_services--; n_services = dnsp->dis_n_services; ENABLE_AST if(dnsp->serving) { if(n_services == 5) { /* dis_stop_serving(); */ do_dis_stop_serving_dns(dnsp); } } return(found); } void do_dis_stop_serving_dns(DIS_DNS_CONN *dnsp) { register SERVICE *servp, *prevp; void dim_stop_threads(void); int dis_no_dns(); int hash_index, old_index; dnsp->serving = 0; dis_init(); /* dis_hash_service_init(); prevp = 0; if(Dis_conn_id) { dna_close(Dis_conn_id); Dis_conn_id = 0; } */ { DISABLE_AST if(dnsp->dns_timr_ent) { dtq_rem_entry(Dis_timer_q, dnsp->dns_timr_ent); dnsp->dns_timr_ent = NULL; } if(dnsp->dns_dis_conn_id) { dna_close(dnsp->dns_dis_conn_id); dnsp->dns_dis_conn_id = 0; } ENABLE_AST } { DISABLE_AST prevp = 0; hash_index = -1; old_index = -1; while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) ) { if(servp->dnsp == dnsp) { dis_remove_service(servp->id); if(old_index != hash_index) prevp = 0; } else { prevp = servp; old_index = hash_index; } } ENABLE_AST } dnsp->dis_first_time = 1; /* if(dnsp != Default_DNS) { dll_remove(dnsp); free(dnsp); } */ /* if(dll_empty(DNS_head)) */ if(dis_no_dns()) dis_stop_serving(); } void dis_stop_serving_dns(long dnsid) { DIS_DNS_CONN *dnsp, *dis_find_dns(); dnsp = dis_find_dns(dnsid); do_dis_stop_serving_dns(dnsp); } void dis_stop_serving() { register SERVICE *servp, *prevp; void dim_stop_threads(void); int hash_index; Serving = 0; dis_init(); if(Dis_conn_id) { dna_close(Dis_conn_id); Dis_conn_id = 0; } /* if(Dns_dis_conn_id) { dna_close(Dns_dis_conn_id); Dns_dis_conn_id = 0; } */ { DISABLE_AST prevp = 0; hash_index = -1; while( (servp = dis_hash_service_get_next(&hash_index, prevp, 0)) ) { dis_remove_service(servp->id); prevp = 0; } ENABLE_AST } /* if(Dis_conn_id) dna_close(Dis_conn_id); if(Dns_dis_conn_id) dna_close(Dns_dis_conn_id); Dns_dis_conn_id = 0; */ Dis_first_time = 1; /* if(Dns_timr_ent) { dtq_rem_entry(Dis_timer_q, Dns_timr_ent); Dns_timr_ent = NULL; } */ dtq_delete(Dis_timer_q); Dis_timer_q = 0; dim_stop_threads(); } /* find service by name */ SERVICE *find_service(char *name) { return(dis_hash_service_exists(name)); } CLIENT *find_client(int conn_id) { register CLIENT *clip; clip = (CLIENT *) dll_search( (DLL *) Client_head, &conn_id, sizeof(conn_id)); return(clip); } void release_all_requests(int conn_id, CLIENT *clip) { register REQUEST_PTR *reqpp, *auxp; register REQUEST *reqp; int found = 0; int release_request(); DIS_DNS_CONN *dnsp; DISABLE_AST; if(clip) { reqpp = clip->requestp_head; while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head, (DLL *) reqpp)) ) { auxp = reqpp->prev; reqp = (REQUEST *) reqpp->reqp; release_request(reqp, reqpp, 0); found = 1; reqpp = auxp; } dnsp = clip->dnsp; dll_remove(clip); free(clip->requestp_head); free(clip); } if(found) { Last_client = -conn_id; if(dnsp->dis_client_id) dis_update_service(dnsp->dis_client_id); } dna_close(conn_id); ENABLE_AST; } CLIENT *check_delay_delete(int conn_id) { register REQUEST_PTR *reqpp; register CLIENT *clip; register REQUEST *reqp; int found = 0; DISABLE_AST; clip = find_client(conn_id); if(clip) { reqpp = clip->requestp_head; while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head, (DLL *) reqpp)) ) { reqp = (REQUEST *) reqpp->reqp; if(reqp->delay_delete) { reqp->to_delete = 1; found = 1; } } } ENABLE_AST; if(found) { return((CLIENT *)-1); } return(clip); } char *dis_get_error_services() { return(dis_get_client_services(Error_conn_id)); } char *dis_get_client_services(int conn_id) { register REQUEST_PTR *reqpp; register CLIENT *clip; register REQUEST *reqp; register SERVICE *servp; int n_services = 0; int max_size; static int curr_allocated_size = 0; static char *service_info_buffer; char *buff_ptr; if(!conn_id) return((char *)0); { DISABLE_AST; clip = find_client(conn_id); if(clip) { reqpp = clip->requestp_head; while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head, (DLL *) reqpp))) { n_services++; } if(!n_services) { ENABLE_AST return((char *)0); } max_size = n_services * MAX_NAME; if(!curr_allocated_size) { service_info_buffer = (char *)malloc(max_size); curr_allocated_size = max_size; } else if (max_size > curr_allocated_size) { free(service_info_buffer); service_info_buffer = (char *)malloc(max_size); curr_allocated_size = max_size; } service_info_buffer[0] = '\0'; buff_ptr = service_info_buffer; reqpp = clip->requestp_head; while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head, (DLL *) reqpp)) ) { reqp = (REQUEST *) reqpp->reqp; servp = reqp->service_ptr; strcat(buff_ptr, servp->name); strcat(buff_ptr, "\n"); buff_ptr += strlen(buff_ptr); } } else { ENABLE_AST return((char *)0); } ENABLE_AST; } /* dim_print_date_time(); dna_get_node_task(conn_id, node, task); printf("Client %s@%s uses services: \n", task, node); printf("%s\n",service_info_buffer); */ return(service_info_buffer); } int find_release_request(int conn_id, int service_id) { register REQUEST_PTR *reqpp, *auxp; register CLIENT *clip; register REQUEST *reqp; int release_request(); DISABLE_AST clip = find_client(conn_id); if(clip) { reqpp = clip->requestp_head; while( (reqpp = (REQUEST_PTR *) dll_get_next((DLL *)clip->requestp_head, (DLL *) reqpp)) ) { reqp = (REQUEST *) reqpp->reqp; if(reqp->service_id == service_id) { if(reqp->delay_delete) { reqp->to_delete += 0x2; } else { auxp = reqpp->prev; release_request(reqp, reqpp, 0); reqpp = auxp; } } } if( dll_empty((DLL *)clip->requestp_head) ) { release_conn( conn_id, 0, 0 ); } } ENABLE_AST return(1); } int release_request(REQUEST *reqp, REQUEST_PTR *reqpp, int remove) { int conn_id; CLIENT *clip; DISABLE_AST conn_id = reqp->conn_id; if(reqpp) dll_remove((DLL *)reqpp); dll_remove((DLL *)reqp); if(reqp->timr_ent) dtq_rem_entry(Dis_timer_q, reqp->timr_ent); id_free(reqp->req_id, SRC_DIS); free(reqp); free(reqpp); /* Would do it too early, the client will disconnect anyway */ if((remove) && (!Serving)) { clip = find_client(conn_id); if(clip) { if( dll_empty((DLL *)clip->requestp_head) ) { release_conn( conn_id, 0, 0); } } } ENABLE_AST return(1); } static int release_conn(int conn_id, int print_flg, int dns_flag) { static int releasing = 0; CLIENT *clip; int do_exit_handler(); DISABLE_AST if(print_flg){} if(dns_flag) { recv_dns_dis_rout( conn_id, 0, 0, STA_DISC ); ENABLE_AST return(0); } #ifdef VMS if(print_flg) { dim_print_date_time(); dna_get_node_task(conn_id, node, task); printf(" Couldn't write to client %s@%s, releasing connection %d\n", task, node, conn_id); fflush(stdout); } #endif clip = check_delay_delete(conn_id); if(clip != (CLIENT *)-1) { if( Client_exit_user_routine != 0 ) { releasing++; Curr_conn_id = conn_id; do_exit_handler(conn_id); releasing--; } if(!releasing) { release_all_requests(conn_id, clip); } } ENABLE_AST return(1); } typedef struct cmnds{ struct cmnds *next; long tag; int size; int buffer[1]; } DIS_CMND; static DIS_CMND *Cmnds_head = (DIS_CMND *)0; void std_cmnd_handler(long *tag, int *cmnd_buff, int *size) { register DIS_CMND *new_cmnd; /* queue the command */ if(!Cmnds_head) { Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND)); sll_init((SLL *) Cmnds_head); } new_cmnd = (DIS_CMND *)malloc((*size)+12); new_cmnd->next = 0; new_cmnd->tag = *tag; new_cmnd->size = *size; memcpy(new_cmnd->buffer, cmnd_buff, *size); sll_insert_queue((SLL *) Cmnds_head, (SLL *) new_cmnd); } int dis_get_next_cmnd(long *tag, int *buffer, int *size) { register DIS_CMND *cmndp; register int ret_val = -1; DISABLE_AST if(!Cmnds_head) { Cmnds_head = (DIS_CMND *)malloc(sizeof(DIS_CMND)); sll_init((SLL *) Cmnds_head); } if(*size == 0) { if( (cmndp = (DIS_CMND *) sll_get_head((SLL *) Cmnds_head))) { if(cmndp->size > 0) { *size = cmndp->size; *tag = cmndp->tag; ENABLE_AST return(-1); } } } if( (cmndp = (DIS_CMND *) sll_remove_head((SLL *) Cmnds_head)) ) { if (*size >= cmndp->size) { *size = cmndp->size; ret_val = 1; } memcpy(buffer, cmndp->buffer, *size); *tag = cmndp->tag; free(cmndp); ENABLE_AST return(ret_val); } ENABLE_AST return(0); } int dis_get_conn_id() { return(Curr_conn_id); } int dis_get_client(char *name) { int ret = 0; char node[MAX_NODE_NAME], task[MAX_TASK_NAME]; DISABLE_AST if(Curr_conn_id) { dna_get_node_task(Curr_conn_id, node, task); strcpy(name,task); strcat(name,"@"); strcat(name,node); ret = Curr_conn_id; } ENABLE_AST return(ret); } #ifdef VMS dis_convert_str(c_str, for_str) char *c_str; struct dsc$descriptor_s *for_str; { int i; strcpy(for_str->dsc$a_pointer, c_str); for(i = strlen(c_str); i< for_str->dsc$w_length; i++) for_str->dsc$a_pointer[i] = ' '; } #endif void client_info(long *tag, int **bufp, int *size, int *first_time) { register CLIENT *clip; int curr_conns[MAX_CONNS]; int i, index, max_size; static int curr_allocated_size = 0; static char *dns_info_buffer; register char *dns_client_info; char node[MAX_NODE_NAME], task[MAX_TASK_NAME]; DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag; max_size = sizeof(DNS_CLIENT_INFO); if(!curr_allocated_size) { dns_info_buffer = malloc(max_size); curr_allocated_size = max_size; } dns_client_info = dns_info_buffer; dns_client_info[0] = '\0'; index = 0; if(*first_time) { clip = Client_head; while( (clip = (CLIENT *)dll_get_next( (DLL *) Client_head, (DLL*) clip)) ) { if(clip->dnsp != dnsp) continue; curr_conns[index++] = clip->conn_id; } max_size = (index+1)*sizeof(DNS_CLIENT_INFO); if (max_size > curr_allocated_size) { free(dns_info_buffer); dns_info_buffer = malloc(max_size); curr_allocated_size = max_size; } dns_client_info = dns_info_buffer; dns_client_info[0] = '\0'; } else { if(Last_client > 0) { strcat(dns_client_info,"+"); curr_conns[index++] = Last_client; } else { strcat(dns_client_info,"-"); curr_conns[index++] = -Last_client; } } for(i=0; iname,"/RpcIn")) { strcpy(name,servp->name); ptr = (char *)strstr(name,"/RpcIn"); *ptr = 0; strcat(service_info_buffer, name); strcat(service_info_buffer, "|"); if(servp->def[0]) { strcat(service_info_buffer, servp->def); } strcat(name,"/RpcOut"); if( (servp = find_service(name)) ) { strcat(service_info_buffer, ","); if(servp->def[0]) { strcat(service_info_buffer, servp->def); } } strcat(service_info_buffer, "|RPC"); strcat(service_info_buffer, "\n"); } else if(strstr(servp->name,"/RpcOut")) { /* if(servp->def[0]) { strcat(service_info_buffer, servp->def); } strcat(service_info_buffer, "|RPC"); strcat(service_info_buffer, "\n"); */ } else { strcat(service_info_buffer, servp->name); strcat(service_info_buffer, "|"); if(servp->def[0]) { strcat(service_info_buffer, servp->def); } strcat(service_info_buffer, "|"); if(servp->type == COMMAND) { strcat(service_info_buffer, "CMD"); } strcat(service_info_buffer, "\n"); } } void service_info(long *tag, int **bufp, int *size, int *first_time) { register SERVICE *servp; int max_size, done = 0; static int curr_allocated_size = 0; static char *service_info_buffer; char *buff_ptr; DIS_DNS_CONN *dnsp = (DIS_DNS_CONN *)*tag; int hash_index; DISABLE_AST max_size = (dnsp->dis_n_services+10) * (MAX_NAME*2 + 4); if(!curr_allocated_size) { service_info_buffer = (char *)malloc(max_size); curr_allocated_size = max_size; } else if (max_size > curr_allocated_size) { free(service_info_buffer); service_info_buffer = (char *)malloc(max_size); curr_allocated_size = max_size; } service_info_buffer[0] = '\0'; buff_ptr = service_info_buffer; servp = 0; hash_index = -1; if(*first_time) { while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) ) { if(servp->dnsp != dnsp) continue; if(servp->registered) { servp->registered = 2; append_service(buff_ptr, servp); buff_ptr += strlen(buff_ptr); } } } else { while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) ) { if(servp->dnsp != dnsp) continue; if(servp->registered == 1) { if(!done) { strcat(buff_ptr, "+"); buff_ptr += strlen(buff_ptr); done = 1; } append_service(buff_ptr, servp); buff_ptr += strlen(buff_ptr); servp->registered = 2; } else if(servp->registered == 0) { strcat(buff_ptr, "-"); buff_ptr += strlen(buff_ptr); append_service(buff_ptr, servp); buff_ptr += strlen(buff_ptr); } } } *bufp = (int *)service_info_buffer; *size = buff_ptr - service_info_buffer+1; ENABLE_AST } void add_exit_handler(int *tag, int *bufp, int *size) { EXIT_H *newp; if(size){} if(tag){} if(*bufp) { if(!Exit_h_head) { Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H)); sll_init( (SLL *) Exit_h_head ); } newp = (EXIT_H *)malloc(sizeof(EXIT_H)); newp->conn_id = Curr_conn_id; newp->exit_id = *bufp; sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp ); } else { if(!Exit_h_head) return; if((newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, (char *)&Curr_conn_id, 4)) ) { sll_remove( (SLL *) Exit_h_head, (SLL *) newp ); } } } void dis_set_client_exit_handler(int conn_id, int tag) { EXIT_H *newp; DISABLE_AST if(tag) { if(!Exit_h_head) { Exit_h_head = (EXIT_H *)malloc(sizeof(EXIT_H)); sll_init( (SLL *) Exit_h_head ); } if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, (char *)&conn_id, 4)) ) { newp->conn_id = conn_id; newp->exit_id = tag; } else { newp = (EXIT_H *)malloc(sizeof(EXIT_H)); newp->conn_id = conn_id; newp->exit_id = tag; sll_insert_queue( (SLL *) Exit_h_head, (SLL *) newp ); } } else { if(!Exit_h_head) { ENABLE_AST return; } if( (newp = (EXIT_H *)sll_search((SLL *) Exit_h_head, (char *)&conn_id, 4)) ) { sll_remove( (SLL *) Exit_h_head, (SLL *) newp ); } } ENABLE_AST } int do_exit_handler(int conn_id) { register EXIT_H *exitp; DISABLE_AST; if(!Exit_h_head) { ENABLE_AST; return(0); } while( (exitp = (EXIT_H *) sll_search_next_remove((SLL *) Exit_h_head, 0, (char *) &conn_id, 4)) ) { (Client_exit_user_routine)( &exitp->exit_id ); free(exitp); } ENABLE_AST return(1); } static void exit_handler(int *tag, int *bufp, int *size) { if(size){} if(tag){} if(Exit_user_routine) (Exit_user_routine)( bufp ); else { /* printf("%s PID %d Exiting!\n", Task_name, getpid()); */ exit(*bufp); } } static void error_handler(int conn_id, int severity, int errcode, char *reason) { int exit_tag, exit_code, exit_size; int last_conn_id; if(Error_user_routine) { Error_conn_id = conn_id; last_conn_id = Curr_conn_id; Curr_conn_id = conn_id; (Error_user_routine)( severity, errcode, reason); Error_conn_id = 0; Curr_conn_id = last_conn_id; } else { dim_print_msg(reason, severity); } if(severity == DIM_FATAL) { exit_tag = 0; exit_code = errcode; exit_size = sizeof(int); exit_handler(&exit_tag, &exit_code, &exit_size); } } /* #define MAX_HASH_ENTRIES 2000 */ #define MAX_HASH_ENTRIES 5000 static SERVICE *Service_hash_table[MAX_HASH_ENTRIES]; static int Service_new_entries[MAX_HASH_ENTRIES]; int dis_hash_service_init() { int i; static int done = 0; if(!done) { for( i = 0; i < MAX_HASH_ENTRIES; i++ ) { Service_hash_table[i] = (SERVICE *) malloc(8); dll_init((DLL *) Service_hash_table[i]); Service_new_entries[i] = 0; } done = 1; } return(1); } int dis_hash_service_insert(SERVICE *servp) { int index; index = HashFunction(servp->name, MAX_HASH_ENTRIES); Service_new_entries[index]++; dll_insert_queue((DLL *) Service_hash_table[index], (DLL *) servp); return(1); } int dis_hash_service_registered(int index, SERVICE *servp) { servp->registered = 1; Service_new_entries[index]--; if(Service_new_entries[index] < 0) Service_new_entries[index] = 0; return 1; } int dis_hash_service_remove(SERVICE *servp) { dll_remove( (DLL *) servp ); return(1); } SERVICE *dis_hash_service_exists(char *name) { int index; SERVICE *servp; index = HashFunction(name, MAX_HASH_ENTRIES); if( (servp = (SERVICE *) dll_search( (DLL *) Service_hash_table[index], name, strlen(name)+1)) ) { return(servp); } return((SERVICE *)0); } SERVICE *dis_hash_service_get_next(int *curr_index, SERVICE *prevp, int new_entries) { int index; SERVICE *servp = 0; /* if(!prevp) { index = -1; } */ index = *curr_index; if(index == -1) { index++; prevp = Service_hash_table[index]; } if(!prevp) { prevp = Service_hash_table[index]; } do { if((!new_entries) || (Service_new_entries[index] > 0)) { servp = (SERVICE *) dll_get_next( (DLL *) Service_hash_table[index], (DLL *) prevp); if(servp) break; } index++; if(index == MAX_HASH_ENTRIES) { *curr_index = -1; return((SERVICE *) 0); } prevp = Service_hash_table[index]; } while(!servp); *curr_index = index; return(servp); } DIS_DNS_CONN *dis_find_dns(long dnsid) { DIS_DNS_CONN *dnsp; dnsp = (DIS_DNS_CONN *) dll_search( (DLL *) DNS_head, &dnsid, sizeof(dnsid)); /* if(!dnsp) { dnsp = create_dns(dnsid); } */ return dnsp; } int dis_no_dns() { DIS_DNS_CONN *dnsp; dnsp = (DIS_DNS_CONN *) DNS_head; while ( (dnsp = (DIS_DNS_CONN *) dll_get_next( (DLL *) DNS_head, (DLL *) dnsp))) { /* if(dnsp != Default_DNS) return 0; */ if(dnsp->serving) return 0; } return 1; } DIS_DNS_CONN *find_dns_by_conn_id(int conn_id) { DIS_DNS_CONN *dnsp; extern long dns_get_dnsid(); long dnsid; dnsid = dns_get_dnsid(conn_id, SRC_DIS); dnsp = dis_find_dns(dnsid); if(!dnsp) dnsp = Default_DNS; return (DIS_DNS_CONN *)dnsp; } void dis_print_hash_table() { SERVICE *servp; int i; int n_entries, max_entry_index = 0; int max_entries = 0; for( i = 0; i < MAX_HASH_ENTRIES; i++ ) { n_entries = 0; servp = Service_hash_table[i]; while( (servp = (SERVICE *) dll_get_next( (DLL *) Service_hash_table[i], (DLL *) servp)) ) { n_entries++; if(n_entries == 1) printf(" Name = %s\n",servp->name); } if(n_entries != 0) printf("HASH[%d] - %d entries\n", i, n_entries); if(n_entries > max_entries) { max_entries = n_entries; max_entry_index = i; } } printf("Maximum : HASH[%d] - %d entries\n", max_entry_index, max_entries); fflush(stdout); } void dis_hash_print() { SERVICE *servp; int hash_index; servp = 0; hash_index = -1; while( (servp = dis_hash_service_get_next(&hash_index, servp, 0)) ) { printf("Name = %s\n",servp->name); } } #ifdef VMS /* CFORTRAN WRAPPERS */ FCALLSCFUN1(INT, dis_start_serving, DIS_START_SERVING, dis_start_serving, STRING) FCALLSCFUN3(INT, dis_get_next_cmnd, DIS_GET_NEXT_CMND, dis_get_next_cmnd, PINT, PVOID, PINT) FCALLSCFUN1(INT, dis_get_client, DIS_GET_CLIENT, dis_get_client, PSTRING) FCALLSCFUN6(INT, dis_add_service, DIS_ADD_SERVICE, dis_add_service, STRING, PVOID, PVOID, INT, PVOID, INT) FCALLSCSUB4( dis_add_cmnd, DIS_ADD_CMND, dis_add_cmnd, STRING, PVOID, PVOID, INT) FCALLSCSUB1( dis_add_client_exit_handler, DIS_ADD_CLIENT_EXIT_HANDLER, dis_add_client_exit_handler, PVOID) FCALLSCSUB2( dis_set_client_exit_handler, DIS_SET_CLIENT_EXIT_HANDLER, dis_set_client_exit_handler, INT, INT) FCALLSCSUB1( dis_add_exit_handler, DIS_ADD_EXIT_HANDLER, dis_add_exit_handler, PVOID) FCALLSCSUB1( dis_report_service, DIS_REPORT_SERVICE, dis_report_service, STRING) FCALLSCSUB2( dis_convert_str, DIS_CONVERT_STR, dis_convert_str, PVOID, PVOID) FCALLSCFUN1(INT, dis_update_service, DIS_UPDATE_SERVICE, dis_update_service, INT) FCALLSCFUN1(INT, dis_remove_service, DIS_REMOVE_SERVICE, dis_remove_service, INT) FCALLSCSUB3( dis_send_service, DIS_SEND_SERVICE, dis_send_service, INT, PVOID, INT) FCALLSCSUB2( dis_set_quality, DIS_SET_QUALITY, dis_set_quality, INT, INT) FCALLSCSUB3(INT, dis_set_timestamp, DIS_SET_TIMESTAMP, dis_set_timestamp, INT, INT, INT) FCALLSCFUN2(INT, dis_selective_update_service, DIS_SELECTIVE_UPDATE_SERVICE, dis_selective_update_service, INT, PINT) FCALLSCSUB3(INT, dis_get_timestamp, DIS_GET_TIMESTAMP, dis_get_timestamp, INT, PINT, PINT) #endif