/**
 * Drops and deallocates a r_public.
 * \note Must be called with a lock on the domain to avoid races
 * \note When calling be sure that get_r_public(d,aor) returns p,
 * to avoid a bogus removal
 * @param c - the r_contact that this r_public is attached currently to
 * @param p - the r_public to remove
 */
void del_r_public(r_contact *c,r_public *p)
{
	if (c->head == p) c->head = p->next;
	else p->prev->next = p->next;
	if (c->tail == p) c->tail = p->prev;
	else p->next->prev = p->prev;
	free_r_public(p);
}
Example #2
0
/**
 * Drops and deallocates a r_public.
 * \note Don't forget to release the lock on the !!OLD!! hash value (yes, the memory is 
 * deallocated, so you can not do r_unlock(p->hash) because p does not exist anymore!)
 * \note When calling be sure that get_r_public(aor) returns p, to avoid a bogus removal
 * @param p - the r_public to remove
 */
void del_r_public(r_public *p)
{
	S_drop_all_dialogs(p->aor);
	if (registrar[p->hash].head == p) registrar[p->hash].head = p->next;
	else p->prev->next = p->next;
	if (registrar[p->hash].tail == p) registrar[p->hash].tail = p->prev;
	else p->next->prev = p->prev;
	free_r_public(p);
}
Example #3
0
/**
 * Destroy the registrar
 */
void r_storage_destroy()
{
	int i;
	r_public *p,*np;
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			p = registrar[i].head;
			while(p){
				np = p->next;
				free_r_public(p);
				p = np;
			}
		r_unlock(i);
		lock_dealloc(registrar[i].lock);
	}
	shm_free(registrar);
}
/**
 * Frees memory taken by a r_contact structure
 * @param c - the r_contact to be deallocated
 */
void free_r_contact(r_contact *c)
{
	r_public *p,*n;
	int i;

	if (!c) return;
	if (c->pinhole) shm_free(c->pinhole);
	if (c->host.s) shm_free(c->host.s);
	if (c->uri.s) shm_free(c->uri.s);
	if (c->service_route){
		i=0;
		for(i=0;i<c->service_route_cnt;i++)
			if (c->service_route[i].s)
				shm_free(c->service_route[i].s);
		shm_free(c->service_route);
	}
	p = c->head;
	while(p){
		n = p->next;
		free_r_public(p);
		p = n;
	}
	if (c->security_temp) free_r_security(c->security_temp);
	if (c->security) free_r_security(c->security);
	if (c->pcc_session_id.len) shm_free(c->pcc_session_id.s);
    if(c->si_pc)
	{
      if(c->si_pc->name.s) shm_free(c->si_pc->name.s);
	  if(c->si_pc->address_str.s) shm_free(c->si_pc->address_str.s);
	  if(c->si_pc->port_no_str.s) shm_free(c->si_pc->port_no_str.s);
	  shm_free(c->si_pc);	
	}
	if(c->si_ps)
	{
      if(c->si_ps->name.s) shm_free(c->si_ps->name.s);
	  if(c->si_ps->address_str.s) shm_free(c->si_ps->address_str.s);
	  if(c->si_ps->port_no_str.s) shm_free(c->si_ps->port_no_str.s);	
	  shm_free(c->si_ps);
	}

	shm_free(c);
}
Example #5
0
/**
 *	Decode a r_contact from a binary data structure
 * @param x - binary data to decode from
 * @returns the r_contact* where the data has been decoded
 */
r_contact* bin_decode_r_contact(bin_data *x)
{
	r_contact *c=0;
	r_public *p=0,*pn=0;
	int len,i;
	char k;
	unsigned short us;
	str st;
	
	len = sizeof(r_contact);
	c = (r_contact*) shm_malloc(len);
	if (!c) {
		LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error allocating %d bytes.\n",len);
		goto error;
	}
	memset(c,0,len);
	
	if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->host),&st)) goto error;
	if (!bin_decode_ushort(x,&c->port)) goto error;
	if (!bin_decode_char(x,&c->transport)) goto error;

	c->hash = get_contact_hash(c->host,c->port,c->transport,r_hash_size);
	
	if (!bin_decode_r_security(x,&(c->security_temp))) goto error;
	if (!bin_decode_r_security(x,&(c->security))) goto error;
	
	if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->uri),&st)) goto error;
	
	if (!bin_decode_char(x,&k)) goto error;
	c->reg_state = k;

	if (!bin_decode_time_t(x,&c->expires)) goto error;
	
	if (!bin_decode_ushort(x,	&c->service_route_cnt)) goto error;

	len = sizeof(str)*c->service_route_cnt;
	c->service_route = (str*) shm_malloc(len);
	if (!c->service_route) {
		LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error allocating %d bytes.\n",len);
		goto error;
	}
	memset(c->service_route,0,len);	
	for(i=0;i<c->service_route_cnt;i++)
		if (!bin_decode_str(x,&st)||!str_shm_dup(c->service_route+i,&st)) goto error;
	
	if (!bin_decode_pinhole(x,&(c->pinhole ))) goto error;
	
	if (!bin_decode_char(x,&k)) goto error;
	c->sos_flag = k;
	
	if (!bin_decode_str(x,&st)||!str_shm_dup(&(c->pcc_session_id),&st)) goto error;
		
	if (!bin_decode_ushort(x,&us)) goto error;
	for(i=0;i<us;i++){
		p = bin_decode_r_public(x);
		if (!p) goto error;
		p->prev = c->tail;
		p->next = 0;
		if (c->tail) c->tail->next = p;
		c->tail = p;
		if (!c->head) c->head = p;
	}
	return c;
error:
	LOG(L_ERR,"ERR:"M_NAME":bin_decode_r_contact: Error while decoding (at %d (%04x)).\n",x->max,x->max);
	if (c) {
		if (c->host.s) shm_free(c->host.s);		
		if (c->security_temp) free_r_security(c->security_temp);
		if (c->security) free_r_security(c->security);
		if (c->uri.s) shm_free(c->uri.s);
		if (c->pinhole) shm_free(c->pinhole);
		while(c->head){
			p = c->head;
			pn = p->next;
			free_r_public(p);
			c->head = pn;
		}
		shm_free(c);
	}
	return 0;
}
Example #6
0
/**
 * Updates the r_public with the new reg_state and ims_subscription values.
 * If not found, it will be inserted.
 * \note Aquires the lock on the hash_slot on success, so release it when you are done.
 * @param aor - the address of record
 * @param reg_state - new registration state, NULL if no update necessary
 * @param s - the new subscription attached, NULL if no update necessary
 * @returns the update r_public or NULL on error
 */
r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s,
	str *ccf1, str *ccf2, str *ecf1, str *ecf2)
{
	r_public *p=0;
	//LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s);
	
	if ((*s)->wpsi) {
		p = get_r_public_wpsi(aor);
	} else {
		p = get_r_public(aor);
	}
	
	if (!p){
		//LOG(L_DBG,"updating a new r_public profile\n");			 
		if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
			p = add_r_public(aor,*reg_state,*s);
			
			if (!p) return p;			
			if (ccf1) {
				if (p->ccf1.s) shm_free(p->ccf1.s);
				STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
			}
			if (ccf2) {
				if (p->ccf2.s) shm_free(p->ccf2.s);
				STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
			}
			if (ecf1) {
				if (p->ecf1.s) shm_free(p->ecf1.s);
				STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
			}
			if (ecf2) {
				if (p->ecf2.s) shm_free(p->ecf2.s);
				STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
			}
			//LOG(L_DBG,"update_r_public():  it was actually adding\n");
			return p;
		}
		else return 0;
	}else{
		//LOG(L_DBG,"updating a not so new r_public profile\n");		
		if (reg_state) p->reg_state = *reg_state;
		if (*s) {
			
			if (p->s){
				lock_get(p->s->lock);
				if (p->s->ref_count==1){
					free_user_data(p->s);
				}else{
					p->s->ref_count--;
					lock_release(p->s->lock);
				}
			}			
			p->s = *s;
			lock_get(p->s->lock);
				p->s->ref_count++;
			lock_release(p->s->lock);
			
			
			 if ((*s)->wpsi)
			 {	
			 	
			 	 p->s=NULL; 
			 	 			 	 
			 	 if (p->prev) p->prev->next=p->next;
			 	 else registrar[r_hash_size].head=p->next;	
			 	 if (p->next) p->next->prev=p->prev;
			 	 else registrar[r_hash_size].tail=p->prev;
			 	 
			 	 free_r_public(p);
			 	 r_unlock(r_hash_size);			 
			 	 p=add_r_public(aor,0,*s);
			 	 
			 }
			
			
		}
		if (ccf1) {
			if (p->ccf1.s) shm_free(p->ccf1.s);
			STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
		}
		if (ccf2) {
			if (p->ccf2.s) shm_free(p->ccf2.s);
			STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
		}
		if (ecf1) {
			if (p->ecf1.s) shm_free(p->ecf1.s);
			STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
		}
		if (ecf2) {
			if (p->ecf2.s) shm_free(p->ecf2.s);
			STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
		}
		//LOG(L_DBG,"update_r_public():    return normaly\n");
		return p;
	}
out_of_memory:
	return p;	
}