/** * init module function */ static int mod_init(void) { LM_INFO("initializing...\n"); init_db_url( db_url , 0 /*cannot be null*/); db_table.len = strlen(db_table.s); sdomain_column.len = strlen(sdomain_column.s); prefix_column.len = strlen(prefix_column.s); domain_column.len = strlen(domain_column.s); prefix.len = strlen(prefix.s); pdt_char_list.len = strlen(pdt_char_list.s); if(pdt_char_list.len<=0) { LM_ERR("invalid pdt char list\n"); return -1; } LM_INFO("pdt_char_list=%s \n",pdt_char_list.s); /* binding to mysql module */ if(db_bind_mod(&db_url, &pdt_dbf)) { LM_ERR("database module not found\n"); return -1; } if (!DB_CAPABILITY(pdt_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 */ db_con = pdt_dbf.init(&db_url); if(db_con==NULL) { LM_ERR("failed to connect to the database\n"); return -1; } if (pdt_dbf.use_table(db_con, &db_table) < 0) { LM_ERR("failed to use_table\n"); goto error1; } LM_DBG("database connection opened successfully\n"); /* create & init lock */ if ((pdt_lock = lock_init_rw()) == NULL) { LM_CRIT("failed to init lock\n"); goto error1; } /* tree pointer in shm */ _ptree = (pdt_tree_t**)shm_malloc( sizeof(pdt_tree_t*) ); if (_ptree==0) { LM_ERR("out of shm mem for pdtree\n"); goto error1; } *_ptree=0; /* loading all information from database */ if(pdt_load_db()!=0) { LM_ERR("cannot load info from database\n"); goto error1; } pdt_dbf.close(db_con); db_con = 0; #if 0 pdt_print_tree(*_ptree); #endif /* success code */ return 0; error1: if (pdt_lock) { lock_destroy_rw( pdt_lock ); pdt_lock = 0; } if(_ptree!=0) shm_free(_ptree); if(db_con!=NULL) { pdt_dbf.close(db_con); db_con = 0; } return -1; }
/* * Record destination status * param code Destination status * param dest Destination */ static void ospRecordCode( int code, osp_dest* dest) { struct usr_avp* destmediaavp = NULL; int_str destmediaval; LM_DBG("code '%d'\n", code); dest->lastcode = code; switch (code) { case 100: if (!dest->time100) { dest->time100 = time(NULL); } else { LM_DBG("100 already recorded\n"); } break; case 180: case 181: case 182: case 183: if (!dest->time180) { dest->time180 = time(NULL); if (!dest->endtime) { dest->endtime = time(NULL); } else { LM_DBG("180, 181, 182 or 183 end allready recorded\n"); } } else { LM_DBG("180, 181, 182 or 183 allready recorded\n"); } break; case 200: case 202: if (!dest->time200) { dest->time200 = time(NULL); if ((_osp_destmedia_avpid >= 0) && ((destmediaavp = search_first_avp(_osp_destmedia_avptype, _osp_destmedia_avpid, &destmediaval, 0)) != NULL) && (destmediaavp->flags & AVP_VAL_STR) && (destmediaval.s.s && destmediaval.s.len)) { snprintf(dest->destmedia, sizeof(dest->destmedia), "%.*s", destmediaval.s.len, destmediaval.s.s); } else { dest->destmedia[0] = '\0'; } } else { LM_DBG("200 or 202 allready recorded\n"); } break; case 408: case 487: if (!dest->endtime) { dest->endtime = time(NULL); } else { LM_DBG("408 or 487 end allready recorded\n"); } break; default: /* It may overwrite existing end time, it is the expected behavior */ if ((code >= 400) && (code <= 699)) { dest->endtime = time(NULL); } } }
/* * Delete a row from table */ int dbt_delete(db1_con_t* _h, db_key_t* _k, db_op_t* _o, db_val_t* _v, int _n) { dbt_table_p _tbc = NULL; dbt_row_p _drp = NULL, _drp0 = NULL; int *lkey = NULL; if (!_h || !CON_TABLE(_h)) { LM_ERR("invalid parameters\n"); return -1; } /* lock database */ _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(!_tbc) { LM_ERR("failed to load table <%.*s>!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); return -1; } if(!_k || !_v || _n<=0) { LM_DBG("deleting all records\n"); dbt_table_free_rows(_tbc); /* unlock databse */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); return 0; } lkey = dbt_get_refs(_tbc, _k, _n); if(!lkey) goto error; _drp = _tbc->rows; while(_drp) { _drp0 = _drp->next; if(dbt_row_match(_tbc, _drp, lkey, _o, _v, _n)) { // delete row if(_drp->prev) (_drp->prev)->next = _drp->next; else _tbc->rows = _drp->next; if(_drp->next) (_drp->next)->prev = _drp->prev; _tbc->nrrows--; // free row dbt_row_free(_tbc, _drp); } _drp = _drp0; } dbt_table_update_flags(_tbc, DBT_TBFL_MODI, DBT_FL_SET, 1); /* dbt_print_table(_tbc, NULL); */ /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(lkey) pkg_free(lkey); return 0; error: /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); LM_ERR("failed to delete from table!\n"); return -1; }
static inline int oma_match_identity_condition(xmlNodePtr condition, subs_t *subs, str *w_uri) { int r = 0, many_match = 0; char *domain = NULL; str uri; str *normalized_uri; xmlNodePtr node = NULL, except_node = NULL; for(node = condition->children; node; node = node->next) { if(xmlStrcasecmp(node->name, (unsigned char*)"one") == 0) { uri.s = xmlNodeGetAttrContentByName(node, "id"); if(uri.s == NULL) { LM_ERR("when extracting entry attribute\n"); continue; } uri.len = strlen(uri.s); normalized_uri = normalizeSipUri(&uri); if (normalized_uri->s == NULL || normalized_uri->len == 0) { LM_ERR("normalizing URI\n"); xmlFree(uri.s); continue; } xmlFree(uri.s); if (normalized_uri->len == w_uri->len && strncmp(normalized_uri->s, w_uri->s, w_uri->len) == 0) { r = 1; break; } } else if(xmlStrcasecmp(node->name, (unsigned char*)"many") == 0) { domain = xmlNodeGetAttrContentByName(node, "domain"); if(domain == NULL) { LM_DBG("No domain attribute in identity many\n"); } else { LM_DBG("<many domain= %s>\n", domain); if(!(strlen(domain) == subs->from_domain.len && strncmp(domain, subs->from_domain.s, subs->from_domain.len) == 0)) { xmlFree(domain); continue; } xmlFree(domain); } many_match = 1; for(except_node = node->children; except_node; except_node= except_node->next) { if(xmlStrcasecmp(except_node->name, (unsigned char*)"except")) continue; uri.s = xmlNodeGetAttrContentByName(except_node, "id"); if(uri.s != NULL) { uri.len = strlen(uri.s); normalized_uri = normalizeSipUri(&uri); if (normalized_uri->s == NULL || normalized_uri->len == 0) { LM_ERR("normalizing URI\n"); xmlFree(uri.s); continue; } xmlFree(uri.s); if (normalized_uri->len == w_uri->len && strncmp(normalized_uri->s, w_uri->s, w_uri->len) == 0) { many_match = 0; break; } } else { domain = NULL; domain = xmlNodeGetAttrContentByName(except_node, "domain"); if(domain != NULL) { LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n", domain, (int)strlen(domain)); if(strlen(domain)==subs->from_domain.len && (strncmp(domain,subs->from_domain.s , subs->from_domain.len)==0)) { LM_DBG("except domain match\n"); xmlFree(domain); many_match = 0; break; } xmlFree(domain); } } } if(many_match) { r = 1; break; } } } return r; }
static void ietf_get_rules(subs_t* subs, xmlDocPtr xcap_tree, xcap_rule_t **rules) { str w_uri= {0, 0}; char* id = NULL, *domain = NULL, *time_cont= NULL; int apply_rule = -1; xmlNodePtr ruleset_node = NULL, node1= NULL, node2= NULL; xmlNodePtr cond_node = NULL, except_node = NULL; xmlNodePtr identity_node = NULL, sphere_node = NULL; xmlNodePtr iden_child; xmlNodePtr validity_node, time_node; time_t t_init, t_fin, t; int valid= 0; xcap_rule_t *rule = NULL; *rules = NULL; uandd_to_uri(subs->from_user, subs->from_domain, &w_uri); if(w_uri.s == NULL) { LM_ERR("while creating uri\n"); return; } ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL); if(ruleset_node == NULL) { LM_DBG("ruleset_node NULL\n"); goto error; } for(node1 = ruleset_node->children ; node1; node1 = node1->next) { if(xmlStrcasecmp(node1->name, (unsigned char*)"text")==0 ) continue; /* process conditions */ LM_DBG("node1->name= %s\n", node1->name); cond_node = xmlNodeGetChildByName(node1, "conditions"); if(cond_node == NULL) { LM_DBG("cond node NULL\n"); goto error; } LM_DBG("cond_node->name= %s\n", cond_node->name); validity_node = xmlNodeGetChildByName(cond_node, "validity"); if(validity_node !=NULL) { LM_DBG("found validity tag\n"); t= time(NULL); /* search all from-until pair */ for(time_node= validity_node->children; time_node; time_node= time_node->next) { if(xmlStrcasecmp(time_node->name, (unsigned char*)"from")!= 0) { continue; } time_cont= (char*)xmlNodeGetContent(time_node); t_init= xml_parse_dateTime(time_cont); xmlFree(time_cont); if(t_init< 0) { LM_ERR("failed to parse xml dateTime\n"); goto error; } if(t< t_init) { LM_DBG("the lower time limit is not respected\n"); continue; } time_node= time_node->next; while(1) { if(time_node== NULL) { LM_ERR("bad formatted xml doc:until child not found in" " validity pair\n"); goto error; } if( xmlStrcasecmp(time_node->name, (unsigned char*)"until")== 0) break; time_node= time_node->next; } time_cont= (char*)xmlNodeGetContent(time_node); t_fin= xml_parse_dateTime(time_cont); xmlFree(time_cont); if(t_fin< 0) { LM_ERR("failed to parse xml dateTime\n"); goto error; } if(t <= t_fin) { LM_DBG("the rule is active at this time\n"); valid= 1; } } if(!valid) { LM_DBG("the rule is not active at this time\n"); continue; } } sphere_node = xmlNodeGetChildByName(cond_node, "sphere"); if(sphere_node!= NULL) { /* check to see if matches presentity current sphere */ /* ask presence for sphere information */ char* sphere= pres_get_sphere(&subs->pres_uri); if(sphere) { char* attr= (char*)xmlNodeGetContent(sphere_node); if(xmlStrcasecmp((unsigned char*)attr, (unsigned char*)sphere)!= 0) { LM_DBG("sphere condition not respected\n"); pkg_free(sphere); xmlFree(attr); continue; } pkg_free(sphere); xmlFree(attr); } else { LM_DBG("Noo sphere definition found\n"); continue; } /* if the user has not define a sphere * consider the condition false*/ } identity_node = xmlNodeGetChildByName(cond_node, "identity"); if(identity_node == NULL) { LM_ERR("didn't find identity tag\n"); goto error; } iden_child= xmlNodeGetChildByName(identity_node, "one"); if(iden_child) { for(node2 = identity_node->children; node2; node2 = node2->next) { if(xmlStrcasecmp(node2->name, (unsigned char*)"one")!= 0) continue; id = xmlNodeGetAttrContentByName(node2, "id"); if(id== NULL) { LM_ERR("while extracting attribute\n"); goto error; } if((strlen(id)== w_uri.len && (strncmp(id, w_uri.s, w_uri.len)==0))) { apply_rule = 1; xmlFree(id); break; } xmlFree(id); } } /* search for many node*/ iden_child= xmlNodeGetChildByName(identity_node, "many"); if(iden_child) { domain = NULL; for(node2 = identity_node->children; node2; node2 = node2->next) { if(xmlStrcasecmp(node2->name, (unsigned char*)"many")!= 0) continue; domain = xmlNodeGetAttrContentByName(node2, "domain"); if(domain == NULL) { LM_DBG("No domain attribute to many\n"); } else { LM_DBG("<many domain= %s>\n", domain); if((strlen(domain)!= subs->from_domain.len && strncmp(domain, subs->from_domain.s, subs->from_domain.len) )) { xmlFree(domain); continue; } } xmlFree(domain); apply_rule = 1; if(node2->children == NULL) /* there is no exception */ break; for(except_node = node2->children; except_node; except_node= except_node->next) { if(xmlStrcasecmp(except_node->name, (unsigned char*)"except")) continue; id = xmlNodeGetAttrContentByName(except_node, "id"); if(id!=NULL) { if((strlen(id)- 1== w_uri.len && (strncmp(id, w_uri.s, w_uri.len)==0))) { xmlFree(id); apply_rule = 0; break; } xmlFree(id); } else { domain = NULL; domain = xmlNodeGetAttrContentByName(except_node, "domain"); if(domain!=NULL) { LM_DBG("Found except domain= %s\n- strlen(domain)= %d\n", domain, (int)strlen(domain)); if(strlen(domain)==subs->from_domain.len && (strncmp(domain,subs->from_domain.s , subs->from_domain.len)==0)) { LM_DBG("except domain match\n"); xmlFree(domain); apply_rule = 0; break; } xmlFree(domain); } } } if(apply_rule== 1) /* if a match was found no need to keep searching*/ break; } } if(apply_rule ==1) break; } LM_DBG("apply_rule= %d\n", apply_rule); if(w_uri.s!=NULL) pkg_free(w_uri.s); if( !apply_rule || !node1) return; rule = (xcap_rule_t *)pkg_malloc(sizeof(*rule)); if (rule == NULL) { LM_ERR("cannot allocate pkg_mem\n"); return; } /* TODO: in IETF mode only the first matching rule is returned */ rule->node = node1; rule->next = NULL; *rules = rule; return; error: if(w_uri.s) pkg_free(w_uri.s); }
static int _bm_register_timer(char *tname, int mode, unsigned int *id) { benchmark_timer_t *bmt = 0; benchmark_timer_t **tidx = 0; if(tname==NULL || id==NULL || bm_mycfg==NULL || strlen(tname)==0 || strlen(tname)>BM_NAME_LEN-1) return -1; bmt = bm_mycfg->timers; while(bmt) { if(strcmp(bmt->name, tname)==0) { *id = bmt->id; return 0; } bmt = bmt->next; } if(mode==0) return -1; bmt = (benchmark_timer_t*)shm_malloc(sizeof(benchmark_timer_t)); if(bmt==0) { LM_ERR("no more shm\n"); return -1; } memset(bmt, 0, sizeof(benchmark_timer_t)); bmt->lock = lock_alloc(); if(bmt->lock == NULL) { shm_free(bmt); LM_ERR("no more shm\n"); return -1; } if (!lock_init(bmt->lock)) { lock_dealloc(bmt->lock); shm_free(bmt); LM_ERR("failed to init lock\n"); return -1; } /* private memory, otherwise we have races */ bmt->start = (bm_timeval_t*)pkg_malloc(sizeof(bm_timeval_t)); if(bmt->start == NULL) { lock_dealloc(bmt->lock); shm_free(bmt); LM_ERR("no more pkg\n"); return -1; } memset(bmt->start, 0, sizeof(bm_timeval_t)); strcpy(bmt->name, tname); if(bm_mycfg->timers==0) { bmt->id = 0; bm_mycfg->timers = bmt; } else { bmt->id = bm_mycfg->timers->id+1; bmt->next = bm_mycfg->timers; bm_mycfg->timers = bmt; } /* do the indexing */ if(bmt->id%10==0) { if(bm_mycfg->tindex!=NULL) tidx = bm_mycfg->tindex; bm_mycfg->tindex = (benchmark_timer_t**)shm_malloc((10+bmt->id)* sizeof(benchmark_timer_t*)); if(bm_mycfg->tindex==0) { LM_ERR("no more share memory\n"); if(tidx!=0) shm_free(tidx); return -1; } memset(bm_mycfg->tindex, 0, (10+bmt->id)*sizeof(benchmark_timer_t*)); if(tidx!=0) { memcpy(bm_mycfg->tindex, tidx, bmt->id*sizeof(benchmark_timer_t*)); shm_free(tidx); } } bm_mycfg->tindex[bmt->id] = bmt; bm_mycfg->nrtimers = bmt->id + 1; reset_timer(bmt->id); *id = bmt->id; LM_DBG("timer [%s] added with index <%u>\n", bmt->name, bmt->id); return 0; }
/* first time it will called for a CALLER leg - at that time there will be no leg allocated, so automatically CALLER gets the first position, while the CALLEE legs will follow into the array in the same order they came */ int dlg_add_leg_info(struct dlg_cell *dlg, str* tag, str *rr, str *contact,str *cseq, struct socket_info *sock, str *mangled_from,str *mangled_to,str *sdp) { struct dlg_leg* leg,*new_legs; rr_t *head = NULL, *rrp; if ( (dlg->legs_no[DLG_LEGS_ALLOCED]-dlg->legs_no[DLG_LEGS_USED])==0) { new_legs = (struct dlg_leg*)shm_realloc(dlg->legs, (dlg->legs_no[DLG_LEGS_ALLOCED]+2)*sizeof(struct dlg_leg)); if (new_legs==NULL) { LM_ERR("Failed to resize legs array\n"); return -1; } dlg->legs=new_legs; dlg->legs_no[DLG_LEGS_ALLOCED] += 2; memset( dlg->legs+dlg->legs_no[DLG_LEGS_ALLOCED]-2, 0, 2*sizeof(struct dlg_leg)); } leg = &dlg->legs[ dlg->legs_no[DLG_LEGS_USED] ]; leg->tag.s = (char*)shm_malloc(tag->len); leg->r_cseq.s = (char*)shm_malloc( cseq->len ); if ( leg->tag.s==NULL || leg->r_cseq.s==NULL) { LM_ERR("no more shm mem\n"); if (leg->tag.s) shm_free(leg->tag.s); if (leg->r_cseq.s) shm_free(leg->r_cseq.s); return -1; } if (dlg->legs_no[DLG_LEGS_USED] == 0) { /* first leg = caller. also store inv cseq */ leg->inv_cseq.s = (char *)shm_malloc( cseq->len); if (leg->inv_cseq.s == NULL) { LM_ERR("no more shm mem\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); return -1; } } if (contact->len) { /* contact */ leg->contact.s = shm_malloc(rr->len + contact->len); if (leg->contact.s==NULL) { LM_ERR("no more shm mem\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); return -1; } leg->contact.len = contact->len; memcpy( leg->contact.s, contact->s, contact->len); /* rr */ if (rr->len) { leg->route_set.s = leg->contact.s + contact->len; leg->route_set.len = rr->len; memcpy( leg->route_set.s, rr->s, rr->len); if (parse_rr_body(leg->route_set.s,leg->route_set.len,&head) != 0) { LM_ERR("failed parsing route set\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); shm_free(leg->contact.s); return -1; } rrp = head; leg->nr_uris = 0; while (rrp) { leg->route_uris[leg->nr_uris++] = rrp->nameaddr.uri; rrp = rrp->next; } free_rr(&head); } } /* save mangled from URI, if any */ if (mangled_from && mangled_from->s && mangled_from->len) { leg->from_uri.s = shm_malloc(mangled_from->len); if (!leg->from_uri.s) { LM_ERR("no more shm\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); if (leg->contact.s) shm_free(leg->contact.s); return -1; } leg->from_uri.len = mangled_from->len; memcpy(leg->from_uri.s,mangled_from->s,mangled_from->len); } if (mangled_to && mangled_to->s && mangled_to->len) { leg->to_uri.s = shm_malloc(mangled_to->len); if (!leg->to_uri.s) { LM_ERR("no more shm\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); if (leg->contact.s) shm_free(leg->contact.s); if (leg->from_uri.s) shm_free(leg->from_uri.s); return -1; } leg->to_uri.len = mangled_to->len; memcpy(leg->to_uri.s,mangled_to->s,mangled_to->len); } /* TODO - consider late negociation here and when handling the first ACK */ if (dlg->legs_no[DLG_LEGS_USED] == 0 && sdp && sdp->s && sdp->len) { /* save this just for the caller leg here, for the callee leg we'll have to update anyway */ leg->sdp.s = shm_malloc(sdp->len); if (!leg->sdp.s) { LM_ERR("no more shm\n"); shm_free(leg->tag.s); shm_free(leg->r_cseq.s); if (leg->contact.s) shm_free(leg->contact.s); if (leg->from_uri.s) shm_free(leg->from_uri.s); return -1; } leg->sdp.len = sdp->len; memcpy(leg->sdp.s,sdp->s,sdp->len); } /* tag */ leg->tag.len = tag->len; memcpy( leg->tag.s, tag->s, tag->len); /* socket */ leg->bind_addr = sock; if (dlg->legs_no[DLG_LEGS_USED] == 0) { /* first leg = caller . store inv cseq */ leg->inv_cseq.len = cseq->len; memcpy(leg->inv_cseq.s,cseq->s,cseq->len); /* set cseq for caller to 0 * future requests to the caller leg will update this * needed for proper validation of in-dialog requests * * TM also increases this value by one, if dialog * is terminated from the middle, so 0 is ok*/ leg->r_cseq.len = 1; leg->r_cseq.s[0]='0'; } else { /* cseq */ leg->r_cseq.len = cseq->len; memcpy( leg->r_cseq.s, cseq->s, cseq->len); } /* make leg visible for searchers */ dlg->legs_no[DLG_LEGS_USED]++; LM_DBG("set leg %d for %p: tag=<%.*s> rcseq=<%.*s>\n", dlg->legs_no[DLG_LEGS_USED]-1, dlg, leg->tag.len,leg->tag.s, leg->r_cseq.len,leg->r_cseq.s ); return 0; }
/** * Initialize the database module. * No function should be called before this * \param _url URL used for initialization * \return zero on success, negative value on failure */ db1_con_t* erlang_srdb1_init(const str* _url) { LM_DBG("erlang_srdb1_init %.*s \n", _url->len, _url->s); return db_do_init(_url, (void *)erlang_srdb1_new_connection); }
//temporary void erlang_srdb1_free_connection(struct erlang_connection* con) { LM_DBG("erlang_free_connection %p \n",con); free_db_id(con->hdr.id); pkg_free(con); return; }
/** * Query a table for specified rows. * \param _h structure representing database connection * \param _k key names * \param _op operators *\param _v values of the keys that must match * \param _c column names to return * \param _n number of key=values pairs to compare * \param _nc number of columns to return * \param _o order by the specified column * \param _r pointer to a structure representing the result * \return zero on success, negative value on failure */ int erlang_srdb1_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, const db_key_t* _c, const int _n, const int _nc, const db_key_t _o, db1_res_t** _r) { ei_x_buff argbuf,retbuf; int retcode,i,j,x; int n_cols,n_rows,len; db1_res_t *res; db_row_t *rows = NULL, *row; db_val_t *val; char atom[MAXATOMLEN], *p; ei_term term; int ei_type,size; str *sname; if (!_h || !_r) { LM_ERR("invalid parameter value\n"); return -1; } *_r=NULL; LM_DBG("erlang_srdb1_query table %.*s\n",CON_TABLE(_h)->len, CON_TABLE(_h)->s); ei_x_new(&argbuf); //encode tuple {db_op, table, [cols], [params]} ei_x_encode_tuple_header(&argbuf, 5); ei_x_encode_atom(&argbuf,"select"); ei_x_encode_atom_len(&argbuf,CON_TABLE(_h)->s,CON_TABLE(_h)->len); srdb1_encode_c(_c, _nc, &argbuf); srdb1_encode_k(_k, _op, _v, _n, &argbuf); // ei_x_encode_atom_len(&argbuf,_o->s,_o->len); ei_x_encode_list_header(&argbuf, 0); retcode=erl_bind.do_erlang_call(&(CON_ERLANG(_h)->con),&(CON_ERLANG(_h)->regname), &argbuf, &retbuf); ei_x_free(&argbuf); if (retcode<0) { if(retbuf.buff) shm_free(retbuf.buff); return retcode; } // we have a tuple there: ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &i); x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of field list should be %d\n",x); //first is list of 5-element tuples containing name and type of field ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_cols); LM_DBG("erlang_srdb1_query: length -f field_list is %d\n",n_cols); res=db_new_result(); if (db_allocate_columns(res, n_cols) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_columns failed\n"); goto error; } RES_COL_N(res) = n_cols; for(i=0; i < n_cols; i++) { x=retbuf.index; ei_skip_term(retbuf.buff, &x); LM_DBG("erlang_srdb1_query: position of end of this field should be %d\n",x); ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if( j!=5) LM_ERR("erlang_srdb1_query name&type list element tuple is not 5\n"); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //1 name len=strlen(atom); sname = (str*)pkg_malloc(sizeof(str)+len+1); if (!sname) { LM_ERR("no private memory left\n"); goto error; } sname->len = len; sname->s = (char*)sname + sizeof(str); memcpy(sname->s, atom, len); sname->s[len] = '\0'; RES_NAMES(res)[i] = sname; LM_DBG("decoded header %d, fieled 1: %s\n",i,atom); ei_decode_atom(retbuf.buff, &(retbuf.index), atom); //2 type atom if(strcmp("int",atom)==0) { RES_TYPES(res)[i]=DB1_INT; } if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_STRING; } if(strcmp("float",atom)==0) { RES_TYPES(res)[i]=DB1_DOUBLE; } if(strcmp("datetime",atom)==0) { RES_TYPES(res)[i]=DB1_DATETIME; } // if(strcmp("string",atom)==0) { RES_TYPES(res)[i]=DB1_BLOB; } ei_skip_term(retbuf.buff, &(retbuf.index)); //3 size (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //4 default value (ignored) ei_skip_term(retbuf.buff, &(retbuf.index)); //3 null status (ignored) LM_DBG("end of %d record: %d\n",i,retbuf.index); } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, LM_DBG("erlang_srdb1_query: position after scanning is %d\n",retbuf.index); //now rows, list of tuples ei_decode_list_header(retbuf.buff, &(retbuf.index), &n_rows); LM_DBG("erlang_srdb1_query values list size is %d\n",n_rows); if (n_rows<=0) { LM_DBG("erlang_srdb1_query no rows returned\n"); RES_ROWS(res) = NULL; RES_NUM_ROWS(res)=0; *_r=res; return 0; } RES_NUM_ROWS(res)=n_rows; rows = pkg_realloc(rows, sizeof(db_row_t) * n_rows); if (rows == NULL) { LM_ERR("erlang_srdb1_query: pkg_realloc rows failed\n"); goto error; } RES_ROWS(res) = rows; for(i=0; i < n_rows; i++) { RES_ROW_N(res)=i+1; row = &RES_ROWS(res)[i]; if (db_allocate_row(res, row) != 0) { LM_ERR("erlang_srdb1_query: db_allocate_row failed for row %d\n",i); goto error; } ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &j); if(j!=n_cols) { LM_ERR("erlang_srdb1_query: mismatch:values list element tuple size is %d n_cols from header was %d\n",j, n_cols); } for (j = 0, val = ROW_VALUES(row); j < RES_COL_N(res); j++, val++) { VAL_TYPE(val) = RES_TYPES(res)[j]; VAL_NULL(val) = 0; VAL_FREE(val) = 0; retcode=ei_get_type_internal(retbuf.buff, &(retbuf.index), &ei_type, &size); if (retcode < 0) { LM_ERR("erlang_srdb1_query: error getting type for element %d %d\n",i,j); goto error; } LM_DBG("erlang_srdb1_query: element %d %d ei_type=%d size=%d\n",i,j,ei_type, size); switch(ei_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: retcode=ei_decode_long(retbuf.buff, &(retbuf.index), &VAL_INT(val)); if(retcode < 0) goto error; LM_DBG("decoded interger %d\n",VAL_INT(val)); break; case ERL_FLOAT_EXT: case NEW_FLOAT_EXT: retcode=ei_decode_double(retbuf.buff, &(retbuf.index), &VAL_DOUBLE(val)); if(retcode < 0) goto error; LM_DBG("decoded float %f\n",VAL_DOUBLE(val)); break; case ERL_ATOM_EXT: case ERL_SMALL_ATOM_EXT: case ERL_ATOM_UTF8_EXT: case ERL_SMALL_ATOM_UTF8_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_atom(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded small_atom_utf %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_STRING_EXT: p=pkg_malloc(size+1); if(!p) { LM_ERR("erlang_srdb1_query: no memory\n"); goto error; } retcode=ei_decode_string(retbuf.buff, &(retbuf.index), p); if(retcode < 0) { pkg_free(p); goto error; } LM_DBG("decoded string %s\n",p); VAL_STRING(val)=p; VAL_FREE(val)=1; break; case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: LM_DBG("got tuple)\n"); if (VAL_TYPE(val)==DB1_DATETIME) { struct tm tm; LM_DBG("and col type is datetime\n"); retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_year);tm.tm_year -=1900; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mon); tm.tm_mon -=1; if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_mday); if(retcode < 0) goto error; retcode=ei_decode_tuple_header(retbuf.buff, &(retbuf.index), &x); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_hour); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_min); if(retcode < 0) goto error; retcode=ei_decode_long(retbuf.buff, &(retbuf.index), (long int *)&tm.tm_sec); if(retcode < 0) goto error; VAL_TIME(val)=mktime(&tm); break; } LM_ERR("erlang_srdb1_query: got tuple but valtype is not datetime element %d in row %d in response\n",j,i); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: case ERL_PORT_EXT: case ERL_PID_EXT: case ERL_NIL_EXT: case ERL_LIST_EXT: case ERL_BINARY_EXT: case ERL_SMALL_BIG_EXT: case ERL_LARGE_BIG_EXT: case ERL_NEW_FUN_EXT: case ERL_FUN_EXT: default: LM_ERR("erlang_srdb1_query: don't know how to handle element %d in row %d in response\n",j,i); } } } ei_decode_ei_term(retbuf.buff, &(retbuf.index), &term); // List tail, *_r=res; return 0; error: if (res) db_free_result(res); LM_ERR("erlang_srdb1_query: Failed\n"); return -1; }
/** * Store the name of table that will be used by subsequent database functions * \param _h database handle * \param _t table name * \return zero on success, negative value on failure */ int erlang_srdb1_use_table(db1_con_t* _h, const str* _t) { LM_DBG("erlang_srdb1_use_table %.*s\n", _t->len, _t->s); return db_use_table(_h, _t); }
/** * "pdt_delete" syntax: * sdomain * domain */ struct mi_root* pdt_mi_delete(struct mi_root* cmd_tree, void* param) { str sd, sdomain; struct mi_node* node= NULL; db_key_t db_keys[2] = {&sdomain_column, &domain_column}; db_val_t db_vals[2]; db_op_t db_ops[2] = {OP_EQ, OP_EQ}; /* read sdomain */ node = cmd_tree->node.kids; if(node == NULL) goto error; sdomain = node->value; if(sdomain.s == NULL || sdomain.len== 0) return init_mi_tree( 404, "domain not found", 16); if( *sdomain.s=='.' ) return init_mi_tree( 400, "400 empty param",11); /* read domain */ node= node->next; if(node == NULL || node->next!=NULL) goto error; sd= node->value; if(sd.s== NULL || sd.len==0) { LM_ERR("could not read domain\n"); return init_mi_tree(404, "domain not found", 16); } if(*sd.s=='.') return init_mi_tree( 400, "empty param", 11); db_vals[0].type = DB_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = sdomain.s; db_vals[0].val.str_val.len = sdomain.len; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = sd.s; db_vals[1].val.str_val.len = sd.len; if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, 2)<0) { LM_ERR("database/cache are inconsistent\n"); return init_mi_tree( 500, "database/cache are inconsistent", 31 ); } /* re-loading all information from database */ if(pdt_load_db()!=0) { LM_ERR("cannot re-load info from database\n"); return init_mi_tree( 500, "cannot reload", 13 ); } LM_DBG("prefix for sdomain [%.*s] domain [%.*s] " "removed\n", sdomain.len, sdomain.s, sd.len, sd.s); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); error: return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); }
/** * "pdt_add" syntax : * sdomain * prefix * domain */ struct mi_root* pdt_mi_add(struct mi_root* cmd_tree, void* param) { db_key_t db_keys[NR_KEYS] = {&sdomain_column, &prefix_column, &domain_column}; db_val_t db_vals[NR_KEYS]; db_op_t db_ops[NR_KEYS] = {OP_EQ, OP_EQ}; int i= 0; str sd, sp, sdomain; struct mi_node* node= NULL; if(_ptree==NULL) { LM_ERR("strange situation\n"); return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN); } /* read sdomain */ node = cmd_tree->node.kids; if(node == NULL) goto error1; sdomain = node->value; if(sdomain.s == NULL || sdomain.len== 0) return init_mi_tree( 404, "domain not found", 16); if(*sdomain.s=='.' ) return init_mi_tree( 400, "empty param",11); /* read prefix */ node = node->next; if(node == NULL) goto error1; sp= node->value; if(sp.s== NULL || sp.len==0) { LM_ERR("could not read prefix\n"); return init_mi_tree( 404, "prefix not found", 16); } if(*sp.s=='.') return init_mi_tree(400, "empty param", 11); while(i< sp.len) { if(strpos(pdt_char_list.s,sp.s[i]) < 0) return init_mi_tree(400, "bad prefix", 10); i++; } /* read domain */ node= node->next; if(node == NULL || node->next!=NULL) goto error1; sd= node->value; if(sd.s== NULL || sd.len==0) { LM_ERR("could not read domain\n"); return init_mi_tree( 400, "domain not found", 16); } if(*sd.s=='.') return init_mi_tree(400, "empty param", 11); if(pdt_check_domain!=0 && *_ptree!=NULL && pdt_check_pd(*_ptree, &sdomain, &sp, &sd)==1) { LM_ERR("(sdomain,prefix,domain) exists\n"); return init_mi_tree(400, "(sdomain,prefix,domain) exists already", 38); } db_vals[0].type = DB_STR; db_vals[0].nul = 0; db_vals[0].val.str_val.s = sdomain.s; db_vals[0].val.str_val.len = sdomain.len; db_vals[1].type = DB_STR; db_vals[1].nul = 0; db_vals[1].val.str_val.s = sp.s; db_vals[1].val.str_val.len = sp.len; db_vals[2].type = DB_STR; db_vals[2].nul = 0; db_vals[2].val.str_val.s = sd.s; db_vals[2].val.str_val.len = sd.len; /* insert a new domain into database */ if(pdt_dbf.insert(db_con, db_keys, db_vals, NR_KEYS)<0) { LM_ERR("failed to store new prefix/domain\n"); return init_mi_tree( 500,"Cannot store prefix/domain", 26); } /* re-loading all information from database */ if(pdt_load_db()!=0) { LM_ERR("cannot re-load info from database\n"); goto error; } LM_DBG("new prefix added %.*s-%.*s => %.*s\n", sdomain.len, sdomain.s, sp.len, sp.s, sd.len, sd.s); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); error: if(pdt_dbf.delete(db_con, db_keys, db_ops, db_vals, NR_KEYS)<0) LM_ERR("database/cache are inconsistent\n"); return init_mi_tree( 500, "could not add to cache", 23 ); error1: return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); }
/* change the r-uri if it is a PSTN format */ static int prefix2domain(struct sip_msg* msg, int mode, int sd_en) { str *d, p, all={"*",1}; int plen; struct sip_uri uri; if(msg==NULL) { LM_ERR("received null msg\n"); return -1; } /* parse the uri, if not yet */ if(msg->parsed_uri_ok==0) if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the R-URI\n"); return -1; } /* if the user part begin with the prefix for PSTN users, extract the code*/ if (msg->parsed_uri.user.len<=0) { LM_DBG("user part of the message is empty\n"); return -1; } if(prefix.len>0) { if (msg->parsed_uri.user.len<=prefix.len) { LM_DBG("user part is less than prefix\n"); return -1; } if(strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } } if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len && strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } p.s = msg->parsed_uri.user.s + prefix.len; p.len = msg->parsed_uri.user.len - prefix.len; lock_start_read( pdt_lock ); if(sd_en==2) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } } else if(sd_en==1) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("ERROR cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } else { /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } /* update the new uri */ if(update_new_uri(msg, plen, d, mode)<0) { LM_ERR("new_uri cannot be updated\n"); goto error; } lock_stop_read( pdt_lock ); return 1; error: lock_stop_read( pdt_lock ); return -1; }
/*! * \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) { dlg_cell_t *dlg = NULL; dlg_iuid_t *iuid = NULL; int new_state, old_state, unref, event; str tag; sip_msg_t *req = param->req; sip_msg_t *rpl = param->rpl; if (shutdown_done) return; iuid = (dlg_iuid_t*)(*param->param); dlg = dlg_get_by_iuid(iuid); if(dlg==0) return; unref = 0; if (type & (TMCB_RESPONSE_IN|TMCB_ON_FAILURE)) { /* Set the dialog context so it is available in onreply_route and failure_route*/ set_current_dialog(req, dlg); dlg_set_ctx_iuid(dlg); goto done; } if (type==TMCB_RESPONSE_FWDED) { /* The state does not change, but the msg is mutable in this callback*/ run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); goto done; } 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; next_state_dlg( dlg, event, &old_state, &new_state, &unref); dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state); if (new_state==DLG_STATE_EARLY) { run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); if (old_state!=DLG_STATE_EARLY) if_update_stat(dlg_enable_stats, early_dlgs, 1); goto done; } if (new_state==DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) { LM_DBG("dialog %p confirmed (ACK pending)\n",dlg); if (rpl != FAKED_REPLY) { /* get to tag*/ if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0) || !rpl->to) ) { LM_ERR("bad reply or missing TO hdr :-/\n"); tag.s = 0; tag.len = 0; } else { tag = get_to(rpl)->tag_value; if (tag.s==0 || tag.len==0) { LM_ERR("missing TAG param in TO hdr :-/\n"); tag.s = 0; tag.len = 0; } } /* save callee's tag, cseq, contact and record route*/ if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) { LM_ERR("could not add further info to the dialog\n"); } } else { LM_ERR("Faked reply!\n"); } /* 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 ( dlg_db_mode==DB_MODE_REALTIME ) update_dialog_dbinfo(dlg); 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' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state, dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); } else { /* dialog pointer inserted in timer list */ dlg_ref(dlg, 1); } /* dialog confirmed (ACK pending) */ run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0); if (old_state==DLG_STATE_EARLY) if_update_stat(dlg_enable_stats, early_dlgs, -1); if (unref) dlg_unref(dlg, unref); if_update_stat(dlg_enable_stats, active_dlgs, 1); goto done; } if(new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { /* set end time */ dlg->end_ts = (unsigned int)(time(0)); } if ( new_state==DLG_STATE_DELETED && (old_state==DLG_STATE_UNCONFIRMED || old_state==DLG_STATE_EARLY) ) { 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); if(dlg_wait_ack==1) dlg_set_tm_waitack(t, dlg); /* do unref */ if (unref) dlg_unref(dlg, unref); if (old_state==DLG_STATE_EARLY) if_update_stat(dlg_enable_stats, early_dlgs, -1); if_update_stat(dlg_enable_stats, failed_dlgs, 1); goto done; } if (unref) dlg_unref(dlg, unref); done: /* unref due to dlg_get_by_iuid() */ dlg_release(dlg); return; }
/** * Shut down the database module. * No function should be called after this * \param _h handle to the closed connection * \return zero on success, negative value on failure */ void erlang_srdb1_close(db1_con_t* _h) { LM_DBG("erlang_erlang_srdb1_close %p \n",_h); db_do_close(_h, erlang_srdb1_free_connection); }
/*! * \brief Create a new dialog from a sip message * * Create a new dialog from a SIP message, register a callback * to keep track of the dialog with help of the tm module. * This function is either called from the request callback, or * from the dlg_manage function in the configuration script. * \see dlg_onreq * \see w_dlg_manage * \param req SIP message * \param t transaction * \param run_initial_cbs if set zero, initial callbacks are not executed * \return 0 on success, -1 on failure */ int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs) { dlg_cell_t *dlg; str s; str callid; str ftag; str ttag; str req_uri; unsigned int dir; dlg = dlg_get_ctx_dialog(); if(dlg != NULL) { dlg_release(dlg); return -1; } if(req->first_line.u.request.method_value != METHOD_INVITE) return -1; if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) { LM_WARN("pre-matching failed\n"); return -1; } if(ttag.s!=0 && ttag.len!=0) return -1; if(pv_printf_s(req, ruri_param_model, &req_uri)<0) { LM_ERR("error - cannot print the r-uri format\n"); return -1; } trim(&req_uri); dir = DLG_DIR_NONE; /* search dialog by SIP attributes * - hash table slot is left locked */ dlg = dlg_search(&callid, &ftag, &ttag, &dir); if(dlg) { if (detect_spirals) { if (spiral_detected == 1) { dlg_hash_release(&callid); return 0; } if ( dlg->state != DLG_STATE_DELETED ) { LM_DBG("Callid '%.*s' found, must be a spiraled request\n", callid.len, callid.s); spiral_detected = 1; if (run_initial_cbs) run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0); /* set ctx dlg id shortcuts */ _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; /* search_dlg() has incremented the ref count by 1 */ dlg_release(dlg); dlg_hash_release(&callid); return 0; } dlg_release(dlg); } } spiral_detected = 0; dlg = build_new_dlg (&callid /*callid*/, &(get_from(req)->uri) /*from uri*/, &(get_to(req)->uri) /*to uri*/, &ftag/*from_tag*/, &req_uri /*r-uri*/ ); if (dlg==0) { dlg_hash_release(&callid); LM_ERR("failed to create new dialog\n"); return -1; } /* save caller's tag, cseq, contact and record route*/ if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG, &(get_from(req)->tag_value)) !=0) { dlg_hash_release(&callid); LM_ERR("could not add further info to the dialog\n"); shm_free(dlg); return -1; } /* Populate initial varlist: */ dlg->vars = get_local_varlist_pointer(req, 1); /* after dlg_search() slot was kept locked */ link_dlg(dlg, 0, 1); /* unlock after dlg_search() */ dlg_hash_release(&callid); dlg->lifetime = get_dlg_timeout(req); s.s = _dlg_ctx.to_route_name; s.len = strlen(s.s); dlg_set_toroute(dlg, &s); dlg->sflags |= _dlg_ctx.flags; dlg->iflags |= _dlg_ctx.iflags; if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0) dlg->iflags |= DLG_IFLAG_TIMEOUTBYE; if (run_initial_cbs) run_create_callbacks( dlg, req); /* first INVITE seen (dialog created, unconfirmed) */ if ( seq_match_mode!=SEQ_MATCH_NO_ID && add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) { LM_ERR("failed to add RR param\n"); goto error; } if_update_stat( dlg_enable_stats, processed_dlgs, 1); _dlg_ctx.cpid = my_pid(); _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; set_current_dialog(req, dlg); return 0; error: if (!spiral_detected) dlg_unref(dlg, 1); // undo ref regarding linking return -1; }
pcontact_t * getContactP(struct sip_msg* _m, udomain_t* _d, enum pcontact_reg_states reg_state, char service_routes[][MAXROUTESIZE], int num_service_routes) { ppublic_t * p; contact_body_t *b = 0; contact_t *ct; pcontact_info_t search_ci; str received_host = {0, 0}; char srcip[50]; struct via_body *vb; unsigned short port, proto; str host; sip_uri_t contact_uri; int mustRetryViaSearch = 0; int mustRetryReceivedSearch = 0; LM_DBG("number of service routes to look for is %d\n", num_service_routes); b = cscf_parse_contacts(_m); if (_m->first_line.type == SIP_REPLY && _m->contact && _m->contact->parsed && b->contacts) { mustRetryViaSearch = 1; mustRetryReceivedSearch = 1; LM_DBG("This is a reply - to look for contact we favour the contact header above the via (b2bua)... if no contact we will use last via\n"); ct = b->contacts; host = ct->uri; if (parse_uri(ct->uri.s, ct->uri.len, &contact_uri) != 0) { LM_WARN("Failed to parse contact [%.*s]\n", ct->uri.len, ct->uri.s); return NULL; } host = contact_uri.host; port = contact_uri.port_no ? contact_uri.port_no : 5060; proto = contact_uri.proto; if (proto == 0) { LM_DBG("Contact protocol not specified - using received\n"); proto = _m->rcv.proto; } } else { if (_m->first_line.type == SIP_REPLY) LM_DBG("This is a reply but we are forced to use the via header\n"); else LM_DBG("This is a request - using first via to find contact\n"); vb = cscf_get_ue_via(_m); host = vb->host; port = vb->port ? vb->port : 5060; proto = vb->proto; } LM_DBG("searching for contact with host:port:proto contact [%d://%.*s:%d]\n", proto, host.len, host.s, port); received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof (srcip)); received_host.s = srcip; // if (_m->id != current_msg_id) { current_msg_id = _m->id; c = NULL; //search_ci.reg_state = PCONTACT_REGISTERED; //we can do this because this function is always called expecting a REGISTERED contact memset(&search_ci, 0, sizeof(struct pcontact_info)); search_ci.reg_state = reg_state; search_ci.received_host.s = received_host.s; search_ci.received_host.len = received_host.len; search_ci.received_port = _m->rcv.src_port; search_ci.received_proto = _m->rcv.proto; search_ci.searchflag = SEARCH_RECEIVED; search_ci.num_service_routes = 0; if (is_registered_fallback2ip == 1) { search_ci.searchflag = SEARCH_NORMAL; } search_ci.via_host = host; search_ci.via_port = port; search_ci.via_prot = proto; search_ci.aor.s = 0; search_ci.aor.len = 0; int size = num_service_routes==0?1:num_service_routes; str s_service_routes[size]; int i; for (i=0;i<num_service_routes;i++) { s_service_routes[i].s = service_routes[i]; s_service_routes[i].len = strlen(service_routes[i]); LM_DBG("Setting service routes str for pos %d to %.*s", i, s_service_routes[i].len, s_service_routes[i].s); } if (num_service_routes > 0) { LM_DBG("asked to search for specific service routes...\n"); search_ci.service_routes = s_service_routes; search_ci.num_service_routes = num_service_routes; search_ci.extra_search_criteria = SEARCH_SERVICE_ROUTES; } // b = cscf_parse_contacts(_m); tryagain: if (b && b->contacts) { for (ct = b->contacts; ct; ct = ct->next) { search_ci.aor = ct->uri; if (ul.get_pcontact(_d, &search_ci, &c) == 0) { if (checkcontact(_m, c) != 0) { c = NULL; } else { break; } } } } else { LM_WARN("No contact-header found...\n"); } if ((c == NULL) && (is_registered_fallback2ip == 1)) { LM_INFO("Contact not found based on Contact-header, trying IP/Port/Proto\n"); // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); // received_host.s = srcip; search_ci.searchflag = SEARCH_RECEIVED; if (ul.get_pcontact(_d, &search_ci, &c) == 1) { LM_DBG("No entry in usrloc for %.*s:%i (Proto %i) found!\n", received_host.len, received_host.s, _m->rcv.src_port, _m->rcv.proto); } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } if ((c == NULL) && (is_registered_fallback2ip == 2)) { LM_INFO("Contact not found based on IP/Port/Proto, trying Contact-header\n"); search_ci.searchflag = SEARCH_NORMAL; if (ul.get_pcontact(_d, &search_ci, &c) == 1) { } else { if (checkcontact(_m, c) != 0) { c = NULL; } } } asserted_identity = NULL; registration_contact = NULL; if (c) { LM_DBG("Trying to set asserted identity field"); registration_contact = &c->contact_user; p = c->head; while (p) { LM_DBG("Checking through contact users"); if (p->is_default == 1) { LM_DBG("Found default contact user so setting asserted identity"); asserted_identity = &p->public_identity; } p = p->next; } } if (asserted_identity != NULL && asserted_identity->len > 0) { LM_DBG("Have set the asserted_identity param to [%.*s]\n", asserted_identity->len, asserted_identity->s); } else { LM_DBG("Asserted identity not set"); } // LM_DBG("pcontact flag is [%d]\n", c->flags); // if (c && (c->flags & (1<<FLAG_READFROMDB)) != 0) { // LM_DBG("we have a contact that was read fresh from the DB....\n"); // } if (!c && mustRetryViaSearch) { LM_DBG("This is a reply so we will search using the last via once more...\n"); vb = cscf_get_ue_via(_m); search_ci.via_host = vb->host; search_ci.via_port = vb->port ? vb->port : 5060; search_ci.via_prot = vb->proto; mustRetryViaSearch = 0; goto tryagain; } if (!c && mustRetryReceivedSearch) { LM_DBG("This is a reply and we still don't have a match - will try src ip/port of message\n"); search_ci.via_host = received_host; search_ci.via_port = _m->rcv.src_port; search_ci.via_prot = _m->rcv.proto; mustRetryReceivedSearch = 0; goto tryagain; } return c; }
/* * IMPORTANT: if a dialog reference is returned, the dialog hash entry will be kept locked when this function returns NOTE: if a reply tree is returned, no dialog reference is returned. */ static inline struct mi_root* process_mi_params(struct mi_root *cmd_tree, struct dlg_cell **dlg_p, unsigned int *idx, unsigned int *cnt) { struct mi_node* node; struct dlg_entry *d_entry; struct dlg_cell *dlg; str *p1; str *p2; unsigned int h_entry; node = cmd_tree->node.kids; if (node == NULL) { /* no parameters at all */ *dlg_p = NULL; *idx = *cnt = 0; return NULL; } /* we have params -> get p1 and p2 */ p1 = &node->value; LM_DBG("p1='%.*s'\n", p1->len, p1->s); node = node->next; if ( !node || !node->value.s || !node->value.len) { p2 = NULL; } else { p2 = &node->value; LM_DBG("p2='%.*s'\n", p2->len, p2->s); if ( node->next!=NULL ) return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); } /* check the params */ if (p2 && str2int(p1,idx)==0 && str2int(p2,cnt)==0) { /* 2 numerical params -> index and counter */ *dlg_p = NULL; return NULL; } *idx = *cnt = 0; if (!p1->s) return init_mi_tree( 400, "Invalid Call-ID specified", 25); h_entry = dlg_hash( p1/*callid*/ ); 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, p1/*callid*/, p2/*from_tag*/)==1) { if (dlg->state==DLG_STATE_DELETED) { *dlg_p = NULL; break; } else { *dlg_p = dlg; return 0; } } } dlg_unlock( d_table, d_entry); return init_mi_tree( 404, MI_SSTR("No such dialog")); }
/** * Check, if a user-agent follows the indicated service-routes */ int check_service_routes(struct sip_msg* _m, udomain_t* _d) { struct sip_uri uri; int i; struct hdr_field *hdr; rr_t *r; char routes[MAXROUTES][MAXROUTESIZE]; unsigned int num_routes = 0; struct via_body * vb; unsigned short port; unsigned short proto; /* Contact not found => not following service-routes */ // if (c == NULL) return -1; /* Search for the first Route-Header: */ if (find_first_route(_m) < 0) return -1; // LM_DBG("Got %i Route-Headers.\n", c->num_service_routes); vb = cscf_get_ue_via(_m); port = vb->port?vb->port:5060; proto = vb->proto; /* Lock this record while working with the data: */ ul.lock_udomain(_d, &vb->host, port, proto); if (_m->route) { hdr = _m->route; r = (rr_t*)hdr->parsed; //get rid of ourselves from route header if (r) { LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0) && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) { LM_DBG("Self\n"); /* Check for more headers and fail, if it was the last one Check, if service-routes are indicated. If yes, request is not following service-routes */ if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; LM_DBG("hdr is %p\n", hdr); LM_DBG("r is %p\n", r); if (r) LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); } int i = 0; while (r) { memset(routes[i],0,MAXROUTESIZE); memcpy(routes[i], r->nameaddr.uri.s, r->nameaddr.uri.len); if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; i += 1; num_routes += 1; } LM_DBG("num_routes is %d\n", num_routes); for (i=0; i<num_routes; i++) { LM_DBG("route %d for checking is %s\n", i, routes[i]); } pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, routes, num_routes); if (!c) { LM_DBG("no contact found in usrloc when checking for service route\n"); goto error; } LM_DBG("we have a contact which satisifes the routes...\n"); ul.unlock_udomain(_d, &vb->host, port, proto); return 1; } } else { LM_DBG("Request doesn't have any route headers to check service-route...ignoring\n"); goto error; } pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED, 0, 0); if (!c) { LM_DBG("no contact found in usrloc when checking for service route\n"); goto error; } /* Check the route-set: */ if (_m->route) { hdr = _m->route; LM_DBG("hdr is %p\n", hdr); /* Check, if the first host is ourself: */ r = (rr_t*)hdr->parsed; if (r) { LM_DBG("Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Skip first headers containing myself: */ while (r && (parse_uri(r->nameaddr.uri.s, r->nameaddr.uri.len, &uri) == 0) && check_self(&uri.host,uri.port_no?uri.port_no:SIP_PORT,0)) { LM_DBG("Self\n"); /* Check for more headers and fail, if it was the last one Check, if service-routes are indicated. If yes, request is not following service-routes */ if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; if (!r && (c->num_service_routes > 0)) { LM_DBG("Not enough route-headers in Message\n"); goto error; } LM_DBG("hdr is %p\n", hdr); LM_DBG("r is %p\n", r); if (r) LM_DBG("Next Route is %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); } LM_DBG("We have %d service-routes\n", c->num_service_routes); /* Then check the following headers: */ for (i=0; i< c->num_service_routes; i++) { LM_DBG("Route must be: %.*s\n", c->service_routes[i].len, c->service_routes[i].s); /* No more Route-Headers? Not following service-routes */ if (!r) { LM_DBG("No more route headers in message.\n"); goto error; } LM_DBG("Route is: %.*s\n", r->nameaddr.uri.len, r->nameaddr.uri.s); /* Check length: */ if (r->nameaddr.uri.len != c->service_routes[i].len) { LM_DBG("Length does not match.\n"); goto error; } /* Check contents: */ if (strncasecmp(r->nameaddr.uri.s, c->service_routes[i].s, c->service_routes[i].len) != 0) { LM_DBG("String comparison failed.\n"); goto error; } if (find_next_route(_m, &hdr) != 0) r = NULL; else r = (rr_t*)hdr->parsed; } /* Check, if it was the last route-header in the message: */ if (r) { LM_DBG("Too many route headers in message.\n"); goto error; } } else { LM_WARN("Strange: Route-Header is present, but not parsed?!?"); if (c->num_service_routes > 0) goto error; } } else { LM_DBG("No route header in Message.\n"); /* No route-header? Check, if service-routes are indicated. If yes, request is not following service-routes */ if (c->num_service_routes > 0) goto error; } /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return -1; }
void next_state_dlg(struct dlg_cell *dlg, int event, int dir, int *old_state, int *new_state, int *unref, int last_dst_leg, char is_replicated) { struct dlg_entry *d_entry; d_entry = &(d_table->entries[dlg->h_entry]); *unref = 0; dlg_lock( d_table, d_entry); *old_state = dlg->state; switch (event) { case DLG_EVENT_TDEL: switch (dlg->state) { case DLG_STATE_UNCONFIRMED: case DLG_STATE_EARLY: dlg->state = DLG_STATE_DELETED; unref_dlg_unsafe(dlg,1,d_entry); /* unref from TM CBs*/ *unref = 1; /* unref from hash -> t failed */ break; case DLG_STATE_CONFIRMED_NA: case DLG_STATE_CONFIRMED: unref_dlg_unsafe(dlg,1,d_entry); /* unref from TM CBs*/ break; case DLG_STATE_DELETED: /* as the dialog aleady is in DELETE state, it is dangerous to directly unref it from here as it might be last ref -> dialog will be destroied and we will end up with a dangling pointer :D - bogdan */ *unref = 1; /* unref from TM CBs*/ break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_RPL1xx: switch (dlg->state) { case DLG_STATE_UNCONFIRMED: case DLG_STATE_EARLY: dlg->state = DLG_STATE_EARLY; break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_RPL3xx: switch (dlg->state) { case DLG_STATE_UNCONFIRMED: case DLG_STATE_EARLY: dlg->state = DLG_STATE_DELETED; *unref = 1; /* unref from hash -> t failed */ break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_RPL2xx: switch (dlg->state) { case DLG_STATE_DELETED: if (dlg->flags&DLG_FLAG_HASBYE) { log_next_state_dlg(event, dlg); break; } ref_dlg_unsafe(dlg,1); /* back in hash */ case DLG_STATE_UNCONFIRMED: case DLG_STATE_EARLY: dlg->state = DLG_STATE_CONFIRMED_NA; break; case DLG_STATE_CONFIRMED_NA: case DLG_STATE_CONFIRMED: break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_REQACK: switch (dlg->state) { case DLG_STATE_CONFIRMED_NA: dlg->state = DLG_STATE_CONFIRMED; break; case DLG_STATE_CONFIRMED: break; case DLG_STATE_DELETED: break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_REQBYE: switch (dlg->state) { case DLG_STATE_CONFIRMED_NA: case DLG_STATE_CONFIRMED: if (dir == DLG_DIR_DOWNSTREAM && last_dst_leg!=dlg->legs_no[DLG_LEG_200OK] ) /* to end the call, the BYE must be received * on the same leg as the 200 OK for INVITE */ break; dlg->flags |= DLG_FLAG_HASBYE; dlg->state = DLG_STATE_DELETED; *unref = 1; /* unref from hash -> dialog ended */ break; case DLG_STATE_DELETED: break; default: /* only case for BYEs in early or unconfirmed states * is for requests generate by caller or callee. * We never internally generate BYEs for early dialogs * * RFC says caller may send BYEs for early dialogs, * while the callee side MUST not send such requests*/ if (last_dst_leg == 0) log_next_state_dlg(event, dlg); } break; case DLG_EVENT_REQPRACK: switch (dlg->state) { case DLG_STATE_EARLY: case DLG_STATE_CONFIRMED_NA: break; default: log_next_state_dlg(event, dlg); } break; case DLG_EVENT_REQ: switch (dlg->state) { case DLG_STATE_EARLY: case DLG_STATE_CONFIRMED_NA: case DLG_STATE_CONFIRMED: break; default: log_next_state_dlg(event, dlg); } break; default: LM_INFO("unknown event %d in state %d " "for dlg %p [%u:%u] with clid '%.*s' and tags '%.*s' '%.*s'\n", event, dlg->state, dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg_leg_print_info( dlg, DLG_CALLER_LEG, tag), dlg_leg_print_info( dlg, callee_idx(dlg), tag)); } *new_state = dlg->state; dlg_unlock( d_table, d_entry); if (*old_state != *new_state) raise_state_changed_event( dlg->h_entry, dlg->h_id, (unsigned int)(*old_state), (unsigned int)(*new_state) ); if ( !is_replicated && dialog_replicate_cluster && (*old_state==DLG_STATE_CONFIRMED_NA || *old_state==DLG_STATE_CONFIRMED) && dlg->state==DLG_STATE_DELETED ) replicate_dialog_deleted(dlg); LM_DBG("dialog %p changed from state %d to " "state %d, due event %d\n",dlg,*old_state,*new_state,event); }
/** * Force Service routes (upon request) */ int force_service_routes(struct sip_msg* _m, udomain_t* _d) { struct hdr_field *it; int i; str new_route_header; struct lump* lmp = NULL; char * buf; pcontact_t * c = getContactP(_m, _d, PCONTACT_REGISTERED,0 ,0); // char srcip[20]; // str received_host; struct via_body* vb; unsigned short port; unsigned short proto; // Contact not found => not following service-routes if (c == NULL) return -1; /* we need to be sure we have seen all HFs */ parse_headers(_m, HDR_EOH_F, 0); vb = cscf_get_ue_via(_m); port = vb->port?vb->port:5060; proto = vb->proto; /* Save current buffer */ buf = _m->buf; // Delete old Route headers: if (_m->route) { for (it = _m->route; it; it = it->next) { if (it->type == HDR_ROUTE_T) { if ((lmp = del_lump(_m, it->name.s - buf, it->len, HDR_ROUTE_T)) == 0) { LM_ERR("del_lump failed \n"); return -1; } } } } /* Reset dst_uri if previously set either by loose route or manually */ if (_m->dst_uri.s && _m->dst_uri.len) { pkg_free(_m->dst_uri.s); _m->dst_uri.s = NULL; _m->dst_uri.len = 0; } // received_host.len = ip_addr2sbuf(&_m->rcv.src_ip, srcip, sizeof(srcip)); // received_host.s = srcip; /* Lock this record while working with the data: */ ul.lock_udomain(_d, &vb->host, port, proto); if (c->num_service_routes > 0) { /* Create anchor for new Route-Header: */ lmp = anchor_lump(_m, _m->headers->name.s - buf,0,0); if (lmp == 0) { LM_ERR("Failed to get anchor lump\n"); goto error; } /* Calculate the length: */ new_route_header.len = route_start.len + route_end.len + (c->num_service_routes-1) * route_sep.len; for(i=0; i< c->num_service_routes; i++) new_route_header.len+=c->service_routes[i].len; /* Allocate the memory for this new header: */ new_route_header.s = pkg_malloc(new_route_header.len); if (!new_route_header.s) { LM_ERR("Error allocating %d bytes\n", new_route_header.len); goto error; } /* Construct new header */ new_route_header.len = 0; STR_APPEND(new_route_header, route_start); for(i=0; i < c->num_service_routes; i++) { if (i) STR_APPEND(new_route_header, route_sep); STR_APPEND(new_route_header, c->service_routes[i]); } STR_APPEND(new_route_header, route_end); LM_DBG("Setting route header to <%.*s> \n", new_route_header.len, new_route_header.s); if ((lmp = insert_new_lump_after(lmp, new_route_header.s, new_route_header.len, HDR_ROUTE_T)) == 0) { LM_ERR("Error inserting new route set\n"); pkg_free(new_route_header.s); goto error; } LM_DBG("Setting dst_uri to <%.*s> \n", c->service_routes[0].len, c->service_routes[0].s); if (set_dst_uri(_m, &c->service_routes[0]) !=0 ) { LM_ERR("Error setting new dst uri\n"); goto error; } } /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return 1; error: /* Unlock domain */ ul.unlock_udomain(_d, &vb->host, port, proto); return -1; return 1; }
static inline int get_resource_list(str *username, str *domain, str *filename, str *selector, xmlNodePtr *rl_node, xmlDocPtr *xmldoc) { static char path_buf[MAX_PATH_LEN+1]; int checked = 0; str path; str *doc = NULL; str *etag = NULL; xmlXPathContextPtr xpathCtx = NULL; xmlXPathObjectPtr xpathObj = NULL; if (filename==NULL || username==NULL || domain==NULL) { LM_ERR("invalid parameters\n"); return -1; } if (xcapDbGetDoc(username, domain, RESOURCE_LISTS, filename, NULL, &doc, &etag) < 0) { LM_DBG("No rl document found\n"); return -1; } LM_DBG("rl document:\n%.*s\n", doc->len, doc->s); path.s = path_buf; path.len = 0; if (selector->s) { while (checked < selector->len && path.len <= MAX_PATH_LEN) { if (selector->s[checked] == '/') { memcpy(path.s+path.len, "/xmlns:", 7); path.len += 7; } else { path.s[path.len++] = selector->s[checked]; } checked++; } path.s[path.len] = '\0'; LM_DBG("path: %.*s", path.len, path.s); } *xmldoc = xmlParseMemory(doc->s, doc->len); if (*xmldoc == NULL) { LM_ERR("while parsing XML memory\n"); goto error; } if(path.len == 0) { LM_ERR("no path specified\n"); goto error; } /* TODO: move this to xcap module? */ xpathCtx = xmlXPathNewContext(*xmldoc); if (xpathCtx == NULL) { LM_ERR("unable to create new XPath context"); goto error; } if (xmlXPathRegisterNs(xpathCtx, BAD_CAST "xmlns", BAD_CAST "urn:ietf:params:xml:ns:resource-lists") != 0) { LM_ERR("unable to register xmlns\n"); goto error; } xpathObj = xmlXPathEvalExpression(BAD_CAST path.s, xpathCtx); if (xpathObj == NULL) { LM_ERR("unable to evaluate path\n"); goto error; } if (xpathObj->nodesetval == NULL || xpathObj->nodesetval->nodeNr <= 0) { LM_ERR("no nodes found\n"); goto error; } if (xpathObj->nodesetval->nodeTab[0] != NULL && xpathObj->nodesetval->nodeTab[0]->type != XML_ELEMENT_NODE) { LM_ERR("no nodes of the correct type found\n"); goto error; } *rl_node = xpathObj->nodesetval->nodeTab[0]; xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); pkg_free(doc->s); pkg_free(doc); pkg_free(etag->s); pkg_free(etag); return 0; error: if (doc != NULL) { if (doc->s != NULL) pkg_free(doc->s); pkg_free(doc); } if (etag != NULL) { if (etag->s != NULL) pkg_free(etag->s); pkg_free(etag); } if (xpathObj) xmlXPathFreeObject(xpathObj); if (xpathCtx) xmlXPathFreeContext(xpathCtx); if (*xmldoc) xmlFreeDoc(*xmldoc); return -1; }
/*! * \brief Function that is registered as RR callback for dialog tracking * * Function that is registered as RR callback for dialog tracking. It * sets the appropriate events after the SIP method and run the state * machine to update the dialog state. It updates then the saved * dialogs and also the statistics. * \param req SIP request * \param route_params record-route parameter * \param param unused */ void dlg_onroute(struct sip_msg* req, str *route_params, void *param) { dlg_cell_t *dlg; dlg_iuid_t *iuid; str val, callid, ftag, ttag; int h_entry, h_id, new_state, old_state, unref, event, timeout, reset; unsigned int dir; int ret = 0; dlg = dlg_get_ctx_dialog(); if (dlg!=NULL) { dlg_release(dlg); return; } /* skip initial requests - they may end up here because of the * preloaded route */ if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) { LM_ERR("bad request or missing TO hdr :-/\n"); return; } if ( get_to(req)->tag_value.len==0 ) return; dlg = 0; dir = DLG_DIR_NONE; if ( seq_match_mode!=SEQ_MATCH_NO_ID ) { if( d_rrb.get_route_param( req, &rr_param, &val)!=0) { LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s); if (seq_match_mode==SEQ_MATCH_STRICT_ID ) return; } else { LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len); if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 ) return; dlg = dlg_lookup(h_entry, h_id); if (dlg==0) { LM_WARN("unable to find dialog for %.*s " "with route param '%.*s' [%u:%u]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s, val.len,val.s, h_entry, h_id); if (seq_match_mode==SEQ_MATCH_STRICT_ID ) return; } else { if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) { // lookup_dlg has incremented the ref count by 1 dlg_release(dlg); return; } if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) { LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, " "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s, callid.len, callid.s, callid.len, ftag.len, ftag.s, ftag.len, ttag.len, ttag.s, ttag.len, dir); LM_WARN("dialog identification elements are callid='%.*s'/%d, " "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n", dlg->callid.len, dlg->callid.s, dlg->callid.len, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s, dlg->tag[DLG_CALLEE_LEG].len); // lookup_dlg has incremented the ref count by 1 dlg_release(dlg); // Reset variables in order to do a lookup based on SIP-Elements. dlg = 0; dir = DLG_DIR_NONE; if (seq_match_mode==SEQ_MATCH_STRICT_ID ) return; } } } } if (dlg==0) { if (pre_match_parse(req, &callid, &ftag, &ttag, 1)<0) return; /* TODO - try to use the RR dir detection to speed up here the * search -bogdan */ dlg = get_dlg(&callid, &ftag, &ttag, &dir); if (dlg==0){ LM_DBG("Callid '%.*s' not found\n", req->callid->body.len, req->callid->body.s); return; } } /* set current dialog - re-use ref increment from dlg_get() above */ set_current_dialog( req, dlg); _dlg_ctx.iuid.h_entry = dlg->h_entry; _dlg_ctx.iuid.h_id = dlg->h_id; if(dlg->iflags & DLG_IFLAG_CSEQ_DIFF) { if(dlg_cseq_refresh(req, dlg, dir)<0) { LM_ERR("failed to refresh cseq update\n"); } } if (req->first_line.u.request.method_value != METHOD_ACK) { iuid = dlg_get_iuid_shm_clone(dlg); if(iuid!=NULL) { /* register callback for the replies of this request */ if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_IN|TMCB_ON_FAILURE, dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) { LM_ERR("failed to register TMCB (3)\n"); shm_free(iuid); } iuid = NULL; } } /* run state machine */ switch ( req->first_line.u.request.method_value ) { case METHOD_PRACK: event = DLG_EVENT_REQPRACK; break; case METHOD_ACK: event = DLG_EVENT_REQACK; break; case METHOD_BYE: event = DLG_EVENT_REQBYE; break; default: event = DLG_EVENT_REQ; } next_state_dlg( dlg, event, &old_state, &new_state, &unref); CURR_DLG_ID = req->id; CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts; CURR_DLG_STATUS = new_state; dlg_run_event_route(dlg, req, old_state, new_state); /* delay deletion of dialog until transaction has died off in order * to absorb in-air messages */ if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { /* set end time */ dlg->end_ts = (unsigned int)(time(0)); iuid = dlg_get_iuid_shm_clone(dlg); if(iuid!=NULL) { if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY, unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) { LM_ERR("failed to register deletion delay function\n"); shm_free(iuid); } else { dlg_ref(dlg, 1); } } } if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED) dlg_ka_add(dlg); /* run actions for the transition */ if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_DBG("BYE successfully processed\n"); /* 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' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); } else if (ret > 0) { LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] " "with clid '%.*s' and tags '%.*s' '%.*s'\n", dlg, dlg->h_entry, dlg->h_id, dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); } else { /* one extra unref due to removal from timer list */ unref++; } /* dialog terminated (BYE) */ dlg_terminated( req, dlg, dir); dlg_unref(dlg, unref); _dlg_ctx.cpid = my_pid(); _dlg_ctx.expect_t = 1; dlg_set_ctx_iuid(dlg); if_update_stat( dlg_enable_stats, active_dlgs, -1); goto done; } if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK) && (new_state==DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) { timeout = get_dlg_timeout(req); if (timeout!=default_timeout) { dlg->lifetime = timeout; } reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset); if ((new_state!=DLG_STATE_EARLY) && (old_state!=DLG_STATE_CONFIRMED || reset)) { if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) { LM_ERR("failed to update dialog lifetime\n"); } else { dlg->dflags |= DLG_FLAG_CHANGED; } } if(event != DLG_EVENT_REQACK) { if(dlg_refresh_contacts(dlg, req, dir)!=0) { LM_ERR("contacts update failed\n"); } else { dlg->dflags |= DLG_FLAG_CHANGED; } if(update_cseqs(dlg, req, dir)!=0) { LM_ERR("cseqs update failed\n"); } else { dlg->dflags |= DLG_FLAG_CHANGED; } } if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) { update_dialog_dbinfo(dlg); } if (old_state==DLG_STATE_CONFIRMED_NA) { LM_DBG("confirming ACK successfully processed\n"); /* confirming ACK request */ run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0); } else { LM_DBG("sequential request successfully processed\n"); /* within dialog request */ run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0); if (add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) { LM_ERR("failed to add RR param\n"); goto done; } if ( (event!=DLG_EVENT_REQACK) && (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) { iuid = dlg_get_iuid_shm_clone(dlg); if(iuid!=NULL) { /* register callback for the replies of this request */ if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED, (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply: dlg_seq_up_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) { LM_ERR("failed to register TMCB (2)\n"); shm_free(iuid); } } } } } if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){ dlg->dflags |= DLG_FLAG_CHANGED; if(dlg_db_mode == DB_MODE_REALTIME) update_dialog_dbinfo(dlg); } done: dlg_release(dlg); return; }
static void oma_get_rules(subs_t* subs, xmlDocPtr xcap_tree, xcap_rule_t **rules) { int apply_rule = 0, current_node_type = -1; str w_uri = {0, 0}; xmlNodePtr ruleset_node = NULL, cond_node = NULL; xmlNodePtr node1 = NULL, node2 = NULL, current_node = NULL; xcap_rule_t *tmp_rule = NULL; xcap_rule_t *identity_rules = NULL, *external_rules = NULL, *anonymous_rules = NULL, *other_identity_rules = NULL; xcap_rule_t *identity_tail = NULL, *external_tail = NULL, *anonymous_tail = NULL, *other_identity_tail = NULL; *rules = NULL; uandd_to_uri(subs->from_user, subs->from_domain, &w_uri); if(w_uri.s == NULL) { LM_ERR("while creating uri\n"); return; } ruleset_node = xmlDocGetNodeByName(xcap_tree, "ruleset", NULL); if(ruleset_node == NULL) { LM_ERR("ruleset_node not found\n"); pkg_free(w_uri.s); return; } for(node1 = ruleset_node->children; node1; node1 = node1->next) { if(xmlStrcasecmp(node1->name, (unsigned char*)"text")==0) continue; cond_node = xmlNodeGetChildByName(node1, "conditions"); if(cond_node == NULL) { LM_WARN("condition node not found\n"); continue; } apply_rule = 0; current_node = node1; current_node_type = -1; for(node2 = cond_node->children; node2; node2 = node2->next) { if(xmlStrcasecmp(node2->name, (unsigned char*)"identity") == 0) { current_node_type = IDENTITY_RULE; apply_rule = oma_match_identity_condition(node2, subs, &w_uri); break; } else if(xmlStrcasecmp(node2->name, (unsigned char*)"external-list") == 0) { current_node_type = EXTERNAL_LIST_RULE; apply_rule = oma_match_external_list_condition(node2, subs, &w_uri); break; } else if(xmlStrcasecmp(node2->name, (unsigned char*)"anonymous-request") == 0) { current_node_type = ANONYMOUS_REQUEST_RULE; apply_rule = oma_match_anonymous_condition(node2, subs, &w_uri); break; } else if(xmlStrcasecmp(node2->name, (unsigned char*)"other-identity") == 0) { current_node_type = OTHER_IDENTITY_RULE; apply_rule = 1; break; } else { /* unknown condition */ continue; } } /* finished scanning all conditions for a given rule */ if (apply_rule) { tmp_rule = (xcap_rule_t *)pkg_malloc(sizeof(*tmp_rule)); if (tmp_rule == NULL) { LM_ERR("pkg mem\n"); goto error; } tmp_rule->node = current_node; tmp_rule->next = NULL; switch (current_node_type) { case IDENTITY_RULE: if(identity_rules == NULL) identity_rules = tmp_rule; else identity_tail->next = tmp_rule; identity_tail = tmp_rule; break; case EXTERNAL_LIST_RULE: if(external_rules == NULL) external_rules = tmp_rule; else external_tail->next = tmp_rule; external_tail = tmp_rule; break; case ANONYMOUS_REQUEST_RULE: if(anonymous_rules == NULL) anonymous_rules = tmp_rule; else anonymous_tail->next = tmp_rule; anonymous_tail = tmp_rule; break; case OTHER_IDENTITY_RULE: if(other_identity_rules == NULL) other_identity_rules = tmp_rule; else other_identity_tail->next = tmp_rule; other_identity_tail = tmp_rule; break; default: /* this will never happen */ break; } } } if (anonymous_rules) { *rules = anonymous_rules; free_rules(identity_rules); free_rules(external_rules); free_rules(other_identity_rules); } else if (identity_rules) { *rules = identity_rules; free_rules(external_rules); free_rules(anonymous_rules); free_rules(other_identity_rules); } else if (external_rules) { *rules = external_rules; free_rules(identity_rules); free_rules(anonymous_rules); free_rules(other_identity_rules); } else if (other_identity_rules) { *rules = other_identity_rules; free_rules(identity_rules); free_rules(external_rules); free_rules(anonymous_rules); } else { *rules = NULL; LM_DBG("no matching rules found\n"); } pkg_free(w_uri.s); return; error: if (w_uri.s) pkg_free(w_uri.s); free_rules(identity_rules); free_rules(external_rules); free_rules(anonymous_rules); free_rules(other_identity_rules); }
/*! * \brief Timer function that removes expired dialogs, run timeout route * \param tl dialog timer list */ void dlg_ontimeout(struct dlg_tl *tl) { dlg_cell_t *dlg; int new_state, old_state, unref; sip_msg_t *fmsg; void* timeout_cb = 0; /* get the dialog tl payload */ dlg = ((struct dlg_cell*)((char *)(tl) - (unsigned long)(&((struct dlg_cell*)0)->tl))); /* mark dialog as expired */ dlg->dflags |= DLG_FLAG_EXPIRED; if(dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { if(dlg->toroute>0 && dlg->toroute<main_rt.entries && main_rt.rlist[dlg->toroute]!=NULL) { fmsg = faked_msg_next(); if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0) { dlg_ref(dlg, 1); dlg_set_ctx_iuid(dlg); LM_DBG("executing route %d on timeout\n", dlg->toroute); set_route_type(REQUEST_ROUTE); run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0); dlg_reset_ctx_iuid(); exec_post_script_cb(fmsg, REQUEST_CB_TYPE); dlg_unref(dlg, 1); } } if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE) { /* set the dialog context so that it's available in * tm:local-request event route */ dlg_set_ctx_iuid(dlg); if(dlg_bye_all(dlg, NULL)<0) dlg_unref(dlg, 1); dlg_reset_ctx_iuid(); dlg_unref(dlg, 1); if_update_stat(dlg_enable_stats, expired_dlgs, 1); return; } } next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref); /* used for computing duration for timed out acknowledged dialog */ if (DLG_STATE_CONFIRMED == old_state) { timeout_cb = (void *)CONFIRMED_DIALOG_STATE; } dlg_run_event_route(dlg, NULL, old_state, new_state); if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n", dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); /* set end time */ dlg->end_ts = (unsigned int)(time(0)); /* dialog timeout */ run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb); dlg_unref(dlg, unref+1); if_update_stat( dlg_enable_stats, expired_dlgs, 1); if_update_stat( dlg_enable_stats, active_dlgs, -1); } else { dlg_unref(dlg, 1); } return; }
int dbt_query(db1_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, db1_res_t** _r) { dbt_table_p _tbc = NULL; dbt_row_p _drp = NULL; dbt_result_p _dres = NULL; int result = 0; int *lkey=NULL, *lres=NULL; db_key_t *_o_k=NULL; /* columns in order-by */ char *_o_op=NULL; /* operators for oder-by */ int _o_n; /* no of elements in order-by */ int *_o_l=NULL; /* column selection for order-by */ int _o_nc; /* no of elements in _o_l but not lres */ if ((!_h) || (!_r) || !CON_TABLE(_h)) { LM_ERR("invalid parameters\n"); return -1; } *_r = NULL; if (_o) { if (dbt_parse_orderbyclause(&_o_k, &_o_op, &_o_n, _o) < 0) return -1; } /* lock database */ _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(!_tbc) { LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); return -1; } if(!_tbc || _tbc->nrcols < _nc) { LM_ERR("table %s not loaded! (too few columns)\n", CON_TABLE(_h)->s); goto error; } if(_k) { lkey = dbt_get_refs(_tbc, _k, _n); if(!lkey) goto error; } if(_c) { lres = dbt_get_refs(_tbc, _c, _nc); if(!lres) goto error; } if(_o_k) { _o_l = dbt_get_refs(_tbc, _o_k, _o_n); if (!_o_l) goto error; /* enlarge select-columns lres by all order-by columns, _o_nc is how many */ if (dbt_mangle_columnselection(&lres, &_nc, &_o_nc, _o_l, _o_n) < 0) goto error; } LM_DBG("new res with %d cols\n", _nc); _dres = dbt_result_new(_tbc, lres, _nc); if(!_dres) goto error; _drp = _tbc->rows; while(_drp) { if(dbt_row_match(_tbc, _drp, lkey, _op, _v, _n)) { if(dbt_result_extract_fields(_tbc, _drp, lres, _dres)) { LM_ERR("failed to extract result fields!\n"); goto clean; } } _drp = _drp->next; } dbt_table_update_flags(_tbc, DBT_TBFL_ZERO, DBT_FL_IGN, 1); /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if (_o_l) { if (_dres->nrrows > 1) { if (dbt_sort_result(_dres, _o_l, _o_op, _o_n, lres, _nc) < 0) goto error_nounlock; } /* last but not least, remove surplus columns */ if (_o_nc) dbt_project_result(_dres, _o_nc); } /* dbt_result_print(_dres); */ if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); if(_o_k) pkg_free(_o_k); if(_o_op) pkg_free(_o_op); if(_o_l) pkg_free(_o_l); result = dbt_get_result(_r, _dres); if(result != 0) dbt_result_free(_dres); return result; error: /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); error_nounlock: if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); if(_o_k) pkg_free(_o_k); if(_o_op) pkg_free(_o_op); if(_o_l) pkg_free(_o_l); if(_dres) dbt_result_free(_dres); LM_ERR("failed to query the table!\n"); return -1; clean: /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); if(_o_k) pkg_free(_o_k); if(_o_op) pkg_free(_o_op); if(_o_l) pkg_free(_o_l); if(_dres) dbt_result_free(_dres); return -1; }
/*! * \brief Parse SIP message and populate leg informations * * Parse SIP message and populate leg informations. * \param dlg the dialog to add cseq, contact & record_route * \param msg sip message * \param t transaction * \param leg type of the call leg * \param tag SIP To tag * \return 0 on success, -1 on failure * \note for a request: get record route in normal order, for a reply get * in reverse order, skipping the ones from the request and the proxies' own */ int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg, struct cell* t, unsigned int leg, str *tag) { unsigned int skip_recs; str cseq; str contact; str rr_set; dlg->bind_addr[leg] = msg->rcv.bind_address; /* extract the cseq number as string */ if (leg==DLG_CALLER_LEG) { if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq)) || !msg->cseq->parsed){ LM_ERR("bad sip message or missing CSeq hdr :-/\n"); goto error0; } cseq = (get_cseq(msg))->number; } else { /* use the same as in request */ cseq = dlg->cseq[DLG_CALLEE_LEG]; } /* extract the contact address */ if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){ LM_ERR("bad sip message or missing Contact hdr\n"); goto error0; } if ( parse_contact(msg->contact)<0 || ((contact_body_t *)msg->contact->parsed)->contacts==NULL || ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) { LM_ERR("bad Contact HDR\n"); goto error0; } contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri; /* extract the RR parts */ if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0) ){ LM_ERR("failed to parse record route header\n"); goto error0; } if (leg==DLG_CALLER_LEG) { skip_recs = 0; } else { /* was the 200 OK received or local generated */ skip_recs = dlg->from_rr_nb + ((t->relayed_reply_branch>=0)? ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2: ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0)) :0); } if(msg->record_route){ if( print_rr_body(msg->record_route, &rr_set, leg, &skip_recs) != 0 ){ LM_ERR("failed to print route records \n"); goto error0; } } else { rr_set.s = 0; rr_set.len = 0; } if(leg==DLG_CALLER_LEG) dlg->from_rr_nb = skip_recs; LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n", rr_set.len, rr_set.s, contact.len, contact.s, cseq.len, cseq.s, msg->rcv.bind_address->sock_str.len, msg->rcv.bind_address->sock_str.s); if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) { LM_ERR("dlg_set_leg_info failed\n"); if (rr_set.s) pkg_free(rr_set.s); goto error0; } if (rr_set.s) pkg_free(rr_set.s); return 0; error0: return -1; }
/** * run keep-alive list * */ int dlg_ka_run(ticks_t ti) { dlg_ka_t *dka; dlg_cell_t *dlg; if(dlg_ka_interval<=0) return 0; while(1) { /* get head item */ lock_get(dlg_ka_list_lock); if(*dlg_ka_list_head==NULL) { lock_release(dlg_ka_list_lock); return 0; } dka = *dlg_ka_list_head; #if 0 LM_DBG("dlg ka timer at %lu for" " dlg[%u,%u] on %lu\n", (unsigned long)ti, dka->iuid.h_entry, dka->iuid.h_id, (unsigned long)dka->katime); #endif if(dka->katime>ti) { lock_release(dlg_ka_list_lock); return 0; } if(*dlg_ka_list_head == *dlg_ka_list_tail) { *dlg_ka_list_head = NULL; *dlg_ka_list_tail = NULL; } *dlg_ka_list_head = dka->next; lock_release(dlg_ka_list_lock); /* send keep-alive for dka */ dlg = dlg_get_by_iuid(&dka->iuid); if(dlg==NULL) { shm_free(dka); dka = NULL; } else { if(dka->iflags & DLG_IFLAG_KA_SRC) dlg_send_ka(dlg, DLG_CALLER_LEG); if(dka->iflags & DLG_IFLAG_KA_DST) dlg_send_ka(dlg, DLG_CALLEE_LEG); dlg_release(dlg); } /* append to tail */ if(dka!=NULL) { dka->katime = ti + dlg_ka_interval; lock_get(dlg_ka_list_lock); if(*dlg_ka_list_tail!=NULL) (*dlg_ka_list_tail)->next = dka; if(*dlg_ka_list_head==NULL) *dlg_ka_list_head = dka; *dlg_ka_list_tail = dka; lock_release(dlg_ka_list_lock); } } return 0; }
int update_phtable(presentity_t* presentity, str pres_uri, str body) { char* sphere= NULL; unsigned int hash_code; pres_entry_t* p; int ret= 0; str* xcap_doc= NULL; /* get new sphere */ sphere= extract_sphere(body); if(sphere==NULL) { LM_DBG("no sphere defined in new body\n"); return 0; } /* search for record in hash table */ hash_code= core_hash(&pres_uri, NULL, phtable_size); lock_get(&pres_htable[hash_code].lock); p= search_phtable(&pres_uri, presentity->event->evp->parsed, hash_code); if(p== NULL) { lock_release(&pres_htable[hash_code].lock); goto done; } if(p->sphere) { if(strcmp(p->sphere, sphere)!= 0) { /* new sphere definition */ shm_free(p->sphere); } else { /* no change in sphere definition */ lock_release(&pres_htable[hash_code].lock); pkg_free(sphere); return 0; } } p->sphere= (char*)shm_malloc(strlen(sphere)+ 1); if(p->sphere== NULL) { lock_release(&pres_htable[hash_code].lock); ret= -1; goto done; } strcpy(p->sphere, sphere); lock_release(&pres_htable[hash_code].lock); /* call for watchers status update */ if(presentity->event->get_rules_doc(&presentity->user, &presentity->domain, &xcap_doc)< 0) { LM_ERR("failed to retreive xcap document\n"); ret= -1; goto done; } update_watchers_status(pres_uri, presentity->event, xcap_doc); done: if(xcap_doc) { if(xcap_doc->s) pkg_free(xcap_doc->s); pkg_free(xcap_doc); } if(sphere) pkg_free(sphere); return ret; }