コード例 #1
0
ファイル: impurecord.c プロジェクト: nakchak/kamailio
/*!
 * \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;
}
コード例 #2
0
ファイル: udomain.c プロジェクト: krys1976/kamailio
/*!
 * \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);
        }
    }
    
}