Ejemplo n.º 1
0
/**
 * Drop all dialogs belonging to one contact.
 *  on deregistration for example.
 * @param host - host that originates/terminates this dialog
 * @param port - port that originates/terminates this dialog
 * @param transport - transport that originates/terminates this dialog
 * @returns the number of dialogs dropped 
 */
int P_drop_all_dialogs(str host,int port, int transport)
{
	p_dialog *d,*dn;
	int i,cnt=0;;
	
	LOG(L_DBG,"DBG:"M_NAME":P_drop_all_dialogs: Called for <%d://%.*s:%d>\n",transport,host.len,host.s,port);

	for(i=0;i<p_dialogs_hash_size;i++){
		d_lock(i);
			d = p_dialogs[i].head;
			while(d){
				dn = d->next;
				if (d->transport == transport &&
					d->port == port &&
					d->host.len == host.len &&
					strncasecmp(d->host.s,host.s,host.len)==0) {
					del_p_dialog(d);
					cnt++;
				}						
				d = dn;
			}
		d_unlock(i);
	}
//	print_p_dialogs(L_INFO);	
	return cnt;
}
Ejemplo n.º 2
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 P_drop_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	p_dialog *d;
	int hash;
	str host;
	int port,transport;
	struct sip_msg *req;
	enum p_dialog_direction dir;
	
	dir = get_dialog_direction(str1);
	
	if (msg->first_line.type==SIP_REPLY) req = cscf_get_request_from_reply(msg);
	else req = msg;
	if (!find_dialog_contact(req,dir,&host,&port,&transport)){
		LOG(L_ERR,"ERR:"M_NAME":P_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":P_drop_dialog(%s): Call-ID <%.*s> %d://%.*s:%d\n",
		str1,call_id.len,call_id.s,
		transport,host.len,host.s,port);

	d = get_p_dialog(call_id,host,port,transport,&dir);
	if (!d)
		d = get_p_dialog(call_id,host,port,transport,0);
	if (!d){
		LOG(L_INFO,"INFO:"M_NAME":P_drop_dialog: dialog does not exists!\n");	
		return CSCF_RETURN_FALSE;
	}

	hash = d->hash;
	
	del_p_dialog(d);
		
	d_unlock(hash);
	
	print_p_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;	
}
Ejemplo n.º 3
0
/** 
 * Terminates a dialog - called before del_p_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_p_dialog(p_dialog *d)
{
	if (!pcscf_dialogs_enable_release) return 0;
	switch (d->method){
		case DLG_METHOD_INVITE:
			if (release_call_p(d,503,reason_terminate_p_dialog_s)==-1){				
				del_p_dialog(d);
			}
			return 1;
			break;
		case DLG_METHOD_SUBSCRIBE:
			LOG(L_ERR,"ERR:"M_NAME":terminate_p_dialog(): Not needed for SUBSCRIBE dialogs - silent drop on expiration.\n");
			return 0;
			break;
		default:
			LOG(L_ERR,"ERR:"M_NAME":terminate_p_dialog(): Not implemented yet for method[%d]!\n",d->method);
			return 0;
	}
}
Ejemplo n.º 4
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 confirmed_response(struct cell *t,int type,struct tmcb_params *ps)
{		
	p_dialog *d;
	unsigned int hash;
	str call_id;
	
	enum p_dialog_direction dir;
	
	
	if (!ps->param) return;
	dir = *((enum p_dialog_direction *) *(ps->param));
	shm_free(*ps->param);
	*ps->param = 0;		
		
	//call_id = cscf_get_call_id(ps->rpl,0);
	call_id = t->callid;
  	call_id.s+=9;
  	call_id.len-=11;
	
	LOG(L_INFO,"DBG:"M_NAME":confirmed_response(): Received a BYE for a call release for <%.*s> DIR[%d].\n",
		call_id.len,call_id.s,dir);
	
	d = get_p_dialog_dir(call_id,dir);
	if (!d)	{
		LOG(L_ERR,"ERR:"M_NAME":confirmed_response(): Received a BYE 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;
			del_p_dialog(d);
			d_unlock(hash);			 
		} else {
			hash=d->hash;
			d->state=DLG_STATE_TERMINATED_ONE_SIDE;
			d_unlock(hash);
		}		
	} 
}
Ejemplo n.º 5
0
/**
 * The dialog timer looks for expired dialogs and removes them.
 * @param ticks - the current time
 * @param param - pointer to the dialogs list
 */
