Example #1
0
/**
 * Given a call-id, locate if its terminating,orginating or both
 * release the dialog involved and drop the dialog
 * @param callid - the Call-ID to release
 * @param reason - the Reason header to include in messages
 * @returns 0 on error, 1 on success  
 */ 
int release_call(str callid,int reason_code,str reason_text)
{
	p_dialog *d=0;
	unsigned int hash;
	int res = 0;
	
	d = get_p_dialog_dir(callid,DLG_MOBILE_ORIGINATING);
	if (d) {				
		hash = d->hash;
		if (release_call_p(d,reason_code,reason_text)>0) res = 1;		
		goto done;		
	}
	d = get_p_dialog_dir(callid,DLG_MOBILE_TERMINATING);
	if (d) {				
		hash = d->hash;
		if (release_call_p(d,reason_code,reason_text)>0) res = 1;		
		goto done;
	} 
	
	/*Neither ORGINATING nor TERMINATING is UNKNOWN!*/
	/*or doesn't exist*/
	/*drop it silently?*/
	/*treat it as ORIGINATING or TERMINATING?*/				
done:		
	if (d) d_unlock(hash);
	return 0;	
}
Example #2
0
/**
 * Releases a call from the on reply route block
 * called with any reply to an INVITE
 * useful in cases of rejecting a call when you are processing the SDP
 * or handling QoS things
 * @msg  - the sip message being processed
 * @str1 - the first parameter  "orig" or "term"
 * @str2 - [optional] the Reason header that you want to go to the messages 
 * @returns - TRUE on success or FALSE on misscall and BREAK on error
 */
int P_release_call_onreply(struct sip_msg *msg,char *str1,char *str2)
{
	enum p_dialog_direction dir;
	p_dialog *d=NULL;
	str callid;
	struct hdr_field *h1;
	str reason={NULL,0};
	
	if (str2) {
		reason.s=str2;
		reason.len=strlen(str2);
	} else
		reason = _488_text_s;
		
	
	dir= (str1[0]=='o' || str1[0]=='O' || str1[0]=='0')? DLG_MOBILE_ORIGINATING : DLG_MOBILE_TERMINATING;
	
	if (msg->first_line.type== SIP_REQUEST)
	{
		LOG(L_ERR,"ERR: P_release_call_on_reply called with a request\n");
		return CSCF_RETURN_FALSE;
	}
	
	callid=cscf_get_call_id(msg,&h1);
	if (is_p_dialog_dir(callid,dir)) {
		d=get_p_dialog_dir(callid,dir);
		if (msg->first_line.u.reply.statuscode > 199)
		{
			release_call_previous(d,RELEASE_CALL_WEIRD,488,reason);
			d_unlock(d->hash);
			return CSCF_RETURN_TRUE;
		} else {
			release_call_previous(d,RELEASE_CALL_EARLY,488,reason);
			d_unlock(d->hash);
			return CSCF_RETURN_TRUE;
		}
	} else {
		LOG(L_ERR,"ERR:"M_NAME "P_release_call_onreply :  unable to find dialog\n");
		return CSCF_RETURN_BREAK;
	}
	
}
Example #3
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);
		}		
	} 
}
Example #4
0
/**
 * Releases a call from the on reply route block
 * called with any reply to an INVITE
 * useful in cases of rejecting a call when you are processing the SDP
 * or handling QoS things
 * @msg  - the sip message being processed
 * @str1 - the first parameter  "orig" or "term"
 * @str2 - [optional] the Reason header that you want to go to the messages
 * @returns - BREAK ... whatever happens this message is not relayed
 */
int P_release_call_onreply(struct sip_msg *msg,char *str1,char *str2)
{
    enum p_dialog_direction dir;
    p_dialog *d=NULL;
    str callid;
    struct hdr_field *h1;
    str reason= {NULL,0};
    unsigned int hash;

    struct cell* t; /*needed to distinguish between UPDATE and INVITE*/

    LOG(L_INFO,ANSI_WHITE"P_release_call_on_reply\n");

    if (str2) {
        reason.s=str2;
        reason.len=strlen(str2);
    } else
        reason = _488_text_s;


    dir= (str1[0]=='o' || str1[0]=='O' || str1[0]=='0')? DLG_MOBILE_ORIGINATING : DLG_MOBILE_TERMINATING;

    if (msg->first_line.type== SIP_REQUEST)
    {
        LOG(L_ERR,"ERR: P_release_call_on_reply called with a request\n");
        return CSCF_RETURN_FALSE;
    }

    callid=cscf_get_call_id(msg,&h1);
    if (is_p_dialog_dir(callid,dir)) {
        d=get_p_dialog_dir(callid,dir);
        hash=d->hash;

        t=tmb.t_gett();
        if (!t) {
            LOG(L_ERR,"P_release_call_onreply(): unable to get transaction\n");
            return CSCF_RETURN_BREAK;
        }
        if (t->method.len==6 && memcmp(t->method.s,"INVITE",6)==0)
        {
            // If its an INVTE, the state depends on which reply we are processing

            if (msg->first_line.u.reply.statuscode > 199)
            {
                release_call_previous(d,RELEASE_CALL_WEIRD,488,reason);
            } else {
                release_call_previous(d,RELEASE_CALL_EARLY,488,reason);
            }
            // This means we already finished with the dialog
            if (d->pcc_session_id.s) shm_free(d->pcc_session_id.s);
            d->pcc_session_id.s=0;
            d->pcc_session_id.len=0;
            d_unlock(hash);
            return CSCF_RETURN_BREAK;
        } else {

            //UPDATE so early
            release_call_early(d,488,reason);
            d_unlock(hash);
            return CSCF_RETURN_BREAK;

        }

    } else {
        LOG(L_ERR,"ERR:"M_NAME "P_release_call_onreply :  unable to find dialog\n");
        return CSCF_RETURN_ERROR;
    }

}