Ejemplo n.º 1
0
/*!
 * \brief Get pointer to ucontact with given contact
 * \param _r record where to search the contacts
 * \param _c contact string
 * \param _callid callid
 * \param _path path
 * \param _cseq CSEQ number
 * \param _co found contact
 * \return 0 - found, 1 - not found, -1 - invalid found,
 * -2 - found, but to be skipped (same cseq) - don't forget to release_ucontact so dec. the ref counter
 */
int get_scontact(str* _c, str* _callid, str* _path, int _cseq, struct ucontact** _co) {
    unsigned int sl;
    ucontact_t* ptr;
    int with_callid = 0;
    ptr = 0;
    *_co = 0;

    sl = core_hash(_c, 0, contact_list->size);
    LM_DBG("looking for contact [%.*s] in slot %d\n", _c->len, _c->s, sl);
    get_act_time();

    lock_contact_slot_i(sl);

    switch (matching_mode) {
    case CONTACT_ONLY:
        ptr = contact_match(sl, _c);
        break;
    case CONTACT_CALLID:
        ptr = contact_callid_match(sl, _c, _callid);
        with_callid = 1;
        break;
    case CONTACT_PATH:
        ptr = contact_path_match(sl, _c, _path);
        break;
    case CONTACT_PORT_IP_ONLY:
        ptr = contact_port_ip_match(sl, _c);
        break;
    default:
        LM_CRIT("unknown matching_mode %d\n", matching_mode);
        unlock_contact_slot_i(sl);
        return -1;
    }

    if (ptr) {
        LM_DBG("have partially found a contact\n");
        /* found -> check callid and cseq */
        if (!with_callid || (_callid && ptr->callid.len == _callid->len
                             && memcmp(_callid->s, ptr->callid.s, _callid->len) == 0)) {
            if (_cseq < ptr->cseq) {
                LM_DBG("cseq less than expected\n");
            }

        }
        LM_DBG("contact found p=[%p], aor:[%.*s] and contact:[%.*s], state [%d]\n", ptr, ptr->aor.len, ptr->aor.s, ptr->c.len, ptr->c.s, ptr->state);
        ref_contact_unsafe(ptr);
        *_co = ptr;
        unlock_contact_slot_i(sl); /*TODO: we probably need to ref count here..... */
        return 0;
    }
    unlock_contact_slot_i(sl);

    return 1;
}
Ejemplo n.º 2
0
/*!
 * \brief Add a new contact in memory
 *
 * Add a new contact in memory, contacts are ordered by:
 * 1) q value, 2) descending modification time
 * \param _r record this contact belongs to
 * \param _c contact
 * \param _ci contact information
 * \return pointer to new created contact on success, 0 on failure
 */
ucontact_t* mem_insert_scontact(impurecord_t* _r, str* _c, ucontact_info_t* _ci) {
    ucontact_t* c;
    int sl;

    if ((c = new_ucontact(_r->domain, &_r->public_identity, _c, _ci)) == 0) {
        LM_ERR("failed to create new contact\n");
        return 0;
    }
    counter_inc(ul_scscf_cnts_h.active_contacts);

    LM_DBG("Created new contact in memory with AOR: [%.*s] and hash [%d]\n", _c->len, _c->s, c->sl);

    sl = (c->sl);
    lock_contact_slot_i(sl);
    contact_slot_add(&contact_list->slot[sl], c);
    unlock_contact_slot_i(sl);

    return c;
}
Ejemplo n.º 3
0
void unlock_contact_slot(str* contact_uri) {
    unsigned int sl;
    sl = core_hash(contact_uri, 0, contact_list->size);

    unlock_contact_slot_i(sl);
}
Ejemplo n.º 4
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");
}
Ejemplo n.º 5
0
/*!
 * \brief Expires timer for NO_DB db_mode
 *
 * Expires timer for NO_DB db_mode, process all contacts from
 * the record, delete the expired ones from memory.
 * \param _r processed record
 */
