[Asterisk-code-review] pjproject: Update bundled to 2.12 release. (asterisk[master])

Joshua Colp asteriskteam at digium.com
Mon Feb 28 08:39:40 CST 2022


Joshua Colp has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/18114 )


Change subject: pjproject: Update bundled to 2.12 release.
......................................................................

pjproject: Update bundled to 2.12 release.

ASTERISK-29351

Change-Id: Id39ece02dedb7b9f739e0e37ea47d76854af7191
---
M third-party/pjproject/patches/0000-configure-ssl-library-path.patch
M third-party/pjproject/patches/0000-remove-third-party.patch
D third-party/pjproject/patches/0000-set_apps_initial_log_level.patch
D third-party/pjproject/patches/0000-solaris.patch
D third-party/pjproject/patches/0011-sip_inv_patch.patch
D third-party/pjproject/patches/0020-pjlib_cancel_timer_0.patch
D third-party/pjproject/patches/0050-fix-race-parallel-build.patch
D third-party/pjproject/patches/0060-clone-sdp-for-sip-timer-refresh-invite.patch
D third-party/pjproject/patches/0070-fix-incorrect-copying-when-creating-cancel.patch
D third-party/pjproject/patches/0080-fix-sdp-neg-modify-local-offer.patch
D third-party/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch
D third-party/pjproject/patches/0100-fix-double-stun-free.patch
D third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch
D third-party/pjproject/patches/0111-ssl-premature-destroy.patch
D third-party/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch
D third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch
D third-party/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch
D third-party/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch
D third-party/pjproject/patches/0160-Additional-multipart-improvements.patch
D third-party/pjproject/pjproject-2.10.tar.bz2.md5
A third-party/pjproject/pjproject-2.12.tar.bz2.md5
M third-party/versions.mak
22 files changed, 27 insertions(+), 2,708 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/14/18114/1

diff --git a/third-party/pjproject/patches/0000-configure-ssl-library-path.patch b/third-party/pjproject/patches/0000-configure-ssl-library-path.patch
index 3c1f749..c4dbb49 100644
--- a/third-party/pjproject/patches/0000-configure-ssl-library-path.patch
+++ b/third-party/pjproject/patches/0000-configure-ssl-library-path.patch
@@ -1,19 +1,9 @@
-From e8000cc80e5f8ba02cc52852edc02cdb0e949525 Mon Sep 17 00:00:00 2001
-From: Richard Mudgett <rmudgett at digium.com>
-Date: Mon, 6 Aug 2018 11:24:25 -0500
-Subject: [PATCH 1/5] 0000-configure-ssl-library-path.patch
-
----
- aconfigure    | 6 +++++-
- aconfigure.ac | 6 +++++-
- 2 files changed, 10 insertions(+), 2 deletions(-)
-
 diff --git a/aconfigure b/aconfigure
-index 1c449b8..c4c6060 100755
+index d6f0e8809..9dcd46398 100755
 --- a/aconfigure
 +++ b/aconfigure
-@@ -7954,7 +7954,11 @@ else
-                 if test "x$with_ssl" != "xno" -a "x$with_ssl" != "x"; then
+@@ -8986,7 +8986,11 @@ else $as_nop
+ 	        if test "x$with_ssl" != "xno" -a "x$with_ssl" != "x"; then
                      CFLAGS="$CFLAGS -I$with_ssl/include"
                      CPPFLAGS="$CPPFLAGS -I$with_ssl/include"
 -                    LDFLAGS="$LDFLAGS -L$with_ssl/lib"
@@ -22,15 +12,15 @@
 +                    else
 +                        LDFLAGS="$LDFLAGS -L$with_ssl"
 +                    fi
-                     { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using SSL prefix... $with_ssl" >&5
- $as_echo "Using SSL prefix... $with_ssl" >&6; }
+                     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using SSL prefix... $with_ssl" >&5
+ printf "%s\n" "Using SSL prefix... $with_ssl" >&6; }
                  fi
 diff --git a/aconfigure.ac b/aconfigure.ac
-index 2c272cd..a5d6d97 100644
+index 16b311045..849da81ab 100644
 --- a/aconfigure.ac
 +++ b/aconfigure.ac
