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
462133e5e4
commit
de745157ca
|
@ -2881,97 +2881,6 @@ static int chan_pjsip_sendtext(struct ast_channel *ast, const char *text)
|
||||||
return rc;
|
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)
|
static void chan_pjsip_session_begin(struct ast_sip_session *session)
|
||||||
{
|
{
|
||||||
RAII_VAR(struct ast_datastore *, datastore, NULL, ao2_cleanup);
|
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);
|
ast_set_hangupsource(session->channel, ast_channel_name(session->channel), 0);
|
||||||
if (!ast_channel_hangupcause(session->channel) && session->inv_session) {
|
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);
|
ast_queue_hangup_with_cause(session->channel, cause);
|
||||||
} else {
|
} 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,
|
snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "SIP %d %.*s", status.code,
|
||||||
(int) pj_strlen(&status.reason), pj_strbuf(&status.reason));
|
(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_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);
|
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
|
* \param uri The pjsip_uri to check
|
||||||
*
|
*
|
||||||
* \retva; 1 if allowed
|
* \retval 1 if allowed
|
||||||
* \retval 0 if not allowed
|
* \retval 0 if not allowed
|
||||||
*/
|
*/
|
||||||
int ast_sip_is_allowed_uri(pjsip_uri *uri);
|
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);
|
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 */
|
#endif /* _RES_PJSIP_H */
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "asterisk/uuid.h"
|
#include "asterisk/uuid.h"
|
||||||
#include "asterisk/sorcery.h"
|
#include "asterisk/sorcery.h"
|
||||||
#include "asterisk/file.h"
|
#include "asterisk/file.h"
|
||||||
|
#include "asterisk/causes.h"
|
||||||
#include "asterisk/cli.h"
|
#include "asterisk/cli.h"
|
||||||
#include "asterisk/callerid.h"
|
#include "asterisk/callerid.h"
|
||||||
#include "asterisk/res_pjsip_cli.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;
|
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
|
#ifdef TEST_FRAMEWORK
|
||||||
AST_TEST_DEFINE(xml_sanitization_end_null)
|
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 *cause;
|
||||||
char *text;
|
char *text;
|
||||||
int code;
|
int code;
|
||||||
|
int cause_q850, cause_sip;
|
||||||
|
|
||||||
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
|
header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &str_reason, NULL);
|
||||||
for (; header;
|
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));
|
ast_copy_pj_str(buf, &header->hvalue, sizeof(buf));
|
||||||
cause = ast_skip_blanks(buf);
|
cause = ast_skip_blanks(buf);
|
||||||
|
|
||||||
if (strncasecmp(cause, "Q.850", 5) || !(cause = strstr(cause, "cause="))) {
|
cause_q850 = !strncasecmp(cause, "Q.850", 5);
|
||||||
continue;
|
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 is present get rid of it */
|
||||||
if ((text = strstr(cause, ";"))) {
|
if ((text = strchr(cause, ';'))) {
|
||||||
*text = '\0';
|
*text = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sscanf(cause, "cause=%30d", &code) != 1) {
|
if (sscanf(cause, "cause=%30d", &code) != 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cause_q850) {
|
||||||
ast_channel_hangupcause_set(session->channel, code & 0x7f);
|
ast_channel_hangupcause_set(session->channel, code & 0x7f);
|
||||||
break;
|
break;
|
||||||
|
} else if (cause_sip) {
|
||||||
|
ast_channel_hangupcause_set(session->channel, ast_sip_hangup_sip2cause(code));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue