/*usage: dlg: the dialog to add cseq, contact & record_route * msg: sip message * flag: 0-for a request(INVITE), * 1- for a reply(200 ok) * * 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 */ static int init_leg_info( struct dlg_cell *dlg, struct sip_msg *msg, struct cell* t, str *tag,str *mangled_from,str *mangled_to) { unsigned int skip_recs; str cseq; str contact; str rr_set; int is_req; is_req = (msg->first_line.type==SIP_REQUEST)?1:0; /* extract the cseq number as string */ if (is_req) { /* cseq */ 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; /* routing info */ skip_recs = 0; get_routing_info(msg, is_req, &skip_recs, &contact, &rr_set); dlg->from_rr_nb = skip_recs; } else { /* use the same as in invite cseq in caller leg */ cseq = dlg->legs[DLG_CALLER_LEG].inv_cseq; if ((dlg->flags & DLG_FLAG_TOPHIDING) && (msg->REPLY_STATUS<200 && msg->REPLY_STATUS>100)) { /* save contact && rr_set , may need need to route requests * before the INVITE transaction terminates */ get_routing_info(msg,is_req,0,&contact,&rr_set); } else { /* no need to save these here, wait for final response */ rr_set.len = contact.len = 0; rr_set.s = contact.s = NULL; } } LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n", rr_set.len, ZSW(rr_set.s), contact.len, ZSW(contact.s), cseq.len, cseq.s, msg->rcv.bind_address->sock_str.len, msg->rcv.bind_address->sock_str.s); if (dlg_add_leg_info( dlg, tag, &rr_set, &contact, &cseq, msg->rcv.bind_address,mangled_from,mangled_to)!=0) { LM_ERR("dlg_add_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; }
/** * replicates a confirmed dialog from another OpenSIPS instance * by reading the relevant information using the Binary Packet Interface */ int dlg_replicated_create(struct dlg_cell *cell, str *ftag, str *ttag, int safe) { int next_id, h_entry; unsigned int dir, dst_leg; str callid, from_uri, to_uri, from_tag, to_tag; str cseq1,cseq2,contact1,contact2,rroute1,rroute2,mangled_fu,mangled_tu; str sock, vars, profiles; struct dlg_cell *dlg = NULL; struct socket_info *caller_sock, *callee_sock; struct dlg_entry *d_entry; if_update_stat(dlg_enable_stats, processed_dlgs, 1); LM_DBG("Received replicated dialog!\n"); if (!cell) { bin_pop_str(&callid); bin_pop_str(&from_tag); bin_pop_str(&to_tag); bin_pop_str(&from_uri); bin_pop_str(&to_uri); dlg = get_dlg(&callid, &from_tag, &to_tag, &dir, &dst_leg); h_entry = dlg_hash(&callid); d_entry = &d_table->entries[h_entry]; if (safe) dlg_lock(d_table, d_entry); if (dlg) { LM_DBG("Dialog with ci '%.*s' is already created\n", callid.len, callid.s); unref_dlg_unsafe(dlg, 1, d_entry); dlg_unlock(d_table, d_entry); return 0; } dlg = build_new_dlg(&callid, &from_uri, &to_uri, &from_tag); if (!dlg) { LM_ERR("Failed to create replicated dialog!\n"); goto pre_linking_error; } } else { h_entry = dlg_hash(&cell->callid); d_entry = &d_table->entries[h_entry]; if (safe) dlg_lock(d_table, d_entry); from_tag = *ftag; to_tag = *ttag; dlg = cell; } bin_pop_int(&dlg->h_id); bin_pop_int(&dlg->start_ts); bin_pop_int(&dlg->state); next_id = d_table->entries[dlg->h_entry].next_id; d_table->entries[dlg->h_entry].next_id = (next_id <= dlg->h_id) ? (dlg->h_id + 1) : next_id; if (bin_pop_str(&sock)) goto pre_linking_error; caller_sock = fetch_socket_info(&sock); if (bin_pop_str(&sock)) goto pre_linking_error; callee_sock = fetch_socket_info(&sock); if (!caller_sock || !callee_sock) { LM_ERR("Dialog in DB doesn't match any listening sockets\n"); goto pre_linking_error; } bin_pop_str(&cseq1); bin_pop_str(&cseq2); bin_pop_str(&rroute1); bin_pop_str(&rroute2); bin_pop_str(&contact1); bin_pop_str(&contact2); bin_pop_str(&mangled_fu); bin_pop_str(&mangled_tu); /* add the 2 legs */ if (dlg_add_leg_info(dlg, &from_tag, &rroute1, &contact1, &cseq1, caller_sock, 0, 0) != 0 || dlg_add_leg_info(dlg, &to_tag, &rroute2, &contact2, &cseq2, callee_sock, &mangled_fu, &mangled_tu) != 0) { LM_ERR("dlg_set_leg_info failed\n"); goto pre_linking_error; } dlg->legs_no[DLG_LEG_200OK] = DLG_FIRST_CALLEE_LEG; /* link the dialog into the hash */ dlg->h_id = d_entry->next_id++; if (!d_entry->first) d_entry->first = d_entry->last = dlg; else { d_entry->last->next = dlg; dlg->prev = d_entry->last; d_entry->last = dlg; } dlg->ref++; d_entry->cnt++; bin_pop_str(&vars); bin_pop_str(&profiles); bin_pop_int(&dlg->user_flags); bin_pop_int(&dlg->flags); bin_pop_int((void *)&dlg->tl.timeout); bin_pop_int(&dlg->legs[DLG_CALLER_LEG].last_gen_cseq); bin_pop_int(&dlg->legs[callee_idx(dlg)].last_gen_cseq); if (dlg->tl.timeout <= (unsigned int)time(0)) dlg->tl.timeout = 0; else dlg->tl.timeout -= (unsigned int)time(0); /* restore the timer values */ if (insert_dlg_timer(&dlg->tl, (int)dlg->tl.timeout) != 0) { LM_CRIT("Unable to insert 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->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); goto error; } if (dlg->state == DLG_STATE_CONFIRMED_NA || dlg->state == DLG_STATE_CONFIRMED) active_dlgs_cnt++; /* reference the dialog as kept in the timer list */ ref_dlg_unsafe(dlg, 1); LM_DBG("Received initial timeout of %d for dialog %.*s, safe = %d\n",dlg->tl.timeout,callid.len,callid.s,safe); dlg->lifetime = 0; /* Do not replicate the pinging - we might terminate dialogs badly when running as backup if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) { if (insert_ping_timer(dlg) != 0) LM_CRIT("Unable to insert dlg %p into ping timer\n",dlg); else { ref_dlg_unsafe(dlg, 1); } } */ if (dlg_db_mode == DB_MODE_DELAYED) { /* to be later removed by timer */ ref_dlg_unsafe(dlg, 1); } if (vars.s && vars.len != 0) read_dialog_vars(vars.s, vars.len, dlg); dlg_unlock(d_table, d_entry); if (profiles.s && profiles.len != 0) read_dialog_profiles(profiles.s, profiles.len, dlg, 0, 1); if_update_stat(dlg_enable_stats, active_dlgs, 1); run_load_callback_per_dlg(dlg); return 0; pre_linking_error: dlg_unlock(d_table, d_entry); if (dlg) destroy_dlg(dlg); return -1; error: dlg_unlock(d_table, d_entry); if (dlg) unref_dlg(dlg, 1); return -1; }
static int load_dialog_info_from_db(int dlg_hash_size) { db_res_t * res; db_val_t * values; db_row_t * rows; int i, nr_rows; struct dlg_cell *dlg; str callid, from_uri, to_uri, from_tag, to_tag; str cseq1,cseq2,contact1,contact2,rroute1,rroute2,mangled_fu,mangled_tu; unsigned int next_id; int no_rows = 10; struct socket_info *caller_sock,*callee_sock; res = 0; if((nr_rows = select_entire_dialog_table(&res,&no_rows)) < 0) goto end; nr_rows = RES_ROW_N(res); do { LM_DBG("loading information from database for %i dialogs\n", nr_rows); rows = RES_ROWS(res); /* for every row---dialog */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values) || VAL_NULL(values+1)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", h_entry_column.len, h_entry_column.s, h_id_column.len, h_id_column.s); continue; } if (VAL_NULL(values+7) || VAL_NULL(values+8)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", start_time_column.len, start_time_column.s, state_column.len, state_column.s); continue; } if ( VAL_INT(values+8) == DLG_STATE_DELETED ) { LM_DBG("dialog already terminated -> skipping\n"); continue; } caller_sock = create_socket_info(values, 16); callee_sock = create_socket_info(values, 17); if (caller_sock == NULL || callee_sock == NULL) { LM_ERR("Dialog in DB doesn't match any listening sockets"); continue; } /*restore the dialog info*/ GET_STR_VALUE(callid, values, 2, 1, 0); GET_STR_VALUE(from_uri, values, 3, 1, 0); GET_STR_VALUE(from_tag, values, 4, 1, 0); GET_STR_VALUE(to_uri, values, 5, 1, 0); if((dlg=build_new_dlg(&callid, &from_uri, &to_uri, &from_tag))==0){ LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != VAL_INT(values)){ LM_ERR("inconsistent hash data in the dialog database: " "you may have restarted opensips using a different " "hash_size: please erase %.*s database and restart\n", dialog_table_name.len, dialog_table_name.s); shm_free(dlg); goto error; } /*link the dialog*/ link_dlg(dlg, 0); dlg->h_id = VAL_INT(values+1); next_id = d_table->entries[dlg->h_entry].next_id; d_table->entries[dlg->h_entry].next_id = (next_id < dlg->h_id) ? (dlg->h_id+1) : next_id; GET_STR_VALUE(to_tag, values, 6, 1, 1); dlg->start_ts = VAL_INT(values+7); dlg->state = VAL_INT(values+8); if (dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { active_dlgs_cnt++; } else if (dlg->state==DLG_STATE_EARLY) { early_dlgs_cnt++; } GET_STR_VALUE(cseq1, values, 10 , 1, 1); GET_STR_VALUE(cseq2, values, 11 , 1, 1); GET_STR_VALUE(rroute1, values, 12, 0, 0); GET_STR_VALUE(rroute2, values, 13, 0, 0); GET_STR_VALUE(contact1, values, 14, 0, 1); GET_STR_VALUE(contact2, values, 15, 0, 1); GET_STR_VALUE(mangled_fu, values, 24,0,1); GET_STR_VALUE(mangled_tu, values, 25,0,1); /* add the 2 legs */ if ( (dlg_add_leg_info( dlg, &from_tag, &rroute1, &contact1, &cseq1, caller_sock,0,0)!=0) || (dlg_add_leg_info( dlg, &to_tag, &rroute2, &contact2, &cseq2, callee_sock,&mangled_fu,&mangled_tu)!=0) ) { LM_ERR("dlg_set_leg_info failed\n"); /* destroy the dialog */ unref_dlg(dlg,1); continue; } dlg->legs_no[DLG_LEG_200OK] = DLG_FIRST_CALLEE_LEG; /* script variables */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, dlg); /* profiles */ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), dlg,0); /* script flags */ if (!VAL_NULL(values+20)) { dlg->user_flags = VAL_INT(values+20); } /* top hiding */ dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) dlg->flags |= DLG_FLAG_NEW; /* calculcate timeout */ dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (dlg->tl.timeout<=(unsigned int)time(0)) dlg->tl.timeout = 0; else dlg->tl.timeout -= (unsigned int)time(0); /* restore the timer values */ if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) { LM_CRIT("Unable to insert 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->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); /* destroy the dialog */ unref_dlg(dlg,1); continue; } /* reference the dialog as kept in the timer list */ ref_dlg(dlg,1); LM_DBG("current dialog timeout is %u\n", dlg->tl.timeout); dlg->lifetime = 0; dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); dlg->legs[callee_idx(dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) { if (0 != insert_ping_timer(dlg)) LM_CRIT("Unable to insert dlg %p into ping timer\n",dlg); else { /* reference dialog as kept in ping timer list */ ref_dlg(dlg,1); } } next_dialog: ; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH)) { if (dialog_dbf.fetch_result( dialog_db_handle, &res,no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); end: dialog_dbf.free_result(dialog_db_handle, res); return 0; error: dialog_dbf.free_result(dialog_db_handle, res); return -1; }
static int sync_dlg_db_mem(void) { db_res_t * res; db_val_t * values; db_row_t * rows; struct dlg_entry *d_entry; struct dlg_cell *it,*known_dlg,*dlg=NULL; int i, nr_rows,callee_leg_idx,next_id,db_timeout; int no_rows = 10; unsigned int db_caller_cseq,db_callee_cseq,dlg_caller_cseq,dlg_callee_cseq; struct socket_info *caller_sock,*callee_sock; str callid, from_uri, to_uri, from_tag, to_tag; str cseq1,cseq2,contact1,contact2,rroute1,rroute2,mangled_fu,mangled_tu; res = 0; if((nr_rows = select_entire_dialog_table(&res,&no_rows)) < 0) goto error; nr_rows = RES_ROW_N(res); do { LM_DBG("loading information from database for %i dialogs\n", nr_rows); rows = RES_ROWS(res); /* for every row---dialog */ for(i=0; i<nr_rows; i++){ values = ROW_VALUES(rows + i); if (VAL_NULL(values) || VAL_NULL(values+1)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", h_entry_column.len, h_entry_column.s, h_id_column.len, h_id_column.s); continue; } if (VAL_NULL(values+7) || VAL_NULL(values+8)) { LM_ERR("columns %.*s or/and %.*s cannot be null -> skipping\n", start_time_column.len, start_time_column.s, state_column.len, state_column.s); continue; } if ( VAL_INT(values+8) == DLG_STATE_DELETED ) { LM_DBG("dialog already terminated -> skipping\n"); continue; } /*restore the dialog info*/ GET_STR_VALUE(callid, values, 2, 1, 0); GET_STR_VALUE(from_tag, values, 4, 1, 0); GET_STR_VALUE(to_tag, values, 6, 1, 1); /* TODO - check about hash resize ? maybe hash was lowered & we overflow the hash */ known_dlg = 0; d_entry = &(d_table->entries[VAL_INT(values)]); for (it=d_entry->first;it;it=it->next) if (it->callid.len == callid.len && it->legs[DLG_CALLER_LEG].tag.len == from_tag.len && memcmp(it->callid.s,callid.s,callid.len)==0 && memcmp(it->legs[DLG_CALLER_LEG].tag.s,from_tag.s,from_tag.len)==0) { /* callid & ftag match */ callee_leg_idx = callee_idx(it); if (it->legs[callee_leg_idx].tag.len == to_tag.len && memcmp(it->legs[callee_leg_idx].tag.s,to_tag.s,to_tag.len)==0) { /* full dlg match */ known_dlg = it; break; } } if (known_dlg == 0) { LM_DBG("First seen dialog - load all stuff - callid = [%.*s]\n",callid.len,callid.s); GET_STR_VALUE(from_uri, values, 3, 1, 0); GET_STR_VALUE(to_uri, values, 5, 1, 0); caller_sock = create_socket_info(values, 16); callee_sock = create_socket_info(values, 17); if (caller_sock == NULL || callee_sock == NULL) { LM_ERR("Dialog in DB doesn't match any listening sockets"); continue; } /* first time we see this dialog - build it from scratch */ if((dlg=build_new_dlg(&callid, &from_uri, &to_uri, &from_tag))==0){ LM_ERR("failed to build new dialog\n"); goto error; } if(dlg->h_entry != VAL_INT(values)){ LM_ERR("inconsistent hash data in the dialog database: " "you may have restarted opensips using a different " "hash_size: please erase %.*s database and restart\n", dialog_table_name.len, dialog_table_name.s); shm_free(dlg); goto error; } /*link the dialog*/ link_dlg(dlg, 0); dlg->h_id = VAL_INT(values+1); next_id = d_table->entries[dlg->h_entry].next_id; d_table->entries[dlg->h_entry].next_id = (next_id < dlg->h_id) ? (dlg->h_id+1) : next_id; dlg->start_ts = VAL_INT(values+7); dlg->state = VAL_INT(values+8); if (dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { if_update_stat(dlg_enable_stats, active_dlgs, 1); } else if (dlg->state==DLG_STATE_EARLY) { if_update_stat(dlg_enable_stats, early_dlgs, 1); } GET_STR_VALUE(cseq1, values, 10 , 1, 1); GET_STR_VALUE(cseq2, values, 11 , 1, 1); GET_STR_VALUE(rroute1, values, 12, 0, 0); GET_STR_VALUE(rroute2, values, 13, 0, 0); GET_STR_VALUE(contact1, values, 14, 0, 1); GET_STR_VALUE(contact2, values, 15, 0, 1); GET_STR_VALUE(mangled_fu, values, 24,0,1); GET_STR_VALUE(mangled_tu, values, 25,0,1); /* add the 2 legs */ if ( (dlg_add_leg_info( dlg, &from_tag, &rroute1, &contact1, &cseq1, caller_sock,0,0)!=0) || (dlg_add_leg_info( dlg, &to_tag, &rroute2, &contact2, &cseq2, callee_sock,&mangled_fu,&mangled_tu)!=0) ) { LM_ERR("dlg_set_leg_info failed\n"); /* destroy the dialog */ unref_dlg(dlg,1); continue; } dlg->legs_no[DLG_LEG_200OK] = DLG_FIRST_CALLEE_LEG; /* script variables */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, dlg); /* profiles */ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), dlg,0); /* script flags */ if (!VAL_NULL(values+20)) { dlg->user_flags = VAL_INT(values+20); } /* top hiding */ dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) dlg->flags |= DLG_FLAG_NEW; /* calculcate timeout */ dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (dlg->tl.timeout<=(unsigned int)time(0)) dlg->tl.timeout = 0; else dlg->tl.timeout -= (unsigned int)time(0); /* restore the timer values */ if (0 != insert_dlg_timer( &(dlg->tl), (int)dlg->tl.timeout )) { LM_CRIT("Unable to insert 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->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); /* destroy the dialog */ unref_dlg(dlg,1); continue; } /* reference the dialog as kept in the timer list */ ref_dlg(dlg,1); LM_DBG("current dialog timeout is %u\n", dlg->tl.timeout); dlg->lifetime = 0; dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); dlg->legs[callee_idx(dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); if (dlg->flags & DLG_FLAG_PING_CALLER || dlg->flags & DLG_FLAG_PING_CALLEE) { if (0 != insert_ping_timer(dlg)) LM_CRIT("Unable to insert dlg %p into ping timer\n",dlg); else { /* reference dialog as kept in ping timer list */ ref_dlg(dlg,1); } } } else { /* we already saw this dialog before * check which is the newer version */ if (known_dlg->state > VAL_INT(values+8)) { LM_DBG("mem has a newer state - ignore \n"); /* we know a newer version compared to the DB * ignore it */ goto next_dialog; } else if (known_dlg->state == VAL_INT(values+8)) { LM_DBG("mem has same state as DB \n"); /* same state :-( no way to tell which is newer */ /* play nice and store longest timeout, although not always correct*/ db_timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (db_timeout<=(unsigned int)time(0)) db_timeout = 0; else db_timeout -= (unsigned int)time(0); if (known_dlg->tl.timeout < db_timeout) known_dlg->tl.timeout = db_timeout; /* check with is newer cseq for caller leg */ if (!VAL_NULL(values+10)) { cseq1.s = VAL_STR(values+10).s; cseq1.len = strlen(cseq1.s); str2int(&cseq1,&db_caller_cseq); str2int(&known_dlg->legs[DLG_CALLER_LEG].r_cseq,&dlg_caller_cseq); /* Is DB cseq newer ? */ if (db_caller_cseq > dlg_caller_cseq) { if (known_dlg->legs[DLG_CALLER_LEG].r_cseq.len < cseq1.len) { known_dlg->legs[DLG_CALLER_LEG].r_cseq.s = shm_realloc(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.len); if (!known_dlg->legs[DLG_CALLER_LEG].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.s,cseq1.len); known_dlg->legs[DLG_CALLER_LEG].r_cseq.len = cseq1.len; } } else { /* DB has a null cseq - just keep * what we have so far */ ; } /* check with is newer cseq for caller leg */ if (!VAL_NULL(values+11)) { cseq2.s = VAL_STR(values+11).s; cseq2.len = strlen(cseq2.s); callee_leg_idx = callee_idx(known_dlg); str2int(&cseq2,&db_callee_cseq); str2int(&known_dlg->legs[callee_leg_idx].r_cseq,&dlg_callee_cseq); /* Is DB cseq newer ? */ if (db_callee_cseq > dlg_callee_cseq) { if (known_dlg->legs[callee_leg_idx].r_cseq.len < cseq2.len) { known_dlg->legs[callee_leg_idx].r_cseq.s = shm_realloc(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.len); if (!known_dlg->legs[callee_leg_idx].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.s,cseq2.len); known_dlg->legs[callee_leg_idx].r_cseq.len = cseq2.len; } } else { /* DB has a null cseq - just keep * what we have so far */ ; } /* update ping cseqs, whichever is newer */ if (known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq < (unsigned int)(VAL_INT(values+21))) known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); if (known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq < (unsigned int)(VAL_INT(values+22))) known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); /* update script variables * if already found, delete the old ones * and replace with new one */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, known_dlg); /* skip flags - keep what we have - anyway can't tell which is new */ /* profiles - do not insert into a profile * is dlg is already in that profile*/ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), known_dlg,1); } else { /* DB has newer state, just update fields from DB */ LM_DBG("DB has newer state \n"); /* set new state */ known_dlg->state = VAL_INT(values+8); /* update timeout */ known_dlg->tl.timeout = (unsigned int)(VAL_INT(values+9)) + get_ticks(); if (known_dlg->tl.timeout<=(unsigned int)time(0)) known_dlg->tl.timeout = 0; else known_dlg->tl.timeout -= (unsigned int)time(0); /* update cseqs */ if (!VAL_NULL(values+10)) { cseq1.s = VAL_STR(values+10).s; cseq1.len = strlen(cseq1.s); if (known_dlg->legs[DLG_CALLER_LEG].r_cseq.len < cseq1.len) { known_dlg->legs[DLG_CALLER_LEG].r_cseq.s = shm_realloc(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.len); if (!known_dlg->legs[DLG_CALLER_LEG].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[DLG_CALLER_LEG].r_cseq.s,cseq1.s,cseq1.len); known_dlg->legs[DLG_CALLER_LEG].r_cseq.len = cseq1.len; } if (!VAL_NULL(values+11)) { cseq2.s = VAL_STR(values+11).s; cseq2.len = strlen(cseq1.s); callee_leg_idx = callee_idx(known_dlg); if (known_dlg->legs[callee_leg_idx].r_cseq.len < cseq2.len) { known_dlg->legs[callee_leg_idx].r_cseq.s = shm_realloc(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.len); if (!known_dlg->legs[callee_leg_idx].r_cseq.s) { LM_ERR("no more shm\n"); goto next_dialog; } } memcpy(known_dlg->legs[callee_leg_idx].r_cseq.s,cseq2.s,cseq2.len); known_dlg->legs[callee_leg_idx].r_cseq.len = cseq2.len; } /* update ping cseqs */ known_dlg->legs[DLG_CALLER_LEG].last_gen_cseq = (unsigned int)(VAL_INT(values+21)); known_dlg->legs[callee_idx(known_dlg)].last_gen_cseq = (unsigned int)(VAL_INT(values+22)); /* update flags */ known_dlg->flags = VAL_INT(values+23); if (dlg_db_mode==DB_MODE_SHUTDOWN) known_dlg->flags |= DLG_FLAG_NEW; /* update script variables * if already found, delete the old one * and replace with new one */ if (!VAL_NULL(values+18)) read_dialog_vars( VAL_STR(values+18).s, VAL_STR(values+18).len, known_dlg); /* profiles - do not insert into a profile * is dlg is already in that profile*/ if (!VAL_NULL(values+19)) read_dialog_profiles( VAL_STR(values+19).s, strlen(VAL_STR(values+19).s), known_dlg,1); } } next_dialog: ; } /* any more data to be fetched ?*/ if (DB_CAPABILITY(dialog_dbf, DB_CAP_FETCH)) { if (dialog_dbf.fetch_result( dialog_db_handle, &res,no_rows) < 0) { LM_ERR("fetching more rows failed\n"); goto error; } nr_rows = RES_ROW_N(res); } else { nr_rows = 0; } }while (nr_rows>0); return 0; error: return -1; }