void dialog_timer(unsigned int ticks, void* param)
{
	p_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 (!p_dialogs) p_dialogs = (p_dialog_hash_slot*)param;

	d_act_time();
	
	for(i=0;i<p_dialogs_hash_size;i++){
		d_lock(i);
			d = p_dialogs[i].head;
			while(d){
				dn = d->next;
				if (d->expires<=d_time_now) {						
						if (!terminate_p_dialog(d)) 
							del_p_dialog(d);					
				}
				#ifdef WITH_IMS_PM
					else dialog_cnt[d->method]++;
				#endif										
				d = dn;
			}
		d_unlock(i);
	}
	print_p_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	
}
Ejemplo n.º 6
0
/**
 * This functions sends BYE for a confirmed dialog
 * @param d - the p_dialog to end
 * @param reason - the Reason: header to include in the messages
 * @returns 0 on error 1 on success
 */
int release_call_confirmed(p_dialog *d, int reason_code, str reason_text)
{
	enum p_dialog_direction odir;
	p_dialog *o;
	str r;
	str hdrs={0,0};	
	char buf[256];
	
	LOG(L_INFO,"DBG:"M_NAME":release_call_confirmed(): Releasing call <%.*s> DIR[%d].\n",
		d->call_id.len,d->call_id.s,d->direction);
	
	r.len = snprintf(buf,256,"%.*s%d%.*s%.*s%.*s",
		reason_hdr_s.len,reason_hdr_s.s,
		reason_code,
		reason_hdr_1.len,reason_hdr_1.s,
		reason_text.len,reason_text.s,
		reason_hdr_e.len,reason_hdr_e.s);
	r.s = buf;

	hdrs.len = r.len+content_length_s.len;	
	hdrs.s = pkg_malloc(hdrs.len);
	if (!hdrs.s){
		LOG(L_INFO,"DBG:"M_NAME":release_call_confirmed(): Error allocating %d bytes.\n",hdrs.len);
		hdrs.len=0;
		goto error;
	}
	hdrs.len=0;	
	STR_APPEND(hdrs,r);
	STR_APPEND(hdrs,content_length_s);	
		
	/* 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_p_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_confirmed(): had to delete silently dialog %.*s in direction %i\n",d->call_id.len,d->call_id.s,d->direction);
		del_p_dialog(d);
		goto error;
	}
	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_request(method_BYE_s,hdrs,d->dialog_c,confirmed_response,d->direction);
		send_request(method_BYE_s,hdrs,d->dialog_s,confirmed_response,d->direction);
		
		/*the dialog is droped by the callback-function when receives the two replies */
	}	 

	if (hdrs.s) pkg_free(hdrs.s);
	return 1;
error:
	if (hdrs.s) pkg_free(hdrs.s);
	return 0;	
}
Ejemplo n.º 7
0
/**
 * Function that releases a call in early or early200 situation
 * early200 is when the callee has already sent out 200 but that hasn't
 * arrived yet to the caller
 * @param d - p_dialog of the call
 * @situation - flag to distinguish between two situations
 * @return 0 on error 1 on success
 * 
 * \note This function shouldn't be called directly!
 * use release_call_early or release_call_early200 instead 
 * 
 * \note This function is full of tricks to fake states and
 * to decieve the transaction module so that it lets us
 * end a call in weird state
 * 
 * \note any move in the order of functions to clarify the structure
 * can lead to a crash in P-CSCF so watch out!
 */
