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");	
}
/**
 * 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	
}
示例#3
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);
}
示例#4
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);
}
示例#5
0
/**
 * Returns a subscription if it exists
 * \note - this returns with a lock on the subscriptions[s->hash] if found. Don't forget to unlock when done!!!
 * @param aor - AOR to look for
 * @returns 1 if found, 0 if not
 */
r_subscription* get_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)
			{
				return s;
			}
			s = s->next;
		}
	subs_unlock(hash);	
	return 0;
}
示例#6
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");	
}
示例#7
0
/**
 * Destroys the subscription list
 */
void r_subscription_destroy()
{
	int i;
	r_subscription *s,*ns;
	for(i=0;i<subscriptions_hash_size;i++){
		subs_lock(i);
		s = subscriptions[i].head;
		while(s){
			ns = s->next;
			//TODO send out unSUBSCRIBE
			free_r_subscription(s);
			s = ns;
		}
		lock_destroy(subscriptions[i].lock);
		lock_dealloc(subscriptions[i].lock);
	}	
	shm_free(subscriptions);
}
示例#8
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;

}
示例#9
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;
}