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>
char *dest = NULL;
char *status;
char *parse;
+ int protocol = 0;
+ char status_protocol[20];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(dest);
);
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);
/* 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;
}
}
/* 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";
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;
}
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;
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) {
--- /dev/null
+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.
*/
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
\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)) {
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);