Example #1
0
/**
 * Drop all dialogs belonging to one AOR.
 *  on deregistration for example.
 * @param aor - the public identity of the user
 * @returns the number of dialogs dropped 
 */
int S_drop_all_dialogs(str aor)
{
	s_dialog *d,*dn;
	int i,cnt=0;;
	
	LOG(L_DBG,"DBG:"M_NAME":S_drop_all_dialogs: Called for <%.*s>\n",aor.len,aor.s);

	for(i=0;i<s_dialogs_hash_size;i++){
		d_lock(i);
			d = s_dialogs[i].head;
			while(d){
				dn = d->next;
				if (d->direction == DLG_MOBILE_ORIGINATING &&
					d->aor.len == aor.len &&
					strncasecmp(d->aor.s,aor.s,aor.len)==0) {
					if (!terminate_s_dialog(d)) del_s_dialog(d);
					cnt++;
				}						
				d = dn;
			}
		d_unlock(i);
	}
	//print_s_dialogs(L_INFO);	
	return cnt;
}
Example #2
0
/**
 * Given an s_dialog, releases the call.
 * This function is already called with a lock in d
 * after returning d should be unlocked.
 * @param d - pointer to the s_dialog structure
 * @param reason - Reason header to include
 * @returns -1 if dialog the dialog is not confirmed, 0 on error or 1 on success
 */
int release_call_s(s_dialog *d,str reason)
{
	enum s_dialog_direction odir;
	s_dialog *o;

	LOG(L_INFO,"DBG:"M_NAME":release_call_s(): Releasing call <%.*s> DIR[%d].\n",
		d->call_id.len,d->call_id.s,d->direction);
					
	/* As for now, i'm only releasing confirmed dialogs */
	if (d->state < DLG_STATE_CONFIRMED){
		LOG(L_INFO,"ERR:"M_NAME":release_call_s(): Unable to release a non-confirmed dialog\n");		
		return -1;
	}
		
	/* get the dialog in the other direction to see if something going on there and mark as in releasing */
	switch (d->direction){
		case DLG_MOBILE_ORIGINATING:
			odir = DLG_MOBILE_TERMINATING;
			break;
		case DLG_MOBILE_TERMINATING:
			odir = DLG_MOBILE_ORIGINATING;
			break;
		default:
			odir = d->direction;
	}	
	
	o = get_s_dialog_dir_nolock(d->call_id,odir);
	if (o && !o->is_releasing) o->is_releasing = 1;
		
	d->is_releasing++;
		
	if (d->is_releasing>MAX_TIMES_TO_TRY_TO_RELEASE){
		LOG(L_ERR,"ERR:"M_NAME":release_call_s(): had to delete silently dialog %.*s in direction %i\n",d->call_id.len,d->call_id.s,d->direction);
		del_s_dialog(d);
		return 0;
	}
	if (d->is_releasing==1) {	
		/*Before generating a request, we have to generate
		 * the route_set in the dlg , because the route set
		 * in the dialog is for the UAC everything which was in the 
		 * Record-Routes (including local address)*/
		alter_dialog_route_set(d->dialog_c,d->direction);		
		
		/*first generate the bye for called user*/
		/*then generate the bye for the calling user*/
		send_bye(d->dialog_c,bye_response,d->direction,reason);
		send_bye(d->dialog_s,bye_response,d->direction,reason);
		
		/*the dialog is droped by the callback-function when recieves the two replies */
	}	 
	return 1;
}
Example #3
0
/** 
 * Terminates a dialog - called before del_s_dialog to send out terminatination messages.
 * @param d - the dialog to terminate
 * @returns - 1 if the requests were sent and the dialog will be deleted, 0 on error (you will have to delete the
 * dialog yourself!) 
 */
