[svn-commits] mmichelson: branch 13 r433619 - in /branches/13: include/asterisk/ res/ res/r...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Mar 27 15:30:19 CDT 2015


Author: mmichelson
Date: Fri Mar 27 15:30:18 2015
New Revision: 433619

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433619
Log:
Add stateful PJSIP response API call, and use it for out-of-dialog responses.

Asterisk had an issue where retransmissions of MESSAGE requests resulted in
Asterisk processing the retransmission as if it were a new MESSAGE request.

This patch fixes the issue by creating a transaction in PJSIP on the incoming
request. This way, if a retransmission arrives, the PJSIP transaction layer
will resend the response and Asterisk will not ever see the retransmission.

ASTERISK-24920 #close
Reported by Mark Michelson


Modified:
    branches/13/include/asterisk/res_pjsip.h
    branches/13/res/res_pjsip.c
    branches/13/res/res_pjsip/pjsip_options.c
    branches/13/res/res_pjsip_messaging.c
    branches/13/res/res_pjsip_registrar.c

Modified: branches/13/include/asterisk/res_pjsip.h
URL: http://svnview.digium.com/svn/asterisk/branches/13/include/asterisk/res_pjsip.h?view=diff&rev=433619&r1=433618&r2=433619
==============================================================================
--- branches/13/include/asterisk/res_pjsip.h (original)
+++ branches/13/include/asterisk/res_pjsip.h Fri Mar 27 15:30:18 2015
@@ -1279,6 +1279,11 @@
 /*!
  * \brief Send a response to an out of dialog request
  *
+ * Use this function sparingly, since this does not create a transaction
+ * within PJSIP. This means that if the request is retransmitted, it is
+ * your responsibility to detect this and not process the same request
+ * twice, and to send the same response for each retransmission.
+ *
  * \param res_addr The response address for this response
  * \param tdata The response to send
  * \param endpoint The ast_sip_endpoint associated with this response
@@ -1287,6 +1292,24 @@
  * \retval -1 Failure
  */
 int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint);
+
+/*!
+ * \brief Send a stateful response to an out of dialog request
+ *
+ * This creates a transaction within PJSIP, meaning that if the request
+ * that we are responding to is retransmitted, we will not attempt to
+ * re-handle the request.
+ *
+ * \param rdata The request that is being responded to
+ * \param tdata The response to send
+ * \param endpoint The ast_sip_endpoint associated with this response
+ *
+ * \since 13.4.0
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint);
 
 /*!
  * \brief Determine if an incoming request requires authentication

Modified: branches/13/res/res_pjsip.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip.c?view=diff&rev=433619&r1=433618&r2=433619
==============================================================================
--- branches/13/res/res_pjsip.c (original)
+++ branches/13/res/res_pjsip.c Fri Mar 27 15:30:18 2015
@@ -3292,7 +3292,7 @@
 	return PJ_FALSE;
 }
 
-int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
+static void supplement_outgoing_response(pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
 {
 	struct ast_sip_supplement *supplement;
 	pjsip_cseq_hdr *cseq = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CSEQ, NULL);
@@ -3300,8 +3300,7 @@
 
 	AST_RWLIST_RDLOCK(&supplements);
 	AST_LIST_TRAVERSE(&supplements, supplement, next) {
-		if (supplement->outgoing_response
-			&& does_method_match(&cseq->method.name, supplement->method)) {
+		if (supplement->outgoing_response && does_method_match(&cseq->method.name, supplement->method)) {
 			supplement->outgoing_response(sip_endpoint, contact, tdata);
 		}
 	}
@@ -3309,8 +3308,33 @@
 
 	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, supplement_module.id, MOD_DATA_CONTACT, NULL);
 	ao2_cleanup(contact);
+}
+
+int ast_sip_send_response(pjsip_response_addr *res_addr, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
+{
+	supplement_outgoing_response(tdata, sip_endpoint);
 
 	return pjsip_endpt_send_response(ast_sip_get_pjsip_endpoint(), res_addr, tdata, NULL, NULL);
+}
+
+int ast_sip_send_stateful_response(pjsip_rx_data *rdata, pjsip_tx_data *tdata, struct ast_sip_endpoint *sip_endpoint)
+{
+	pjsip_transaction *tsx;
+
+	if (pjsip_tsx_create_uas(NULL, rdata, &tsx) != PJ_SUCCESS) {
+		pjsip_tx_data_dec_ref(tdata);
+		return -1;
+	}
+	pjsip_tsx_recv_msg(tsx, rdata);
+
+	supplement_outgoing_response(tdata, sip_endpoint);
+
+	if (pjsip_tsx_send_msg(tsx, tdata) != PJ_SUCCESS) {
+		pjsip_tx_data_dec_ref(tdata);
+		return -1;
+	}
+
+	return 0;
 }
 
 int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code,

Modified: branches/13/res/res_pjsip/pjsip_options.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip/pjsip_options.c?view=diff&rev=433619&r1=433618&r2=433619
==============================================================================
--- branches/13/res/res_pjsip/pjsip_options.c (original)
+++ branches/13/res/res_pjsip/pjsip_options.c Fri Mar 27 15:30:18 2015
@@ -577,7 +577,6 @@
 	pjsip_transaction *trans = pjsip_rdata_get_tsx(rdata);
 	pjsip_tx_data *tdata;
 	const pjsip_hdr *hdr;
-	pjsip_response_addr res_addr;
 	pj_status_t status;
 
 	/* Make the response object */
