[Asterisk-code-review] chan_pjsip: Transfer failure sip result passed through channel: Trans... (asterisk[master])

Dan Cropp asteriskteam at digium.com
Fri Jan 22 09:11:07 CST 2021


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


Change subject: chan_pjsip: Transfer failure sip result passed through channel: Transfer parameter returns the sip protocol error code control: Redirect support additional transfer protocol parameter app_transfer: TRANSFERSTATUSPROTOCOL channel variable addition
......................................................................

chan_pjsip: Transfer failure sip result passed through
channel: Transfer parameter returns the sip protocol error code
control: Redirect support additional transfer protocol parameter
app_transfer: TRANSFERSTATUSPROTOCOL channel variable addition

When a Transfer/REFER is executed, the SIP protocol code is now
passed from chan_pjsip through the channel to the application
layer.  Application layer sets the TRANSFERSTATUSPROTOCOL
channel variable to this value.

This allows applications to detect the failure reason and
take different 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
M include/asterisk/channel.h
M main/channel.c
M res/stasis/control.c
5 files changed, 49 insertions(+), 11 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/38/15338/1

diff --git a/apps/app_transfer.c b/apps/app_transfer.c
index 4fe3dca..9640f03 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 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,7 +102,10 @@
 	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 +119,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 +128,12 @@
 	/* 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);
+	res = ast_transfer(chan, dest, &protocol);
 
 	if (res < 0) {
 		status = "FAILURE";
@@ -126,7 +143,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..c741425 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,17 @@
 			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/include/asterisk/channel.h b/include/asterisk/channel.h
index baefedd..45ef0c2 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2637,8 +2637,9 @@
  * \retval 1 if supported and requested
  * \param chan current channel
  * \param dest destination extension for transfer
+ * \param protocol result code for transfer (0 success, else sip error code)
  */
-int ast_transfer(struct ast_channel *chan, char *dest);
+int ast_transfer(struct ast_channel *chan, char *dest, int *protocol);
 
 /*!
  * \brief Inherits channel variable from parent to child channel
diff --git a/main/channel.c b/main/channel.c
index d75c615..5e269d9 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -6466,10 +6466,13 @@
 	\arg app_transfer
 	\arg the manager interface
 */
-int ast_transfer(struct ast_channel *chan, char *dest)
+int ast_transfer(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 +6506,8 @@
 				res = 1;
 			} else {
 				res = -1;
+				if(protocol)
+					*protocol = *message;
 			}
 
 			ast_frfree(fr);
diff --git a/res/stasis/control.c b/res/stasis/control.c
index 584e60e..c95b4f2 100644
--- a/res/stasis/control.c
+++ b/res/stasis/control.c
@@ -483,11 +483,12 @@
 {
 	char *endpoint = data;
 	int res;
+	int protocol = 0;
 
 	ast_assert(control->channel != NULL);
 	ast_assert(endpoint != NULL);
 
-	res = ast_transfer(control->channel, endpoint);
+	res = ast_transfer(control->channel, endpoint, &protocol);
 	if (!res) {
 		ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
 			ast_channel_name(control->channel));

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

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: Ia6a94784b4925628af122409cdd733c9f29abfc4
Gerrit-Change-Number: 15338
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/20210122/df23c351/attachment-0001.html>


More information about the asterisk-code-review mailing list