int release_call_previous(p_dialog *d,enum release_call_situation situation,int reason_code,str reason_text)
{
	struct cell* t;
	p_dialog *o;
	enum p_dialog_direction odir;
	int i;
	str r;
	str hdrs={0,0};	
	char buf[256];
	
	LOG(L_INFO,"DBG:"M_NAME":release_call_previous(): Releasing call <%.*s> DIR[%d].\n",
		d->call_id.len,d->call_id.s,d->direction);
	
	r.len = snprintf(buf,256,"%.*s%d%.*s%.*s%.*s",
		reason_hdr_s.len,reason_hdr_s.s,
		reason_code,
		reason_hdr_1.len,reason_hdr_1.s,
		reason_text.len,reason_text.s,
		reason_hdr_e.len,reason_hdr_e.s);
	r.s = buf;

	hdrs.len = r.len+content_length_s.len;	
	hdrs.s = pkg_malloc(hdrs.len);
	if (!hdrs.s){
		LOG(L_INFO,"DBG:"M_NAME":release_call_previous(): Error allocating %d bytes.\n",hdrs.len);
		hdrs.len=0;
		goto error;
	}
	hdrs.len=0;
	STR_APPEND(hdrs,r);
	STR_APPEND(hdrs,content_length_s);	
													
	/* 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_p_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_previous(): had to delete silently dialog %.*s in direction %i\n",d->call_id.len,d->call_id.s,d->direction);
		del_p_dialog(d);
		goto error;
	}
	
	alter_dialog_route_set(d->dialog_c,d->direction);
	
	d->state=DLG_STATE_TERMINATED_ONE_SIDE;
	/*this is just a trick to use the same callback function*/	
	
	/*trick or treat!*/
	d->dialog_c->state=DLG_CONFIRMED;
	
	if (situation == RELEASE_CALL_WEIRD){
		send_request(method_ACK_s,hdrs,d->dialog_c,0,0);
		send_request(method_BYE_s,hdrs,d->dialog_c,confirmed_response,d->direction);
		//d->dialog_c->state=DLG_EARLY;
	} else {/*(situation == RELEASE_CALL_EARLY)*/		
		send_request(method_CANCEL_s,hdrs,d->dialog_c,confirmed_response,d->direction);
		//d->dialog_c->state=DLG_EARLY;
	}

	/*i need the cell of the invite!!*/
	/*this is very experimental
	 * and very tricky too*/
	t=tmb.t_gett();
	
	if (t && t->uas.request) {
		/*first trick: i really want to get this reply sent even though we are onreply*/
		*tmb.route_mode=MODE_ONFAILURE;
		
		/*second trick .. i haven't recieve any response from the uac
		 * if i don't do this i get a cancel sent to the S-CSCF .. its not a big deal*/
		 /*if i cared about sip forking then probably i would not do that and let the 
		  * CANCEL go to the S-CSCF (reread specifications needed)*/
		for (i=0; i< t->nr_of_outgoings; i++)
			t->uac[i].last_received=99;
		/*t->uas.status=100;*/ /*no one cares about this*/
		/*now its safe to do this*/
		
		tmb.t_reply(t->uas.request,reason_code,reason_text.s);
		*tmb.route_mode=MODE_ONREPLY;
		tmb.t_release(t->uas.request);

		/*needed because if not i get last message retransmited... 
		 * probably there is a more logical way to do this.. but since i really
		 * want this transaction to end .. whats the point?*/
	}
	
	return 1;
error:
	if (hdrs.s) pkg_free(hdrs.s);
	return 0;	
}
Ejemplo n.º 8
0
/**
 * Function that releases a call in early or early200 situation
 * early200 is when the callee has already sent out 200 but that hasn't
 * arrived yet to the caller
 * @param d - p_dialog of the call
 * @situation - flag to distinguish between two situations
 * @return 0 on error 1 on success
 *
 * \note This function shouldn't be called directly!
 * use release_call_early or release_call_early200 instead
 *
 * \note This function is full of tricks to fake states and
 * to decieve the transaction module so that it lets us
 * end a call in weird state
 *
 * \note any move in the order of functions to clarify the structure
 * can lead to a crash in P-CSCF so watch out!
 */