@@ -611,17 +610,8 @@
 	} else {
 		struct ast_sip_endpoint *endpoint;
 
-		/* Get where to send response. */
-		status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
-		if (status != PJ_SUCCESS) {
-			ast_log(LOG_ERROR, "Unable to get response address (%d)\n", status);
-
-			pjsip_tx_data_dec_ref(tdata);
-			return status;
-		}
-
 		endpoint = ast_pjsip_rdata_get_endpoint(rdata);
-		status = ast_sip_send_response(&res_addr, tdata, endpoint);
+		status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
 		ao2_cleanup(endpoint);
 	}
 

Modified: branches/13/res/res_pjsip_messaging.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip_messaging.c?view=diff&rev=433619&r1=433618&r2=433619
==============================================================================
--- branches/13/res/res_pjsip_messaging.c (original)
+++ branches/13/res/res_pjsip_messaging.c Fri Mar 27 15:30:18 2015
@@ -610,7 +610,6 @@
 {
 	pjsip_tx_data *tdata;
 	pj_status_t status;
-	pjsip_response_addr res_addr;
 
 	status = ast_sip_create_response(rdata, code, NULL, &tdata);
 	if (status != PJ_SUCCESS) {
@@ -623,15 +622,8 @@
 	} else {
 		struct ast_sip_endpoint *endpoint;
 
-		/* Get where to send response. */
-		status = pjsip_get_response_addr(tdata->pool, rdata, &res_addr);
-		if (status != PJ_SUCCESS) {
-			ast_log(LOG_ERROR, "Unable to get response address (%d)\n", status);
-			return status;
-		}
-
 		endpoint = ast_pjsip_rdata_get_endpoint(rdata);
-		status = ast_sip_send_response(&res_addr, tdata, endpoint);
+		status = ast_sip_send_stateful_response(rdata, tdata, endpoint);
 		ao2_cleanup(endpoint);
 	}
 

Modified: branches/13/res/res_pjsip_registrar.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/res/res_pjsip_registrar.c?view=diff&rev=433619&r1=433618&r2=433619
==============================================================================
--- branches/13/res/res_pjsip_registrar.c (original)
+++ branches/13/res/res_pjsip_registrar.c Fri Mar 27 15:30:18 2015
@@ -418,7 +418,6 @@
 	pjsip_contact_hdr *contact_hdr = NULL;
 	struct registrar_contact_details details = { 0, };
 	pjsip_tx_data *tdata;
-	pjsip_response_addr addr;
 	const char *aor_name = ast_sorcery_object_get_id(task_data->aor);
 	RAII_VAR(struct ast_str *, path_str, NULL, ast_free);
 	struct ast_sip_contact *response_contact;
@@ -603,11 +602,7 @@
 		pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)expires_hdr);
 	}
 
-	if (pjsip_get_response_addr(tdata->pool, task_data->rdata, &addr) == PJ_SUCCESS) {
-		ast_sip_send_response(&addr, tdata, task_data->endpoint);
-	} else {
-		pjsip_tx_data_dec_ref(tdata);
-	}
+	ast_sip_send_stateful_response(task_data->rdata, tdata, task_data->endpoint);
 
 	return PJ_TRUE;
 }




More information about the svn-commits mailing list