int terminate_s_dialog(s_dialog *d)
{
	if (!scscf_dialogs_enable_release) return 0;	
	switch (d->method){
		case DLG_METHOD_INVITE:
			if (release_call_s(d,Reason)<=0){
				//dialog has expired and not confirmed
				// or error releasing dialog
				del_s_dialog(d);
			}
			return 1;
			break;
		case DLG_METHOD_SUBSCRIBE:
			if (!release_subscription(d)){
				//error releasing the subscription - just drop silently
				del_s_dialog(d);
			}
			return 1;
			break;
		default:
			LOG(L_ERR,"ERR:"M_NAME":terminate_s_dialog(): Not implemented yet for method[%d]!\n",d->method);
			return 0;
	}
}
Example #4
0
/**
 * Drops and deletes a dialog.
 * @param msg - the request/response
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int S_drop_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	s_dialog *d;
	int hash;
//	struct sip_msg *req;
	enum s_dialog_direction dir = get_dialog_direction(str1);
	
	
//	if (!find_dialog_aor(msg,str1,&aor)){
//		LOG(L_ERR,"ERR:"M_NAME":S_is_in_dialog(): Error retrieving %s contact\n",str1);
//		return CSCF_RETURN_BREAK;
//	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_DBG,"DBG:"M_NAME":S_drop_dialog(%s): Call-ID <%.*s> DIR[%d]\n",
		str1,call_id.len,call_id.s,
		dir);

	d = get_s_dialog_dir(call_id,dir);
//	if (!d && msg->first_line.type==SIP_REPLY){
//		/* Try to get the dialog from the request */
//		req = cscf_get_request_from_reply(msg);		
//		if (!find_dialog_aor(req,str1,&aor)){
//			LOG(L_ERR,"ERR:"M_NAME":S_update_dialog(%s): Error retrieving %s contact\n",str1,str1);
//			return CSCF_RETURN_BREAK;
//		}		
//		d = get_s_dialog(call_id,aor);		
//	}
	if (!d){
		LOG(L_ERR,"ERR:"M_NAME":S_drop_dialog: dialog does not exists!\n");	
		return CSCF_RETURN_FALSE;
	}

	hash = d->hash;
	
	del_s_dialog(d);
		
	d_unlock(hash);
	
	print_s_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
}
Example #5
0
/** 
 * Terminates a dialog - called before del_s_dialog to send out terminatination messages.
 * @param d - the dialog to terminate
 * @returns - 1 if the requests were sent and the dialog will be deleted, 0 on error (you will have to delete the
 * dialog yourself!) 
 */
int terminate_s_dialog(s_dialog *d)
{
	switch (d->method){
		case DLG_METHOD_INVITE:
			if (release_call_s(d)==-1){
				//dialog has expired and not confirmed
				del_s_dialog(d);
			}
			return 1;
			break;
		case DLG_METHOD_SUBSCRIBE:
			LOG(L_ERR,"ERR:"M_NAME":terminate_s_dialog(): Not implemented yet for SUBSCRIBE dialogs!\n");
			return 0;
			break;
		default:
			LOG(L_ERR,"ERR:"M_NAME":terminate_s_dialog(): Not implemented yet for method[%d]!\n",d->method);
			return 0;
	}
}
Example #6
0
/**
 * Callback function for BYE requests!
 * Identify the s_dialog, then see if one BYE has already been recieved
 * if yes drop it , if no, wait for the second
 */
void bye_response(struct cell *t,int type,struct tmcb_params *ps)
{		
	s_dialog *d;
	unsigned int hash;
	str call_id;
	
	enum s_dialog_direction dir;
	
	
	if (!ps->param) return;
	dir = *((enum s_dialog_direction *) *(ps->param));
	shm_free(*ps->param);
	*ps->param = 0;		
		
	call_id = t->callid;
  	call_id.s+=9;
  	call_id.len-=11;

	LOG(L_INFO,"DBG:"M_NAME":bye_response(): Received a %d response to BYE for a call release for <%.*s> DIR[%d].\n",
		ps->code, call_id.len,call_id.s,dir);
			
	d = get_s_dialog_dir(call_id,dir);
	if (!d)	{
		LOG(L_ERR,"ERR:"M_NAME":bye_response(): Received a BYE response for a call release but there is no dialog for <%.*s> DIR[%d].\n",
			call_id.len,call_id.s,dir);
		return;
	}
	
	if (ps->code>=200){
		if (d->state==DLG_STATE_TERMINATED_ONE_SIDE){
			hash=d->hash;
			LOG(L_INFO,"INFO:"M_NAME":bye_response(): Received a response to second BYE. Dialog is dropped.\n");
			del_s_dialog(d);
			d_unlock(hash);			 
		} else {
			hash=d->hash;
			d->state=DLG_STATE_TERMINATED_ONE_SIDE;
			d_unlock(hash);
		}		
	} 	
}
Example #7
0
/**
 * The dialog timer looks for expires dialogs and removes them
 * @param ticks - the current time
 * @param param - pointer to the dialogs list
 */
