/** * Creates a new s_dialog structure. * Does not add the structure to the list * @param call_id - call_id of the dialog * @param aor - aor of the user * @param dir - the direction * @returns the new s_dialog* or NULL s_dialog */ s_dialog* new_s_dialog(str call_id,str aor, enum s_dialog_direction dir) { s_dialog *d; if (!s_dialog_count_increment()) return 0; d = shm_malloc(sizeof(s_dialog)); if (!d) { LOG(L_ERR,"ERR:"M_NAME":new_s_dialog(): Unable to alloc %d bytes\n", sizeof(s_dialog)); goto error; } memset(d,0,sizeof(s_dialog)); d->hash = get_s_dialog_hash(call_id); STR_SHM_DUP(d->call_id,call_id,"shm"); STR_SHM_DUP(d->aor,aor,"shm"); d->direction = dir; d->is_releasing = 0; return d; error: out_of_memory: if (d){ shm_free(d); } s_dialog_count_decrement(); return 0; }
/** * Creates a new p_dialog structure. * Does not add the structure to the list. * @param call_id - call-id of the dialog * @param host - host that originates/terminates this dialog * @param port - port that originates/terminates this dialog * @param transport - transport that originates/terminates this dialog * @returns the new p_dialog* on success, or NULL on error; */ p_dialog* new_p_dialog(str call_id,str host,int port, int transport) { p_dialog *d; if (!p_dialog_count_increment()) return 0; d = shm_malloc(sizeof(p_dialog)); if (!d) { LOG(L_ERR,"ERR:"M_NAME":new_p_dialog(): Unable to alloc %d bytes\n", sizeof(p_dialog)); goto error; } memset(d,0,sizeof(p_dialog)); d->hash = get_p_dialog_hash(call_id); STR_SHM_DUP(d->call_id,call_id,"shm"); STR_SHM_DUP(d->host,host,"shm"); d->port = port; d->transport = transport; return d; error: out_of_memory: if (d){ if (d->call_id.s) shm_free(d->call_id.s); if (d->host.s) shm_free(d->host.s); shm_free(d); } p_dialog_count_decrement(); return 0; }
/** * Creates a new lrf_dialog structure. * Does not add the structure to the list. * @param call_id - call-id of the dialog * @param target_uri - target of the dialog * @returns the new lrf_dialog* on success, or NULL on error; */ lrf_dialog* new_lrf_dialog(str call_id, str target_uri) { lrf_dialog *d; if (!lrf_dialog_count_increment()) return 0; d = shm_malloc(sizeof(lrf_dialog)); if (!d) { LOG(L_ERR,"ERR:"M_NAME":new_lrf_dialog(): Unable to alloc %d bytes\n", sizeof(lrf_dialog)); goto error; } memset(d,0,sizeof(lrf_dialog)); d->hash = get_lrf_dialog_hash(call_id); STR_SHM_DUP(d->call_id,call_id,"shm"); if(target_uri.len>0 && target_uri.s!=NULL) STR_SHM_DUP(d->target_uri, target_uri, "shm"); return d; error: out_of_memory: if (d){ if (d->call_id.s) shm_free(d->call_id.s); if (d->target_uri.s) shm_free(d->target_uri.s); shm_free(d); } lrf_dialog_count_decrement(); return 0; }
/*! * \brief Create and initialize new record structure * \param _dom domain name * \param _aor address of record * \param _r pointer to the new record * \return 0 on success, negative on failure */ int new_impurecord(str* _dom, str* public_identity, int reg_state, int barring, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, impurecord_t** _r) { *_r = (impurecord_t*) shm_malloc(sizeof (impurecord_t)); if (*_r == 0) { LM_ERR("no more shared memory\n"); return -1; } memset(*_r, 0, sizeof (impurecord_t)); //setup callback list (*_r)->cbs = (struct ulcb_head_list*) shm_malloc( sizeof (struct ulcb_head_list)); if ((*_r)->cbs == 0) { LM_CRIT("no more shared mem\n"); shm_free(*_r); *_r = 0; return -2; } (*_r)->cbs->first = 0; (*_r)->cbs->reg_types = 0; (*_r)->public_identity.s = (char*) shm_malloc(public_identity->len); if ((*_r)->public_identity.s == 0) { LM_ERR("no more shared memory\n"); shm_free(*_r); *_r = 0; return -2; } memcpy((*_r)->public_identity.s, public_identity->s, public_identity->len); (*_r)->public_identity.len = public_identity->len; (*_r)->domain = _dom; (*_r)->aorhash = core_hash(public_identity, 0, 0); (*_r)->reg_state = reg_state; if (barring >= 0) { //just in case we call this with no barring -1 will ignore (*_r)->barring = barring; } (*_r)->send_sar_on_delete = 1; /*defaults to 1 */ if (ccf1 && ccf1->len > 0) STR_SHM_DUP((*_r)->ccf1, *ccf1, "CCF1"); if (ccf2 && ccf2->len > 0) STR_SHM_DUP((*_r)->ccf2, *ccf2, "CCF2"); if (ecf1 && ecf1->len > 0) STR_SHM_DUP((*_r)->ecf1, *ecf1, "ECF1"); if (ecf2 && ecf2->len > 0) STR_SHM_DUP((*_r)->ecf2, *ecf2, "ECF2"); /*assign ims subscription profile*/ if (*s) { (*_r)->s = *s; lock_get((*_r)->s->lock); (*_r)->s->ref_count++; lock_release((*_r)->s->lock); } return 0; out_of_memory: LM_ERR("no more shared memory\n"); return -3; }
/** * Creates a registrar ipsec container. * This does not insert it in the registrar * the strings are duplicated in shm * @param spi_uc - SPI for UserEndpoint Client * @param spi_us - SPI for UserEndpoint Server * @param spi_pc - SPI for P-CSCF Client * @param spi_ps - SPI for UserEndpoint Server * @param port_uc - port for UserEndpoint Client * @param port_us - port for UserEndpoint Server * @param ealg_setkey - Cypher Algorithm * @param r_ealg - received Cypher Algorithm * @param ck_esp - Cypher Key * @param r_alg - received Integrity Algorithm * @param ik_esp - Integrity Key * @param prot - The IPSec protocol (either 'ah' or 'esp') * @param mod - The IPSec mode (either 'transport' or 'tunnel') * @returns the new r_ipsec* container or NULL on error */ r_ipsec* new_r_ipsec(unsigned int spi_uc,unsigned int spi_us,unsigned int spi_pc,unsigned int spi_ps,unsigned short int port_uc,unsigned short int port_us, str ealg_setkey,str r_ealg, str ck_esp,str alg_setkey,str r_alg, str ik_esp, str prot, str mod) { r_ipsec *ipsec; ipsec = shm_malloc(sizeof(r_ipsec)); if (!ipsec) { LOG(L_ERR,"ERR:"M_NAME":new_r_ipsec(): Unable to alloc %d bytes\n", sizeof(r_ipsec)); return 0; } memset(ipsec,0,sizeof(r_ipsec)); ipsec->spi_uc = spi_uc; ipsec->spi_us = spi_us; ipsec->spi_pc = spi_pc; ipsec->spi_ps = spi_ps; ipsec->port_uc = port_uc; ipsec->port_us = port_us; STR_SHM_DUP(ipsec->ealg,ealg_setkey,"new_r_ipsec"); STR_SHM_DUP(ipsec->r_ealg,r_ealg,"new_r_ipsec"); STR_SHM_DUP(ipsec->alg,alg_setkey,"new_r_ipsec"); STR_SHM_DUP(ipsec->r_alg,r_alg,"new_r_ipsec"); STR_SHM_DUP(ipsec->ck,ck_esp,"new_r_ipsec"); STR_SHM_DUP(ipsec->ik,ik_esp,"new_r_ipsec"); STR_SHM_DUP(ipsec->prot,prot,"new_r_ipsec"); STR_SHM_DUP(ipsec->mod,mod,"new_r_ipsec"); return ipsec; out_of_memory: if (ipsec) free_r_ipsec(ipsec); return 0; }
/** * Save the Record-routes for a dialog. * @param msg - the SIP message to extract RRs from * @param str1 - the direction to know if to reverse the RR list or not * @param d - dialog to save to */ void save_dialog_routes(struct sip_msg* msg, char* str1,p_dialog *d) { int i; rr_t *rr,*ri; struct hdr_field *hdr; if (d->routes){ for(i=0;i<d->routes_cnt;i++) shm_free(d->routes[i].s); shm_free(d->routes); d->routes = 0; } d->routes_cnt = 0; for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){ rr = (rr_t*)hdr->parsed; for(ri=rr;ri;ri=ri->next) d->routes_cnt++; } d->routes = shm_malloc(sizeof(str)*d->routes_cnt); if (!d->routes){ LOG(L_ERR,"ERR:"M_NAME":save_dialog_routes(): Unable to alloc %d bytes\n", sizeof(str)*d->routes_cnt); d->routes_cnt = 0; return; } if (!str1) return; if (str1[0]=='o'||str1[0]=='0'||str1[0]=='O'){ /* originating - reverse order */ i = d->routes_cnt-1; for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){ rr = (rr_t*)hdr->parsed; for(ri=rr;ri;ri=ri->next){ STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm"); i--; } } }else{ /* terminating - normal order */ i = 0; for(hdr=cscf_get_next_record_route(msg,0);hdr;hdr=cscf_get_next_record_route(msg,hdr)){ rr = (rr_t*)hdr->parsed; for(ri=rr;ri;ri=ri->next){ STR_SHM_DUP(d->routes[i],ri->nameaddr.uri,"shm"); i++; } } } out_of_memory: return; }
/** * Creates a subscription based on the given parameters. * @param req_uri - the AOR of the user to subcribe to * @param from - the From header * @param duration - expires time in seconds * @param asserted_identity - P-Asserted-Identity-Header to use * @returns the r_notification or NULL on error */ r_subscription* new_r_subscription(str req_uri,int duration) { r_subscription *s=0; s = shm_malloc(sizeof(r_subscription)); if (!s){ LOG(L_ERR,"ERR:"M_NAME":new_r_subscription: Error allocating %d bytes\n", sizeof(r_subscription)); goto error; } memset(s,0,sizeof(r_subscription)); STR_SHM_DUP(s->req_uri,req_uri,"new_r_subscription"); if (!s->req_uri.s) goto error; s->duration = duration; s->expires = 0; return s; error: out_of_memory: if (s->req_uri.s) shm_free(s->req_uri.s); if (s) shm_free(s); return 0; }
/** * Creates a registrar public id subscriber * This does not insert it in the registrar * @param subscriber - the contact of the subscribption - the subscriber * @param event - what event to subscribe to * @param expires - time of expiration * @param dialog - dialog for the subscription * @returns the r_subscriber created, NULL on error */ r_subscriber* new_r_subscriber(str subscriber,int event,int expires,dlg_t *dialog) { r_subscriber *s; s = shm_malloc(sizeof(r_subscriber)); if (!s) { LOG(L_ERR,"ERR:"M_NAME":new_r_subscriber(): Unable to alloc %d bytes\n", sizeof(r_subscriber)); goto error; } memset(s,0,sizeof(r_subscriber)); STR_SHM_DUP(s->subscriber,subscriber,"new_r_subscriber"); s->event = event; s->expires = expires; s->dialog = dialog; return s; error: if (s){ if (s->subscriber.s) shm_free(s->subscriber.s); shm_free(s); } return 0; }
/** * Creates a registrar contact * This does not insert it in the registrar * @param host - the host part of the contact, in string * @param port - the port number of the contact * @param transport - the transport of the contact * @param uri - URI of the contact * @param reg_state - Registration state * @param expires - expires in * @param service_route - array of service routes * @param service_route_cnt - the size of the array above * @returns the new r_contact* or NULL on error */ r_contact* new_r_contact(str host,int port,int transport,str uri,enum Reg_States reg_state,int expires, str *service_route,int service_route_cnt, r_reg_type sos_flag) { r_contact *c; int i; c = shm_malloc(sizeof(r_contact)); if (!c) { LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n", sizeof(r_contact)); goto error; } memset(c,0,sizeof(r_contact)); STR_SHM_DUP(c->host,host,"new_r_contact"); c->port = port; c->transport = transport; c->hash = get_contact_hash(host,port,transport,r_hash_size); STR_SHM_DUP(c->uri,uri,"new_r_contact"); c->reg_state = reg_state; c->expires = expires; c->sos_flag = sos_flag; if (service_route_cnt && service_route){ c->service_route = shm_malloc(service_route_cnt*sizeof(str)); if (!c->service_route){ LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n", service_route_cnt*sizeof(str)); goto error; } for(i=0;i<service_route_cnt;i++) STR_SHM_DUP(c->service_route[i],service_route[i],"new_r_contact"); c->service_route_cnt = service_route_cnt; } return c; error: out_of_memory: if (c){ free_r_contact(c); } return 0; }
/** * Saves a dialog. * @param msg - the initial request * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_save_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; s_dialog *d; str aor; str uri,tag; str ruri; enum s_dialog_direction dir = get_dialog_direction(str1); if (!find_dialog_aor(msg,dir,&aor)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); if (is_s_dialog(call_id,aor)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n"); return CSCF_RETURN_FALSE; } d = add_s_dialog(call_id,aor,dir); if (!d) return CSCF_RETURN_FALSE; d->method = get_dialog_method(msg->first_line.u.request.method); STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm"); d->first_cseq = cscf_get_cseq(msg,0); d->last_cseq = d->first_cseq; d->state = DLG_STATE_INITIAL; d->expires = d_act_time()+60; cscf_get_from_tag(msg,&tag); cscf_get_from_uri(msg,&uri); ruri=cscf_get_identity_from_ruri(msg); tmb.new_dlg_uac(&call_id, &tag, d->first_cseq,&uri, &ruri, &d->dialog_c); tmb.new_dlg_uas(msg,99,&d->dialog_s); d_unlock(d->hash); // print_s_dialogs(L_INFO); return CSCF_RETURN_TRUE; }
r_security *new_r_security(str sec_header,r_security_type type,float q) { r_security *s=0; s = shm_malloc(sizeof(r_security)); if (!s){ LOG(L_ERR,"ERR:"M_NAME":save_contact_security: Error allocating %d bytes.\n",sizeof(r_security)); goto error ; } memset(s,0,sizeof(r_security)); s->type = type; s->q = q; STR_SHM_DUP(s->sec_header,sec_header,"save_contact_security"); if (!s->sec_header.s) goto error; return s; error: out_of_memory: if (s) shm_free(s); return 0; }
scscf_list* new_scscf_list(str call_id,scscf_entry *sl) { scscf_list *l; l = shm_malloc(sizeof(scscf_list)); if (!l) { LOG(L_ERR,"ERR:"M_NAME":new_scscf_list(): Unable to alloc %d bytes\n", sizeof(scscf_list)); goto error; } memset(l,0,sizeof(scscf_list)); STR_SHM_DUP(l->call_id,call_id,"shm"); l->list = sl; return l; error: out_of_memory: if (l){ shm_free(l); } return 0; }
/** * Creates a notification based on the given parameters * @param req_uri - the Request-URI for the NOTIFY * @param uri - uri to send to * @param subscription_state - the Subscription-State header value * @param event - the event * @param content_type - content type * @param content - content * @param dialog - dialog to send on * @returns the r_notification or NULL on error */ r_notification* new_r_notification(str req_uri,str uri,str subscription_state,str event, str content_type,str content,dlg_t *dialog,int version) { r_notification *n=0; str buf; char bufc[MAX_REGINFO_SIZE]; n = shm_malloc(sizeof(r_notification)); if (!n){ LOG(L_ERR,"ERR:"M_NAME":new_r_notification: Error allocating %d bytes\n", sizeof(r_notification)); goto error; } memset(n,0,sizeof(r_notification)); STR_SHM_DUP(n->req_uri,req_uri,"new_r_notification"); STR_SHM_DUP(n->uri,uri,"new_r_notification"); STR_SHM_DUP(n->subscription_state,subscription_state,"new_r_notification"); STR_SHM_DUP(n->event,event,"new_r_notification"); STR_SHM_DUP(n->content_type,content_type,"new_r_notification"); sprintf(bufc,content.s,version); buf.s = bufc; buf.len = strlen(bufc); STR_SHM_DUP(n->content,buf,"new_r_notification"); n->dialog = dialog; return n; error: out_of_memory: free_r_notification(n); return 0; }
int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c) { int i, has_rinstance=0; ppublic_t* ppublic_ptr; int is_default = 1, params_len; struct sip_uri sip_uri; char* p, *params, *sep; str rinstance = {0,0}; *_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t) + _contact->len + _ci->received_host.len + _ci->via_host.len); if (*_c == 0) { LM_ERR("no more shared memory\n"); return -1; } memset(*_c, 0, sizeof(pcontact_t)); LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n", _contact->len, _contact->s, _ci->num_public_ids, reg_state_to_string(_ci->reg_state)); p = (char*)((struct pcontact*)(*_c) + 1); (*_c)->aor.s = p; memcpy(p, _contact->s, _contact->len); p += _contact->len; (*_c)->aor.len = _contact->len; (*_c)->domain = (str*)_d; if (parse_uri((*_c)->aor.s, (*_c)->aor.len, &sip_uri) != 0) { LM_ERR("unable to determine contact host from uri [%.*s\n", (*_c)->aor.len, (*_c)->aor.s); shm_free((*_c)->aor.s); shm_free(*_c); *_c = 0; return -2; } /* is there an rinstance param */ LM_DBG("checking for rinstance"); /*check for alias - NAT */ params = sip_uri.sip_params.s; params_len = sip_uri.sip_params.len; while (params_len >= RINSTANCE_LEN) { if (strncmp(params, RINSTANCE, RINSTANCE_LEN) == 0) { has_rinstance = 1; break; } sep = memchr(params, 59 /* ; */, params_len); if (sep == NULL) { LM_DBG("no rinstance param\n"); break; } else { params_len = params_len - (sep - params + 1); params = sep + 1; } } if (has_rinstance) { rinstance.s = params + RINSTANCE_LEN; rinstance.len = params_len - RINSTANCE_LEN; sep = (char*)memchr(rinstance.s, 59 /* ; */, rinstance.len); if (sep != NULL){ rinstance.len = (sep-rinstance.s); } } (*_c)->rinstance.s = rinstance.s; (*_c)->rinstance.len = rinstance.len; (*_c)->contact_host.s = sip_uri.host.s; (*_c)->contact_host.len = sip_uri.host.len; (*_c)->contact_port = sip_uri.port_no?sip_uri.port_no:5060; (*_c)->contact_user.s = sip_uri.user.s; (*_c)->contact_user.len = sip_uri.user.len; (*_c)->expires = _ci->expires; (*_c)->reg_state = _ci->reg_state; // Add received Info: if (_ci->received_host.len > 0 && _ci->received_host.s) { (*_c)->received_host.s = p; memcpy(p, _ci->received_host.s, _ci->received_host.len); p += _ci->received_host.len; (*_c)->received_host.len = _ci->received_host.len; (*_c)->received_port = _ci->received_port; (*_c)->received_proto = _ci->received_proto; } if (_ci->via_host.len > 0 && _ci->via_host.s) { (*_c)->via_host.s = p; memcpy(p, _ci->via_host.s, _ci->via_host.len); p += _ci->via_host.len; (*_c)->via_host.len = _ci->via_host.len; (*_c)->via_port = _ci->via_port; (*_c)->via_proto = _ci->via_prot; } (*_c)->aorhash = get_aor_hash(_d, &_ci->via_host, _ci->via_port, _ci->via_prot); //setup public ids for (i=0; i<_ci->num_public_ids; i++) { if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default) if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) { LM_ERR("unable to create new ppublic\n"); } else { insert_ppublic(*_c, ppublic_ptr); } } //add the service routes if (_ci->num_service_routes > 0) { (*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str)); if (!(*_c)->service_routes) { LM_ERR("no more shm mem\n"); goto out_of_memory; } else { for (i = 0; i < _ci->num_service_routes; i++) { STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact"); } (*_c)->num_service_routes = _ci->num_service_routes; } } LM_DBG("New contact host:port [%.*s:%d]\n", (*_c)->contact_host.len, (*_c)->contact_host.s, (*_c)->contact_port); LM_DBG("New contact via host:port:proto: [%.*s:%d:%d]\n", (*_c)->via_host.len, (*_c)->via_host.s, (*_c)->via_port, (*_c)->via_proto); LM_DBG("New contact received host:port:proto: [%.*s:%d:%d]\n", (*_c)->received_host.len, (*_c)->received_host.s, (*_c)->received_port, (*_c)->received_proto); LM_DBG("New contact aorhash [%u]\n", (*_c)->aorhash); return 0; out_of_memory: return -1; }
void async_aar_callback(int is_timeout, void *param, AAAMessage *aaa, long elapsed_msecs) { struct cell *t = 0; unsigned int cdp_result; int result = CSCF_RETURN_ERROR; LM_DBG("Received AAR callback\n"); saved_transaction_t* data = (saved_transaction_t*) param; LM_DBG("received AAA answer"); if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("t_continue: transaction not found\n"); goto error; } else { LM_DBG("t_continue: transaction found\n"); } //we have T, lets restore our state (esp. for AVPs) set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); if (is_timeout != 0) { LM_ERR("Error timeout when sending AAR message via CDP\n"); counter_inc(ims_qos_cnts_h.media_aar_timeouts); goto error; } if (!aaa) { LM_ERR("Error sending message via CDP\n"); goto error; } counter_inc(ims_qos_cnts_h.media_aars); counter_add(ims_qos_cnts_h.media_aar_response_time, elapsed_msecs); counter_inc(ims_qos_cnts_h.media_aar_replies_received); /* Process the response to AAR, retrieving result code and associated Rx session ID */ if (rx_process_aaa(aaa, &cdp_result) < 0) { LM_ERR("Failed to process AAA from PCRF\n"); //puri.host.len, puri.host.s); goto error; } if (cdp_result >= 2000 && cdp_result < 3000) { LM_DBG("Success, received code: [%i] from PCRF for AAR request\n", cdp_result); counter_inc(ims_qos_cnts_h.successful_media_aars); LM_DBG("Auth session ID [%.*s]", aaa->sessionId->data.len, aaa->sessionId->data.s); if(!data->aar_update) { LM_DBG("This is an AAA response to an initial AAR"); counter_inc(ims_qos_cnts_h.active_media_rx_sessions); str * passed_rx_session_id = shm_malloc(sizeof (struct _str)); passed_rx_session_id->s = 0; passed_rx_session_id->len = 0; STR_SHM_DUP(*passed_rx_session_id, aaa->sessionId->data, "cb_passed_rx_session_id"); LM_DBG("passed rx session id [%.*s]", passed_rx_session_id->len, passed_rx_session_id->s); dlgb.register_dlgcb_nodlg(&data->callid, &data->ftag, &data->ttag, DLGCB_TERMINATED | DLGCB_DESTROY | DLGCB_EXPIRED | DLGCB_RESPONSE_WITHIN | DLGCB_CONFIRMED | DLGCB_FAILED, callback_dialog, (void*) (passed_rx_session_id), free_dialog_data); } result = CSCF_RETURN_TRUE; } else { LM_DBG("Received negative reply from PCRF for AAR Request\n"); counter_inc(ims_qos_cnts_h.failed_media_aars); //we don't free rx_authdata_p here - it is free-ed when the CDP session expires goto error; // if its not a success then that means i want to reject this call! } //set success response code AVP create_return_code(result); goto done; out_of_memory: error : //set failure response code create_return_code(result); done: if (t) tmb.unref_cell(t); //free memory if (aaa) cdpb.AAAFreeMessage(&aaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_transaction_global_data(data); }
int update_pcontact(struct udomain* _d, struct pcontact_info* _ci, struct pcontact* _c) //TODO: should prob move this to pcontact { int is_default = 1; ppublic_t* ppublic_ptr; int i; _c->reg_state = _ci->reg_state; if (_ci->expires > 0) { _c->expires = _ci->expires; } if (_ci->num_service_routes > 0 && _ci->service_routes) { //replace all existing service routes if (_c->service_routes) { //remove old service routes for (i=0; i<_c->num_service_routes; i++) { if (_c->service_routes[i].s) shm_free(_c->service_routes[i].s); shm_free(_c->service_routes); _c->service_routes=0; _c->num_service_routes=0; } } //now add the new service routes if (_ci->num_service_routes > 0) { _c->service_routes = shm_malloc(_ci->num_service_routes*sizeof(str)); if (!_c->service_routes) { LM_ERR("no more shm mem trying to allocate [%ld bytes]\n", _ci->num_service_routes*sizeof(str)); goto out_of_memory; } else { for (i=0; i<_ci->num_service_routes; i++) { STR_SHM_DUP(_c->service_routes[i], _ci->service_routes[i], "update_pcontact"); } _c->num_service_routes = _ci->num_service_routes; } } } if (_ci->num_public_ids > 0 && _ci->public_ids) { if (_c->head) { LM_DBG("ppublic's already exist.... .not updating\n"); } else { for (i = 0; i < _ci->num_public_ids; i++) { if (i > 0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default) if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr) != 0) { LM_ERR("unable to create new ppublic\n"); } else { insert_ppublic(_c, ppublic_ptr); } } } } // update received info (if info is available): if (_ci->received_host.len > 0) { if (_c->received_host.s) shm_free(_c->received_host.s); STR_SHM_DUP(_c->received_host, _ci->received_host, "update_pcontact"); } if (_ci->received_port > 0) _c->received_port = _ci->received_port; if (_ci->received_proto > 0) _c->received_proto = _ci->received_proto; //TODO: update path, etc run_ul_callbacks(PCSCF_CONTACT_UPDATE, _c); return 0; out_of_memory: return -1; }
/** * Updates a dialog. * If the initial request was: * - INVITE - refreshes the expiration or looks for the BYE and destroys the dialog * if found * - SUBSCRIBE - looks for the Subscription-state in NOTIFY, refreshes the expiration * and if terminated destroys the dialog * - When adding more dialogs, add the refreshal methods here or they will expire and will * be destroyed. Also add the termination to reduce the memory consumption and improve the * performance. * @param msg - the request/response * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int P_update_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; p_dialog *d; int response; int cseq; struct hdr_field *h=0; struct sip_msg *req=0; str host; int port,transport; int expires; str totag; time_t t_time=0; str ses_exp = {0,0}; str refresher = {0,0}; enum p_dialog_direction dir; dir = get_dialog_direction(str1); if (msg->first_line.type==SIP_REPLY) req = cscf_get_request_from_reply(msg); else req = msg; if (!find_dialog_contact(req,dir,&host,&port,&transport)){ LOG(L_ERR,"ERR:"M_NAME":P_update_dialog(%s): Error retrieving %s contact\n",str1,str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); d = get_p_dialog(call_id,host,port,transport,&dir); if (!d) d = get_p_dialog(call_id,host,port,transport,0); if (!d){ if (msg->first_line.type==SIP_REQUEST && msg->first_line.u.request.method.len == 3 && strncasecmp(msg->first_line.u.request.method.s,"ACK",3)){ /* to skip the ACK after a 4xx when the dialog was dropped already*/ return CSCF_RETURN_TRUE; }else{ LOG(L_CRIT,"ERR:"M_NAME":P_update_dialog: dialog does not exists!\n"); return CSCF_RETURN_FALSE; } } if (msg->first_line.type==SIP_REQUEST){ /* Request */ LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): Method <%.*s> \n",str1, msg->first_line.u.request.method.len,msg->first_line.u.request.method.s); cseq = cscf_get_cseq(msg,&h); if (cseq>d->last_cseq) d->last_cseq = cseq; if (get_dialog_method(msg->first_line.u.request.method) == DLG_METHOD_INVITE) { d->uac_supp_timer = supports_extension(msg, &str_ext_timer); ses_exp = cscf_get_session_expires_body(msg, &h); t_time = cscf_get_session_expires(ses_exp, &refresher); if (!t_time){ d->expires = d_act_time()+pcscf_dialogs_expiration_time; d->lr_session_expires = 0; } else { d->expires = d_act_time() + t_time; d->lr_session_expires = t_time; if (refresher.len) STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER"); } } else if (d->method == DLG_METHOD_SUBSCRIBE && msg->first_line.u.request.method.len == 6 && strncasecmp(msg->first_line.u.request.method.s,"NOTIFY",6)==0) { // Subscription-State header is mandatory for NOTIFY. See RFC 3265, Section 7.2 expires = cscf_get_subscription_state(msg); if (expires >= 0) { d->expires = d_act_time()+expires; } else { d->expires = d_act_time()+pcscf_dialogs_expiration_time; } } else { expires = cscf_get_expires_hdr(msg); if (expires >= 0) { LOG(L_INFO,"DBG:"M_NAME":P_update_dialog(%.*s): Update expiration time to %d via Expire header 2\n",call_id.len,call_id.s,expires); d->expires = d_act_time()+expires; } else { LOG(L_INFO,"INF:"M_NAME": update_dialog(%.*s): d->expires+=pcscf_dialogs_expiration_time 4\n",call_id.len,call_id.s); d->expires = d_act_time()+pcscf_dialogs_expiration_time; } d->lr_session_expires = 0; } }else{ /* Reply */ response = msg->first_line.u.reply.statuscode; LOG(L_DBG,"DBG:"M_NAME":P_update_dialog(%s): <%d> \n",str1,response); cseq = cscf_get_cseq(msg,&h); if (cseq==0 || h==0) return CSCF_RETURN_FALSE; if (d->first_cseq==cseq && d->method_str.len == ((struct cseq_body *)h->parsed)->method.len && strncasecmp(d->method_str.s,((struct cseq_body *)h->parsed)->method.s,d->method_str.len)==0 && d->state < DLG_STATE_CONFIRMED){ /* reply to initial request */ if (response<200 && response>100){ save_dialog_routes(msg,str1,d); d->state = DLG_STATE_EARLY; d->expires = d_act_time()+300; cscf_get_to_tag(msg,&totag); tmb.update_dlg_uas(d->dialog_s,response,&totag); tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH); }else if (response>=200 && response<300){ save_dialog_routes(msg,str1,d); d->state = DLG_STATE_CONFIRMED; update_dialog_on_reply(msg, d); cscf_get_to_tag(msg,&totag); tmb.update_dlg_uas(d->dialog_s,response,&totag); tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH); }else if (response>300){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); return P_drop_dialog(msg,str1,str2); } }else{ /* reply to subsequent request */ if (!req) req = cscf_get_request_from_reply(msg); /* destroy dialogs on specific methods */ switch (d->method){ case DLG_METHOD_OTHER: expires = cscf_get_expires_hdr(msg); if (expires >= 0) { d->expires = d_act_time()+expires; } else { d->expires = d_act_time()+pcscf_dialogs_expiration_time; } d->lr_session_expires = 0; break; case DLG_METHOD_INVITE: if (req && req->first_line.u.request.method.len==3 && strncasecmp(req->first_line.u.request.method.s,"BYE",3)==0){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); return P_drop_dialog(msg,str1,str2); } update_dialog_on_reply(msg, d); break; case DLG_METHOD_SUBSCRIBE: // if (req && req->first_line.u.request.method.len==9 && // strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0 && // cscf_get_expires_hdr(msg)==0){ // d->state = DLG_STATE_TERMINATED; // d_unlock(d->hash); // return P_drop_dialog(msg,str1,str2); // } if (req && req->first_line.u.request.method.len==6 && strncasecmp(req->first_line.u.request.method.s,"NOTIFY",6)==0){ expires = cscf_get_subscription_state(req); if (expires==0){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); return P_drop_dialog(msg,str1,str2); }else if (expires>0){ d->expires = d_act_time() + expires; } } break; } if (cseq>d->last_cseq) d->last_cseq = cseq; } } d_unlock(d->hash); print_p_dialogs(L_INFO); return CSCF_RETURN_TRUE; out_of_memory: d_unlock(d->hash); return CSCF_RETURN_ERROR; }
/** * Updates a dialog. * If the initial request was: * - INVITE - refreshes the expiration or looks for the BYE and destroys the dialog * if found * - SUBSCRIBE - looks for the Subscription-state in NOTIFY, refreshes the expiration * and if terminated destroys the dialog * - When adding more dialogs, add the refreshal methods here or they will expire and will * be destroyed. Also add the termination to reduce the memory consumption and improve the * performance. * @param msg - the request/response * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_update_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; s_dialog *d; int response; int cseq; struct hdr_field *h=0; struct sip_msg *req=0; int expires=0; str totag; time_t t_time; str ses_exp = {0,0}; str refresher = {0,0}; enum s_dialog_direction dir = get_dialog_direction(str1); // if (!find_dialog_aor(msg,str1,&aor)){ // req = cscf_get_request_from_reply(msg); // if (!find_dialog_aor(req,str1,&aor)){ // LOG(L_ERR,"ERR:"M_NAME":S_update_dialog(%s): Error retrieving %s contact\n",str1,str1); // return CSCF_RETURN_BREAK; // } // } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); d = get_s_dialog_dir(call_id,dir); // if (!d && msg->first_line.type==SIP_REPLY){ // /* Try to get the dialog from the request */ // if (!req) req = cscf_get_request_from_reply(msg); // if (!find_dialog_aor(req,str1,&aor)){ // LOG(L_ERR,"ERR:"M_NAME":S_update_dialog(%s): Error retrieving %s contact\n",str1,str1); // return CSCF_RETURN_BREAK; // } // d = get_s_dialog_dir(call_id,aor); // } if (!d){ LOG(L_INFO,"INFO:"M_NAME":S_update_dialog: dialog does not exists!\n"); return CSCF_RETURN_FALSE; } if (msg->first_line.type==SIP_REQUEST){ /* Request */ LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): Method <%.*s> \n",str1, msg->first_line.u.request.method.len,msg->first_line.u.request.method.s); cseq = cscf_get_cseq(msg,&h); if (cseq>d->last_cseq) d->last_cseq = cseq; if (get_dialog_method(msg->first_line.u.request.method) == DLG_METHOD_INVITE) { d->uac_supp_timer = supports_extension(msg, &str_ext_timer); ses_exp = cscf_get_session_expires_body(msg, &h); t_time = cscf_get_session_expires(ses_exp, &refresher); if (!t_time) { d->expires = d_act_time()+scscf_dialogs_expiration_time; d->lr_session_expires = 0; } else { d->expires = d_act_time() + t_time; d->lr_session_expires = t_time; if (refresher.len) STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER"); } } else if (d->method == DLG_METHOD_SUBSCRIBE && msg->first_line.u.request.method.len == 6 && strncasecmp(msg->first_line.u.request.method.s,"NOTIFY",6)==0) { // Subscription-State header is mandatory for NOTIFY. See RFC 3265, Section 7.2 expires = cscf_get_subscription_state(msg); if (expires >= 0) d->expires = d_act_time()+expires; else d->expires = d_act_time()+scscf_dialogs_expiration_time; } else { expires = cscf_get_expires_hdr(msg,0); if (expires >= 0) d->expires = d_act_time()+expires; else d->expires = d_act_time()+scscf_dialogs_expiration_time; d->lr_session_expires = 0; } }else{ /* Reply */ response = msg->first_line.u.reply.statuscode; LOG(L_DBG,"DBG:"M_NAME":S_update_dialog(%s): <%d> \n",str1,response); cseq = cscf_get_cseq(msg,&h); if (cseq==0 || h==0) return CSCF_RETURN_FALSE; if (d->first_cseq==cseq && d->method_str.len == ((struct cseq_body *)h->parsed)->method.len && strncasecmp(d->method_str.s,((struct cseq_body *)h->parsed)->method.s,d->method_str.len)==0 && d->state < DLG_STATE_CONFIRMED){ /* reply to initial request */ if (response<200){ d->state = DLG_STATE_EARLY; d->expires = d_act_time()+300; }else if (response>=200 && response<300){ d->state = DLG_STATE_CONFIRMED; update_dialog_on_reply(msg, d); /*I save the dialogs only here because * i only want to release confirmed dialogs*/ cscf_get_to_tag(msg,&totag); if (d->dialog_s){ tmb.update_dlg_uas(d->dialog_s,response,&totag); tmb.dlg_response_uac(d->dialog_c,msg,IS_NOT_TARGET_REFRESH); }else{ LOG(L_ERR,"ERR:S_update_dialog(): dialog_s for dialog was NULL!\n"); } }else if (response>300){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); struct cell * t = tmb.t_gett(); if(t->nr_of_outgoings < 2) return S_drop_dialog(msg,str1,str2); } }else{ /* reply to subsequent request */ if (!req) req = cscf_get_request_from_reply(msg); /* destroy dialogs on specific methods */ switch (d->method){ case DLG_METHOD_OTHER: d->expires = d_act_time()+scscf_dialogs_expiration_time; d->lr_session_expires = 0; break; case DLG_METHOD_INVITE: if (req && req->first_line.u.request.method.len==3 && strncasecmp(req->first_line.u.request.method.s,"BYE",3)==0){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); return S_drop_dialog(msg,str1,str2); } update_dialog_on_reply(msg, d); break; case DLG_METHOD_SUBSCRIBE: // if (req && req->first_line.u.request.method.len==9 && // strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0 && // cscf_get_expires_hdr(msg)==0){ // d->state = DLG_STATE_TERMINATED; // d_unlock(d->hash); // return P_dros_dialog(msg,str1,str2); // } if (req && req->first_line.u.request.method.len==6 && strncasecmp(req->first_line.u.request.method.s,"NOTIFY",6)==0){ expires = cscf_get_subscription_state(req); if (expires==0){ d->state = DLG_STATE_TERMINATED; d_unlock(d->hash); return S_drop_dialog(msg,str1,str2); }else if (expires>0){ d->expires = d_act_time() + expires; } } else if (req && req->first_line.u.request.method.len==9 && strncasecmp(req->first_line.u.request.method.s,"SUBSCRIBE",9)==0){ expires = cscf_get_expires_hdr(msg,0); if (expires >= 0) d->expires = d_act_time()+expires; else d->expires = d_act_time()+scscf_dialogs_expiration_time; } break; } if (cseq>d->last_cseq) d->last_cseq = cseq; } } d_unlock(d->hash); print_s_dialogs(L_INFO); return CSCF_RETURN_TRUE; out_of_memory: if (d) d_unlock(d->hash); return CSCF_RETURN_ERROR; }
/* update an existing impurecord. if one doesnt exist it will be created. * make sure yuo lock the domain before calling this and unlock it afterwards * return: 0 on success, -1 on failure */ int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) { int res; res = get_impurecord(_d, public_identity, _r); if (res != 0) { if (reg_state != IMPU_NOT_REGISTERED && s) { LM_DBG("No existing impu record for <%.*s>.... creating new one\n", public_identity->len, public_identity->s); res = insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r); //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored) (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn if (reg_state == IMPU_UNREGISTERED) { //update unreg expiry so the unreg record is not stored 'forever' (*_r)->expires = time(NULL) + unreg_validity; } if (res != 0) { LM_ERR("Unable to insert new IMPU for <%.*s>\n", public_identity->len, public_identity->s); return -1; } else { run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL); return 0; } } else { LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n"); return 0; } } //if we get here, we have a record to update LM_DBG("updating IMPU record with public identity for <%.*s>\n", public_identity->len, public_identity->s); (*_r)->reg_state = reg_state; if (reg_state == IMPU_UNREGISTERED) { //update unreg expiry so the unreg record is not stored 'forever' (*_r)->expires = time(NULL) + unreg_validity; } if (barring >= 0) (*_r)->barring = barring; if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete; if (ccf1) { if ((*_r)->ccf1.s) shm_free((*_r)->ccf1.s); STR_SHM_DUP((*_r)->ccf1, *ccf1, "SHM CCF1"); } if (ccf2) { if ((*_r)->ccf2.s) shm_free((*_r)->ccf2.s); STR_SHM_DUP((*_r)->ccf2, *ccf2, "SHM CCF2"); } if (ecf1) { if ((*_r)->ecf1.s) shm_free((*_r)->ecf1.s); STR_SHM_DUP((*_r)->ecf1, *ecf1, "SHM ECF1"); } if (ecf2) { if ((*_r)->ecf2.s) shm_free((*_r)->ecf2.s); STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2"); } if (s) { LM_DBG("we have a new ims_subscription\n"); if ((*_r)->s) { lock_get((*_r)->s->lock); if ((*_r)->s->ref_count == 1) { LM_DBG("freeing user data as no longer referenced\n"); free_ims_subscription_data((*_r)->s); //no need to release lock after this. its gone ;) (*_r)->s = 0; } else { (*_r)->s->ref_count--; LM_DBG("new ref count for ims sub is %d\n", (*_r)->s->ref_count); lock_release((*_r)->s->lock); } } (*_r)->s = *s; lock_get((*_r)->s->lock); (*_r)->s->ref_count++; lock_release((*_r)->s->lock); } run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL); return 0; out_of_memory: unlock_udomain(_d, public_identity); return -1; }
/** * Updates the r_contact with the new states * If not found, it will be inserted * \note Aquires the lock on the hash_slot on success, so release it when you are done. * @param host - the host part of the contact, in string * @param port - the port number of the contact * @param transport - the transport of the contact * @param uri - URI of the contact * @param reg_state - Registration state * @param expires - expires in * @param service_route - array of service routes * @param service_route_cnt - the size of the array above * @param pinhole - NAT pin hole * @param sos_flag - flag for Emergency Registration * @returns the updated added r_contact, 0 on error */ r_contact* update_r_contact(str host,int port,int transport, str *uri,enum Reg_States *reg_state,int *expires,str **service_route, int *service_route_cnt, r_nat_dest **pinhole, int *sos_flag) { r_contact *c=0; int i; r_reg_type sos_mask; if(sos_flag && (*sos_flag>0)) sos_mask = EMERG_REG; else sos_mask = NORMAL_REG; c = get_r_contact(host,port,transport, sos_mask); if (!c){ if (uri&®_state && expires && service_route && service_route_cnt) return pinhole?add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, *pinhole, sos_mask): add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, 0, sos_mask); else return 0; }else{ /* first drop the old temporary public ids */ if (c->reg_state==DEREGISTERED && reg_state && *reg_state==REGISTERED){ while(c->head){ del_r_public(c,c->head); } } if (uri) { if (c->uri.s) shm_free(c->uri.s); STR_SHM_DUP(c->uri,*uri,"update_r_contact"); } if (reg_state) c->reg_state = *reg_state; if (expires) c->expires = *expires; if (service_route){ if (c->service_route){ for(i=0;i<c->service_route_cnt;i++) if (c->service_route[i].s) shm_free(c->service_route[i].s); shm_free(c->service_route); c->service_route=0; c->service_route_cnt=0; } if (*service_route&&*service_route_cnt){ c->service_route = shm_malloc((*service_route_cnt)*sizeof(str)); if (!c->service_route){ LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n", (*service_route_cnt)*sizeof(str)); goto out_of_memory; }else{ for(i=0;i<*service_route_cnt;i++) STR_SHM_DUP(c->service_route[i],(*service_route)[i],"new_r_contact"); c->service_route_cnt = *service_route_cnt; } } } if (pinhole) c->pinhole = *pinhole; c->sos_flag = sos_mask; return c; } out_of_memory: return c; }
/** * Saves a dialog. * @param msg - the initial request * @param str1 - direction - "orig" or "term" * @param str2 - not used * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error */ int S_save_dialog(struct sip_msg* msg, char* str1, char* str2) { str call_id; s_dialog *d; str aor; char buf1[256],buf2[256]; str uri,tag,ruri,x; time_t t_time; str ses_exp = {0,0}; str refresher = {0,0}; str event = {0,0}; struct hdr_field *h; unsigned int hash; enum s_dialog_direction dir = get_dialog_direction(str1); if (!find_dialog_aor(msg,dir,&aor)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1); return CSCF_RETURN_BREAK; } call_id = cscf_get_call_id(msg,0); if (!call_id.len) return CSCF_RETURN_FALSE; LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s); if (is_s_dialog(call_id,aor,dir)){ LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n"); return CSCF_RETURN_TRUE; } d = add_s_dialog(call_id,aor,dir); if (!d) return CSCF_RETURN_FALSE; d->method = get_dialog_method(msg->first_line.u.request.method); STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm"); d->first_cseq = cscf_get_cseq(msg,0); d->last_cseq = d->first_cseq; d->state = DLG_STATE_INITIAL; d->uac_supp_timer = supports_extension(msg, &str_ext_timer); ses_exp = cscf_get_session_expires_body(msg, &h); t_time = cscf_get_session_expires(ses_exp, &refresher); if (!t_time) { d->expires = d_act_time() + 60; d->lr_session_expires = 0; } else { d->expires = d_act_time() + t_time; d->lr_session_expires = t_time; if (refresher.len) STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER"); } cscf_get_from_tag(msg,&tag); cscf_get_from_uri(msg,&x); uri.len = snprintf(buf1,256,"<%.*s>",x.len,x.s); uri.s = buf1; cscf_get_to_uri(msg,&x); ruri.len = snprintf(buf2,256,"<%.*s>",x.len,x.s); ruri.s = buf2; tmb.new_dlg_uac(&call_id, &tag, d->first_cseq,&uri, &ruri, &d->dialog_c); tmb.new_dlg_uas(msg,99,&d->dialog_s); event = cscf_get_event(msg); if (event.len){ STR_SHM_DUP(d->event,event,"shm"); } else d->event = event; d_unlock(d->hash); print_s_dialogs(L_INFO); return CSCF_RETURN_TRUE; out_of_memory: if (d){ hash = d->hash; del_s_dialog(d); d_unlock(hash); } return CSCF_RETURN_ERROR; }
/** * Updates the r_public with the new reg_state and ims_subscription values, with a previous lock on the registrar. * If not found, it will be inserted. * \note Aquires the lock on the hash_slot on success and if the lock is different from previous_lock, so release it * when you are done and if different then from previous lock. * @param aor - the address of record * @param locked_hash - the previous lock on the registrar * @param reg_state - new registration state, NULL if no update necessary * @param s - the new subscription attached, NULL if no update necessary * @returns the update r_public or NULL on error */ r_public* update_r_public_previous_lock(str aor,int locked_hash,enum Reg_States *reg_state,ims_subscription **s, str *ccf1, str *ccf2, str *ecf1, str *ecf2) { r_public *p=0; p = get_r_public_previous_lock(aor,locked_hash); if (!p){ if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){ p = add_r_public_previous_lock(aor,locked_hash,*reg_state,*s); if (!p) return p; if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } return p; } else return 0; }else{ if (reg_state) p->reg_state = *reg_state; if (*s) { if (p->s){ lock_get(p->s->lock); if (p->s->ref_count==1){ free_user_data(p->s); }else{ p->s->ref_count--; lock_release(p->s->lock); } } p->s = *s; lock_get(p->s->lock); p->s->ref_count++; lock_release(p->s->lock); } if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } return p; } out_of_memory: return p; }
int new_pcontact(struct udomain* _d, str* _contact, struct pcontact_info* _ci, struct pcontact** _c) { int i; ppublic_t* ppublic_ptr; int is_default = 1; struct sip_uri sip_uri; *_c = (pcontact_t*)shm_malloc(sizeof(pcontact_t)); if (*_c == 0) { LM_ERR("no more shared memory\n"); return -1; } memset(*_c, 0, sizeof(pcontact_t)); LM_DBG("New contact [<%.*s>] with %d associated IMPUs in state: [%s]\n", _contact->len, _contact->s, _ci->num_public_ids, reg_state_to_string(_ci->reg_state)); (*_c)->aor.s = (char*) shm_malloc(_contact->len); if ((*_c)->aor.s == 0) { LM_ERR("no more shared memory\n"); shm_free(*_c); *_c = 0; return -2; } memcpy((*_c)->aor.s, _contact->s, _contact->len); (*_c)->aor.len = _contact->len; (*_c)->domain = (str*)_d; if (parse_uri((*_c)->aor.s, (*_c)->aor.len, &sip_uri) != 0) { LM_ERR("unable to determine contact host from uri [%.*s\n", (*_c)->aor.len, (*_c)->aor.s); shm_free((*_c)->aor.s); shm_free(*_c); *_c = 0; return -2; } (*_c)->contact_host.s = sip_uri.host.s; (*_c)->contact_host.len = sip_uri.host.len; (*_c)->contact_port = sip_uri.port_no; (*_c)->contact_user.s = sip_uri.user.s; (*_c)->contact_user.len = sip_uri.user.len; if (hashing_type==0) { (*_c)->aorhash = core_hash(_contact, 0, 0); } else { (*_c)->aorhash = core_hash(&(*_c)->contact_host, 0, 0); } (*_c)->expires = _ci->expires; (*_c)->reg_state = _ci->reg_state; // Add received Info: if (_ci->received_host.len > 0 && _ci->received_host.s) { (*_c)->received_host.s = (char*) shm_malloc(_ci->received_host.len); if ((*_c)->received_host.s == 0) { LM_ERR("no more share memory\n"); shm_free((*_c)->aor.s); shm_free(*_c); *_c = 0; return -2; } memcpy((*_c)->received_host.s, _ci->received_host.s, _ci->received_host.len); (*_c)->received_host.len = _ci->received_host.len; (*_c)->received_port = _ci->received_port; (*_c)->received_proto = _ci->received_proto; } //setup public ids for (i=0; i<_ci->num_public_ids; i++) { if (i>0) is_default = 0; //only the first one is default - P-Associated-uri (first one is default) if (new_ppublic(&_ci->public_ids[i], is_default, &ppublic_ptr)!=0) { LM_ERR("unable to create new ppublic\n"); } else { insert_ppublic(*_c, ppublic_ptr); } } //add the service routes if (_ci->num_service_routes > 0) { (*_c)->service_routes = shm_malloc(_ci->num_service_routes * sizeof(str)); if (!(*_c)->service_routes) { LM_ERR("no more shm mem\n"); goto out_of_memory; } else { for (i = 0; i < _ci->num_service_routes; i++) { STR_SHM_DUP((*_c)->service_routes[i], _ci->service_routes[i], "new_pcontact"); } (*_c)->num_service_routes = _ci->num_service_routes; } } return 0; out_of_memory: return -1; }
/** * Updates the r_public with the new reg_state and ims_subscription values. * If not found, it will be inserted. * \note Aquires the lock on the hash_slot on success, so release it when you are done. * @param aor - the address of record * @param reg_state - new registration state, NULL if no update necessary * @param s - the new subscription attached, NULL if no update necessary * @returns the update r_public or NULL on error */ r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s, str *ccf1, str *ccf2, str *ecf1, str *ecf2) { r_public *p=0; //LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s); if ((*s)->wpsi) { p = get_r_public_wpsi(aor); } else { p = get_r_public(aor); } if (!p){ //LOG(L_DBG,"updating a new r_public profile\n"); if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){ p = add_r_public(aor,*reg_state,*s); if (!p) return p; if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } //LOG(L_DBG,"update_r_public(): it was actually adding\n"); return p; } else return 0; }else{ //LOG(L_DBG,"updating a not so new r_public profile\n"); if (reg_state) p->reg_state = *reg_state; if (*s) { if (p->s){ lock_get(p->s->lock); if (p->s->ref_count==1){ free_user_data(p->s); }else{ p->s->ref_count--; lock_release(p->s->lock); } } p->s = *s; lock_get(p->s->lock); p->s->ref_count++; lock_release(p->s->lock); if ((*s)->wpsi) { p->s=NULL; if (p->prev) p->prev->next=p->next; else registrar[r_hash_size].head=p->next; if (p->next) p->next->prev=p->prev; else registrar[r_hash_size].tail=p->prev; free_r_public(p); r_unlock(r_hash_size); p=add_r_public(aor,0,*s); } } if (ccf1) { if (p->ccf1.s) shm_free(p->ccf1.s); STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1"); } if (ccf2) { if (p->ccf2.s) shm_free(p->ccf2.s); STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2"); } if (ecf1) { if (p->ecf1.s) shm_free(p->ecf1.s); STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1"); } if (ecf2) { if (p->ecf2.s) shm_free(p->ecf2.s); STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2"); } //LOG(L_DBG,"update_r_public(): return normaly\n"); return p; } out_of_memory: return p; }