Esempio n. 1
0
/**
 * Processes a notification and updates the registrar info.
 * @param n - the notification
 * @param expires - the Subscription-Status expires parameter
 * @returns 1 on success, 0 on error
 */
int r_notification_process(r_notification *n,int expires)
{
	r_registration *r;
	r_regcontact *rc;	
	r_contact *c;
	struct sip_uri puri;
	enum Reg_States reg_state;
	int expires2;
	r_subscription *s=0;
	
	r_notification_print(n);	
	if (!n) return 0;
	
	r_act_time();
	r = n->registration;
	while(r){
		
		rc = r->contact;
		while(rc){
			if (parse_uri(rc->uri.s,rc->uri.len,&puri)<0){
				LOG(L_ERR,"ERR:"M_NAME":r_notification_process: Error parsing Contact URI <%.*s>\n",
					rc->uri.len,rc->uri.s);
				goto next;
			}
//			LOG(L_CRIT,"DBG:"M_NAME":r_notification_process: refreshing contacts <%.*s> [%d]\n",rc->uri.len,rc->uri.s,rc->expires);
			if (rc->state==IMS_REGINFO_TERMINATED){
				reg_state = DEREGISTERED;
				expires2 = time_now+30;
				c = update_r_contact(puri.host,puri.port_no,puri.proto,
					0,&reg_state,&expires2,0,0,0);
				if (c) {
					LOG(L_DBG,"DBG:"M_NAME":r_notification_process: expired contact <%.*s>\n",
						c->uri.len,c->uri.s);
					r_unlock(c->hash);					
				}
			}else{
				reg_state = REGISTERED;
				expires2 = rc->expires+time_now;
				c = update_r_contact(puri.host,puri.port_no,puri.proto,
					0,&reg_state,&expires2,0,0,0);
				if (c) {
					LOG(L_DBG,"DBG:"M_NAME":r_notification_process: refreshing contact <%.*s> [%d]\n",
						c->uri.len,c->uri.s,rc->expires);
					r_unlock(c->hash);					
				}

			}
next:				
			rc = rc->next;	
		}
		s = get_r_subscription(r->aor);
		if (s){
			update_r_subscription(s,expires);
			subs_unlock(s->hash);
		}
		r = r->next;
	}

	return 1;
}
Esempio n. 2
0
/**
 * Response callback for subscribe
 */
void r_subscribe_response(struct cell *t,int type,struct tmcb_params *ps)
{
	str req_uri;
	int expires;
	r_subscription *s=0;
	LOG(L_DBG,"DBG:"M_NAME":r_subscribe_response: code %d\n",ps->code);
	if (!ps->rpl) {
		LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: No reply\n");
		return;	
	}
	req_uri = *((str*) *(ps->param));		
	s = get_r_subscription(req_uri);
	if (!s){
		LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: received a SUBSCRIBE response but no subscription for <%.*s>\n",
			req_uri.len,req_uri.s);
		return;
	}
	if (ps->code>=200 && ps->code<300){
		expires = cscf_get_expires_hdr(ps->rpl);
		update_r_subscription(s,expires);
		tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH);
	}else
		if (ps->code==404){
			update_r_subscription(s,0);			
			//tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH);
		}else{
			LOG(L_INFO,"INF:"M_NAME":r_subscribe_response: SUBSCRIRE response code %d ignored\n",ps->code);				
		}	
	if (s) subs_unlock(s->hash);		
}
void print_subs(int log_level)
{
	r_subscription *s;
	int i;
#ifdef SER_MOD_INTERFACE
	if (!is_printable(log_level))
#else		
	if (debug<log_level)
#endif	
		return; /* to avoid useless calls when nothing will be printed */

	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Subscription list begin ---------\n");
	for(i=0;i<subscriptions_hash_size;i++){
		subs_lock(i);
		s = subscriptions[i].head;
		r_act_time();
		while(s){
			LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4u]\tP: <"ANSI_BLUE"%.*s"ANSI_GREEN"> D:["ANSI_CYAN"%5d"ANSI_GREEN"] E:["ANSI_MAGENTA"%5d"ANSI_GREEN"] Att:[%2d]\n",
				s->hash,s->req_uri.len,s->req_uri.s,s->duration,(int)(s->expires-time_now),s->attempts_left);
			s = s->next;			
		}
		subs_unlock(i);
	}
	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Subscription list end -----------\n");	
}
Esempio n. 4
0
/**
 * Finds out if a subscription exists
 * @param aor - AOR to look for
 * @returns 1 if found, 0 if not
 */
