[Asterisk-code-review] chan_pjsip, app_transfer: Add TRANSFERSTATUSPROTOCOL variable (asterisk[18])

Dan Cropp asteriskteam at digium.com
Wed Jan 27 08:35:01 CST 2021


Dan Cropp has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/15377 )


Change subject: chan_pjsip, app_transfer: Add TRANSFERSTATUSPROTOCOL variable
......................................................................

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
---
M apps/app_transfer.c
M channels/chan_pjsip.c
A doc/CHANGES-staging/app_transferprotocol.txt
M include/asterisk/channel.h
M main/channel.c
5 files changed, 86 insertions(+), 8 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/77/15377/1

diff --git a/apps/app_transfer.c b/apps/app_transfer.c
index 4fe3dca..d152340 100644
--- a/apps/app_transfer.c
+++ b/apps/app_transfer.c
@@ -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 @@
 	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 @@
 	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 @@
 		/* 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 @@
 	/* 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 @@
 		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;
 }
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 483cd3e..5c19443 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -1982,12 +1982,17 @@
 			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 @@
 			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) {
diff --git a/doc/CHANGES-staging/app_transferprotocol.txt b/doc/CHANGES-staging/app_transferprotocol.txt
new file mode 100644
index 0000000..5d3521b
--- /dev/null
+++ b/doc/CHANGES-staging/app_transferprotocol.txt
@@ -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.
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index baefedd..40069b0 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2641,6 +2641,18 @@
 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
  * \param child Child channel
diff --git a/main/channel.c b/main/channel.c
index d75c615..986b29a 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -6468,8 +6468,30 @@
 */
 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)) {
@@ -6503,6 +6525,13 @@
 				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);

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/15377
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 18
Gerrit-Change-Id: Ia6a94784b4925628af122409cdd733c9f29abfc4
Gerrit-Change-Number: 15377
Gerrit-PatchSet: 1
Gerrit-Owner: Dan Cropp <dan at amtelco.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210127/9f99647f/attachment.html>


More information about the asterisk-code-review mailing list