<p>George Joseph <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/17733">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">bundled_pjproject: Add more support for multipart bodies<br><br>Adding upstream patch for pull request...<br>https://github.com/pjsip/pjproject/pull/2920<br>---------------------------------------------------------------<br><br>sip_inv: Additional multipart support (#2919)<br><br>sip_inv.c:inv_check_sdp_in_incoming_msg() deals with multipart<br>message bodies in rdata correctly. In the case where early media is<br>involved though, the existing sdp has to be retrieved from the last<br>tdata sent in this transaction. This, however, always assumes that<br>the sdp sent is in a non-multipart body. While there's a function<br>to retrieve the sdp from multipart and non-multpart rdata bodies,<br>no similar function for tdata exists. So...<br><br>* The existing pjsip_rdata_get_sdp_info2 was refactored to<br> find the sdp in any body, multipart or non-multipart, and<br> from either an rdata or tdata. The new function is<br> pjsip_get_sdp_info. This new function detects whether the<br> pjsip_msg->body->data is the text representation of the sdp<br> from an rdata or an existing pjmedia_sdp_session object<br> from a tdata, or whether pjsip_msg->body is a multipart<br> body containing either of the two sdp formats.<br><br>* The exsting pjsip_rdata_get_sdp_info and pjsip_rdata_get_sdp_info2<br> functions are now wrappers that get the body and Content-Type<br> header from the rdata and call pjsip_get_sdp_info.<br><br>* Two new wrappers named pjsip_tdata_get_sdp_info and<br> pjsip_tdata_get_sdp_info2 have been created that get the body<br> from the tdata and call pjsip_get_sdp_info.<br><br>* inv_offer_answer_test.c was updated to test multipart scenarios.<br><br>ASTERISK-29804<br><br>Change-Id: I483c7c3d413280c9e247a96ad581278347f9c71b<br>---<br>A third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch<br>1 file changed, 661 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch b/third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch</span><br><span>new file mode 100644</span><br><span>index 0000000..91feefb</span><br><span>--- /dev/null</span><br><span>+++ b/third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch</span><br><span>@@ -0,0 +1,661 @@</span><br><span style="color: hsl(120, 100%, 40%);">+From 0ed41eb5fd0e4192e1b7dc374f819d17aef3e805 Mon Sep 17 00:00:00 2001</span><br><span style="color: hsl(120, 100%, 40%);">+From: George Joseph <gtjoseph@users.noreply.github.com></span><br><span style="color: hsl(120, 100%, 40%);">+Date: Tue, 21 Dec 2021 19:32:22 -0700</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: [PATCH] sip_inv: Additional multipart support (#2919) (#2920)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+---</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip/include/pjsip-ua/sip_inv.h | 108 ++++++++++-</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip/src/pjsip-ua/sip_inv.c | 240 ++++++++++++++++++++-----</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip/src/test/inv_offer_answer_test.c | 103 ++++++++++-</span><br><span style="color: hsl(120, 100%, 40%);">+ 3 files changed, 394 insertions(+), 57 deletions(-)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h</span><br><span style="color: hsl(120, 100%, 40%);">+index 14f2d23fa..c33551786 100644</span><br><span style="color: hsl(120, 100%, 40%);">+--- a/pjsip/include/pjsip-ua/sip_inv.h</span><br><span>++++ b/pjsip/include/pjsip-ua/sip_inv.h</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -451,11 +451,11 @@ struct pjsip_inv_session</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+- * This structure represents SDP information in a pjsip_rx_data. Application</span><br><span style="color: hsl(120, 100%, 40%);">+- * retrieve this information by calling #pjsip_rdata_get_sdp_info(). This</span><br><span style="color: hsl(120, 100%, 40%);">++ * This structure represents SDP information in a pjsip_(rx|tx)_data. Application</span><br><span style="color: hsl(120, 100%, 40%);">++ * retrieve this information by calling #pjsip_get_sdp_info(). This</span><br><span style="color: hsl(120, 100%, 40%);">+ * mechanism supports multipart message body.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+-typedef struct pjsip_rdata_sdp_info</span><br><span style="color: hsl(120, 100%, 40%);">++typedef struct pjsip_sdp_info</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Pointer and length of the text body in the incoming message. If</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -475,7 +475,15 @@ typedef struct pjsip_rdata_sdp_info</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ pjmedia_sdp_session *sdp;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+-} pjsip_rdata_sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++} pjsip_sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * For backwards compatibility and completeness,</span><br><span style="color: hsl(120, 100%, 40%);">++ * pjsip_rdata_sdp_info and pjsip_tdata_sdp_info</span><br><span style="color: hsl(120, 100%, 40%);">++ * are typedef'd to pjsip_sdp_info.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++typedef pjsip_sdp_info pjsip_rdata_sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++typedef pjsip_sdp_info pjsip_tdata_sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -1045,6 +1053,44 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_body(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">+ pjmedia_sdp_session *sdp,</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_msg_body **p_body);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * This is a utility function to create a multipart body with the</span><br><span style="color: hsl(120, 100%, 40%);">++ * SIP body as the first part.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param pool Pool to allocate memory.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param sdp SDP session to be put in the SIP message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param p_body Pointer to receive SIP message body containing</span><br><span style="color: hsl(120, 100%, 40%);">++ * the SDP session.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @return PJ_SUCCESS on success.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DECL(pj_status_t) pjsip_create_multipart_sdp_body( pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjmedia_sdp_session *sdp,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_msg_body **p_body);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * Retrieve SDP information from a message body. Application should</span><br><span style="color: hsl(120, 100%, 40%);">++ * prefer to use this function rather than parsing the SDP manually since</span><br><span style="color: hsl(120, 100%, 40%);">++ * this function supports multipart message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * This function will only parse the SDP once, the first time it is called</span><br><span style="color: hsl(120, 100%, 40%);">++ * on the same message. Subsequent call on the same message will just pick</span><br><span style="color: hsl(120, 100%, 40%);">++ * up the already parsed SDP from the message.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param pool Pool to allocate memory.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param body The message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param msg_media_type From the rdata or tdata Content-Type header, if available.</span><br><span style="color: hsl(120, 100%, 40%);">++ * If NULL, the content_type from the body will be used.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param search_media_type The media type to search for.</span><br><span style="color: hsl(120, 100%, 40%);">++ * If NULL, "application/sdp" will be used.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @return The SDP info.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DECL(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_msg_body *body,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type *msg_media_type,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+ * Retrieve SDP information from an incoming message. Application should</span><br><span style="color: hsl(120, 100%, 40%);">+ * prefer to use this function rather than parsing the SDP manually since</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -1061,6 +1107,60 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_body(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * Retrieve SDP information from an incoming message. Application should</span><br><span style="color: hsl(120, 100%, 40%);">++ * prefer to use this function rather than parsing the SDP manually since</span><br><span style="color: hsl(120, 100%, 40%);">++ * this function supports multipart message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * This function will only parse the SDP once, the first time it is called</span><br><span style="color: hsl(120, 100%, 40%);">++ * on the same message. Subsequent call on the same message will just pick</span><br><span style="color: hsl(120, 100%, 40%);">++ * up the already parsed SDP from the message.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param rdata The incoming message.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param search_media_type The SDP media type to search for.</span><br><span style="color: hsl(120, 100%, 40%);">++ * If NULL, "application/sdp" will be used.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @return The SDP info.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_rx_data *rdata,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * Retrieve SDP information from an outgoing message. Application should</span><br><span style="color: hsl(120, 100%, 40%);">++ * prefer to use this function rather than parsing the SDP manually since</span><br><span style="color: hsl(120, 100%, 40%);">++ * this function supports multipart message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * This function will only parse the SDP once, the first time it is called</span><br><span style="color: hsl(120, 100%, 40%);">++ * on the same message. Subsequent call on the same message will just pick</span><br><span style="color: hsl(120, 100%, 40%);">++ * up the already parsed SDP from the message.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param tdata The outgoing message.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @return The SDP info.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++/**</span><br><span style="color: hsl(120, 100%, 40%);">++ * Retrieve SDP information from an outgoing message. Application should</span><br><span style="color: hsl(120, 100%, 40%);">++ * prefer to use this function rather than parsing the SDP manually since</span><br><span style="color: hsl(120, 100%, 40%);">++ * this function supports multipart message body.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * This function will only parse the SDP once, the first time it is called</span><br><span style="color: hsl(120, 100%, 40%);">++ * on the same message. Subsequent call on the same message will just pick</span><br><span style="color: hsl(120, 100%, 40%);">++ * up the already parsed SDP from the message.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param tdata The outgoing message.</span><br><span style="color: hsl(120, 100%, 40%);">++ * @param search_media_type The SDP media type to search for.</span><br><span style="color: hsl(120, 100%, 40%);">++ * If NULL, "application/sdp" will be used.</span><br><span style="color: hsl(120, 100%, 40%);">++ *</span><br><span style="color: hsl(120, 100%, 40%);">++ * @return The SDP info.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_tx_data *tdata,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_END_DECL</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /**</span><br><span style="color: hsl(120, 100%, 40%);">+diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c</span><br><span style="color: hsl(120, 100%, 40%);">+index ca225015b..b68ae0f16 100644</span><br><span style="color: hsl(120, 100%, 40%);">+--- a/pjsip/src/pjsip-ua/sip_inv.c</span><br><span>++++ b/pjsip/src/pjsip-ua/sip_inv.c</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -118,6 +118,8 @@ static pj_status_t handle_timer_response(pjsip_inv_session *inv,</span><br><span style="color: hsl(120, 100%, 40%);">+ static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv,</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_event *e);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++static int print_sdp(pjsip_msg_body *body, char *buf, pj_size_t len);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) = </span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ &inv_on_state_null,</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -946,66 +948,170 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg,</span><br><span style="color: hsl(120, 100%, 40%);">+ return PJ_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+-PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_msg_body *body,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type *msg_media_type,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_rdata_sdp_info *sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_msg_body *body = rdata->msg_info.msg->body;</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype;</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_media_type app_sdp;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_sdp_info *sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type search_type;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type multipart_mixed;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type multipart_alternative;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type *msg_type;</span><br><span style="color: hsl(120, 100%, 40%);">++ pj_status_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info = (pjsip_rdata_sdp_info*)</span><br><span style="color: hsl(120, 100%, 40%);">+- rdata->endpt_info.mod_data[mod_inv.mod.id];</span><br><span style="color: hsl(120, 100%, 40%);">+- if (sdp_info)</span><br><span style="color: hsl(120, 100%, 40%);">+- return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info = PJ_POOL_ZALLOC_T(pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_sdp_info);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info = PJ_POOL_ZALLOC_T(rdata->tp_info.pool,</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_rdata_sdp_info);</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_ASSERT_RETURN(mod_inv.mod.id >= 0, sdp_info);</span><br><span style="color: hsl(120, 100%, 40%);">+- rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_media_type_init2(&app_sdp, "application", "sdp");</span><br><span style="color: hsl(120, 100%, 40%);">++ if (!body) {</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- if (body && ctype_hdr &&</span><br><span style="color: hsl(120, 100%, 40%);">+- pj_stricmp(&ctype_hdr->media.type, &app_sdp.type)==0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+- pj_stricmp(&ctype_hdr->media.subtype, &app_sdp.subtype)==0)</span><br><span style="color: hsl(120, 100%, 40%);">++ if (msg_media_type) {</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_type = msg_media_type;</span><br><span style="color: hsl(120, 100%, 40%);">++ } else {</span><br><span style="color: hsl(120, 100%, 40%);">++ if (body->content_type.type.slen == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_type = &body->content_type;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ if (!search_media_type) {</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_init2(&search_type, "application", "sdp");</span><br><span style="color: hsl(120, 100%, 40%);">++ } else {</span><br><span style="color: hsl(120, 100%, 40%);">++ pj_memcpy(&search_type, search_media_type, sizeof(search_type));</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_init2(&multipart_mixed, "multipart", "mixed");</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_init2(&multipart_alternative, "multipart", "alternative");</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ if (pjsip_media_type_cmp(msg_type, &search_type, PJ_FALSE) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.ptr = (char*)body->data;</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.slen = body->len;</span><br><span style="color: hsl(120, 100%, 40%);">+- } else if (body && ctype_hdr &&</span><br><span style="color: hsl(120, 100%, 40%);">+- pj_stricmp2(&ctype_hdr->media.type, "multipart")==0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+- (pj_stricmp2(&ctype_hdr->media.subtype, "mixed")==0 ||</span><br><span style="color: hsl(120, 100%, 40%);">+- pj_stricmp2(&ctype_hdr->media.subtype, "alternative")==0))</span><br><span style="color: hsl(120, 100%, 40%);">++ /*</span><br><span style="color: hsl(120, 100%, 40%);">++ * If the print_body function is print_sdp, we know that</span><br><span style="color: hsl(120, 100%, 40%);">++ * body->data is a pjmedia_sdp_session object and came from</span><br><span style="color: hsl(120, 100%, 40%);">++ * a tx_data. If not, it's the text representation of the</span><br><span style="color: hsl(120, 100%, 40%);">++ * sdp from an rx_data.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (body->print_body == print_sdp) {</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->sdp = body->data;</span><br><span style="color: hsl(120, 100%, 40%);">++ } else {</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.ptr = (char*)body->data;</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.slen = body->len;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ } else if (pjsip_media_type_cmp(&multipart_mixed, msg_type, PJ_FALSE) == 0 ||</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_cmp(&multipart_alternative, msg_type, PJ_FALSE) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+- pjsip_multipart_part *part;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_multipart_part *part;</span><br><span style="color: hsl(120, 100%, 40%);">++ part = pjsip_multipart_find_part(body, &search_type, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++ if (part) {</span><br><span style="color: hsl(120, 100%, 40%);">++ if (part->body->print_body == print_sdp) {</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->sdp = part->body->data;</span><br><span style="color: hsl(120, 100%, 40%);">++ } else {</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.ptr = (char*)part->body->data;</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.slen = part->body->len;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- part = pjsip_multipart_find_part(body, &app_sdp, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+- if (part) {</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.ptr = (char*)part->body->data;</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.slen = part->body->len;</span><br><span style="color: hsl(120, 100%, 40%);">+- }</span><br><span style="color: hsl(120, 100%, 40%);">++ /*</span><br><span style="color: hsl(120, 100%, 40%);">++ * If the body was already a pjmedia_sdp_session, we can just</span><br><span style="color: hsl(120, 100%, 40%);">++ * return it. If not and there wasn't a text representation</span><br><span style="color: hsl(120, 100%, 40%);">++ * of the sdp either, we can also just return.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (sdp_info->sdp || !sdp_info->body.ptr) {</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- if (sdp_info->body.ptr) {</span><br><span style="color: hsl(120, 100%, 40%);">+- pj_status_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+- status = pjmedia_sdp_parse(rdata->tp_info.pool,</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.ptr,</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->body.slen,</span><br><span style="color: hsl(120, 100%, 40%);">+- &sdp_info->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">+- if (status == PJ_SUCCESS)</span><br><span style="color: hsl(120, 100%, 40%);">+- status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);</span><br><span style="color: hsl(120, 100%, 40%);">++ /*</span><br><span style="color: hsl(120, 100%, 40%);">++ * If the body was the text representation of teh SDP, we need</span><br><span style="color: hsl(120, 100%, 40%);">++ * to parse it to create a pjmedia_sdp_session object.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++ status = pjmedia_sdp_parse(pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.ptr,</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->body.slen,</span><br><span style="color: hsl(120, 100%, 40%);">++ &sdp_info->sdp);</span><br><span style="color: hsl(120, 100%, 40%);">++ if (status == PJ_SUCCESS)</span><br><span style="color: hsl(120, 100%, 40%);">++ status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- if (status != PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->sdp = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+- PJ_PERROR(1,(THIS_FILE, status,</span><br><span style="color: hsl(120, 100%, 40%);">+- "Error parsing/validating SDP body"));</span><br><span style="color: hsl(120, 100%, 40%);">+- }</span><br><span style="color: hsl(120, 100%, 40%);">++ if (status != PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->sdp = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_PERROR(1, (THIS_FILE, status,</span><br><span style="color: hsl(120, 100%, 40%);">++ "Error parsing/validating SDP body"));</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info->sdp_err = status;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- sdp_info->sdp_err = status;</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_rx_data *rdata,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type *msg_media_type = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_rdata_sdp_info *sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ if (rdata->endpt_info.mod_data[mod_inv.mod.id]) {</span><br><span style="color: hsl(120, 100%, 40%);">++ return (pjsip_rdata_sdp_info *)rdata->endpt_info.mod_data[mod_inv.mod.id];</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ /*</span><br><span style="color: hsl(120, 100%, 40%);">++ * rdata should have a Content-Type header at this point but we'll</span><br><span style="color: hsl(120, 100%, 40%);">++ * make sure.</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (rdata->msg_info.ctype) {</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_media_type = &rdata->msg_info.ctype->media;</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info = pjsip_get_sdp_info(rdata->tp_info.pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ rdata->msg_info.msg->body,</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_media_type,</span><br><span style="color: hsl(120, 100%, 40%);">++ search_media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++ rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ return pjsip_rdata_get_sdp_info2(rdata, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_tx_data *tdata,</span><br><span style="color: hsl(120, 100%, 40%);">++ const pjsip_media_type *search_media_type)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_ctype_hdr *ctype_hdr = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type *msg_media_type = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_tdata_sdp_info *sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ if (tdata->mod_data[mod_inv.mod.id]) {</span><br><span style="color: hsl(120, 100%, 40%);">++ return (pjsip_tdata_sdp_info *)tdata->mod_data[mod_inv.mod.id];</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ /*</span><br><span style="color: hsl(120, 100%, 40%);">++ * tdata won't usually have a Content-Type header at this point</span><br><span style="color: hsl(120, 100%, 40%);">++ * but we'll check just the same,</span><br><span style="color: hsl(120, 100%, 40%);">++ */</span><br><span style="color: hsl(120, 100%, 40%);">++ ctype_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTENT_TYPE, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++ if (ctype_hdr) {</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_media_type = &ctype_hdr->media;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_info = pjsip_get_sdp_info(tdata->pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ tdata->msg->body,</span><br><span style="color: hsl(120, 100%, 40%);">++ msg_media_type,</span><br><span style="color: hsl(120, 100%, 40%);">++ search_media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++ tdata->mod_data[mod_inv.mod.id] = sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ return sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ return pjsip_tdata_get_sdp_info2(tdata, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Verify incoming INVITE request.</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -1730,13 +1836,55 @@ PJ_DEF(pj_status_t) pjsip_create_sdp_body( pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">+ return PJ_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++static pjsip_multipart_part* create_sdp_part(pj_pool_t *pool, pjmedia_sdp_session *sdp)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_multipart_part *sdp_part;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type media_type;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_init2(&media_type, "application", "sdp");</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part = pjsip_multipart_create_part(pool);</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(sdp_part != NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(sdp_part->body != NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_cp(pool, &sdp_part->body->content_type, &media_type);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part->body->data = sdp;</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part->body->clone_data = clone_sdp;</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part->body->print_body = print_sdp;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ return sdp_part;</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++PJ_DEF(pj_status_t) pjsip_create_multipart_sdp_body(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjmedia_sdp_session *sdp,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_msg_body **p_body)</span><br><span style="color: hsl(120, 100%, 40%);">++{</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type media_type;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_msg_body *multipart;</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_multipart_part *sdp_part;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_media_type_init2(&media_type, "multipart", "mixed");</span><br><span style="color: hsl(120, 100%, 40%);">++ multipart = pjsip_multipart_create(pool, &media_type, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(multipart != NULL, PJ_ENOMEM);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ sdp_part = create_sdp_part(pool, sdp);</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(sdp_part != NULL, PJ_ENOMEM);</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_multipart_add_part(pool, multipart, sdp_part);</span><br><span style="color: hsl(120, 100%, 40%);">++ *p_body = multipart;</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ return PJ_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">++}</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ static pjsip_msg_body *create_sdp_body(pj_pool_t *pool,</span><br><span style="color: hsl(120, 100%, 40%);">+ const pjmedia_sdp_session *c_sdp)</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_msg_body *body;</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_status_t status;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+- status = pjsip_create_sdp_body(pool, </span><br><span style="color: hsl(120, 100%, 40%);">++ status = pjsip_create_sdp_body(pool,</span><br><span style="color: hsl(120, 100%, 40%);">+ pjmedia_sdp_session_clone(pool, c_sdp),</span><br><span style="color: hsl(120, 100%, 40%);">+ &body);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+@@ -2059,6 +2207,7 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,</span><br><span style="color: hsl(120, 100%, 40%);">+ )</span><br><span style="color: hsl(120, 100%, 40%);">+ )</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">++ pjsip_sdp_info *tdata_sdp_info;</span><br><span style="color: hsl(120, 100%, 40%);">+ const pjmedia_sdp_session *reoffer_sdp = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_LOG(4,(inv->obj_name, "Received %s response "</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -2067,14 +2216,15 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,</span><br><span style="color: hsl(120, 100%, 40%);">+ (st_code/10==18? "early" : "final" )));</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Retrieve original SDP offer from INVITE request */</span><br><span style="color: hsl(120, 100%, 40%);">+- reoffer_sdp = (const pjmedia_sdp_session*) </span><br><span style="color: hsl(120, 100%, 40%);">+- tsx->last_tx->msg->body->data;</span><br><span style="color: hsl(120, 100%, 40%);">++ tdata_sdp_info = pjsip_tdata_get_sdp_info(tsx->last_tx);</span><br><span style="color: hsl(120, 100%, 40%);">++ reoffer_sdp = tdata_sdp_info->sdp;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Feed the original offer to negotiator */</span><br><span style="color: hsl(120, 100%, 40%);">+ status = pjmedia_sdp_neg_modify_local_offer2(inv->pool_prov, </span><br><span style="color: hsl(120, 100%, 40%);">+ inv->neg,</span><br><span style="color: hsl(120, 100%, 40%);">+ inv->sdp_neg_flags,</span><br><span style="color: hsl(120, 100%, 40%);">+ reoffer_sdp);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ if (status != PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_LOG(1,(inv->obj_name, "Error updating local offer for "</span><br><span style="color: hsl(120, 100%, 40%);">+ "forked 2xx/18x response (err=%d)", status));</span><br><span style="color: hsl(120, 100%, 40%);">+diff --git a/pjsip/src/test/inv_offer_answer_test.c b/pjsip/src/test/inv_offer_answer_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+index ad5fcd409..9cdd2654b 100644</span><br><span style="color: hsl(120, 100%, 40%);">+--- a/pjsip/src/test/inv_offer_answer_test.c</span><br><span>++++ b/pjsip/src/test/inv_offer_answer_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -137,6 +137,7 @@ typedef struct inv_test_param_t</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_bool_t need_established;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned count;</span><br><span style="color: hsl(120, 100%, 40%);">+ oa_t oa[4];</span><br><span style="color: hsl(120, 100%, 40%);">++ pj_bool_t multipart_body;</span><br><span style="color: hsl(120, 100%, 40%);">+ } inv_test_param_t;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ typedef struct inv_test_t</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -257,6 +258,17 @@ static void on_media_update(pjsip_inv_session *inv_ses,</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++ /* Special handling for standard offer/answer */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (inv_test.param.count == 1 &&</span><br><span style="color: hsl(120, 100%, 40%);">++ inv_test.param.oa[0] == OFFERER_UAC &&</span><br><span style="color: hsl(120, 100%, 40%);">++ inv_test.param.need_established)</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ jobs[job_cnt].type = ESTABLISH_CALL;</span><br><span style="color: hsl(120, 100%, 40%);">++ jobs[job_cnt].who = PJSIP_ROLE_UAS;</span><br><span style="color: hsl(120, 100%, 40%);">++ job_cnt++;</span><br><span style="color: hsl(120, 100%, 40%);">++ TRACE_((THIS_FILE, " C+++"));</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_assert(job_cnt <= PJ_ARRAY_SIZE(jobs));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -333,6 +345,15 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata)</span><br><span style="color: hsl(120, 100%, 40%);">+ NULL, &tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_assert(status == PJ_SUCCESS);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++ /* Use multipart body, if configured */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (sdp && inv_test.param.multipart_body) {</span><br><span style="color: hsl(120, 100%, 40%);">++ status = pjsip_create_multipart_sdp_body(</span><br><span style="color: hsl(120, 100%, 40%);">++ tdata->pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjmedia_sdp_session_clone(tdata->pool, sdp),</span><br><span style="color: hsl(120, 100%, 40%);">++ &tdata->msg->body);</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ pj_assert(status == PJ_SUCCESS);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ status = pjsip_inv_send_msg(inv_test.uas, tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+ pj_assert(status == PJ_SUCCESS);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+@@ -426,6 +447,7 @@ static int perform_test(inv_test_param_t *param)</span><br><span style="color: hsl(120, 100%, 40%);">+ sdp = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac);</span><br><span style="color: hsl(120, 100%, 40%);">++ //inv_test.uac->create_multipart = param->multipart_body;</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ TRACE_((THIS_FILE, " Sending INVITE %s offer", (sdp ? "with" : "without")));</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -436,8 +458,17 @@ static int perform_test(inv_test_param_t *param)</span><br><span style="color: hsl(120, 100%, 40%);">+ status = pjsip_inv_invite(inv_test.uac, &tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">++ /* Use multipart body, if configured */</span><br><span style="color: hsl(120, 100%, 40%);">++ if (sdp && param->multipart_body) {</span><br><span style="color: hsl(120, 100%, 40%);">++ status = pjsip_create_multipart_sdp_body(</span><br><span style="color: hsl(120, 100%, 40%);">++ tdata->pool,</span><br><span style="color: hsl(120, 100%, 40%);">++ pjmedia_sdp_session_clone(tdata->pool, sdp),</span><br><span style="color: hsl(120, 100%, 40%);">++ &tdata->msg->body);</span><br><span style="color: hsl(120, 100%, 40%);">++ }</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -40);</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">+ status = pjsip_inv_send_msg(inv_test.uac, tdata);</span><br><span style="color: hsl(120, 100%, 40%);">+- PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_ASSERT_RETURN(status==PJ_SUCCESS, -50);</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Wait until test completes</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -525,13 +556,14 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ 200/INVITE (answer) <--</span><br><span style="color: hsl(120, 100%, 40%);">+ ACK --></span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+-#if 0</span><br><span style="color: hsl(120, 100%, 40%);">++#if 1</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ "Standard INVITE with offer",</span><br><span style="color: hsl(120, 100%, 40%);">+ 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 1,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAC }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -539,7 +571,25 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSIP_INV_REQUIRE_100REL,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 1,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAC }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "Standard INVITE with offer, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ 0,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 1,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "Standard INVITE with offer, with 100rel, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ PJSIP_INV_REQUIRE_100REL,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 1,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ #endif</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+@@ -555,7 +605,8 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 1,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAS }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAS },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+@@ -563,7 +614,25 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSIP_INV_REQUIRE_100REL,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 1,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAS }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAS },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "INVITE with no offer, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ 0,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 1,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAS },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">++</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "INVITE with no offer, with 100rel, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ PJSIP_INV_REQUIRE_100REL,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 1,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAS },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ #endif</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+@@ -584,14 +653,24 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 2,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAC, OFFERER_UAC }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC, OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "INVITE and UPDATE by UAC, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ 0,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 2,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC, OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ {</span><br><span style="color: hsl(120, 100%, 40%);">+ "INVITE and UPDATE by UAC, with 100rel",</span><br><span style="color: hsl(120, 100%, 40%);">+ PJSIP_INV_REQUIRE_100REL,</span><br><span style="color: hsl(120, 100%, 40%);">+ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">+ 2,</span><br><span style="color: hsl(120, 100%, 40%);">+- { OFFERER_UAC, OFFERER_UAC }</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC, OFFERER_UAC },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_FALSE</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">+ #endif</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+@@ -617,6 +696,14 @@ static inv_test_param_t test_params[] =</span><br><span style="color: hsl(120, 100%, 40%);">+ 4,</span><br><span style="color: hsl(120, 100%, 40%);">+ { OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS }</span><br><span style="color: hsl(120, 100%, 40%);">+ },</span><br><span style="color: hsl(120, 100%, 40%);">++ {</span><br><span style="color: hsl(120, 100%, 40%);">++ "INVITE and many UPDATE by UAC and UAS, with Multipart",</span><br><span style="color: hsl(120, 100%, 40%);">++ 0,</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE,</span><br><span style="color: hsl(120, 100%, 40%);">++ 4,</span><br><span style="color: hsl(120, 100%, 40%);">++ { OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS },</span><br><span style="color: hsl(120, 100%, 40%);">++ PJ_TRUE</span><br><span style="color: hsl(120, 100%, 40%);">++ },</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+-- </span><br><span style="color: hsl(120, 100%, 40%);">+2.33.1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/17733">change 17733</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/17733"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I483c7c3d413280c9e247a96ad581278347f9c71b </div>
<div style="display:none"> Gerrit-Change-Number: 17733 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>