/** * Alters the saved dlg_t routes for the dialog by removing * the first routes before myself. * This is requiered because half of the RRset is useless. * @param d - the dialog to modify the Record-Routes * @param dir - the direction */ void alter_dialog_route_set(dlg_t *d,enum s_dialog_direction dir) { rr_t *r,*r_new; str p; /*this is going to point to the scscf uri*/ switch (dir) { case DLG_MOBILE_ORIGINATING: p = scscf_record_route_mo_uri; break; case DLG_MOBILE_TERMINATING: p = scscf_record_route_mt_uri; break; default: return; } for(r=d->route_set;r!=NULL;r=r->next) { if (r->nameaddr.uri.len>=p.len && strncasecmp(r->nameaddr.uri.s,p.s,r->nameaddr.uri.len)==0) { r_new = r->next; r->next = NULL; shm_free_rr(&d->route_set); d->route_set = r_new; return; } } }
int preset_dialog_route(dlg_t* dialog, str *route) { rr_t *old_r, *r = NULL; int res; /* check parameters */ if ((!dialog) || (is_str_empty(route))) { ERR("bad parameters\n"); return -1; } if (dialog->state != DLG_NEW) { ERR("Dialog is not in DLG_NEW state\n"); return -1; } if (parse_rr_body(route->s, route->len, &r) < 0) { ERR("can't parse given route\n"); return -1; } if (!r) { ERR("empty route\n"); return -1; } old_r = dialog->route_set; dialog->route_set = NULL; res = shm_duplicate_rr(&dialog->route_set, r); if (r) free_rr(&r); if (res < 0) { /* return old routeset to its place */ dialog->route_set = old_r; ERR("can't duplicate route\n"); return -1; } /* free old route */ if (old_r) shm_free_rr(&old_r); res = tmb.calculate_hooks(dialog); if (res < 0) { ERR("Error while calculating hooks\n"); return -2; } return 0; }
/* * Destroy a dialog state */ void free_dlg(dlg_t* _d) { if (!_d) return; if (_d->id.call_id.s) shm_free(_d->id.call_id.s); if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s); if (_d->id.loc_tag.s) shm_free(_d->id.loc_tag.s); if (_d->loc_uri.s) shm_free(_d->loc_uri.s); if (_d->rem_uri.s) shm_free(_d->rem_uri.s); if (_d->rem_target.s) shm_free(_d->rem_target.s); if (_d->dst_uri.s) shm_free(_d->dst_uri.s); /* Free all routes in the route set */ shm_free_rr(&_d->route_set); shm_free(_d); }
/** * Alters the saved dlg_t routes for the dialog by removing * @param d - the dialog to modify the Record-Routes * @param dir - the direction */ void alter_dialog_route_set(dlg_t *d,enum p_dialog_direction dir,enum release_call_situation situation) { rr_t *r; rr_t *r_new; str p; /*this is going to point to the scscf uri*/ switch (dir) { case DLG_MOBILE_ORIGINATING: p = pcscf_record_route_mo_uri; break; case DLG_MOBILE_TERMINATING: p = pcscf_record_route_mt_uri; break; default: return; } d->route_set=revert_route(d->route_set); //LOG(L_CRIT,"Looking for <%.*s> in\n",p.len,p.s); //for(r=d->route_set;r!=NULL;r=r->next) //LOG(L_CRIT,"<%.*s>\n",r->nameaddr.uri.len,r->nameaddr.uri.s); for(r=d->route_set;r!=NULL;r=r->next) { if (r->nameaddr.uri.len>=p.len && strncasecmp(r->nameaddr.uri.s,p.s,r->nameaddr.uri.len)==0) { r_new=r->next; r->next=NULL; shm_free_rr(&d->route_set); d->route_set = r_new; return; } } }
/* * Extract all necessary information from a response and put it * in a dialog structure */ static inline int response2dlg(struct sip_msg* _m, dlg_t* _d) { str contact, rtag; rtag.s=0; /* Parse the whole message, we will need all Record-Route headers */ if (parse_headers(_m, HDR_EOH_F, 0) == -1) { LOG(L_ERR, "response2dlg(): Error while parsing headers\n"); return -1; } if (get_contact_uri(_m, &contact) < 0) return -2; if (_d->rem_target.s) { shm_free(_d->rem_target.s); _d->rem_target.s = 0; _d->rem_target.len = 0; } if (_d->dst_uri.s) { shm_free(_d->dst_uri.s); _d->dst_uri.s = 0; _d->dst_uri.len = 0; } if (contact.len && str_duplicate(&_d->rem_target, &contact) < 0) return -3; if (get_to_tag(_m, &rtag) < 0) goto err1; //Its unlikely needed to update the tag with responses but for some reason i do it if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s); if (rtag.len && str_duplicate(&_d->id.rem_tag, &rtag) < 0) goto err1; if (_d->route_set) shm_free_rr(&_d->route_set); if (get_route_set(_m, &_d->route_set, REVERSE_ORDER) < 0) goto err2; return 0; err2: if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s); _d->id.rem_tag.s = 0; _d->id.rem_tag.len = 0; err1: if (_d->rem_target.s) shm_free(_d->rem_target.s); _d->rem_target.s = 0; _d->rem_target.len = 0; return -4; }
/* * Destroy a dialog state */ void free_dlg(dlg_t* _d) { if (!_d) return; #ifdef DIALOG_CALLBACKS destroy_trans_dlg_callbacks(_d); #endif if (_d->id.call_id.s) shm_free(_d->id.call_id.s); if (_d->id.rem_tag.s) shm_free(_d->id.rem_tag.s); if (_d->id.loc_tag.s) shm_free(_d->id.loc_tag.s); if (_d->loc_uri.s) shm_free(_d->loc_uri.s); if (_d->rem_uri.s) shm_free(_d->rem_uri.s); if (_d->rem_target.s) shm_free(_d->rem_target.s); if (_d->dst_uri.s) shm_free(_d->dst_uri.s); /* Free all routes in the route set */ shm_free_rr(&_d->route_set); shm_free(_d); }
/* * Create a copy of route set either in normal or reverse order */ static inline int get_route_set(struct sip_msg* _m, rr_t** _rs, unsigned char _order) { struct hdr_field* ptr; rr_t* last, *p, *t; last = 0; ptr = _m->record_route; while(ptr) { if (ptr->type == HDR_RECORDROUTE_T) { if (parse_rr(ptr) < 0) { LOG(L_ERR, "get_route_set(): Error while parsing Record-Route body\n"); goto error; } p = (rr_t*)ptr->parsed; if (shm_duplicate_rr(&t, p) < 0) { LOG(L_ERR, "get_route_set(): Error while duplicating rr_t\n"); goto error; } if (!*_rs) *_rs = t; if (last) last->next = t; last = t; while (last->next) last = last->next; /* !!! there may be more routes in one hdr field !!! */ } ptr = ptr->next; } if ((*_rs) && (_order != NORMAL_ORDER)) { /* better to revert the route outside of cycle above */ *_rs = revert_route(*_rs); } return 0; error: shm_free_rr(_rs); return -1; }
/* * Duplicate a single rr_t structure using pkg_malloc or shm_malloc */ static inline int do_duplicate_rr(rr_t** _new, rr_t* _r, int _shm, int _first) { int len, ret; rr_t* res, *prev, *it; if (!_new || !_r) { LM_ERR("invalid parameter value\n"); return -1; } prev = NULL; *_new = NULL; it = _r; while(it) { if (it->params) { len = it->params->name.s + it->params->len - it->nameaddr.name.s; } else { len = it->nameaddr.len; } if (_shm) res = shm_malloc(sizeof(rr_t) + len); else res = pkg_malloc(sizeof(rr_t) + len); if (!res) { LM_ERR("no shm memory left\n"); goto error; } memcpy(res, it, sizeof(rr_t)); res->nameaddr.name.s = (char*)res + sizeof(rr_t); memcpy(res->nameaddr.name.s, it->nameaddr.name.s, len); if (_shm) { ret = shm_duplicate_params(&res->params, it->params); } else { ret = duplicate_params(&res->params, it->params); } if (ret < 0) { LM_ERR("failed to duplicate parameters\n"); if (_shm) shm_free(res); else pkg_free(res); goto error; } xlate_pointers(it, res); res->next=NULL; if(*_new==NULL) *_new = res; if (_first) return 0; if(prev) prev->next = res; prev = res; it = it->next; } return 0; error: if (_shm) shm_free_rr(_new); else free_rr(_new); *_new = NULL; return -1; }