-@@ -1580,7 +1580,11 @@ AC_ARG_ENABLE(ssl,
-                 if test "x$with_ssl" != "xno" -a "x$with_ssl" != "x"; then
+@@ -1838,7 +1838,11 @@ AC_ARG_ENABLE(ssl,
+ 	        if test "x$with_ssl" != "xno" -a "x$with_ssl" != "x"; then
                      CFLAGS="$CFLAGS -I$with_ssl/include"
                      CPPFLAGS="$CPPFLAGS -I$with_ssl/include"
 -                    LDFLAGS="$LDFLAGS -L$with_ssl/lib"
@@ -42,6 +32,3 @@
                      AC_MSG_RESULT([Using SSL prefix... $with_ssl])
                  fi
  
--- 
-2.7.4
-
diff --git a/third-party/pjproject/patches/0000-remove-third-party.patch b/third-party/pjproject/patches/0000-remove-third-party.patch
index f25aeac..1de154d 100644
--- a/third-party/pjproject/patches/0000-remove-third-party.patch
+++ b/third-party/pjproject/patches/0000-remove-third-party.patch
@@ -1,14 +1,5 @@
-From 665a2fbc3a09a71cd77988ae2deb3f5d3e205f63 Mon Sep 17 00:00:00 2001
-From: Richard Mudgett <rmudgett at digium.com>
-Date: Thu, 23 Feb 2017 17:10:07 -0600
-Subject: [PATCH 2/5] 0000-remove-third-party.patch
-
----
- build.mak.in | 97 ------------------------------------------------------------
- 1 file changed, 97 deletions(-)
-
 diff --git a/build.mak.in b/build.mak.in
-index 80ccad1..41ec64e 100644
+index 4bc464f8c..80681d961 100644
 --- a/build.mak.in
 +++ b/build.mak.in
 @@ -1,4 +1,3 @@
@@ -16,7 +7,7 @@
  include $(PJDIR)/version.mak
  export PJ_DIR := $(PJDIR)
  
-@@ -37,19 +36,6 @@ export APP_THIRD_PARTY_EXT :=
+@@ -41,19 +40,6 @@ export APP_THIRD_PARTY_EXT :=
  export APP_THIRD_PARTY_LIBS :=
  export APP_THIRD_PARTY_LIB_FILES :=
  
@@ -36,7 +27,7 @@
  ifeq (@ac_pjmedia_resample@,libresample)
  APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libresample-$(LIB_SUFFIX)
  ifeq ($(PJ_SHARED_LIBRARIES),)
-@@ -66,89 +52,6 @@ APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFI
+@@ -70,102 +56,6 @@ APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFI
  endif
  endif
  
@@ -122,10 +113,20 @@
 -endif
 -endif
 -
+-ifneq (@ac_no_webrtc_aec3@,1)
+-ifeq (@ac_external_webrtc_aec3@,1)
+-APP_THIRD_PARTY_EXT += -lwebrtc-aec3
+-else
+-APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libwebrtc-aec3-$(LIB_SUFFIX)
+-ifeq ($(PJ_SHARED_LIBRARIES),)
+-APP_THIRD_PARTY_LIBS += -lwebrtc-aec3-$(TARGET_NAME)
+-else
+-APP_THIRD_PARTY_LIBS += -lwebrtc-aec3
+-APP_THIRD_PARTY_LIB_FILES += $(PJ_DIR)/third_party/lib/libwebrtc-aec3.$(SHLIB_SUFFIX).$(PJ_VERSION_MAJOR) $(PJ_DIR)/third_party/lib/libwebrtc.$(SHLIB_SUFFIX)
+-endif
+-endif
+-endif
 -
+
  # Additional flags
  @ac_build_mak_vars@
- 
--- 
-2.7.4
-
diff --git a/third-party/pjproject/patches/0000-set_apps_initial_log_level.patch b/third-party/pjproject/patches/0000-set_apps_initial_log_level.patch
deleted file mode 100644
index b1fe02c..0000000
--- a/third-party/pjproject/patches/0000-set_apps_initial_log_level.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From c40ad6ba454fdf6456d8ffa92faa4cd49f2c807d Mon Sep 17 00:00:00 2001
-From: Richard Mudgett <rmudgett at digium.com>
-Date: Thu, 23 Feb 2017 17:11:00 -0600
-Subject: [PATCH 3/5] 0000-set_apps_initial_log_level.patch
-
----
- pjsip-apps/src/pjsua/main.c             | 2 ++
- pjsip-apps/src/pjsystest/main_console.c | 2 ++
- pjsip-apps/src/python/_pjsua.c          | 3 ++-
- 3 files changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/pjsip-apps/src/pjsua/main.c b/pjsip-apps/src/pjsua/main.c
-index 2baaf82..11831f2 100644
---- a/pjsip-apps/src/pjsua/main.c
-+++ b/pjsip-apps/src/pjsua/main.c
-@@ -126,5 +126,7 @@ int main_func(int argc, char *argv[])
- 
- int main(int argc, char *argv[])
- {
-+    pj_log_set_level(1);
-+
-     return pj_run_app(&main_func, argc, argv, 0);
- }
-diff --git a/pjsip-apps/src/pjsystest/main_console.c b/pjsip-apps/src/pjsystest/main_console.c
-index 122cdc7..dc79eab 100644
---- a/pjsip-apps/src/pjsystest/main_console.c
-+++ b/pjsip-apps/src/pjsystest/main_console.c
-@@ -133,6 +133,8 @@ void gui_sleep(unsigned sec)
- 
- int main()
- {
-+    pj_log_set_level(1);
-+
-     if (systest_init() != PJ_SUCCESS)
- 	return 1;
- 
-diff --git a/pjsip-apps/src/python/_pjsua.c b/pjsip-apps/src/python/_pjsua.c
-index 31b835e..3e15030 100644
---- a/pjsip-apps/src/python/_pjsua.c
-+++ b/pjsip-apps/src/python/_pjsua.c
-@@ -4434,7 +4434,8 @@ init_pjsua(void)
-     PyObject* m = NULL;
- #define ADD_CONSTANT(mod,name)	PyModule_AddIntConstant(mod,#name,name)
- 
--    
-+    pj_log_set_level(1);
-+
-     PyEval_InitThreads();
- 
-     if (PyType_Ready(&PyTyp_pjsua_callback) < 0)
--- 
-2.7.4
-
diff --git a/third-party/pjproject/patches/0000-solaris.patch b/third-party/pjproject/patches/0000-solaris.patch
deleted file mode 100644
index 155cdbe..0000000
--- a/third-party/pjproject/patches/0000-solaris.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-From 1ac599a0f29500a15faf0dbbdc2565cc7dce2420 Mon Sep 17 00:00:00 2001
-From: Shaun Ruffell <sruffell at digium.com>
-Date: Fri, 7 Sep 2012 14:31:19 -0500
-Subject: [PATCH 4/5] pjproject: Fix for Solaris builds. Do not undef s_addr.
-
-pjproject, in order to solve build problems on Windows [1], undefines s_addr in
-one of it's headers that is included in res_rtp_asterisk.c. On Solaris s_addr is
-not a structure member, but defined to map to the real strucuture member,
-therefore when building on Solaris it's possible to get build errors like:
-
-    [CC] res_rtp_asterisk.c -> res_rtp_asterisk.o
-    In file included from /export/home/admin/asterisk-11-svn/include/asterisk/stun.h:29,
-                     from res_rtp_asterisk.c:51:
-    /export/home/admin/asterisk-11-svn/include/asterisk/network.h: In function `inaddrcmp':
-    /export/home/admin/asterisk-11-svn/include/asterisk/network.h:92: error: structure has no member named `s_addr'
-    /export/home/admin/asterisk-11-svn/include/asterisk/network.h:92: error: structure has no member named `s_addr'
-    res_rtp_asterisk.c: In function `ast_rtp_on_ice_tx_pkt':
-    res_rtp_asterisk.c:706: warning: dereferencing type-punned pointer will break strict-aliasing rules
-    res_rtp_asterisk.c:710: warning: dereferencing type-punned pointer will break strict-aliasing rules
-    res_rtp_asterisk.c: In function `rtp_add_candidates_to_ice':
-    res_rtp_asterisk.c:1085: error: structure has no member named `s_addr'
-    make[2]: *** [res_rtp_asterisk.o] Error 1
-    make[1]: *** [res] Error 2
-    make[1]: Leaving directory `/export/home/admin/asterisk-11-svn'
-    gmake: *** [_cleantest_all] Error 2
-
-Unfortunately, in order to make this work, I also had to make sure pjproject
-only used the typdef pj_in_addr and not the struct pj_in_addr so that when
-building Asterisk I could "typedef struct in_addr pj_in_addr". It's possible
-then that the library and users of those interfaces in Asterisk have a different
-idea about the type of the argument. While on the surface it looks like they are
-all 32 bit big endian values.
-
-[1] http://trac.pjsip.org/repos/changeset/484
-
-Reported-by: Ben Klang
-(issues ASTERISK-20366)
-
-Updated by ASTERISK-27997
----
- pjlib/include/pj/sock.h         | 8 +++++++-
- pjlib/src/pj/sock_bsd.c         | 2 +-
- pjlib/src/pj/sock_symbian.cpp   | 2 +-
- pjlib/src/pj/sock_uwp.cpp       | 2 +-
- pjsip/src/test/transport_test.c | 2 +-
- 5 files changed, 11 insertions(+), 5 deletions(-)
-
-diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
-index 4daf298..c35833c 100644
---- a/pjlib/include/pj/sock.h
-+++ b/pjlib/include/pj/sock.h
-@@ -484,6 +484,7 @@ typedef enum pj_socket_sd_type
-  */
- #define PJ_INVALID_SOCKET   (-1)
- 
-+#ifndef _ASTERISK_H
- /* Must undefine s_addr because of pj_in_addr below */
- #undef s_addr
- 
-@@ -495,6 +496,11 @@ typedef struct pj_in_addr
-     pj_uint32_t	s_addr;		/**< The 32bit IP address.	    */
- } pj_in_addr;
- 
-+#else
-+#include <sys/types.h>
-+#include <netinet/in.h>
-+typedef struct in_addr pj_in_addr;
-+#endif
- 
- /**
-  * Maximum length of text representation of an IPv4 address.
-@@ -712,7 +718,7 @@ PJ_DECL(char*) pj_inet_ntoa(pj_in_addr inaddr);
-  *
-  * @return	nonzero if the address is valid, zero if not.
-  */
--PJ_DECL(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp);
-+PJ_DECL(int) pj_inet_aton(const pj_str_t *cp, pj_in_addr *inp);
- 
- /**
-  * This function converts an address in its standard text presentation form
-diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c
-index e416991..940fce1 100644
---- a/pjlib/src/pj/sock_bsd.c
-+++ b/pjlib/src/pj/sock_bsd.c
-@@ -244,7 +244,7 @@ PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
-  * numbers-and-dots notation into binary data and stores it in the structure
-  * that inp points to. 
-  */
--PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
-+PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, pj_in_addr *inp)
- {
-     char tempaddr[PJ_INET_ADDRSTRLEN];
- 
-diff --git a/pjlib/src/pj/sock_symbian.cpp b/pjlib/src/pj/sock_symbian.cpp
-index 09239b0..e72bbda 100644
---- a/pjlib/src/pj/sock_symbian.cpp
-+++ b/pjlib/src/pj/sock_symbian.cpp
-@@ -299,7 +299,7 @@ PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
-  * numbers-and-dots notation into binary data and stores it in the structure
-  * that inp points to. 
-  */
--PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
-+PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, pj_in_addr *inp)
- {
-     enum { MAXIPLEN = PJ_INET_ADDRSTRLEN };
- 
-diff --git a/pjlib/src/pj/sock_uwp.cpp b/pjlib/src/pj/sock_uwp.cpp
-index 876c328..40250bf 100644
---- a/pjlib/src/pj/sock_uwp.cpp
-+++ b/pjlib/src/pj/sock_uwp.cpp
-@@ -933,7 +933,7 @@ PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
-  * numbers-and-dots notation into binary data and stores it in the structure
-  * that inp points to. 
-  */
--PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
-+PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, pj_in_addr *inp)
- {
-     char tempaddr[PJ_INET_ADDRSTRLEN];
- 
-diff --git a/pjsip/src/test/transport_test.c b/pjsip/src/test/transport_test.c
-index e5083d1..c429cc7 100644
---- a/pjsip/src/test/transport_test.c
-+++ b/pjsip/src/test/transport_test.c
-@@ -35,7 +35,7 @@ int generic_transport_test(pjsip_transport *tp)
- 
-     /* Check that local address name is valid. */
-     {
--	struct pj_in_addr addr;
-+	pj_in_addr addr;
- 
- 	if (pj_inet_pton(pj_AF_INET(), &tp->local_name.host,
- 			 &addr) == PJ_SUCCESS)
--- 
-2.7.4
-
diff --git a/third-party/pjproject/patches/0011-sip_inv_patch.patch b/third-party/pjproject/patches/0011-sip_inv_patch.patch
deleted file mode 100644
index 7f77c74..0000000
--- a/third-party/pjproject/patches/0011-sip_inv_patch.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-commit c3c1bf45cae2a35003aa16c267d59f97027f9c5e
-Author: Kevin Harwell <kharwell at digium.com>
-Date:   Thu Jun 11 11:11:13 2020 -0500
-
-    sip_inv - fix invite session ref count crash
-    
-    Ensure the session's ref count is only decremented under proper conditons.
-    
-    For more details see the following issue report:
-    https://github.com/pjsip/pjproject/issues/2443
-    
-    Patch supplied by sauwming
-
-diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
-index ca225015b..7c11b1c8e 100644
---- a/pjsip/src/pjsip-ua/sip_inv.c
-+++ b/pjsip/src/pjsip-ua/sip_inv.c
-@@ -323,9 +323,19 @@ static void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
- 	(*mod_inv.cb.on_state_changed)(inv, e);
-     pjsip_inv_dec_ref(inv);
- 
--    /* Only decrement when previous state is not already DISCONNECTED */
-+    /* The above callback may change the state, so we need to be careful here
-+     * and only decrement inv under the following conditions:
-+     * 1. If the state parameter is DISCONNECTED, and previous state is not
-+     *    already DISCONNECTED.
-+     *    This is to make sure that dec_ref() is not called more than once.
-+     * 2. If current state is PJSIP_INV_STATE_DISCONNECTED.
-+     *    This is to make sure that dec_ref() is not called if user restarts
-+     *    inv within the callback. Note that this check must be last since
-+     *    inv may have already been destroyed.
-+     */
-     if (state == PJSIP_INV_STATE_DISCONNECTED &&
--	prev_state != PJSIP_INV_STATE_DISCONNECTED) 
-+	prev_state != PJSIP_INV_STATE_DISCONNECTED &&
-+	inv->state == PJSIP_INV_STATE_DISCONNECTED) 
-     {
- 	pjsip_inv_dec_ref(inv);
-     }
diff --git a/third-party/pjproject/patches/0020-pjlib_cancel_timer_0.patch b/third-party/pjproject/patches/0020-pjlib_cancel_timer_0.patch
deleted file mode 100644
index 09f72d8..0000000
--- a/third-party/pjproject/patches/0020-pjlib_cancel_timer_0.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-commit 40dd48d10911f4ff9b8dfbf16428fbc9acc434ba
-Author: Riza Sulistyo <trengginas at users.noreply.github.com>
-Date:   Thu Jul 9 17:47:24 2020 +0700
-
-    Modify timer_id check on cancel() (#2463)
-    
-    * modify timer_id check on cancel().
-    
-    * modification based on comments.
-
-diff --git a/pjlib/include/pj/timer.h b/pjlib/include/pj/timer.h
-index b738a6e76..4b76ab65d 100644
---- a/pjlib/include/pj/timer.h
-+++ b/pjlib/include/pj/timer.h
-@@ -120,7 +120,10 @@ typedef struct pj_timer_entry
- 
-     /** 
-      * Internal unique timer ID, which is assigned by the timer heap. 
--     * Application should not touch this ID.
-+     * Positive values indicate that the timer entry is running, 
-+     * while -1 means that it's not. Any other value may indicate that it 
-+     * hasn't been properly initialised or is in a bad state.
-+     * Application should not touch this ID. 
-      */
-     pj_timer_id_t _timer_id;
- 
-diff --git a/pjlib/src/pj/timer.c b/pjlib/src/pj/timer.c
-index 66516fce8..34966c481 100644
---- a/pjlib/src/pj/timer.c
-+++ b/pjlib/src/pj/timer.c
-@@ -535,7 +535,7 @@ static int cancel( pj_timer_heap_t *ht,
-     PJ_CHECK_STACK();
- 
-     // Check to see if the timer_id is out of range
--    if (entry->_timer_id < 0 || (pj_size_t)entry->_timer_id > ht->max_size) {
-+    if (entry->_timer_id < 1 || (pj_size_t)entry->_timer_id >= ht->max_size) {
- 	entry->_timer_id = -1;
-     	return 0;
-     }
diff --git a/third-party/pjproject/patches/0050-fix-race-parallel-build.patch b/third-party/pjproject/patches/0050-fix-race-parallel-build.patch
deleted file mode 100644
index 674baa2..0000000
--- a/third-party/pjproject/patches/0050-fix-race-parallel-build.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From 78683646c8bc670ec730a42494e075f671a08e28 Mon Sep 17 00:00:00 2001
-From: Guido Falsi <mad at madpilot.net>
-Date: Mon, 11 May 2020 08:50:39 +0200
-Subject: [PATCH] Fix race condition in parallel builds (#2426)
-
-* Some targets residing in `OBJDIRS` are missing a dependency on that directory, which results in a race condition, causing build to fail sometimes due to the directory not existing when running parallel builds.
-
-* The `PJSUA_LIB` variable is not defined anywhere, resulting in an empty value, and no correct dependency on the pjsua shared library for `pjsua2`. The correct variable seems to be `PJSUA_LIB_LIB`, defined at the start of this same `Makefile`.
----
- build/rules.mak      | 12 ++++++------
- pjsip/build/Makefile |  2 +-
- 2 files changed, 7 insertions(+), 7 deletions(-)
-
-diff --git a/build/rules.mak b/build/rules.mak
-index 8fa98655e..912199c41 100644
---- a/build/rules.mak
-+++ b/build/rules.mak
-@@ -129,7 +129,7 @@ endif
- $(OBJDIR)/$(app).o: $(OBJDIRS) $(OBJS)
- 	$(CROSS_COMPILE)ld -r -o $@ $(OBJS)
- 
--$(OBJDIR)/$(app).ko: $(OBJDIR)/$(app).o
-+$(OBJDIR)/$(app).ko: $(OBJDIR)/$(app).o | $(OBJDIRS)
- 	@echo Creating kbuild Makefile...
- 	@echo "# Our module name:" > $(OBJDIR)/Makefile
- 	@echo 'obj-m += $(app).o' >> $(OBJDIR)/Makefile
-@@ -154,27 +154,27 @@ $(OBJDIR)/$(app).ko: $(OBJDIR)/$(app).o
- ../lib/$(app).ko: $(LIB) $(OBJDIR)/$(app).ko
- 	cp $(OBJDIR)/$(app).ko ../lib
- 
--$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.m
-+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.m | $(OBJDIRS)
- 	$(CC) $($(APP)_CFLAGS) \
- 		$(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
- 		$(subst /,$(HOST_PSEP),$<) 
- 
--$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.c
-+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.c | $(OBJDIRS)
- 	$(CC) $($(APP)_CFLAGS) \
- 		$(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
- 		$(subst /,$(HOST_PSEP),$<) 
- 
--$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.S
-+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.S | $(OBJDIRS)
- 	$(CC) $($(APP)_CFLAGS) \
- 		$(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
- 		$(subst /,$(HOST_PSEP),$<) 
- 
--$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.cpp
-+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.cpp | $(OBJDIRS)
- 	$(CXX) $($(APP)_CXXFLAGS) \
- 		$(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
- 		$(subst /,$(HOST_PSEP),$<)
- 
--$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.cc
-+$(OBJDIR)/%$(OBJEXT): $(SRCDIR)/%.cc | $(OBJDIRS)
- 	$(CXX) $($(APP)_CXXFLAGS) \
- 		$(CC_OUT)$(subst /,$(HOST_PSEP),$@) \
- 		$(subst /,$(HOST_PSEP),$<)
-diff --git a/pjsip/build/Makefile b/pjsip/build/Makefile
-index b85c7817a..20777909f 100644
---- a/pjsip/build/Makefile
-+++ b/pjsip/build/Makefile
-@@ -262,7 +262,7 @@ $(PJSUA_LIB_LIB) $(PJSUA_LIB_SONAME): $(PJSIP_LIB) $(PJSIP_SONAME) $(PJSIP_SIMPL
- 
- pjsua2-lib: $(PJSUA2_LIB_LIB)
- $(PJSUA2_LIB_SONAME): $(PJSUA2_LIB_LIB)
--$(PJSUA2_LIB_LIB) $(PJSUA2_LIB_SONAME): $(PJSUA_LIB) $(PSJUA_LIB_SONAME) $(PJSIP_LIB) $(PJSIP_SONAME) $(PJSIP_SIMPLE_LIB) $(PJSIP_SIMPLE_SONAME) $(PJSIP_UA_LIB) $(PJSIP_UA_SONAME)
-+$(PJSUA2_LIB_LIB) $(PJSUA2_LIB_SONAME): $(PJSUA_LIB_LIB) $(PJSUA_LIB_SONAME) $(PJSIP_LIB) $(PJSIP_SONAME) $(PJSIP_SIMPLE_LIB) $(PJSIP_SIMPLE_SONAME) $(PJSIP_UA_LIB) $(PJSIP_UA_SONAME)
- 	$(MAKE) -f $(RULES_MAK) APP=PJSUA2_LIB app=pjsua2-lib $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
- 
- pjsip-test: $(TEST_EXE)
diff --git a/third-party/pjproject/patches/0060-clone-sdp-for-sip-timer-refresh-invite.patch b/third-party/pjproject/patches/0060-clone-sdp-for-sip-timer-refresh-invite.patch
deleted file mode 100644
index f1f180a..0000000
--- a/third-party/pjproject/patches/0060-clone-sdp-for-sip-timer-refresh-invite.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-diff -ur source.orig/pjmedia/src/pjmedia/sdp_neg.c source/pjmedia/src/pjmedia/sdp_neg.c
---- source.orig/pjmedia/src/pjmedia/sdp_neg.c	2020-07-02 10:35:42.022459904 +0200
-+++ source/pjmedia/src/pjmedia/sdp_neg.c	2020-07-02 10:33:24.996316867 +0200
-@@ -906,7 +906,7 @@
-  * after receiving remote answer.
-  */
- static pj_status_t process_answer(pj_pool_t *pool,
--				  pjmedia_sdp_session *offer,
-+				  pjmedia_sdp_session *local_offer,
- 				  pjmedia_sdp_session *answer,
- 				  pj_bool_t allow_asym,
- 				  pjmedia_sdp_session **p_active)
-@@ -914,10 +914,14 @@
-     unsigned omi = 0; /* Offer media index */
-     unsigned ami = 0; /* Answer media index */
-     pj_bool_t has_active = PJ_FALSE;
-+    pjmedia_sdp_session *offer;
-     pj_status_t status;
- 
-     /* Check arguments. */
--    PJ_ASSERT_RETURN(pool && offer && answer && p_active, PJ_EINVAL);
-+    PJ_ASSERT_RETURN(pool && local_offer && answer && p_active, PJ_EINVAL);
-+
-+    /* Duplicate local offer SDP. */
-+    offer = pjmedia_sdp_session_clone(pool, local_offer);
- 
-     /* Check that media count match between offer and answer */
-     // Ticket #527, different media count is allowed for more interoperability,
diff --git a/third-party/pjproject/patches/0070-fix-incorrect-copying-when-creating-cancel.patch b/third-party/pjproject/patches/0070-fix-incorrect-copying-when-creating-cancel.patch
deleted file mode 100644
index 95725c1..0000000
--- a/third-party/pjproject/patches/0070-fix-incorrect-copying-when-creating-cancel.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From ce18018cc17bef8f80c08686e3a7b28384ef3ba5 Mon Sep 17 00:00:00 2001
-From: sauwming <ming at teluu.com>
-Date: Mon, 12 Oct 2020 13:31:25 +0800
-Subject: [PATCH] Fix incorrect copying of destination info when creating
- CANCEL (#2546)
-
----
- pjsip/src/pjsip/sip_util.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
-diff --git a/pjsip/src/pjsip/sip_util.c b/pjsip/src/pjsip/sip_util.c
-index d10a6fa30..a1bf878ea 100644
---- a/pjsip/src/pjsip/sip_util.c
-+++ b/pjsip/src/pjsip/sip_util.c
-@@ -779,14 +779,14 @@ PJ_DEF(pj_status_t) pjsip_endpt_create_cancel( pjsip_endpoint *endpt,
- 	    pjsip_hdr_clone(cancel_tdata->pool, req_tdata->saved_strict_route);
-     }
- 
--    /* Copy the destination host name from the original request */
--    pj_strdup(cancel_tdata->pool, &cancel_tdata->dest_info.name,
--	      &req_tdata->dest_info.name);
--
--    /* Finally copy the destination info from the original request */
-+    /* Copy the destination info from the original request */
-     pj_memcpy(&cancel_tdata->dest_info, &req_tdata->dest_info,
- 	      sizeof(req_tdata->dest_info));
- 
-+    /* Finally, copy the destination host name from the original request */
-+    pj_strdup(cancel_tdata->pool, &cancel_tdata->dest_info.name,
-+	      &req_tdata->dest_info.name);
-+
-     /* Done.
-      * Return the transmit buffer containing the CANCEL request.
-      */
--- 
-2.25.1
-
diff --git a/third-party/pjproject/patches/0080-fix-sdp-neg-modify-local-offer.patch b/third-party/pjproject/patches/0080-fix-sdp-neg-modify-local-offer.patch
deleted file mode 100644
index c27a489..0000000
--- a/third-party/pjproject/patches/0080-fix-sdp-neg-modify-local-offer.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-diff --git a/pjmedia/src/pjmedia/sdp_neg.c b/pjmedia/src/pjmedia/sdp_neg.c
-index 3b85b4273..a14009662 100644
---- a/pjmedia/src/pjmedia/sdp_neg.c
-+++ b/pjmedia/src/pjmedia/sdp_neg.c
-@@ -304,7 +304,6 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_modify_local_offer2(
- {
-     pjmedia_sdp_session *new_offer;
-     pjmedia_sdp_session *old_offer;
--    char media_used[PJMEDIA_MAX_SDP_MEDIA];
-     unsigned oi; /* old offer media index */
-     pj_status_t status;
- 
-@@ -323,8 +322,19 @@ PJ_DEF(pj_status_t) pjmedia_sdp_neg_modify_local_offer2(
-     /* Change state to STATE_LOCAL_OFFER */
-     neg->state = PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER;
- 
-+    /* When there is no active local SDP in state PJMEDIA_SDP_NEG_STATE_DONE,
-+     * it means that the previous initial SDP nego must have been failed,
-+     * so we'll just set the local SDP offer here.
-+     */
-+    if (!neg->active_local_sdp) {
-+	neg->initial_sdp_tmp = NULL;
-+	neg->initial_sdp = pjmedia_sdp_session_clone(pool, local);
-+	neg->neg_local_sdp = pjmedia_sdp_session_clone(pool, local);
-+
-+	return PJ_SUCCESS;
-+    }
-+
-     /* Init vars */
--    pj_bzero(media_used, sizeof(media_used));
-     old_offer = neg->active_local_sdp;
-     new_offer = pjmedia_sdp_session_clone(pool, local);
- 
diff --git a/third-party/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch b/third-party/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch
deleted file mode 100644
index a2db220..0000000
--- a/third-party/pjproject/patches/0090-Skip-unsupported-digest-algorithm-2408.patch
+++ /dev/null
@@ -1,212 +0,0 @@
-From bdbeb7c4b2b11efc2e59f5dee7aa4360a2bc9fff Mon Sep 17 00:00:00 2001
-From: sauwming <ming at teluu.com>
-Date: Thu, 22 Apr 2021 14:03:28 +0800
-Subject: [PATCH 90/90] Skip unsupported digest algorithm (#2408)
-
-Co-authored-by: Nanang Izzuddin <nanang at teluu.com>
----
- pjsip/src/pjsip/sip_auth_client.c             | 32 +++++--
- tests/pjsua/scripts-sipp/uas-auth-two-algo.py |  7 ++
- .../pjsua/scripts-sipp/uas-auth-two-algo.xml  | 83 +++++++++++++++++++
- 3 files changed, 117 insertions(+), 5 deletions(-)
- create mode 100644 tests/pjsua/scripts-sipp/uas-auth-two-algo.py
- create mode 100644 tests/pjsua/scripts-sipp/uas-auth-two-algo.xml
-
-diff --git a/pjsip/src/pjsip/sip_auth_client.c b/pjsip/src/pjsip/sip_auth_client.c
-index 828b04db9..7eb2f5cd1 100644
---- a/pjsip/src/pjsip/sip_auth_client.c
-+++ b/pjsip/src/pjsip/sip_auth_client.c
-@@ -1042,7 +1042,7 @@ static pj_status_t process_auth( pj_pool_t *req_pool,
-     pjsip_hdr *hdr;
-     pj_status_t status;
- 
--    /* See if we have sent authorization header for this realm */
-+    /* See if we have sent authorization header for this realm (and scheme) */
-     hdr = tdata->msg->hdr.next;
-     while (hdr != &tdata->msg->hdr) {
- 	if ((hchal->type == PJSIP_H_WWW_AUTHENTICATE &&
-@@ -1052,7 +1052,8 @@ static pj_status_t process_auth( pj_pool_t *req_pool,
- 	{
- 	    sent_auth = (pjsip_authorization_hdr*) hdr;
- 	    if (pj_stricmp(&hchal->challenge.common.realm,
--			   &sent_auth->credential.common.realm )==0)
-+			   &sent_auth->credential.common.realm)==0 &&
-+		pj_stricmp(&hchal->scheme, &sent_auth->scheme)==0)
- 	    {
- 		/* If this authorization has empty response, remove it. */
- 		if (pj_stricmp(&sent_auth->scheme, &pjsip_DIGEST_STR)==0 &&
-@@ -1062,6 +1063,14 @@ static pj_status_t process_auth( pj_pool_t *req_pool,
- 		    hdr = hdr->next;
- 		    pj_list_erase(sent_auth);
- 		    continue;
-+		} else
-+		if (pj_stricmp(&sent_auth->scheme, &pjsip_DIGEST_STR)==0 &&
-+		    pj_stricmp(&sent_auth->credential.digest.algorithm,
-+		               &hchal->challenge.digest.algorithm)!=0)
-+		{
-+		    /* Same 'digest' scheme but different algo */
-+		    hdr = hdr->next;
-+		    continue;
- 		} else {
- 		    /* Found previous authorization attempt */
- 		    break;
-@@ -1155,9 +1164,10 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
- {
-     pjsip_tx_data *tdata;
-     const pjsip_hdr *hdr;
--    unsigned chal_cnt;
-+    unsigned chal_cnt, auth_cnt;
-     pjsip_via_hdr *via;
-     pj_status_t status;
-+    pj_status_t last_auth_err;
- 
-     PJ_ASSERT_RETURN(sess && rdata && old_request && new_request,
- 		     PJ_EINVAL);
-@@ -1178,6 +1188,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
-      */
-     hdr = rdata->msg_info.msg->hdr.next;
-     chal_cnt = 0;
-+    auth_cnt = 0;
-+    last_auth_err = PJSIP_EAUTHNOAUTH;
-     while (hdr != &rdata->msg_info.msg->hdr) {
- 	pjsip_cached_auth *cached_auth;
- 	const pjsip_www_authenticate_hdr *hchal;
-@@ -1222,8 +1234,13 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
- 	 */
- 	status = process_auth(tdata->pool, hchal, tdata->msg->line.req.uri,
- 			      tdata, sess, cached_auth, &hauth);
--	if (status != PJ_SUCCESS)
--	    return status;
-+	if (status != PJ_SUCCESS) {
-+	    last_auth_err = status;
-+
-+	    /* Process next header. */
-+	    hdr = hdr->next;
-+	    continue;
-+	}
- 
- 	if (pj_pool_get_used_size(cached_auth->pool) >
- 	    PJSIP_AUTH_CACHED_POOL_MAX_SIZE) 
-@@ -1236,12 +1253,17 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req(	pjsip_auth_clt_sess *sess,
- 
- 	/* Process next header. */
- 	hdr = hdr->next;
-+	auth_cnt++;
-     }
- 
-     /* Check if challenge is present */
-     if (chal_cnt == 0)
- 	return PJSIP_EAUTHNOCHAL;
- 
-+    /* Check if any authorization header has been created */
-+    if (auth_cnt == 0)
-+	return last_auth_err;
-+
-     /* Remove branch param in Via header. */
-     via = (pjsip_via_hdr*) pjsip_msg_find_hdr(tdata->msg, PJSIP_H_VIA, NULL);
-     via->branch_param.slen = 0;
-diff --git a/tests/pjsua/scripts-sipp/uas-auth-two-algo.py b/tests/pjsua/scripts-sipp/uas-auth-two-algo.py
-new file mode 100644
-index 000000000..c79c9f6d3
---- /dev/null
-+++ b/tests/pjsua/scripts-sipp/uas-auth-two-algo.py
-@@ -0,0 +1,7 @@
-+# $Id$
-+#
-+import inc_const as const
-+
-+PJSUA = ["--null-audio --max-calls=1 --id=sip:a at localhost --username=a --realm=* --registrar=$SIPP_URI"]
-+
-+PJSUA_EXPECTS = [[0, "registration success", ""]]
-diff --git a/tests/pjsua/scripts-sipp/uas-auth-two-algo.xml b/tests/pjsua/scripts-sipp/uas-auth-two-algo.xml
-new file mode 100644
-index 000000000..bd4871940
---- /dev/null
-+++ b/tests/pjsua/scripts-sipp/uas-auth-two-algo.xml
-@@ -0,0 +1,83 @@
-+<?xml version="1.0" encoding="ISO-8859-1" ?>
-+<!DOCTYPE scenario SYSTEM "sipp.dtd">
-+
-+<scenario name="Basic UAS responder">
-+  <recv request="REGISTER" crlf="true">
-+  </recv>
-+
-+  <send>
-+    <![CDATA[
-+      SIP/2.0 100 Trying
-+      [last_Via:];received=1.1.1.1;rport=1111
-+      [last_From:]
-+      [last_To:];tag=[call_number]
-+      [last_Call-ID:]
-+      [last_CSeq:]
-+      Content-Length: 0
-+    ]]>
-+  </send>
-+
-+  <send>
-+    <![CDATA[
-+      SIP/2.0 401 Unauthorized
-+      [last_Via:];received=1.1.1.1;rport=1111
-+      [last_From:]
-+      [last_To:];tag=[call_number]
-+      [last_Call-ID:]
-+      [last_CSeq:]
-+      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=SHA-256, qop="auth"
-+      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=MD5, qop="auth"
-+      WWW-Authenticate: Digest realm="sip.linphone.org", nonce="PARV4gAAAADgw3asAADW8zsi5BEAAAAA", opaque="+GNywA==", algorithm=MD2, qop="auth"
-+      Content-Length: 0
-+    ]]>
-+  </send>
-+
-+  <recv request="REGISTER" crlf="true">
-+    <action>
-+      <ereg regexp=".*"
-+            search_in="hdr"
-+	    header="Authorization:"
-+	    assign_to="have_auth" />
-+    </action>
-+  </recv>
-+
-+  <nop next="resp_okay" test="have_auth" />
-+  
-+  <send next="end">
-+    <![CDATA[
-+      SIP/2.0 403 no auth
-+      [last_Via:];received=1.1.1.1;rport=1111
-+      [last_From:]
-+      [last_To:];tag=[call_number]
-+      [last_Call-ID:]
-+      [last_CSeq:]
-+      [last_Contact:]
-+      Content-Length: 0
-+    ]]>
-+  </send>
-+
-+  <label id="resp_okay" />
-+  
-+  <send>
-+    <![CDATA[
-+      SIP/2.0 200 OK
-+      [last_Via:];received=1.1.1.1;rport=1111
-+      [last_From:]
-+      [last_To:];tag=[call_number]
-+      [last_Call-ID:]
-+      [last_CSeq:]
-+      [last_Contact:]
-+      Content-Length: 0
-+    ]]>
-+  </send>
-+
-+  <label id="end" />
-+
-+  <!-- definition of the response time repartition table (unit is ms)   -->
-+  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
-+
-+  <!-- definition of the call length repartition table (unit is ms)     -->
-+  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
-+
-+</scenario>
-+
--- 
-2.31.1
-
diff --git a/third-party/pjproject/patches/0100-fix-double-stun-free.patch b/third-party/pjproject/patches/0100-fix-double-stun-free.patch
deleted file mode 100644
index b1cfcfd..0000000
--- a/third-party/pjproject/patches/0100-fix-double-stun-free.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-commit f0ff5817d0647bdecd1ec99488db9378e304cf83
-Author: sauwming <ming at teluu.com>
-Date:   Mon May 17 09:56:27 2021 +0800
-
-    Fix double free of stun session (#2709)
-
-diff --git a/pjnath/include/pjnath/stun_session.h b/pjnath/include/pjnath/stun_session.h
-index bee630ab4..afca06911 100644
---- a/pjnath/include/pjnath/stun_session.h
-+++ b/pjnath/include/pjnath/stun_session.h
-@@ -341,6 +341,7 @@ struct pj_stun_tx_data
-     pj_pool_t		*pool;		/**< Pool.			    */
-     pj_stun_session	*sess;		/**< The STUN session.		    */
-     pj_stun_msg		*msg;		/**< The STUN message.		    */
-+    pj_bool_t		 is_destroying; /**< Is destroying?		    */
- 
-     void		*token;		/**< The token.			    */
- 
-diff --git a/pjnath/src/pjnath/stun_session.c b/pjnath/src/pjnath/stun_session.c
-index f2b4f7058..d436b94bf 100644
---- a/pjnath/src/pjnath/stun_session.c
-+++ b/pjnath/src/pjnath/stun_session.c
-@@ -167,16 +167,27 @@ static void tdata_on_destroy(void *arg)
- {
-     pj_stun_tx_data *tdata = (pj_stun_tx_data*)arg;
- 
-+    if (tdata->grp_lock) {
-+	pj_grp_lock_dec_ref(tdata->sess->grp_lock);
-+    }
-+
-     pj_pool_safe_release(&tdata->pool);
- }
- 
- static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force)
- {
--    TRACE_((THIS_FILE, "tdata %p destroy request, force=%d, tsx=%p", tdata,
--	    force, tdata->client_tsx));
-+    TRACE_((THIS_FILE,
-+	    "tdata %p destroy request, force=%d, tsx=%p, destroying=%d",
-+	    tdata, force, tdata->client_tsx, tdata->is_destroying));
-+
-+    /* Just return if destroy has been requested before */
-+    if (tdata->is_destroying)
-+	return;
- 
-     /* STUN session may have been destroyed, except when tdata is cached. */
- 
-+    tdata->is_destroying = PJ_TRUE;
-+
-     if (tdata->res_timer.id != PJ_FALSE) {
- 	pj_timer_heap_cancel_if_active(tdata->sess->cfg->timer_heap,
- 				       &tdata->res_timer, PJ_FALSE);
-@@ -189,7 +200,6 @@ static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force)
- 	    pj_stun_client_tsx_set_data(tdata->client_tsx, NULL);
- 	}
- 	if (tdata->grp_lock) {
--	    pj_grp_lock_dec_ref(tdata->sess->grp_lock);
- 	    pj_grp_lock_dec_ref(tdata->grp_lock);
- 	} else {
- 	    tdata_on_destroy(tdata);
-@@ -200,11 +210,11 @@ static void destroy_tdata(pj_stun_tx_data *tdata, pj_bool_t force)
- 	    /* "Probably" this is to absorb retransmission */
- 	    pj_time_val delay = {0, 300};
- 	    pj_stun_client_tsx_schedule_destroy(tdata->client_tsx, &delay);
-+	    tdata->is_destroying = PJ_FALSE;
- 
- 	} else {
- 	    pj_list_erase(tdata);
- 	    if (tdata->grp_lock) {
--		pj_grp_lock_dec_ref(tdata->sess->grp_lock);
- 		pj_grp_lock_dec_ref(tdata->grp_lock);
- 	    } else {
- 		tdata_on_destroy(tdata);
-@@ -238,7 +248,7 @@ static void on_cache_timeout(pj_timer_heap_t *timer_heap,
-     sess = tdata->sess;
- 
-     pj_grp_lock_acquire(sess->grp_lock);
--    if (sess->is_destroying) {
-+    if (sess->is_destroying || tdata->is_destroying) {
- 	pj_grp_lock_release(sess->grp_lock);
- 	return;
-     }
diff --git a/third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch b/third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch
deleted file mode 100644
index 81781f2..0000000
--- a/third-party/pjproject/patches/0110-tls-parent-listener-destroyed.patch
+++ /dev/null
@@ -1,166 +0,0 @@
-From bb92c97ea512aa0ef316c9b2335c7d57b84dfc9a Mon Sep 17 00:00:00 2001
-From: Nanang Izzuddin <nanang at teluu.com>
-Date: Wed, 16 Jun 2021 12:12:35 +0700
-Subject: [PATCH 1/2] - Avoid SSL socket parent/listener getting destroyed
- during handshake by increasing parent's reference count. - Add missing SSL
- socket close when the newly accepted SSL socket is discarded in SIP TLS
- transport.
-
----
- pjlib/src/pj/ssl_sock_imp_common.c  | 44 +++++++++++++++++++++--------
- pjsip/src/pjsip/sip_transport_tls.c | 23 ++++++++++++++-
- 2 files changed, 55 insertions(+), 12 deletions(-)
-
-diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c
-index bc468bcb3..abec31805 100644
---- a/pjlib/src/pj/ssl_sock_imp_common.c
-+++ b/pjlib/src/pj/ssl_sock_imp_common.c
-@@ -224,6 +224,8 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
- 
-     /* Accepting */
-     if (ssock->is_server) {
-+	pj_bool_t ret = PJ_TRUE;
-+
- 	if (status != PJ_SUCCESS) {
- 	    /* Handshake failed in accepting, destroy our self silently. */
- 
-@@ -241,6 +243,12 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
- 		      status);
- 	    }
- 
-+	    /* Decrement ref count of parent */
-+	    if (ssock->parent->param.grp_lock) {
-+		pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
-+		ssock->parent = NULL;
-+	    }
-+
- 	    /* Originally, this is a workaround for ticket #985. However,
- 	     * a race condition may occur in multiple worker threads
- 	     * environment when we are destroying SSL objects while other
-@@ -284,23 +292,29 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
- 
- 	    return PJ_FALSE;
- 	}
-+
- 	/* Notify application the newly accepted SSL socket */
- 	if (ssock->param.cb.on_accept_complete2) {
--	    pj_bool_t ret;
- 	    ret = (*ssock->param.cb.on_accept_complete2) 
- 		    (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr, 
- 		    pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr), 
- 		    status);
--	    if (ret == PJ_FALSE)
--		return PJ_FALSE;	
- 	} else if (ssock->param.cb.on_accept_complete) {
--	    pj_bool_t ret;
- 	    ret = (*ssock->param.cb.on_accept_complete)
- 		      (ssock->parent, ssock, (pj_sockaddr_t*)&ssock->rem_addr,
- 		       pj_sockaddr_get_len((pj_sockaddr_t*)&ssock->rem_addr));
--	    if (ret == PJ_FALSE)
--		return PJ_FALSE;
- 	}
-+
-+	/* Decrement ref count of parent and reset parent (we don't need it
-+	 * anymore, right?).
-+	 */
-+	if (ssock->parent->param.grp_lock) {
-+	    pj_grp_lock_dec_ref(ssock->parent->param.grp_lock);
-+	    ssock->parent = NULL;
-+	}
-+
-+	if (ret == PJ_FALSE)
-+	    return PJ_FALSE;
-     }
- 
-     /* Connecting */
-@@ -864,9 +878,13 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
-     if (status != PJ_SUCCESS)
- 	goto on_return;
- 
-+    /* Set parent and add ref count (avoid parent destroy during handshake) */
-+    ssock->parent = ssock_parent;
-+    if (ssock->parent->param.grp_lock)
-+	pj_grp_lock_add_ref(ssock->parent->param.grp_lock);
-+
-     /* Update new SSL socket attributes */
-     ssock->sock = newsock;
--    ssock->parent = ssock_parent;
-     ssock->is_server = PJ_TRUE;
-     if (ssock_parent->cert) {
- 	status = pj_ssl_sock_set_certificate(ssock, ssock->pool, 
-@@ -913,16 +931,20 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
-     ssock->asock_rbuf = (void**)pj_pool_calloc(ssock->pool, 
- 					       ssock->param.async_cnt,
- 					       sizeof(void*));
--    if (!ssock->asock_rbuf)
--        return PJ_ENOMEM;
-+    if (!ssock->asock_rbuf) {
-+		status = PJ_ENOMEM;
-+		goto on_return;
-+	}
- 
-     for (i = 0; i<ssock->param.async_cnt; ++i) {
--	ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
-+		ssock->asock_rbuf[i] = (void*) pj_pool_alloc(
- 					    ssock->pool, 
- 					    ssock->param.read_buffer_size + 
- 					    sizeof(read_data_t*));
--        if (!ssock->asock_rbuf[i])
--            return PJ_ENOMEM;
-+		if (!ssock->asock_rbuf[i]) {
-+			status = PJ_ENOMEM;
-+			goto on_return;
-+		}
-     }
- 
-     /* Create active socket */
-diff --git a/pjsip/src/pjsip/sip_transport_tls.c b/pjsip/src/pjsip/sip_transport_tls.c
-index 17b7ae3de..ce524d53f 100644
---- a/pjsip/src/pjsip/sip_transport_tls.c
-+++ b/pjsip/src/pjsip/sip_transport_tls.c
-@@ -1325,9 +1325,26 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
-     PJ_UNUSED_ARG(src_addr_len);
- 
-     listener = (struct tls_listener*) pj_ssl_sock_get_user_data(ssock);
-+    if (!listener) {
-+	/* Listener already destroyed, e.g: after TCP accept but before SSL
-+	 * handshake is completed.
-+	 */
-+	if (new_ssock && accept_status == PJ_SUCCESS) {
-+	    /* Close the SSL socket if the accept op is successful */
-+	    PJ_LOG(4,(THIS_FILE,
-+		      "Incoming TLS connection from %s (sock=%d) is discarded "
-+		      "because listener is already destroyed",
-+		      pj_sockaddr_print(src_addr, addr, sizeof(addr), 3),
-+		      new_ssock));
-+
-+	    pj_ssl_sock_close(new_ssock);
-+	}
-+
-+	return PJ_FALSE;
-+    }
- 
-     if (accept_status != PJ_SUCCESS) {
--	if (listener && listener->tls_setting.on_accept_fail_cb) {
-+	if (listener->tls_setting.on_accept_fail_cb) {
- 	    pjsip_tls_on_accept_fail_param param;
- 	    pj_ssl_sock_info ssi;
- 
-@@ -1350,6 +1367,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
-     PJ_ASSERT_RETURN(new_ssock, PJ_TRUE);
- 
-     if (!listener->is_registered) {
-+	pj_ssl_sock_close(new_ssock);
-+
- 	if (listener->tls_setting.on_accept_fail_cb) {
- 	    pjsip_tls_on_accept_fail_param param;
- 	    pj_bzero(&param, sizeof(param));
-@@ -1401,6 +1420,8 @@ static pj_bool_t on_accept_complete2(pj_ssl_sock_t *ssock,
- 			 ssl_info.grp_lock, &tls);
-     
-     if (status != PJ_SUCCESS) {
-+	pj_ssl_sock_close(new_ssock);
-+
- 	if (listener->tls_setting.on_accept_fail_cb) {
- 	    pjsip_tls_on_accept_fail_param param;
- 	    pj_bzero(&param, sizeof(param));
diff --git a/third-party/pjproject/patches/0111-ssl-premature-destroy.patch b/third-party/pjproject/patches/0111-ssl-premature-destroy.patch
deleted file mode 100644
index 9de2915..0000000
--- a/third-party/pjproject/patches/0111-ssl-premature-destroy.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-From 68c69f516f95df1faa42e5647e9ce7cfdc41ac38 Mon Sep 17 00:00:00 2001
-From: Nanang Izzuddin <nanang at teluu.com>
-Date: Wed, 16 Jun 2021 12:15:29 +0700
-Subject: [PATCH 2/2] - Fix silly mistake: accepted active socket created
- without group lock in SSL socket. - Replace assertion with normal validation
- check of SSL socket instance in OpenSSL verification callback (verify_cb())
- to avoid crash, e.g: if somehow race condition with SSL socket destroy
- happens or OpenSSL application data index somehow gets corrupted.
-
----
- pjlib/src/pj/ssl_sock_imp_common.c |  3 +-
- pjlib/src/pj/ssl_sock_ossl.c       | 45 +++++++++++++++++++++++++-----
- 2 files changed, 40 insertions(+), 8 deletions(-)
-
-diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c
-index bc468bcb3..c2b8a846b 100644
---- a/pjlib/src/pj/ssl_sock_imp_common.c
-+++ b/pjlib/src/pj/ssl_sock_imp_common.c
-@@ -927,6 +927,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
- 
-     /* Create active socket */
-     pj_activesock_cfg_default(&asock_cfg);
-+    asock_cfg.grp_lock = ssock->param.grp_lock;
-     asock_cfg.async_cnt = ssock->param.async_cnt;
-     asock_cfg.concurrency = ssock->param.concurrency;
-     asock_cfg.whole_data = PJ_TRUE;
-@@ -942,7 +943,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
- 	    goto on_return;
- 
- 	pj_grp_lock_add_ref(glock);
--	asock_cfg.grp_lock = ssock->param.grp_lock = glock;
-+	ssock->param.grp_lock = glock;
- 	pj_grp_lock_add_handler(ssock->param.grp_lock, ssock->pool, ssock,
- 				ssl_on_destroy);
-     }
-diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
-index a95b339a5..56841f80a 100644
---- a/pjlib/src/pj/ssl_sock_ossl.c
-+++ b/pjlib/src/pj/ssl_sock_ossl.c
-@@ -327,7 +327,8 @@ static pj_status_t STATUS_FROM_SSL_ERR(char *action, pj_ssl_sock_t *ssock,
- 	ERROR_LOG("STATUS_FROM_SSL_ERR", err, ssock);
-     }
- 
--    ssock->last_err = err;
-+    if (ssock)
-+	ssock->last_err = err;
-     return GET_STATUS_FROM_SSL_ERR(err);
- }
- 
-@@ -344,7 +345,8 @@ static pj_status_t STATUS_FROM_SSL_ERR2(char *action, pj_ssl_sock_t *ssock,
-     /* Dig for more from OpenSSL error queue */
-     SSLLogErrors(action, ret, err, len, ssock);
- 
--    ssock->last_err = ssl_err;
-+    if (ssock)
-+	ssock->last_err = ssl_err;
-     return GET_STATUS_FROM_SSL_ERR(ssl_err);
- }
- 
-@@ -587,6 +589,13 @@ static pj_status_t init_openssl(void)
- 
-     /* Create OpenSSL application data index for SSL socket */
-     sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL);
-+	if (sslsock_idx == -1) {
-+		status = STATUS_FROM_SSL_ERR2("Init", NULL, -1, ERR_get_error(), 0);
-+		PJ_LOG(1,(THIS_FILE,
-+				  "Fatal error: failed to get application data index for "
-+				  "SSL socket"));
-+		return status;
-+	}
- 
-     return status;
- }
-@@ -614,21 +623,36 @@ static int password_cb(char *buf, int num, int rwflag, void *user_data)
- }
- 
- 
--/* SSL password callback. */
-+/* SSL certificate verification result callback.
-+ * Note that this callback seems to be always called from library worker
-+ * thread, e.g: active socket on_read_complete callback, which should have
-+ * already been equipped with race condition avoidance mechanism (should not
-+ * be destroyed while callback is being invoked).
-+ */
- static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
- {
--    pj_ssl_sock_t *ssock;
--    SSL *ossl_ssl;
-+    pj_ssl_sock_t *ssock = NULL;
-+    SSL *ossl_ssl = NULL;
-     int err;
- 
-     /* Get SSL instance */
-     ossl_ssl = X509_STORE_CTX_get_ex_data(x509_ctx, 
- 				    SSL_get_ex_data_X509_STORE_CTX_idx());
--    pj_assert(ossl_ssl);
-+    if (!ossl_ssl) {
-+	PJ_LOG(1,(THIS_FILE,
-+		  "SSL verification callback failed to get SSL instance"));
-+	goto on_return;
-+    }
- 
-     /* Get SSL socket instance */
-     ssock = SSL_get_ex_data(ossl_ssl, sslsock_idx);
--    pj_assert(ssock);
-+    if (!ssock) {
-+	/* SSL socket may have been destroyed */
-+	PJ_LOG(1,(THIS_FILE,
-+		  "SSL verification callback failed to get SSL socket "
-+		  "instance (sslsock_idx=%d).", sslsock_idx));
-+	goto on_return;
-+    }
- 
-     /* Store verification status */
-     err = X509_STORE_CTX_get_error(x509_ctx);
-@@ -706,6 +730,7 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
-     if (PJ_FALSE == ssock->param.verify_peer)
- 	preverify_ok = 1;
- 
-+on_return:
-     return preverify_ok;
- }
- 
-@@ -1213,6 +1238,12 @@ static void ssl_destroy(pj_ssl_sock_t *ssock)
- static void ssl_reset_sock_state(pj_ssl_sock_t *ssock)
- {
-     ossl_sock_t *ossock = (ossl_sock_t *)ssock;
-+
-+    /* Detach from SSL instance */
-+    if (ossock->ossl_ssl) {
-+	SSL_set_ex_data(ossock->ossl_ssl, sslsock_idx, NULL);
-+    }
-+
-     /**
-      * Avoid calling SSL_shutdown() if handshake wasn't completed.
-      * OpenSSL 1.0.2f complains if SSL_shutdown() is called during an
diff --git a/third-party/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch b/third-party/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch
deleted file mode 100644
index 1b1fcad..0000000
--- a/third-party/pjproject/patches/0120-pjmedia_sdp_attr_get_rtpmap-Strip-param-trailing-whi.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 2ae784030b0d9cf217c3d562af20e4967f19a3dc Mon Sep 17 00:00:00 2001
-From: George Joseph <gjoseph at sangoma.com>
-Date: Tue, 14 Sep 2021 10:47:29 -0600
-Subject: [PATCH] pjmedia_sdp_attr_get_rtpmap: Strip param trailing whitespace
-
-Use pj_scan_get() to parse the param part of rtpmap so
-trailing whitespace is automatically stripped.
-
-Fixes #2827
----
- pjmedia/src/pjmedia/sdp.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/pjmedia/src/pjmedia/sdp.c b/pjmedia/src/pjmedia/sdp.c
-index 5d05a0d9c..3448749c9 100644
---- a/pjmedia/src/pjmedia/sdp.c
-+++ b/pjmedia/src/pjmedia/sdp.c
-@@ -313,9 +313,9 @@ PJ_DEF(pj_status_t) pjmedia_sdp_attr_get_rtpmap( const pjmedia_sdp_attr *attr,
- 
- 	/* Expecting either '/' or EOF */
- 	if (*scanner.curptr == '/') {
-+	    /* Skip the '/' */
- 	    pj_scan_get_char(&scanner);
--	    rtpmap->param.ptr = scanner.curptr;
--	    rtpmap->param.slen = scanner.end - scanner.curptr;
-+	    pj_scan_get(&scanner, &cs_token, &rtpmap->param);
- 	} else {
- 	    rtpmap->param.slen = 0;
- 	}
--- 
-2.31.1
-
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
deleted file mode 100644
index 91feefb..0000000
--- a/third-party/pjproject/patches/0130-sip_inv-Additional-multipart-support-2919-2920.patch
+++ /dev/null
@@ -1,661 +0,0 @@
-From 0ed41eb5fd0e4192e1b7dc374f819d17aef3e805 Mon Sep 17 00:00:00 2001
-From: George Joseph <gtjoseph at users.noreply.github.com>
-Date: Tue, 21 Dec 2021 19:32:22 -0700
-Subject: [PATCH] sip_inv:  Additional multipart support (#2919) (#2920)
-
----
- pjsip/include/pjsip-ua/sip_inv.h       | 108 ++++++++++-
- pjsip/src/pjsip-ua/sip_inv.c           | 240 ++++++++++++++++++++-----
- pjsip/src/test/inv_offer_answer_test.c | 103 ++++++++++-
- 3 files changed, 394 insertions(+), 57 deletions(-)
-
-diff --git a/pjsip/include/pjsip-ua/sip_inv.h b/pjsip/include/pjsip-ua/sip_inv.h
-index 14f2d23fa..c33551786 100644
---- a/pjsip/include/pjsip-ua/sip_inv.h
-+++ b/pjsip/include/pjsip-ua/sip_inv.h
-@@ -451,11 +451,11 @@ struct pjsip_inv_session
- 
- 
- /**
-- * This structure represents SDP information in a pjsip_rx_data. Application
-- * retrieve this information by calling #pjsip_rdata_get_sdp_info(). This
-+ * This structure represents SDP information in a pjsip_(rx|tx)_data. Application
-+ * retrieve this information by calling #pjsip_get_sdp_info(). This
-  * mechanism supports multipart message body.
-  */
--typedef struct pjsip_rdata_sdp_info
-+typedef struct pjsip_sdp_info
- {
-     /**
-      * Pointer and length of the text body in the incoming message. If
-@@ -475,7 +475,15 @@ typedef struct pjsip_rdata_sdp_info
-      */
-     pjmedia_sdp_session *sdp;
- 
--} pjsip_rdata_sdp_info;
-+} pjsip_sdp_info;
-+
-+/**
-+ * For backwards compatibility and completeness,
-+ * pjsip_rdata_sdp_info and pjsip_tdata_sdp_info
-+ * are typedef'd to pjsip_sdp_info.
-+ */
-+typedef pjsip_sdp_info pjsip_rdata_sdp_info;
-+typedef pjsip_sdp_info pjsip_tdata_sdp_info;
- 
- 
- /**
-@@ -1045,6 +1053,44 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_body(pj_pool_t *pool,
- 					   pjmedia_sdp_session *sdp,
- 					   pjsip_msg_body **p_body);
- 
-+/**
-+ * This is a utility function to create a multipart body with the
-+ * SIP body as the first part.
-+ *
-+ * @param pool		Pool to allocate memory.
-+ * @param sdp		SDP session to be put in the SIP message body.
-+ * @param p_body	Pointer to receive SIP message body containing
-+ *			the SDP session.
-+ *
-+ * @return		PJ_SUCCESS on success.
-+ */
-+PJ_DECL(pj_status_t) pjsip_create_multipart_sdp_body( pj_pool_t *pool,
-+                                           pjmedia_sdp_session *sdp,
-+                                           pjsip_msg_body **p_body);
-+
-+/**
-+ * Retrieve SDP information from a message body. Application should
-+ * prefer to use this function rather than parsing the SDP manually since
-+ * this function supports multipart message body.
-+ *
-+ * This function will only parse the SDP once, the first time it is called
-+ * on the same message. Subsequent call on the same message will just pick
-+ * up the already parsed SDP from the message.
-+ *
-+ * @param pool               Pool to allocate memory.
-+ * @param body               The message body.
-+ * @param msg_media_type     From the rdata or tdata Content-Type header, if available.
-+ *                           If NULL, the content_type from the body will be used.
-+ * @param search_media_type  The media type to search for.
-+ *                           If NULL, "application/sdp" will be used.
-+ *
-+ * @return                   The SDP info.
-+ */
-+PJ_DECL(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,
-+					   pjsip_msg_body *body,
-+					   pjsip_media_type *msg_media_type,
-+					   const pjsip_media_type *search_media_type);
-+
- /**
-  * Retrieve SDP information from an incoming message. Application should
-  * prefer to use this function rather than parsing the SDP manually since
-@@ -1061,6 +1107,60 @@ PJ_DECL(pj_status_t) pjsip_create_sdp_body(pj_pool_t *pool,
- PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata);
- 
- 
-+/**
-+ * Retrieve SDP information from an incoming message. Application should
-+ * prefer to use this function rather than parsing the SDP manually since
-+ * this function supports multipart message body.
-+ *
-+ * This function will only parse the SDP once, the first time it is called
-+ * on the same message. Subsequent call on the same message will just pick
-+ * up the already parsed SDP from the message.
-+ *
-+ * @param rdata               The incoming message.
-+ * @param search_media_type   The SDP media type to search for.
-+ *                            If NULL, "application/sdp" will be used.
-+ *
-+ * @return                    The SDP info.
-+ */
-+PJ_DECL(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(
-+					    pjsip_rx_data *rdata,
-+					    const pjsip_media_type *search_media_type);
-+
-+/**
-+ * Retrieve SDP information from an outgoing message. Application should
-+ * prefer to use this function rather than parsing the SDP manually since
-+ * this function supports multipart message body.
-+ *
-+ * This function will only parse the SDP once, the first time it is called
-+ * on the same message. Subsequent call on the same message will just pick
-+ * up the already parsed SDP from the message.
-+ *
-+ * @param tdata    The outgoing message.
-+ *
-+ * @return         The SDP info.
-+ */
-+PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata);
-+
-+/**
-+ * Retrieve SDP information from an outgoing message. Application should
-+ * prefer to use this function rather than parsing the SDP manually since
-+ * this function supports multipart message body.
-+ *
-+ * This function will only parse the SDP once, the first time it is called
-+ * on the same message. Subsequent call on the same message will just pick
-+ * up the already parsed SDP from the message.
-+ *
-+ * @param tdata               The outgoing message.
-+ * @param search_media_type   The SDP media type to search for.
-+ *                            If NULL, "application/sdp" will be used.
-+ *
-+ * @return                    The SDP info.
-+ */
-+PJ_DECL(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(
-+					    pjsip_tx_data *tdata,
-+					    const pjsip_media_type *search_media_type);
-+
-+
- PJ_END_DECL
- 
- /**
-diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c
-index ca225015b..b68ae0f16 100644
---- a/pjsip/src/pjsip-ua/sip_inv.c
-+++ b/pjsip/src/pjsip-ua/sip_inv.c
-@@ -118,6 +118,8 @@ static pj_status_t handle_timer_response(pjsip_inv_session *inv,
- static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv,
- 				      pjsip_event *e);
- 
-+static int print_sdp(pjsip_msg_body *body, char *buf, pj_size_t len);
-+
- static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) = 
- {
-     &inv_on_state_null,
-@@ -946,66 +948,170 @@ PJ_DEF(pj_status_t) pjsip_inv_create_uac( pjsip_dialog *dlg,
-     return PJ_SUCCESS;
- }
- 
--PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)
-+PJ_DEF(pjsip_sdp_info*) pjsip_get_sdp_info(pj_pool_t *pool,
-+                                           pjsip_msg_body *body,
-+                                           pjsip_media_type *msg_media_type,
-+                                           const pjsip_media_type *search_media_type)
- {
--    pjsip_rdata_sdp_info *sdp_info;
--    pjsip_msg_body *body = rdata->msg_info.msg->body;
--    pjsip_ctype_hdr *ctype_hdr = rdata->msg_info.ctype;
--    pjsip_media_type app_sdp;
-+    pjsip_sdp_info *sdp_info;
-+    pjsip_media_type search_type;
-+    pjsip_media_type multipart_mixed;
-+    pjsip_media_type multipart_alternative;
-+    pjsip_media_type *msg_type;
-+    pj_status_t status;
- 
--    sdp_info = (pjsip_rdata_sdp_info*)
--	       rdata->endpt_info.mod_data[mod_inv.mod.id];
--    if (sdp_info)
--	return sdp_info;
-+    sdp_info = PJ_POOL_ZALLOC_T(pool,
-+                                pjsip_sdp_info);
- 
--    sdp_info = PJ_POOL_ZALLOC_T(rdata->tp_info.pool,
--				pjsip_rdata_sdp_info);
-     PJ_ASSERT_RETURN(mod_inv.mod.id >= 0, sdp_info);
--    rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;
- 
--    pjsip_media_type_init2(&app_sdp, "application", "sdp");
-+    if (!body) {
-+        return sdp_info;
-+    }
- 
--    if (body && ctype_hdr &&
--	pj_stricmp(&ctype_hdr->media.type, &app_sdp.type)==0 &&
--	pj_stricmp(&ctype_hdr->media.subtype, &app_sdp.subtype)==0)
-+    if (msg_media_type) {
-+	msg_type = msg_media_type;
-+    } else {
-+	if (body->content_type.type.slen == 0) {
-+	    return sdp_info;
-+	}
-+	msg_type = &body->content_type;
-+    }
-+
-+    if (!search_media_type) {
-+        pjsip_media_type_init2(&search_type, "application", "sdp");
-+    } else {
-+        pj_memcpy(&search_type, search_media_type, sizeof(search_type));
-+    }
-+
-+    pjsip_media_type_init2(&multipart_mixed, "multipart", "mixed");
-+    pjsip_media_type_init2(&multipart_alternative, "multipart", "alternative");
-+
-+    if (pjsip_media_type_cmp(msg_type, &search_type, PJ_FALSE) == 0)
-     {
--	sdp_info->body.ptr = (char*)body->data;
--	sdp_info->body.slen = body->len;
--    } else if  (body && ctype_hdr &&
--	    	pj_stricmp2(&ctype_hdr->media.type, "multipart")==0 &&
--	    	(pj_stricmp2(&ctype_hdr->media.subtype, "mixed")==0 ||
--	    	 pj_stricmp2(&ctype_hdr->media.subtype, "alternative")==0))
-+	/*
-+	 * If the print_body function is print_sdp, we know that
-+	 * body->data is a pjmedia_sdp_session object and came from
-+	 * a tx_data.  If not, it's the text representation of the
-+	 * sdp from an rx_data.
-+	 */
-+        if (body->print_body == print_sdp) {
-+            sdp_info->sdp = body->data;
-+        } else {
-+            sdp_info->body.ptr = (char*)body->data;
-+            sdp_info->body.slen = body->len;
-+        }
-+    } else if (pjsip_media_type_cmp(&multipart_mixed, msg_type, PJ_FALSE) == 0 ||
-+	pjsip_media_type_cmp(&multipart_alternative, msg_type, PJ_FALSE) == 0)
-     {
--	pjsip_multipart_part *part;
-+        pjsip_multipart_part *part;
-+        part = pjsip_multipart_find_part(body, &search_type, NULL);
-+        if (part) {
-+            if (part->body->print_body == print_sdp) {
-+                sdp_info->sdp = part->body->data;
-+            } else {
-+                sdp_info->body.ptr = (char*)part->body->data;
-+                sdp_info->body.slen = part->body->len;
-+            }
-+        }
-+    }
- 
--	part = pjsip_multipart_find_part(body, &app_sdp, NULL);
--	if (part) {
--	    sdp_info->body.ptr = (char*)part->body->data;
--	    sdp_info->body.slen = part->body->len;
--	}
-+    /*
-+     * If the body was already a pjmedia_sdp_session, we can just
-+     * return it.  If not and there wasn't a text representation
-+     * of the sdp either, we can also just return.
-+     */
-+    if (sdp_info->sdp || !sdp_info->body.ptr) {
-+	return sdp_info;
-     }
- 
--    if (sdp_info->body.ptr) {
--	pj_status_t status;
--	status = pjmedia_sdp_parse(rdata->tp_info.pool,
--				   sdp_info->body.ptr,
--				   sdp_info->body.slen,
--				   &sdp_info->sdp);
--	if (status == PJ_SUCCESS)
--	    status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);
-+    /*
-+     * If the body was the text representation of teh SDP, we need
-+     * to parse it to create a pjmedia_sdp_session object.
-+     */
-+    status = pjmedia_sdp_parse(pool,
-+				sdp_info->body.ptr,
-+				sdp_info->body.slen,
-+				&sdp_info->sdp);
-+    if (status == PJ_SUCCESS)
-+	status = pjmedia_sdp_validate2(sdp_info->sdp, PJ_FALSE);
- 
--	if (status != PJ_SUCCESS) {
--	    sdp_info->sdp = NULL;
--	    PJ_PERROR(1,(THIS_FILE, status,
--			 "Error parsing/validating SDP body"));
--	}
-+    if (status != PJ_SUCCESS) {
-+	sdp_info->sdp = NULL;
-+	PJ_PERROR(1, (THIS_FILE, status,
-+	    "Error parsing/validating SDP body"));
-+    }
-+
-+    sdp_info->sdp_err = status;
-+
-+    return sdp_info;
-+}
- 
--	sdp_info->sdp_err = status;
-+PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info2(
-+                                            pjsip_rx_data *rdata,
-+                                            const pjsip_media_type *search_media_type)
-+{
-+    pjsip_media_type *msg_media_type = NULL;
-+    pjsip_rdata_sdp_info *sdp_info;
-+
-+    if (rdata->endpt_info.mod_data[mod_inv.mod.id]) {
-+	return (pjsip_rdata_sdp_info *)rdata->endpt_info.mod_data[mod_inv.mod.id];
-+    }
-+
-+    /*
-+     * rdata should have a Content-Type header at this point but we'll
-+     * make sure.
-+     */
-+    if (rdata->msg_info.ctype) {
-+	msg_media_type = &rdata->msg_info.ctype->media;
-+    }
-+    sdp_info = pjsip_get_sdp_info(rdata->tp_info.pool,
-+				   rdata->msg_info.msg->body,
-+				   msg_media_type,
-+				   search_media_type);
-+    rdata->endpt_info.mod_data[mod_inv.mod.id] = sdp_info;
-+
-+    return sdp_info;
-+}
-+
-+PJ_DEF(pjsip_rdata_sdp_info*) pjsip_rdata_get_sdp_info(pjsip_rx_data *rdata)
-+{
-+    return pjsip_rdata_get_sdp_info2(rdata, NULL);
-+}
-+
-+PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info2(
-+                                            pjsip_tx_data *tdata,
-+                                            const pjsip_media_type *search_media_type)
-+{
-+    pjsip_ctype_hdr *ctype_hdr = NULL;
-+    pjsip_media_type *msg_media_type = NULL;
-+    pjsip_tdata_sdp_info *sdp_info;
-+
-+    if (tdata->mod_data[mod_inv.mod.id]) {
-+	return (pjsip_tdata_sdp_info *)tdata->mod_data[mod_inv.mod.id];
-+    }
-+    /*
-+     * tdata won't usually have a Content-Type header at this point
-+     * but we'll check just the same,
-+     */
-+    ctype_hdr = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTENT_TYPE, NULL);
-+    if (ctype_hdr) {
-+	msg_media_type = &ctype_hdr->media;
-     }
- 
-+    sdp_info = pjsip_get_sdp_info(tdata->pool,
-+				   tdata->msg->body,
-+				   msg_media_type,
-+				   search_media_type);
-+    tdata->mod_data[mod_inv.mod.id] = sdp_info;
-+
-     return sdp_info;
- }
- 
-+PJ_DEF(pjsip_tdata_sdp_info*) pjsip_tdata_get_sdp_info(pjsip_tx_data *tdata)
-+{
-+    return pjsip_tdata_get_sdp_info2(tdata, NULL);
-+}
- 
- /*
-  * Verify incoming INVITE request.
-@@ -1730,13 +1836,55 @@ PJ_DEF(pj_status_t) pjsip_create_sdp_body( pj_pool_t *pool,
-     return PJ_SUCCESS;
- }
- 
-+static pjsip_multipart_part* create_sdp_part(pj_pool_t *pool, pjmedia_sdp_session *sdp)
-+{
-+    pjsip_multipart_part *sdp_part;
-+    pjsip_media_type media_type;
-+
-+    pjsip_media_type_init2(&media_type, "application", "sdp");
-+
-+    sdp_part = pjsip_multipart_create_part(pool);
-+    PJ_ASSERT_RETURN(sdp_part != NULL, NULL);
-+
-+    sdp_part->body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
-+    PJ_ASSERT_RETURN(sdp_part->body != NULL, NULL);
-+
-+    pjsip_media_type_cp(pool, &sdp_part->body->content_type, &media_type);
-+
-+    sdp_part->body->data = sdp;
-+    sdp_part->body->clone_data = clone_sdp;
-+    sdp_part->body->print_body = print_sdp;
-+
-+    return sdp_part;
-+}
-+
-+PJ_DEF(pj_status_t) pjsip_create_multipart_sdp_body(pj_pool_t *pool,
-+						     pjmedia_sdp_session *sdp,
-+						     pjsip_msg_body **p_body)
-+{
-+    pjsip_media_type media_type;
-+    pjsip_msg_body *multipart;
-+    pjsip_multipart_part *sdp_part;
-+
-+    pjsip_media_type_init2(&media_type, "multipart", "mixed");
-+    multipart = pjsip_multipart_create(pool, &media_type, NULL);
-+    PJ_ASSERT_RETURN(multipart != NULL, PJ_ENOMEM);
-+
-+    sdp_part = create_sdp_part(pool, sdp);
-+    PJ_ASSERT_RETURN(sdp_part != NULL, PJ_ENOMEM);
-+    pjsip_multipart_add_part(pool, multipart, sdp_part);
-+    *p_body = multipart;
-+
-+    return PJ_SUCCESS;
-+}
-+
- static pjsip_msg_body *create_sdp_body(pj_pool_t *pool,
- 				       const pjmedia_sdp_session *c_sdp)
- {
-     pjsip_msg_body *body;
-     pj_status_t status;
- 
--    status = pjsip_create_sdp_body(pool, 
-+    status = pjsip_create_sdp_body(pool,
- 				   pjmedia_sdp_session_clone(pool, c_sdp),
- 				   &body);
- 
-@@ -2059,6 +2207,7 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
- 	       )
- 	   )
- 	{
-+	    pjsip_sdp_info *tdata_sdp_info;
- 	    const pjmedia_sdp_session *reoffer_sdp = NULL;
- 
- 	    PJ_LOG(4,(inv->obj_name, "Received %s response "
-@@ -2067,14 +2216,15 @@ static pj_status_t inv_check_sdp_in_incoming_msg( pjsip_inv_session *inv,
- 		      (st_code/10==18? "early" : "final" )));
- 
- 	    /* Retrieve original SDP offer from INVITE request */
--	    reoffer_sdp = (const pjmedia_sdp_session*) 
--			  tsx->last_tx->msg->body->data;
-+	    tdata_sdp_info = pjsip_tdata_get_sdp_info(tsx->last_tx);
-+	    reoffer_sdp = tdata_sdp_info->sdp;
- 
- 	    /* Feed the original offer to negotiator */
- 	    status = pjmedia_sdp_neg_modify_local_offer2(inv->pool_prov, 
- 							 inv->neg,
-                                                          inv->sdp_neg_flags,
- 						         reoffer_sdp);
-+
- 	    if (status != PJ_SUCCESS) {
- 		PJ_LOG(1,(inv->obj_name, "Error updating local offer for "
- 			  "forked 2xx/18x response (err=%d)", status));
-diff --git a/pjsip/src/test/inv_offer_answer_test.c b/pjsip/src/test/inv_offer_answer_test.c
-index ad5fcd409..9cdd2654b 100644
---- a/pjsip/src/test/inv_offer_answer_test.c
-+++ b/pjsip/src/test/inv_offer_answer_test.c
-@@ -137,6 +137,7 @@ typedef struct inv_test_param_t
-     pj_bool_t	need_established;
-     unsigned	count;
-     oa_t	oa[4];
-+    pj_bool_t	multipart_body;
- } inv_test_param_t;
- 
- typedef struct inv_test_t
-@@ -257,6 +258,17 @@ static void on_media_update(pjsip_inv_session *inv_ses,
- 	    }
- 	}
- 
-+	/* Special handling for standard offer/answer */
-+	if (inv_test.param.count == 1 &&
-+	    inv_test.param.oa[0] == OFFERER_UAC &&
-+	    inv_test.param.need_established)
-+	{
-+	    jobs[job_cnt].type = ESTABLISH_CALL;
-+	    jobs[job_cnt].who = PJSIP_ROLE_UAS;
-+	    job_cnt++;
-+	    TRACE_((THIS_FILE, "      C+++"));
-+	}
-+
- 	pj_assert(job_cnt <= PJ_ARRAY_SIZE(jobs));
-     }
- }
-@@ -333,6 +345,15 @@ static pj_bool_t on_rx_request(pjsip_rx_data *rdata)
- 					  NULL, &tdata);
- 	pj_assert(status == PJ_SUCCESS);
- 
-+	/* Use multipart body, if configured */
-+	if (sdp && inv_test.param.multipart_body) {
-+	     status = pjsip_create_multipart_sdp_body(
-+				tdata->pool,
-+				pjmedia_sdp_session_clone(tdata->pool, sdp),
-+				&tdata->msg->body);
-+	}
-+	pj_assert(status == PJ_SUCCESS);
-+
- 	status = pjsip_inv_send_msg(inv_test.uas, tdata);
- 	pj_assert(status == PJ_SUCCESS);
- 
-@@ -426,6 +447,7 @@ static int perform_test(inv_test_param_t *param)
- 	sdp = NULL;
- 
-     status = pjsip_inv_create_uac(dlg, sdp, inv_test.param.inv_option, &inv_test.uac);
-+    //inv_test.uac->create_multipart = param->multipart_body;
-     PJ_ASSERT_RETURN(status==PJ_SUCCESS, -20);
- 
-     TRACE_((THIS_FILE, "    Sending INVITE %s offer", (sdp ? "with" : "without")));
-@@ -436,8 +458,17 @@ static int perform_test(inv_test_param_t *param)
-     status = pjsip_inv_invite(inv_test.uac, &tdata);
-     PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);
- 
-+    /* Use multipart body, if configured */
-+    if (sdp && param->multipart_body) {
-+	 status = pjsip_create_multipart_sdp_body(
-+			    tdata->pool,
-+			    pjmedia_sdp_session_clone(tdata->pool, sdp),
-+			    &tdata->msg->body);
-+    }
-+    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -40);
-+
-     status = pjsip_inv_send_msg(inv_test.uac, tdata);
--    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -30);
-+    PJ_ASSERT_RETURN(status==PJ_SUCCESS, -50);
- 
-     /*
-      * Wait until test completes
-@@ -525,13 +556,14 @@ static inv_test_param_t test_params[] =
-     200/INVITE (answer)	<--
-     ACK    		-->
-  */
--#if 0
-+#if 1
-     {
- 	"Standard INVITE with offer",
- 	0,
- 	PJ_TRUE,
- 	1,
--	{ OFFERER_UAC }
-+	{ OFFERER_UAC },
-+	PJ_FALSE
-     },
- 
-     {
-@@ -539,7 +571,25 @@ static inv_test_param_t test_params[] =
- 	PJSIP_INV_REQUIRE_100REL,
- 	PJ_TRUE,
- 	1,
--	{ OFFERER_UAC }
-+	{ OFFERER_UAC },
-+	PJ_FALSE
-+    },
-+    {
-+	"Standard INVITE with offer, with Multipart",
-+	0,
-+	PJ_TRUE,
-+	1,
-+	{ OFFERER_UAC },
-+	PJ_TRUE
-+    },
-+
-+    {
-+	"Standard INVITE with offer, with 100rel, with Multipart",
-+	PJSIP_INV_REQUIRE_100REL,
-+	PJ_TRUE,
-+	1,
-+	{ OFFERER_UAC },
-+	PJ_TRUE
-     },
- #endif
- 
-@@ -555,7 +605,8 @@ static inv_test_param_t test_params[] =
- 	0,
- 	PJ_TRUE,
- 	1,
--	{ OFFERER_UAS }
-+	{ OFFERER_UAS },
-+	PJ_FALSE
-     },
- 
-     {
-@@ -563,7 +614,25 @@ static inv_test_param_t test_params[] =
- 	PJSIP_INV_REQUIRE_100REL,
- 	PJ_TRUE,
- 	1,
--	{ OFFERER_UAS }
-+	{ OFFERER_UAS },
-+	PJ_FALSE
-+    },
-+    {
-+	"INVITE with no offer, with Multipart",
-+	0,
-+	PJ_TRUE,
-+	1,
-+	{ OFFERER_UAS },
-+	PJ_TRUE
-+    },
-+
-+    {
-+	"INVITE with no offer, with 100rel, with Multipart",
-+	PJSIP_INV_REQUIRE_100REL,
-+	PJ_TRUE,
-+	1,
-+	{ OFFERER_UAS },
-+	PJ_TRUE
-     },
- #endif
- 
-@@ -584,14 +653,24 @@ static inv_test_param_t test_params[] =
- 	0,
- 	PJ_TRUE,
- 	2,
--	{ OFFERER_UAC, OFFERER_UAC }
-+	{ OFFERER_UAC, OFFERER_UAC },
-+	PJ_FALSE
-+    },
-+    {
-+	"INVITE and UPDATE by UAC, with Multipart",
-+	0,
-+	PJ_TRUE,
-+	2,
-+	{ OFFERER_UAC, OFFERER_UAC },
-+	PJ_TRUE
-     },
-     {
- 	"INVITE and UPDATE by UAC, with 100rel",
- 	PJSIP_INV_REQUIRE_100REL,
- 	PJ_TRUE,
- 	2,
--	{ OFFERER_UAC, OFFERER_UAC }
-+	{ OFFERER_UAC, OFFERER_UAC },
-+	PJ_FALSE
-     },
- #endif
- 
-@@ -617,6 +696,14 @@ static inv_test_param_t test_params[] =
- 	4,
- 	{ OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS }
-     },
-+    {
-+	"INVITE and many UPDATE by UAC and UAS, with Multipart",
-+	0,
-+	PJ_TRUE,
-+	4,
-+	{ OFFERER_UAC, OFFERER_UAS, OFFERER_UAC, OFFERER_UAS },
-+	PJ_TRUE
-+    },
- 
- };
- 
--- 
-2.33.1
-
diff --git a/third-party/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch b/third-party/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch
deleted file mode 100644
index 22df638..0000000
--- a/third-party/pjproject/patches/0140-Fix-incorrect-unescaping-of-tokens-during-parsing-29.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-From 3faf1d2b4da553bbaee04f9a13a5d084b381e5fb Mon Sep 17 00:00:00 2001
-From: sauwming <ming at teluu.com>
-Date: Tue, 4 Jan 2022 15:28:49 +0800
-Subject: [PATCH] Fix incorrect unescaping of tokens during parsing (#2933)
-
----
- pjsip/src/pjsip/sip_parser.c | 29 +++++++++++++++++++++++++----
- pjsip/src/test/msg_test.c    |  6 +++---
- 2 files changed, 28 insertions(+), 7 deletions(-)
-
-diff --git a/pjsip/src/pjsip/sip_parser.c b/pjsip/src/pjsip/sip_parser.c
-index c2add3299..b9a7c6a5c 100644
---- a/pjsip/src/pjsip/sip_parser.c
-+++ b/pjsip/src/pjsip/sip_parser.c
-@@ -378,17 +378,23 @@ static pj_status_t init_parser()
-     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-     pj_cis_add_str( &pconst.pjsip_TOKEN_SPEC, TOKEN);
- 
-+    /* Token is allowed to have '%' so we do not need this. */
-+    /*
-     status = pj_cis_dup(&pconst.pjsip_TOKEN_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC);
-     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-     pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%");
-+    */
- 
-     status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC);
-     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-     pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, "[:]");
- 
-+    /* Token is allowed to have '%' */
-+    /*
-     status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC);
-     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-     pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC_ESC, "[:]");
-+    */
- 
-     status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC);
-     PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-@@ -1210,7 +1216,11 @@ static void parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
- 			     unsigned option)
- {
-     /* pname */
--    parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
-+    if (!esc_spec) {
-+    	pj_scan_get(scanner, spec, pname);
-+    } else {
-+	parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
-+    }
- 
-     /* init pvalue */
-     pvalue->ptr = NULL;
-@@ -1240,7 +1250,12 @@ static void parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
- 		// pj_scan_get_until_ch(scanner, ']', pvalue);
- 		// pj_scan_get_char(scanner);
- 	    } else if(pj_cis_match(spec, *scanner->curptr)) {
--		parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue);
-+	    	if (!esc_spec) {
-+    		    pj_scan_get(scanner, spec, pvalue);
-+    		} else {
-+		    parser_get_and_unescape(scanner, pool, spec, esc_spec,
-+		    			    pvalue);
-+		}
- 	    }
- 	}
-     }
-@@ -1252,7 +1267,10 @@ PJ_DEF(void) pjsip_parse_param_imp(pj_scanner *scanner, pj_pool_t *pool,
- 			     	   unsigned option)
- {
-     parse_param_imp(scanner, pool, pname, pvalue, &pconst.pjsip_TOKEN_SPEC,
--		    &pconst.pjsip_TOKEN_SPEC_ESC, option);
-+		    // Token does not need to be unescaped.
-+		    // Refer to PR #2933.
-+		    // &pconst.pjsip_TOKEN_SPEC_ESC,
-+		    NULL, option);
- }
- 
- 
-@@ -2168,7 +2186,10 @@ static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
- 	pj_scan_get_char(scanner);
- 	parse_param_imp(scanner, pool, &pname, &pvalue,
- 			&pconst.pjsip_VIA_PARAM_SPEC,
--			&pconst.pjsip_VIA_PARAM_SPEC_ESC,
-+		    	// Token does not need to be unescaped.
-+		     	// Refer to PR #2933.
-+		    	// &pconst.pjsip_VIA_PARAM_SPEC_ESC,
-+			NULL,
- 			0);
- 
- 	if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
-diff --git a/pjsip/src/test/msg_test.c b/pjsip/src/test/msg_test.c
-index c511e1cf6..24e3d405d 100644
---- a/pjsip/src/test/msg_test.c
-+++ b/pjsip/src/test/msg_test.c
-@@ -953,7 +953,7 @@ static int hdr_test_subject_utf(pjsip_hdr *h);
- 
- 
- #define GENERIC_PARAM	     "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
--#define GENERIC_PARAM_PARSED "p0=a;p1=\"ab:;cd\";p2=ab:cd;p3"
-+#define GENERIC_PARAM_PARSED "p0=a;p1=\"ab:;cd\";p2=ab%3acd;p3"
- #define PARAM_CHAR	     "][/:&+$"
- #define SIMPLE_ADDR_SPEC     "sip:host"
- #define ADDR_SPEC	     SIMPLE_ADDR_SPEC ";"PARAM_CHAR"="PARAM_CHAR ";p1=\";\""
-@@ -1401,7 +1401,7 @@ static int generic_param_test(pjsip_param *param_head)
-     param = param->next;
-     if (pj_strcmp2(&param->name, "p2"))
- 	return -956;
--    if (pj_strcmp2(&param->value, "ab:cd"))
-+    if (pj_strcmp2(&param->value, "ab%3acd"))
- 	return -957;
- 
-     param = param->next;
-@@ -1621,7 +1621,7 @@ static int hdr_test_content_type(pjsip_hdr *h)
-     prm = prm->next;
-     if (prm == &hdr->media.param) return -1960;
-     if (pj_strcmp2(&prm->name, "p2")) return -1961;
--    if (pj_strcmp2(&prm->value, "ab:cd")) return -1962;
-+    if (pj_strcmp2(&prm->value, "ab%3acd")) return -1962;
- 
-     prm = prm->next;
-     if (prm == &hdr->media.param) return -1970;
--- 
-2.32.0
-
diff --git a/third-party/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch b/third-party/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch
deleted file mode 100644
index 6ddb346..0000000
--- a/third-party/pjproject/patches/0150-Create-generic-pjsip_hdr_find-functions.patch
+++ /dev/null
@@ -1,176 +0,0 @@
-From 7e3dfd8a15fd0f98dbf0e04d2d7a5bded90ee401 Mon Sep 17 00:00:00 2001
-From: George Joseph <gjoseph at sangoma.com>
-Date: Tue, 11 Jan 2022 09:27:23 -0700
-Subject: [PATCH] Create generic pjsip_hdr_find functions
-
-pjsip_msg_find_hdr(), pjsip_msg_find_hdr_by_name(), and
-pjsip_msg_find_hdr_by_names() require a pjsip_msg to be passed in
-so if you need to search a header list that's not in a pjsip_msg,
-you have to do it yourself.  This commit adds generic versions of
-those 3 functions that take in the actual header list head instead
-of a pjsip_msg so if you need to search a list of headers in
-something like a pjsip_multipart_part, you can do so easily.
----
- pjsip/include/pjsip/sip_msg.h | 53 +++++++++++++++++++++++++++++++++++
- pjsip/src/pjsip/sip_msg.c     | 51 +++++++++++++++++++++++----------
- 2 files changed, 89 insertions(+), 15 deletions(-)
-
-diff --git a/pjsip/include/pjsip/sip_msg.h b/pjsip/include/pjsip/sip_msg.h
-index 4c9100d39..e3502e94e 100644
---- a/pjsip/include/pjsip/sip_msg.h
-+++ b/pjsip/include/pjsip/sip_msg.h
-@@ -362,6 +362,59 @@ PJ_DECL(void*) pjsip_hdr_shallow_clone( pj_pool_t *pool, const void *hdr );
-  */
- PJ_DECL(int) pjsip_hdr_print_on( void *hdr, char *buf, pj_size_t len);
- 
-+/**
-+ * Find a header in a header list by the header type.
-+ *
-+ * @param hdr_list  The "head" of the header list.
-+ * @param type      The header type to find.
-+ * @param start     The first header field where the search should begin.
-+ *                  If NULL is specified, then the search will begin from the
-+ *                  first header, otherwise the search will begin at the
-+ *                  specified header.
-+ *
-+ * @return          The header field, or NULL if no header with the specified
-+ *                  type is found.
-+ */
-+PJ_DECL(void*)  pjsip_hdr_find( const void *hdr_list,
-+				pjsip_hdr_e type,
-+				const void *start);
-+
-+/**
-+ * Find a header in a header list by its name.
-+ *
-+ * @param hdr_list  The "head" of the header list.
-+ * @param name      The header name to find.
-+ * @param start     The first header field where the search should begin.
-+ *                  If NULL is specified, then the search will begin from the
-+ *                  first header, otherwise the search will begin at the
-+ *                  specified header.
-+ *
-+ * @return          The header field, or NULL if no header with the specified
-+ *                  type is found.
-+ */
-+PJ_DECL(void*)  pjsip_hdr_find_by_name( const void *hdr_list,
-+					const pj_str_t *name,
-+					const void *start);
-+
-+/**
-+ * Find a header in a header list by its name and short name version.
-+ *
-+ * @param hdr_list  The "head" of the header list.
-+ * @param name      The header name to find.
-+ * @param sname     The short name version of the header name.
-+ * @param start     The first header field where the search should begin.
-+ *                  If NULL is specified, then the search will begin from the
-+ *                  first header, otherwise the search will begin at the
-+ *                  specified header.
-+ *
-+ * @return	    The header field, or NULL if no header with the specified
-+ *		    type is found.
-+ */
-+PJ_DECL(void*)  pjsip_hdr_find_by_names( const void *hdr_list,
-+					 const pj_str_t *name,
-+					 const pj_str_t *sname,
-+					 const void *start);
-+
- /**
-  * @}
-  */
-diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c
-index 6ba3054da..2a6a96af0 100644
---- a/pjsip/src/pjsip/sip_msg.c
-+++ b/pjsip/src/pjsip/sip_msg.c
-@@ -356,13 +356,13 @@ PJ_DEF(pjsip_msg*) pjsip_msg_clone( pj_pool_t *pool, const pjsip_msg *src)
-     return dst;
- }
- 
--PJ_DEF(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg, 
--				   pjsip_hdr_e hdr_type, const void *start)
-+PJ_DEF(void*)  pjsip_hdr_find( const void *hdr_list,
-+			       pjsip_hdr_e hdr_type, const void *start)
- {
--    const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=&msg->hdr;
-+    const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
- 
-     if (hdr == NULL) {
--	hdr = msg->hdr.next;
-+	hdr = end->next;
-     }
-     for (; hdr!=end; hdr = hdr->next) {
- 	if (hdr->type == hdr_type)
-@@ -371,14 +371,14 @@ PJ_DEF(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg,
-     return NULL;
- }
- 
--PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg, 
--					   const pj_str_t *name, 
--					   const void *start)
-+PJ_DEF(void*)  pjsip_hdr_find_by_name( const void *hdr_list,
-+				       const pj_str_t *name,
-+				       const void *start)
- {
--    const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
-+    const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
- 
-     if (hdr == NULL) {
--	hdr = msg->hdr.next;
-+	hdr = end->next;
-     }
-     for (; hdr!=end; hdr = hdr->next) {
- 	if (pj_stricmp(&hdr->name, name) == 0)
-@@ -387,15 +387,15 @@ PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
-     return NULL;
- }
- 
--PJ_DEF(void*)  pjsip_msg_find_hdr_by_names( const pjsip_msg *msg, 
--					    const pj_str_t *name, 
--					    const pj_str_t *sname,
--					    const void *start)
-+PJ_DEF(void*)  pjsip_hdr_find_by_names( const void *hdr_list,
-+					const pj_str_t *name,
-+					const pj_str_t *sname,
-+					const void *start)
- {
--    const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
-+    const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=hdr_list;
- 
-     if (hdr == NULL) {
--	hdr = msg->hdr.next;
-+	hdr = end->next;
-     }
-     for (; hdr!=end; hdr = hdr->next) {
- 	if (pj_stricmp(&hdr->name, name) == 0)
-@@ -406,6 +406,27 @@ PJ_DEF(void*)  pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
-     return NULL;
- }
- 
-+PJ_DEF(void*)  pjsip_msg_find_hdr( const pjsip_msg *msg,
-+				   pjsip_hdr_e hdr_type, const void *start)
-+{
-+    return pjsip_hdr_find(&msg->hdr, hdr_type, start);
-+}
-+
-+PJ_DEF(void*)  pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
-+					   const pj_str_t *name,
-+					   const void *start)
-+{
-+    return pjsip_hdr_find_by_name(&msg->hdr, name, start);
-+}
-+
-+PJ_DEF(void*)  pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
-+					    const pj_str_t *name,
-+					    const pj_str_t *sname,
-+					    const void *start)
-+{
-+    return pjsip_hdr_find_by_names(&msg->hdr, name, sname, start);
-+}
-+
- PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg, 
- 				         pjsip_hdr_e hdr_type, void *start)
- {
--- 
-2.34.1
-
diff --git a/third-party/pjproject/patches/0160-Additional-multipart-improvements.patch b/third-party/pjproject/patches/0160-Additional-multipart-improvements.patch
deleted file mode 100644
index 373f9b8..0000000
--- a/third-party/pjproject/patches/0160-Additional-multipart-improvements.patch
+++ /dev/null
@@ -1,644 +0,0 @@
-From b7ecff22e77887626fd8e8608c4dd73bc7b7366f Mon Sep 17 00:00:00 2001
-From: George Joseph <gjoseph at sangoma.com>
-Date: Tue, 18 Jan 2022 06:14:31 -0700
-Subject: [PATCH] Additional multipart improvements
-
-Added the following APIs:
-pjsip_multipart_find_part_by_header()
-pjsip_multipart_find_part_by_header_str()
-pjsip_multipart_find_part_by_cid_str()
-pjsip_multipart_find_part_by_cid_uri()
----
- pjsip/include/pjsip/sip_multipart.h |  83 ++++++++++
- pjsip/src/pjsip/sip_multipart.c     | 223 +++++++++++++++++++++++++++
- pjsip/src/test/multipart_test.c     | 225 +++++++++++++++++++++++++++-
- 3 files changed, 530 insertions(+), 1 deletion(-)
-
-diff --git a/pjsip/include/pjsip/sip_multipart.h b/pjsip/include/pjsip/sip_multipart.h
-index 1c05767c5..c6b82b0b4 100644
---- a/pjsip/include/pjsip/sip_multipart.h
-+++ b/pjsip/include/pjsip/sip_multipart.h
-@@ -153,6 +153,89 @@ pjsip_multipart_find_part( const pjsip_msg_body *mp,
- 			   const pjsip_media_type *content_type,
- 			   const pjsip_multipart_part *start);
- 
-+/**
-+ * Find a body inside multipart bodies which has a header matching the
-+ * supplied one. Most useful for finding a part with a specific Content-ID.
-+ *
-+ * @param pool		Memory pool to use for temp space.
-+ * @param mp		The multipart body.
-+ * @param search_hdr	Header to search for.
-+ * @param start		If specified, the search will begin at
-+ * 			start->next part. Otherwise it will begin at
-+ * 			the first part in the multipart bodies.
-+ *
-+ * @return		The first part which has a header matching the
-+ * 			specified one, or NULL if not found.
-+ */
-+PJ_DECL(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_header(pj_pool_t *pool,
-+				    const pjsip_msg_body *mp,
-+				    void *search_hdr,
-+				    const pjsip_multipart_part *start);
-+
-+/**
-+ * Find a body inside multipart bodies which has a header matching the
-+ * supplied name and value. Most useful for finding a part with a specific
-+ * Content-ID.
-+ *
-+ * @param pool		Memory pool to use for temp space.
-+ * @param mp		The multipart body.
-+ * @param hdr_name	Header name to search for.
-+ * @param hdr_value	Header value search for.
-+ * @param start		If specified, the search will begin at
-+ * 			start->next part. Otherwise it will begin at
-+ * 			the first part in the multipart bodies.
-+ *
-+ * @return		The first part which has a header matching the
-+ * 			specified one, or NULL if not found.
-+ */
-+PJ_DECL(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_header_str(pj_pool_t *pool,
-+				    const pjsip_msg_body *mp,
-+				    const pj_str_t *hdr_name,
-+				    const pj_str_t *hdr_value,
-+				    const pjsip_multipart_part *start);
-+
-+
-+
-+/**
-+ * Find a body inside multipart bodies which has a Content-ID value matching the
-+ * supplied "cid" URI in pj_str form.  The "cid:" scheme will be assumed if the
-+ * URL doesn't start with it.  Enclosing angle brackets will also be handled
-+ * correctly if they exist.
-+ *
-+ * @see RFC2392 Content-ID and Message-ID Uniform Resource Locators
-+ *
-+ * @param pool	Memory pool to use for temp space.
-+ * @param mp	The multipart body.
-+ * @param cid	The "cid" URI to search for in pj_str form.
-+ *
-+ * @return		The first part which has a Content-ID header matching the
-+ * 			specified "cid" URI. or NULL if not found.
-+ */
-+PJ_DECL(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_cid_str(pj_pool_t *pool,
-+				 const pjsip_msg_body *mp,
-+				 pj_str_t *cid);
-+
-+/**
-+ * Find a body inside multipart bodies which has a Content-ID value matching the
-+ * supplied "cid" URI.
-+ *
-+ * @see RFC2392 Content-ID and Message-ID Uniform Resource Locators
-+ *
-+ * @param pool	Memory pool to use for temp space.
-+ * @param mp	The multipart body.
-+ * @param cid	The "cid" URI to search for.
-+ *
-+ * @return		The first part which had a Content-ID header matching the
-+ * 			specified "cid" URI. or NULL if not found.
-+ */
-+PJ_DECL(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_cid_uri(pj_pool_t *pool,
-+				 const pjsip_msg_body *mp,
-+				 pjsip_other_uri *cid_uri);
-+
- /**
-  * Parse multipart message.
-  *
-diff --git a/pjsip/src/pjsip/sip_multipart.c b/pjsip/src/pjsip/sip_multipart.c
-index e7d722d2e..9d8be55b0 100644
---- a/pjsip/src/pjsip/sip_multipart.c
-+++ b/pjsip/src/pjsip/sip_multipart.c
-@@ -19,6 +19,7 @@
- #include <pjsip/sip_multipart.h>
- #include <pjsip/sip_parser.h>
- #include <pjlib-util/scanner.h>
-+#include <pjlib-util/string.h>
- #include <pj/assert.h>
- #include <pj/ctype.h>
- #include <pj/errno.h>
-@@ -416,6 +417,220 @@ pjsip_multipart_find_part( const pjsip_msg_body *mp,
-     return NULL;
- }
- 
-+/*
-+ * Find a body inside multipart bodies which has the header and value.
-+ */
-+PJ_DEF(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_header_str(pj_pool_t *pool,
-+				    const pjsip_msg_body *mp,
-+				    const pj_str_t *hdr_name,
-+				    const pj_str_t *hdr_value,
-+				    const pjsip_multipart_part *start)
-+{
-+    struct multipart_data *m_data;
-+    pjsip_multipart_part *part;
-+    pjsip_hdr *found_hdr;
-+    pj_str_t found_hdr_str;
-+    pj_str_t found_hdr_value;
-+    pj_size_t expected_hdr_slen;
-+    pj_size_t buf_size;
-+    int hdr_name_len;
-+#define REASONABLE_PADDING 32
-+#define SEPARATOR_LEN 2
-+    /* Must specify mandatory params */
-+    PJ_ASSERT_RETURN(mp && hdr_name && hdr_value, NULL);
-+
-+    /* mp must really point to an actual multipart msg body */
-+    PJ_ASSERT_RETURN(mp->print_body==&multipart_print_body, NULL);
-+
-+    /*
-+     * We'll need to "print" each header we find to test it but
-+     * allocating a buffer of PJSIP_MAX_URL_SIZE is overkill.
-+     * Instead, we'll allocate one large enough to hold the search
-+     * header name, the ": " separator, the search hdr value, and
-+     * the NULL terminator.  If we can't print the found header
-+     * into that buffer then it can't be a match.
-+     *
-+     * Some header print functions such as generic_int require enough
-+     * space to print the maximum possible header length so we'll
-+     * add a reasonable amount to the print buffer size.
-+     */
-+    expected_hdr_slen = hdr_name->slen + SEPARATOR_LEN + hdr_value->slen;
-+    buf_size = expected_hdr_slen + REASONABLE_PADDING;
-+    found_hdr_str.ptr = pj_pool_alloc(pool, buf_size);
-+    found_hdr_str.slen = 0;
-+    hdr_name_len = hdr_name->slen + SEPARATOR_LEN;
-+
-+    m_data = (struct multipart_data*)mp->data;
-+
-+    if (start)
-+	part = start->next;
-+    else
-+	part = m_data->part_head.next;
-+
-+    while (part != &m_data->part_head) {
-+	found_hdr = NULL;
-+	while ((found_hdr = pjsip_hdr_find_by_name(&part->hdr, hdr_name,
-+	    (found_hdr ? found_hdr->next : NULL))) != NULL) {
-+
-+	    found_hdr_str.slen = pjsip_hdr_print_on((void*) found_hdr, found_hdr_str.ptr, buf_size);
-+	    /*
-+	     * If the buffer was too small (slen = -1) or the result wasn't
-+	     * the same length as the search header, it can't be a match.
-+	     */
-+	    if (found_hdr_str.slen != expected_hdr_slen) {
-+		continue;
-+	    }
-+	    /*
-+	     * Set the value overlay to start at the found header value...
-+	     */
-+	    found_hdr_value.ptr = found_hdr_str.ptr + hdr_name_len;
-+	    found_hdr_value.slen = found_hdr_str.slen - hdr_name_len;
-+	    /* ...and compare it to the supplied header value. */
-+	    if (pj_strcmp(hdr_value, &found_hdr_value) == 0) {
-+		return part;
-+	    }
-+	}
-+	part = part->next;
-+    }
-+    return NULL;
-+#undef SEPARATOR_LEN
-+#undef REASONABLE_PADDING
-+}
-+
-+PJ_DEF(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_header(pj_pool_t *pool,
-+				    const pjsip_msg_body *mp,
-+				    void *search_for,
-+				    const pjsip_multipart_part *start)
-+{
-+    struct multipart_data *m_data;
-+    pjsip_hdr *search_hdr = search_for;
-+    pj_str_t search_buf;
-+
-+    /* Must specify mandatory params */
-+    PJ_ASSERT_RETURN(mp && search_hdr, NULL);
-+
-+    /* mp must really point to an actual multipart msg body */
-+    PJ_ASSERT_RETURN(mp->print_body==&multipart_print_body, NULL);
-+
-+    /*
-+     * Unfortunately, there isn't enough information to determine
-+     * the maximum printed size of search_hdr at this point so we
-+     * have to allocate a reasonable max.
-+     */
-+    search_buf.ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
-+    search_buf.slen = pjsip_hdr_print_on(search_hdr, search_buf.ptr, PJSIP_MAX_URL_SIZE - 1);
-+    if (search_buf.slen <= 0) {
-+	return NULL;
-+    }
-+    /*
-+     * Set the header value to start after the header name plus the ":", then
-+     * strip leading and trailing whitespace.
-+     */
-+    search_buf.ptr += (search_hdr->name.slen + 1);
-+    search_buf.slen -= (search_hdr->name.slen + 1);
-+    pj_strtrim(&search_buf);
-+
-+    return pjsip_multipart_find_part_by_header_str(pool, mp, &search_hdr->name, &search_buf, start);
-+}
-+
-+/*
-+ * Convert a Content-ID URI to it's corresponding header value.
-+ * RFC2392 says...
-+ * A "cid" URL is converted to the corresponding Content-ID message
-+ * header by removing the "cid:" prefix, converting the % encoded
-+ * character(s) to their equivalent US-ASCII characters, and enclosing
-+ * the remaining parts with an angle bracket pair, "<" and ">".
-+ *
-+ * This implementation will accept URIs with or without the "cid:"
-+ * scheme and optional angle brackets.
-+ */
-+static pj_str_t cid_uri_to_hdr_value(pj_pool_t *pool, pj_str_t *cid_uri)
-+{
-+    pj_size_t cid_len = pj_strlen(cid_uri);
-+    pj_size_t alloc_len = cid_len + 2 /* for the leading and trailing angle brackets */;
-+    pj_str_t uri_overlay;
-+    pj_str_t cid_hdr;
-+    pj_str_t hdr_overlay;
-+
-+    pj_strassign(&uri_overlay, cid_uri);
-+    /* If the URI is already enclosed in angle brackets, remove them. */
-+    if (uri_overlay.ptr[0] == '<') {
-+	uri_overlay.ptr++;
-+	uri_overlay.slen -= 2;
-+    }
-+    /* If the URI starts with the "cid:" scheme, skip over it. */
-+    if (pj_strncmp2(&uri_overlay, "cid:", 4) == 0) {
-+	uri_overlay.ptr += 4;
-+	uri_overlay.slen -= 4;
-+    }
-+    /* Start building */
-+    cid_hdr.ptr = pj_pool_alloc(pool, alloc_len);
-+    cid_hdr.ptr[0] = '<';
-+    cid_hdr.slen = 1;
-+    hdr_overlay.ptr = cid_hdr.ptr + 1;
-+    hdr_overlay.slen = 0;
-+    pj_strcpy_unescape(&hdr_overlay, &uri_overlay);
-+    cid_hdr.slen += hdr_overlay.slen;
-+    cid_hdr.ptr[cid_hdr.slen] = '>';
-+    cid_hdr.slen++;
-+
-+    return cid_hdr;
-+}
-+
-+PJ_DEF(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_cid_str(pj_pool_t *pool,
-+				 const pjsip_msg_body *mp,
-+				 pj_str_t *cid)
-+{
-+    struct multipart_data *m_data;
-+    pjsip_multipart_part *part;
-+    pjsip_generic_string_hdr *found_hdr;
-+    pj_str_t found_hdr_value;
-+    static pj_str_t hdr_name = { "Content-ID", 10};
-+    pj_str_t hdr_value;
-+
-+    PJ_ASSERT_RETURN(pool && mp && cid && (pj_strlen(cid) > 0), NULL);
-+
-+    hdr_value = cid_uri_to_hdr_value(pool, cid);
-+    if (pj_strlen(&hdr_value) == 0) {
-+	return NULL;
-+    }
-+
-+    m_data = (struct multipart_data*)mp->data;
-+    part = m_data->part_head.next;
-+
-+    while (part != &m_data->part_head) {
-+	found_hdr = NULL;
-+	while ((found_hdr = pjsip_hdr_find_by_name(&part->hdr, &hdr_name,
-+	    (found_hdr ? found_hdr->next : NULL))) != NULL) {
-+	    if (pj_strcmp(&hdr_value, &found_hdr->hvalue) == 0) {
-+		return part;
-+	    }
-+	}
-+	part = part->next;
-+    }
-+    return NULL;
-+}
-+
-+PJ_DEF(pjsip_multipart_part*)
-+pjsip_multipart_find_part_by_cid_uri(pj_pool_t *pool,
-+				 const pjsip_msg_body *mp,
-+				 pjsip_other_uri *cid_uri)
-+{
-+    PJ_ASSERT_RETURN(pool && mp && cid_uri, NULL);
-+
-+    if (pj_strcmp2(&cid_uri->scheme, "cid") != 0) {
-+	return NULL;
-+    }
-+    /*
-+     * We only need to pass the URI content so we
-+     * can do that directly.
-+     */
-+    return pjsip_multipart_find_part_by_cid_str(pool, mp, &cid_uri->content);
-+}
-+
- /* Parse a multipart part. "pct" is parent content-type  */
- static pjsip_multipart_part *parse_multipart_part(pj_pool_t *pool,
- 						  char *start,
-@@ -584,6 +799,7 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
- 		(int)boundary.slen, boundary.ptr));
-     }
- 
-+
-     /* Build the delimiter:
-      *   delimiter = "--" boundary
-      */
-@@ -630,6 +846,8 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
- 	if (*curptr=='\r') ++curptr;
- 	if (*curptr!='\n') {
- 	    /* Expecting a newline here */
-+	    PJ_LOG(2, (THIS_FILE, "Failed to find newline"));
-+
- 	    return NULL;
- 	}
- 	++curptr;
-@@ -645,6 +863,7 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
- 	    curptr = pj_strstr(&subbody, &delim);
- 	    if (!curptr) {
- 		/* We're really expecting end delimiter to be found. */
-+		PJ_LOG(2, (THIS_FILE, "Failed to find end-delimiter"));
- 		return NULL;
- 	    }
- 	}
-@@ -670,9 +889,13 @@ PJ_DEF(pjsip_msg_body*) pjsip_multipart_parse(pj_pool_t *pool,
- 	part = parse_multipart_part(pool, start_body, end_body - start_body,
- 				    ctype);
- 	if (part) {
-+	    TRACE_((THIS_FILE, "Adding part"));
- 	    pjsip_multipart_add_part(pool, body, part);
-+	} else {
-+	    PJ_LOG(2, (THIS_FILE, "Failed to add part"));
- 	}
-     }
-+    TRACE_((THIS_FILE, "pjsip_multipart_parse finished: %p", body));
- 
-     return body;
- }
-diff --git a/pjsip/src/test/multipart_test.c b/pjsip/src/test/multipart_test.c
-index 4f16e68bf..97267a290 100644
---- a/pjsip/src/test/multipart_test.c
-+++ b/pjsip/src/test/multipart_test.c
-@@ -28,6 +28,7 @@
- typedef pj_status_t (*verify_ptr)(pj_pool_t*,pjsip_msg_body*);
- 
- static pj_status_t verify1(pj_pool_t *pool, pjsip_msg_body *body);
-+static pj_status_t verify2(pj_pool_t *pool, pjsip_msg_body *body);
- 
- static struct test_t
- {
-@@ -68,7 +69,41 @@ static struct test_t
- 		"This is epilogue, which should be ignored too",
- 
- 		&verify1
-+	},
-+	{
-+		/* Content-type */
-+		"multipart", "mixed", "12345",
-+
-+		/* Body: */
-+		"This is the prolog, which should be ignored.\r\n"
-+		"--12345\r\n"
-+		"Content-Type: text/plain\r\n"
-+		"Content-ID: <header1 at example.org>\r\n"
-+		"Content-ID: <\"header1\"@example.org>\r\n"
-+		"Content-Length: 13\r\n"
-+		"\r\n"
-+		"has header1\r\n"
-+		"--12345 \t\r\n"
-+		"Content-Type: application/pidf+xml\r\n"
-+		"Content-ID: <my header2 at example.org>\r\n"
-+		"Content-ID: <my\xffheader2 at example.org>\r\n"
-+		"Content-Length: 13\r\n"
-+		"\r\n"
-+		"has header2\r\n"
-+		"--12345\r\n"
-+		"Content-Type: text/plain\r\n"
-+		"Content-ID: <my header3 at example.org>\r\n"
-+		"Content-ID: <header1 at example.org>\r\n"
-+		"Content-ID: <my header4 at example.org>\r\n"
-+		"Content-Length: 13\r\n"
-+		"\r\n"
-+		"has header4\r\n"
-+		"--12345--\r\n"
-+		"This is epilogue, which should be ignored too",
-+
-+		&verify2
- 	}
-+
- };
- 
- static void init_media_type(pjsip_media_type *mt,
-@@ -87,6 +122,192 @@ static void init_media_type(pjsip_media_type *mt,
-     }
- }
- 
-+static int verify_hdr(pj_pool_t *pool, pjsip_msg_body *multipart_body,
-+    void *hdr, char *part_body)
-+{
-+    pjsip_media_type mt;
-+    pjsip_multipart_part *part;
-+    pj_str_t the_body;
-+
-+
-+    part = pjsip_multipart_find_part_by_header(pool, multipart_body, hdr, NULL);
-+    if (!part) {
-+	return -1;
-+    }
-+
-+    the_body.ptr = (char*)part->body->data;
-+    the_body.slen = part->body->len;
-+
-+    if (pj_strcmp2(&the_body, part_body) != 0) {
-+	return -2;
-+    }
-+
-+    return 0;
-+}
-+
-+static int verify_cid_str(pj_pool_t *pool, pjsip_msg_body *multipart_body,
-+    pj_str_t cid_url, char *part_body)
-+{
-+    pjsip_media_type mt;
-+    pjsip_multipart_part *part;
-+    pj_str_t the_body;
-+
-+    part = pjsip_multipart_find_part_by_cid_str(pool, multipart_body, &cid_url);
-+    if (!part) {
-+	return -3;
-+    }
-+
-+    the_body.ptr = (char*)part->body->data;
-+    the_body.slen = part->body->len;
-+
-+    if (pj_strcmp2(&the_body, part_body) != 0) {
-+	return -4;
-+    }
-+
-+    return 0;
-+}
-+
-+static int verify_cid_uri(pj_pool_t *pool, pjsip_msg_body *multipart_body,
-+    pjsip_other_uri *cid_uri, char *part_body)
-+{
-+    pjsip_media_type mt;
-+    pjsip_multipart_part *part;
-+    pj_str_t the_body;
-+
-+    part = pjsip_multipart_find_part_by_cid_uri(pool, multipart_body, cid_uri);
-+    if (!part) {
-+	return -5;
-+    }
-+
-+    the_body.ptr = (char*)part->body->data;
-+    the_body.slen = part->body->len;
-+
-+    if (pj_strcmp2(&the_body, part_body) != 0) {
-+	return -6;
-+    }
-+
-+    return 0;
-+}
-+
-+static pj_status_t verify2(pj_pool_t *pool, pjsip_msg_body *body)
-+{
-+    int rc = 0;
-+    int rcbase = 300;
-+    pjsip_other_uri *cid_uri;
-+    pjsip_ctype_hdr *ctype_hdr = pjsip_ctype_hdr_create(pool);
-+
-+    ctype_hdr->media.type = pj_str("application");
-+    ctype_hdr->media.subtype = pj_str("pidf+xml");
-+
-+    rc = verify_hdr(pool, body, ctype_hdr, "has header2");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("cid:header1 at example.org"), "has header1");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("%22header1%22 at example.org"), "has header1");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:%22header1%22 at example.org>",
-+	strlen("<cid:%22header1%22 at example.org>"), 0));
-+    rcbase += 10;
-+    rc = verify_cid_uri(pool, body, cid_uri, "has header1");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("<cid:my%20header2 at example.org>"), "has header2");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("cid:my%ffheader2 at example.org"), "has header2");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:my%ffheader2 at example.org>",
-+	strlen("<cid:my%ffheader2 at example.org>"), 0));
-+    rcbase += 10;
-+    rc = verify_cid_uri(pool, body, cid_uri, "has header2");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("cid:my%20header3 at example.org"), "has header4");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("<cid:my%20header4 at example.org>"), "has header4");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    cid_uri = pjsip_uri_get_uri(pjsip_parse_uri(pool, "<cid:my%20header4 at example.org>",
-+	strlen("<cid:my%20header4 at example.org>"), 0));
-+    rcbase += 10;
-+    rc = verify_cid_uri(pool, body, cid_uri, "has header4");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("<my%20header3 at example.org>"), "has header4");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    /* These should all fail for malformed or missing URI */
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("cid:"), "has header4");
-+    if (!rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str(""), "has header4");
-+    if (!rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("<>"), "has header4");
-+    if (!rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("<cid>"), "has header4");
-+    if (!rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    /*
-+     * This is going to pass but the ' ' in the uri is un-encoded which is invalid
-+     * so we should never see it.
-+     */
-+    rcbase += 10;
-+    rc = verify_cid_str(pool, body, pj_str("cid:my header3 at example.org"), "has header4");
-+    if (rc) {
-+	return (rc - rcbase);
-+    }
-+
-+    return 0;
-+}
-+
- static int verify_part(pjsip_multipart_part *part,
- 		       char *h_content_type,
- 		       char *h_content_subtype,
-@@ -236,8 +457,10 @@ static int parse_test(void)
- 
- 	pj_strdup2_with_null(pool, &str, p_tests[i].msg);
- 	body = pjsip_multipart_parse(pool, str.ptr, str.slen, &ctype, 0);
--	if (!body)
-+	if (!body) {
-+	    pj_pool_release(pool);
- 	    return -100;
-+	}
- 
- 	if (p_tests[i].verify) {
- 	    rc = p_tests[i].verify(pool, body);
--- 
-2.34.1
-
diff --git a/third-party/pjproject/pjproject-2.10.tar.bz2.md5 b/third-party/pjproject/pjproject-2.10.tar.bz2.md5
deleted file mode 100644
index 57261b4..0000000
--- a/third-party/pjproject/pjproject-2.10.tar.bz2.md5
+++ /dev/null
@@ -1,2 +0,0 @@
-5d0202f79a7aeb14873c45b0e4c14a70 *pjproject-2.10.zip
-4fffc49b461133f0a4143b05a22fb30e  pjproject-2.10.tar.bz2
diff --git a/third-party/pjproject/pjproject-2.12.tar.bz2.md5 b/third-party/pjproject/pjproject-2.12.tar.bz2.md5
new file mode 100644
index 0000000..ab9b9d4
--- /dev/null
+++ b/third-party/pjproject/pjproject-2.12.tar.bz2.md5
@@ -0,0 +1 @@
+ad796d38f5f0357cb5b2fe1b4460b581  pjproject-2.12.tar.bz2
diff --git a/third-party/versions.mak b/third-party/versions.mak
index 2a59cf4..b95d687 100644
--- a/third-party/versions.mak
+++ b/third-party/versions.mak
@@ -1,2 +1,2 @@
 JANSSON_VERSION = 2.14
-PJPROJECT_VERSION = 2.10
+PJPROJECT_VERSION = 2.12

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

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: Id39ece02dedb7b9f739e0e37ea47d76854af7191
Gerrit-Change-Number: 18114
Gerrit-PatchSet: 1
Gerrit-Owner: Joshua Colp <jcolp at sangoma.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220228/c4820351/attachment-0001.html>


More information about the asterisk-code-review mailing list