/** * 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; } }
/*Send cancel and 503 or 488 */ int release_call_early(p_dialog *d,int reason_code,str reason_text) { /*CANCEL will be badly routed because the response hasn't being processed * it will be sent to I-CSCF who will relay to S-CSCF and from there to term@P-CSCF*/ return release_call_previous(d,RELEASE_CALL_EARLY,reason_code,reason_text); }
/*send ACK,BYE and 503 or 488*/ int release_call_early200(p_dialog *d,int reason_code,str reason_text) { return release_call_previous(d,RELEASE_CALL_WEIRD,reason_code,reason_text); }
/** * 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; } }