chan_pjsip, app_transfer: Add TRANSFERSTATUSPROTOCOL variable
When a Transfer/REFER is executed, TRANSFERSTATUSPROTOCOL variable is 0 when no protocl specific error SIP example of failure, 3xx-6xx for the SIP error code received This allows applications to perform actions based on the failure reason. ASTERISK-29252 #close Reported-by: Dan Cropp Change-Id: Ia6a94784b4925628af122409cdd733c9f29abfc4
This commit is contained in:
parent
6d980de282
commit
55891227e8
|
@ -69,6 +69,14 @@
|
|||
Transfer unsupported by channel driver.
|
||||
</value>
|
||||
</variable>
|
||||
<variable name="TRANSFERSTATUSPROTOCOL">
|
||||
<value name="0">
|
||||
No error.
|
||||
</value>
|
||||
<value name="3xx-6xx">
|
||||
SIP example - Error result code.
|
||||
</value>
|
||||
</variable>
|
||||
</variablelist>
|
||||
</description>
|
||||
</application>
|
||||
|
@ -85,6 +93,8 @@ static int transfer_exec(struct ast_channel *chan, const char *data)
|
|||
char *dest = NULL;
|
||||
char *status;
|
||||
char *parse;
|
||||
int protocol = 0;
|
||||
char status_protocol[20];
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(dest);
|
||||
);
|
||||
|
@ -92,6 +102,8 @@ static int transfer_exec(struct ast_channel *chan, const char *data)
|
|||
if (ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Transfer requires an argument ([Tech/]destination)\n");
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "FAILURE");
|
||||
snprintf(status_protocol, sizeof(status_protocol), "%d", protocol);
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUSPROTOCOL", status_protocol);
|
||||
return 0;
|
||||
} else
|
||||
parse = ast_strdupa(data);
|
||||
|
@ -106,6 +118,8 @@ static int transfer_exec(struct ast_channel *chan, const char *data)
|
|||
/* Allow execution only if the Tech/destination agrees with the type of the channel */
|
||||
if (strncasecmp(ast_channel_tech(chan)->type, tech, len)) {
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "FAILURE");
|
||||
snprintf(status_protocol, sizeof(status_protocol), "%d", protocol);
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUSPROTOCOL", status_protocol);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +127,14 @@ static int transfer_exec(struct ast_channel *chan, const char *data)
|
|||
/* Check if the channel supports transfer before we try it */
|
||||
if (!ast_channel_tech(chan)->transfer) {
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", "UNSUPPORTED");
|
||||
snprintf(status_protocol, sizeof(status_protocol), "%d", protocol);
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUSPROTOCOL", status_protocol);
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = ast_transfer(chan, dest);
|
||||
/* New transfer API returns a protocol code
|
||||
SIP example, 0 = success, 3xx-6xx are sip error codes for the REFER */
|
||||
res = ast_transfer_protocol(chan, dest, &protocol);
|
||||
|
||||
if (res < 0) {
|
||||
status = "FAILURE";
|
||||
|
@ -126,7 +144,11 @@ static int transfer_exec(struct ast_channel *chan, const char *data)
|
|||
res = 0;
|
||||
}
|
||||
|
||||
snprintf(status_protocol, sizeof(status_protocol), "%d", protocol);
|
||||
ast_debug(1, "ast_transfer channel %s TRANSFERSTATUS=%s, TRANSFERSTATUSPROTOCOL=%s\n",
|
||||
ast_channel_name(chan), status, status_protocol);
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUS", status);
|
||||
pbx_builtin_setvar_helper(chan, "TRANSFERSTATUSPROTOCOL", status_protocol);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -1982,12 +1982,17 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
|
|||
rdata = event->body.tsx_state.src.rdata;
|
||||
msg = rdata->msg_info.msg;
|
||||
|
||||
if (!pjsip_method_cmp(&msg->line.req.method, pjsip_get_notify_method())) {
|
||||
body = msg->body;
|
||||
if (body && !pj_stricmp2(&body->content_type.type, "message")
|
||||
&& !pj_stricmp2(&body->content_type.subtype, "sipfrag")) {
|
||||
pjsip_parse_status_line((char *)body->data, body->len, &status_line);
|
||||
if (msg->type == PJSIP_REQUEST_MSG) {
|
||||
if (!pjsip_method_cmp(&msg->line.req.method, pjsip_get_notify_method())) {
|
||||
body = msg->body;
|
||||
if (body && !pj_stricmp2(&body->content_type.type, "message")
|
||||
&& !pj_stricmp2(&body->content_type.subtype, "sipfrag")) {
|
||||
pjsip_parse_status_line((char *)body->data, body->len, &status_line);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status_line.code = msg->line.status.code;
|
||||
status_line.reason = msg->line.status.reason;
|
||||
}
|
||||
} else {
|
||||
status_line.code = 500;
|
||||
|
@ -2000,12 +2005,16 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event)
|
|||
res = -1;
|
||||
|
||||
/* If the subscription has terminated, return AST_TRANSFER_SUCCESS for 2XX.
|
||||
* Any other status code returns AST_TRANSFER_FAILED.
|
||||
* Return AST_TRANSFER_FAILED for any code < 200.
|
||||
* Otherwise, return the status code.
|
||||
* The subscription should not terminate for any code < 200,
|
||||
* but if it does, that constitutes a failure. */
|
||||
if (status_line.code < 200 || status_line.code >= 300) {
|
||||
if (status_line.code < 200) {
|
||||
message = AST_TRANSFER_FAILED;
|
||||
} else if (status_line.code >= 300) {
|
||||
message = status_line.code;
|
||||
}
|
||||
|
||||
/* If subscription not terminated and subscription is finished (status code >= 200)
|
||||
* terminate it */
|
||||
if (!is_last) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
Subject: chan_pjsip, app_transfer
|
||||
|
||||
Added TRANSFERSTATUSPROTOCOL variable. When transfer is performed,
|
||||
transfers can pass a protocol specific error code.
|
||||
Example, in SIP 3xx-6xx represent any SIP specific error received when
|
||||
performing a REFER.
|
|
@ -2640,6 +2640,18 @@ int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(co
|
|||
*/
|
||||
int ast_transfer(struct ast_channel *chan, char *dest);
|
||||
|
||||
/*!
|
||||
* \brief Transfer a channel (if supported) receieve protocol result.
|
||||
* \retval -1 on error
|
||||
* \retval 0 if not supported
|
||||
* \retval 1 if supported and requested
|
||||
* \param chan current channel
|
||||
* \param dest destination extension for transfer
|
||||
* \param protocol specific error code in case of failure
|
||||
* Example, sip 0 success, else sip error code
|
||||
*/
|
||||
int ast_transfer_protocol(struct ast_channel *chan, char *dest, int *protocol);
|
||||
|
||||
/*!
|
||||
* \brief Inherits channel variable from parent to child channel
|
||||
* \param parent Parent channel
|
||||
|
|
|
@ -6474,9 +6474,31 @@ int ast_call(struct ast_channel *chan, const char *addr, int timeout)
|
|||
\arg the manager interface
|
||||
*/
|
||||
int ast_transfer(struct ast_channel *chan, char *dest)
|
||||
{
|
||||
int protocol;
|
||||
return ast_transfer_protocol(chan, dest, &protocol);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Transfer a call to dest, if the channel supports transfer
|
||||
|
||||
\param chan channel to transfer
|
||||
\param dest destination to transfer to
|
||||
\param protocol is the protocol result
|
||||
SIP example, 0=success, 3xx-6xx is SIP error code
|
||||
|
||||
Called by:
|
||||
\arg app_transfer
|
||||
\arg the manager interface
|
||||
*/
|
||||
int ast_transfer_protocol(struct ast_channel *chan, char *dest, int *protocol)
|
||||
{
|
||||
int res = -1;
|
||||
|
||||
if (protocol) {
|
||||
*protocol = 0;
|
||||
}
|
||||
|
||||
/* Stop if we're a zombie or need a soft hangup */
|
||||
ast_channel_lock(chan);
|
||||
if (!ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
|
||||
|
@ -6510,6 +6532,13 @@ int ast_transfer(struct ast_channel *chan, char *dest)
|
|||
res = 1;
|
||||
} else {
|
||||
res = -1;
|
||||
/* Message can contain a protocol specific code
|
||||
AST_TRANSFER_SUCCESS indicates success
|
||||
Else, failure. Protocol will be set to the failure reason.
|
||||
SIP example, 0 is success, else error code 3xx-6xx */
|
||||
if (protocol) {
|
||||
*protocol = *message;
|
||||
}
|
||||
}
|
||||
|
||||
ast_frfree(fr);
|
||||
|
|
Loading…
Reference in New Issue