Exemple #1
0
void mem_timer_udomain(udomain_t* _d)
{
	struct pcontact* ptr;
	int i;

	for(i=0; i<_d->size; i++)
	{
		lock_ulslot(_d, i);

		ptr = _d->table[i].first;

		while(ptr) {
			timer_pcontact(ptr);
			/* Remove the entire record if it is empty */
			//if (ptr->contacts == 0) {
			//	t = ptr;
			//	ptr = ptr->next;
			//	mem_delete_pcontact(_d, t);
			//}//// else {
			//	ptr = ptr->next;
			//}
			ptr = ptr->next;
		}
		unlock_ulslot(_d, i);
	}
}
Exemple #2
0
/*!
 * \brief Run timer handler for given domain
 * \param _d domain
 */
void mem_timer_udomain(udomain_t* _d)
{
    struct urecord* ptr, *t;
    int i;

    for(i=0; i<_d->size; i++)
    {
        lock_ulslot(_d, i);

        ptr = _d->table[i].first;

        while(ptr) {
            timer_urecord(ptr);
            /* Remove the entire record if it is empty */
            if (ptr->contacts == 0) {
                t = ptr;
                ptr = ptr->next;
                mem_delete_urecord(_d, t);
            } else {
                ptr = ptr->next;
            }
        }
        unlock_ulslot(_d, i);
    }
}
Exemple #3
0
/*!
 * \brief Free all memory allocated for the domain
 * \param _d freed domain
 */
void free_udomain(udomain_t* _d) {
    int i;

    if (_d->table) {
	for (i = 0; i < _d->size; i++) {
	    lock_ulslot(_d, i);
	    deinit_slot(_d->table + i);
	    unlock_ulslot(_d, i);
	}
	shm_free(_d->table);
    }
    shm_free(_d);
}
Exemple #4
0
/*!
 * \brief Obtain a urecord pointer if the urecord exists in domain (lock slot)
 * \param _d domain to search the record
 * \param _aorhash hash id for address of record
 * \param _ruid record internal unique id
 * \param _r store pointer to location record
 * \param _c store pointer to contact structure
 * \return 0 if a record was found, 1 if nothing could be found
 */
int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
                        str *_ruid, struct urecord** _r, struct ucontact** _c)
{
    unsigned int sl, i;
    urecord_t* r;
    ucontact_t* c;

    sl = _aorhash&(_d->size-1);
    lock_ulslot(_d, sl);

    if (db_mode!=DB_ONLY) {
        /* search in cache */
        r = _d->table[sl].first;

        for(i = 0; i < _d->table[sl].n; i++) {
            if(r->aorhash==_aorhash) {
                c = r->contacts;
                while(c) {
                    if(c->ruid.len==_ruid->len
                            && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
                        *_r = r;
                        *_c = c;
                        return 0;
                    }
                }
            }
            r = r->next;
        }
    } else {
        /* search in DB */
        r = db_load_urecord_by_ruid(_d, _ruid);
        if (r) {
            if(r->aorhash==_aorhash) {
                c = r->contacts;
                while(c) {
                    if(c->ruid.len==_ruid->len
                            && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
                        *_r = r;
                        *_c = c;
                        return 0;
                    }
                }
            }
        }
    }

    unlock_ulslot(_d, (_aorhash & (_d->size - 1)));
    return -1;   /* Nothing found */
}
Exemple #5
0
int ul_refresh_keepalive(unsigned int _aorhash, str *_ruid)
{
	dlist_t *p;
	urecord_t *r;
	ucontact_t *c;
	int i;

	/* todo: get location domain via param */

	for (p = root; p != NULL; p = p->next)
	{
		i = _aorhash&(p->d->size-1);
		lock_ulslot(p->d, i);
		if(p->d->table[i].n<=0)
		{
			unlock_ulslot(p->d, i);
			continue;
		}
		for (r = p->d->table[i].first; r != NULL; r = r->next)
		{
			if(r->aorhash==_aorhash)
			{
				for (c = r->contacts; c != NULL; c = c->next)
				{
					if (c->c.len <= 0 || c->ruid.len<=0)
						continue;
					if(c->ruid.len==_ruid->len
							&& !memcmp(c->ruid.s, _ruid->s, _ruid->len))
					{
						/* found */
						c->last_keepalive = time(NULL);
						LM_DBG("updated keepalive for [%.*s:%u] to %u\n",
								_ruid->len, _ruid->s, _aorhash,
								(unsigned int)c->last_keepalive);
						unlock_ulslot(p->d, i);
						return 0;
					}
				}
			}
		}
		unlock_ulslot(p->d, i);
	}

	return 0;
}
Exemple #6
0
void mem_timer_udomain(udomain_t* _d)
{
	struct pcontact* ptr, *tmp;
	int i;

	for(i=0; i<_d->size; i++)
	{
		lock_ulslot(_d, i);

		ptr = _d->table[i].first;

		while(ptr) {
		    tmp = ptr;
			ptr = ptr->next;
		    timer_pcontact(tmp);
		}
		
		unlock_ulslot(_d, i);
	}
}
Exemple #7
0
/*!
 * \brief Get all contacts from the memory, in partitions if wanted
 * \see get_all_ucontacts
 * \param buf target buffer
 * \param len length of buffer
 * \param flags contact flags
 * \param part_idx part index
 * \param part_max maximal part
 * \param options options
 * \return 0 on success, positive if buffer size was not sufficient, negative on failure
 */
static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max,
								int options)
{
	dlist_t *p;
	urecord_t *r;
	ucontact_t *c;
	void *cp;
	int shortage;
	int needed;
	int i = 0;
	cp = buf;
	shortage = 0;
	time_t tnow = 0;


	if(ul_keepalive_timeout>0)
		tnow = time(NULL);

	/* Reserve space for terminating 0000 */
	len -= sizeof(c->c.len);

	for (p = root; p != NULL; p = p->next) {

		for(i=0; i<p->d->size; i++) {

			if ( (i % part_max) != part_idx )
				continue;

			lock_ulslot(p->d, i);
			if(p->d->table[i].n<=0)
			{
				unlock_ulslot(p->d, i);
				continue;
			}
			for (r = p->d->table[i].first; r != NULL; r = r->next) {
				for (c = r->contacts; c != NULL; c = c->next) {
					if (c->c.len <= 0)
						continue;
					/*
					 * List only contacts that have all requested
					 * flags set
					 */
					if ((c->cflags & flags) != flags)
						continue;

					if(options&GAU_OPT_SERVER_ID && server_id!=c->server_id)
						continue;

					if(ul_keepalive_timeout>0 && c->last_keepalive>0)
					{
						if(c->sock!=NULL && c->sock->proto==PROTO_UDP)
						{
							if(c->last_keepalive+ul_keepalive_timeout < tnow)
							{
								/* set contact as expired in 10s */
								if(c->expires > tnow + 10)
									c->expires = tnow + 10;
								continue;
							}
						}
					}

					needed = (int)(sizeof(c->c.len) + c->c.len
							+ sizeof(c->received.len) + c->received.len
							+ sizeof(c->sock) + sizeof(c->cflags)
							+ sizeof(c->path.len) + c->path.len
							+ sizeof(c->ruid.len) + c->ruid.len
							+ sizeof(r->aorhash));
					if (len >= needed) {
						memcpy(cp, &c->c.len, sizeof(c->c.len));
						cp = (char*)cp + sizeof(c->c.len);
						memcpy(cp, c->c.s, c->c.len);
						cp = (char*)cp + c->c.len;
						memcpy(cp,&c->received.len,sizeof(c->received.len));
						cp = (char*)cp + sizeof(c->received.len);
						memcpy(cp, c->received.s, c->received.len);
						cp = (char*)cp + c->received.len;
						memcpy(cp, &c->sock, sizeof(c->sock));
						cp = (char*)cp + sizeof(c->sock);
						memcpy(cp, &c->cflags, sizeof(c->cflags));
						cp = (char*)cp + sizeof(c->cflags);
						memcpy(cp, &c->path.len, sizeof(c->path.len));
						cp = (char*)cp + sizeof(c->path.len);
						memcpy(cp, c->path.s, c->path.len);
						cp = (char*)cp + c->path.len;
						memcpy(cp, &c->ruid.len, sizeof(c->ruid.len));
						cp = (char*)cp + sizeof(c->ruid.len);
						memcpy(cp, c->ruid.s, c->ruid.len);
						cp = (char*)cp + c->ruid.len;
						memcpy(cp, &r->aorhash, sizeof(r->aorhash));
						cp = (char*)cp + sizeof(r->aorhash);
						len -= needed;
					} else {
						shortage += needed;
					}
				}
			}
			unlock_ulslot(p->d, i);
		}
	}
	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(c->c.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Exemple #8
0
/*!
 * \brief Dump the content of the usrloc
 * \param cmd mi_root containing the parameter
 * \param param not used
 * \return mi_root with the result or 0 on failure
 */
struct mi_root* mi_usrloc_dump(struct mi_root *cmd, void *param)
{
	struct mi_root *rpl_tree;
	struct mi_node *rpl, *node;
	struct mi_attr *attr;
	struct urecord* r;
	dlist_t* dl;
	udomain_t* dom;
	time_t t;
	char *p;
	int max, len, n, i, short_dump;

	node = cmd->node.kids;
	if (node && node->next)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

	if (node && node->value.len==5 && !strncasecmp(node->value.s, "brief", 5)){
		/* short version */
		short_dump = 1;
	} else {
		short_dump = 0;
	}

	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
	if (rpl_tree==NULL)
		return 0;
	rpl = &rpl_tree->node;
	t = time(0);

	for( dl=root ; dl ; dl=dl->next ) {
		/* add a domain node */
		node = add_mi_node_child( rpl, 0, "Domain", 6,
					dl->name.s, dl->name.len);
		if (node==0)
			goto error;

		dom = dl->d;
		/* add some attributes to the domain node */
		p= int2str((unsigned long)dom->size, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, "table", 5, p, len);
		if (attr==0)
			goto error;

		/* add the entries per hash */
		for(i=0,n=0,max=0; i<dom->size; i++) {
			lock_ulslot( dom, i);

			n += dom->table[i].n;
			if(max<dom->table[i].n)
				max= dom->table[i].n;
			for( r = dom->table[i].first ; r ; r=r->next ) {
				/* add entry */
				if (mi_add_aor_node( node, r, t, short_dump)!=0) {
					unlock_ulslot( dom, i);
					goto error;
				}
			}

			unlock_ulslot( dom, i);
		}

		/* add more attributes to the domain node */
		p= int2str((unsigned long)n, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, "records", 7, p, len);
		if (attr==0)
			goto error;

		p= int2str((unsigned long)max, &len);
		attr = add_mi_attr( node, MI_DUP_VALUE, "max_slot", 8, p, len);
		if (attr==0)
			goto error;

	}

	return rpl_tree;
error:
	free_mi_tree(rpl_tree);
	return 0;
}
Exemple #9
0
/*!
 * \brief Get lock for a domain
 * \param _d domain
 * \param _aor adress of record, used as hash source for the lock slot
 */
void lock_udomain(udomain_t* _d, str* _aor) {
    unsigned int sl;
    sl = core_hash(_aor, 0, _d->size);
    lock_ulslot(_d, sl);
}
Exemple #10
0
static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
							unsigned int part_idx, unsigned int part_max)
{
	dlist_t *p;
	pcontact_t *c;
	void *cp;
	int shortage;
	int needed;
	int i = 0;
	cp = buf;
	shortage = 0;
	unsigned int received_len = 0;
	char received_s[60]; // IPv6-Address (39) + "sip:" (4) + ":" (1) + Port (5); 60 should be plenty.
	/* Reserve space for terminating 0000 */
	len -= sizeof(int);

	for (p = root; p != NULL; p = p->next) {

		for(i=0; i<p->d->size; i++) {

			if ( (i % part_max) != part_idx )
				continue;

			lock_ulslot(p->d, i);
			if(p->d->table[i].n<=0)
			{
				unlock_ulslot(p->d, i);
				continue;
			}
			for (c = p->d->table[i].first; c != NULL; c = c->next) {
					if (c->received_host.s) {
						received_len = snprintf(received_s, sizeof(received_s), "sip:%.*s:%x", c->received_host.len,
							c->received_host.s, c->received_port) - 1; 

						needed = (int)(sizeof(received_len)
								+ received_len + sizeof(c->sock)
								+ sizeof(unsigned int) + sizeof(c->path.len)
								+ c->path.len);
						if (len >= needed) {
							cp = (char*)cp + received_len;
							cp = (char*)cp + sizeof(received_len);

							memcpy(cp, received_s, received_len);
							cp = (char*)cp + received_len;

							memcpy(cp, &c->sock, sizeof(c->sock));
							cp = (char*)cp + sizeof(c->sock);

							memset(cp, 0, sizeof(unsigned int));
							cp = (char*)cp + sizeof(unsigned int);

							memcpy(cp, &c->path.len, sizeof(c->path.len));
							cp = (char*)cp + sizeof(c->path.len);
							memcpy(cp, c->path.s, c->path.len);
							cp = (char*)cp + c->path.len;
							len -= needed;
						} else {
							shortage += needed;
						}
					}
			}
			unlock_ulslot(p->d, i);
		}
	}
	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(int));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Exemple #11
0
static int receive_sync_request(int node_id)
{
	bin_packet_t *sync_packet;
	dlist_t *dl;
	udomain_t *dom;
	map_iterator_t it;
	struct urecord *r;
	ucontact_t* c;
	str st;
	void **p;
	int i;

	for (dl = root; dl; dl = dl->next) {
		dom = dl->d;
		for(i = 0; i < dom->size; i++) {
			lock_ulslot(dom, i);
			for (map_first(dom->table[i].records, &it);
				iterator_is_valid(&it);
				iterator_next(&it)) {

				p = iterator_val(&it);
				if (p == NULL)
					goto error_unlock;
				r = (urecord_t *)*p;

				sync_packet = clusterer_api.sync_chunk_start(&contact_repl_cap,
											location_cluster, node_id);
				if (!sync_packet)
					goto error_unlock;

				/* urecord in this chunk */
				bin_push_int(sync_packet, 0);

				bin_push_str(sync_packet, r->domain);
				bin_push_str(sync_packet, &r->aor);

				for (c = r->contacts; c; c = c->next) {
					sync_packet = clusterer_api.sync_chunk_start(&contact_repl_cap,
												location_cluster, node_id);
					if (!sync_packet)
						goto error_unlock;

					/* contact in this chunk */
					bin_push_int(sync_packet, 1);

					bin_push_str(sync_packet, r->domain);
					bin_push_str(sync_packet, &r->aor);
					bin_push_str(sync_packet, &c->c);
					bin_push_str(sync_packet, &c->callid);
					bin_push_str(sync_packet, &c->user_agent);
					bin_push_str(sync_packet, &c->path);
					bin_push_str(sync_packet, &c->attr);
					bin_push_str(sync_packet, &c->received);
					bin_push_str(sync_packet, &c->instance);

					st.s = (char *)&c->expires;
					st.len = sizeof c->expires;
					bin_push_str(sync_packet, &st);

					st.s = (char *)&c->q;
					st.len = sizeof c->q;
					bin_push_str(sync_packet, &st);

					bin_push_str(sync_packet, c->sock?&c->sock->sock_str:NULL);
					bin_push_int(sync_packet, c->cseq);
					bin_push_int(sync_packet, c->flags);
					bin_push_int(sync_packet, c->cflags);
					bin_push_int(sync_packet, c->methods);

					st.s = (char *)&c->last_modified;
					st.len = sizeof c->last_modified;
					bin_push_str(sync_packet, &st);
				}
			}
			unlock_ulslot(dom, i);
		}
	}

	return 0;

error_unlock:
	unlock_ulslot(dom, i);
	return -1;
}
Exemple #12
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);
        }
    }
    
}
Exemple #13
0
/* can't assume we are locked here */
int get_pcontact_by_src(udomain_t* _d, str * _host, unsigned short _port, unsigned short _proto, struct pcontact** _c) {
	int i;
	struct pcontact* c;
	unsigned int aorhash, sl;
	char c_contact[256], *p;
	str s_contact;

	if (hashing_type == 1) {//we hash on IP:PORT - so no need to search sequentially..
		/* get_aor_hash in this mode expects to see contact as host:port */
		memset(c_contact, 0, 256);
		memcpy(c_contact, _host->s, _host->len);
		p = c_contact + _host->len;
		*p = ':';
		p++;
		sprintf(p,"%d", _port);
		s_contact.s = c_contact;
		s_contact.len = strlen(c_contact);

		aorhash = get_aor_hash(_d, &s_contact);
		sl = aorhash & (_d->size - 1);
		c = _d->table[sl].first;

		for (i = 0; i < _d->table[sl].n; i++) {
			lock_ulslot(_d, i);
			LM_DBG("Searching for contact in P-CSCF usrloc [%.*s]\n",
					s_contact.len,
					s_contact.s);

			// First check, if Proto and Port matches:
			if ((c->received_port == _port) && (c->received_proto == _proto)) {
				LM_DBG("Received host len %d (search %d)\n", c->received_host.len, _host->len);
				// Then check the length:
				if (c->received_host.len == _host->len) {
					LM_DBG("Received host %.*s (search %.*s)\n",
							c->received_host.len, c->received_host.s,
							_host->len, _host->s);

					// Finally really compare the "received_host"
					if (!memcmp(c->received_host.s, _host->s, _host->len)) {
						*_c = c;
						return 0;
					}
				}
			}
			unlock_ulslot(_d, i);
		}
	} else {
		/* search sequentially */
		for(i=0; i<_d->size; i++)
		{
			c = _d->table[i].first;
			while(c) {
				LM_DBG("Port %d (search %d), Proto %d (search %d), reg_state %s (search %s)\n",
					c->received_port, _port, c->received_proto, _proto,
					reg_state_to_string(c->reg_state), reg_state_to_string(PCONTACT_REGISTERED)
					);
				// First check, if Proto and Port matches:
				if ((c->received_port == _port) && (c->received_proto == _proto)) {
					LM_DBG("Received host len %d (search %d)\n", c->received_host.len, _host->len);
					// Then check the length:
					if (c->received_host.len == _host->len) {
						LM_DBG("Received host %.*s (search %.*s)\n",
							c->received_host.len, c->received_host.s,
							_host->len, _host->s);

						// Finally really compare the "received_host"
						if (!memcmp(c->received_host.s, _host->s, _host->len)) {
							*_c = c;
							return 0;
						}
					}
				}
				c = c->next;
			}
		}
	}
	return 1; /* Nothing found */
}
Exemple #14
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");
}
Exemple #15
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;
    
}
Exemple #16
0
/*!
 * \brief Get all contacts from the memory, in partitions if wanted
 * \see get_all_ucontacts
 * \param buf target buffer
 * \param len length of buffer
 * \param flags contact flags
 * \param part_idx part index
 * \param part_max maximal part
 * \return 0 on success, positive if buffer size was not sufficient, negative on failure
 */