void dialog_timer(unsigned int ticks, void* param)
{
	s_dialog *d,*dn;
	int i;
	#ifdef WITH_IMS_PM
		int dialog_cnt[DLG_METHOD_MAX+1];
		for(i=0;i<=DLG_METHOD_MAX;i++)
			dialog_cnt[i]=0;
	#endif
		
	LOG(L_DBG,"DBG:"M_NAME":dialog_timer: Called at %d\n",ticks);
	if (!s_dialogs) s_dialogs = (s_dialog_hash_slot*)param;

	d_act_time();
	
	for(i=0;i<s_dialogs_hash_size;i++){
		d_lock(i);
			d = s_dialogs[i].head;
			while(d){
				dn = d->next;
				if (d->expires<=d_time_now) {
					if (!terminate_s_dialog(d)) del_s_dialog(d);
				}
				#ifdef WITH_IMS_PM
					else dialog_cnt[d->method]++;
				#endif						
				d = dn;
			}
		d_unlock(i);
	}
	print_s_dialogs(L_INFO);
	#ifdef WITH_IMS_PM
		for(i=0;i<=DLG_METHOD_MAX;i++)
			IMS_PM_LOG11(RD_NbrDialogs,get_dialog_method_str(i),dialog_cnt[i]);		
	#endif						
}
Example #8
0
/**
 * The dialog timer looks for expires dialogs and removes them
 * @param ticks - the current time
 * @param param - pointer to the dialogs list
 */
void dialog_timer(unsigned int ticks, void* param)
{
	s_dialog *d,*dn;
	int i;
	
	LOG(L_DBG,"DBG:"M_NAME":dialog_timer: Called at %d\n",ticks);
	if (!s_dialogs) s_dialogs = (s_dialog_hash_slot*)param;

	d_act_time();
	
	for(i=0;i<s_dialogs_hash_size;i++){
		d_lock(i);
			d = s_dialogs[i].head;
			while(d){
				dn = d->next;
				if (d->expires<=d_time_now) {
					if (!terminate_s_dialog(d)) del_s_dialog(d);
				}						
				d = dn;
			}
		d_unlock(i);
	}
	print_s_dialogs(L_INFO);
}
Example #9
0
/**
 * Saves a dialog.
 * @param msg - the initial request
 * @param str1 - direction - "orig" or "term"
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if ok, #CSCF_RETURN_FALSE if not or #CSCF_RETURN_BREAK on error 
 */
int S_save_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	s_dialog *d;
	str aor;
	char buf1[256],buf2[256];
	str uri,tag,ruri,x;	
	time_t t_time;
	str ses_exp = {0,0};
	str refresher = {0,0};
	str event = {0,0};
	struct hdr_field *h;
	unsigned int hash;
	
	enum s_dialog_direction dir = get_dialog_direction(str1);
	
	if (!find_dialog_aor(msg,dir,&aor)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog(): Error retrieving %s contact\n",str1);
		return CSCF_RETURN_BREAK;
	}		
		
	call_id = cscf_get_call_id(msg,0);
	if (!call_id.len)
		return CSCF_RETURN_FALSE;

	LOG(L_INFO,"DBG:"M_NAME":S_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	if (is_s_dialog(call_id,aor,dir)){
		LOG(L_ERR,"ERR:"M_NAME":S_save_dialog: dialog already exists!\n");	
		return CSCF_RETURN_TRUE;
	}
	
	d = add_s_dialog(call_id,aor,dir);
	if (!d) return CSCF_RETURN_FALSE;

	d->method = get_dialog_method(msg->first_line.u.request.method);
	STR_SHM_DUP(d->method_str,msg->first_line.u.request.method,"shm");
	d->first_cseq = cscf_get_cseq(msg,0);
	d->last_cseq = d->first_cseq;
	d->state = DLG_STATE_INITIAL;

	d->uac_supp_timer = supports_extension(msg, &str_ext_timer);

	ses_exp = cscf_get_session_expires_body(msg, &h);
	t_time = cscf_get_session_expires(ses_exp, &refresher);
	if (!t_time) {
		d->expires = d_act_time() + 60;
		d->lr_session_expires = 0;
	} else {
		d->expires = d_act_time() + t_time;
		d->lr_session_expires = t_time;
		if (refresher.len)
			STR_SHM_DUP(d->refresher, refresher, "DIALOG_REFRESHER");
	}
	
	cscf_get_from_tag(msg,&tag);
	cscf_get_from_uri(msg,&x);
	uri.len = snprintf(buf1,256,"<%.*s>",x.len,x.s);
	uri.s = buf1;	
	cscf_get_to_uri(msg,&x);
	ruri.len = snprintf(buf2,256,"<%.*s>",x.len,x.s);
	ruri.s = buf2;
	 
	tmb.new_dlg_uac(&call_id,
						&tag,
						d->first_cseq,&uri,
						&ruri,
						&d->dialog_c);
	
	tmb.new_dlg_uas(msg,99,&d->dialog_s);
	
	event = cscf_get_event(msg);
	if (event.len){
		STR_SHM_DUP(d->event,event,"shm");
	}
	else
		d->event = event;

	d_unlock(d->hash);
	
	print_s_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
out_of_memory:
	if (d){
		hash = d->hash;
		del_s_dialog(d);
		d_unlock(hash);
	}
	return CSCF_RETURN_ERROR;	
}