Beispiel #1
0
/*!
 * \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;
}
Beispiel #2
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;
}
Beispiel #3
0
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");
	}
}
Beispiel #4
0
/**
 * @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);
    }
}
Beispiel #5
0
/*!
 * \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);
}
Beispiel #6
0
/*
 * 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;
}
Beispiel #7
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");
}
Beispiel #8
0
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;
	}

}