int is_r_subscription(str aor)
{
	r_subscription *s;
	unsigned int hash = get_subscription_hash(aor);
	subs_lock(hash);
		s = subscriptions[hash].head;
		while(s){
			if (s->req_uri.len == aor.len &&
				strncasecmp(s->req_uri.s,aor.s,aor.len)==0)
			{
				subs_unlock(hash);	
				return 1;
			}
			s = s->next;
		}
	subs_unlock(hash);	
	return 0;
}
/**
 * The Subscription timer looks for almost expired subscriptions and subscribes again.
 * @param ticks - the current time
 * @param param - the generic parameter
 */
void subscription_timer(unsigned int ticks, void* param)
{
	r_subscription *s,*ns;
	int i;
	#ifdef WITH_IMS_PM
		int subs_cnt=0;
	#endif
	for(i=0;i<subscriptions_hash_size;i++){
		subs_lock(i);
		s = subscriptions[i].head;
		r_act_time();
		while(s){
			ns = s->next;			
			if (s->attempts_left > 0 ){
				/* attempt to send a subscribe */
				if (!r_send_subscribe(s,s->duration)){
					LOG(L_ERR,"ERR:"M_NAME":subscription_timer: Error on SUBSCRIBE (%d times)... droping\n",
						pcscf_subscribe_retries);
					del_r_subscription_nolock(s);
				}else{
					s->attempts_left--;
					#ifdef WITH_IMS_PM
						subs_cnt++;
					#endif
				}
			}else if (s->attempts_left==0) {
				/* we failed to many times, drop the subscription */
				LOG(L_ERR,"ERR:"M_NAME":subscription_timer: Error on SUBSCRIBE for %d times... aborting\n",pcscf_subscribe_retries);
				del_r_subscription_nolock(s);										
			}else{
				/* we are subscribed already */
				/* if expired, drop it */
				if (s->expires<time_now) 
					del_r_subscription_nolock(s);
				#ifdef WITH_IMS_PM
					else subs_cnt++;
				#endif
					
				/* if not expired, check for renewal */
//		Commented as the S-CSCF should adjust the subscription time accordingly				
//				if ((s->duration<1200 && s->expires-time_now<s->duration/2)||
//					(s->duration>=1200 && s->expires-time_now<600))
//				{
//					/* if we need a resubscribe, we mark it as such and try to subscribe again */					
//					s->attempts_left = pcscf_subscribe_retries;
//					ns = s;
//				}
			}
			s = ns;
		}	
		subs_unlock(i);
	}
	print_subs(L_INFO);
	#ifdef WITH_IMS_PM
		IMS_PM_LOG01(RD_NbrSubs,subs_cnt);
	#endif	
}
Esempio n. 6
0
/**
 * Updates the expiration time of a subscription.
 * \todo Maybe we should use a hash here to index it as this is called for every notification
 * @param aor - aor to look for
 * @param expires - new expiration time
 * @returns 1 if found, 0 if not
 */
int update_r_subscription(r_subscription *s,int expires)
{
	LOG(L_DBG,"DBG:"M_NAME":update_r_subscription: refreshing subscription for <%.*s> [%d]\n",
		s->req_uri.len,s->req_uri.s,expires);
	s->attempts_left = -1;
	if (expires == 0) del_r_subscription_nolock(s);
	else s->expires = expires+time_now;;
	subs_unlock(s->hash);	
	return 1;
}
Esempio n. 7
0
/**
 * Deletes a subscription from the list of subscriptions 
 * @param s - the subscription to be deleted
 */
