<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/17733">View Change</a></p><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;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/33/17733/1</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><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-MessageType: newchange </div>