예제 #1
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)
{
	r_public *p;

	p = get_r_public(aor);
	if (!p){
		if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s)
			return add_r_public(aor,*reg_state,*s);
		else return 0;
	}else{
		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);
		}
		return p;
	}
}
예제 #2
0
/**
 * Updates the r_public with the new is_default.
 * If not found, it will be inserted
 * \note Must be called with a lock on the domain to avoid races
 * @param c - the r_contact to add to
 * @param pub_id - the public identity
 * @param is_default - if this is the default contact
 * @returns the newly added r_public, 0 on error
 */
r_public* update_r_public(r_contact *c,str pub_id,int *is_default)
{
	r_public *p;

	if (!c) return 0;
	p = get_r_public(c,pub_id);
	if (!p){
		if (is_default)
			return add_r_public(c,pub_id,*is_default);
		else return 0;
	}else{
		if (is_default)	p->is_default = *is_default;
		return p;
	}
}
예제 #3
0
/**
 * Save this subscription.
 * @param msg - the SIP SUBSCRIBE message
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error
 */
int S_subscribe(struct sip_msg *msg,char *str1,char *str2)
{
	int ret=CSCF_RETURN_FALSE;
	struct sip_uri puri;
	str uri={0,0};
	str event;
	int event_i=IMS_EVENT_NONE;
	int expires=0,expires_time=0;
	str subscriber;
	r_public *p=0;
	r_subscriber *s=0,*new_s=0;
	dlg_t *dialog=0;

	LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Saving SUBSCRIBE\n");

	/* First check the parameters */
	if (msg->first_line.type!=SIP_REQUEST)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a request\n");
		goto error;
	}		
	if (msg->first_line.u.request.method.len != 9 ||
		memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a SUBSCRIBE\n");
		goto error;
	}

	/* 1. Get the event 	*/
	event = cscf_get_event(msg);
	if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n",
			event.len,event.s);
		ret = CSCF_RETURN_FALSE;	
		goto done;
	} 
	if (event.len==0 && strncasecmp(event.s,"reg",3)==0)
		event_i = IMS_EVENT_REG;
	
	/* 2. Get the target of the SUBSCRIBE from RequestURI */
	if (msg->new_uri.s) uri = msg->new_uri;
	else uri = msg->first_line.u.request.uri;
	
	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error parsing uri <%.*s>\n",
			uri.len,uri.s);
		goto error;
	}
	uri.len = lookup_sip.len+puri.user.len+1+puri.host.len;
	uri.s = pkg_malloc(uri.len);
	if (!uri.s){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error allocating %d bytes\n",uri.len);
		goto error;
	}
	uri.len=0;
	memcpy(uri.s,lookup_sip.s,lookup_sip.len);
	uri.len+=lookup_sip.len;
	memcpy(uri.s+uri.len,puri.user.s,puri.user.len);
	uri.len+=puri.user.len;
	uri.s[uri.len++]='@';
	memcpy(uri.s+uri.len,puri.host.s,puri.host.len);
	uri.len+=puri.host.len;

	/* 3. Get the Subscriber's Identity */
	subscriber = cscf_get_contact(msg);
	if (!subscriber.len){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Contact empty.\n");
		ret =  CSCF_RETURN_FALSE;
		goto done;		
	}
	LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Contact <%.*s>.\n",
		subscriber.len,subscriber.s);
	
	p = get_r_public(uri);

	/* Registration is possible even if the user is not registered... so just create one */
	if (!p){
		p = add_r_public(uri,0,0);
	}
	if (!p){		
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Identity not found and error on creation <%.*s>\n",
			uri.len,uri.s);
		ret =  CSCF_RETURN_FALSE;
		goto done;
	}
		
	expires = cscf_get_expires_hdr(msg,0);
	if (expires == -1) expires = subscription_default_expires;
	if (expires > 0) {
		if (expires < subscription_min_expires) expires = subscription_min_expires;
		if (expires > subscription_max_expires) expires = subscription_max_expires;
		r_act_time();
		expires_time = expires + time_now;
		
		/* get the old subscriber - if any */
		s = get_r_subscriber(p,subscriber,event_i);	
		if (!s){
			/* create a new dialog */
			if (tmb.new_dlg_uas(msg, 200, &dialog) < 0) {		
				LOG(L_ERR,"ERR:"M_NAME":S_subscribe:  Error while creating dialog state\n");
				ret = CSCF_RETURN_FALSE;
				goto error;
			}
		}else
			dialog = s->dialog;
		
		/* update the subscriber */
		if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){		
			//if (!s)	/* Only on first subscription, not on refreshes, send a notify */
				S_event_reg(p,0,new_s,IMS_REGISTRAR_SUBSCRIBE,0);
			ret = CSCF_RETURN_TRUE;
		}
		else
			ret = CSCF_RETURN_FALSE;	
	}else{
		/* Unsubscribe */
		/* get the old subscriber - if any */
		r_act_time();
		s = get_r_subscriber(p,subscriber,event_i);	
		if (s) {
			s->expires = time_now;
			S_event_reg(p,0,s,IMS_REGISTRAR_UNSUBSCRIBE,1);
			del_r_subscriber(p,s);
		}
		ret = CSCF_RETURN_TRUE;
	}
done:	
	r_unlock(p->hash);
	if (expires ==0 )S_SUBSCRIBE_reply(msg,200,MSG_REG_UNSUBSCRIBE_OK,&expires,&uri);
	else S_SUBSCRIBE_reply(msg,200,MSG_REG_SUBSCRIBE_OK,&expires,&uri);
	if (uri.s) pkg_free(uri.s);
	return ret;
error:
	if (p) r_unlock(p->hash);
	if (uri.s) pkg_free(uri.s);
	ret=CSCF_RETURN_FALSE;
	return ret;	
}
예제 #4
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;	
}
예제 #5
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;

	p = get_r_public(aor);
	if (!p){
		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");
			}
			return p;
		}
		else return 0;
	}else{
		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 (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");
		}
		return p;
	}
out_of_memory:
	return p;	
}