/* Register a new hook callback */ int fd_hook_register ( uint32_t type_mask, void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata), void *regdata, struct fd_hook_data_hdl *data_hdl, struct fd_hook_hdl ** handler ) { struct fd_hook_hdl * newhdl = NULL; int i; TRACE_ENTRY("%x %p %p %p %p", type_mask, fd_hook_cb, regdata, data_hdl, handler); CHECK_PARAMS( fd_hook_cb && handler ); CHECK_MALLOC( newhdl = malloc(sizeof(struct fd_hook_hdl)) ); memset(newhdl, 0, sizeof(struct fd_hook_hdl)); newhdl->fd_hook_cb = fd_hook_cb; newhdl->regdata = regdata; newhdl->data_hdl = data_hdl; for (i=0; i <= HOOK_LAST; i++) { fd_list_init(&newhdl->chain[i], newhdl); if (type_mask & (1<<i)) { CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); fd_list_insert_before( &HS_array[i].sentinel, &newhdl->chain[i]); CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); } } *handler = newhdl; return 0; }
/* Get a slot in the array */ int fd_hook_data_register( size_t permsgdata_size, void (*permsgdata_init_cb) (struct fd_hook_permsgdata *), void (*permsgdata_fini_cb) (struct fd_hook_permsgdata *), struct fd_hook_data_hdl **new_handle) { int ret = ENOSPC, idx; TRACE_ENTRY("%zd %p %p %p", permsgdata_size, permsgdata_init_cb, permsgdata_fini_cb, new_handle); CHECK_PARAMS( permsgdata_size && new_handle ); CHECK_POSIX( pthread_mutex_lock(&HDH_lock) ); if (max_index < FD_HOOK_HANDLE_LIMIT) { idx = max_index++; ret = 0; } CHECK_POSIX( pthread_mutex_unlock(&HDH_lock) ); if (ret == 0) { HDH_array[idx].pmd_size = permsgdata_size; HDH_array[idx].pmd_init_cb = permsgdata_init_cb; HDH_array[idx].pmd_fini_cb = permsgdata_fini_cb; *new_handle = &HDH_array[idx]; } return ret; }
/* The callback called on new messages */ static int rtereg_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates) { struct msg * msg = *pmsg; struct avp * avp = NULL; TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); CHECK_PARAMS(msg && candidates); /* Check if it is worth processing the message */ if (FD_IS_LIST_EMPTY(candidates)) { return 0; } /* Now search the AVP in the message */ CHECK_FCT( fd_msg_search_avp ( msg, rtereg_conf.avp, &avp ) ); if (avp != NULL) { struct avp_hdr * ahdr = NULL; CHECK_FCT( fd_msg_avp_hdr ( avp, &ahdr ) ); if (ahdr->avp_value != NULL) { #ifndef HAVE_REG_STARTEND int ret; /* Lock the buffer */ CHECK_POSIX( pthread_mutex_lock(&mtx) ); /* Augment the buffer if needed */ if (ahdr->avp_value->os.len >= bufsz) { CHECK_MALLOC_DO( buf = realloc(buf, ahdr->avp_value->os.len + 1), { pthread_mutex_unlock(&mtx); return ENOMEM; } );
/* Initialize the array of sentinels for the hooks */ int fd_hooks_init(void) { int i; for (i=0; i <= HOOK_LAST; i++) { fd_list_init(&HS_array[i].sentinel, NULL); CHECK_POSIX( pthread_rwlock_init(&HS_array[i].rwlock, NULL) ); } return 0; }
/* free this hook callback */ int fd_hook_unregister( struct fd_hook_hdl * handler ) { int i; TRACE_ENTRY("%p", handler); CHECK_PARAMS( handler ); for (i=0; i <= HOOK_LAST; i++) { if ( ! FD_IS_LIST_EMPTY(&handler->chain[i])) { CHECK_POSIX( pthread_rwlock_wrlock(&HS_array[i].rwlock) ); fd_list_unlink(&handler->chain[i]); CHECK_POSIX( pthread_rwlock_unlock(&HS_array[i].rwlock) ); } } free(handler); return 0; }
/* Alloc / reinit a peer structure. if *ptr is not NULL, it must already point to a valid struct fd_peer. */ int fd_peer_alloc(struct fd_peer ** ptr) { struct fd_peer *p; TRACE_ENTRY("%p", ptr); CHECK_PARAMS(ptr); if (*ptr) { p = *ptr; } else { CHECK_MALLOC( p = malloc(sizeof(struct fd_peer)) ); *ptr = p; } /* Now initialize the content */ memset(p, 0, sizeof(struct fd_peer)); fd_list_init(&p->p_hdr.chain, p); fd_list_init(&p->p_hdr.info.pi_endpoints, p); fd_list_init(&p->p_hdr.info.runtime.pir_apps, p); p->p_eyec = EYEC_PEER; CHECK_POSIX( pthread_mutex_init(&p->p_state_mtx, NULL) ); fd_list_init(&p->p_actives, p); fd_list_init(&p->p_expiry, p); CHECK_FCT( fd_fifo_new(&p->p_tosend, 5) ); CHECK_FCT( fd_fifo_new(&p->p_tofailover, 0) ); p->p_hbh = lrand48(); fd_list_init(&p->p_sr.srs, p); fd_list_init(&p->p_sr.exp, p); CHECK_POSIX( pthread_mutex_init(&p->p_sr.mtx, NULL) ); CHECK_POSIX( pthread_cond_init(&p->p_sr.cnd, NULL) ); fd_list_init(&p->p_connparams, p); return 0; }
/* Search for a peer */ int fd_peer_getbyid( DiamId_t diamid, size_t diamidlen, int igncase, struct peer_hdr ** peer ) { struct fd_list * li; TRACE_ENTRY("%p %zd %d %p", diamid, diamidlen, igncase, peer); CHECK_PARAMS( diamid && diamidlen && peer ); *peer = NULL; /* Search in the list */ CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) ); if (igncase) { for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { struct fd_peer * next = (struct fd_peer *)li; int cmp, cont; cmp = fd_os_almostcasesrch( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen, &cont ); if (cmp == 0) { *peer = &next->p_hdr; break; } if (!cont) break; } } else { for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { struct fd_peer * next = (struct fd_peer *)li; int cmp = fd_os_cmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen ); if (cmp > 0) continue; if (cmp == 0) *peer = &next->p_hdr; break; } } CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); return 0; }
// Remove a peer entry. int fd_peer_remove ( DiamId_t diamid, size_t diamidlen ) { struct fd_list * li; // Find the peer in the peer list from its pi_diamid. CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) ); for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { struct fd_peer * peer = (struct fd_peer *)li; int cmp = fd_os_cmp( diamid, diamidlen, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen ); if (cmp == 0) { /* update the peer lifetime, set the expiry flag and call fd_p_expi_update so that the * p_exp_timer value is updated and the peer expires immediately. */ peer->p_hdr.info.config.pic_flags.exp = PI_EXP_INACTIVE; peer->p_hdr.info.config.pic_lft = 0; CHECK_FCT( fd_p_expi_update(peer) ); break; } } CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); return 0; }
static int ta_conf_init(void) { ta_conf = &_conf; memset(ta_conf, 0, sizeof(struct ta_conf)); /* Set the default values */ ta_conf->vendor_id = 999999; /* Dummy value */ ta_conf->appli_id = 0xffffff; /* dummy value */ ta_conf->cmd_id = 0xfffffe; /* Experimental */ ta_conf->avp_id = 0xffffff; /* dummy value */ ta_conf->long_avp_len = 5000; ta_conf->mode = MODE_SERV | MODE_CLI; ta_conf->dest_realm = strdup(fd_g_config->cnf_diamrlm); ta_conf->dest_host = NULL; ta_conf->signal = TEST_APP_DEFAULT_SIGNAL; ta_conf->bench_concur = 100; ta_conf->bench_duration = 10; /* Initialize the mutex */ CHECK_POSIX( pthread_mutex_init(&ta_conf->stats_lock, NULL) ); return 0; }
/* Add a new peer entry */ int fd_peer_add ( struct peer_info * info, const char * orig_dbg, void (*cb)(struct peer_info *, void *), void * cb_data ) { struct fd_peer *p = NULL; struct fd_list * li, *li_inf; int ret = 0; TRACE_ENTRY("%p %p %p %p", info, orig_dbg, cb, cb_data); CHECK_PARAMS(info && info->pi_diamid); if (info->config.pic_realm) { if (!fd_os_is_valid_DiameterIdentity((os0_t)info->config.pic_realm, strlen(info->config.pic_realm))) { TRACE_DEBUG(INFO, "'%s' is not a valid DiameterIdentity.", info->config.pic_realm); return EINVAL; } } /* Create a structure to contain the new peer information */ CHECK_FCT( fd_peer_alloc(&p) ); /* Copy the informations from the parameters received */ p->p_hdr.info.pi_diamid = info->pi_diamid; CHECK_FCT( fd_os_validate_DiameterIdentity(&p->p_hdr.info.pi_diamid, &p->p_hdr.info.pi_diamidlen, 1) ); memcpy( &p->p_hdr.info.config, &info->config, sizeof(p->p_hdr.info.config) ); /* Duplicate the strings if provided */ if (info->config.pic_realm) { CHECK_MALLOC( p->p_hdr.info.config.pic_realm = strdup(info->config.pic_realm) ); } if (info->config.pic_priority) { CHECK_MALLOC( p->p_hdr.info.config.pic_priority = strdup(info->config.pic_priority) ); } /* Move the list of endpoints into the peer */ if (info->pi_endpoints.next) while (!FD_IS_LIST_EMPTY( &info->pi_endpoints ) ) { li = info->pi_endpoints.next; fd_list_unlink(li); fd_list_insert_before(&p->p_hdr.info.pi_endpoints, li); } /* The internal data */ if (orig_dbg) { CHECK_MALLOC( p->p_dbgorig = strdup(orig_dbg) ); } else { CHECK_MALLOC( p->p_dbgorig = strdup("unspecified") ); } p->p_cb = cb; p->p_cb_data = cb_data; /* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */ CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) ); li_inf = &fd_g_peers; for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { struct fd_peer * next = (struct fd_peer *)li; int cont; int cmp = fd_os_almostcasesrch( p->p_hdr.info.pi_diamid, p->p_hdr.info.pi_diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen, &cont ); if (cmp > 0) li_inf = li; /* it will come after this element, for sure */ if (cmp == 0) { ret = EEXIST; /* we have a duplicate */ break; } if (!cont) break; } /* We can insert the new peer object */ if (! ret) do { /* Update expiry list */ CHECK_FCT_DO( ret = fd_p_expi_update( p ), break ); /* Insert the new element in the list */ fd_list_insert_after( li_inf, &p->p_hdr.chain ); } while (0); CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) ); if (ret) { CHECK_FCT( fd_peer_free(&p) ); } else { CHECK_FCT( fd_psm_begin(p) ); } return ret; }
Condition::Condition() { CHECK_POSIX(::pthread_cond_init(&m_condition, 0)); }
void Condition::Wait() { CHECK_POSIX(::pthread_cond_wait(&m_condition, &m_mutex.m_mutex)); }
void Condition::SignalAll() { CHECK_POSIX(::pthread_cond_broadcast(&m_condition)); }
void Condition::Signal() { CHECK_POSIX(::pthread_cond_signal(&m_condition)); }
Condition::~Condition() { CHECK_POSIX(::pthread_cond_destroy(&m_condition)); }