static int update_pw_dialogs(subs_t* subs, unsigned int hash_code, subs_t** subs_array) { subs_t* s, *ps, *cs; int i= 0; LM_DBG("start\n"); if (subs_dbmode == DB_ONLY) return(update_pw_dialogs_dbonlymode(subs, subs_array)); lock_get(&subs_htable[hash_code].lock); ps= subs_htable[hash_code].entries; while(ps && ps->next) { s= ps->next; if(s->event== subs->event && s->pres_uri.len== subs->pres_uri.len && s->watcher_user.len== subs->watcher_user.len && s->watcher_domain.len==subs->watcher_domain.len && presence_sip_uri_match(&s->pres_uri, &subs->pres_uri)== 0 && presence_sip_uri_match(&s->watcher_user, &subs->watcher_user)== 0 && presence_sip_uri_match(&s->watcher_domain, &subs->watcher_domain)==0) { i++; s->status= subs->status; s->reason= subs->reason; s->db_flag= UPDATEDB_FLAG; cs= mem_copy_subs(s, PKG_MEM_TYPE); if(cs== NULL) { LM_ERR( "copying subs_t stucture\n"); lock_release(&subs_htable[hash_code].lock); return -1; } cs->local_cseq++; cs->expires-= (int)time(NULL); cs->next= (*subs_array); (*subs_array)= cs; if(subs->status== TERMINATED_STATUS) { ps->next= s->next; shm_free(s->contact.s); shm_free(s); LM_DBG(" deleted terminated dialog from hash table\n"); } else ps= s; printf_subs(cs); } else ps= s; } LM_DBG("found %d matching dialogs\n", i); lock_release(&subs_htable[hash_code].lock); return 0; }
void publ_cback_func(struct cell *t, int type, struct tmcb_params *ps) { struct hdr_field* hdr= NULL; struct sip_msg* msg= NULL; ua_pres_t* presentity= NULL; ua_pres_t* db_presentity= NULL; ua_pres_t* hentity= NULL; int found = 0; int size= 0; unsigned int lexpire= 0; str etag; unsigned int hash_code; db1_res_t *res=NULL; ua_pres_t dbpres; str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0}; int end_transaction = 1; memset(&dbpres, 0, sizeof(dbpres)); dbpres.pres_uri = &pres_uri; dbpres.watcher_uri = &watcher_uri; dbpres.extra_headers = &extra_headers; 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; } } if(ps->param== NULL|| *ps->param== NULL) { LM_ERR("NULL callback parameter\n"); goto error; } hentity= (ua_pres_t*)(*ps->param); msg= ps->rpl; if(msg == NULL) { LM_ERR("no reply message found\n "); goto error; } if(msg== FAKED_REPLY) { LM_DBG("FAKED_REPLY\n"); goto done; } hash_code= core_hash(hentity->pres_uri, NULL, HASH_SIZE); if( ps->code>= 300 ) { find_and_delete_record(hentity, hash_code); if(ps->code== 412 && hentity->body && hentity->flag!= MI_PUBLISH && hentity->flag!= MI_ASYN_PUBLISH) { /* sent a PUBLISH within a dialog that no longer exists * send again an intial PUBLISH */ LM_DBG("received a 412 reply- try again to send PUBLISH\n"); publ_info_t publ; memset(&publ, 0, sizeof(publ_info_t)); publ.pres_uri= hentity->pres_uri; publ.body= hentity->body; if(hentity->desired_expires== 0) publ.expires= -1; else if(hentity->desired_expires<= (int)time(NULL)) publ.expires= 0; else publ.expires= hentity->desired_expires- (int)time(NULL)+ 3; publ.source_flag|= hentity->flag; publ.event|= hentity->event; publ.content_type= hentity->content_type; publ.id= hentity->id; publ.extra_headers= hentity->extra_headers; publ.outbound_proxy = hentity->outbound_proxy; publ.cb_param= hentity->cb_param; 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; if(send_publish(&publ)< 0) { LM_ERR("when trying to send PUBLISH\n"); goto error; } } goto done; } /* code >= 300 */ if( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); goto error; } if(msg->expires== NULL || msg->expires->body.len<= 0) { LM_ERR("No Expires header found\n"); goto error; } 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= %u\n", lexpire); hdr = msg->headers; while (hdr!= NULL) { if(cmp_hdrname_strzn(&hdr->name, "SIP-ETag",8)==0 ) { found = 1; break; } hdr = hdr->next; } if(found== 0) /* must find SIP-Etag header field in 200 OK msg*/ { LM_ERR("no SIP-ETag header field found\n"); goto error; } etag= hdr->body; LM_DBG("completed with status %d [contact:%.*s]\n", ps->code, hentity->pres_uri->len, hentity->pres_uri->s); if (lexpire == 0) { find_and_delete_record(hentity, hash_code); goto done; } if (hentity->etag.s) { if (pua_dbf.affected_rows != NULL || dbmode != PUA_DB_ONLY) { if (find_and_update_record(hentity, hash_code, lexpire, &etag) > 0) goto done; } else if ((db_presentity = get_record_puadb(hentity->id, &hentity->etag, &dbpres, &res)) != NULL) { update_record_puadb(hentity, lexpire, &etag); goto done; } } size= sizeof(ua_pres_t)+ sizeof(str)+ (hentity->pres_uri->len+ hentity->tuple_id.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, hentity->pres_uri->s, hentity->pres_uri->len); presentity->pres_uri->len= hentity->pres_uri->len; size+= hentity->pres_uri->len; presentity->tuple_id.s= (char*)presentity+ size; memcpy(presentity->tuple_id.s, hentity->tuple_id.s, hentity->tuple_id.len); presentity->tuple_id.len= hentity->tuple_id.len; size+= presentity->tuple_id.len; 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; } presentity->desired_expires= hentity->desired_expires; presentity->expires= lexpire+ (int)time(NULL); presentity->flag|= hentity->flag; presentity->event|= hentity->event; presentity->etag.s= (char*)shm_malloc(etag.len* sizeof(char)); if(presentity->etag.s== NULL) { LM_ERR("No more share memory\n"); goto error; } memcpy(presentity->etag.s, etag.s, etag.len); presentity->etag.len= etag.len; if (dbmode==PUA_DB_ONLY) { insert_record_puadb(presentity); } else { lock_get(&HashT->p_records[hash_code].lock); insert_htable(presentity, hash_code); lock_release(&HashT->p_records[hash_code].lock); } LM_DBG("Inserted record\n"); done: if(hentity->ua_flag == REQ_OTHER) { run_pua_callbacks(hentity, msg); } if(*ps->param) { shm_free(*ps->param); *ps->param= NULL; } if(dbmode==PUA_DB_ONLY && presentity) { shm_free(presentity->etag.s); shm_free(presentity); } if (res) free_results_puadb(res); 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; } } return; error: if(*ps->param) { shm_free(*ps->param); *ps->param= NULL; } if(presentity) shm_free(presentity); if (res) 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; }
void async_cdp_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) { struct cell *t = 0; pcontact_t* pcontact; unsigned int cdp_result; struct pcontact_info ci; udomain_t* domain_t; int finalReply = 0; int result = CSCF_RETURN_ERROR; LM_DBG("Received AAR callback\n"); saved_transaction_local_t* local_data = (saved_transaction_local_t*) param; saved_transaction_t* data = local_data->global_data; domain_t = data->domain; int is_rereg = local_data->is_rereg; //before we do anything else, lets decrement the reference counter on replies lock_get(data->lock); data->answers_not_received--; if (data->answers_not_received <= 0) { finalReply = 1; } if (data->ignore_replies) { //there was obv. a subsequent error AFTER we had sent one/more AAR's - so we can ignore these replies and just free memory free_saved_transaction_data(local_data); if (finalReply) { free_saved_transaction_global_data(data); } return; } lock_release(data->lock); LM_DBG("received answer and we are waiting for [%d] answers so far failures flag is [%d]\n", data->answers_not_received, data->failed); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); goto error; } //we have T, lets restore our state (esp. for AVPs) set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); if (is_timeout != 0) { LM_ERR("Error timeout when sending AAR message via CDP\n"); update_stat(stat_aar_timeouts, 1); goto error; } if (!aaa) { LM_ERR("Error sending message via CDP\n"); goto error; } update_stat(aar_replies_received, 1); update_stat(aar_replies_response_time, elapsed_msecs); /* Process the response to AAR, retrieving result code and associated Rx session ID */ if (rx_process_aaa(aaa, &cdp_result) < 0) { LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s); goto error; } if (cdp_result >= 2000 && cdp_result < 3000) { if (is_rereg) { LM_DBG("this is a re-registration, therefore we don't need to do anything except know that the the subscription was successful\n"); result = CSCF_RETURN_TRUE; create_return_code(result); goto done; } LM_DBG("Success, received code: [%i] from PCRF for AAR request (contact: [%.*s]), (auth session id: %.*s)\n", cdp_result, local_data->contact.len, local_data->contact.s, local_data->auth_session_id.len, local_data->auth_session_id.s); LM_DBG("Registering for Usrloc callbacks on DELETE\n"); ul.lock_udomain(domain_t, &local_data->contact); if (ul.get_pcontact(domain_t, &local_data->contact, &pcontact) != 0) { LM_ERR("Shouldn't get here, can find contact....\n"); ul.unlock_udomain(domain_t, &local_data->contact); goto error; } //at this point we have the contact /*set the contact state to say we have succesfully done ARR for register and that we dont need to do it again * for the duration of the registration. * */ if (ul.update_rx_regsession(domain_t, &local_data->auth_session_id, pcontact) != 0) { LM_ERR("unable to update pcontact......\n"); ul.unlock_udomain(domain_t, &local_data->contact); goto error; } memset(&ci, 0, sizeof(struct pcontact_info)); ci.reg_state = PCONTACT_REG_PENDING_AAR; ci.num_service_routes = 0; ci.num_public_ids = 0; LM_DBG("impu: [%.*s] updating status to PCONTACT_REG_PENDING\n", pcontact->aor.len, pcontact->aor.s); ul.update_pcontact(domain_t, &ci, pcontact); //register for callbacks on contact ul.register_ulcb(pcontact, PCSCF_CONTACT_DELETE | PCSCF_CONTACT_EXPIRE, callback_pcscf_contact_cb, NULL); ul.unlock_udomain(domain_t, &local_data->contact); result = CSCF_RETURN_TRUE; } else { LM_ERR("Received negative reply from PCRF for AAR Request\n"); result = CSCF_RETURN_FALSE; goto error; } //set success response code AVP create_return_code(result); goto done; error: //set failure response code create_return_code(result); done: if (t) tmb.unref_cell(t); //free memory if (aaa) cdpb.AAAFreeMessage(&aaa); if (finalReply) { tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_global_data(data); } free_saved_transaction_data(local_data); }
static void rpc_delete(rpc_t* rpc, void* c) { str sd; unsigned int dhash; int hash_entry; pd_t *it; pd_op_t *ito, *tmp; db_key_t db_keys[1] = {domain_column}; db_val_t db_vals[1]; db_op_t db_ops[1] = {OP_EQ}; if(_dhash==NULL) { LOG(L_ERR, "PDT:pdt_fifo_delete: strange situation\n"); rpc->fault(c, 500, "Server Error"); return; } /* Use s to make sure the string is zero terminated */ if (rpc->scan(c, "s", &sd.s) < 1) { rpc->fault(c, 400, "Parameter Missing"); return; } sd.len = strlen(sd.s); if(*sd.s=='\0') { LOG(L_INFO, "PDT:pdt_fifo_delete: empty domain\n"); rpc->fault(c, 400, "Empty Parameter"); return; } dhash = pdt_compute_hash(sd.s); hash_entry = get_hash_entry(dhash, _dhash->hash_size); lock_get(&_dhash->diff_lock); lock_get(&_dhash->dhash[hash_entry].lock); it = _dhash->dhash[hash_entry].e; while(it!=NULL && it->dhash<=dhash) { if(it->dhash==dhash && it->domain.len==sd.len && strncasecmp(it->domain.s, sd.s, sd.len)==0) break; it = it->n; } if(it!=NULL) { if(it->p!=NULL) (it->p)->n = it->n; else _dhash->dhash[hash_entry].e = it->n; if(it->n) (it->n)->p = it->p; } lock_release(&_dhash->dhash[hash_entry].lock); if(it!=NULL) { tmp = new_pd_op(it, 0, PDT_DELETE); if(tmp==NULL) { LOG(L_ERR, "PDT:pdt_fifo_delete: no more shm!\n"); rpc->fault(c, 431, "No Shared Memory Left"); lock_release(&_dhash->diff_lock); return; } _dhash->max_id++; tmp->id = _dhash->max_id; if(_dhash->diff==NULL) { _dhash->diff = tmp; DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op); goto done; } ito = _dhash->diff; while(ito->n!=NULL) ito = ito->n; ito->n = tmp; tmp->p = ito; DBG("PDT:pdt_fifo_delete: op[%d]=%d...\n", tmp->id, tmp->op); dhash = 1; } else { dhash = 0; } done: lock_release(&_dhash->diff_lock); if(dhash==0) { DBG("PDT:pdt_fifo_delete: prefix for domain [%s] not found\n", sd.s); rpc->fault(c, 404, "Domain Not Found"); } else { db_vals[0].type = DB_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = sd.s; db_vals[0].val.str_val.len = sd.len; if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 1)<0) { LOG(L_ERR,"PDT:pdt_fifo_delete: database/cache are inconsistent\n"); rpc->fault(c, 502, "Database And Cache Are Inconsistent"); } } }
static inline int mi_print_b2be_dlg(struct mi_node *rpl, b2b_table htable, unsigned int hsize) { int i, len; char* p; b2b_dlg_t* dlg; dlg_leg_t* leg; struct mi_node *node=NULL, *node1=NULL; struct mi_attr* attr; for(i = 0; i< hsize; i++) { lock_get(&htable[i].lock); dlg = htable[i].first; while(dlg) { p = int2str((unsigned long)(dlg->id), &len); node = add_mi_node_child(rpl, MI_DUP_VALUE, "dlg", 3, p, len); if(node == NULL) goto error; attr = add_mi_attr(node, MI_DUP_VALUE, "param", 5, dlg->param.s, dlg->param.len); if(attr == NULL) goto error; p = int2str((unsigned long)(dlg->state), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "state", 5, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(dlg->last_invite_cseq), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "last_invite_cseq", 16, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(dlg->last_method), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "last_method", 11, p, len); if(attr == NULL) goto error; if (dlg->last_reply_code) { p = int2str((unsigned long)(dlg->last_reply_code), &len); attr = add_mi_attr(node,MI_DUP_VALUE,"last_reply_code",15,p,len); if(attr == NULL) goto error; } p = int2str((unsigned long)(dlg->db_flag), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "db_flag", 7, p, len); if(attr == NULL) goto error; if (dlg->ruri.len) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "ruri", 4, dlg->ruri.s, dlg->ruri.len); if(node1 == NULL) goto error; } node1 = add_mi_node_child(node, MI_DUP_VALUE, "callid", 6, dlg->callid.s, dlg->callid.len); if(node1 == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "from", 4, dlg->from_dname.s, dlg->from_dname.len); if(node1 == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "uri", 3, dlg->from_uri.s, dlg->from_uri.len); if(attr == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3, dlg->tag[0].s, dlg->tag[0].len); if(attr == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "to", 2, dlg->to_dname.s, dlg->to_dname.len); if(node1 == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "uri", 3, dlg->to_uri.s, dlg->to_uri.len); if(attr == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3, dlg->tag[1].s, dlg->tag[1].len); if(attr == NULL) goto error; node1 = add_mi_node_child(node, MI_DUP_VALUE, "cseq", 4, NULL, 0); if(node1 == NULL) goto error; p = int2str((unsigned long)(dlg->cseq[0]), &len); attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(dlg->cseq[1]), &len); attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6, p, len); if(attr == NULL) goto error; if (dlg->route_set[0].len||dlg->route_set[1].len) { node1 = add_mi_node_child(node,MI_DUP_VALUE,"route_set",9,NULL,0); if(node1 == NULL) goto error; if (dlg->route_set[0].len) { attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6, dlg->route_set[0].s, dlg->route_set[0].len); if(attr == NULL) goto error; } if (dlg->route_set[1].len) { attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6, dlg->route_set[1].s, dlg->route_set[1].len); if(attr == NULL) goto error; } } node1 = add_mi_node_child(node, MI_DUP_VALUE, "contact", 7, NULL, 0); if(node1 == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "caller", 6, dlg->contact[0].s, dlg->contact[0].len); if(attr == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "callee", 6, dlg->contact[1].s, dlg->contact[1].len); if(attr == NULL) goto error; if (dlg->send_sock) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "send_sock", 9, dlg->send_sock->name.s, dlg->send_sock->name.len); if(node1 == NULL) goto error; } if(dlg->uac_tran||dlg->uas_tran||dlg->update_tran||dlg->cancel_tm_tran) { node1 = add_mi_node_child(node, MI_DUP_VALUE, "tm_tran", 7, NULL, 0); if(node1 == NULL) goto error; if(dlg->uac_tran) attr = add_mi_attr(node1,MI_DUP_VALUE,"uac",3,NULL,0); if(attr == NULL) goto error; if(dlg->uas_tran) attr = add_mi_attr(node1,MI_DUP_VALUE,"uas",3,NULL,0); if(attr == NULL) goto error; if(dlg->update_tran) attr = add_mi_attr(node1,MI_DUP_VALUE,"update",6,NULL,0); if(attr == NULL) goto error; if(dlg->cancel_tm_tran) attr = add_mi_attr(node1,MI_DUP_VALUE,"cancel_tm",9,NULL,0); if(attr == NULL) goto error; } leg=dlg->legs; while(leg) { p = int2str((unsigned long)(leg->id), &len); node1 = add_mi_node_child(node, MI_DUP_VALUE, "leg", 3, p, len); if(node1 == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "tag", 3, leg->tag.s, leg->tag.len); if(attr == NULL) goto error; p = int2str((unsigned long)(leg->cseq), &len); attr = add_mi_attr(node1, MI_DUP_VALUE, "cseq", 4, p, len); if(attr == NULL) goto error; attr = add_mi_attr(node1, MI_DUP_VALUE, "contact", 7, leg->contact.s, leg->contact.len); if(attr == NULL) goto error; if(leg->route_set.len) { attr = add_mi_attr(node1, MI_DUP_VALUE, "route_set", 8, leg->route_set.s, leg->route_set.len); if(attr == NULL) goto error; } leg=leg->next; } dlg = dlg->next; } lock_release(&htable[i].lock); } return 0; error: lock_release(&htable[i].lock); LM_ERR("failed to add node\n"); return -1; }
static void rpc_uac_reg_info(rpc_t* rpc, void* ctx) { int i; reg_item_t *reg = NULL; void* th; str none = {"none", 4}; time_t tn; str attr = {0}; str val = {0}; str *rval; if(_reg_htable==NULL) { rpc->fault(ctx, 500, "Not enabled"); return; } if(rpc->scan(ctx, "S.S", &attr, &val)<2) { rpc->fault(ctx, 500, "Invalid Parameters"); return; } if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL) { LM_ERR("bad parameter values\n"); rpc->fault(ctx, 500, "Invalid Parameter Values"); return; } tn = time(NULL); for(i=0; i<_reg_htable->htsize; i++) { /* walk through entries */ lock_get(&_reg_htable->entries[i].lock); reg = _reg_htable->entries[i].byuuid; while(reg) { if(attr.len==10 && strncmp(attr.s, "l_username", 10)==0) { rval = ®->r->l_username; } else if(attr.len==10 && strncmp(attr.s, "r_username", 10)==0) { rval = ®->r->r_username; } else if(attr.len==6 && strncmp(attr.s, "l_uuid", 6)==0) { rval = ®->r->l_uuid; } else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) { rval = ®->r->auth_username; } else { lock_release(&_reg_htable->entries[i].lock); LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s); rpc->fault(ctx, 500, "Unsupported Filter Attribtue"); return; } if(rval->len==val.len && strncmp(val.s, rval->s, val.len)==0) { /* add entry node */ if (rpc->add(ctx, "{", &th) < 0) { rpc->fault(ctx, 500, "Internal error creating rpc"); return; } if(rpc->struct_add(th, "SSSSSSSSSdddd", "l_uuid", ®->r->l_uuid, "l_username", ®->r->l_username, "l_domain", ®->r->l_domain, "r_username", ®->r->r_username, "r_domain", ®->r->r_domain, "realm", ®->r->realm, "auth_username", ®->r->auth_username, "auth_password", ®->r->auth_password, "auth_proxy", (reg->r->auth_proxy.len)? ®->r->auth_proxy:&none, "expires", (int)reg->r->expires, "flags", (int)reg->r->flags, "diff_expires", (int)(reg->r->timer_expires - tn), "timer_expires", (int)reg->r->timer_expires )<0) { lock_release(&_reg_htable->entries[i].lock); rpc->fault(ctx, 500, "Internal error adding item"); return; } lock_release(&_reg_htable->entries[i].lock); return; } reg = reg->next; } lock_release(&_reg_htable->entries[i].lock); } }
int uac_reg_free_ht(void) { int i; reg_item_t *it = NULL; reg_item_t *it0 = NULL; if(_reg_htable_gc_lock != NULL) { lock_destroy(_reg_htable_gc_lock); shm_free((void*)_reg_htable_gc_lock); _reg_htable_gc_lock = NULL; } if(_reg_htable_gc!=NULL) { for(i=0; i<_reg_htable_gc->htsize; i++) { it = _reg_htable_gc->entries[i].byuuid; while(it) { it0 = it; it = it->next; shm_free(it0); } it = _reg_htable_gc->entries[i].byuser; while(it) { it0 = it; it = it->next; shm_free(it0->r); shm_free(it0); } } shm_free(_reg_htable_gc->entries); shm_free(_reg_htable_gc); _reg_htable_gc = NULL; } if(_reg_htable==NULL) { LM_DBG("no hash table\n"); return -1; } for(i=0; i<_reg_htable->htsize; i++) { lock_get(&_reg_htable->entries[i].lock); /* free entries */ it = _reg_htable->entries[i].byuuid; while(it) { it0 = it; it = it->next; shm_free(it0); } it = _reg_htable->entries[i].byuser; while(it) { it0 = it; it = it->next; shm_free(it0->r); shm_free(it0); } lock_destroy(&_reg_htable->entries[i].lock); } shm_free(_reg_htable->entries); shm_free(_reg_htable); _reg_htable = NULL; return 0; }
/* * Update a row in table */ int dbt_update(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, db_key_t* _uk, db_val_t* _uv, int _n, int _un) { tbl_cache_p _tbc = NULL; dbt_table_p _dtp = NULL; dbt_row_p _drp = NULL; int i; str stbl; int *lkey=NULL, *lres=NULL; if (!_h || !CON_TABLE(_h) || !_uk || !_uv || _un <= 0) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_update: Invalid parameter value\n"); #endif return -1; } stbl.s = (char*)CON_TABLE(_h); stbl.len = strlen(CON_TABLE(_h)); _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl); if(!_tbc) { DBG("DBT:dbt_update: table does not exist!\n"); return -1; } lock_get(&_tbc->sem); _dtp = _tbc->dtp; if(!_dtp || _dtp->nrcols < _un) { DBG("DBT:dbt_update: table not loaded or more values" " to update than columns!\n"); goto error; } if(_k) { lkey = dbt_get_refs(_dtp, _k, _n); if(!lkey) goto error; } lres = dbt_get_refs(_dtp, _uk, _un); if(!lres) goto error; DBG("DBT:dbt_update: ---- \n"); _drp = _dtp->rows; while(_drp) { if(dbt_row_match(_dtp, _drp, lkey, _o, _v, _n)) { // update fields for(i=0; i<_un; i++) { if(dbt_is_neq_type(_dtp->colv[lres[i]]->type, _uv[i].type)) { DBG("DBT:dbt_update: incompatible types!\n"); goto error; } if(dbt_row_update_val(_drp, &(_uv[i]), _uv[i].type, lres[i])) { DBG("DBT:dbt_update: cannot set v[%d] in c[%d]!\n", i, lres[i]); goto error; } } } _drp = _drp->next; } dbt_table_update_flags(_dtp, DBT_TBFL_MODI, DBT_FL_SET, 1); #ifdef DBT_EXTRA_DEBUG dbt_print_table(_dtp, NULL); #endif lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); return 0; error: lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); DBG("DBT:dbt_update: error while updating table!\n"); return -1; }
int real_main(int argc, char *argv[]) { int ret=1; int option=0; int daemon=1; int forking=1; int strip=0; int randomise=0; struct lock *lock=NULL; struct conf **confs=NULL; int forceoverwrite=0; enum action act=ACTION_LIST; const char *backup=NULL; const char *backup2=NULL; char *restoreprefix=NULL; const char *regex=NULL; const char *browsefile=NULL; char *browsedir=NULL; const char *conffile=get_conf_path(); const char *orig_client=NULL; const char *logfile=NULL; // The orig_client is the original client that the normal client // would like to restore from. #ifndef HAVE_WIN32 int generate_ca_only=0; #endif int vss_restore=1; int test_confs=0; enum burp_mode mode; log_init(argv[0]); #ifndef HAVE_WIN32 if(!strcmp(prog, "bedup")) return run_bedup(argc, argv); if(!strcmp(prog, "bsigs")) return run_bsigs(argc, argv); #endif while((option=getopt(argc, argv, "a:b:c:C:d:fFghil:nq:r:s:tvxjz:?"))!=-1) { switch(option) { case 'a': if(parse_action(&act, optarg)) goto end; break; case 'b': // The diff command may have two backups // specified. if(!backup2 && backup) backup2=optarg; if(!backup) backup=optarg; break; case 'c': conffile=optarg; break; case 'C': orig_client=optarg; break; case 'd': restoreprefix=optarg; // for restores browsedir=optarg; // for lists break; case 'f': forceoverwrite=1; break; case 'F': daemon=0; break; case 'g': #ifndef HAVE_WIN32 generate_ca_only=1; #endif break; case 'i': cmd_print_all(); ret=0; goto end; case 'l': logfile=optarg; break; case 'n': forking=0; break; case 'q': randomise=atoi(optarg); break; case 'r': regex=optarg; break; case 's': strip=atoi(optarg); break; case 'v': printf("%s-%s\n", progname(), VERSION); ret=0; goto end; case 'x': vss_restore=0; break; case 't': test_confs=1; break; case 'z': browsefile=optarg; break; case 'h': case '?': default: usage(); goto end; } } if(optind<argc) { usage(); goto end; } if(act==ACTION_MONITOR) { // Try to output everything in JSON. log_set_json(1); #ifndef HAVE_WIN32 // Need to do this so that processes reading stdout get the // result of the printfs of logp straight away. setlinebuf(stdout); #endif } if(!(confs=confs_alloc())) goto end; if(reload(confs, conffile, 1 /* first time */, 0 /* no oldmax_children setting */, 0 /* no oldmax_status_children setting */)) goto end; // Dry run to test config file syntax. if(test_confs) { ret=run_test_confs(confs, orig_client, conffile); goto end; } if(!backup) switch(act) { case ACTION_DELETE: logp("No backup specified for deletion.\n"); goto end; case ACTION_RESTORE: case ACTION_VERIFY: case ACTION_DIFF: case ACTION_DIFF_LONG: logp("No backup specified. Using the most recent.\n"); backup="0"; default: break; } if(!backup2) switch(act) { case ACTION_DIFF: case ACTION_DIFF_LONG: logp("No second backup specified. Using file system scan.\n"); backup2="n"; // For 'next'. default: break; } // The logfile option is only used for the status client stuff. if(logfile && (act!=ACTION_STATUS && act!=ACTION_STATUS_SNAPSHOT)) logp("-l <logfile> option obsoleted\n"); if(orig_client && *orig_client && set_string(confs[OPT_ORIG_CLIENT], orig_client)) goto end; // The random delay needs to happen before the lock is got, otherwise // you would never be able to use burp by hand. if(randomise) set_int(confs[OPT_RANDOMISE], randomise); mode=get_e_burp_mode(confs[OPT_BURP_MODE]); if(mode==BURP_MODE_CLIENT && (act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK)) random_delay(confs); if(mode==BURP_MODE_SERVER && act==ACTION_CHAMP_CHOOSER) { // These server modes need to run without getting the lock. } else if(mode==BURP_MODE_CLIENT && (act==ACTION_LIST || act==ACTION_LIST_LONG || act==ACTION_DIFF || act==ACTION_DIFF_LONG || act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT || act==ACTION_MONITOR)) { // These client modes need to run without getting the lock. } else { const char *lockfile=confs_get_lockfile(confs); if(!(lock=lock_alloc_and_init(lockfile))) goto end; lock_get(lock); switch(lock->status) { case GET_LOCK_GOT: break; case GET_LOCK_NOT_GOT: logp("Could not get lockfile.\n"); logp("Another process is probably running,\n"); goto end; case GET_LOCK_ERROR: default: logp("Could not get lockfile.\n"); logp("Maybe you do not have permissions to write to %s.\n", lockfile); goto end; } } set_int(confs[OPT_OVERWRITE], forceoverwrite); set_int(confs[OPT_STRIP], strip); set_int(confs[OPT_FORK], forking); set_int(confs[OPT_DAEMON], daemon); strip_trailing_slashes(&restoreprefix); strip_trailing_slashes(&browsedir); if(replace_conf_str(confs[OPT_BACKUP], backup) || replace_conf_str(confs[OPT_BACKUP2], backup2) || replace_conf_str(confs[OPT_RESTOREPREFIX], restoreprefix) || replace_conf_str(confs[OPT_REGEX], regex) || replace_conf_str(confs[OPT_BROWSEFILE], browsefile) || replace_conf_str(confs[OPT_BROWSEDIR], browsedir) || replace_conf_str(confs[OPT_MONITOR_LOGFILE], logfile)) goto end; base64_init(); hexmap_init(); if(mode==BURP_MODE_SERVER) { #ifdef HAVE_WIN32 logp("Sorry, server mode is not implemented for Windows.\n"); #else ret=server_modes(act, conffile, lock, generate_ca_only, confs); #endif } else { ret=client(confs, act, vss_restore); } end: lock_release(lock); lock_free(&lock); confs_free(&confs); return ret; }
/* * Insert a row into table */ int dbt_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n) { tbl_cache_p _tbc = NULL; dbt_table_p _dtp = NULL; dbt_row_p _drp = NULL; str stbl; int *lkey=NULL, i, j; if (!_h || !CON_TABLE(_h)) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_insert: Invalid parameter value\n"); #endif return -1; } if(!_k || !_v || _n<=0) { #ifdef DBT_EXTRA_DEBUG DBG("DBT:dbt_insert: no key-value to insert\n"); #endif return -1; } stbl.s = (char*)CON_TABLE(_h); stbl.len = strlen(CON_TABLE(_h)); _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl); if(!_tbc) { DBG("DBT:db_insert: table does not exist!\n"); return -1; } lock_get(&_tbc->sem); _dtp = _tbc->dtp; if(!_dtp) { DBG("DBT:db_insert: table does not exist!!\n"); goto error; } if(_dtp->nrcols<_n) { DBG("DBT:db_insert: more values than columns!!\n"); goto error; } if(_k) { lkey = dbt_get_refs(_dtp, _k, _n); if(!lkey) goto error; } _drp = dbt_row_new(_dtp->nrcols); if(!_drp) { DBG("DBT:db_insert: no memory for a new row!!\n"); goto error; } for(i=0; i<_n; i++) { j = (lkey)?lkey[i]:i; if(dbt_is_neq_type(_dtp->colv[j]->type, _v[i].type)) { DBG("DBT:db_insert: incompatible types v[%d] - c[%d]!\n", i, j); goto clean; } if(dbt_row_set_val(_drp, &(_v[i]), _v[i].type, j)) { DBG("DBT:db_insert: cannot set v[%d] in c[%d]!\n", i, j); goto clean; } } if(dbt_table_add_row(_dtp, _drp)) { DBG("DBT:db_insert: cannot insert the new row!!\n"); goto clean; } #ifdef DBT_EXTRA_DEBUG dbt_print_table(_dtp, NULL); #endif lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); DBG("DBT:db_insert: done!\n"); return 0; error: lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); DBG("DBT:db_insert: error inserting row in table!\n"); return -1; clean: lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); if(_drp) // free row dbt_row_free(_dtp, _drp); DBG("DBT:db_insert: make clean!\n"); return -1; }
/* * Delete a row from table */ int dbt_delete(db_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n) { tbl_cache_p _tbc = NULL; dbt_table_p _dtp = NULL; dbt_row_p _drp = NULL, _drp0 = NULL; int *lkey = NULL; str stbl; if (!_h || !CON_TABLE(_h)) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_delete: Invalid parameter value\n"); #endif return -1; } stbl.s = (char*)CON_TABLE(_h); stbl.len = strlen(CON_TABLE(_h)); _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl); if(!_tbc) { DBG("DBT:dbt_delete: error loading table <%s>!\n", CON_TABLE(_h)); return -1; } lock_get(&_tbc->sem); _dtp = _tbc->dtp; if(!_dtp) { DBG("DBT:dbt_delete: table does not exist!!\n"); goto error; } if(!_k || !_v || _n<=0) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_delete: delete all values\n"); #endif dbt_table_free_rows(_dtp); lock_release(&_tbc->sem); return 0; } lkey = dbt_get_refs(_dtp, _k, _n); if(!lkey) goto error; _drp = _dtp->rows; while(_drp) { _drp0 = _drp->next; if(dbt_row_match(_dtp, _drp, lkey, _o, _v, _n)) { // delete row DBG("DBT:dbt_delete: deleting a row!\n"); if(_drp->prev) (_drp->prev)->next = _drp->next; else _dtp->rows = _drp->next; if(_drp->next) (_drp->next)->prev = _drp->prev; _dtp->nrrows--; // free row dbt_row_free(_dtp, _drp); } _drp = _drp0; } dbt_table_update_flags(_dtp, DBT_TBFL_MODI, DBT_FL_SET, 1); #ifdef DBT_EXTRA_DEBUG dbt_print_table(_dtp, NULL); #endif lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); return 0; error: lock_release(&_tbc->sem); DBG("DBT:dbt_delete: error deleting from table!\n"); return -1; }
int dbt_query(db_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, db_key_t* _c, int _n, int _nc, db_key_t _o, db_res_t** _r) { tbl_cache_p _tbc = NULL; dbt_table_p _dtp = NULL; dbt_row_p _drp = NULL; dbt_result_p _dres = NULL; str stbl; int *lkey=NULL, *lres=NULL; if ((!_h) || (!_r) || !CON_TABLE(_h)) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_query: Invalid parameter value\n"); #endif return -1; } stbl.s = (char*)CON_TABLE(_h); stbl.len = strlen(CON_TABLE(_h)); _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), &stbl); if(!_tbc) { DBG("DBT:dbt_query: table does not exist!\n"); return -1; } lock_get(&_tbc->sem); _dtp = _tbc->dtp; if(!_dtp || _dtp->nrcols < _nc) { DBG("DBT:dbt_query: table not loaded!\n"); goto error; } if(_k) { lkey = dbt_get_refs(_dtp, _k, _n); if(!lkey) goto error; } if(_c) { lres = dbt_get_refs(_dtp, _c, _nc); if(!lres) goto error; } DBG("DBT:dbt_query: new res with %d cols\n", _nc); _dres = dbt_result_new(_dtp, lres, _nc); if(!_dres) goto error; _drp = _dtp->rows; while(_drp) { if(dbt_row_match(_dtp, _drp, lkey, _op, _v, _n)) { if(dbt_result_extract_fields(_dtp, _drp, lres, _dres)) { DBG("DBT:dbt_query: error extracting result fields!\n"); goto clean; } } _drp = _drp->next; } dbt_table_update_flags(_dtp, DBT_TBFL_ZERO, DBT_FL_IGN, 1); lock_release(&_tbc->sem); #ifdef DBT_EXTRA_DEBUG dbt_result_print(_dres); #endif DBT_CON_RESULT(_h) = _dres; if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); return dbt_get_result(_h, _r); error: lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); DBG("DBT:dbt_query: error while querying table!\n"); return -1; clean: lock_release(&_tbc->sem); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); if(_dres) dbt_result_free(_dres); DBG("DBT:dbt_query: make clean\n"); return -1; }
int notify_ebr_subscriptions( ebr_event *ev, evi_params_t *params) { ebr_subscription *sub, *sub_next, *sub_prev; ebr_filter *filter; ebr_ipc_job *job; evi_param_t *e_param; int matches; char *s; struct usr_avp *avps=(void*)-1; unsigned int my_time; LM_DBG("notification received for event %.*s, checking subscriptions\n", ev->event_name.len, ev->event_name.s); my_time = get_ticks(); lock_get( &(ev->lock) ); /* check the EBR subscription on this event and apply the filters */ sub_prev = NULL; for ( sub=ev->subs ; sub ; sub_prev=sub, sub=sub_next?sub_next:(sub?sub->next:NULL) ) { /* discard expired NOTIFY subscriptions */ if (sub->flags&EBR_SUBS_TYPE_NOTY && sub->expire<my_time) { LM_DBG("subscription type [NOTIFY]from process %d(pid %d) on " "event <%.*s> expired at %d\n", sub->proc_no, pt[sub->proc_no].pid, sub->event->event_name.len, sub->event->event_name.s, sub->expire ); /* remove the subscription */ sub_next = sub->next; /* unlink it */ if (sub_prev) sub_prev->next = sub_next; else ev->subs = sub_next; /* free it */ free_ebr_subscription(sub); /* do not count us as prev, as we are removed */ sub = sub_prev; continue; } /* run the filters */ matches = 1; sub_next = NULL; for ( filter=sub->filters ; matches && filter ; filter=filter->next ) { /* look for the evi param with the same name */ for ( e_param=params->first ; e_param ; e_param=e_param->next ) { if (e_param->name.len==filter->key.len && strncasecmp(e_param->name.s,filter->key.s,filter->key.len)==0){ /* name matches, let's see the value */ LM_DBG("key <%.*s> found, checking value \n", filter->key.len, filter->key.s); if (filter->val.len==0) { /* a "no value" matches anything */ } else { if (e_param->flags&EVI_INT_VAL) { s=int2str((unsigned long)e_param->val.n, NULL); if (s==NULL) { LM_ERR("failed to covert int EVI param to " "string, EBR filter failed\n"); matches = 0; } else { /* the output of int2str is NULL terminated */ if (fnmatch( filter->val.s, s, 0)!=0) matches = 0; } } else if (e_param->flags&EVI_STR_VAL) { s=(char*)pkg_malloc(e_param->val.s.len+1); if (s==NULL) { LM_ERR("failed to allocate PKG fnmatch " "buffer, EBR filter failed\n"); matches = 0; } else { memcpy(s,e_param->val.s.s,e_param->val.s.len); s[e_param->val.s.len] = 0; if (fnmatch( filter->val.s, s, 0)!=0) matches = 0; pkg_free(s); } } else { LM_ERR("non-string EVI params are not supported " "yet\n"); matches = 0; } } break; } /* a filter not matching any EVI params is simply ignored */ } /* end EVI param iterator */ } /* end EBR filter iterator */ /* did the EVI event match the EBR filters for this subscription ? */ if (matches) { LM_DBG("subscription type [%s]from process %d(pid %d) matched " "event, generating notification via IPC\n", (sub->flags&EBR_SUBS_TYPE_WAIT)?"WAIT":"NOTIFY", sub->proc_no, pt[sub->proc_no].pid); /* convert the EVI params into AVP (only once) */ if (avps==(void*)-1) { avps = pack_evi_params_as_avp_list(params); } /* pack the EVI params to be attached to the IPC job */ job =(ebr_ipc_job*)shm_malloc( sizeof(ebr_ipc_job) ); if (job==NULL) { LM_ERR("failed to allocated new IPC job, skipping..\n"); continue; /* with the next subscription */ } job->ev = ev; job->avps = clone_avp_list( avps ); job->data = sub->data; job->flags = sub->flags; job->tm = sub->tm; if (sub->flags&EBR_SUBS_TYPE_NOTY) { /* dispatch the event notification via IPC to the right * process. Key question - which one is the "right" process ? * - the current processs * - the process which performed the subscription * Let's give it to ourselves for the moment */ if (ipc_send_job( process_no, ebr_ipc_type , (void*)job)<0) { LM_ERR("failed to send job via IPC, skipping...\n"); shm_free(job); } } else { /* sent the event notification via IPC to resume on the * subscribing process */ if (ipc_send_job( sub->proc_no, ebr_ipc_type , (void*)job)<0) { LM_ERR("failed to send job via IPC, skipping...\n"); shm_free(job); } /* remove the subscription, as it can be triggered only * one time */ sub_next = sub->next; /* unlink it */ if (sub_prev) sub_prev->next = sub_next; else ev->subs = sub_next; /* free it */ free_ebr_subscription(sub); /* do not count us as prev, as we are removed */ sub = sub_prev; } } } /* end EBR subscription iterator */ lock_release( &(ev->lock) ); if (avps!=(void*)-1) destroy_avp_list( &avps ); return 0; }
/*! \brief * handle io routine, based on the fd_map type * (it will be called from reactor_main_loop ) * params: fm - pointer to a fd hash entry * idx - index in the fd_array (or -1 if not known) * return: -1 on error, or when we are not interested any more on reads * from this fd (e.g.: we are closing it ) * 0 on EAGAIN or when by some other way it is known that no more * io events are queued on the fd (the receive buffer is empty). * Usefull to detect when there are no more io events queued for * sigio_rt, epoll_et, kqueue. * >0 on successfull read from the fd (when there might be more io * queued -- the receive buffer might still be non-empty) */ inline static int handle_io(struct fd_map* fm, int idx,int event_type) { int ret=0; int n; struct tcp_connection* con; int s,rw; long resp; long response[2]; switch(fm->type){ case F_TIMER_JOB: handle_timer_job(); break; case F_SCRIPT_ASYNC: async_resume_f( &fm->fd, fm->data); return 0; case F_TCPMAIN: again: ret=n=receive_fd(fm->fd, response, sizeof(response), &s, 0); if (n<0){ if (errno == EWOULDBLOCK || errno == EAGAIN){ ret=0; break; }else if (errno == EINTR) goto again; else{ LM_CRIT("read_fd: %s \n", strerror(errno)); abort(); /* big error*/ } } if (n==0){ LM_WARN("0 bytes read\n"); break; } con = (struct tcp_connection *)response[0]; rw = (int)response[1]; if (con==0){ LM_CRIT("null pointer\n"); break; } if (s==-1) { LM_BUG("read_fd:no fd read\n"); /* FIXME? */ return -1; } if (con==tcp_conn_lst){ LM_CRIT("duplicate" " connection received: %p, id %d, fd %d, refcnt %d" " state %d (n=%d)\n", con, con->id, con->fd, con->refcnt, con->state, n); tcpconn_release(con, CONN_ERROR,0); break; /* try to recover */ } LM_DBG("We have received conn %p with rw %d on fd %d\n",con,rw,s); if (rw & IO_WATCH_READ) { /* 0 attempts so far for this SIP MSG */ con->msg_attempts = 0; /* must be before reactor_add, as the add might catch some * already existing events => might call handle_io and * handle_io might decide to del. the new connection => * must be in the list */ tcpconn_listadd(tcp_conn_lst, con, c_next, c_prev); con->timeout = con->lifetime; if (reactor_add_reader( s, F_TCPCONN, RCT_PRIO_NET, con )<0) { LM_CRIT("failed to add new socket to the fd list\n"); tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); goto con_error; } /* mark that the connection is currently in our process future writes to this con won't have to acquire FD */ con->proc_id = process_no; /* save FD which is valid in context of this TCP worker */ con->fd=s; } else if (rw & IO_WATCH_WRITE) { LM_DBG("Received con for async write %p ref = %d\n",con,con->refcnt); lock_get(&con->write_lock); resp = protos[con->type].net.write( (void*)con, s ); lock_release(&con->write_lock); if (resp<0) { ret=-1; /* some error occured */ con->state=S_CONN_BAD; tcpconn_release(con, CONN_ERROR,1); break; } else if (resp==1) { tcpconn_release(con, ASYNC_WRITE,1); } else { tcpconn_release(con, CONN_RELEASE,1); } ret = 0; /* we always close the socket received for writing */ close(s); } break; case F_TCPCONN: if (event_type & IO_WATCH_READ) { con=(struct tcp_connection*)fm->data; resp = protos[con->type].net.read( (void*)con, &ret ); if (resp<0) { ret=-1; /* some error occured */ con->state=S_CONN_BAD; reactor_del_all( con->fd, idx, IO_FD_CLOSING ); tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); con->proc_id = -1; if (con->fd!=-1) { close(con->fd); con->fd = -1; } tcpconn_release(con, CONN_ERROR,0); } else if (con->state==S_CONN_EOF) { reactor_del_all( con->fd, idx, IO_FD_CLOSING ); tcpconn_listrm(tcp_conn_lst, con, c_next, c_prev); con->proc_id = -1; if (con->fd!=-1) { close(con->fd); con->fd = -1; } tcpconn_release(con, CONN_EOF,0); } else { //tcpconn_release(con, CONN_RELEASE); /* keep the connection for now */ break; } } break; case F_NONE: LM_CRIT("empty fd map %p: " "{%d, %d, %p}\n", fm, fm->fd, fm->type, fm->data); goto error; default: LM_CRIT("uknown fd type %d\n", fm->type); goto error; } return ret; con_error: con->state=S_CONN_BAD; tcpconn_release(con, CONN_ERROR,0); return ret; error: return -1; }
dlg_t * build_dlg_t(struct dlg_cell * cell, int dir) { dlg_t* td = NULL; str cseq; unsigned int loc_seq; str route_set; str contact; struct dlg_cell_out *dlg_out = 0; struct dlg_entry_out* dlg_entry_out = 0; /* if trying to send by to callee we need to get the corresponding dlg_out cell */ lock_get(cell->dlg_out_entries_lock); dlg_entry_out = &cell->dlg_entry_out; dlg_out = dlg_entry_out->first; //must be concurrent call - lets choose - TODO - ie. check if there is more if (!dlg_out) { LM_ERR("Trying to send BYE for dialog with no callee leg\n"); lock_release(cell->dlg_out_entries_lock); return NULL; } td = (dlg_t*) pkg_malloc(sizeof (dlg_t)); if (!td) { LM_ERR("out of pkg memory\n"); lock_release(cell->dlg_out_entries_lock); return NULL; } memset(td, 0, sizeof (dlg_t)); if (dir == DLG_CALLER_LEG) { cseq = cell->first_req_cseq; route_set = cell->caller_route_set; contact = cell->caller_contact; td->rem_uri = cell->from_uri; td->loc_uri = dlg_out->to_uri; td->id.rem_tag = cell->from_tag; td->id.loc_tag = dlg_out->to_tag; td->send_sock = cell->caller_bind_addr; } else { cseq = dlg_out->callee_cseq; route_set = dlg_out->callee_route_set; contact = dlg_out->callee_contact; td->rem_uri = dlg_out->to_uri; td->loc_uri = cell->from_uri; td->id.rem_tag = dlg_out->to_tag; td->id.loc_tag = cell->from_tag; td->send_sock = dlg_out->callee_bind_addr; } if (str2int(&cseq, &loc_seq) != 0) { LM_ERR("invalid cseq\n"); goto error; } /*we don not increase here the cseq as this will be done by TM*/ td->loc_seq.value = loc_seq; td->loc_seq.is_set = 1; /*route set*/ if (route_set.s && route_set.len) { if (parse_rr_body(route_set.s, route_set.len, &td->route_set) != 0) { LM_ERR("failed to parse route set\n"); goto error; } } if (contact.s == 0 || contact.len == 0) { LM_ERR("no contact available\n"); goto error; } td->id.call_id = cell->callid; td->rem_target = contact; td->state = DLG_CONFIRMED; lock_release(cell->dlg_out_entries_lock); return td; error: lock_release(cell->dlg_out_entries_lock); free_tm_dlg(td); return NULL; }
void sipwatch_lock(void) { lock_get(&siplua_watch->lock); }
int uac_reg_db_refresh(str *pl_uuid) { db1_con_t *reg_db_con = NULL; db_func_t reg_dbf; reg_uac_t reg; db_key_t db_cols[12] = { &l_uuid_column, &l_username_column, &l_domain_column, &r_username_column, &r_domain_column, &realm_column, &auth_username_column, &auth_password_column, &auth_proxy_column, &expires_column, &flags_column, ®_delay_column }; db_key_t db_keys[1] = {&l_uuid_column}; db_val_t db_vals[1]; db1_res_t* db_res = NULL; int i, ret; /* binding to db module */ if(reg_db_url.s==NULL) { LM_ERR("no db url\n"); return -1; } if(db_bind_mod(®_db_url, ®_dbf)) { LM_ERR("database module not found\n"); return -1; } if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL)) { LM_ERR("database module does not " "implement all functions needed by the module\n"); return -1; } /* open a connection with the database */ reg_db_con = reg_dbf.init(®_db_url); if(reg_db_con==NULL) { LM_ERR("failed to connect to the database\n"); return -1; } if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0) { LM_ERR("failed to use_table\n"); return -1; } db_vals[0].type = DB1_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = pl_uuid->s; db_vals[0].val.str_val.len = pl_uuid->len; if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols, 1 /*nr keys*/, 12 /*nr cols*/, 0, &db_res))!=0 || RES_ROW_N(db_res)<=0 ) { reg_dbf.free_result(reg_db_con, db_res); if( ret==0) { return 0; } else { goto error; } } memset(®, 0, sizeof(reg_uac_t));; i = 0; /* check for NULL values ?!?! */ reg_db_set_attr(l_uuid, 0); reg_db_set_attr(l_username, 1); reg_db_set_attr(l_domain, 2); reg_db_set_attr(r_username, 3); reg_db_set_attr(r_domain, 4); /* realm may be empty */ if(!VAL_NULL(&RES_ROWS(db_res)[i].values[5])) { reg.realm.s = (char*)(RES_ROWS(db_res)[i].values[5].val.string_val); reg.realm.len = strlen(reg.realm.s); } reg_db_set_attr(auth_username, 6); reg_db_set_attr(auth_password, 7); reg_db_set_attr(auth_proxy, 8); reg.expires = (unsigned int)RES_ROWS(db_res)[i].values[9].val.int_val; reg.h_uuid = reg_compute_hash(®.l_uuid); reg.h_user = reg_compute_hash(®.l_username); reg.flags = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val; reg.reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val; lock_get(_reg_htable_gc_lock); if(reg_ht_get_byuuid(pl_uuid)!=NULL) { if(reg_ht_update_attrs(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error updating reg to htable\n"); goto error; } } else { if(reg_ht_add(®)<0) { lock_release(_reg_htable_gc_lock); LM_ERR("Error adding reg to htable\n"); goto error; } } lock_release(_reg_htable_gc_lock); reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); return 0; error: if (reg_db_con) { reg_dbf.free_result(reg_db_con, db_res); reg_dbf.close(reg_db_con); } return -1; }
/** * Print the contents of an ims_subscription structure. * @param log_level - level to log on * @param s - the ims_subscription to be printed */ void print_user_data(int log_level,ims_subscription *s) { int i,j,k; LOG(log_level,"INF:"M_NAME":IMSSubscription:\n"); if (!s) return; lock_get(s->lock); LOG(log_level,"INF:"M_NAME":\tPrivate Identity: <%.*s>\n",s->private_identity.len,s->private_identity.s); for(i=0;i<s->service_profiles_cnt;i++){ LOG(log_level,"INF:"M_NAME":\tService Profile:\n"); for(j=0;j<s->service_profiles[i].public_identities_cnt;j++){ LOG(log_level,"INF:"M_NAME":\t\tPublic Identity: Barring [%d] <%.*s> \n", s->service_profiles[i].public_identities[j].barring, s->service_profiles[i].public_identities[j].public_identity.len, s->service_profiles[i].public_identities[j].public_identity.s); } for(j=0;j<s->service_profiles[i].filter_criteria_cnt;j++){ LOG(log_level,"INF:"M_NAME":\t\tFilter Criteria: Priority [%d]ProfilePartInd [%d]\n", s->service_profiles[i].filter_criteria[j].priority, s->service_profiles[i].filter_criteria[j].profile_part_indicator? *(s->service_profiles[i].filter_criteria[j].profile_part_indicator):-1 ); if (s->service_profiles[i].filter_criteria[j].trigger_point){ LOG(log_level,"INF:"M_NAME":\t\t\tTrigger Point: CNF [%c] %s\n", s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?'X':' ', s->service_profiles[i].filter_criteria[j].trigger_point->condition_type_cnf?"(_|_)&(_|_)":"(_&_)|(_&_)" ); for(k=0;k<s->service_profiles[i].filter_criteria[j].trigger_point->spt_cnt;k++){ LOG(log_level,"INF:"M_NAME":\t\t\t\tSPT: Grp[%d] NOT[%c] RegType[%d]\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].group, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].condition_negated?'X':' ', s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].registration_type ); switch(s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].type){ case 1: LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Request-URI == <%.*s>\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].request_uri.s); break; case 2: LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Method == <%.*s>\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].method.s); break; case 3: LOG(log_level,"INF:"M_NAME":\t\t\t\t\t Hdr(%.*s(%d)) == <%.*s>\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.header.s, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.type, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].sip_header.content.s); break; case 4: LOG(log_level,"INF:"M_NAME":\t\t\t\t\t SessionCase [%d]\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_case); break; case 5: LOG(log_level,"INF:"M_NAME":\t\t\t\t\t SDP(%.*s) == <%.*s>\n", s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.line.s, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.len, s->service_profiles[i].filter_criteria[j].trigger_point->spt[k].session_desc.content.s); break; } } } LOG(log_level,"INF:"M_NAME":\t\t\tAS: <%.*s> Handling [%d] SrvInfo: <%.*s>\n", s->service_profiles[i].filter_criteria[j].application_server.server_name.len, s->service_profiles[i].filter_criteria[j].application_server.server_name.s, s->service_profiles[i].filter_criteria[j].application_server.default_handling, s->service_profiles[i].filter_criteria[j].application_server.service_info.len, s->service_profiles[i].filter_criteria[j].application_server.service_info.s); } if (s->service_profiles[i].cn_service_auth){ LOG(log_level,"INF:"M_NAME":\t\tCN Serv Auth: Subs Media Profile ID [%d]\n", s->service_profiles[i].cn_service_auth->subscribed_media_profile_id); } for(j=0;j<s->service_profiles[i].shared_ifc_set_cnt;j++){ LOG(log_level,"INF:"M_NAME":\t\tShared IFC Set: [%d]\n", s->service_profiles[i].shared_ifc_set[j]); } } lock_release(s->lock); }
static void rpc_uac_reg_update_flag(rpc_t* rpc, void* ctx, int mode, int fval) { int i; reg_item_t *reg = NULL; str attr = {0}; str val = {0}; str *rval; if(_reg_htable==NULL) { rpc->fault(ctx, 500, "Not enabled"); return; } if(rpc->scan(ctx, "S.S", &attr, &val)<2) { rpc->fault(ctx, 500, "Invalid Parameters"); return; } if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL) { LM_ERR("bad parameter values\n"); rpc->fault(ctx, 500, "Invalid Parameter Values"); return; } for(i=0; i<_reg_htable->htsize; i++) { lock_get(&_reg_htable->entries[i].lock); /* walk through entries */ reg = _reg_htable->entries[i].byuuid; while(reg) { if(attr.len==10 && strncmp(attr.s, "l_username", 10)==0) { rval = ®->r->l_username; } else if(attr.len==10 && strncmp(attr.s, "r_username", 10)==0) { rval = ®->r->r_username; } else if(attr.len==6 && strncmp(attr.s, "l_uuid", 6)==0) { rval = ®->r->l_uuid; } else if(attr.len==13 && strncmp(attr.s, "auth_username", 13)==0) { rval = ®->r->auth_username; } else { lock_release(&_reg_htable->entries[i].lock); LM_ERR("usupoorted filter attribute %.*s\n", attr.len, attr.s); rpc->fault(ctx, 500, "Unsupported Filter Attribtue"); return; } if(rval->len==val.len && strncmp(val.s, rval->s, val.len)==0) { /* found */ if(mode==1) { reg->r->flags |= fval; } else { reg->r->flags &= ~fval; } reg->r->timer_expires = time(NULL) + 1; lock_release(&_reg_htable->entries[i].lock); return; } reg = reg->next; } lock_release(&_reg_htable->entries[i].lock); } }
int w_rl_check_3(struct sip_msg *_m, char *_n, char *_l, char *_a) { str name; int limit = 0, ret = 1, should_update = 0; str algorithm; unsigned int hash_idx; rl_pipe_t **pipe; rl_algo_t algo = -1; /* retrieve and check parameters */ if (!_n || !_l) { LM_ERR("invalid parameters\n"); goto end; } if (fixup_get_svalue(_m, (gparam_p)_n, &name) < 0) { LM_ERR("cannot retrieve identifier\n"); goto end; } if (fixup_get_ivalue(_m, (gparam_p)_l, &limit) < 0) { LM_ERR("cannot retrieve limit\n"); goto end; } algorithm.s = 0; if (!_a || fixup_get_svalue(_m, (gparam_p)_a, &algorithm) < 0 || (algo = get_rl_algo(algorithm)) < 0) { algo = PIPE_ALGO_NOP; } /* get limit for FEEDBACK algorithm */ if (algo == PIPE_ALGO_FEEDBACK) { lock_get(rl_lock); if (*rl_feedback_limit) { if (*rl_feedback_limit != limit) { LM_WARN("FEEDBACK limit should be the same for all pipes, but" " new limit %d differs - setting to %d\n", limit, *rl_feedback_limit); limit = *rl_feedback_limit; } } else { if (limit <= 0 || limit >= 100) { LM_ERR("invalid limit for FEEDBACK algorithm " "(must be between 0 and 100)\n"); lock_release(rl_lock); goto end; } *rl_feedback_limit = limit; pid_setpoint_limit(limit); } lock_release(rl_lock); } hash_idx = RL_GET_INDEX(name); RL_GET_LOCK(hash_idx); /* try to get the value */ pipe = RL_GET_PIPE(hash_idx, name); if (!pipe) { LM_ERR("cannot get the index\n"); goto release; } if (!*pipe) { /* allocate new pipe */ *pipe = shm_malloc(sizeof(rl_pipe_t)); if (!*pipe) { LM_ERR("no more shm memory\n"); goto release; } memset(*pipe, 0, sizeof(rl_pipe_t)); LM_DBG("Pipe %.*s doens't exist, but was created %p\n", name.len, name.s, *pipe); if (algo == PIPE_ALGO_NETWORK) should_update = 1; (*pipe)->algo = (algo == PIPE_ALGO_NOP) ? rl_default_algo : algo; } else { LM_DBG("Pipe %.*s found: %p - last used %lu\n", name.len, name.s, *pipe, (*pipe)->last_used); if (algo != PIPE_ALGO_NOP && (*pipe)->algo != algo) { LM_WARN("algorithm %d different from the initial one %d for pipe " "%.*s", algo, (*pipe)->algo, name.len, name.s); } } /* set/update the limit */ (*pipe)->limit = limit; /* set the last used time */ (*pipe)->last_used = time(0); if (RL_USE_CDB(*pipe)) { /* release the counter for a while */ if (rl_change_counter(&name, *pipe, 1) < 0) { LM_ERR("cannot increase counter\n"); goto end; } } else { (*pipe)->counter++; } ret = rl_pipe_check(*pipe); LM_DBG("Pipe %.*s counter:%d load:%d limit:%d should %sbe blocked (%p)\n", name.len, name.s, (*pipe)->counter, (*pipe)->load, (*pipe)->limit, ret == 1? "NOT " : "", *pipe); release: RL_RELEASE_LOCK(hash_idx); if (should_update) { lock_get(rl_lock); (*rl_network_count)++; lock_release(rl_lock); } end: return ret; }
static void rpc_add(rpc_t* rpc, void* c) { db_key_t db_keys[NR_KEYS] = {prefix_column, domain_column}; db_val_t db_vals[NR_KEYS]; db_op_t db_ops[NR_KEYS] = {OP_EQ, OP_EQ}; pd_t* cell; pd_op_t *ito, *tmp; str sd, sp; char* t; if(_dhash==NULL) { LOG(L_ERR, "PDT:pdt_fifo_add: strange situation\n"); rpc->fault(c, 500, "Server Error"); return; } /* Use 's' to make sure strings are zero terminated */ if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) { rpc->fault(c, 400, "Invalid Parameter Value"); return; } sp.len = strlen(sp.s); sd.len = strlen(sd.s); t = sp.s; while(t!=NULL && *t!='\0') { if(*t < '0' || *t > '9') { LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s); rpc->fault(c, 400, "Bad Prefix"); return; } t++; } if(pdt_check_pd(_dhash, &sp, &sd)!=0) { LOG(L_ERR, "PDT:pdt_fifo_add: prefix or domain exists\n"); rpc->fault(c, 400, "Prefix Or Domain Exists"); return; } db_vals[0].type = DB_STR; db_vals[0].nul = 0; db_vals[0].val.str_val = sp; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val= sd; DBG("PDT:pdt_fifo_add: [%.*s] <%.*s>\n", sp.len, sp.s, sd.len, sd.s); /* insert a new domain into database */ if(pdt_dbf.insert(db_con, db_keys, db_vals, NR_KEYS)<0) { LOG(L_ERR, "PDT:pdt_fifo_add: error storing new prefix/domain\n"); rpc->fault(c, 430, "Cannot Store Prefix/domain"); return; } /* insert the new domain into hashtables, too */ cell = new_cell(&sp, &sd); if(cell==NULL) { LOG(L_ERR, "PDT:pdt_fifo_add: no more shm\n"); rpc->fault(c, 431, "Out Of Shared Memory"); goto error1; } tmp = new_pd_op(cell, 0, PDT_ADD); if(tmp==NULL) { LOG(L_ERR, "PDT:pdt_fifo_add: no more shm!\n"); rpc->fault(c, 431, "Out Of Shared Memory"); goto error2; } lock_get(&_dhash->diff_lock); if(pdt_add_to_hash(_dhash, &sp, &sd)!=0) { LOG(L_ERR, "PDT:pdt_fifo_add: could not add to cache\n"); rpc->fault(c, 431, "Could Not Add To Cache"); goto error3; } _dhash->max_id++; tmp->id = _dhash->max_id; if(_dhash->diff==NULL) { _dhash->diff = tmp; goto done; } ito = _dhash->diff; while(ito->n!=NULL) ito = ito->n; ito->n = tmp; tmp->p = ito; done: DBG("PDT:pdt_fifo_add: op[%d]=%d...\n", tmp->id, tmp->op); lock_release(&_dhash->diff_lock); return; error3: lock_release(&_dhash->diff_lock); free_pd_op(tmp); error2: free_cell(cell); error1: if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, NR_KEYS)<0) LOG(L_ERR,"PDT:pdt_fifo_add: database/cache are inconsistent\n"); }
/* timer housekeeping, invoked each timer interval to reset counters */ void rl_timer(unsigned int ticks, void *param) { unsigned int i = 0; map_iterator_t it, del; rl_pipe_t **pipe; str *key; void *value; unsigned long now = time(0); /* get CPU load */ if (get_cpuload() < 0) { LM_ERR("cannot update CPU load\n"); i = 1; } lock_get(rl_lock); /* if CPU was successfully loaded */ if (!i) do_update_load(); /* update network if needed */ if (*rl_network_count) *rl_network_load = get_total_bytes_waiting(PROTO_NONE); lock_release(rl_lock); /* iterate through each map */ for (i = 0; i < rl_htable.size; i++) { RL_GET_LOCK(i); /* iterate through all the entries */ if (map_first(rl_htable.maps[i], &it) < 0) { LM_ERR("map doesn't exist\n"); goto next_map; } for (; iterator_is_valid(&it);) { pipe = (rl_pipe_t **)iterator_val(&it); if (!pipe || !*pipe) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_pipe; } key = iterator_key(&it); if (!key) { LM_ERR("cannot retrieve pipe key\n"); goto next_pipe; } /* check to see if it is expired */ if ((*pipe)->last_used + rl_expire_time < now) { /* this pipe is engaged in a transaction */ del = it; if (iterator_next(&it) < 0) LM_DBG("cannot find next iterator\n"); if ((*pipe)->algo == PIPE_ALGO_NETWORK) { lock_get(rl_lock); (*rl_network_count)--; lock_release(rl_lock); } LM_DBG("Deleting ratelimit pipe key \"%.*s\"\n", key->len, key->s); value = iterator_delete(&del); /* free resources */ if (value) shm_free(value); continue; } else { /* leave the lock if a cachedb query should be done*/ if (RL_USE_CDB(*pipe)) { if (rl_get_counter(key, *pipe) < 0) { LM_ERR("cannot get pipe counter\n"); goto next_pipe; } } switch ((*pipe)->algo) { case PIPE_ALGO_NETWORK: /* handle network algo */ (*pipe)->load = (*rl_network_load > (*pipe)->limit) ? -1 : 1; break; case PIPE_ALGO_RED: if ((*pipe)->limit && rl_timer_interval) (*pipe)->load = (*pipe)->counter / ((*pipe)->limit * rl_timer_interval); break; default: break; } (*pipe)->last_counter = rl_get_all_counters(*pipe); if (RL_USE_CDB(*pipe)) { if (rl_change_counter(key, *pipe, 0) < 0) { LM_ERR("cannot reset counter\n"); } } else { (*pipe)->counter = 0; } } next_pipe: if (iterator_next(&it) < 0) break; } next_map: RL_RELEASE_LOCK(i); } }
/** * Fifo command example: * * --- * :pdt_list:[response_file]\n * prefix\n * domain\n * \n * -- * * - '.' (dot) means NULL value for [prefix] and [domain] * - if both [prefix] and [domain] are NULL, all prefix-domain pairs are listed * - the comparison operation is 'START WITH' -- if domain is 'a' then * all domains starting with 'a' are listed */ static void rpc_list(rpc_t* rpc, void* c) { str sd, sp; pd_t *it; int i; char* buf1, *buf2, *t; if(_dhash==NULL) { LOG(L_ERR, "PDT:pdt_fifo_list: strange situation\n"); rpc->fault(c, 500, "Server Error"); return; } if (rpc->scan(c, "ss", &sp.s, &sd.s) < 2) { rpc->fault(c, 400, "Invalid parameter value"); return; } sp.len = strlen(sp.s); sd.len = strlen(sd.s); t = sp.s; if(*t!='\0' && *t!='.') { while(t!=NULL && *t!='\0') { if(*t < '0' || *t > '9') { LOG(L_ERR, "PDT:pdt_fifo_add: bad prefix [%s]\n", sp.s); rpc->fault(c, 400, "Bad Prefix"); return; } t++; } } else { sp.s = NULL; sp.len = 0; } if(*sd.s=='\0' || *sd.s=='.') { sd.s = NULL; sd.len = 0; } lock_get(&_dhash->diff_lock); for(i=0; i<_dhash->hash_size; i++) { lock_get(&_dhash->dhash[i].lock); it = _dhash->dhash[i].e; for (it = _dhash->dhash[i].e; it; it = it->n) { if((sp.s==NULL && sd.s==NULL) || (sp.s!=NULL && it->prefix.len>=sp.len && strncmp(it->prefix.s, sp.s, sp.len)==0) || (sd.s!=NULL && it->domain.len>=sd.len && strncasecmp(it->domain.s, sd.s, sd.len)==0)) { buf1 = pkg_malloc(it->prefix.len + 1); if (!buf1) continue; memcpy(buf1, it->prefix.s, it->prefix.len); buf1[it->prefix.len] = '\0'; buf2 = pkg_malloc(it->domain.len + 1); if (!buf2) { pkg_free(buf1); continue; } memcpy(buf2, it->domain.s, it->domain.len); buf2[it->domain.len] = '\0'; rpc->add(c, "ss", buf1, buf2); pkg_free(buf1); pkg_free(buf2); } } lock_release(&_dhash->dhash[i].lock); } lock_release(&_dhash->diff_lock); }
int is_nonce_index_valid(int index) { /* if greater than MAX_NONCE_INDEX ->error */ if(index>= MAX_NONCE_INDEX ) { LM_ERR("index greater than buffer length\n"); return 0; } lock_get(nonce_lock); /* if in the first 30 seconds */ if(sec_monit[*second]== -1) { if(index>= *next_index) { LM_DBG("index out of range\n"); lock_release(nonce_lock); return 0; } else { set_buf_bit(index); lock_release(nonce_lock); return 1; } } /* check if right interval */ if(*next_index < sec_monit[*second]) { if(!(index>= sec_monit[*second] || index<= *next_index)) { LM_DBG("index out of the permitted interval\n"); goto error; } } else { if(!(index >= sec_monit[*second] && index<=*next_index)) { LM_DBG("index out of the permitted interval\n"); goto error; } } /* check if the first time used */ if(check_buf_bit(index)) { LM_DBG("nonce already used\n"); goto error; } set_buf_bit(index); lock_release(nonce_lock); return 1; error: lock_release(nonce_lock); return 0; }
/*! * \brief Function that is registered as TM callback and called on replies * * Function that is registered as TM callback and called on replies. It * parses the reply and set the appropriate event. This is then used to * update the dialog state, run eventual dialog callbacks and save or * update the necessary informations about the dialog. * \see next_state_dlg * \param t transaction, unused * \param type type of the entered callback * \param param saved dialog structure in the callback */ static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) { struct dlg_cell *dlg; struct dlg_cell_out *dlg_out = 0; int new_state, old_state, unref, event; str to_tag, to_uri; struct sip_msg *req = param->req; struct sip_msg *rpl = param->rpl; struct dlg_entry_out* dlg_entry_out = 0; if (t && t->fwded_totags) LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] and TO is [%.*s]\n", type, t->fwded_totags->tag.len, t->fwded_totags->tag.s); else LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i]\n", type); dlg = (struct dlg_cell *) (*param->param); if (shutdown_done || dlg == 0) return; if (t) { dlg->transaction = t; } LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id); if (type == TMCB_RESPONSE_FWDED) { // The state does not change, but the msg is mutable in this callback LM_DBG("TMCB_RESPONSE_FWDED from TM received"); run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } if (type == TMCB_RESPONSE_READY) { LM_DBG("TMCB_RESPONSE_READY\n"); return; } if (type == TMCB_RESPONSE_OUT) { if (rpl == FAKED_REPLY) { LM_DBG("Faked reply\n"); return; } // get to tag LM_DBG("Extracting to-tag from reply"); if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) { LM_ERR("bad reply or missing TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; } else { //populate to uri for this branch. to_uri = get_to(rpl)->uri; to_tag = get_to(rpl)->tag_value; if (to_tag.s == 0 || to_tag.len == 0) { LM_ERR("missing TAG param in TO hdr :-/\n"); to_tag.s = 0; to_tag.len = 0; //Here we assume that the transaction module timer will remove any early dialogs return; } } LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s); } if (type == TMCB_DESTROY) event = DLG_EVENT_TDEL; else if (param->code < 200) event = DLG_EVENT_RPL1xx; else if (param->code < 300) event = DLG_EVENT_RPL2xx; else event = DLG_EVENT_RPL3xx; LM_DBG("Calling next_state_dlg and event is %i\n", event); next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag); if (type == TMCB_RESPONSE_OUT) { LM_DBG("Checking if there is an existing dialog_out entry with same to-tag"); dlg_entry_out = &dlg->dlg_entry_out; lock_get(dlg->dlg_out_entries_lock); dlg_out = dlg_entry_out->first; LM_DBG("Scanning dlg_entry_out list for dlg_out"); while (dlg_out) { //Check if there is an already dialog_out entry with same To-tag if (dlg_out->to_tag.len == to_tag.len && memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) { //Found a dialog_out entry with same to_tag! LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s); break; } dlg_out = dlg_out->next; } lock_release(dlg->dlg_out_entries_lock); if (!dlg_out) { LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg); dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag); link_dlg_out(dlg, dlg_out, 0); /* save callee's cseq, caller cseq, callee contact and callee record route*/ if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) { LM_ERR("could not add further info to the dlg out\n"); } if (!dlg_out) { LM_ERR("failed to create new dialog out structure\n"); //TODO do something on this error! } } else { //This dlg_out already exists, update cseq and contact if present LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s); if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq || !rpl->cseq->parsed) { LM_ERR("bad sip message or missing CSeq hdr :-/\n"); } dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag)); /* extract the contact address to update if present*/ if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) { LM_ERR("Can not update callee contact: bad sip message or missing Contact hdr\n"); } else if (parse_contact(rpl->contact) < 0 || ((contact_body_t *) rpl->contact->parsed)->contacts == NULL || ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) { LM_ERR("Can not update callee contact: bad Contact HDR\n"); } else { str contact; contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri; dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag)); } } } if (new_state == DLG_STATE_EARLY) { run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); return; } LM_DBG("new state is %i and old state is %i\n", new_state, old_state); if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) { LM_DBG("dialog %p confirmed \n", dlg); //Remove all the other entries in dialog_out for the same dialog after TM expires the transaction //(not before in order to absorb late in-early-dialog requests). //remove all other dlg_out objects if (dlg_out) { if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unlink_dlgouts_from_cb, (void*) dlg, NULL) < 0) { LM_ERR("failed to register deletion delay function\n"); LM_DBG("Removing all other DLGs"); dlg_remove_dlg_out(dlg_out, dlg, 0); } else { //mark the outs for deletion dlg_remove_dlg_out(dlg_out, dlg, 1); } } else { LM_ERR("There is no dlg_out structure - this is bad\n"); //TODO: add error handling here } /* set start time */ dlg->start_ts = (unsigned int) (time(0)); /* save the settings to the database, * if realtime saving mode configured- save dialog now * else: the next time the timer will fire the update*/ dlg->dflags |= DLG_FLAG_NEW; if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) { LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] " "with clid '%.*s' and tags '%.*s' \n", dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state, dlg->callid.len, dlg->callid.s, dlg->from_tag.len, dlg->from_tag.s); } else { ref_dlg(dlg, 1); } run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); if (unref) unref_dlg(dlg, unref); return; } if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) { //This is a concurrently confirmed call LM_DBG("This is a concurrently confirmed call."); //Create a new Dialog ID token “X” //Not sure how to do this so just going to use existing Did and add an X character to it str new_did; create_concurrent_did(dlg, &new_did); //assign new did to the created or updated dialog_out entry. update_dlg_out_did(dlg_out, &new_did); //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires struct dlg_cell *new_dlg = 0; new_dlg = build_new_dlg(&(dlg->callid) /*callid*/, &(dlg->from_uri) /*from uri*/, &(dlg->from_tag)/*from_tag*/, &(dlg->req_uri) /*r-uri*/); //assign new did to dlg_in update_dlg_did(new_dlg, &new_did); if (new_dlg == 0) { LM_ERR("failed to create new dialog\n"); return; } //link the new_dlg with dlg_out object link_dlg_out(new_dlg, dlg_out, 0); } if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED) { LM_DBG("dialog %p failed (negative reply)\n", dlg); /* dialog setup not completed (3456XX) */ run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); /* do unref */ if (unref) unref_dlg(dlg, unref); return; } if (unref) unref_dlg(dlg, unref); return; }
int reserve_nonce_index(void) { unsigned int curr_sec; int index; int i; curr_sec = get_ticks()%(nonce_expire+1); lock_get(nonce_lock); /* update last index for the previous seconds */ if(*next_index== -1) /* for the first request */ *next_index= 0; else { /* if the portion with still alive nonces is not yet reached */ if(*second!= curr_sec) { /* get the index for the next nonce */ index= (*next_index==MAX_NONCE_INDEX)?MAX_NONCE_INDEX-1:*next_index -1; /* set the interval in sec_monit vector */ if(curr_sec> *second) { for (i= *second; i< curr_sec; i++) sec_monit[i]= index; } else { for (i= *second; i<= nonce_expire; i++) sec_monit[i]= index; for (i= 0; i< curr_sec; i++) sec_monit[i]= index; } } } *second= curr_sec; if(sec_monit[curr_sec]== -1) /* if in the first second*/ { if(*next_index == MAX_NONCE_INDEX) { lock_release(nonce_lock); return -1; } goto done; } if(*next_index> sec_monit[curr_sec]) /* if at the end of the buffer */ { /* if at the end of the buffer */ if(*next_index == MAX_NONCE_INDEX) { *next_index = 0; goto index_smaller; } goto done; } index_smaller: if(*next_index== sec_monit[curr_sec]) /* no more space -> return error */ { lock_release(nonce_lock); LM_INFO("no more indexes available\n"); return -1; } done: unset_buf_bit(*next_index); index= *next_index; *next_index = *next_index + 1; LM_DBG("second= %d, sec_monit= %d, index= %d\n", *second, sec_monit[curr_sec], index); lock_release(nonce_lock); return index; }
int send_publish( publ_info_t* publ ) { str met = {"PUBLISH", 7}; str* str_hdr = NULL; ua_pres_t* presentity= NULL; str* body= NULL; str* tuple_id= NULL; ua_pres_t* cb_param= NULL; unsigned int hash_code=0; str etag= {0, 0}; int ver= 0; int result; int ret_code= 0; pua_event_t* ev= NULL; 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}; int ret = -1; LM_DBG("pres_uri=%.*s\n", publ->pres_uri->len, publ->pres_uri->s ); 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; } } /* get event from list */ ev= get_event(publ->event); if(ev== NULL) { LM_ERR("event not found in list\n"); goto error; } if (dbmode==PUA_DB_ONLY) { if (publ->etag) { memset(&dbpres, 0, sizeof(dbpres)); dbpres.pres_uri = &pres_uri; dbpres.watcher_uri = &watcher_uri; dbpres.extra_headers = &extra_headers; presentity = get_record_puadb(publ->id, publ->etag, &dbpres, &res); } } else { ua_pres_t pres; memset(&pres, 0, sizeof(ua_pres_t)); pres.pres_uri = publ->pres_uri; pres.flag = publ->source_flag; pres.id = publ->id; pres.event = publ->event; if(publ->etag) pres.etag = *publ->etag; hash_code= core_hash(publ->pres_uri, NULL, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); presentity= search_htable(&pres, hash_code); } if(publ->etag && presentity== NULL) { if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); ret = 418; goto error; } if(publ->flag & INSERT_TYPE) { LM_DBG("Insert flag set\n"); goto insert; } if(presentity== NULL) { insert: if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); LM_DBG("insert type\n"); if(publ->flag & UPDATE_TYPE ) { LM_DBG("UPDATE_TYPE and no record found \n"); publ->flag= INSERT_TYPE; } if(publ->expires== 0) { LM_DBG("request for a publish with expires 0 and" " no record found\n"); goto done; } if(publ->body== NULL) { LM_ERR("New PUBLISH and no body found- invalid request\n"); ret = ERR_PUBLISH_NO_BODY; goto error; } } else { LM_DBG("record found\n"); publ->flag= UPDATE_TYPE; etag.s= (char*)pkg_malloc(presentity->etag.len* sizeof(char)); if(etag.s== NULL) { LM_ERR("while allocating memory\n"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } memcpy(etag.s, presentity->etag.s, presentity->etag.len); etag.len= presentity->etag.len; if(presentity->tuple_id.s && presentity->tuple_id.len) { /* get tuple_id*/ tuple_id=(str*)pkg_malloc(sizeof(str)); if(tuple_id== NULL) { LM_ERR("No more memory\n"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } tuple_id->s= (char*)pkg_malloc(presentity->tuple_id.len* sizeof(char)); if(tuple_id->s== NULL) { LM_ERR("No more memory\n"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto error; } memcpy(tuple_id->s, presentity->tuple_id.s, presentity->tuple_id.len); tuple_id->len= presentity->tuple_id.len; } if(publ->expires== 0) { LM_DBG("expires= 0- delete from hash table\n"); if (dbmode!=PUA_DB_ONLY) lock_release(&HashT->p_records[hash_code].lock); goto send_publish; } presentity->version++; ver= presentity->version; if (dbmode==PUA_DB_ONLY) { update_version_puadb(presentity); } else { lock_release(&HashT->p_records[hash_code].lock); } } /* handle body */ if(publ->body && publ->body->s) { ret_code= ev->process_body(publ, &body, ver, &tuple_id ); if( ret_code< 0 || body== NULL) { LM_ERR("while processing body\n"); if(body== NULL) LM_ERR("NULL body\n"); goto error; } } if(tuple_id) LM_DBG("tuple_id= %.*s\n", tuple_id->len, tuple_id->s ); send_publish: /* construct the callback parameter */ if(etag.s && etag.len) publ->etag = &etag; cb_param= publish_cbparam(publ, body, tuple_id, REQ_OTHER); if(cb_param== NULL) { LM_ERR("constructing callback parameter\n"); goto error; } if(publ->flag & UPDATE_TYPE) LM_DBG("etag:%.*s\n", etag.len, etag.s); str_hdr = publ_build_hdr((publ->expires< 0)?3600:publ->expires, ev, &publ->content_type, (publ->flag & UPDATE_TYPE)?&etag:NULL, publ->extra_headers, (body)?1:0); if(str_hdr == NULL) { LM_ERR("while building extra_headers\n"); goto error; } LM_DBG("publ->pres_uri:\n%.*s\n ", publ->pres_uri->len, publ->pres_uri->s); LM_DBG("str_hdr:\n%.*s %d\n ", str_hdr->len, str_hdr->s, str_hdr->len); if(body && body->len && body->s ) LM_DBG("body:\n%.*s\n ", body->len, body->s); set_uac_req(&uac_r, &met, str_hdr, body, 0, TMCB_LOCAL_COMPLETED, publ_cback_func, (void*)cb_param); result= tmb.t_request(&uac_r, publ->pres_uri, /*! Request-URI */ publ->pres_uri, /*! To */ publ->pres_uri, /*! From */ publ->outbound_proxy? publ->outbound_proxy:&outbound_proxy /*! Outbound proxy*/ ); if(result< 0) { LM_ERR("in t_request tm module function\n"); goto error; } done: ret = 0; 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; } } goto finish; error: if(cb_param) shm_free(cb_param); if (dbmode == PUA_DB_ONLY && pua_dbf.abort_transaction) { if (pua_dbf.abort_transaction(pua_db) < 0) LM_ERR("in abort_transaction\n"); } finish: if(etag.s) pkg_free(etag.s); if(body && ret_code) { if(body->s) xmlFree(body->s); pkg_free(body); } if(str_hdr) pkg_free(str_hdr); if(tuple_id) { if(tuple_id->s) pkg_free(tuple_id->s); pkg_free(tuple_id); } free_results_puadb(res); return ret; }
/*callback function to handle responses to the BYE request */ void bye_reply_cb(struct cell* t, int type, struct tmcb_params* ps) { struct dlg_cell* dlg; int event, old_state, new_state, unref, ret; struct dlg_cell_out *dlg_out = 0; if (ps->param == NULL || *ps->param == NULL) { LM_ERR("invalid parameter\n"); return; } if (ps->code < 200) { LM_DBG("receiving a provisional reply\n"); return; } LM_DBG("receiving a final reply %d\n", ps->code); dlg = (struct dlg_cell *) (*(ps->param)); event = DLG_EVENT_REQBYE; //get the corresponding dlg out structure for this REQ struct dlg_entry_out *dlg_entry_out = &dlg->dlg_entry_out; lock_get(dlg->dlg_out_entries_lock); dlg_out = dlg_entry_out->first; //TODO check for concurrent call if (!dlg_out) return; next_state_dlg(dlg, event, &old_state, &new_state, &unref, &dlg_out->to_tag); lock_release(dlg->dlg_out_entries_lock); if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) { LM_DBG("removing dialog with h_entry %u and h_id %u\n", dlg->h_entry, dlg->h_id); /* remove from timer */ ret = remove_dialog_timer(&dlg->tl); if (ret < 0) { LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] " "with clid '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s); } else if (ret > 0) { LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] " "with clid '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s); } else { unref++; } /* dialog terminated (BYE) */ run_dlg_callbacks(DLGCB_TERMINATED, dlg, ps->req, ps->rpl, DLG_DIR_NONE, 0); /* derefering the dialog */ unref_dlg(dlg, unref + 1); } if (new_state == DLG_STATE_DELETED && old_state == DLG_STATE_DELETED) { /* trash the dialog from DB and memory */ /* force delete from mem */ unref_dlg(dlg, 1); } }
static struct mi_root* mi_cc_list_agents(struct mi_root *cmd_tree, void *param) { struct cc_agent *agent; struct mi_root *rpl_tree; struct mi_node *node; struct mi_node *rpl; struct mi_attr *attr; str state; static str s_free={"free", 4}; static str s_wrapup={"wrapup", 6}; static str s_incall={"incall", 6}; char *p; int len; int i; rpl_tree = init_mi_tree( 200, MI_SSTR("OK") ); if ( rpl_tree==NULL) return NULL; rpl = &rpl_tree->node; /* block access to data */ lock_get( data->lock ); for(i=0; i< 2; i++) { for( agent=data->agents[i] ; agent ; agent=agent->next ) { node = add_mi_node_child( rpl, MI_DUP_VALUE, "Agent", 5, agent->id.s, agent->id.len ); if (node==NULL) goto error; p = int2str( (unsigned long)(agent->ref_cnt), &len); attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Ref"), p, len); if (attr==NULL) goto error; if(!agent->loged_in) attr = add_mi_attr( node, MI_DUP_VALUE, "Loged in", 8, "NO", 2); else { attr = add_mi_attr( node, MI_DUP_VALUE, "Loged in", 8, "YES", 3); if (attr==NULL) goto error; switch ( agent->state ) { case CC_AGENT_FREE: state = s_free; break; case CC_AGENT_WRAPUP: state = s_wrapup; break; case CC_AGENT_INCALL: state = s_incall; break; default: state.s =0; state.len = 0; } attr = add_mi_attr( node, MI_DUP_VALUE, "State", 5, state.s, state.len ); } if (attr==NULL) goto error; } } lock_release( data->lock ); return rpl_tree; error: lock_release( data->lock ); return 0; }
int update_contact(struct sip_msg* msg, char* str1, char* str2) { ua_pres_t* p, hentity; str contact; struct to_body *pto = NULL, TO = {0}, *pfrom = NULL; unsigned int hash_code; if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("when parsing headers\n"); return -1; } /* find the record */ if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); return -1; } if (!msg->from || !msg->from->body.s) { LM_ERR("cannot find 'from' header!\n"); return -1; } if (msg->from->parsed == NULL) { if ( parse_from_header( msg )<0 ) { LM_ERR("cannot parse From header\n"); return -1; } } 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"); return -1; } if( msg->to==NULL || msg->to->body.s==NULL) { LM_ERR("cannot parse TO header\n"); return -1; } 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_DBG("'To' header NOT parsed\n"); goto error; } pto = &TO; } if( pto->tag_value.s ==NULL || pto->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } hentity.watcher_uri= &pto->uri; hentity.pres_uri= &pfrom->uri; hentity.call_id= msg->callid->body; hentity.to_tag= pto->tag_value; hentity.from_tag= pfrom->tag_value; /* extract the contact */ if(msg->contact== NULL || msg->contact->body.s== NULL) { LM_ERR("no contact header found in 200 OK reply"); goto error; } contact= msg->contact->body; if (dbmode==PUA_DB_ONLY) { update_contact_puadb(&hentity, &contact ); free_to_params(&TO); return(1); } hash_code= core_hash(hentity.pres_uri,hentity.watcher_uri, HASH_SIZE); lock_get(&HashT->p_records[hash_code].lock); p= get_dialog(&hentity, hash_code); if(p== NULL) { lock_release(&HashT->p_records[hash_code].lock); LM_ERR("no record for the dialog found in hash table\n"); goto error; } shm_free(p->remote_contact.s); if(!(p->remote_contact.len== contact.len && strncmp(p->remote_contact.s, contact.s, contact.len)==0)) { /* update remote contact */ shm_free(p->remote_contact.s); p->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char)); if(p->remote_contact.s== NULL) { LM_ERR("no more shared memory\n"); lock_release(&HashT->p_records[hash_code].lock); goto error; } memcpy(p->remote_contact.s, contact.s, contact.len); p->remote_contact.len= contact.len; } lock_release(&HashT->p_records[hash_code].lock); free_to_params(&TO); return 1; error: free_to_params(&TO); return -1; }