static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max)
{
	dlist_t *p;
	impurecord_t *r;
	ucontact_t *c;
	void *cp;
	int shortage;
	int needed;
	int i = 0;
	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(c->c.len);

	for (p = root; p != NULL; p = p->next) {

		for(i=0; i<p->d->size; i++) {

			if ( (i % part_max) != part_idx )
				continue;

			lock_ulslot(p->d, i);
			if(p->d->table[i].n<=0)
			{
				unlock_ulslot(p->d, i);
				continue;
			}
			for (r = p->d->table[i].first; r != NULL; r = r->next) {
				for (c = r->contacts; c != NULL; c = c->next) {
					if (c->c.len <= 0)
						continue;
					/*
					 * List only contacts that have all requested
					 * flags set
					 */
					if ((c->cflags & flags) != flags)
						continue;
					if (c->received.s) {
						needed = (int)(sizeof(c->received.len)
								+ c->received.len + sizeof(c->sock)
								+ sizeof(c->cflags) + sizeof(c->path.len)
								+ c->path.len);
						if (len >= needed) {
							memcpy(cp,&c->received.len,sizeof(c->received.len));
							cp = (char*)cp + sizeof(c->received.len);
							memcpy(cp, c->received.s, c->received.len);
							cp = (char*)cp + c->received.len;
							memcpy(cp, &c->sock, sizeof(c->sock));
							cp = (char*)cp + sizeof(c->sock);
							memcpy(cp, &c->cflags, sizeof(c->cflags));
							cp = (char*)cp + sizeof(c->cflags);
							memcpy(cp, &c->path.len, sizeof(c->path.len));
							cp = (char*)cp + sizeof(c->path.len);
							memcpy(cp, c->path.s, c->path.len);
							cp = (char*)cp + c->path.len;
							len -= needed;
						} else {
							shortage += needed;
						}
					} else {
						needed = (int)(sizeof(c->c.len) + c->c.len +
							sizeof(c->sock) + sizeof(c->cflags) +
							sizeof(c->path.len) + c->path.len);
						if (len >= needed) {
							memcpy(cp, &c->c.len, sizeof(c->c.len));
							cp = (char*)cp + sizeof(c->c.len);
							memcpy(cp, c->c.s, c->c.len);
							cp = (char*)cp + c->c.len;
							memcpy(cp, &c->sock, sizeof(c->sock));
							cp = (char*)cp + sizeof(c->sock);
							memcpy(cp, &c->cflags, sizeof(c->cflags));
							cp = (char*)cp + sizeof(c->cflags);
							memcpy(cp, &c->path.len, sizeof(c->path.len));
							cp = (char*)cp + sizeof(c->path.len);
							memcpy(cp, c->path.s, c->path.len);
							cp = (char*)cp + c->path.len;
							len -= needed;
						} else {
							shortage += needed;
						}
					}
				}
			}
			unlock_ulslot(p->d, i);
		}
	}
	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(c->c.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Exemple #17
0
static void ul_rpc_dump(rpc_t* rpc, void* ctx)
{
	struct urecord* r;
	dlist_t* dl;
	udomain_t* dom;
	time_t t;
	str brief = {0, 0};
	str empty_str = {"[not set]", 9};
	str state_str = {"[not set]", 9};
	str socket_str = {"[not set]", 9};
	int summary = 0;
	ucontact_t* c;
	void* th;
	void* ah;
	void* ih;
	void* vh;
	void* sh;
	int max, n, i;

	rpc->scan(ctx, "*S", &brief);

	if(brief.len==5 && (strncmp(brief.s, "brief", 5)==0))
		summary = 1;
	
	t = time(0);
	for( dl=root ; dl ; dl=dl->next ) {
		dom = dl->d;
		if (rpc->add(ctx, "{", &th) < 0)
		{
			rpc->fault(ctx, 500, "Internal error creating top rpc");
			return;
		}
		if(rpc->struct_add(th, "Sd{",
					"Domain",  &dl->name,
					"Size",    (int)dom->size,
					"AoRs",    &ah)<0)
		{
			rpc->fault(ctx, 500, "Internal error creating inner struct");
			return;
		}
		for(i=0,n=0,max=0; i<dom->size; i++) {
			lock_ulslot( dom, i);
			n += dom->table[i].n;
			if(max<dom->table[i].n)
				max= dom->table[i].n;
			for( r = dom->table[i].first ; r ; r=r->next ) {
				if(summary==1)
				{
					if(rpc->struct_add(ah, "S",
							"AoR", &r->aor)<0)
					{
						unlock_ulslot( dom, i);
						rpc->fault(ctx, 500, "Internal error creating aor struct");
						return;
					}
				} else {
					if(rpc->struct_add(ah, "Sd{",
							"AoR", &r->aor,
							"HashID", r->aorhash,
							"Contacts", &ih)<0)
					{
						unlock_ulslot( dom, i);
						rpc->fault(ctx, 500, "Internal error creating aor struct");
						return;
					}
					for( c=r->contacts ; c ; c=c->next)
					{
						if(rpc->struct_add(ih, "{",
							"Contact", &vh)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500, "Internal error creating contact struct");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"Address", &c->c)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding addr");
								return;
						}
						if (c->expires == 0) {
							if(rpc->struct_add(vh, "s",
									"Expires", "permanent")<0)
							{
								unlock_ulslot( dom, i);
								rpc->fault(ctx, 500,
										"Internal error adding expire");
								return;
							}
						} else if (c->expires == UL_EXPIRED_TIME) {
							if(rpc->struct_add(vh, "s",
									"Expires", "deleted")<0)
							{
								unlock_ulslot( dom, i);
								rpc->fault(ctx, 500,
										"Internal error adding expire");
								return;
							}
						} else if (t > c->expires) {
							if(rpc->struct_add(vh, "s",
									"Expires", "expired")<0)
							{
								unlock_ulslot( dom, i);
								rpc->fault(ctx, 500,
										"Internal error adding expire");
								return;
							}
						} else {
							if(rpc->struct_add(vh, "d",
									"Expires", (int)(c->expires - t))<0)
							{
								unlock_ulslot( dom, i);
								rpc->fault(ctx, 500,
										"Internal error adding expire");
								return;
							}
						}
						if (c->state == CS_NEW) {
							state_str.s = "CS_NEW";
							state_str.len = 6;
						} else if (c->state == CS_SYNC) {
							state_str.s = "CS_SYNC";
							state_str.len = 7;
						} else if (c->state== CS_DIRTY) {
							state_str.s = "CS_DIRTY";
							state_str.len = 8;
						} else {
							state_str.s = "CS_UNKNOWN";
							state_str.len = 10;
						}
						if(c->sock)
						{
							socket_str.s = c->sock->sock_str.s;
							socket_str.len = c->sock->sock_str.len;
						}
						if(rpc->struct_add(vh, "f",
									"Q", c->q)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding q");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"Call-ID", &c->callid)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding callid");
							return;
						}
						if(rpc->struct_add(vh, "d",
									"CSeq", c->cseq)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding cseq");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"User-Agent",
										(c->user_agent.len)?&c->user_agent:
												&empty_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding user-agent");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"Received",
										(c->received.len)?&c->received:
												&empty_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding received");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"Path",
										(c->path.len)?&c->path:
												&empty_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding path");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"State", &state_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding state");
							return;
						}
						if(rpc->struct_add(vh, "d",
									"Flags", c->flags)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding flags");
							return;
						}
						if(rpc->struct_add(vh, "d",
									"CFlags", c->cflags)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding cflags");
							return;
						}
						if(rpc->struct_add(vh, "S",
									"Socket", &socket_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding socket");
							return;
						}
						if(rpc->struct_add(vh, "d",
									"Methods", c->methods)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding methods");
							return;
						}
						if(rpc->struct_add(vh, "S",
								"Ruid", (c->ruid.len)?&c->ruid: &empty_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding ruid");
							return;
						}
						if(rpc->struct_add(vh, "S",
								"Instance",
								(c->instance.len)?&c->instance: &empty_str)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding instance");
							return;
						}
						if(rpc->struct_add(vh, "d",
									"Reg-Id", c->reg_id)<0)
						{
							unlock_ulslot( dom, i);
							rpc->fault(ctx, 500,
									"Internal error adding reg_id");
							return;
						}

					}
				}
			}

			unlock_ulslot( dom, i);
		}

		/* extra attributes node */
		if(rpc->struct_add(th, "{",
					"Stats",    &sh)<0)
		{
			rpc->fault(ctx, 500, "Internal error creating stats struct");
			return;
		}
		if(rpc->struct_add(sh, "dd",
				"Records", n,
				"Max-Slots", max)<0)
		{
			rpc->fault(ctx, 500, "Internal error adding stats");
			return;
		}
	}
}