void del_r_subscription(r_subscription *s)
{
	if (!s) return;
	subs_lock(s->hash);
		if (subscriptions[s->hash].head == s) subscriptions[s->hash].head = s->next;
		else s->prev->next = s->next;
		if (subscriptions[s->hash].tail == s) subscriptions[s->hash].tail = s->prev;
		else s->next->prev = s->prev;
	subs_unlock(s->hash);
	free_r_subscription(s);
}
Esempio n. 8
0
/**
 * Adds a subscription to the list of subscriptions at the end (FIFO).
 * @param s - the subscription to be added
 */
void add_r_subscription(r_subscription *s)
{
	if (!s) return;
	s->hash = get_subscription_hash(s->req_uri);
	subs_lock(s->hash);
		s->next = 0;
		s->prev = subscriptions[s->hash].tail;
		if (subscriptions[s->hash].tail) subscriptions[s->hash].tail->next = s;			
		subscriptions[s->hash].tail = s;
		if (!subscriptions[s->hash].head) subscriptions[s->hash].head = s;		
	subs_unlock(s->hash);
}
Esempio n. 9
0
void print_subs(int log_level)
{
	r_subscription *s;
	int i;
	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Subscription list begin ---------\n");
	for(i=0;i<subscriptions_hash_size;i++){
		subs_lock(i);
		s = subscriptions[i].head;
		r_act_time();
		while(s){
			LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4u]\tP: <"ANSI_BLUE"%.*s"ANSI_GREEN"> D:["ANSI_CYAN"%5d"ANSI_GREEN"] E:["ANSI_MAGENTA"%5d"ANSI_GREEN"] Att:[%2d]\n",
				s->hash,s->req_uri.len,s->req_uri.s,s->duration,(int)(s->expires-time_now),s->attempts_left);
			s = s->next;			
		}
		subs_unlock(i);
	}
	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Subscription list end -----------\n");	
}
Esempio n. 10
0
/**
 * Creates a subcription and starts the timer resubscription for the given contact.
 * @param uri - the contact to subscribe to (actually to its default public id)
 * @param duration - SUBCRIBE expires
 * @returns 1 on success, 0 on failure
 */
int r_subscribe(str uri,int duration)
{
	r_subscription *s;
	/* first we try to update. if not found, add it */
	s = get_r_subscription(uri);	
	if (s){
		s->duration = duration;
		s->attempts_left=pcscf_subscribe_retries;
		subs_unlock(s->hash);
	}else{			
		s = new_r_subscription(uri,duration);
		if (!s){
			LOG(L_ERR,"ERR:"M_NAME":r_subscribe: Error creating new subscription\n");
			return 0;
		}
		add_r_subscription(s);
		s->attempts_left=pcscf_subscribe_retries;
	}
		
	return 1;
}
Esempio n. 11
0
/**
 * Loads the subscriptions data from the last snapshot.
 * @returns 1 on success or 0 on failure
 */
