str* client_new(client_info_t* ci,b2b_notify_t b2b_cback, b2b_add_dlginfo_t add_dlginfo, str* param) { int result; b2b_dlg_t* dlg; unsigned int hash_index; str* callid = NULL; int size; str ehdr = {0, 0}; str* b2b_key_shm = NULL; dlg_t td; str from_tag; str random_info = {0, 0}; if(ci == NULL || b2b_cback == NULL || param== NULL) { LM_ERR("Wrong parameters.\n"); return NULL; } if(param && param->len > B2BL_MAX_KEY_LEN) { LM_ERR("parameter too long, received [%d], maximum [%d]\n", param->len, B2BL_MAX_KEY_LEN); return 0; } hash_index = core_hash(&ci->from_uri, &ci->to_uri, client_hsize); if(ci->from_tag) from_tag = *ci->from_tag; else generate_tag(&from_tag, &ci->from_uri, ci->extra_headers); /* create a dummy b2b dialog structure to be inserted in the hash table*/ size = sizeof(b2b_dlg_t) + ci->to_uri.len + ci->from_uri.len + ci->from_dname.len + ci->to_dname.len + from_tag.len + ci->local_contact.len + B2B_MAX_KEY_SIZE + B2BL_MAX_KEY_LEN; /* create record in hash table */ dlg = (b2b_dlg_t*)shm_malloc(size); if(dlg == NULL) { LM_ERR("No more shared memory\n"); return 0; } memset(dlg, 0, size); size = sizeof(b2b_dlg_t); CONT_COPY(dlg, dlg->from_uri, ci->from_uri); CONT_COPY(dlg, dlg->to_uri, ci->to_uri); if(ci->to_dname.s) CONT_COPY(dlg, dlg->to_dname, ci->to_dname); if(ci->from_dname.s) CONT_COPY(dlg, dlg->from_dname, ci->from_dname); CONT_COPY(dlg, dlg->tag[CALLER_LEG], from_tag); CONT_COPY(dlg, dlg->contact[CALLER_LEG], ci->local_contact); if(param && param->s) { dlg->param.s = (char*)dlg + size; memcpy(dlg->param.s, param->s, param->len); dlg->param.len = param->len; size+= B2BL_MAX_KEY_LEN; } dlg->b2b_cback = b2b_cback; dlg->add_dlginfo = add_dlginfo; if(parse_method(ci->method.s, ci->method.s+ci->method.len, &dlg->last_method)< 0) { LM_ERR("wrong method %.*s\n", ci->method.len, ci->method.s); shm_free(dlg); goto error; } dlg->state = B2B_NEW; dlg->cseq[CALLER_LEG] =(ci->cseq?ci->cseq:1); dlg->send_sock = ci->send_sock; /* if the callid should be the same in more instances running at the same time (replication)*/ if(!replication_mode) { srand(get_uticks()); random_info.s = int2str(rand(), &random_info.len); } dlg->send_sock = ci->send_sock; dlg->id = core_hash(&from_tag, random_info.s?&random_info:0, HASH_SIZE); /* callid must have the special format */ dlg->db_flag = NO_UPDATEDB_FLAG; callid = b2b_htable_insert(client_htable, dlg, hash_index, B2B_CLIENT, 0); if(callid == NULL) { LM_ERR("Inserting new record in hash table failed\n"); shm_free(dlg); goto error; } if(b2breq_complete_ehdr(ci->extra_headers, &ehdr, ci->body, &ci->local_contact)< 0) { LM_ERR("Failed to complete extra headers\n"); goto error; } /* copy the key in shared memory to transmit it as a parameter to the tm callback */ b2b_key_shm = b2b_key_copy_shm(callid); if(b2b_key_shm== NULL) { LM_ERR("no more shared memory\n"); goto error; } CONT_COPY(dlg, dlg->callid, (*callid)); /* create the tm dialog structure with the a costum callid */ memset(&td, 0, sizeof(dlg_t)); td.loc_seq.value = dlg->cseq[CALLER_LEG]; dlg->last_invite_cseq = dlg->cseq[CALLER_LEG]; td.loc_seq.is_set = 1; td.id.call_id = *callid; td.id.loc_tag = from_tag; td.id.rem_tag.s = 0; td.id.rem_tag.len = 0; td.rem_uri = ci->to_uri; if(ci->req_uri.s) td.rem_target = ci->req_uri; else td.rem_target = ci->to_uri; if(td.rem_target.s[0] == '<') { td.rem_target.s++; td.rem_target.len-=2; } td.rem_dname = ci->to_dname; td.loc_uri = ci->from_uri; td.loc_dname = ci->from_dname; td.state= DLG_CONFIRMED; td.T_flags=T_NO_AUTOACK_FLAG|T_PASS_PROVISIONAL_FLAG ; td.send_sock = ci->send_sock; if(ci->dst_uri.len) td.obp = ci->dst_uri; td.avps = ci->avps; tmb.setlocalTholder(&dlg->uac_tran); /* send request */ result= tmb.t_request_within (&ci->method, /* method*/ &ehdr, /* extra headers*/ ci->body, /* body*/ &td, /* dialog structure*/ b2b_client_tm_cback, /* callback function*/ b2b_key_shm, shm_free_param); /* function to release the parameter*/ if(td.route_set) pkg_free(td.route_set); if(result< 0) { LM_ERR("while sending request with t_request\n"); pkg_free(callid); shm_free(b2b_key_shm); return NULL; } tmb.setlocalTholder(NULL); LM_DBG("new client entity [%p] callid=[%.*s] tag=[%.*s] param=[%.*s]" " last method=[%d] dlg->uac_tran=[%p]\n", dlg, callid->len, callid->s, dlg->tag[CALLER_LEG].len, dlg->tag[CALLER_LEG].s, dlg->param.len, dlg->param.s, dlg->last_method, dlg->uac_tran); return callid; error: if(callid) pkg_free(callid); return NULL; }
int b2b_entities_restore(void) { db_res_t *result= NULL; db_row_t *rows = NULL; db_val_t *row_vals= NULL; int i; dlg_leg_t leg, *new_leg; b2b_dlg_t dlg, *shm_dlg= NULL; unsigned int hash_index, local_index; int nr_rows; str* b2b_key; str sockinfo_str; str host; int port, proto; b2b_table htable; int type; int no_rows = 10; if(b2be_db == NULL) { LM_DBG("NULL database connection\n"); return 0; } if(b2be_dbf.use_table(b2be_db, &b2be_dbtable)< 0) { LM_ERR("sql use table failed\n"); return -1; } if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH)) { if(b2be_dbf.query(b2be_db,0,0,0,qcols, 0, DB_COLS_NO, 0, 0) < 0) { LM_ERR("Error while querying (fetch) database\n"); return -1; } no_rows = estimate_available_rows( DB_COLS_NO*128, DB_COLS_NO); if (no_rows==0) no_rows = 10; if(b2be_dbf.fetch_result(b2be_db,&result,no_rows)<0) { LM_ERR("fetching rows failed\n"); return -1; } } else { if (b2be_dbf.query (b2be_db, 0, 0, 0,qcols,0, DB_COLS_NO, 0, &result) < 0) { LM_ERR("querying presentity\n"); return -1; } } nr_rows = RES_ROW_N(result); do { LM_DBG("loading information from database %i records\n", nr_rows); rows = RES_ROWS(result); /* for every row */ for(i=0; i<nr_rows; i++) { row_vals = ROW_VALUES(rows +i); memset(&dlg, 0, sizeof(b2b_dlg_t)); type = row_vals[0].val.int_val; dlg.tag[1].s = (char*)row_vals[2].val.string_val; dlg.tag[1].len = dlg.tag[1].s?strlen(dlg.tag[1].s):0; dlg.callid.s = (char*)row_vals[3].val.string_val; dlg.callid.len = dlg.callid.s?strlen(dlg.callid.s):0; if(type == B2B_SERVER)/* extract hash and local index */ { htable = server_htable; if(b2b_parse_key(&dlg.tag[1], &hash_index, &local_index) < 0) { LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.tag[1].len, dlg.tag[1].s); goto error; } } else { htable = client_htable; if(b2b_parse_key(&dlg.callid, &hash_index, &local_index) < 0) { LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.callid.len, dlg.callid.s); goto error; } } dlg.id = local_index; dlg.state = row_vals[13].val.int_val; dlg.ruri.s = (char*)row_vals[4].val.string_val; dlg.ruri.len = dlg.ruri.s?strlen(dlg.ruri.s):0; dlg.from_uri.s = (char*)row_vals[5].val.string_val; dlg.from_uri.len = strlen(dlg.from_uri.s); dlg.from_dname.s = (char*)row_vals[6].val.string_val; dlg.from_dname.len = strlen(dlg.from_dname.s); dlg.to_uri.s = (char*)row_vals[7].val.string_val; dlg.to_uri.len = strlen(dlg.to_uri.s); dlg.to_dname.s = (char*)row_vals[8].val.string_val; dlg.to_dname.len = dlg.to_dname.s?strlen(dlg.to_dname.s):0; dlg.tag[0].s = (char*)row_vals[1].val.string_val; dlg.tag[0].len = dlg.tag[0].s?strlen(dlg.tag[0].s):0; dlg.cseq[0] = row_vals[14].val.int_val; dlg.cseq[1] = row_vals[15].val.int_val; dlg.route_set[0].s = (char*)row_vals[9].val.string_val; dlg.route_set[0].len = dlg.route_set[0].s?strlen(dlg.route_set[0].s):0; dlg.route_set[1].s = (char*)row_vals[10].val.string_val; dlg.route_set[1].len = dlg.route_set[1].s?strlen(dlg.route_set[1].s):0; dlg.contact[0].s = (char*)row_vals[19].val.string_val; dlg.contact[0].len = dlg.contact[0].s?strlen(dlg.contact[0].s):0; dlg.contact[1].s = (char*)row_vals[20].val.string_val; dlg.contact[1].len = dlg.contact[1].s?strlen(dlg.contact[1].s):0; dlg.last_method = row_vals[16].val.int_val; dlg.last_reply_code = row_vals[17].val.int_val; dlg.last_invite_cseq = row_vals[18].val.int_val; dlg.param.s = (char*)row_vals[12].val.string_val; dlg.param.len = strlen(dlg.param.s); sockinfo_str.s = (char*)row_vals[11].val.string_val; if(sockinfo_str.s) { sockinfo_str.len = strlen(sockinfo_str.s); if(sockinfo_str.len) { if (parse_phostport (sockinfo_str.s, sockinfo_str.len, &host.s, &host.len, &port, &proto )< 0) { LM_ERR("bad format for stored sockinfo string [%.*s]\n", sockinfo_str.len, sockinfo_str.s); goto error; } dlg.send_sock = grep_sock_info(&host, (unsigned short) port, (unsigned short) proto); } } dlg.db_flag = NO_UPDATEDB_FLAG; shm_dlg = b2b_dlg_copy(&dlg); if(shm_dlg == NULL) { LM_ERR("Failed to create new dialog structure\n"); goto error; } b2b_key= b2b_htable_insert(htable,shm_dlg,hash_index,type, 1); if(b2b_key == NULL) { LM_ERR("Failed to insert new record\n"); goto error; } pkg_free(b2b_key); memset(&leg, 0, sizeof(dlg_leg_t)); leg.tag.s= (char*)row_vals[21].val.string_val; if(!leg.tag.s) continue; leg.tag.len = strlen(leg.tag.s); leg.cseq = row_vals[22].val.int_val; leg.contact.s = (char*)row_vals[23].val.string_val; leg.contact.len = leg.contact.s?strlen(leg.contact.s):0; leg.route_set.s = (char*)row_vals[24].val.string_val; leg.route_set.len = leg.route_set.s?strlen(leg.route_set.s):0; new_leg = b2b_dup_leg(&leg, SHM_MEM_TYPE); if(new_leg== NULL) { LM_ERR("Failed to construct b2b leg structure\n"); goto error; } shm_dlg->legs = new_leg; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH)) { if (b2be_dbf.fetch_result( b2be_db, &result, no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(result); } else { nr_rows = 0; } }while (nr_rows>0); b2be_dbf.free_result(b2be_db, result); return 0; error: if(result) b2be_dbf.free_result(b2be_db, result); return -1; }
str* server_new(struct sip_msg* msg, str* local_contact, b2b_notify_t b2b_cback, str* param) { b2b_dlg_t* dlg; unsigned int hash_index; static str reason = {"Trying", 6}; int ret; if(param && param->len > B2BL_MAX_KEY_LEN) { LM_ERR("parameter too long, received [%d], maximum [%d]\n", param->len, B2BL_MAX_KEY_LEN); return NULL; } /* create new entry in hash table */ dlg = b2b_new_dlg(msg, local_contact, 0, param); if( dlg == NULL ) { LM_ERR("failed to create new dialog structure entry\n"); return NULL; } hash_index = core_hash(&dlg->callid, &dlg->tag[CALLER_LEG], server_hsize); /* check if record does not exist already */ dlg->state = B2B_NEW; dlg->b2b_cback = b2b_cback; /* get the pointer to the tm transaction to store it the tuple record */ dlg->uas_tran = tmb.t_gett(); if(dlg->uas_tran == NULL || dlg->uas_tran == T_UNDEFINED) { ret = tmb.t_newtran(msg); if(ret < 1) { if(ret== 0) { LM_DBG("It is a retransmission, drop\n"); } else LM_DBG("Error when creating tm transaction\n"); goto error; } dlg->uas_tran = tmb.t_gett(); } tmb.ref_cell(dlg->uas_tran); tmb.t_reply(msg, 100, &reason); tmb.t_setkr(REQ_FWDED); LM_DBG("new server entity[%p]: callid=[%.*s] tag=[%.*s] param=[%.*s] dlg->uas_tran=[%p]\n", dlg, dlg->callid.len, dlg->callid.s, dlg->tag[CALLER_LEG].len, dlg->tag[CALLER_LEG].s, dlg->param.len, dlg->param.s, dlg->uas_tran); /* add the record in hash table */ dlg->db_flag = INSERTDB_FLAG; return b2b_htable_insert(server_htable, dlg, hash_index, B2B_SERVER, 0); error: if(dlg) shm_free(dlg); return NULL; }