res_pjsip_rfc3326: Add SIP causes support for RFC3326
Add ability to set HANGUPCAUSE when SIP causecode received in BYE (in addition to currently supported Q.850). ASTERISK-30319 #close Change-Id: I3f55622dc680ce713a2ffb5a458ef5dd39fcf645
This commit is contained in:
parent
7dc8773178
commit
410150235a
|
@ -2881,97 +2881,6 @@ static int chan_pjsip_sendtext(struct ast_channel *ast, const char *text)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*! \brief Convert SIP hangup causes to Asterisk hangup causes */
|
||||
static int hangup_sip2cause(int cause)
|
||||
{
|
||||
/* Possible values taken from causes.h */
|
||||
|
||||
switch(cause) {
|
||||
case 401: /* Unauthorized */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 403: /* Not found */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 404: /* Not found */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 405: /* Method not allowed */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 407: /* Proxy authentication required */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 408: /* No reaction */
|
||||
return AST_CAUSE_NO_USER_RESPONSE;
|
||||
case 409: /* Conflict */
|
||||
return AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
|
||||
case 410: /* Gone */
|
||||
return AST_CAUSE_NUMBER_CHANGED;
|
||||
case 411: /* Length required */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 413: /* Request entity too large */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 414: /* Request URI too large */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 415: /* Unsupported media type */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 420: /* Bad extension */
|
||||
return AST_CAUSE_NO_ROUTE_DESTINATION;
|
||||
case 480: /* No answer */
|
||||
return AST_CAUSE_NO_ANSWER;
|
||||
case 481: /* No answer */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 482: /* Loop detected */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 483: /* Too many hops */
|
||||
return AST_CAUSE_NO_ANSWER;
|
||||
case 484: /* Address incomplete */
|
||||
return AST_CAUSE_INVALID_NUMBER_FORMAT;
|
||||
case 485: /* Ambiguous */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 486: /* Busy everywhere */
|
||||
return AST_CAUSE_BUSY;
|
||||
case 487: /* Request terminated */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 488: /* No codecs approved */
|
||||
return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
|
||||
case 491: /* Request pending */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 493: /* Undecipherable */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 500: /* Server internal failure */
|
||||
return AST_CAUSE_FAILURE;
|
||||
case 501: /* Call rejected */
|
||||
return AST_CAUSE_FACILITY_REJECTED;
|
||||
case 502:
|
||||
return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
case 503: /* Service unavailable */
|
||||
return AST_CAUSE_CONGESTION;
|
||||
case 504: /* Gateway timeout */
|
||||
return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
|
||||
case 505: /* SIP version not supported */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 600: /* Busy everywhere */
|
||||
return AST_CAUSE_USER_BUSY;
|
||||
case 603: /* Decline */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 604: /* Does not exist anywhere */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 606: /* Not acceptable */
|
||||
return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
|
||||
default:
|
||||
if (cause < 500 && cause >= 400) {
|
||||
/* 4xx class error that is unknown - someting wrong with our request */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
} else if (cause < 600 && cause >= 500) {
|
||||
/* 5xx class error - problem in the remote end */
|
||||
return AST_CAUSE_CONGESTION;
|
||||
} else if (cause < 700 && cause >= 600) {
|
||||
/* 6xx - global errors in the 4xx class */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
}
|
||||
return AST_CAUSE_NORMAL;
|
||||
}
|
||||
/* Never reached */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void chan_pjsip_session_begin(struct ast_sip_session *session)
|
||||
{
|
||||
RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
|
||||
|
@ -3016,7 +2925,7 @@ static void chan_pjsip_session_end(struct ast_sip_session *session)
|
|||
|
||||
ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
|
||||
if (!ast_channel_hangupcause(session->channel) && session->inv_session) {
|
||||
int cause = hangup_sip2cause(session->inv_session->cause);
|
||||
int cause = ast_sip_hangup_sip2cause(session->inv_session->cause);
|
||||
|
||||
ast_queue_hangup_with_cause(session->channel, cause);
|
||||
} else {
|
||||
|
@ -3210,7 +3119,7 @@ static void chan_pjsip_incoming_response_update_cause(struct ast_sip_session *se
|
|||
snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code,
|
||||
(int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
|
||||
|
||||
cause_code->ast_cause = hangup_sip2cause(status.code);
|
||||
cause_code->ast_cause = ast_sip_hangup_sip2cause(status.code);
|
||||
ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
|
||||
ast_channel_hangupcause_hash_set(session->channel, cause_code, data_size);
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Subject: res_pjsip_rfc3326
|
||||
|
||||
Add ability to set HANGUPCAUSE when SIP causecode received in BYE Reason header (in
|
||||
addition to currently supported Q.850). The first header found will be used to set
|
||||
the HANGUPCAUSE variable.
|
|
@ -3962,7 +3962,7 @@ int ast_sip_is_uri_sip_sips(pjsip_uri *uri);
|
|||
*
|
||||
* \param uri The pjsip_uri to check
|
||||
*
|
||||
* \retva; 1 if allowed
|
||||
* \retval 1 if allowed
|
||||
* \retval 0 if not allowed
|
||||
*/
|
||||
int ast_sip_is_allowed_uri(pjsip_uri *uri);
|
||||
|
@ -4013,4 +4013,15 @@ struct pjsip_param *ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_s
|
|||
*/
|
||||
unsigned int ast_sip_get_all_codecs_on_empty_reinvite(void);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Convert SIP hangup causes to Asterisk hangup causes
|
||||
*
|
||||
* \param cause SIP cause
|
||||
*
|
||||
* \retval matched cause code from causes.h
|
||||
*/
|
||||
const int ast_sip_hangup_sip2cause(int cause);
|
||||
|
||||
|
||||
#endif /* _RES_PJSIP_H */
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "asterisk/uuid.h"
|
||||
#include "asterisk/sorcery.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/causes.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/res_pjsip_cli.h"
|
||||
|
@ -2796,6 +2797,97 @@ struct pjsip_param *ast_sip_pjsip_uri_get_other_param(pjsip_uri *uri, const pj_s
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*! \brief Convert SIP hangup causes to Asterisk hangup causes */
|
||||
const int ast_sip_hangup_sip2cause(int cause)
|
||||
{
|
||||
/* Possible values taken from causes.h */
|
||||
|
||||
switch(cause) {
|
||||
case 401: /* Unauthorized */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 403: /* Not found */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 404: /* Not found */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 405: /* Method not allowed */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 407: /* Proxy authentication required */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 408: /* No reaction */
|
||||
return AST_CAUSE_NO_USER_RESPONSE;
|
||||
case 409: /* Conflict */
|
||||
return AST_CAUSE_NORMAL_TEMPORARY_FAILURE;
|
||||
case 410: /* Gone */
|
||||
return AST_CAUSE_NUMBER_CHANGED;
|
||||
case 411: /* Length required */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 413: /* Request entity too large */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 414: /* Request URI too large */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 415: /* Unsupported media type */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 420: /* Bad extension */
|
||||
return AST_CAUSE_NO_ROUTE_DESTINATION;
|
||||
case 480: /* No answer */
|
||||
return AST_CAUSE_NO_ANSWER;
|
||||
case 481: /* No answer */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 482: /* Loop detected */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 483: /* Too many hops */
|
||||
return AST_CAUSE_NO_ANSWER;
|
||||
case 484: /* Address incomplete */
|
||||
return AST_CAUSE_INVALID_NUMBER_FORMAT;
|
||||
case 485: /* Ambiguous */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 486: /* Busy everywhere */
|
||||
return AST_CAUSE_BUSY;
|
||||
case 487: /* Request terminated */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 488: /* No codecs approved */
|
||||
return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
|
||||
case 491: /* Request pending */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 493: /* Undecipherable */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 500: /* Server internal failure */
|
||||
return AST_CAUSE_FAILURE;
|
||||
case 501: /* Call rejected */
|
||||
return AST_CAUSE_FACILITY_REJECTED;
|
||||
case 502:
|
||||
return AST_CAUSE_DESTINATION_OUT_OF_ORDER;
|
||||
case 503: /* Service unavailable */
|
||||
return AST_CAUSE_CONGESTION;
|
||||
case 504: /* Gateway timeout */
|
||||
return AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
|
||||
case 505: /* SIP version not supported */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
case 600: /* Busy everywhere */
|
||||
return AST_CAUSE_USER_BUSY;
|
||||
case 603: /* Decline */
|
||||
return AST_CAUSE_CALL_REJECTED;
|
||||
case 604: /* Does not exist anywhere */
|
||||
return AST_CAUSE_UNALLOCATED;
|
||||
case 606: /* Not acceptable */
|
||||
return AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
|
||||
default:
|
||||
if (cause < 500 && cause >= 400) {
|
||||
/* 4xx class error that is unknown - someting wrong with our request */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
} else if (cause < 600 && cause >= 500) {
|
||||
/* 5xx class error - problem in the remote end */
|
||||
return AST_CAUSE_CONGESTION;
|
||||
} else if (cause < 700 && cause >= 600) {
|
||||
/* 6xx - global errors in the 4xx class */
|
||||
return AST_CAUSE_INTERWORKING;
|
||||
}
|
||||
return AST_CAUSE_NORMAL;
|
||||
}
|
||||
/* Never reached */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST_FRAMEWORK
|
||||
AST_TEST_DEFINE(xml_sanitization_end_null)
|
||||
{
|
||||
|
|
|
@ -42,6 +42,7 @@ static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pj
|
|||
char *cause;
|
||||
char *text;
|
||||
int code;
|
||||
int cause_q850, cause_sip;
|
||||
|
||||
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
|
||||
for (; header;
|
||||
|
@ -49,21 +50,27 @@ static void rfc3326_use_reason_header(struct ast_sip_session *session, struct pj
|
|||
ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
|
||||
cause = ast_skip_blanks(buf);
|
||||
|
||||
if (strncasecmp(cause, "Q.850", 5) || !(cause = strstr(cause, "cause="))) {
|
||||
cause_q850 = !strncasecmp(cause, "Q.850", 5);
|
||||
cause_sip = !strncasecmp(cause, "SIP", 3);
|
||||
if ((cause_q850 || cause_sip) && (cause = strstr(cause, "cause="))) {
|
||||
/* If text is present get rid of it */
|
||||
if ((text = strchr(cause, ';'))) {
|
||||
*text = '\0';
|
||||
}
|
||||
|
||||
if (sscanf(cause, "cause=%30d", &code) != 1) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If text is present get rid of it */
|
||||
if ((text = strstr(cause, ";"))) {
|
||||
*text = '\0';
|
||||
if (cause_q850) {
|
||||
ast_channel_hangupcause_set(session->channel, code & 0x7f);
|
||||
break;
|
||||
} else if (cause_sip) {
|
||||
ast_channel_hangupcause_set(session->channel, ast_sip_hangup_sip2cause(code));
|
||||
break;
|
||||
}
|
||||
|
||||
if (sscanf(cause, "cause=%30d", &code) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast_channel_hangupcause_set(session->channel, code & 0x7f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue