void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) { LM_DBG("Deleting subscriber"); impurecord_t* urec; LM_DBG("Updating reg subscription in IMPU record"); if(lock_domain) lock_udomain(_t, &s->presentity_uri); int res = get_impurecord(_t, &s->presentity_uri, &urec); if (res != 0) { if(lock_domain) unlock_udomain(_t, &s->presentity_uri); return; } delete_subscriber(urec, s); if(lock_domain) unlock_udomain(_t, &s->presentity_uri); }
void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) { LM_DBG("Deleting subscriber"); impurecord_t* urec; LM_DBG("Updating reg subscription in IMPU record"); if(lock_domain) lock_udomain(_t, &s->presentity_uri); int res = get_impurecord(_t, &s->presentity_uri, &urec); if (res != 0) { if(lock_domain) unlock_udomain(_t, &s->presentity_uri); return; } if (urec->shead == s) urec->shead = s->next; else s->prev->next = s->next; if (urec->stail == s) urec->stail = s->prev; else s->next->prev = s->prev; LM_DBG("About to free subscriber memory"); free_subscriber(s); if(lock_domain) unlock_udomain(_t, &s->presentity_uri); }
/*! * \brief Delete a impurecord from domain * \param _d domain where the record should be deleted * \param _aor address of record * \param _r deleted record * \return 0 on success, -1 if the record could not be deleted */ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r) { // struct ucontact* c;//, *t; LM_DBG("Deleting IMPURECORD [%.*s]\n", _r->public_identity.len, _r->public_identity.s); if (_r == 0) { if (get_impurecord(_d, _aor, &_r) > 0) { return 0; } } //TODO: need to unref the contacts in the contact list (not delete them), the timer should delete all contacts that are unreffed // c = _r->contacts; // while (c) { // t = c; // c = c->next; // if (delete_ucontact(_r, t) < 0) { // LM_ERR("deleting contact failed [%.*s]\n", c->aor.len, c->aor.s); // return -1; // } // } if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE)) { run_ul_callbacks(_r->cbs, UL_IMPU_DELETE, _r, 0); } /*DB?*/ if (db_mode == WRITE_THROUGH && db_delete_impurecord(_d, _r) != 0) { LM_ERR("error deleting IMPU record from db"); return 0; } mem_delete_impurecord(_d, _r); return 0; }
/*! * \brief Delete a impurecord from domain * \param _d domain where the record should be deleted * \param _aor address of record - used only if _r in next param is null * \param _r deleted record to delete - if null will use the aor to search (assumed that domain is locked). * \return 0 on success, -1 if the record could not be deleted */ int delete_impurecord(udomain_t* _d, str* _aor, struct impurecord* _r) { LM_DBG("Deleting IMPURECORD [%.*s]\n", _r->public_identity.len, _r->public_identity.s); if (_r == 0) { LM_DBG("no impurecord passed in - let's search\n"); if (get_impurecord(_d, _aor, &_r) != 0) { return 0; } } if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE)) { run_ul_callbacks(_r->cbs, UL_IMPU_DELETE, _r, 0); } /*DB?*/ if (db_mode == WRITE_THROUGH && db_delete_impurecord(_d, _r) != 0) { LM_ERR("error deleting IMPU record from db...continuing to remove from memory\n"); } mem_delete_impurecord(_d, _r); return 0; }
/* 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; }
static void ul_rpc_show_impu(rpc_t* rpc, void* ctx) { int i, j; str impu; int res; udomain_t* domain; struct impurecord* impu_rec; ucontact_t* contact; void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi; char numstr[21+16]; //enough for all numbers up to 64bits + longest length of field name (16) if (rpc->scan(ctx, "S", &impu) < 1) { rpc->fault(ctx, 400, "required IMPU argument"); return; } LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s); res = get_udomain("location", &domain); if (res != 0) { LM_ERR("Failed to get domain\n"); return; } lock_udomain(domain, &impu); res = get_impurecord(domain, &impu, &impu_rec); if (res != 0) { unlock_udomain(domain, &impu); return; } //now print the data for this IMPU record if (rpc->add(ctx, "{", &ah) < 0) { rpc->fault(ctx, 500, "Internal error creating IMPU struct"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "SsdSSSS", "impu", &impu, "state", get_impu_regstate_as_string(impu_rec->reg_state), "barring", impu_rec->barring, "ccf1", &impu_rec->ccf1, "ccf2", &impu_rec->ccf2, "ecf1", &impu_rec->ecf1, "ecf2", &impu_rec->ecf2 ) < 0) { rpc->fault(ctx, 500, "Internal error adding impu data"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); unlock_udomain(domain, &impu); return; } ims_subscription* subscription = impu_rec->s; lock_get(subscription->lock); //add subscription data if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } //add subscription detail information for (i=0; i<subscription->service_profiles_cnt; i++) { sprintf(numstr, "%d", i+1); if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } for (j=0; j<subscription->service_profiles[i].public_identities_cnt; j++) { sprintf(numstr, "%d", j+1); if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) { rpc->fault(ctx, 500, "Internal error adding impu subscription detail data"); lock_release(subscription->lock); unlock_udomain(domain, &impu); return; } } } lock_release(subscription->lock); //add contact data if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } contact = impu_rec->contacts; while (contact) { //contact is not null terminated so we need to create a null terminated version if (!contact_buf.s || (contact_buf.len <= contact->c.len)) { if (contact_buf.s && contact_buf.len <= contact->c.len){ pkg_free(contact_buf.s); } contact_buflen = contact->c.len + 1; contact_buf.s = (char*)pkg_malloc(contact_buflen); if (!contact_buf.s) { LM_ERR("no more pkg memory"); rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } } memcpy(contact_buf.s, contact->c.s, contact->c.len); contact_buf.s[contact->c.len] = '\0'; contact_buf.len = contact->c.len; LM_DBG("contact is %s\n", contact_buf.s); if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact header"); unlock_udomain(domain, &impu); return; } if (rpc->struct_add(cdh, "dS", "expires", contact->expires - time(NULL), "client", &contact->user_agent) < 0) { rpc->fault(ctx, 500, "Internal error adding impu contact data"); unlock_udomain(domain, &impu); return; } contact = contact->next; } unlock_udomain(domain, &impu); }
static void contact_dlg_handler(struct dlg_cell* dlg, int cb_types, struct dlg_cb_params *dlg_params) { struct ucontact *ucontact_caller = 0x00, *ucontact_callee = 0x00; udomain_t *_d; impurecord_t* from_impu, *to_impu; str from_uri_clean, to_uri_clean; char *p; short iFoundCaller = 0, iFoundCallee = 0; static unsigned int i_confirmed_count = 0, i_terminated_count =0; if ((cb_types == DLGCB_CONFIRMED) || (cb_types == DLGCB_EXPIRED) || (cb_types == DLGCB_TERMINATED) || (cb_types == DLGCB_DESTROY) || (cb_types == DLGCB_FAILED)) { //for now we will abort if there is no dlg_out.... TODO maybe we can only do the caller side.... if (dlg->dlg_entry_out.first == 0x00) { LM_DBG("no dlg out... ignoring!!! for type [%d] - usually happens on failure response in dialog\n",cb_types); return; } register_udomain("location", &_d); from_uri_clean.s = dlg->from_uri.s; from_uri_clean.len = dlg->from_uri.len; p = memchr(dlg->from_uri.s, ';', dlg->from_uri.len); if (p) from_uri_clean.len = p - from_uri_clean.s; lock_udomain(_d, &from_uri_clean); if (get_impurecord(_d, &from_uri_clean, &from_impu) != 0) { LM_DBG("Could not find caller impu for [%.*s]\n", from_uri_clean.len, from_uri_clean.s); unlock_udomain(_d, &from_uri_clean); return; } if (find_contact_from_impu(from_impu, &dlg->caller_contact, &ucontact_caller) !=0) { LM_DBG("Unable to find caller contact from dialog.... continuing\n"); //unlock_udomain(_d, &from_uri_clean); //return; } else { iFoundCaller = 1; } unlock_udomain(_d, &from_uri_clean); to_uri_clean.s = dlg->dlg_entry_out.first->to_uri.s; to_uri_clean.len = dlg->dlg_entry_out.first->to_uri.len; p = memchr(dlg->dlg_entry_out.first->to_uri.s, ';', dlg->dlg_entry_out.first->to_uri.len); if (p) to_uri_clean.len = p - to_uri_clean.s; lock_udomain(_d, &to_uri_clean); if (get_impurecord(_d, &to_uri_clean, &to_impu) != 0) { LM_DBG("Could not find callee impu for [%.*s]\n", to_uri_clean.len, to_uri_clean.s); unlock_udomain(_d, &to_uri_clean); return; } if (find_contact_from_impu(to_impu, &dlg->dlg_entry_out.first->callee_contact, &ucontact_callee) !=0) { LM_DBG("Unable to find callee contact from dialog.... continuing\n"); //unlock_udomain(_d, &to_uri_clean); //return; } else{ iFoundCallee = 1; } unlock_udomain(_d, &to_uri_clean); } else { LM_ERR("Unknown event type [%d] for callid [%.*s] ", cb_types, dlg->callid.len, dlg->callid.s); return; } if(!iFoundCaller && !iFoundCallee) { LM_ERR("No Contacts found for both caller && callee ... bailing\n"); return; } switch (cb_types) { case DLGCB_CONFIRMED: LM_DBG("Confirmed contact of type [%d] ,caller_id [%.*s] from handler ", cb_types, dlg->callid.len, dlg->callid.s); if (iFoundCaller) add_dialog_data_to_contact(ucontact_caller, dlg->h_entry, dlg->h_id); if(iFoundCallee) add_dialog_data_to_contact(ucontact_callee, dlg->h_entry, dlg->h_id);//dlg->dlg_entry_out.first->h_entry, dlg->dlg_entry_out.first->h_id); i_confirmed_count++; break; case DLGCB_FAILED: case DLGCB_DESTROY: case DLGCB_EXPIRED: case DLGCB_TERMINATED: LM_DBG("Terminated contact of type [%d] , caller_id [%.*s] from handler ", cb_types, dlg->callid.len, dlg->callid.s); if(iFoundCaller) remove_dialog_data_from_contact(ucontact_caller, dlg->h_entry, dlg->h_id); if(iFoundCallee) //if (dlg->dlg_entry_out.first) { remove_dialog_data_from_contact(ucontact_callee, dlg->h_entry, dlg->h_id);//dlg->dlg_entry_out.first->h_entry, dlg->dlg_entry_out.first->h_id); //} i_terminated_count++; break; } }