/*! * \brief Delete a urecord 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_urecord(udomain_t* _d, str* _aor, struct urecord* _r) { struct ucontact* c, *t; if (db_mode==DB_ONLY) { if (_r==0) get_static_urecord( _d, _aor, &_r); if (db_delete_urecord(_d, _r)<0) { LM_ERR("DB delete failed\n"); return -1; } free_urecord(_r); return 0; } if (_r==0) { if (get_urecord(_d, _aor, &_r) > 0) { return 0; } } c = _r->contacts; while(c) { t = c; c = c->next; if (delete_ucontact(_r, t) < 0) { LM_ERR("deleting contact failed\n"); return -1; } } release_urecord(_r); return 0; }
static int receive_ucontact_delete(bin_packet_t *packet) { udomain_t *domain; urecord_t *record; ucontact_t *contact; str d, aor, contact_str, callid; int cseq, rc; bin_pop_str(packet, &d); bin_pop_str(packet,&aor); bin_pop_str(packet,&contact_str); bin_pop_str(packet,&callid); bin_pop_int(packet,&cseq); if (find_domain(&d, &domain) != 0) { LM_ERR("domain '%.*s' is not local\n", d.len, d.s); goto error; } lock_udomain(domain, &aor); /* failure in retrieving a urecord may be ok, because packet order in UDP * is not guaranteed, so urecord_delete commands may arrive before * ucontact_delete's */ if (get_urecord(domain, &aor, &record) != 0) { LM_INFO("failed to fetch local urecord - ignoring request " "(ci: '%.*s')\n", callid.len, callid.s); unlock_udomain(domain, &aor); return 0; } /* simply specify a higher cseq and completely avoid any complications */ rc = get_ucontact(record, &contact_str, &callid, cseq + 1, &contact); if (rc != 0 && rc != 2) { LM_ERR("contact '%.*s' not found: (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } if (skip_replicated_db_ops) contact->flags |= FL_MEM; if (delete_ucontact(record, contact, 1) != 0) { LM_ERR("failed to delete ucontact '%.*s' (ci: '%.*s')\n", contact_str.len, contact_str.s, callid.len, callid.s); unlock_udomain(domain, &aor); goto error; } unlock_udomain(domain, &aor); return 0; error: LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n", d.len, d.s, aor.len, aor.s); return -1; }
static void rpc_delete_contact(rpc_t* rpc, void* ctx) { udomain_t* d; urecord_t* r; ucontact_t* con; str uid, t, c; int res; if (rpc->scan(ctx, "SSS", &t, &uid, &c) < 3) return; rpc_find_domain(&t, &d); if (d) { lock_udomain(d); res = get_urecord(d, &uid, &r); if (res < 0) { rpc->fault(ctx, 500, "Error While Searching Table"); ERR("Error while looking for uid %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s); unlock_udomain(d); return; } if (res > 0) { rpc->fault(ctx, 404, "AOR Not Found"); unlock_udomain(d); return; } res = get_ucontact(r, &c, &con); if (res < 0) { rpc->fault(ctx, 500, "Error While Searching for Contact"); ERR("Error while looking for contact %.*s\n", c.len, c.s); unlock_udomain(d); return; } if (res > 0) { rpc->fault(ctx, 404, "Contact Not Found"); unlock_udomain(d); return; } if (delete_ucontact(r, con) < 0) { rpc->fault(ctx, 500, "Error While Deleting Contact"); unlock_udomain(d); return; } release_urecord(r); unlock_udomain(d); } else { rpc->fault(ctx, 404, "Table Not Found"); } }
/** * @brief unref contact - assume a lock on the slot is held prior to calling this * @param c */ void unref_contact_unsafe(ucontact_t* c) { LM_DBG("decrementing ref count on contact [%.*s], was %d\n", c->c.len, c->c.s, c->ref_count); c->ref_count--; if (c->ref_count <= 0) { LM_DBG("contact [%.*s] no longer referenced.... deleting\n", c->c.len, c->c.s); if (c->ref_count < 0) { LM_WARN("reference dropped below zero... this should not happen\n"); } delete_ucontact(c); } }
/*! * \brief Delete a contact from an AOR record * \param cmd mi_root containing the parameter * \param param not used * \note expects 3 nodes: the table name, the AOR and contact * \return mi_root with the result or 0 on failure */ struct mi_root* mi_usrloc_rm_contact(struct mi_root *cmd, void *param) { struct mi_node *node; udomain_t *dom; urecord_t *rec; ucontact_t* con; str *aor, *contact; int ret; node = cmd->node.kids; if (node==NULL || node->next==NULL || node->next->next==NULL || node->next->next->next!=NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); /* look for table */ dom = mi_find_domain( &node->value ); if (dom==NULL) return init_mi_tree( 404, "Table not found", 15); /* process the aor */ aor = &node->next->value; if ( mi_fix_aor(aor)!=0 ) return init_mi_tree( 400, "Domain missing in AOR", 21); lock_udomain( dom, aor); ret = get_urecord( dom, aor, &rec); if (ret == 1) { unlock_udomain( dom, aor); return init_mi_tree( 404, "AOR not found", 13); } contact = &node->next->next->value; set_mi_ul_cid(); ret = get_ucontact( rec, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &con); if (ret < 0) { unlock_udomain( dom, aor); return 0; } if (ret > 0) { unlock_udomain( dom, aor); return init_mi_tree( 404, "Contact not found", 17); } if (delete_ucontact(rec, con) < 0) { unlock_udomain( dom, aor); return 0; } release_urecord(rec); unlock_udomain( dom, aor); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); }
/* * Delete a urecord from domain */ int delete_urecord(udomain_t* _d, str* _uid) { struct ucontact* c, *t; struct urecord* r; if (get_urecord(_d, _uid, &r) > 0) { return 0; } c = r->contacts; while(c) { t = c; c = c->next; if (delete_ucontact(r, t) < 0) { LOG(L_ERR, "delete_urecord(): Error while deleting contact\n"); return -1; } } release_urecord(r); return 0; }
/*! * \brief Run timer handler for given domain * \param _d domain */ void mem_timer_udomain(udomain_t* _d) { struct impurecord* ptr, *t; struct ucontact* contact_ptr, *tmp_contact_ptr; int i; //go through contacts first LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n"); for (i = 0; i < contact_list->size; i++) { #ifdef EXTRA_DEBUG LM_DBG("looking for contacts in slot %d\n", i); #endif lock_contact_slot_i(i); contact_ptr = contact_list->slot[i].first; while (contact_ptr) { LM_DBG("We have a contact in the new contact list in slot %d = [%.*s] (%.*s) which expires in %lf seconds and has a ref count of %d\n", i, contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s, (double) contact_ptr->expires - time(NULL), contact_ptr->ref_count); if (contact_ptr->ref_count <= 0) { LM_DBG("Deleting contact [%.*s]\n", contact_ptr->c.len, contact_ptr->c.s); tmp_contact_ptr = contact_ptr->next; delete_ucontact(contact_ptr); contact_ptr = tmp_contact_ptr; } else { contact_ptr = contact_ptr->next; } } unlock_contact_slot_i(i); } LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n"); int temp = 0; LM_DBG("*** mem_timer_udomain - checking IMPUs - START ***\n"); for (i = 0; i < _d->size; i++) { lock_ulslot(_d, i); ptr = _d->table[i].first; temp = 0; while (ptr) { temp = 1; #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d LOCKED\n", i); #endif t = ptr; ptr = ptr->next; timer_impurecord(t); // if (t->reg_state == IMPU_NOT_REGISTERED && t->shead == 0) { // //remove it - housekeeping - not sure why its still here...? // if (exists_ulcb_type(t->cbs, UL_IMPU_NR_DELETE)) // run_ul_callbacks(t->cbs, UL_IMPU_NR_DELETE, t, NULL); // // LM_DBG("about to delete impurecord\n"); // delete_impurecord(_d, &t->public_identity, t); // } //else if (t->reg_state == IMPU_UNREGISTERED) {//Remove IMPU record if it is in state IMPU_UNREGISTERED and has expired // // if (time_now >= t->expires) {//check here and only remove if no subscribes - if there is a subscribe then bump the validity by unreg_validity // if(t->shead != 0){ // LM_DBG("This impurecord still has subscriptions - extending the expiry"); // t->expires = time(NULL) + unreg_validity; // } else { // if (exists_ulcb_type(t->cbs, UL_IMPU_UNREG_EXPIRED)) // run_ul_callbacks(t->cbs, UL_IMPU_UNREG_EXPIRED, t, NULL); // LM_DBG("about to delete impurecord\n"); // delete_impurecord(_d, &t->public_identity, t); // } // } // //} else if (t->reg_state != IMPU_UNREGISTERED && t->contacts == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */ // } else if (t->reg_state != IMPU_UNREGISTERED && t->num_contacts == 0 && t->shead == 0) { /* Remove the entire record if it is empty IFF it is not an UNREGISTERED RECORD */ // /* TS 23.228 5.3.2.1 (release 11) */ // //need a way of distinguishing between deletes that need a SAR (expired) and deletes that do not need a SAR (explicit de reg) // //we only want to send one SAR for each implicit IMPU set // //make sure all IMPU's associated with this set are de-registered before calling the callbacks // int first=1; // int this_is_first = 0; // // lock_get(t->s->lock); // for (k = 0; k < t->s->service_profiles_cnt; k++){ // for (j = 0;j < t->s->service_profiles[k].public_identities_cnt;j++) { // impu = &(t->s->service_profiles[k].public_identities[j]); // // sl = core_hash(&impu->public_identity, 0, _d->size); // if (sl != i) // lock_udomain(_d, &impu->public_identity); // // if (first) { // first = 0; //dont do anything - we will leave this impu to be processed as normal // if (!strncmp(impu->public_identity.s, t->public_identity.s, t->public_identity.len)) { // //we are the first in the implicit set // this_is_first = 1; // } // } else { // //set all other implicits to not registered // if (update_impurecord(_d, &impu->public_identity, IMPU_NOT_REGISTERED, // -1/*barring*/, -1 /*do not change send sar on delete */, 0/*is_primary*/, NULL, NULL, NULL, NULL, NULL, &temp_impu) != 0) { // LM_ERR("Unable to update impurecord for <%.*s>\n", impu->public_identity.len, impu->public_identity.s); // } // } // if (sl != i) // unlock_udomain(_d, &impu->public_identity); // } // } // lock_release(t->s->lock); // // if (this_is_first) { // //now run a normal callback on our // if (exists_ulcb_type(t->cbs, UL_IMPU_REG_NC_DELETE)) // run_ul_callbacks(t->cbs, UL_IMPU_REG_NC_DELETE, t, NULL); // LM_DBG("about to delete impurecord\n"); // delete_impurecord(_d, &t->public_identity, t); // } // } } if (temp) { #ifdef EXTRA_DEBUG LM_DBG("ULSLOT %d UN-LOCKED\n", i); #endif } unlock_ulslot(_d, i); } LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n"); }
static int ul_rm_contact(FILE* pipe, char* response_file) { char table[MAX_TABLE]; char user[MAX_USER]; char contact[MAX_CONTACT_LEN]; udomain_t* d; urecord_t* r; ucontact_t* con; str aor, t, c; int res; char* at; if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) { fifo_reply(response_file, "400 ul_rm_contact: table name expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: table name expected\n"); return 1; } if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) { fifo_reply(response_file, "400 ul_rm_contact: user name expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: user name expected\n"); return 1; } at = memchr(user, '@', aor.len); if (use_domain) { if (!at) { fifo_reply(response_file, "400 ul_rm_contact: user@domain expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: Domain missing\n"); return 1; } } else { if (at) { aor.len = at - user; } } if (!read_line(contact, MAX_CONTACT_LEN, pipe, &c.len) || c.len == 0) { fifo_reply(response_file, "400 ul_rm_contact: contact expected\n"); LOG(L_ERR, "ERROR: ul_rm_contact: contact expected\n"); return 1; } aor.s = user; strlower(&aor); t.s = table; c.s = contact; fifo_find_domain(&t, &d); LOG(L_INFO, "INFO: deleting user-loc contact (%s,%s,%s)\n", table, user, contact ); if (d) { lock_udomain(d); res = get_urecord(d, &aor, &r); if (res < 0) { fifo_reply(response_file, "500 Error while looking for username %s in table %s\n", user, table); LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for username %s in table %s\n", user, table); unlock_udomain(d); return 1; } if (res > 0) { fifo_reply(response_file, "404 Username %s in table %s not found\n", user, table); unlock_udomain(d); return 1; } res = get_ucontact(r, &c, &con); if (res < 0) { fifo_reply(response_file, "500 Error while looking for contact %s\n", contact); LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for contact %s\n", contact); unlock_udomain(d); return 1; } if (res > 0) { fifo_reply(response_file, "404 Contact %s in table %s not found\n", contact, table); unlock_udomain(d); return 1; } if (delete_ucontact(r, con) < 0) { fifo_reply(response_file, "500 ul_rm_contact: Error while deleting contact %s\n", contact); unlock_udomain(d); return 1; } release_urecord(r); unlock_udomain(d); fifo_reply(response_file, "200 Contact (%s, %s) deleted from table %s\n", user, contact, table); return 1; } else { fifo_reply(response_file, "400 table (%s) not found\n", table); return 1; } }