int load_snapshot_subscriptions()
{
	bin_data x;
	r_subscription *s;
	int k,max;
	FILE *f;

	switch (pcscf_persistency_mode){
		case NO_PERSISTENCY:
			k=0;

		case WITH_FILES:
			f = bin_load_from_file_open(pcscf_persistency_location,"psubscriptions");		
			if (!f) return 0;
			bin_alloc(&x,128*1024);
			k=bin_load_from_file_read(f,&x);
			max = x.max;
			x.max=0;
			LOG(L_INFO,"INFO:"M_NAME":load_snapshot_subscriptions: max %d len %d\n",x.max,x.len);
			while(x.max<x.len){
				s = bin_decode_r_subscription(&x);
				if (!s) return 0;
				LOG(L_INFO,"INFO:"M_NAME":load_snapshot_subscriptions: Loaded r_subscription for <%.*s>\n",s->req_uri.len,s->req_uri.s);
				subs_lock(s->hash);
				s->prev = subscriptions[s->hash].tail;
				s->next = 0;
				if (subscriptions[s->hash].tail) subscriptions[s->hash].tail->next = s;
				subscriptions[s->hash].tail = s;
				if (!subscriptions[s->hash].head) subscriptions[s->hash].head = s;
				subs_unlock(s->hash);
				
				memmove(x.s,x.s+x.max,x.len-x.max);
				x.len = x.max;
				x.max = max;
				k=bin_load_from_file_read(f,&x);
				max = x.max;
				x.max = 0;				
			}
			bin_free(&x);
			bin_load_from_file_close(f);
			k = 1;
			break;
			
		case WITH_DATABASE_BULK:
			k=bin_load_from_db(&x, P_SUBSCRIPTIONS);
			x.max=0;
			LOG(L_INFO,"INFO:"M_NAME":load_snapshot_subscriptions: max %d len %d\n",x.max,x.len);
			while(x.max<x.len){
				s = bin_decode_r_subscription(&x);
				if (!s) return 0;
				LOG(L_INFO,"INFO:"M_NAME":load_snapshot_subscriptions: Loaded r_subscription for <%.*s>\n",s->req_uri.len,s->req_uri.s);
				subs_lock(s->hash);
				s->prev = subscriptions[s->hash].tail;
				s->next = 0;
				if (subscriptions[s->hash].tail) subscriptions[s->hash].tail->next = s;
				subscriptions[s->hash].tail = s;
				if (!subscriptions[s->hash].head) subscriptions[s->hash].head = s;
				subs_unlock(s->hash);
			}
			bin_free(&x);
			break;
			
		case WITH_DATABASE_CACHE:
			k=bin_load_from_db(NULL, P_SUBSCRIPTIONS); //ignore x, x is empty
			break;
			
		default:
			LOG(L_ERR,"ERR:"M_NAME":load_snapshot_subscriptions: Can't resume because no such mode %d\n",pcscf_persistency_mode);
			k=0;
	}	
	if (!k) goto error;
	
	
	return 1;
error:
	return 0;

}
Esempio n. 12
0
/**
 * Creates a snapshots of the subscriptions and then calls the dumping function.
 * @returns 1 on success or 0 on failure
 */
int make_snapshot_subscriptions()
{
	bin_data x={0,0,0};
	r_subscription *s;
	int i,k;	
	time_t unique = time(0);
	FILE *f;
	
	
	switch (pcscf_persistency_mode) {
		case NO_PERSISTENCY:
			return 0;
			
		case WITH_FILES:
			f = bin_dump_to_file_create(pcscf_persistency_location,"psubscriptions",unique);
			if (!f) return 0;

			for(i=0;i<subscriptions_hash_size;i++){
				if (!bin_alloc(&x,1024)) goto error;		
				subs_lock(i);
				s = subscriptions[i].head;
				if (s) {
					while(s){
						if (!bin_encode_r_subscription(&x,s)) goto error;
						s = s->next;
					}
					subs_unlock(i);
					k = bind_dump_to_file_append(f,&x);
					if (k!=x.len) {
						LOG(L_ERR,"ERR:"M_NAME":make_snapshot_registrar: error while dumping to file - only wrote %d bytes of %d \n",k,x.len);
						subs_unlock(i);
						bin_free(&x);
						return 0;
					} 
				}
				else subs_unlock(i);
				bin_free(&x);
			}
	
			return bind_dump_to_file_close(f,pcscf_persistency_location,"psubscriptions",unique);

			break;
			
		case WITH_DATABASE_BULK:
			if (!bin_alloc(&x,1024)) goto error;		
			for(i=0;i<subscriptions_hash_size;i++){
				subs_lock(i);
				s = subscriptions[i].head;
				while(s){
					if (!bin_encode_r_subscription(&x,s)) goto error;
					s = s->next;
				}
				subs_unlock(i);
			}
			return bin_dump_to_db(&x, P_SUBSCRIPTIONS);

		case WITH_DATABASE_CACHE:
			return bin_dump_to_db(NULL, P_SUBSCRIPTIONS); //ignore x, x is empty
		default:
			LOG(L_ERR,"ERR:"M_NAME":make_snapshot_registrar: Snapshot done but no such mode %d\n",pcscf_persistency_mode);
			return 0;
		
	}

error:
	if (x.s) bin_free(&x);	
	return 0;
}