/** * Initializes the session related structures. */ int session_init() { session_lock = lock_alloc(); if (!session_lock){ LOG_NO_MEM("lock",sizeof(gen_lock_t)); goto error; } session_lock = lock_init(session_lock); session_id1 = shm_malloc(sizeof(unsigned int)); if (!session_id1){ LOG_NO_MEM("shm",sizeof(unsigned int)); goto error; } session_id2 = shm_malloc(sizeof(unsigned int)); if (!session_id2){ LOG_NO_MEM("shm",sizeof(unsigned int)); goto error; } srand((unsigned int)time(0)); *session_id1 = rand(); *session_id1 <<= 16; *session_id1 += time(0)&0xFFFF; *session_id2 = 0; return 1; error: return 0; }
/** * Adds a timer to the timer list. * @param expires_in - time until expiration in seconds * @param one_time - if after expiration it should be removed or kept in the timers list * @param cb - callback function to be called on expiration * @param ptr - generic pointer to pass to the callback on expiration * @returns 1 on success or 0 on failure */ int add_timer(int expires_in,int one_time,callback_f cb,void *ptr) { timer_cb_t *n; if (expires_in==0){ LM_ERR("add_timer(): Minimum expiration time is 1 second!\n"); return 0; } n = shm_malloc(sizeof(timer_cb_t)); if (!n){ LOG_NO_MEM("shm",sizeof(timer_cb_t)); return 0; } n->ptr = shm_malloc(sizeof(void*)); if (!n){ LOG_NO_MEM("shm",sizeof(void*)); shm_free(n); return 0; } n->expires = expires_in + time(0); n->one_time = one_time; //n->interval = expires_in; n->cb = cb; *(n->ptr) = ptr; lock_get(timers_lock); n->prev = timers->tail; n->next = 0; if (!timers->head) timers->head = n; if (timers->tail) timers->tail->next = n; timers->tail = n; lock_release(timers_lock); return 1; }
/** * Create and add a transaction to the transaction list. * @param msg - the message that this related to * @param cb - callback to be called on response or time-out * @param ptr - generic pointer to pass to the callback on call * @param timeout - timeout time in seconds * @param auto_drop - whether to auto drop the transaction on event, or let the application do it later * @returns the created cdp_trans_t* or NULL on error */ inline cdp_trans_t* cdp_add_trans(AAAMessage *msg,AAATransactionCallback_f *cb, void *ptr,int timeout,int auto_drop) { cdp_trans_t *x; x = shm_malloc(sizeof(cdp_trans_t)); if (!x) { LOG_NO_MEM("shm",sizeof(cdp_trans_t)); return 0; } x->ptr = shm_malloc(sizeof(void*)); if (!x->ptr) { LOG_NO_MEM("shm",sizeof(void*)); shm_free(x); return 0; } x->endtoendid = msg->endtoendId; x->hopbyhopid = msg->hopbyhopId; x->cb = cb; *(x->ptr) = ptr; x->expires = timeout + time(0); x->auto_drop = auto_drop; x->next = 0; lock_get(trans_list->lock); x->prev = trans_list->tail; if (trans_list->tail) trans_list->tail->next = x; trans_list->tail = x; if (!trans_list->head) trans_list->head = x; lock_release(trans_list->lock); return x; }
/** Adds a new client to list of clients being serviced @Params int timeout - Interim period int callID - je->cid used to identify the subscriber being processed char *subscriber - subscriber name, e.g., Alice int cherge_type - online or offline charging (1 or 0) int did - SIP dialog ID Returns - 0 on failure and 1 on success */ inline int add_client(int timeout, int callID, char *subscriber, int charge_type, int did) { a_client *this; this = shm_malloc(sizeof(a_client)); if (!this) { LOG_NO_MEM("shm",sizeof(a_client)); return 0; } this->ptr = shm_malloc(sizeof(void*)); if (!this->ptr) { LOG_NO_MEM("shm",sizeof(void*)); shm_free(this); return 0; } this->next = 0; this->call_id = callID; this->call_did = did; this->credits = 0; this->timeout = timeout; this->clocking = Not; this->subscriber = subscriber; this->charge_type = charge_type; this->onceoff_credit = 0; this->persec_credit = 0; this->perMbyte_credit = 0; this->used_crtdonce = 0; this->used_crtdpsec = 0; this->used_crtdpMb = 0; this->used_crtdonce_buf = 0; this->used_crtdpsec_buf = 0; this->used_crtdpMb_buf = 0; this->used_crtdonce_buf1 = 0; this->used_crtdpsec_buf1 = 0; this->used_crtdpMb_buf1 = 0; lock_get(list_of_clients->lock); this->prev = list_of_clients->tail; if(list_of_clients->tail){ LOG(L_DBG,"add_client - Clients exist at tail\n"); list_of_clients->tail->next =this; } list_of_clients->tail = this; if (!list_of_clients->head) { LOG(L_DBG,"add_client - No client at head means no clients in the list\n"); list_of_clients->head = this; } lock_release(list_of_clients->lock); LOG(L_DBG,"add_client - We added client Name %s with callID %d\n",this->subscriber,this->call_id); return 1; }
/** * Initializes the session related structures. */ int sessions_init(int hash_size) { int i; session_lock = lock_alloc(); if (!session_lock){ LOG_NO_MEM("lock",sizeof(gen_lock_t)); goto error; } session_lock = lock_init(session_lock); sessions_hash_size=hash_size; sessions = shm_malloc(sizeof(cdp_session_list_t)*hash_size); if (!sessions){ LOG_NO_MEM("shm",sizeof(cdp_session_list_t)*hash_size); goto error; } memset(sessions,0,sizeof(cdp_session_list_t)*hash_size); for(i=0;i<hash_size;i++){ sessions[i].lock = lock_alloc(); if (!sessions[i].lock){ LOG_NO_MEM("lock",sizeof(gen_lock_t)); goto error; } sessions[i].lock = lock_init(sessions[i].lock); } session_id1 = shm_malloc(sizeof(unsigned int)); if (!session_id1){ LOG_NO_MEM("shm",sizeof(unsigned int)); goto error; } session_id2 = shm_malloc(sizeof(unsigned int)); if (!session_id2){ LOG_NO_MEM("shm",sizeof(unsigned int)); goto error; } srand((unsigned int)time(0)); *session_id1 = rand(); *session_id1 <<= 16; *session_id1 += time(0)&0xFFFF; *session_id2 = 0; add_timer(1,0,session_timer,0); return 1; error: return 0; }
/* * Initializes the charging timer @Params char *key_value_file - the IPTV hash table configuration file * * */ int msg_timer_init(char *key_value_file) { LOG(L_INFO,"UCT IMS Charging System\n"); LOG(L_INFO,"Developers: Vitalis Gavole Ozianyi and Joyce B. Mwangama (2009)\n"); LOG(L_INFO,"INFO: msg_timer_init() - Initialize message timer\n"); list_of_clients = shm_malloc(sizeof(client_list)); if (!list_of_clients){ LOG_NO_MEM("shm",sizeof(client_list)); return 0; } list_of_clients->head = 0; list_of_clients->tail = 0; list_of_clients->lock = lock_alloc(); list_of_clients->lock = lock_init(list_of_clients->lock); if(!add_timer(1,0,&msg_timer,0)) { LOG(L_ERR,"CTF - msg_timer_init() - Failed to adder timer"); return 0; } LOG(L_INFO,"INFO: msg_timer_init() - Calling the IPTV function\n\n"); if(!iptv_start(key_value_file)) { LOG(L_CRIT,"CRITICAL: msg_timer_init() - Error on iptv_start\n"); return 0; } return 1; }
/** * Create a new peer. * - All the memory from parameters is duplicated. * @param fqdn - FQDN of the peer * @param realm - Realm of the peer * @param port - port of the peer to connect to * @returns the new peer* if ok, NULL on error */ peer* new_peer(str fqdn,str realm,int port) { peer *x; x = shm_malloc(sizeof(peer)); if (!x){ LOG_NO_MEM("shm",sizeof(peer)); goto error; } memset(x,0,sizeof(peer)); shm_str_dup(x->fqdn,fqdn); if (!x->fqdn.s) goto error; shm_str_dup(x->realm,realm); if (!x->realm.s) goto error; x->port = port; x->lock = lock_alloc(); x->lock = lock_init(x->lock); x->state = Closed; x->I_sock = -1; x->R_sock = -1; x->activity = time(0)-500; x->next = 0; x->prev = 0; return x; error: return 0; }
/** * Initializes the worker structures, like the task queue. */ void worker_init() { tasks = shm_malloc(sizeof(task_queue_t)); tasks->lock = lock_alloc(); tasks->lock = lock_init(tasks->lock); tasks->empty = semget(IPC_PRIVATE,1,0666 | IPC_CREAT ); if (tasks->empty==-1){ LOG(L_ERR,"ERROR:worker_init(): Error creating semaphore for empty queue > %s\n",strerror(errno)); }else semctl(tasks->empty, 0, SETVAL, cdp_semun_init ); tasks->full = semget(IPC_PRIVATE,1, 0666 | IPC_CREAT ); if (tasks->full==-1){ LOG(L_ERR,"ERROR:worker_init(): Error creating semaphore for full queue > %s\n",strerror(errno)); }else semctl(tasks->full, 0, SETVAL, cdp_semun_init); tasks->start = 0; tasks->end = 0; tasks->max = config->queue_length; tasks->queue = shm_malloc(tasks->max*sizeof(task_t)); if (!tasks->queue) LOG_NO_MEM("shm",tasks->max*sizeof(task_t)); memset(tasks->queue,0,tasks->max*sizeof(task_t)); callbacks = shm_malloc(sizeof(cdp_cb_list_t)); callbacks->head = 0; callbacks->tail = 0; cdp_lock_get(tasks->empty); // lock_release(tasks->full); }
/*unsafe*/ int cb_add(cdp_cb_f cb, void *ptr) { cdp_cb_t *x; x = shm_malloc(sizeof (cdp_cb_t)); if (!x) { LOG_NO_MEM("shm", sizeof (cdp_cb_t)); return 0; } x->cb = cb; x->ptr = shm_malloc(sizeof (void*)); if (!x->ptr) { LOG_NO_MEM("shm", sizeof (void*)); return 0; } *(x->ptr) = ptr; x->next = 0; x->prev = callbacks->tail; if (callbacks->tail) callbacks->tail->next = x; callbacks->tail = x; if (!callbacks->head) callbacks->head = x; return 1; }
/** * Create a new dp_config. */ inline routing_entry *new_routing_entry() { routing_entry *x; x = shm_malloc(sizeof(routing_entry)); if (!x) { LOG_NO_MEM("shm",sizeof(routing_entry)); goto error; } memset(x,0,sizeof(routing_entry)); return x; error: LM_ERR("%s(): failed to create new routing_entry.\n",__FUNCTION__); return 0; }
/** * Create a new dp_config. */ inline dp_config *new_dp_config() { dp_config *x; x = shm_malloc(sizeof(dp_config)); if (!x) { LOG_NO_MEM("shm",sizeof(dp_config)); goto error; } memset(x,0,sizeof(dp_config)); return x; error: LM_ERR("%s(): failed to create new dp_config.\n",__FUNCTION__); return 0; }
/** * Initializes the transaction structure. * Also adds a timer callback for checking the transaction statuses * @returns 1 if success or 0 on error */ int cdp_trans_init() { trans_list = shm_malloc(sizeof(cdp_trans_list_t)); if (!trans_list){ LOG_NO_MEM("shm",sizeof(cdp_trans_list_t)); return 0; } trans_list->head = 0; trans_list->tail = 0; trans_list->lock = lock_alloc(); trans_list->lock = lock_init(trans_list->lock); add_timer(1,0,cdp_trans_timer,0); return 1; }
/* and in here we also loop for exosip events*/ void acceptor_process(dp_config *cfg) { int i,k; unsigned int sock; LOG(L_INFO,"INFO:Acceptor process starting up...\n"); listening_socks = pkg_malloc((cfg->acceptors_cnt+1)*sizeof(int)); if (!listening_socks){ LOG_NO_MEM("pkg",(cfg->acceptors_cnt+1)*sizeof(int)); goto done; } memset(listening_socks,0,(cfg->acceptors_cnt+1)*sizeof(int)); k=0; for(i=0;i<cfg->acceptors_cnt;i++) if (create_socket(cfg->acceptors[i].port,cfg->acceptors[i].bind,&sock)){ listening_socks[k++]=sock; } LOG(L_INFO,"INFO:... Acceptor opened sockets. Entering accept loop ...\n"); accept_loop(); for(i=0;listening_socks[i];i++) close(listening_socks[i]); if (listening_socks) pkg_free(listening_socks); #ifdef CDP_FOR_SER #else #ifdef PKG_MALLOC #ifdef PKG_MALLOC LOG(memlog, "Acceptor Memory status (pkg):\n"); //pkg_status(); #ifdef pkg_sums pkg_sums(); #endif #endif #endif dp_del_pid(getpid()); #endif done: LOG(L_INFO,"INFO:... Acceptor process finished\n"); exit(0); }
/** * Create a new session structure * @param id - the session id string, already allocated in shm * @param type - the session type * @returns the new cdp_session_t on success or 0 on failure */ cdp_session_t* new_session(str id,cdp_session_type_t type) { cdp_session_t *x=0; x = shm_malloc(sizeof(cdp_session_t)); if (!x){ LOG_NO_MEM("shm",sizeof(cdp_session_t)); goto error; } memset(x,0,sizeof(cdp_session_t)); x->id = id; x->type = type; x->hash = get_str_hash(x->id,sessions_hash_size); return x; error: return 0; }
/* * Initializes the timer for Listening to SIP requests at the IPTV server * */ int sip_timer_init() { a_sip_lock = shm_malloc(sizeof(sip_lock)); if(!a_sip_lock){ LOG_NO_MEM("shm",sizeof(sip_lock)); return 0; } a_sip_lock->lock = lock_alloc(); a_sip_lock->lock = lock_init(a_sip_lock->lock); if(!add_timer(1,0,&sip_timer,0)) { LOG(L_ERR,"CTF - sip_timer_init() - Failed to adder timer"); return 0; } return 1; }
/** * Trim the quotes from a string and duplicate it. * @param dest - destination for the untrimmed and duplicated string * @param src - source string */ static inline void quote_trim_dup(str *dest, char *src) { int i=0; dest->s=0; dest->len=0; if (!src) return; dest->len = strlen(src); if (src[0]=='\"') {i++;dest->len--;} if (src[dest->len-1]=='\"') {dest->len--;} dest->s = shm_malloc(dest->len+1); if (!dest->s) { LOG_NO_MEM("shm",dest->len); dest->len=0; return; } memcpy(dest->s,src+i,dest->len); dest->s[dest->len]=0; }
/** * Add a pid to the local process list. * @param pid newly forked pid * @returns 1 on success or 0 on error */ inline int dp_add_pid(pid_t pid) { pid_list_t *n; lock_get(pid_list_lock); n = shm_malloc(sizeof(pid_list_t)); if (!n){ LOG_NO_MEM("shm",sizeof(pid_list_t)); lock_release(pid_list_lock); return 0; } n->pid = pid; n->next = 0; n->prev = pid_list->tail; if (!pid_list->head) pid_list->head = n; if (pid_list->tail) pid_list->tail->next = n; pid_list->tail = n; lock_release(pid_list_lock); return 1; }
/** * Initializes the worker structures, like the task queue. */ void worker_init() { tasks = shm_malloc(sizeof(task_queue_t)); tasks->lock = lock_alloc(); tasks->lock = lock_init(tasks->lock); sem_new(tasks->empty,0); sem_new(tasks->full,1); tasks->start = 0; tasks->end = 0; tasks->max = config->queue_length; tasks->queue = shm_malloc(tasks->max*sizeof(task_t)); if (!tasks->queue) { LOG_NO_MEM("shm",tasks->max*sizeof(task_t)); goto out_of_memory; } memset(tasks->queue,0,tasks->max*sizeof(task_t)); callbacks = shm_malloc(sizeof(cdp_cb_list_t)); if (!callbacks) goto out_of_memory; callbacks->head = 0; callbacks->tail = 0; return; out_of_memory: if (tasks){ if (tasks->lock) { lock_destroy(tasks->lock); lock_dealloc(&(tasks->lock)); } sem_free(tasks->full); sem_free(tasks->empty); if (tasks->queue) shm_free(tasks->queue); shm_free(tasks); } if (callbacks) shm_free(callbacks); }
/** * Does the actual receive operations on the Diameter TCP socket, for retrieving incoming messages. * The functions is to be called iteratively, each time there is something to be read from the TCP socket. It uses * a simple state machine to read first the version, then the header and then the rest of the message. When an * entire message is received, it is decoded and passed to the processing functions. * @param sp - the serviced peer to operate on * @return 1 on success, 0 on failure */ static inline int do_receive(serviced_peer_t *sp) { int cnt,n,version; char *dst; AAAMessage *dmsg; switch (sp->state){ case Receiver_Waiting: n = 1; /* wait for version */ dst = sp->buf; break; case Receiver_Header: n = DIAMETER_HEADER_LEN - sp->buf_len; /* waiting for rest of header */ dst = sp->buf+sp->buf_len; break; case Receiver_Rest_of_Message: n = sp->length - sp->msg_len; /* waiting for the rest of the message */ dst = sp->msg+sp->msg_len; break; default: LM_ERR("do_receive(): [%.*s] Unknown state %d\n", sp->p?sp->p->fqdn.len:0, sp->p?sp->p->fqdn.s:0, sp->state); goto error_and_reset; } cnt = recv(sp->tcp_socket,dst,n,0); if (cnt<=0) goto error_and_reset; switch (sp->state){ case Receiver_Waiting: version = (unsigned char)(sp->buf[0]); if (version!=1) { LM_ERR("do_receive(): [%.*s] Received Unknown version [%d]\n", sp->p->fqdn.len, sp->p->fqdn.s, (unsigned char)sp->buf[0]); goto error_and_reset; }else{ sp->state = Receiver_Header; sp->buf_len = 1; } break; case Receiver_Header: sp->buf_len+=cnt; if (sp->buf_len==DIAMETER_HEADER_LEN){ sp->length = get_3bytes(sp->buf+1); if (sp->length>DP_MAX_MSG_LENGTH){ LM_ERR("do_receive(): [%.*s] Msg too big [%d] bytes\n", sp->p?sp->p->fqdn.len:0, sp->p?sp->p->fqdn.s:0, sp->length); goto error_and_reset; } LM_DBG("receive_loop(): [%.*s] Recv Version %d Length %d\n", sp->p?sp->p->fqdn.len:0, sp->p?sp->p->fqdn.s:0, (unsigned char)(sp->buf[0]), sp->length); sp->msg = shm_malloc(sp->length); if (!sp->msg) { LOG_NO_MEM("shm",sp->length); goto error_and_reset; } memcpy(sp->msg,sp->buf,sp->buf_len); sp->msg_len=sp->buf_len; sp->state = Receiver_Rest_of_Message; } break; case Receiver_Rest_of_Message: sp->msg_len+=cnt; if (sp->msg_len==sp->length){ dmsg = AAATranslateMessage((unsigned char*)sp->msg,(unsigned int)sp->msg_len,1); if (dmsg) { sp->msg = 0; receive_message(dmsg,sp); } else { shm_free(sp->msg); sp->msg = 0; } sp->msg_len = 0; sp->buf_len = 0; sp->state = Receiver_Waiting; } break; default: LM_ERR("do_receive(): [%.*s] Unknown state %d\n", sp->p?sp->p->fqdn.len:0, sp->p?sp->p->fqdn.s:0, sp->state); goto error_and_reset; } return 1; error_and_reset: if (sp->msg){ shm_free(sp->msg); sp->msg = 0; sp->msg_len = 0; sp->buf_len = 0; sp->state = Receiver_Waiting; } return 0; }
/** * Initialize the CDiameterPeer from a configuration file. * The file is kept as dtd. See configdtd.h for the DTD and ConfigExample.xml. * @param cfg_filename - file with the configuration * @returns 1 on success, 0 on error */ int diameter_peer_init(char *cfg_filename) { pid_list_t *i,*j; config = parse_dp_config(cfg_filename); if (!config) { LOG(L_ERR,"ERROR:init_diameter_peer(): Error loading configuration file. Aborting...\n"); goto error; } log_dp_config(L_INFO,config); dp_first_pid = shm_malloc(sizeof(pid_t)); if (!dp_first_pid){ LOG_NO_MEM("shm",sizeof(pid_t)); goto error; } *dp_first_pid = getpid(); shutdownx = shm_malloc(sizeof(int)); if (!shutdownx){ LOG_NO_MEM("shm",sizeof(int)); goto error; } *shutdownx = 0; shutdownx_lock = lock_alloc(); if (!shutdownx_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } shutdownx_lock = lock_init(shutdownx_lock); handlers_lock = lock_alloc(); if (!handlers_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } handlers_lock = lock_init(handlers_lock); handlers = shm_malloc(sizeof(handler_list)); if (!handlers){ LOG_NO_MEM("shm",sizeof(handler_list)); goto error; } handlers->head=0; handlers->tail=0; /* init the pid list */ pid_list = shm_malloc(sizeof(pid_list_head_t)); pid_list_lock = lock_alloc(); pid_list_lock = lock_init(pid_list_lock); /* init shared mem pointers before forking */ timer_cdp_init(); worker_init(); /* init the peer manager */ peer_manager_init(config); /* init the msg_handler */ //msg_timer_init(); /* init the session */ if (!session_init()) goto error; #ifdef CDP_FOR_SER /* init diameter transactions */ trans_init(); /* add callback for messages - used to implement the API */ cb_add(api_callback,0); #endif /*********** Added by Vitalis to initialize the transactions **********/ /* init diameter transactions */ trans_init(); /* add callback for messages - used to implement the API */ cb_add(api_callback,0); /*******End of addition ***********/ return 1; error: if (shutdownx) shm_free(shutdownx); if (config) free_dp_config(config); i = pid_list->head; while(i){ j = i->next; shm_free(i); i = j; } shm_free(pid_list); lock_get(pid_list_lock); lock_destroy(pid_list_lock); lock_dealloc((void*)pid_list_lock); return 0; }
/** * Parses a DiameterPeer configuration file. * @param filename - path to the file * @returns the dp_config* structure containing the parsed configuration */ dp_config* parse_dp_config(xmlDocPtr doc) { dp_config *x=0; xmlNodePtr root=0,child=0,nephew=0; xmlChar *xc=0; int k; routing_entry *re,*rei; routing_realm *rr,*rri; if (!doc) goto error; x = new_dp_config(); root = xmlDocGetRootElement(doc); if (!root){ LOG(L_ERR,"ERR:parse_dp_config(): Empty XML \n"); goto error; } k = xmlStrlen(root->name); if (k>12) k = 12; if (strncasecmp((char*)root->name,"DiameterPeer",k)!=0){ LOG(L_ERR,"ERR:parse_dp_config(): XML Root is not <DiameterPeer>\n"); goto error; } xc = xmlGetProp(root,(xmlChar*)"FQDN"); if (xc){ quote_trim_dup(&(x->fqdn),(char*)xc); quote_trim_dup(&(x->identity),(char*)xc); xmlFree(xc); } xc = xmlGetProp(root,(xmlChar*)"Realm"); if (xc){ quote_trim_dup(&(x->realm),(char*)xc); xmlFree(xc); } xc = xmlGetProp(root,(xmlChar*)"Vendor_Id"); if (xc) x->vendor_id = atoi((char*)xc); else x->vendor_id = 0; xc = xmlGetProp(root,(xmlChar*)"Product_Name"); if (xc){ quote_trim_dup(&(x->product_name),(char*)xc); xmlFree(xc); } xc = xmlGetProp(root,(xmlChar*)"AcceptUnknownPeers"); if (xc) {x->accept_unknown_peers = atoi((char*)xc);xmlFree(xc);} else x->accept_unknown_peers = 1; xc = xmlGetProp(root,(xmlChar*)"DropUnknownOnDisconnect"); if (xc) {x->drop_unknown_peers = atoi((char*)xc);xmlFree(xc);} else x->drop_unknown_peers = 1; xc = xmlGetProp(root,(xmlChar*)"Tc"); if (xc) {x->tc = atoi((char*)xc);xmlFree(xc);} else x->tc = 30; xc = xmlGetProp(root,(xmlChar*)"Workers"); if (xc) {x->workers = atoi((char*)xc);xmlFree(xc);} else x->workers = 4; xc = xmlGetProp(root,(xmlChar*)"QueueLength"); if (xc) {x->queue_length = atoi((char*)xc);xmlFree(xc);} else x->queue_length = 32; xc = xmlGetProp(root,(xmlChar*)"TransactionTimeout"); if (xc) {x->transaction_timeout = atoi((char*)xc);xmlFree(xc);} else x->transaction_timeout = 5; xc = xmlGetProp(root,(xmlChar*)"SessionsHashSize"); if (xc) {x->sessions_hash_size = atoi((char*)xc);xmlFree(xc);} else x->sessions_hash_size = 128; for(child = root->children; child; child = child->next) if (child->type == XML_ELEMENT_NODE) { if (xmlStrlen(child->name)==4 && strncasecmp((char*)child->name,"Peer",4)==0){ //PEER x->peers_cnt++; } else if (xmlStrlen(child->name)==8 && strncasecmp((char*)child->name,"Acceptor",8)==0){ //Acceptor x->acceptors_cnt++; } else if (xmlStrlen(child->name)==4 && (strncasecmp((char*)child->name,"Auth",4)==0|| strncasecmp((char*)child->name,"Acct",4)==0)){ //Application x->applications_cnt++; } } x->peers = shm_malloc(x->peers_cnt*sizeof(peer_config)); if (!x->peers){ LOG_NO_MEM("shm",x->peers_cnt*sizeof(peer_config)); goto error; } memset(x->peers,0,x->peers_cnt*sizeof(peer_config)); x->peers_cnt=0; x->acceptors = shm_malloc(x->acceptors_cnt*sizeof(acceptor_config)); if (!x->acceptors){ LOG_NO_MEM("shm",x->acceptors_cnt*sizeof(acceptor_config)); goto error; } memset(x->acceptors,0,x->acceptors_cnt*sizeof(acceptor_config)); x->acceptors_cnt=0; x->applications = shm_malloc(x->applications_cnt*sizeof(app_config)); if (!x->applications){ LOG_NO_MEM("shm",x->applications_cnt*sizeof(app_config)); goto error; } memset(x->applications,0,x->applications_cnt*sizeof(app_config)); x->applications_cnt=0; for(child = root->children; child; child = child->next) if (child->type == XML_ELEMENT_NODE) { if (xmlStrlen(child->name)==4 && strncasecmp((char*)child->name,"Peer",4)==0){ //PEER xc = xmlGetProp(child,(xmlChar*)"FQDN"); if (xc){ quote_trim_dup(&(x->peers[x->peers_cnt].fqdn),(char*)xc); xmlFree(xc); } xc = xmlGetProp(child,(xmlChar*)"Realm"); if (xc){ quote_trim_dup(&(x->peers[x->peers_cnt].realm),(char*)xc); xmlFree(xc); } xc = xmlGetProp(child,(xmlChar*)"port"); if (xc){ x->peers[x->peers_cnt].port = atoi((char*)xc); xmlFree(xc); } x->peers_cnt++; } else if (xmlStrlen(child->name)==8 && strncasecmp((char*)child->name,"Acceptor",8)==0){ //Acceptor xc = xmlGetProp(child,(xmlChar*)"bind"); if (xc){ quote_trim_dup(&(x->acceptors[x->acceptors_cnt].bind),(char*)xc); xmlFree(xc); } xc = xmlGetProp(child,(xmlChar*)"port"); if (xc){ x->acceptors[x->acceptors_cnt].port = atoi((char*)xc); xmlFree(xc); } x->acceptors_cnt++; } else if (xmlStrlen(child->name)==4 && ((char*)strncasecmp((char*)child->name,"Auth",4)==0|| strncasecmp((char*)child->name,"Acct",4)==0)){ //Application xc = xmlGetProp(child,(xmlChar*)"id"); if (xc){ x->applications[x->applications_cnt].id = atoi((char*)xc); xmlFree(xc); } xc = xmlGetProp(child,(xmlChar*)"vendor"); if (xc){ x->applications[x->applications_cnt].vendor = atoi((char*)xc); xmlFree(xc); } if (child->name[1]=='u'||child->name[1]=='U') x->applications[x->applications_cnt].type = DP_AUTHORIZATION; else x->applications[x->applications_cnt].type = DP_ACCOUNTING; x->applications_cnt++; } else if (xmlStrlen(child->name)==12 && ((char*)strncasecmp((char*)child->name,"DefaultRoute",12)==0)){ if (!x->r_table) { x->r_table = shm_malloc(sizeof(routing_table)); memset(x->r_table,0,sizeof(routing_table)); } re = new_routing_entry(); if (re){ xc = xmlGetProp(child,(xmlChar*)"FQDN"); if (xc){ quote_trim_dup(&(re->fqdn),(char*)xc); xmlFree(xc); } xc = xmlGetProp(child,(xmlChar*)"metric"); if (xc){ re->metric = atoi((char*)xc); xmlFree(xc); } /* add it the list in ascending order */ if (! x->r_table->routes || re->metric <= x->r_table->routes->metric){ re->next = x->r_table->routes; x->r_table->routes = re; }else{ for(rei=x->r_table->routes;rei;rei=rei->next) if (!rei->next){ rei->next = re; break; }else{ if (re->metric <= rei->next->metric){ re->next = rei->next; rei->next = re; break; } } } } } else if (xmlStrlen(child->name)==5 && ((char*)strncasecmp((char*)child->name,"Realm",5)==0)){ if (!x->r_table) { x->r_table = shm_malloc(sizeof(routing_table)); memset(x->r_table,0,sizeof(routing_table)); } rr = new_routing_realm(); if (rr){ xc = xmlGetProp(child,(xmlChar*)"name"); quote_trim_dup(&(rr->realm),(char*)xc); if (!x->r_table->realms) { x->r_table->realms = rr; }else{ for(rri=x->r_table->realms;rri->next;rri=rri->next); rri->next = rr; } for(nephew = child->children; nephew; nephew = nephew->next) if (nephew->type == XML_ELEMENT_NODE){ if (xmlStrlen(nephew->name)==5 && ((char*)strncasecmp((char*)nephew->name,"Route",5)==0)) { re = new_routing_entry(); if (re) { xc = xmlGetProp(nephew,(xmlChar*)"FQDN"); if (xc){ quote_trim_dup(&(re->fqdn),(char*)xc); xmlFree(xc); } xc = xmlGetProp(nephew,(xmlChar*)"metric"); if (xc){ re->metric = atoi((char*)xc); xmlFree(xc); } /* add it the list in ascending order */ if (! rr->routes || re->metric <= rr->routes->metric){ re->next = rr->routes; rr->routes = re; }else{ for(rei=rr->routes;rei;rei=rei->next) if (!rei->next){ rei->next = re; break; }else{ if (re->metric <= rei->next->metric){ re->next = rei->next; rei->next = re; break; } } } } } } } } } if (doc) xmlFreeDoc(doc); parser_destroy(); return x; error: if (doc) xmlFreeDoc(doc); parser_destroy(); if (x) free_dp_config(x); return 0; }
/** * Receive Loop for Diameter messages. * Decodes the message and calls receive_message(). * @param sock - the socket to receive from * @returns when the socket is closed */ void receive_loop(int sock) { char buf[hdr_len],*msg; int buf_len,length,version,cnt,msg_len; AAAMessage *dmsg; while(!*shutdownx){ buf_len=0; while(buf_len<1){ cnt = select_recv(sock,buf+buf_len,1,0); if (cnt<0) goto error; buf_len+=cnt; } version = (unsigned char)buf[0]; if (version!=1) { LOG(L_ERR,"ERROR:receive_loop():[%d] Recv Unknown version [%d]\n",sock,(unsigned char)buf[0]); continue; } while(buf_len<hdr_len){ cnt = select_recv(sock,buf+buf_len,hdr_len-buf_len,0); if (cnt<0) goto error; buf_len+=cnt; } length = get_3bytes(buf+1); if (length>DP_MAX_MSG_LENGTH){ LOG(L_ERR,"ERROR:receive_loop():[%d] Msg too big [%d] bytes\n",sock,length); goto error; } LOG(L_DBG,"DBG:receive_loop():[%d] Recv Version %d Length %d\n",sock,version,length); msg = shm_malloc(length); if (!msg) { LOG_NO_MEM("shm",length); goto error; } memcpy(msg,buf,hdr_len); msg_len=hdr_len; while(msg_len<length){ cnt = select_recv(sock,msg+msg_len,length-msg_len,0); if (cnt<0) { shm_free(msg); goto error; } msg_len+=cnt; } LOG(L_DBG,"DBG:receive_loop():[%d] Recv message complete\n",sock); dmsg = AAATranslateMessage((unsigned char*)msg,(unsigned int)msg_len,1); /*shm_free(msg);*/ if (dmsg) receive_message(dmsg,sock); else{ shm_free(msg); } } error: if (this_peer) { if (this_peer->I_sock == sock) sm_process(this_peer,I_Peer_Disc,0,0,sock); if (this_peer->R_sock == sock) sm_process(this_peer,R_Peer_Disc,0,0,sock); } LOG(L_ERR,"INFO:receive_loop():[%d] Client closed connection or error... BYE\n",sock); }
/** * Real initialization, called after the config is parsed */ int diameter_peer_init_real() { pid_list_t *i,*j; if (!config) { LM_ERR("diameter_peer_init_real(): Configuration was not parsed yet. Aborting...\n"); goto error; } log_dp_config(config); dp_first_pid = shm_malloc(sizeof(pid_t)); if (!dp_first_pid){ LOG_NO_MEM("shm",sizeof(pid_t)); goto error; } *dp_first_pid = getpid(); shutdownx = shm_malloc(sizeof(int)); if (!shutdownx){ LOG_NO_MEM("shm",sizeof(int)); goto error; } *shutdownx = 0; shutdownx_lock = lock_alloc(); if (!shutdownx_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } shutdownx_lock = lock_init(shutdownx_lock); handlers_lock = lock_alloc(); if (!handlers_lock){ LOG_NO_MEM("shm",sizeof(gen_lock_t)); goto error; } handlers_lock = lock_init(handlers_lock); handlers = shm_malloc(sizeof(handler_list)); if (!handlers){ LOG_NO_MEM("shm",sizeof(handler_list)); goto error; } handlers->head=0; handlers->tail=0; /* init the pid list */ pid_list = shm_malloc(sizeof(pid_list_head_t)); if (!pid_list){ LOG_NO_MEM("shm",sizeof(pid_list_head_t)); goto error; } bzero(pid_list,sizeof(pid_list_head_t)); pid_list_lock = lock_alloc(); pid_list_lock = lock_init(pid_list_lock); /* init shared mem pointers before forking */ timer_cdp_init(); worker_init(); /* init the peer manager */ peer_manager_init(config); /* init diameter transactions */ cdp_trans_init(); /* init the session */ if (!cdp_sessions_init(config->sessions_hash_size)) goto error; /* add callback for messages - used to implement the API */ cb_add(api_callback,0); return 1; error: if (shutdownx) shm_free(shutdownx); if (config) free_dp_config(config); i = pid_list->head; while(i){ j = i->next; shm_free(i); i = j; } shm_free(pid_list); lock_get(pid_list_lock); lock_destroy(pid_list_lock); lock_dealloc((void*)pid_list_lock); return 0; }