int update_subscriber(impurecord_t* urec, reg_subscriber** _reg_subscriber, int *expires, int *local_cseq, int *version) { subs_t subs; unsigned int hash_code = 0; reg_subscriber *rs = *_reg_subscriber; if (expires) { rs->expires = *expires; } else { LM_DBG("No expires so will not update subscriber expires.\n"); } if (local_cseq) { rs->local_cseq = *local_cseq; } else { LM_DBG("No local cseq so will not update subscriber local cseq.\n"); } if (version) { rs->version = *version; } else { LM_DBG("No version so will not update subscriber version.\n"); } /*This lets us get presentity URI info for subsequent SUBSCRIBEs that don't have presentity URI as req URI*/ get_act_time(); subs.pres_uri = rs->presentity_uri; subs.from_tag = rs->from_tag; subs.to_tag = rs->to_tag; subs.callid = rs->call_id; subs.expires = rs->expires - act_time; subs.contact = rs->watcher_contact; hash_code = core_hash(&subs.callid, &subs.to_tag, sub_dialog_hash_size); LM_DBG("Updating sub dialog hash info with call_id: <%.*s> and ttag <%.*s> amd ftag <%.*s> and hash code <%d>", subs.callid.len, subs.callid.s, subs.to_tag.len, subs.to_tag.s, subs.from_tag.len, subs.from_tag.s, hash_code); if (pres_update_shtable(sub_dialog_table, hash_code, &subs, REMOTE_TYPE)) { LM_ERR("while updating new subscription\n"); return 0; } /*DB?*/ if (db_mode == WRITE_THROUGH && db_insert_subscriber(urec, rs) != 0) { LM_ERR("Failed to insert subscriber into DB subscriber [%.*s] to IMPU [%.*s]...continuing but db will be out of sync!\n", rs->presentity_uri.len, rs->presentity_uri.s, urec->public_identity.len, urec->public_identity.s); } return 1; }
int get_hash_index_and_shared_line(struct sip_msg* msg, unsigned int *hash_index, str **shared_line) { if(shared_line_spec_param.s) { memset(&shared_line_tok, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, &shared_line_spec, &shared_line_tok) < 0) { LM_ERR("Failed to get shared_line value\n"); return -1; } //LM_DBG("got shared_line_spec_param flags [%d]\n", shared_line_tok.flags); if(!(shared_line_tok.flags&PV_VAL_INT) && (shared_line_tok.flags&PV_VAL_STR)) { *shared_line = &shared_line_tok.rs; *hash_index = core_hash(&shared_line_tok.rs, NULL, b2b_sca_hsize); //LM_DBG("got hash_index=[%d] for PV_SPEC user [%.*s]\n", *hash_index, // shared_line_tok.rs.len, shared_line_tok.rs.s); return 0; } else { LM_ERR("No shared line PV [%.*s] defined\n", shared_line_spec_param.len, shared_line_spec_param.s); return -1; } } else { LM_ERR("No shared line PV defined\n"); return -1; } /* If the shared_line_spec_param is not set, use the username from original RURI */ /* parse_orig_ruri(msg); if (msg->parsed_orig_ruri_ok && msg->parsed_orig_ruri.user.s && msg->parsed_orig_ruri.user.len) { *shared_line = &msg->parsed_orig_ruri.user; *hash_index = core_hash(&msg->parsed_orig_ruri.user, NULL, b2b_sca_hsize); //LM_DBG("got hash_index=[%d] for RURI user [%.*s]\n", *hash_index, // msg->parsed_orig_ruri.user.len, msg->parsed_orig_ruri.user.s); return 0; } else { LM_ERR("msg->parsed_orig_ruri_ok is NULL\n"); } */ return -1; }
int dbt_release_table(dbt_cache_p _dc, const str *_s) { int hash; int hashidx; if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0) return -1; hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE); hashidx = hash % DBT_CACHETBL_SIZE; lock_release(&_dbt_cachetbl[hashidx].sem); return 0; }
pres_entry_t* insert_phtable(str* pres_uri, int event, str* etag, char* sphere, int init_turn) { unsigned int hash_code; pres_entry_t* p= NULL; int size; size= sizeof(pres_entry_t)+ pres_uri->len; p= (pres_entry_t*)shm_malloc(size); if(p== NULL) { ERR_MEM(SHARE_MEM); } memset(p, 0, size); size= sizeof(pres_entry_t); p->pres_uri.s= (char*)p+ size; memcpy(p->pres_uri.s, pres_uri->s, pres_uri->len); p->pres_uri.len= pres_uri->len; if(sphere) { p->sphere= (char*)shm_malloc(strlen(sphere)+ 1); if(p->sphere== NULL) { ERR_MEM(SHARE_MEM); } strcpy(p->sphere, sphere); } p->event= event; update_pres_etag(p, etag); hash_code= core_hash(pres_uri, NULL, phtable_size); lock_get(&pres_htable[hash_code].lock); p->next= pres_htable[hash_code].entries->next; pres_htable[hash_code].entries->next= p; p->last_turn = init_turn; lock_release(&pres_htable[hash_code].lock); return p; error: if(p) shm_free(p); return NULL; }
int release_dynamic_lock(struct sip_msg *msg, char *string) { str ret; int hash; if (fixup_get_svalue(msg, (gparam_p)string, &ret) != 0) { LM_ERR("Get string from fixup param failed!\n"); return -1; } hash = (int)core_hash(&ret, NULL, lock_pool_size); lock_set_release(dynamic_locks, hash); LM_DBG("Released dynamic lock----- %d\n", hash); return 1; }
int lcache_htable_insert(cachedb_con *con,str* attr, str* value, int expires) { lcache_entry_t* me, *it; int hash_code; int size; struct timeval start; size= sizeof(lcache_entry_t) + attr->len + value->len; me = (lcache_entry_t*)shm_malloc(size); if(me == NULL) { LM_ERR("no more shared memory\n"); return -1; } memset(me, 0, size); start_expire_timer(start,local_exec_threshold); me->attr.s = (char*)me + (sizeof(lcache_entry_t)); memcpy(me->attr.s, attr->s, attr->len); me->attr.len = attr->len; me->value.s = (char*)me + (sizeof(lcache_entry_t)) + attr->len; memcpy(me->value.s, value->s, value->len); me->value.len = value->len; if( expires != 0) me->expires = get_ticks() + expires; hash_code= core_hash( attr, 0, cache_htable_size); lock_get(&cache_htable[hash_code].lock); it = cache_htable[hash_code].entries; /* if a previous record for the same attr delete it */ lcache_htable_remove_safe( *attr, &it); me->next = it; cache_htable[hash_code].entries = me; lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local insert",attr->s,attr->len,0); return 1; }
int delete_phtable_query(str *pres_uri, int event, str* etag) { pres_entry_t* p; unsigned int hash_code; hash_code = core_hash(pres_uri, 0, phtable_size); lock_get(&pres_htable[hash_code].lock); p = search_phtable_etag(pres_uri, event, etag, hash_code); if(p == NULL) { LM_ERR("Record not found [%.*s]\n", etag->len, etag->s); lock_release(&pres_htable[hash_code].lock); return -1; } delete_phtable(p, hash_code); lock_release(&pres_htable[hash_code].lock); return 0; }
/*! * \brief Helper function that outputs a dialog via the RPC interface * \see rpc_print_dlgs * \param rpc RPC node that should be filled * \param c RPC void pointer * \param with_context if 1 then the dialog context will be also printed */ static void internal_rpc_print_single_dlg(rpc_t *rpc, void *c, int with_context) { str callid, from_tag; dlg_entry_t *d_entry; dlg_cell_t *dlg; unsigned int h_entry; if (rpc->scan(c, ".S.S", &callid, &from_tag) < 2) return; h_entry = core_hash( &callid, 0, d_table->size); d_entry = &(d_table->entries[h_entry]); dlg_lock( d_table, d_entry); for( dlg = d_entry->first ; dlg ; dlg = dlg->next ) { if (match_downstream_dialog( dlg, &callid, &from_tag)==1) { internal_rpc_print_dlg(rpc, c, dlg, with_context); } } dlg_unlock( d_table, d_entry); }
int delete_phtable(str* pres_uri, int event) { unsigned int hash_code; pres_entry_t* p= NULL, *prev_p= NULL; hash_code= core_hash(pres_uri, NULL, phtable_size); lock_get(&pres_htable[hash_code].lock); p= search_phtable(pres_uri, event, hash_code); if(p== NULL) { LM_DBG("record not found\n"); lock_release(&pres_htable[hash_code].lock); return 0; } p->publ_count--; if(p->publ_count== 0) { /* delete record */ prev_p= pres_htable[hash_code].entries; while(prev_p->next) { if(prev_p->next== p) break; prev_p= prev_p->next; } if(prev_p->next== NULL) { LM_ERR("record not found\n"); lock_release(&pres_htable[hash_code].lock); return -1; } prev_p->next= p->next; if(p->sphere) shm_free(p->sphere); shm_free(p); } lock_release(&pres_htable[hash_code].lock); return 0; }
int lcache_htable_remove(cachedb_con *con,str* attr) { int hash_code; struct timeval start; start_expire_timer(start,local_exec_threshold); hash_code= core_hash( attr, 0, cache_htable_size); lock_get(&cache_htable[hash_code].lock); lcache_htable_remove_safe( *attr, &cache_htable[hash_code].entries); lock_release(&cache_htable[hash_code].lock); stop_expire_timer(start,local_exec_threshold, "cachedb_local remove",attr->s,attr->len,0); return 0; }
unsigned long insert_htable(ua_pres_t* presentity) { unsigned int hash_code; str* s1; unsigned long pres_id; ua_pres_t* p; if(presentity->to_uri.s) s1 = &presentity->to_uri; else s1 = presentity->pres_uri; LM_DBG("to_uri= %.*s, watcher_uri= %.*s\n", s1->len, s1->s, (presentity->watcher_uri?presentity->watcher_uri->len:0), (presentity->watcher_uri?presentity->watcher_uri->s:0)); hash_code= core_hash(s1, presentity->watcher_uri, HASH_SIZE); presentity->hash_index = hash_code; LM_DBG("hash_code = %d\n", hash_code); lock_get(&HashT->p_records[hash_code].lock); p= HashT->p_records[hash_code].entity; presentity->db_flag= INSERTDB_FLAG; presentity->next= p->next; if(p->next) { presentity->local_index = p->next->local_index + 1; } else presentity->local_index = 0; p->next= presentity; pres_id = PRES_HASH_ID(presentity); lock_release(&HashT->p_records[hash_code].lock); return pres_id; }
int dbt_db_del_table(dbt_cache_p _dc, const str *_s, int sync) { dbt_table_p _tbc = NULL; int hash; int hashidx; if(!_dbt_cachetbl || !_dc || !_s || !_s->s || _s->len<=0) return -1; hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE); hashidx = hash % DBT_CACHETBL_SIZE; if(sync) lock_get(&_dbt_cachetbl[hashidx].sem); _tbc = _dbt_cachetbl[hashidx].dtp; while(_tbc) { if(_tbc->hash==hash && _tbc->dbname.len == _dc->name.len && _tbc->name.len == _s->len && !strncasecmp(_tbc->dbname.s, _dc->name.s, _dc->name.len) && !strncasecmp(_tbc->name.s, _s->s, _s->len)) { if(_tbc->prev) (_tbc->prev)->next = _tbc->next; else _dbt_cachetbl[hashidx].dtp = _tbc->next; if(_tbc->next) (_tbc->next)->prev = _tbc->prev; break; } _tbc = _tbc->next; } if(sync) lock_release(&_dbt_cachetbl[hashidx].sem); dbt_table_free(_tbc); return 0; }
/* * Obtain a urecord pointer if the urecord exists in the table */ int get_ts_urecord(str* ruri, struct ts_urecord** _r) { int sl, i, rurihash; ts_urecord_t* r; rurihash = core_hash(ruri, 0, 0); sl = rurihash&(t_table->size-1); r = t_table->entries[sl].first; for(i = 0; r!=NULL && i < t_table->entries[sl].n; i++) { if((r->rurihash==rurihash) && (r->ruri.len==ruri->len) && !memcmp(r->ruri.s,ruri->s,ruri->len)){ *_r = r; return 0; } r = r->next; } return 1; /* Nothing found */ }
int get_pcontact(udomain_t* _d, str* _contact, struct pcontact** _c) { unsigned int sl, i, aorhash; struct pcontact* c; /* search in cache */ aorhash = core_hash(_contact, 0, 0); sl = aorhash & (_d->size - 1); c = _d->table[sl].first; for (i = 0; i < _d->table[sl].n; i++) { if ((c->aorhash == aorhash) && (c->aor.len == _contact->len) && !memcmp(c->aor.s, _contact->s, _contact->len)) { *_c = c; return 0; } c = c->next; } return 1; /* Nothing found */ }
/*! * \brief Obtain a impurecord pointer if the impurecord exists in domain * \param _d domain to search the record * \param _aor address of record * \param _r new created record * \return 0 if a record was found, 1 if nothing could be found */ int get_impurecord(udomain_t* _d, str* public_identity, struct impurecord** _r) { unsigned int sl, i, aorhash; impurecord_t* r; /* search in cache */ aorhash = core_hash(public_identity, 0, 0); sl = aorhash & (_d->size - 1); r = _d->table[sl].first; for (i = 0; i < _d->table[sl].n; i++) { if ((r->aorhash == aorhash) && (r->public_identity.len == public_identity->len) && !memcmp(r->public_identity.s, public_identity->s, public_identity->len)) { *_r = r; return 0; } r = r->next; } return 1; /* Nothing found */ }
int convert_temporary_dialog(ua_pres_t *dialog) { ua_pres_t *temp_dialog; unsigned int hash_code; hash_code= core_hash(dialog->pres_uri,dialog->watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); temp_dialog = get_temporary_dialog(dialog, hash_code); if (temp_dialog) delete_htable(temp_dialog, hash_code); else return -1; insert_htable(dialog, hash_code); lock_release(&HashT->p_records[hash_code].lock); return 1; }
/* Treat Notify reply callback */ void notif_cback_func(struct cell *t, int cb_type, struct tmcb_params *params){ int code = params->code; struct sm_subscriber* params_notify = (struct sm_subscriber*)(*params->param); unsigned int hash_code; LM_DBG("TREAT NOTIFY REPLY \n"); LM_DBG("CODE: %d \n ", code); // verify if response is OK if (code >= 200 && code < 300){ // response OK(2XX) if (params_notify->expires > 0){ LM_DBG("REPLY OK timeout %d \n", params_notify->timeout); LM_DBG("REPLY OK expires %d \n", params_notify->expires); time_t rawtime; time(&rawtime); int time_now = (int)rawtime; LM_DBG("TIME : %d \n", (int)rawtime ); // update timeout params_notify->timeout = params_notify->expires + time_now; LM_DBG("TIMEOUT_NOTIFY: %d \n ", params_notify->timeout); return; } if (params_notify->dlg_id->status == TERMINATED){ // delete subs_htable hash_code= core_hash(¶ms_notify->call_dlg_id->callid, 0, subst_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); LM_DBG("********************************************CALLID_STR%.*s\n", params_notify->call_dlg_id->callid.len, params_notify->call_dlg_id->callid.s); delete_shtable(subs_htable, hash_code, params_notify); } }else{ // Response NOK LM_ERR("reply to NOTIFY NOK\n"); } return; }
/*! * \brief Create and initialize new record structure * \param ruri request uri * \param _r pointer to the new record * \return 0 on success, negative on failure */ int new_ts_urecord(str* ruri, ts_urecord_t** _r) { *_r = (ts_urecord_t*)shm_malloc(sizeof(ts_urecord_t)); if (*_r == 0) { LM_ERR("no more share memory\n"); return -1; } memset(*_r, 0, sizeof(ts_urecord_t)); (*_r)->ruri.s = (char*)shm_malloc(ruri->len); if ((*_r)->ruri.s == 0) { LM_ERR("no more share memory\n"); shm_free(*_r); *_r = 0; return -2; } memcpy((*_r)->ruri.s, ruri->s, ruri->len); (*_r)->ruri.len = ruri->len; (*_r)->rurihash = core_hash(ruri, 0, 0); return 0; }
int get_dynamic_lock(struct sip_msg *msg, char *string) { str ret; int hash; if (((gparam_p)string)->type == GPARAM_TYPE_STR) { LM_INFO("Static string given! get_static_lock() function is better!\n"); } if (fixup_get_svalue(msg, (gparam_p)string, &ret) != 0) { LM_ERR("Get string from fixup param failed!\n"); return -1; } hash = (int)core_hash(&ret, NULL, lock_pool_size); LM_DBG("Getting dynamic lock----- %d\n", hash); lock_set_get(dynamic_locks, hash); LM_DBG("Got dynamic lock----- %d\n", hash); return 1; }
int is_dialog(ua_pres_t* dialog) { int ret_code= 0; unsigned int hash_code; str* s1; if(dialog->to_uri.s) s1 = &dialog->to_uri; else s1 = dialog->pres_uri; hash_code= core_hash(s1, dialog->watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); if(get_dialog(dialog, hash_code)== NULL) ret_code= -1; else ret_code= 0; lock_release(&HashT->p_records[hash_code].lock); return ret_code; }
/** * @brief Get a subscription from the subscription list based on the IMPI * NB - does not return with a lock on the subscription but does increment ref count * @param impu string of impu to search for * @param s ims_subscription to be returned if found * @param leave_slot_locked if no subscription is found return with the slot locked (in case we want to add) * @return 0 on success */ int get_subscription(str* impi_s, ims_subscription** s, int leave_slot_locked) { int subscription_hash, sl; ims_subscription* ptr; subscription_hash = core_hash(impi_s, 0, 0); sl = subscription_hash & (subs_hash_size - 1); lock_subscription_slot(sl); ptr = ims_subscription_list->slot[sl].first; while (ptr) { if ((impi_s->len == ptr->private_identity.len) && (memcmp(impi_s->s, ptr->private_identity.s, impi_s->len) == 0)) { LM_DBG("found an existing subscription for IMPI [%.*s]\n", impi_s->len, impi_s->s); (*s) = ptr; lock_subscription(ptr); ref_subscription_unsafe(ptr); unlock_subscription(ptr); unlock_subscription_slot(sl); return 0; } ptr = ptr->next; } if (!leave_slot_locked) unlock_subscription_slot(sl); return 1; }
int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c) { int i; ppublic_t* ppublic_ptr; int is_default = 1; struct sip_uri sip_uri; *_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t)); if (*_c == 0) { LM_ERR("no more shared memory\n"); return -1; } memset(*_c, 0, sizeof(pcontact_t)); LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n", _contact->len, _contact->s, _ci->num_public_ids, reg_state_to_string(_ci->reg_state)); (*_c)->aor.s = (char*) shm_malloc(_contact->len); if ((*_c)->aor.s == 0) { LM_ERR("no more shared memory\n"); shm_free(*_c); *_c = 0; return -2; } memcpy((*_c)->aor.s, _contact->s, _contact->len); (*_c)->aor.len = _contact->len; (*_c)->domain = (str*)_d; if (parse_uri((*_c)->aor.s, (*_c)->aor.len, &sip_uri) != 0) { LM_ERR("unable to determine contact host from uri [%.*s\n", (*_c)->aor.len, (*_c)->aor.s); shm_free((*_c)->aor.s); shm_free(*_c); *_c = 0; return -2; } (*_c)->contact_host.s = sip_uri.host.s; (*_c)->contact_host.len = sip_uri.host.len; (*_c)->contact_port = sip_uri.port_no; (*_c)->contact_user.s = sip_uri.user.s; (*_c)->contact_user.len = sip_uri.user.len; if (hashing_type==0) { (*_c)->aorhash = core_hash(_contact, 0, 0); } else { (*_c)->aorhash = core_hash(&(*_c)->contact_host, 0, 0); } (*_c)->expires = _ci->expires; (*_c)->reg_state = _ci->reg_state; // Add received Info: if (_ci->received_host.len > 0 && _ci->received_host.s) { (*_c)->received_host.s = (char*) shm_malloc(_ci->received_host.len); if ((*_c)->received_host.s == 0) { LM_ERR("no more share memory\n"); shm_free((*_c)->aor.s); shm_free(*_c); *_c = 0; return -2; } memcpy((*_c)->received_host.s, _ci->received_host.s, _ci->received_host.len); (*_c)->received_host.len = _ci->received_host.len; (*_c)->received_port = _ci->received_port; (*_c)->received_proto = _ci->received_proto; } //setup public ids for (i=0; i<_ci->num_public_ids; i++) { if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default) if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) { LM_ERR("unable to create new ppublic\n"); } else { insert_ppublic(*_c, ppublic_ptr); } } //add the service routes if (_ci->num_service_routes > 0) { (*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str)); if (!(*_c)->service_routes) { LM_ERR("no more shm mem\n"); goto out_of_memory; } else { for (i = 0; i < _ci->num_service_routes; i++) { STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact"); } (*_c)->num_service_routes = _ci->num_service_routes; } } return 0; out_of_memory: return -1; }
int send_subscribe(subs_info_t* subs) { ua_pres_t* presentity= NULL; str met= {"SUBSCRIBE", 9}; str* str_hdr= NULL; int ret= -1; unsigned int hash_code=0; ua_pres_t* hentity= NULL; int expires; int flag; int result; uac_req_t uac_r; db1_res_t *res=NULL; ua_pres_t dbpres; str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0}; dlg_t* td= NULL; memset(&dbpres, 0, sizeof(dbpres)); dbpres.pres_uri = &pres_uri; dbpres.watcher_uri = &watcher_uri; dbpres.extra_headers = &extra_headers; print_subs(subs); flag= subs->source_flag; if(subs->source_flag & XMPP_INITIAL_SUBS) subs->source_flag= XMPP_SUBSCRIBE; if(subs->expires< 0) expires= 3600; else expires= subs->expires; str_hdr= subs_build_hdr(subs->contact, expires, subs->event, subs->extra_headers); if(str_hdr== NULL || str_hdr->s== NULL) { LM_ERR("while building extra headers\n"); return -1; } if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } /* generation of hash and getting lock moved from here to further down */ if (dbmode==PUA_DB_ONLY) { presentity = get_dialog_puadb(subs->id, subs->pres_uri, &dbpres, &res); } else { ua_pres_t pres; memset(&pres, 0, sizeof(ua_pres_t)); pres.pres_uri = subs->pres_uri; pres.watcher_uri = subs->watcher_uri; pres.flag = subs->source_flag; pres.id = subs->id; pres.event = subs->event; if (subs->remote_target) pres.remote_contact = *subs->remote_target; hash_code=core_hash(subs->pres_uri, subs->watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); presentity= search_htable(&pres, hash_code); } /* if flag == INSERT_TYPE insert no matter what the search result is */ if(subs->flag & INSERT_TYPE) { LM_DBG("A subscription request with insert type\n"); goto insert; } if(presentity== NULL ) { int size; insert: if (subs->expires == 0) { /* Don't create a new dialog when expires == 0 */ if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto done; } if(subs->flag & UPDATE_TYPE) { LM_DBG("request for a subscription with update type" " and no record found\n"); subs->flag= INSERT_TYPE; } hentity= subscribe_cbparam(subs, REQ_OTHER); if(hentity== NULL) { LM_ERR("while building callback" " param\n"); if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } hentity->flag= flag; set_uac_req(&uac_r, &met, str_hdr, 0, 0, TMCB_LOCAL_COMPLETED, subs_cback_func, (void*)hentity); result= tmb.t_request_outside (&uac_r, /* Type of the message */ subs->remote_target?subs->remote_target:subs->pres_uri,/* Request-URI*/ subs->pres_uri, /* To */ subs->watcher_uri, /* From */ subs->outbound_proxy /* Outbound_proxy */ ); if(result< 0) { LM_ERR("while sending request with t_request\n"); if (uac_r.dialog != NULL) { uac_r.dialog->rem_target.s = 0; uac_r.dialog->dst_uri.s = 0; tmb.free_dlg(uac_r.dialog); uac_r.dialog = 0; } shm_free(hentity); if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); /* Although this is an error must not return -1 as the calling function must continue processing. */ ret = 0; goto error; } /* Now create a temporary hash table entry. This is needed to deal with the race-hazard when NOTIFYs arrive before the 2xx response to the SUBSCRIBE. */ size = sizeof(ua_pres_t)+ 2 * sizeof(str) + ( subs->pres_uri->len + subs->watcher_uri->len + uac_r.dialog->id.loc_tag.len + uac_r.dialog->id.call_id.len + subs->id.len) * sizeof(char); presentity= (ua_pres_t*)shm_malloc(size); if(presentity== NULL) { LM_ERR("no more share memory\n"); if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } memset(presentity, 0, size); size= sizeof(ua_pres_t); presentity->pres_uri = (str *) ((char *) presentity + size); size += sizeof(str); presentity->pres_uri->s= (char *) presentity + size; memcpy(presentity->pres_uri->s, subs->pres_uri->s, subs->pres_uri->len); presentity->pres_uri->len= subs->pres_uri->len; size+= subs->pres_uri->len; presentity->watcher_uri= (str *) ((char *) presentity + size); size += sizeof(str); presentity->watcher_uri->s= (char *) presentity + size; memcpy(presentity->watcher_uri->s, subs->watcher_uri->s, subs->watcher_uri->len); presentity->watcher_uri->len = subs->watcher_uri->len; size += subs->watcher_uri->len; presentity->call_id.s = (char *) presentity + size; memcpy(presentity->call_id.s, uac_r.dialog->id.call_id.s, uac_r.dialog->id.call_id.len); presentity->call_id.len = uac_r.dialog->id.call_id.len; size += uac_r.dialog->id.call_id.len; presentity->from_tag.s = (char *) presentity + size; memcpy(presentity->from_tag.s, uac_r.dialog->id.loc_tag.s, uac_r.dialog->id.loc_tag.len); presentity->from_tag.len= uac_r.dialog->id.loc_tag.len; size += uac_r.dialog->id.loc_tag.len; presentity->id.s = (char *) presentity+ size; memcpy(presentity->id.s, subs->id.s, subs->id.len); presentity->id.len = subs->id.len; size += subs->id.len; presentity->event = subs->event; presentity->flag = subs->source_flag; presentity->cseq = uac_r.dialog->loc_seq.value; /* Set the temporary record expiry for 2 * 64T1 seconds from now */ presentity->expires= (int)time(NULL) + 64; presentity->desired_expires= presentity->expires; if (dbmode==PUA_DB_ONLY) { insert_dialog_puadb(presentity); shm_free(presentity); } else { insert_htable(presentity, hash_code); lock_release(&HashT->p_records[hash_code].lock); } uac_r.dialog->rem_target.s = 0; uac_r.dialog->dst_uri.s = 0; tmb.free_dlg(uac_r.dialog); uac_r.dialog = 0; } else { if (subs->internal_update_flag == INTERNAL_UPDATE_TRUE) { LM_INFO("attempting to re-SUBSCRIBE on internal (rls_update_subs()) update - skipping\n"); if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto done; } if (presentity->to_tag.len == 0) { if (subs->expires > 0) LM_WARN("attempting to re-SUBSCRIBE to a temporary (non-established) dialog - skipping\n"); else { LM_WARN("attempting to un-SUBSCRIBE from a temporary (non-established) dialog - skipping and deleting dialog\n"); if (dbmode==PUA_DB_ONLY) delete_dialog_puadb(presentity); else delete_htable(presentity, hash_code); } if (dbmode != PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto done; } td= pua_build_dlg_t(presentity); if(td== NULL) { LM_ERR("while building tm dlg_t structure"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } hentity= subs_cbparam_indlg(presentity, expires, REQ_OTHER); if(hentity== NULL) { LM_ERR("while building callback param\n"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); LM_DBG("event parameter: %d\n", hentity->event); set_uac_req(&uac_r, &met, str_hdr, 0, td, TMCB_LOCAL_COMPLETED, subs_cback_func, (void*)hentity); result= tmb.t_request_within(&uac_r); if(result< 0) { shm_free(hentity); hentity= NULL; LM_ERR("while sending request with t_request\n"); goto error; } } done: if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } ret = 0; error: pua_free_tm_dlg(td); pkg_free(str_hdr); free_results_puadb(res); if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction) { if (pua_dbf.abort_transaction(pua_db) < 0) LM_ERR("in abort_transaction\n"); } return ret; }
void subs_cback_func(struct cell *t, int cb_type, struct tmcb_params *ps) { struct sip_msg* msg= NULL; int lexpire= 0; unsigned int cseq; ua_pres_t* presentity= NULL, *hentity= NULL; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; int size= 0; unsigned int hash_code; int flag ; str record_route= {0, 0}; int rt; str contact; int initial_request = 0; int end_transaction = 1; if( ps->param== NULL || *ps->param== NULL ) { LM_ERR("null callback parameter\n"); return; } if (dbmode == PUA_DB_ONLY && pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } LM_DBG("completed with status %d\n",ps->code) ; hentity= (ua_pres_t*)(*ps->param); hash_code= core_hash(hentity->pres_uri,hentity->watcher_uri, HASH_SIZE); flag= hentity->flag; if(hentity->flag & XMPP_INITIAL_SUBS) hentity->flag= XMPP_SUBSCRIBE; /* get dialog information from reply message: callid, to_tag, from_tag */ msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n "); goto error; } if(msg== FAKED_REPLY) { struct hdr_field *callid = NULL, *from = NULL; struct to_body FROM = {0}; callid = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (callid == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(callid, 0, sizeof(struct hdr_field)); get_hdr_field(t->callid.s, t->callid.s + t->callid.len, callid); hentity->call_id = callid->body; from = (struct hdr_field *) pkg_malloc(sizeof(struct hdr_field)); if (from == NULL) { LM_ERR("Out of memory\n"); goto faked_error; } memset(from, 0, sizeof(struct hdr_field)); get_hdr_field(t->from.s, t->from.s + t->from.len, from); parse_to(from->body.s, from->body.s + from->body.len + 1, &FROM); if(FROM.uri.len <= 0) { LM_ERR("'From' header NOT parsed\n"); goto faked_error; } hentity->call_id = callid->body; hentity->from_tag = (&FROM)->tag_value; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); faked_error: if (callid) pkg_free(callid); free_to_params(&FROM); if (from) pkg_free(from); goto done; } if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); goto error; } if(ps->rpl->expires && msg->expires->body.len > 0) { if (!msg->expires->parsed && (parse_expires(msg->expires) < 0)) { LM_ERR("cannot parse Expires header\n"); goto error; } lexpire = ((exp_body_t*)msg->expires->parsed)->val; LM_DBG("lexpire= %d\n", lexpire); } /*if initial request */ if(hentity->call_id.s== NULL) { initial_request = 1; if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); goto error; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); goto error; } } pfrom = (struct to_body*)msg->from->parsed; if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } hentity->call_id= msg->callid->body; hentity->from_tag= pfrom->tag_value; if(ps->code >= 300 || lexpire == 0) { hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); goto done; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); goto error; } if(msg->to->parsed != NULL) { pto = (struct to_body*)msg->to->parsed; LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s); } else { parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO); if(TO.uri.len <= 0) { LM_ERR("'To' header NOT parsed\n"); goto error; } pto = &TO; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no to tag value present\n"); goto error; } hentity->to_tag= pto->tag_value; } if(ps->code >= 300 ) { /* if an error code and a stored dialog delete it and try to send a subscription with type= INSERT_TYPE, else return*/ subs_info_t subs; hentity->to_tag.s = NULL; hentity->to_tag.len = 0; find_and_delete_dialog(hentity, hash_code); if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } end_transaction = 0; /* Redirect if the response 3XX */ memset(&subs, 0, sizeof(subs_info_t)); subs.pres_uri= hentity->pres_uri; subs.watcher_uri= hentity->watcher_uri; subs.contact= &hentity->contact; if(hentity->remote_contact.s) subs.remote_target= &hentity->remote_contact; if(hentity->desired_expires== 0) subs.expires= -1; else if(hentity->desired_expires< (int)time(NULL)) subs.expires= 0; else subs.expires= hentity->desired_expires- (int)time(NULL)+ 3; subs.flag= INSERT_TYPE; subs.source_flag= flag; subs.event= hentity->event; subs.id= hentity->id; subs.outbound_proxy= hentity->outbound_proxy; subs.extra_headers= hentity->extra_headers; subs.cb_param= hentity->cb_param; if(send_subscribe(&subs)< 0) { LM_ERR("when trying to send SUBSCRIBE\n"); goto error; } goto done; } if(lexpire== 0 ) { LM_DBG("lexpire= 0 Delete from hash table"); find_and_delete_dialog(hentity, hash_code); goto done; } /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found"); goto error; } if( parse_contact(msg->contact) <0 ) { LM_ERR(" cannot parse contact header\n"); goto error; } if(msg->contact->parsed == NULL) { LM_ERR("cannot parse contact header\n"); goto error; } contact = ((contact_body_t* )msg->contact->parsed)->contacts->uri; if( msg->cseq==NULL || msg->cseq->body.s==NULL) { LM_ERR("cannot parse cseq header\n"); goto error; } if( str2int( &(get_cseq(msg)->number), &cseq)< 0) { LM_ERR("while converting str to int\n"); goto error; } if(initial_request == 0) { hentity->cseq = cseq; find_and_update_dialog(hentity, hash_code, lexpire, &contact); goto done; } /*process record route and add it to a string*/ if (msg->record_route!=NULL) { rt = print_rr_body(msg->record_route, &record_route, 1, 0); if(rt != 0) { LM_ERR("parsing record route [%d]\n", rt); record_route.s=NULL; record_route.len=0; } } size= sizeof(ua_pres_t)+ 2*sizeof(str)+( pto->uri.len+ pfrom->uri.len+ pto->tag_value.len+ pfrom->tag_value.len +msg->callid->body.len+ record_route.len+ hentity->contact.len+ hentity->id.len )*sizeof(char); if(hentity->extra_headers) size+= sizeof(str)+ hentity->extra_headers->len*sizeof(char); presentity= (ua_pres_t*)shm_malloc(size); if(presentity== NULL) { LM_ERR("no more share memory\n"); goto error; } memset(presentity, 0, size); size= sizeof(ua_pres_t); presentity->pres_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->pres_uri->s= (char*)presentity+ size; memcpy(presentity->pres_uri->s, pto->uri.s, pto->uri.len); presentity->pres_uri->len= pto->uri.len; size+= pto->uri.len; presentity->watcher_uri= (str*)( (char*)presentity+ size); size+= sizeof(str); presentity->watcher_uri->s= (char*)presentity+ size; memcpy(presentity->watcher_uri->s, pfrom->uri.s, pfrom->uri.len); presentity->watcher_uri->len= pfrom->uri.len; size+= pfrom->uri.len; presentity->call_id.s= (char*)presentity + size; memcpy(presentity->call_id.s,msg->callid->body.s, msg->callid->body.len); presentity->call_id.len= msg->callid->body.len; size+= presentity->call_id.len; presentity->to_tag.s= (char*)presentity + size; memcpy(presentity->to_tag.s,pto->tag_value.s, pto->tag_value.len); presentity->to_tag.len= pto->tag_value.len; size+= pto->tag_value.len; presentity->from_tag.s= (char*)presentity + size; memcpy(presentity->from_tag.s,pfrom->tag_value.s, pfrom->tag_value.len); presentity->from_tag.len= pfrom->tag_value.len; size+= pfrom->tag_value.len; if(record_route.len && record_route.s) { presentity->record_route.s= (char*)presentity + size; memcpy(presentity->record_route.s, record_route.s, record_route.len); presentity->record_route.len= record_route.len; size+= record_route.len; pkg_free(record_route.s); record_route.s = NULL; } presentity->contact.s= (char*)presentity + size; memcpy(presentity->contact.s, hentity->contact.s, hentity->contact.len); presentity->contact.len= hentity->contact.len; size+= hentity->contact.len; if(hentity->id.s) { presentity->id.s=(char*)presentity+ size; memcpy(presentity->id.s, hentity->id.s, hentity->id.len); presentity->id.len= hentity->id.len; size+= presentity->id.len; } if(hentity->extra_headers) { presentity->extra_headers= (str*)((char*)presentity+ size); size+= sizeof(str); presentity->extra_headers->s=(char*)presentity+ size; memcpy(presentity->extra_headers->s, hentity->extra_headers->s, hentity->extra_headers->len); presentity->extra_headers->len= hentity->extra_headers->len; size+= hentity->extra_headers->len; } /* write the remote contact filed */ presentity->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(presentity->remote_contact.s==NULL) { ERR_MEM(SHARE_MEM); } memcpy(presentity->remote_contact.s, contact.s, contact.len); presentity->remote_contact.len= contact.len; presentity->event|= hentity->event; presentity->flag= hentity->flag; presentity->etag.s= NULL; presentity->cseq= cseq; presentity->desired_expires= hentity->desired_expires; presentity->expires= lexpire+ (int)time(NULL); if(BLA_SUBSCRIBE & presentity->flag) { LM_DBG("BLA_SUBSCRIBE FLAG inserted\n"); } LM_DBG("record for subscribe from %.*s to %.*s inserted in datatbase\n", presentity->watcher_uri->len, presentity->watcher_uri->s, presentity->pres_uri->len, presentity->pres_uri->s); if (dbmode==PUA_DB_ONLY) { if (pua_dbf.end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } if (pua_dbf.start_transaction) { if (pua_dbf.start_transaction(pua_db, db_table_lock) < 0) { LM_ERR("in start_transaction\n"); goto error; } } if (convert_temporary_dialog_puadb(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } else { if (convert_temporary_dialog(presentity) < 0) { LM_ERR("Could not convert temporary dialog into a dialog\n"); goto error; } } done: if(hentity->ua_flag == REQ_OTHER) { hentity->flag= flag; run_pua_callbacks( hentity, msg); } if (dbmode == PUA_DB_ONLY && pua_dbf.end_transaction && end_transaction) { if (pua_dbf.end_transaction(pua_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } goto end; error: if (presentity) { if (presentity->remote_contact.s) shm_free(presentity->remote_contact.s); shm_free(presentity); } if(record_route.s) pkg_free(record_route.s); if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction) { if (pua_dbf.abort_transaction(pua_db) < 0) LM_ERR("in abort_transaction\n"); } end: if(hentity) { shm_free(hentity); hentity= NULL; } free_to_params(&TO); return; }
str* client_new(client_info_t* ci,b2b_notify_t b2b_cback, b2b_add_dlginfo_t add_dlginfo, str* param) { int result; b2b_dlg_t* dlg; unsigned int hash_index; str* callid = NULL; int size; str ehdr = {0, 0}; str* b2b_key_shm = NULL; dlg_t td; str from_tag; str random_info = {0, 0}; if(ci == NULL || b2b_cback == NULL || param== NULL) { LM_ERR("Wrong parameters.\n"); return NULL; } if(param && param->len > B2BL_MAX_KEY_LEN) { LM_ERR("parameter too long, received [%d], maximum [%d]\n", param->len, B2BL_MAX_KEY_LEN); return 0; } hash_index = core_hash(&ci->from_uri, &ci->to_uri, client_hsize); if(ci->from_tag) from_tag = *ci->from_tag; else generate_tag(&from_tag, &ci->from_uri, ci->extra_headers); /* create a dummy b2b dialog structure to be inserted in the hash table*/ size = sizeof(b2b_dlg_t) + ci->to_uri.len + ci->from_uri.len + ci->from_dname.len + ci->to_dname.len + from_tag.len + ci->local_contact.len + B2B_MAX_KEY_SIZE + B2BL_MAX_KEY_LEN; /* create record in hash table */ dlg = (b2b_dlg_t*)shm_malloc(size); if(dlg == NULL) { LM_ERR("No more shared memory\n"); return 0; } memset(dlg, 0, size); size = sizeof(b2b_dlg_t); CONT_COPY(dlg, dlg->from_uri, ci->from_uri); CONT_COPY(dlg, dlg->to_uri, ci->to_uri); if(ci->to_dname.s) CONT_COPY(dlg, dlg->to_dname, ci->to_dname); if(ci->from_dname.s) CONT_COPY(dlg, dlg->from_dname, ci->from_dname); CONT_COPY(dlg, dlg->tag[CALLER_LEG], from_tag); CONT_COPY(dlg, dlg->contact[CALLER_LEG], ci->local_contact); if(param && param->s) { dlg->param.s = (char*)dlg + size; memcpy(dlg->param.s, param->s, param->len); dlg->param.len = param->len; size+= B2BL_MAX_KEY_LEN; } dlg->b2b_cback = b2b_cback; dlg->add_dlginfo = add_dlginfo; if(parse_method(ci->method.s, ci->method.s+ci->method.len, &dlg->last_method)< 0) { LM_ERR("wrong method %.*s\n", ci->method.len, ci->method.s); shm_free(dlg); goto error; } dlg->state = B2B_NEW; dlg->cseq[CALLER_LEG] =(ci->cseq?ci->cseq:1); dlg->send_sock = ci->send_sock; /* if the callid should be the same in more instances running at the same time (replication)*/ if(!replication_mode) { srand(get_uticks()); random_info.s = int2str(rand(), &random_info.len); } dlg->send_sock = ci->send_sock; dlg->id = core_hash(&from_tag, random_info.s?&random_info:0, HASH_SIZE); /* callid must have the special format */ dlg->db_flag = NO_UPDATEDB_FLAG; callid = b2b_htable_insert(client_htable, dlg, hash_index, B2B_CLIENT, 0); if(callid == NULL) { LM_ERR("Inserting new record in hash table failed\n"); shm_free(dlg); goto error; } if(b2breq_complete_ehdr(ci->extra_headers, &ehdr, ci->body, &ci->local_contact)< 0) { LM_ERR("Failed to complete extra headers\n"); goto error; } /* copy the key in shared memory to transmit it as a parameter to the tm callback */ b2b_key_shm = b2b_key_copy_shm(callid); if(b2b_key_shm== NULL) { LM_ERR("no more shared memory\n"); goto error; } CONT_COPY(dlg, dlg->callid, (*callid)); /* create the tm dialog structure with the a costum callid */ memset(&td, 0, sizeof(dlg_t)); td.loc_seq.value = dlg->cseq[CALLER_LEG]; dlg->last_invite_cseq = dlg->cseq[CALLER_LEG]; td.loc_seq.is_set = 1; td.id.call_id = *callid; td.id.loc_tag = from_tag; td.id.rem_tag.s = 0; td.id.rem_tag.len = 0; td.rem_uri = ci->to_uri; if(ci->req_uri.s) td.rem_target = ci->req_uri; else td.rem_target = ci->to_uri; if(td.rem_target.s[0] == '<') { td.rem_target.s++; td.rem_target.len-=2; } td.rem_dname = ci->to_dname; td.loc_uri = ci->from_uri; td.loc_dname = ci->from_dname; td.state= DLG_CONFIRMED; td.T_flags=T_NO_AUTOACK_FLAG|T_PASS_PROVISIONAL_FLAG ; td.send_sock = ci->send_sock; if(ci->dst_uri.len) td.obp = ci->dst_uri; td.avps = ci->avps; tmb.setlocalTholder(&dlg->uac_tran); /* send request */ result= tmb.t_request_within (&ci->method, /* method*/ &ehdr, /* extra headers*/ ci->body, /* body*/ &td, /* dialog structure*/ b2b_client_tm_cback, /* callback function*/ b2b_key_shm, shm_free_param); /* function to release the parameter*/ if(td.route_set) pkg_free(td.route_set); if(result< 0) { LM_ERR("while sending request with t_request\n"); pkg_free(callid); shm_free(b2b_key_shm); return NULL; } tmb.setlocalTholder(NULL); LM_DBG("new client entity [%p] callid=[%.*s] tag=[%.*s] param=[%.*s]" " last method=[%d] dlg->uac_tran=[%p]\n", dlg, callid->len, callid->s, dlg->tag[CALLER_LEG].len, dlg->tag[CALLER_LEG].s, dlg->param.len, dlg->param.s, dlg->last_method, dlg->uac_tran); return callid; error: if(callid) pkg_free(callid); return NULL; }
static int load_sca_info_from_db(void) { db_res_t * res = NULL; db_val_t * values; db_row_t * rows; int i, j, nr_rows; unsigned int valid_record; unsigned int n_result_cols = 0; unsigned int shared_line_col, watchers_col; unsigned int app_shared_entity_col[MAX_APPEARANCE_INDEX]; unsigned int app_call_state_col[MAX_APPEARANCE_INDEX]; unsigned int app_call_info_uri_col[MAX_APPEARANCE_INDEX]; unsigned int app_call_info_appearance_uri_col[MAX_APPEARANCE_INDEX]; unsigned int app_b2bl_key_col[MAX_APPEARANCE_INDEX]; db_key_t q_cols[SCA_TABLE_TOTAL_COL_NO]; str shared_line, watchers_csv; //str_lst_t *watchers; //unsigned int size, watcher_size, watchers_no; //unsigned int size; unsigned int hash_index; //char *p; b2b_sca_record_t *record; b2b_sca_call_t *call; unsigned int shared_entity, appearance_index, call_state; str call_info_uri, call_info_apperance_uri, b2bl_key; b2bl_cb_ctx_t *cb_params; if(use_sca_table()) return -1; q_cols[shared_line_col = n_result_cols++] = &shared_line_column; q_cols[watchers_col = n_result_cols++] = &watchers_column; for (i=0; i<MAX_APPEARANCE_INDEX; i++) { q_cols[app_shared_entity_col[i] = n_result_cols++] = &app_shared_entity_column[i]; q_cols[app_call_state_col[i] = n_result_cols++] = &app_call_state_column[i]; q_cols[app_call_info_uri_col[i] = n_result_cols++] = &app_call_info_uri_column[i]; q_cols[app_call_info_appearance_uri_col[i] = n_result_cols++] = &app_call_info_appearance_uri_column[i]; q_cols[app_b2bl_key_col[i] = n_result_cols++] = &app_b2bl_key_column[i]; } /* select the whole tabel and all the columns */ if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) { if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0, SCA_TABLE_TOTAL_COL_NO, 0, 0) < 0) { LM_ERR("Error while querying (fetch) database\n"); return -1; } if(sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0){ LM_ERR("fetching rows failed\n"); return -1; } } else { if(sca_dbf.query(sca_db_handle, 0, 0, 0, q_cols, 0, SCA_TABLE_TOTAL_COL_NO, 0, &res) < 0) { LM_ERR("Error while querying database\n"); return -1; } } nr_rows = RES_ROW_N(res); do { LM_DBG("loading [%i] records from db\n", nr_rows); rows = RES_ROWS(res); /* for every row/record */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values+shared_line_col) || VAL_NULL(values+watchers_col)) { LM_ERR("columns [%.*s] or/and [%.*s] cannot be null -> skipping\n", shared_line_column.len, shared_line_column.s, watchers_column.len, watchers_column.s); continue; } shared_line.s = (char*)values[shared_line_col].val.string_val; shared_line.len = strlen(shared_line.s); watchers_csv.s = (char*)values[watchers_col].val.string_val; watchers_csv.len = strlen(watchers_csv.s); record = restore_record(&shared_line, &watchers_csv); if (record == NULL) goto error; hash_index = core_hash(&shared_line, NULL, b2b_sca_hsize); j = 0; while (j < MAX_APPEARANCE_INDEX) { if( VAL_NULL(values + app_shared_entity_col[j]) || VAL_NULL(values + app_call_state_col[j]) || VAL_NULL(values + app_call_info_uri_col[j]) || VAL_NULL(values + app_call_info_appearance_uri_col[j]) || VAL_NULL(values + app_b2bl_key_col[j]) ) { goto cont; } appearance_index = j + 1; /* 1 - get shared_entity */ shared_entity = values[app_shared_entity_col[j]].val.int_val; if (shared_entity!=0 && shared_entity!=1) { LM_ERR("Unexpected shared_entity [%d] " "for shared_line [%.*s]\n", shared_entity, shared_line.len, shared_line.s); goto cont; } /* 2 - get call_state */ call_state = values[app_call_state_col[j]].val.int_val; if (call_state == IDLE_STATE) { LM_DBG("empty call[%d]\n", appearance_index); goto cont; } if (call_state > MAX_INDEX_STATE) { LM_ERR("Unexpected call_state [%d] for shared_line [%.*s]\n", call_state, shared_line.len, shared_line.s); goto cont; } /* 3 - get call_info_uri */ call_info_uri.s = (char*)values[app_call_info_uri_col[j]].val.string_val; if (call_info_uri.s) call_info_uri.len = strlen(call_info_uri.s); else { LM_ERR("Missing call_info_uri for shared_line [%.*s][%d]\n", shared_line.len, shared_line.s, appearance_index); goto cont; } LM_DBG("call_info_uri=[%.*s]\n", call_info_uri.len, call_info_uri.s); /* 4 - get call_info_apperance_uri */ call_info_apperance_uri.s = (char*) values[app_call_info_appearance_uri_col[j]].val.string_val; if (call_info_apperance_uri.s) call_info_apperance_uri.len = strlen(call_info_apperance_uri.s); else { LM_ERR("Missing call_info_apperance_uri for " "shared_line [%.*s][%d]\n", shared_line.len, shared_line.s, appearance_index); goto cont; } LM_DBG("call_info_apperance_uri=[%.*s]\n", call_info_apperance_uri.len, call_info_apperance_uri.s); /* 5 - get b2bl_key */ b2bl_key.s = (char*)values[app_b2bl_key_col[j]].val.string_val; if (b2bl_key.s) { b2bl_key.len = strlen(b2bl_key.s); if (b2bl_key.len > B2BL_MAX_KEY_LEN) { LM_ERR("buffer overflow on b2bl_key [%.*s]" " for shared_line [%.*s][%d]\n", b2bl_key.len, b2bl_key.s, shared_line.len, shared_line.s, appearance_index); goto cont; } LM_DBG("b2bl_key=[%.*s]\n", b2bl_key.len, b2bl_key.s); } else { LM_ERR("Missing b2bl_key for shared_line [%.*s][1]\n", shared_line.len, shared_line.s); goto cont; } /* restore the call */ call = restore_call(record, appearance_index, shared_entity, call_state, &call_info_uri, &call_info_apperance_uri); if (call == NULL) { goto error; } /* update record */ if (0!=b2b_sca_update_call_record_key(call, &b2bl_key)) { LM_ERR("Unable to update b2bl_key [%.*s]\n", b2bl_key.len, b2bl_key.s); shm_free(call); call = NULL; record->call[appearance_index-1] = NULL; goto cont; } /* Prepare b2b_logic callback params. */ cb_params = build_cb_params(hash_index, &shared_line, appearance_index); if (cb_params == NULL) { LM_ERR("Unable to build cb_params\n"); goto error; } /* re-register callbacks */ if(b2bl_api.register_cb(&b2bl_key, &sca_logic_notify, cb_params, B2B_RE_INVITE_CB|B2B_CONFIRMED_CB|B2B_DESTROY_CB) != 0){ LM_ERR("Unable register b2b cb\n"); shm_free(call); call = NULL; record->call[appearance_index-1] = NULL; goto cont; } cont: j++; } valid_record = j = 0; while (j < MAX_APPEARANCE_INDEX) { if (record->call[j]) { valid_record = 1; goto check_valid_record; } j++; } check_valid_record: if (valid_record) { b2b_sca_print_record(record); insert_record(hash_index, record); } else { LM_DBG("removing the record from db!\n"); delete_sca_info_from_db(record); } LM_DBG("Done\n"); } /* any more data to be fetched ?*/ if (DB_CAPABILITY(sca_dbf, DB_CAP_FETCH)) { if (sca_dbf.fetch_result(sca_db_handle, &res, SCA_FETCH_SIZE)<0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); sca_dbf.free_result(sca_db_handle, res); return 0; error: sca_dbf.free_result(sca_db_handle, res); return -1; }
/* Treat Notify to Subscriber Dialog in scenario III*/ int treat_notify(struct sip_msg *msg) { int resp = 1; struct sm_subscriber* cell_subs; int expires= 0; char *subs_state, *subs_expires; str callid_orig; str from_tag; struct notify_body* notify_body = NULL; time_t rawtime; int time_now; int version; char *version_init, *version_end, *version_aux; int size_version; unsigned int hash_code; str callid_event; static str msg200={"OK Notify",sizeof("OK Notify")-1}; static str msg481={"Subscription does not exist",sizeof("Subscription does not exist")-1}; static str msg489={"Bad Event",sizeof("Bad Event")-1}; static str msg400={"Bad Request",sizeof("Bad Request")-1}; if(!check_event_header(msg)){ LM_ERR("event header type not allow\n"); if(!eme_tm.t_reply(msg,489,&msg489)){ LM_ERR("t_reply (489)\n"); } return 0; } if ( parse_headers(msg,HDR_EOH_F, 0) == -1 ){ LM_ERR("error in parsing headers\n"); return 0; } // get callid from Notify if( msg->callid==NULL || msg->callid->body.s==NULL){ LM_ERR("reply without callid header\n"); return 0; } callid_event = msg->callid->body; LM_DBG("CALLID: %.*s \n ", callid_event.len, callid_event.s ); /* look for cell in list linked subs_pt with same dialog Id*/ cell_subs = get_subs_cell(msg, callid_event); if(cell_subs == NULL){ if(!eme_tm.t_reply(msg,481,&msg481)){ LM_ERR("t_reply (481)\n"); } return 0; } LM_DBG("STATUS: %d \n ", cell_subs->dlg_id->status); LM_DBG("TIMEOUT NOTIFY: %d \n ", cell_subs->timeout); /* get in Subscription_state header: state and expire */ if(!get_subscription_state_header(msg, &subs_state, &subs_expires)){ LM_ERR("invalid body of Subscription_state header\n"); if(!eme_tm.t_reply(msg,400,&msg400)){ LM_ERR("t_reply (400)\n"); } return 0; } LM_DBG("STATE: %s\n ", subs_state); LM_DBG("SUBS_EXPIRES: %s\n ", subs_expires); time(&rawtime); time_now = (int)rawtime; /* analise state value*/ if (strcmp(subs_state, "active") == 0){ cell_subs->dlg_id->status = ACTIVE; cell_subs->expires = atoi(subs_expires); cell_subs->timeout = cell_subs->expires + time_now; }else{ if (strcmp(subs_state, "pending") == 0){ cell_subs->dlg_id->status = PENDING ; cell_subs->expires = atoi(subs_expires); cell_subs->timeout = TIMER_N + time_now; }else{ if(strcmp(subs_state, "terminated") == 0){ /* state is terminated indicate that subcriber dialog finish then pull cell of the list linked and send esct to VPC*/ LM_DBG(" --- CLEAR CELL \n"); callid_orig = cell_subs->call_dlg_id->callid; from_tag = cell_subs->call_dlg_id->local_tag; LM_DBG(" --- CALLID_ORIG %.*s \n", callid_orig.len, callid_orig.s); LM_DBG(" --- FROM_TAG_ORIG %.*s \n", from_tag.len, from_tag.s); if(send_esct(msg, callid_orig, from_tag) == 0){ LM_ERR("error in send to esct\n"); } hash_code= core_hash(&callid_event, 0, subst_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); delete_shtable(subs_htable, hash_code, cell_subs); /* Reply OK to Notify*/ if(!eme_tm.t_reply(msg,200,&msg200)){ LM_ERR("t_reply (200)\n"); return 0; } return 1; }else{ LM_ERR("INCOMPATIBLE RECEIVED STATUS\n"); if(!eme_tm.t_reply(msg,400,&msg400)){ LM_ERR("t_reply (400)\n"); } return 0; } } } LM_DBG("STATUS: %d \n ", cell_subs->dlg_id->status); LM_DBG(" --- NOTIFY BODY %s", msg->eoh); notify_body = parse_notify(msg->eoh); if( notify_body == NULL){ LM_ERR("invalid body in Notify request\n"); if(!eme_tm.t_reply(msg,400,&msg400)){ LM_ERR("t_reply (400)\n"); } resp = 0; goto end; } version_init = strchr(notify_body->params->version,'\"'); version_init++; version_end = strchr(version_init,'\"'); size_version = version_end - version_init; version_aux = pkg_malloc(size_version + 1); if (version_aux == NULL) { LM_ERR("no more pkg memory\n"); return 0; } memcpy(version_aux, version_init, size_version ); version_aux[size_version] = '\0'; version = atoi(version_aux); pkg_free(version_aux); LM_DBG(" --- STATE %s", notify_body->state); LM_DBG(" --- VERSION %d", version); /* Reply OK to Notify*/ if(!eme_tm.t_reply(msg,200,&msg200)){ LM_DBG("t_reply (200)\n"); free_parsed_notify(notify_body); resp = 0; goto end; } if(cell_subs->version >= version){ LM_ERR(" --- ERRO IN VERSION PARAMETER IN NOTIFY BODY"); free_parsed_notify(notify_body); resp = 0; goto end; }else{ cell_subs->version = version; } /* if Notify body state has terminated value, which indicates that emergency call finish, then send subscribe with expire=0 to terminate the subscriber dialog*/ if(strcmp(notify_body->state, "terminated") == 0){ expires = 0; LM_DBG(" --- STATE %s", notify_body->state); if(send_subscriber_within(msg, cell_subs, expires) == -1){ LM_ERR(" --- Error in send subscriber terminated \n"); } } resp = 1; free_parsed_notify(notify_body); end: pkg_free(subs_state); pkg_free(subs_expires); return resp; }
/* look for subscriber cell using callid and to_tag of Notify*/ struct sm_subscriber* get_subs_cell(struct sip_msg *msg, str callid_event) { str callid; str method; struct to_body *pto= NULL, *pfrom = NULL; struct sm_subscriber* s; unsigned int hash_code; method.s = msg->first_line.u.request.method.s; method.len = msg->first_line.u.request.method.len; if ( parse_headers(msg,HDR_EOH_F, 0) == -1 ){ LM_ERR("error in parsing headers\n"); return NULL; } // get callid from Notify if( msg->callid==NULL || msg->callid->body.s==NULL){ LM_ERR("reply without callid header\n"); return NULL; } callid = msg->callid->body; LM_DBG("CALLID: %.*s \n ", callid.len, callid.s ); if (msg->from->parsed == NULL){ if ( parse_from_header( msg )<0 ){ LM_ERR("reply without From header\n"); return NULL; } } //get From header from Notify pfrom = get_from(msg); LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s ); if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){ LM_ERR("reply without tag value \n"); return NULL; } if( msg->to==NULL || msg->to->body.s==NULL){ LM_ERR("error in parse TO header\n"); return NULL; } // get To header from Notify pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); return NULL; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0){ LM_ERR("reply without tag value \n"); } LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s ); LM_DBG("PTO_TAG: %.*s \n ", pto->tag_value.len, pto->tag_value.s ); LM_DBG("********************************************CALLID_STR%.*s\n", callid_event.len, callid_event.s); hash_code= core_hash(&callid_event, 0, subst_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); s= search_shtable(subs_htable, &callid, &pfrom->tag_value, hash_code, &method); if (s == NULL) { LM_ERR(" ---FAILURE SUB_CELL NOT FOUND IN SHTABLE\n"); } return s; }
/*Create cell to control Subscriber Dialog States This cell save this information: - Dialog Id: .Callid .rem_tag .local_tag - expires - Local_uri - Remote_uri - Notifier_uri - INVITE's Callid - Event body - State */ int create_subscriber_cell(struct sip_msg* reply, struct parms_cb* params_cb){ str* callid = NULL; int expires= 0; struct to_body *pto= NULL, *pfrom = NULL; int size_subs_cell; int vsp_addr_len; char *vsp_addr = "@vsp.com"; time_t rawtime; int time_now; struct sm_subscriber *subs_cell = NULL; char *p; unsigned int hash_code; callid= (str*) pkg_malloc (sizeof (str)); if (callid == NULL) { LM_ERR("--------------------------------------------------no more pkg memory\n"); return 0; } /*Verify repĺy is OK and get callid and expires from response*/ if ( !extract_reply_headers(reply, callid, expires)){ LM_ERR("fail in extract headers\n"); pkg_free(callid); return 0; } /*get From header fields */ pfrom = get_from(reply); LM_DBG("PFROM: %.*s \n ", pfrom->uri.len, pfrom->uri.s ); if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0){ LM_ERR("reply without tag value \n"); pkg_free(callid); return 0; } /*get To header fields */ pto = get_to(reply); LM_DBG("PTO: %.*s \n ", pto->uri.len, pto->uri.s ); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("failed to parse TO header\n"); pkg_free(callid); return 0; } // get source ip address that send INVITE vsp_addr = ip_addr2a(&reply->rcv.src_ip); vsp_addr_len = strlen(vsp_addr); time(&rawtime); time_now = (int)rawtime; LM_DBG("TIME : %d \n", (int)rawtime ); /* build subscriber cell */ size_subs_cell = sizeof (struct sm_subscriber) + (2 * sizeof(struct dialog_id)) + callid->len + pfrom->tag_value.len + pto->tag_value.len + pfrom->uri.len + pto->uri.len + params_cb->callid_ori.len + params_cb->event.len + params_cb->from_tag.len + vsp_addr_len + 9 ; subs_cell = pkg_malloc(size_subs_cell + 1); if (!subs_cell) { LM_ERR("no more shm\n"); return 0; } memset(subs_cell, 0, size_subs_cell + 1); subs_cell->expires = expires; subs_cell->timeout = TIMER_N + time_now; LM_DBG("SUBS_TIMEOUT: %d \n ", subs_cell->timeout ); subs_cell->version = -1; subs_cell->dlg_id = (struct dialog_id*)(subs_cell + 1); subs_cell->dlg_id->callid.len = callid->len; subs_cell->dlg_id->callid.s = (char *) (subs_cell->dlg_id + 1); memcpy(subs_cell->dlg_id->callid.s, callid->s, callid->len); LM_DBG("SUBS_CALLID: %.*s \n ", subs_cell->dlg_id->callid.len, subs_cell->dlg_id->callid.s ); subs_cell->dlg_id->local_tag.len = pfrom->tag_value.len; subs_cell->dlg_id->local_tag.s = (char *) (subs_cell->dlg_id + 1) + callid->len; memcpy(subs_cell->dlg_id->local_tag.s, pfrom->tag_value.s, pfrom->tag_value.len); LM_DBG("SUBS_FROM_TAG: %.*s \n ", subs_cell->dlg_id->local_tag.len, subs_cell->dlg_id->local_tag.s ); subs_cell->dlg_id->rem_tag.len = pto->tag_value.len; subs_cell->dlg_id->rem_tag.s = (char *) (subs_cell->dlg_id + 1) + callid->len + pfrom->tag_value.len; memcpy(subs_cell->dlg_id->rem_tag.s, pto->tag_value.s, pto->tag_value.len); LM_DBG("SUBS_TO_TAG: %.*s \n ", subs_cell->dlg_id->rem_tag.len, subs_cell->dlg_id->rem_tag.s ); p = (char *)(subs_cell->dlg_id + 1) + callid->len + pfrom->tag_value.len + pto->tag_value.len; subs_cell->call_dlg_id = (struct dialog_id*)p; subs_cell->call_dlg_id->callid.len= params_cb->callid_ori.len; subs_cell->call_dlg_id->callid.s = (char *) (subs_cell->call_dlg_id + 1); memcpy(subs_cell->call_dlg_id->callid.s, params_cb->callid_ori.s, params_cb->callid_ori.len); LM_DBG("SUBS_CALLID_ORI: %.*s \n ", subs_cell->call_dlg_id->callid.len, subs_cell->call_dlg_id->callid.s ); subs_cell->call_dlg_id->local_tag.len= params_cb->from_tag.len; subs_cell->call_dlg_id->local_tag.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len; memcpy(subs_cell->call_dlg_id->local_tag.s, params_cb->from_tag.s, params_cb->from_tag.len); LM_DBG("SUBS_FROMTAG_event: %.*s \n ", subs_cell->call_dlg_id->local_tag.len, subs_cell->call_dlg_id->local_tag.s ); subs_cell->loc_uri.len = pfrom->uri.len; subs_cell->loc_uri.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len; memcpy(subs_cell->loc_uri.s,pfrom->uri.s,pfrom->uri.len); LM_DBG("SUBS_LOC_URI: %.*s \n ", subs_cell->loc_uri.len, subs_cell->loc_uri.s ); subs_cell->rem_uri.len= pto->uri.len; subs_cell->rem_uri.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len; memcpy(subs_cell->rem_uri.s, pto->uri.s, pto->uri.len); LM_DBG("SUBS_REM_URI: %.*s \n ", subs_cell->rem_uri.len, subs_cell->rem_uri.s ); subs_cell->event.len= params_cb->event.len; subs_cell->event.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len + pto->uri.len; memcpy(subs_cell->event.s, params_cb->event.s, params_cb->event.len); LM_DBG("SUBS_EVENT: %.*s \n ", subs_cell->event.len, subs_cell->event.s ); subs_cell->contact.len = vsp_addr_len + 9; subs_cell->contact.s = (char *) (subs_cell->call_dlg_id + 1) + params_cb->callid_ori.len + params_cb->from_tag.len + pfrom->uri.len + pto->uri.len + params_cb->event.len; memcpy(subs_cell->contact.s, "sip:test@", 9); memcpy(subs_cell->contact.s + 9, vsp_addr, vsp_addr_len); LM_DBG("SUBS_CONTACT: %.*s \n ", subs_cell->contact.len, subs_cell->contact.s ); subs_cell->dlg_id->status = NOTIFY_WAIT; hash_code= core_hash(&subs_cell->dlg_id->callid, 0, subst_size); LM_DBG("********************************************HASH_CODE%d\n", hash_code); if(insert_shtable(subs_htable, hash_code,subs_cell) == NULL){ LM_ERR("inserting new record in subs_htable\n"); } pkg_free(subs_cell); pkg_free(callid); return 1; }
void unlock_contact_slot(str* contact_uri) { unsigned int sl; sl = core_hash(contact_uri, 0, contact_list->size); unlock_contact_slot_i(sl); }