static inline void process_impurecord(impurecord_t* _r) {
    int flag, mustdeleteimpu = 1, n, k;
    unsigned int sl;
    ucontact_t* ptr;
    int hascontacts;
    udomain_t* _d;
    reg_subscriber *s;
    subs_t* sub_dialog;

    get_act_time();

    s = _r->shead;
    LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
    while (s) {
        if (!valid_subscriber(s, act_time)) {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
                   s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
            delete_subscriber(_r, s);
        } else {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
                   s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
                   (unsigned int) (s->expires - time(NULL)));
            sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
            LM_DBG("Hash size: <%i>", sub_dialog_hash_size);
            LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, sl);
            /* search the record in hash table */
            lock_get(&sub_dialog_table[sl].lock);
            sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl);
            if (sub_dialog == NULL) {
                LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n");
            } else {
                LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s);
            }
            lock_release(&sub_dialog_table[sl].lock);
            mustdeleteimpu = 0;
        }
        s = s->next;
    }

    LM_DBG("\tPublic Identity %.*s, Barred: [%d], State: [%s]\n",
           _r->public_identity.len, _r->public_identity.s,
           _r->barring,
           get_impu_regstate_as_string(_r->reg_state));
    flag = 0;
    hascontacts = 0;
    num_contacts_to_expire = 0;
    for (k = 0; (k < _r->num_contacts) && (k < MAX_CONTACTS_PER_IMPU); k++) {
        if ((ptr = _r->newcontacts[k])) {
            flag = 1;
            if (!VALID_CONTACT(ptr, act_time)) {
                if (ptr->state == CONTACT_DELETED) {
                    LM_DBG("Contact: <%.*s> has been deleted - unlinking from IMPU\n", ptr->c.len, ptr->c.s);
                    contacts_to_expire[num_contacts_to_expire] = ptr;
                    num_contacts_to_expire++;
                } else if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
                    LM_DBG("Contact: <%.*s> is in state CONTACT_EXPIRE_PENDING_NOTIFY....running callback\n", ptr->c.len, ptr->c.s);
                    if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
                        LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", ptr->c.len, ptr->c.s, _r->public_identity.len, _r->public_identity.s);
                        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, ptr);
                    }
                    hascontacts = 1;    // we do this because the impu must only be deleted if in state deleted....
                    mustdeleteimpu = 0;
                } else if (ptr->state == CONTACT_VALID) {
                    LM_DBG("Contact: <%.*s> is in state valid but it has expired.... ignoring as the contact check will set the appropriate action/state\n", ptr->c.len, ptr->c.s);
                    mustdeleteimpu = 0;
                    hascontacts = 1;
                } else {
                    LM_WARN("Bogus state for contact [%.*s] - state: %d... ignoring", ptr->c.len, ptr->c.s, ptr->state);
                    mustdeleteimpu = 0;
                    hascontacts = 1;
                }
            } else {
                LM_DBG("\t\tContact #%i - %.*s, Ref [%d] (expires in %ld seconds) (State: %d)\n",
                       k, ptr->c.len, ptr->c.s, ptr->ref_count, ptr->expires - act_time, ptr->state);
                mustdeleteimpu = 0;
                hascontacts = 1;
            }
        } else {
            LM_WARN("num_contacts and actual data not consistent... .aborting\n");
            break;
        }
    }

    if (num_contacts_to_expire > 0) {
        LM_DBG("\tThere are %d contacts to expire/unlink\n", num_contacts_to_expire);
        for (n = 0; n < num_contacts_to_expire; n++) {
            ptr = contacts_to_expire[n];
            LM_DBG("\t\texpiring contact %i: [%.*s] in slot [%d]\n", n, contacts_to_expire[n]->c.len, contacts_to_expire[n]->c.s, contacts_to_expire[n]->sl);
            sl = ptr->sl;
            lock_contact_slot_i(sl);
            unlink_contact_from_impu(_r, ptr, 1, 0 /*implicit dereg of contact from IMPU*/);
            unlock_contact_slot_i(sl);
        }
    }

    if (!flag)
        LM_DBG("no contacts\n");

    if (mustdeleteimpu) {
        register_udomain("location", &_d);
        delete_impurecord(_d, &_r->public_identity, _r);
    } else {
        if (!hascontacts) {
            LM_DBG("This impu is not to be deleted but has no contacts - changing state to IMPU_UNREGISTERED\n");
            _r->reg_state = IMPU_UNREGISTERED;
        }
    }
}
Ejemplo n.º 6
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;
    int i, n, temp;

    //go through contacts first
    n = contact_list->max_collisions;
    LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n");
    for (i = 0; i < contact_list->size; i++) {
        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);
		//contacts are now deleted during impurecord processing
            contact_ptr = contact_ptr->next;
        } 
        if (contact_list->slot[i].n > n) {
            n = contact_list->slot[i].n;
        }
        unlock_contact_slot_i(i);
        contact_list->max_collisions = n;
    }
    LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n");

    temp = 0;
    n = _d->max_collisions;

    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 (temp) {
#ifdef EXTRA_DEBUG
            LM_DBG("ULSLOT %d UN-LOCKED\n", i);
#endif
        }
        if (_d->table[i].n > n)
            n = _d->table[i].n;
        
        unlock_ulslot(_d, i);
        _d->max_collisions = n;
    }
    LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n");
    
    n = ims_subscription_list->max_collisions;
    for (i = 0; i < ims_subscription_list->size; i++) {
        lock_subscription_slot(i);
        if (ims_subscription_list->slot[i].n > n) {
            n = ims_subscription_list->slot[i].n;
        }
        unlock_subscription_slot(i);
    }
    ims_subscription_list->max_collisions = n;
    
}
Ejemplo n.º 7
0
void release_ucontact(struct ucontact* _c) {
    lock_contact_slot_i(_c->contact_hash);
    _c->ref_count--;
    unlock_contact_slot_i(_c->contact_hash);
}
Ejemplo n.º 8
0
/*!
 * \brief Run timer handler for given domain
 * \param _d domain
 */