int release_call_previous(p_dialog *d,enum release_call_situation situation,int reason_code,str reason_text)
{
    struct cell* t;
    p_dialog *o;
    enum p_dialog_direction odir;
    int i;
    str r;
    str hdrs= {0,0};
    str firstcseq;
    char buf[256];

    if(!d)
        return 0;

    LOG(L_INFO,"DBG:"M_NAME":release_call_previous(): Releasing call <%.*s> DIR[%d].\n",
        d->call_id.len,d->call_id.s,d->direction);

    r.len = snprintf(buf,256,"%.*s%d%.*s%.*s%.*s",
                     reason_hdr_s.len,reason_hdr_s.s,
                     reason_code,
                     reason_hdr_1.len,reason_hdr_1.s,
                     reason_text.len,reason_text.s,
                     reason_hdr_e.len,reason_hdr_e.s);
    r.s = buf;

    hdrs.len = r.len+content_length_s.len;
    hdrs.s = pkg_malloc(hdrs.len);
    if (!hdrs.s) {
        LOG(L_INFO,"DBG:"M_NAME":release_call_previous(): Error allocating %d bytes.\n",hdrs.len);
        hdrs.len=0;
        goto error;
    }
    hdrs.len=0;
    STR_APPEND(hdrs,r);
    STR_APPEND(hdrs,content_length_s);

    /* 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;
    }

    time_t time_now=time(0);

    o = get_p_dialog_dir_nolock(d->call_id,odir);


    if (o && o->is_releasing==0)  {

        o->is_releasing = 1;
        // Addition from Alberto Diez the 2nd November 2007
        // the idea is to put the other one to expire in TIME_TO_EXPIRE
        // just in case no reply is received
        if (o->expires>time_now+TIME_TO_EXPIRE) {
            o->expires=time_now+TIME_TO_EXPIRE;
        }

    }
    d->is_releasing++;

    /*The first time i decrease the expire time for the dialog expire , so that i guarantee that
    	 * its going to be deleted from the table sometime*/


    if (d->expires>time_now+TIME_TO_EXPIRE)
    {
        d->expires=time_now+TIME_TO_EXPIRE;
    }

    if (d->is_releasing>MAX_TIMES_TO_TRY_TO_RELEASE) {
        LOG(L_ERR,"ERR:"M_NAME":release_call_previous(): had to delete silently dialog %.*s in direction %i\n",d->call_id.len,d->call_id.s,d->direction);
        del_p_dialog(d);
        goto error;
    }

    if(alter_dialog_route_set(d->dialog_c,d->direction,situation)<0) {
        LOG(L_ERR,"ERR:"M_NAME":release_call_previous(): had to delete silently dialog %.*s in direction %i\n",d->call_id.len,d->call_id.s,d->direction);
        del_p_dialog(d);
        goto error;
    }

    d->state=DLG_STATE_TERMINATED_ONE_SIDE;
    /*this is just a trick to use the same callback function*/




    /*i need the cell of the invite!!*/
    /*this is very experimental
     * and very tricky too*/
    //t=tmb.t_gett();
    i=0;
    i=snprintf(buf,256,"%i",d->first_cseq); // i just use buf because its there..

    if (i==256) {
        LOG(L_ERR,"release_call_previous: some client used first CSeq way too big\n");
        goto error;
    }

    firstcseq.s=pkg_malloc(i+1); // the \0
    firstcseq.len=i;
    sprintf(firstcseq.s,"%i",d->first_cseq);
    LOG(L_INFO,"CALLED t_lookup_callid with %.*s, %.*s\n",d->call_id.len,d->call_id.s,firstcseq.len,firstcseq.s);
    if (tmb.t_lookup_callid(&t,d->call_id,firstcseq) < 0) {
        pkg_free(firstcseq.s);
        LOG(L_ERR,"release_call_previous: t_lookup_callid failed\n");
        goto error;
    }

    pkg_free(firstcseq.s);

    if (t && t!=(void*) -1  && t->uas.request) {


        if (t->method.len!=6 || t->method.s[0]!='I' || t->method.s[1]!='N' || t->method.s[2]!='V')
        {
            //well this is the transaction of a subsequent request within the dialog
            //and the dialog is not confirmed yet, so its a PRACK or an UPDATE
            //could also be an options, but the important thing is how am i going to get
            //the transaction of the invite, that is the one i have to cancel
            LOG(L_ERR,"this is not my transaction so where am i?\n");
        }


        /*first trick: i really want to get this reply sent even though we are onreply*/

#ifdef SER_MOD_INTERFACE
        route_type = FAILURE_ROUTE;
#else
        *tmb.route_mode=MODE_ONFAILURE;
#endif


        if (situation == RELEASE_CALL_WEIRD) {
            /*second trick .. i haven't recieve any response from the uac
            * if i don't do this i get a cancel sent to the S-CSCF .. its not a big deal*/
            /*if i cared about sip forking then probably i would not do that and let the
            * CANCEL go to the S-CSCF (reread specifications needed)*/
            //for (i=0; i< t->nr_of_outgoings; i++)
            //	t->uac[i].last_received=99;
            /*t->uas.status=100;*/ /*no one cares about this*/
            /*now its safe to do this*/

            /*trick or treat!*/
            for (i=0; i< t->nr_of_outgoings; i++)
                t->uac[i].last_received=99;
            t->uas.status=100;
            d->dialog_c->state=DLG_CONFIRMED;
            send_request(method_ACK_s,hdrs,d->dialog_c,0,0);
            send_request(method_BYE_s,hdrs,d->dialog_c,confirmed_response,d->direction);
            d->dialog_c->state=DLG_EARLY;

            tmb.t_reply(t->uas.request,reason_code,reason_text.s);
            *tmb.route_mode=MODE_ONREPLY;
            t->uas.status=488;
            tmb.t_release(t->uas.request);
            /*needed because if not i get last message retransmited...
             * probably there is a more logical way to do this.. but since i really
             * want this transaction to end .. whats the point?*/
        } else {/*(situation == RELEASE_CALL_EARLY)*/
            d->dialog_c->loc_seq.value++;

            //d->dialog_c->state=DLG_CONFIRMED;
            //send_request(method_CANCEL_s,hdrs,d->dialog_c,confirmed_response,d->direction);
            //d->dialog_c->state=DLG_EARLY;

            tmb.t_reply(t->uas.request,reason_code,reason_text.s);

            /*
            for (i=0; i< t->nr_of_outgoings; i++)
            	t->uac[i].last_received=180;
            */

            // t_reply has decided to send a CANCEL already so no big deal!

            //tmb.cancel_uacs(t,0xFFFF,F_CANCEL_B_FAKE_REPLY);

            //t->uas.status=488;

            //tmb.t_release(t->uas.request);


            // I thought of deleting the dialog here.. but
            // a good SIP client will respond to the CANCEL with a 487
            //del_p_dialog(d);
        }
    }

    if (hdrs.s) pkg_free(hdrs.s);
    return 1;
error:
    if (hdrs.s) pkg_free(hdrs.s);
    return 0;
}
Ejemplo n.º 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 P_save_dialog(struct sip_msg* msg, char* str1, char* str2)
{
	str call_id;
	p_dialog *d;
	str host;
	time_t t_time;
	str ses_exp = {0,0};
	str refresher = {0,0};
	int port,transport;
	char buf1[256],buf2[256];
	str tag,ruri,uri,x;
	struct hdr_field *h;
	unsigned int hash;
	enum p_dialog_direction dir;
	
	dir = get_dialog_direction(str1);
	
	if (!find_dialog_contact(msg,dir,&host,&port,&transport)){
		LOG(L_ERR,"ERR:"M_NAME":P_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":P_save_dialog(%s): Call-ID <%.*s>\n",str1,call_id.len,call_id.s);

	if (is_p_dialog(call_id,host,port,transport,&dir)){
		LOG(L_ERR,"ERR:"M_NAME":P_save_dialog: dialog already exists!\n");	
		return CSCF_RETURN_TRUE;
	}
	
	d = add_p_dialog(call_id,host,port,transport);
	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");
	}
	
	d->direction=dir;
				
	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);
		
	d_unlock(d->hash);
	print_p_dialogs(L_INFO);
	
	return CSCF_RETURN_TRUE;
out_of_memory:
	if (d){
		hash = d->hash;
		del_p_dialog(d);
		d_unlock(hash);
	}
	return CSCF_RETURN_FALSE;
}