[Asterisk-code-review] res/res pjsip session: allow SDP answer to be regenerated (asterisk[15])

Jenkins2 asteriskteam at digium.com
Mon Aug 28 07:24:41 CDT 2017


Jenkins2 has submitted this change and it was merged. ( https://gerrit.asterisk.org/6302 )

Change subject: res/res_pjsip_session: allow SDP answer to be regenerated
......................................................................

res/res_pjsip_session: allow SDP answer to be regenerated

If an SDP answer hasn't been sent yet, it's legal to change it.
This is required for PJSIP_DTMF_MODE to work correctly, and can
also have use in the future for updating codecs too.

ASTERISK-27209 #close

Change-Id: Idbbfb7cb3f72fbd96c94d10d93540f69bd51e7a1
---
M channels/pjsip/dialplan_functions.c
M include/asterisk/res_pjsip_session.h
M res/res_pjsip_session.c
3 files changed, 61 insertions(+), 1 deletion(-)

Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Jenkins2: Approved for Submit



diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index c89d9ca..93875b3 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -1241,10 +1241,13 @@
 	struct refresh_data *data = obj;
 
 	if (data->session->inv_session->state == PJSIP_INV_STATE_CONFIRMED) {
-		ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
+		ast_debug(3, "Changing DTMF mode on channel %s after OFFER/ANSWER completion. Sending session refresh\n", ast_channel_name(data->session->channel));
 
 		ast_sip_session_refresh(data->session, NULL, NULL,
 			sip_session_response_cb, data->method, 1, NULL);
+	} else if (data->session->inv_session->state == PJSIP_INV_STATE_INCOMING) {
+		ast_debug(3, "Changing DTMF mode on channel %s during OFFER/ANSWER exchange. Updating SDP answer\n", ast_channel_name(data->session->channel));
+		ast_sip_session_regenerate_answer(data->session, NULL);
 	}
 
 	return 0;
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index 5f49c82..d5b6fa1 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -673,6 +673,23 @@
 		struct ast_sip_session_media_state *media_state);
 
 /*!
+ * \brief Regenerate SDP Answer
+ *
+ * This method is used when an SDP offer has been received but an SDP answer
+ * has not been sent yet. It requests that a new local SDP be created and
+ * set as the SDP answer. As with any outgoing request in res_pjsip_session,
+ * this will call into registered supplements in case they wish to add anything.
+ *
+ * \param session The session on which the answer will be updated
+ * \param on_sdp_creation Callback called when SDP is created
+ * \param generate_new_sdp Boolean to indicate if a new SDP should be created
+ * \retval 0 Successfully updated the SDP answer
+ * \retval -1 Failure to updated the SDP answer
+ */
+int ast_sip_session_regenerate_answer(struct ast_sip_session *session,
+		ast_sip_session_sdp_creation_cb on_sdp_creation);
+
+/*!
  * \brief Send a SIP response
  *
  * This will send the SIP response specified in tdata and
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index b6b8a21..f6b3b93 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1550,6 +1550,46 @@
 	return 0;
 }
 
+int ast_sip_session_regenerate_answer(struct ast_sip_session *session,
+		ast_sip_session_sdp_creation_cb on_sdp_creation)
+{
+	pjsip_inv_session *inv_session = session->inv_session;
+	pjmedia_sdp_session *new_answer = NULL;
+	const pjmedia_sdp_session *previous_offer = NULL;
+
+	/* The SDP answer can only be regenerated if it is still pending to be sent */
+	if (!inv_session->neg || (pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_REMOTE_OFFER &&
+		pjmedia_sdp_neg_get_state(inv_session->neg) != PJMEDIA_SDP_NEG_STATE_WAIT_NEGO)) {
+		ast_log(LOG_WARNING, "Requested to regenerate local SDP answer for channel '%s' but negotiation in state '%s'\n",
+			ast_channel_name(session->channel), pjmedia_sdp_neg_state_str(pjmedia_sdp_neg_get_state(inv_session->neg)));
+		return -1;
+	}
+
+	pjmedia_sdp_neg_get_neg_remote(inv_session->neg, &previous_offer);
+	if (pjmedia_sdp_neg_get_state(inv_session->neg) == PJMEDIA_SDP_NEG_STATE_WAIT_NEGO) {
+		/* Transition the SDP negotiator back to when it received the remote offer */
+		pjmedia_sdp_neg_negotiate(inv_session->pool, inv_session->neg, 0);
+		pjmedia_sdp_neg_set_remote_offer(inv_session->pool, inv_session->neg, previous_offer);
+	}
+
+	new_answer = create_local_sdp(inv_session, session, previous_offer);
+	if (!new_answer) {
+		ast_log(LOG_WARNING, "Could not create a new local SDP answer for channel '%s'\n",
+			ast_channel_name(session->channel));
+		return -1;
+	}
+
+	if (on_sdp_creation) {
+		if (on_sdp_creation(session, new_answer)) {
+			return -1;
+		}
+	}
+
+	pjsip_inv_set_sdp_answer(inv_session, new_answer);
+
+	return 0;
+}
+
 void ast_sip_session_send_response(struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
 	handle_outgoing_response(session, tdata);

-- 
To view, visit https://gerrit.asterisk.org/6302
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 15
Gerrit-MessageType: merged
Gerrit-Change-Id: Idbbfb7cb3f72fbd96c94d10d93540f69bd51e7a1
Gerrit-Change-Number: 6302
Gerrit-PatchSet: 1
Gerrit-Owner: Torrey Searle <tsearle at gmail.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170828/b6593a93/attachment.html>


More information about the asterisk-code-review mailing list