void mem_timer_udomain(udomain_t* _d, int istart, int istep) {
    struct impurecord* ptr, *t;
    struct ucontact* contact_ptr;
    unsigned int num_expired_contacts = 0;
    int i, n, temp;
    time_t now;
    int abort = 0;
    int slot;
	int ref_count_db;
    
    now = time(0);
    
    if (istart == 0) {
        int numcontacts = contact_list->size*2;     //assume we should be ok for each slot to have 2 collisions
        if (expired_contacts_size < numcontacts) {
            LM_DBG("Changing expired_contacts list size from %d to %d\n", expired_contacts_size, numcontacts);
            if (expired_contacts){
                pkg_free(expired_contacts);
            }
            expired_contacts = (ucontact_t**)pkg_malloc(numcontacts*sizeof(ucontact_t**));
            if (!expired_contacts) {
                LM_ERR("no more pkg mem trying to allocate [%lu] bytes\n", numcontacts*sizeof(ucontact_t**));
                return;
            }
            expired_contacts_size = numcontacts;
        }

        //go through contacts first
        n = contact_list->max_collisions;
        LM_DBG("*** mem_timer_udomain - checking contacts - START ***\n");
        for (i=0; i < contact_list->size; i++) {
            lock_contact_slot_i(i);
            contact_ptr = contact_list->slot[i].first;
            while (contact_ptr) {
                if (num_expired_contacts >= numcontacts) {
                    LM_WARN("we don't have enough space to expire all contacts in this pass - will continue in next pass\n");
                    abort = 1;
                    break;
                }
                LM_DBG("We have a [3gpp=%d] contact in the new contact list in slot %d = [%.*s] (%.*s) which expires in %lf seconds and has a ref count of %d (state: %s)\n", 
                        contact_ptr->is_3gpp, i, contact_ptr->aor.len, contact_ptr->aor.s, contact_ptr->c.len, contact_ptr->c.s, 
                        (double) contact_ptr->expires - now, contact_ptr->ref_count,
                        get_contact_state_as_string(contact_ptr->state));
                    //contacts are now deleted during impurecord processing
                if ((contact_ptr->expires-now) <= 0) {
                    if (contact_ptr->state == CONTACT_DELAYED_DELETE) {
                        if (contact_ptr->ref_count <= 0) {
                            LM_DBG("contact in state CONTACT_DELATED_DELETE is about to be deleted");
                            expired_contacts[num_expired_contacts] = contact_ptr;
                            num_expired_contacts++;
                        } else {
							/* we could fall here not because contact is still
							 referenced but also because we failed before to
							 get a lock to unref the contact, so we check if
							 contact is really referenced*/
							if (db_mode != NO_DB) {
								LM_DBG("contact in state CONTACT_DELAYED_DELETE still has a ref count of [%d] in memory. Check on DB \n", contact_ptr->ref_count);
								ref_count_db = db_check_if_contact_is_linked(contact_ptr);
								if (ref_count_db < 0) {
									LM_ERR("Unable to check if contact is unlinked\n");
								} else if (ref_count_db == 0) {
									LM_DBG("Contact has ref count [%d] but there's no link on the DB. Deleting contact", contact_ptr->ref_count);
									contact_ptr->ref_count = 0;
									expired_contacts[num_expired_contacts] = contact_ptr;
									num_expired_contacts++;
								} else {
									LM_DBG("Contact in state CONTACT_DELAYED_DELETE has ref count [%d] on DB", ref_count_db);
								}
							} else {
								LM_DBG("contact in state CONTACT_DELAYED_DELETE still has a ref count of [%d] in memory. Not doing anything for now \n", contact_ptr->ref_count);
							}
                        }
                    } else if (contact_ptr->state != CONTACT_DELETED) {
                        LM_DBG("expiring contact [%.*s].... setting to CONTACT_EXPIRE_PENDING_NOTIFY\n", contact_ptr->aor.len, contact_ptr->aor.s);
                        contact_ptr->state = CONTACT_EXPIRE_PENDING_NOTIFY;
                        ref_contact_unsafe(contact_ptr);
                        expired_contacts[num_expired_contacts] = contact_ptr;
                        num_expired_contacts++;
                    }
                }
                contact_ptr = contact_ptr->next;
            } 
            if (contact_list->slot[i].n > n) {
                n = contact_list->slot[i].n;
            }
            unlock_contact_slot_i(i);
            contact_list->max_collisions = n;
            if (abort == 1) {
                break;
            }
        }
        LM_DBG("*** mem_timer_udomain - checking contacts - FINISHED ***\n");
    }
       
    temp = 0;
    n = _d->max_collisions;

    LM_DBG("*** mem_timer_udomain - checking IMPUs - START ***\n");
    for (i = istart; i < _d->size; i+=istep) {
        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 (temp) {
#ifdef EXTRA_DEBUG
            LM_DBG("ULSLOT %d UN-LOCKED\n", i);
#endif
        }
        if (_d->table[i].n > n)
            n = _d->table[i].n;
        
        unlock_ulslot(_d, i);
        _d->max_collisions = n;
    }
    LM_DBG("*** mem_timer_udomain - checking IMPUs - FINISHED ***\n");
    
    if (istart == 0) {
        n = ims_subscription_list->max_collisions;
        for (i = 0; i < ims_subscription_list->size; i++) {
            lock_subscription_slot(i);
            if (ims_subscription_list->slot[i].n > n) {
                n = ims_subscription_list->slot[i].n;
            }
            unlock_subscription_slot(i);
        }
        ims_subscription_list->max_collisions = n;

        /* now we delete the expired contacts.  (mark them for deletion */
        for (i=0; i<num_expired_contacts; i++) {
            slot = expired_contacts[i]->sl;
            lock_contact_slot_i(slot);
            if (expired_contacts[i]->state != CONTACT_DELAYED_DELETE) {
                LM_DBG("Setting contact state to CONTACT_DELETED for contact [%.*s]\n", expired_contacts[i]->aor.len, expired_contacts[i]->aor.s);
                expired_contacts[i]->state = CONTACT_DELETED;
                unref_contact_unsafe(expired_contacts[i]);
            } else {
                LM_DBG("deleting contact [%.*s]\n", expired_contacts[i]->aor.len, expired_contacts[i]->aor.s);
                delete_scontact(expired_contacts[i]);
            }
            unlock_contact_slot_i(slot);
        }
    }
    
}