include $(TOPDIR)/rules.mk
PKG_NAME:=pjproject
-PKG_VERSION:=2.8
-PKG_RELEASE:=3
-
-PKG_SOURCE:=pjproject-$(PKG_VERSION).tar.bz2
-PKG_SOURCE_URL:=http://www.pjsip.org/release/$(PKG_VERSION)
-PKG_HASH:=503d0bd7f9f13dc1492ac9b71b761b1089851fbb608b9a13996edc3c42006f79
+PKG_VERSION:=2.10
+PKG_RELEASE:=1
+
+# download "vX.Y.tar.gz" as "pjproject-vX.Y.tar.gz"
+PKG_SOURCE_URL_FILE:=$(PKG_VERSION).tar.gz
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_URL_FILE)
+PKG_SOURCE_URL:=https://github.com/pjsip/$(PKG_NAME)/archive
+PKG_HASH:=936a4c5b98601b52325463a397ddf11ab4106c6a7b04f8dc7cdd377efbb597de
PKG_INSTALL:=1
-PKG_FIXUP:=autoreconf
PKG_LICENSE:=GPL-2.0
PKG_LICENSE_FILES:=COPYING
SECTION:=lib
CATEGORY:=Libraries
SUBMENU:=Telephony
- URL:=http://www.pjsip.org
+ URL:=https://www.pjsip.org
DEPENDS:=$(CXX_DEPENDS) +libopenssl +libuuid +libpthread
endef
CONFIGURE_ARGS+= \
$(if $(CONFIG_SOFT_FLOAT),--disable-floating-point) \
--disable-bcg729 \
+ --disable-darwin-ssl \
--disable-ext-sound \
--disable-ffmpeg \
--disable-g711-codec \
TARGET_CFLAGS+=$(TARGET_CPPFLAGS)
define Build/Compile
+ $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) dep
$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)
endef
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(SED) 's|$(TARGET_CFLAGS)||g' $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libpjproject.pc
- $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libpjproject.pc $(1)/usr/lib/pkgconfig
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libpjproject.pc \
+ $(1)/usr/lib/pkgconfig
endef
$(eval $(call PJSIPpackage,libpj,libpj,+librt))
--- /dev/null
+--- a/build/cc-auto.mak.in
++++ b/build/cc-auto.mak.in
+@@ -2,7 +2,7 @@ export CC = @CC@ -c
+ export CXX = @CXX@ -c
+ export AR = @AR@
+ export AR_FLAGS = @AR_FLAGS@
+-export LD = @LD@
++export LD = @CXX@
+ export LDOUT = -o
+ export RANLIB = @RANLIB@
+
--- /dev/null
+--- a/build/rules.mak
++++ b/build/rules.mak
+@@ -13,7 +13,7 @@ SHLIB = $($(APP)_SHLIB)
+ SONAME = $($(APP)_SONAME)
+
+ ifeq ($(SHLIB_SUFFIX),so)
+-SHLIB_OPT := -shared -Wl,-soname,$(SHLIB)
++SHLIB_OPT := -shared
+ else ifeq ($(SHLIB_SUFFIX),dylib)
+ SHLIB_OPT := -dynamiclib -undefined dynamic_lookup -flat_namespace
+ else ifeq ($(SHLIB_SUFFIX),dll)
--- /dev/null
+--- a/pjlib/src/pj/os_core_unix.c
++++ b/pjlib/src/pj/os_core_unix.c
+@@ -1139,7 +1139,7 @@ static pj_status_t init_mutex(pj_mutex_t
+ return PJ_RETURN_OS_ERROR(rc);
+
+ if (type == PJ_MUTEX_SIMPLE) {
+-#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
++#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
+ defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+ #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
+@@ -1149,7 +1149,7 @@ static pj_status_t init_mutex(pj_mutex_t
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+ #endif
+ } else {
+-#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
++#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
+ defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
+ rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
--- /dev/null
+--- /dev/null
++++ b/pjlib/include/pj/config_site.h
+@@ -0,0 +1,79 @@
++/*
++ * Asterisk config_site.h
++ */
++
++#include <sys/select.h>
++
++/*
++ * Defining PJMEDIA_HAS_SRTP to 0 does NOT disable Asterisk's ability to use srtp.
++ * It only disables the pjmedia srtp transport which Asterisk doesn't use.
++ * The reason for the disable is that while Asterisk works fine with older libsrtp
++ * versions, newer versions of pjproject won't compile with them.
++ */
++#define PJMEDIA_HAS_SRTP 0
++
++#define PJ_HAS_IPV6 1
++#define NDEBUG 1
++
++#define PJ_MAX_HOSTNAME (256)
++#define PJSIP_MAX_URL_SIZE (512)
++#ifdef PJ_HAS_LINUX_EPOLL
++#define PJ_IOQUEUE_MAX_HANDLES (5000)
++#else
++#define PJ_IOQUEUE_MAX_HANDLES (FD_SETSIZE)
++#endif
++#define PJ_IOQUEUE_HAS_SAFE_UNREG 1
++#define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16)
++
++#define PJ_SCANNER_USE_BITWISE 0
++#define PJ_OS_HAS_CHECK_STACK 0
++
++#ifndef PJ_LOG_MAX_LEVEL
++#define PJ_LOG_MAX_LEVEL 6
++#endif
++
++#define PJ_ENABLE_EXTRA_CHECK 1
++#define PJSIP_MAX_TSX_COUNT ((64*1024)-1)
++#define PJSIP_MAX_DIALOG_COUNT ((64*1024)-1)
++#define PJSIP_UDP_SO_SNDBUF_SIZE (512*1024)
++#define PJSIP_UDP_SO_RCVBUF_SIZE (512*1024)
++#define PJ_DEBUG 0
++#define PJSIP_SAFE_MODULE 0
++#define PJ_HAS_STRICMP_ALNUM 0
++
++/*
++ * Do not ever enable PJ_HASH_USE_OWN_TOLOWER because the algorithm is
++ * inconsistently used when calculating the hash value and doesn't
++ * convert the same characters as pj_tolower()/tolower(). Thus you
++ * can get different hash values if the string hashed has certain
++ * characters in it. (ASCII '@', '[', '\\', ']', '^', and '_')
++ */
++#undef PJ_HASH_USE_OWN_TOLOWER
++
++/*
++ It is imperative that PJSIP_UNESCAPE_IN_PLACE remain 0 or undefined.
++ Enabling it will result in SEGFAULTS when URIs containing escape sequences are encountered.
++*/
++#undef PJSIP_UNESCAPE_IN_PLACE
++#define PJSIP_MAX_PKT_LEN 65535
++
++#undef PJ_TODO
++#define PJ_TODO(x)
++
++/* Defaults too low for WebRTC */
++#define PJ_ICE_MAX_CAND 64
++#define PJ_ICE_MAX_CHECKS (PJ_ICE_MAX_CAND * PJ_ICE_MAX_CAND)
++
++/* Increase limits to allow more formats */
++#define PJMEDIA_MAX_SDP_FMT 64
++#define PJMEDIA_MAX_SDP_BANDW 4
++#define PJMEDIA_MAX_SDP_ATTR (PJMEDIA_MAX_SDP_FMT*2 + 4)
++#define PJMEDIA_MAX_SDP_MEDIA 16
++
++/*
++ * Turn off the periodic sending of CRLNCRLN. Default is on (90 seconds),
++ * which conflicts with the global section's keep_alive_interval option in
++ * pjsip.conf.
++ */
++#define PJSIP_TCP_KEEP_ALIVE_INTERVAL 0
++#define PJSIP_TLS_KEEP_ALIVE_INTERVAL 0
--- /dev/null
+--- a/build.mak.in
++++ b/build.mak.in
+@@ -296,7 +296,6 @@ export APP_LDLIBS := $(PJSUA_LIB_LDLIB)
+ $(PJLIB_LDLIB) \
+ @LIBS@
+ export APP_LDXXLIBS := $(PJSUA2_LIB_LDLIB) \
+- -lstdc++ \
+ $(APP_LDLIBS)
+
+ # Here are the variabels to use if application is using the library
+--- a/pjsip/build/Makefile
++++ b/pjsip/build/Makefile
+@@ -152,8 +152,7 @@ export PJSUA2_LIB_LDFLAGS += $(PJSUA_LIB
+ $(PJNATH_LDLIB) \
+ $(PJLIB_UTIL_LDLIB) \
+ $(PJLIB_LDLIB) \
+- $(_LDFLAGS) \
+- -lstdc++
++ $(_LDFLAGS)
+
+
+ ###############################################################################
--- /dev/null
+--- a/libpjproject.pc.in
++++ b/libpjproject.pc.in
+@@ -2,8 +2,8 @@
+
+ prefix=@PREFIX@
+ exec_prefix=${prefix}
+-libdir=@LIBDIR@
+-includedir=@INCLUDEDIR@
++libdir=${exec_prefix}/lib
++includedir=${prefix}/include
+
+ Name: libpjproject
+ Description: Multimedia communication library
+--- a/build.mak.in
++++ b/build.mak.in
+@@ -314,8 +314,7 @@ export PJ_LIBXX_FILES := $(APP_LIBXX_FIL
+ # And here are the variables to use if application is using the
+ # library from the install location (i.e. --prefix)
+ export PJ_INSTALL_DIR := @prefix@
+-export PJ_INSTALL_INC_DIR := @includedir@
+ export PJ_INSTALL_LIB_DIR := @libdir@
+-export PJ_INSTALL_CFLAGS := -I$(PJ_INSTALL_INC_DIR) -DPJ_AUTOCONF=1 @CFLAGS@
++export PJ_INSTALL_CFLAGS := -DPJ_AUTOCONF=1 @CFLAGS@
+ export PJ_INSTALL_CXXFLAGS := @CXXFLAGS@ $(PJ_INSTALL_CFLAGS)
+ export PJ_INSTALL_LDFLAGS := -L$(PJ_INSTALL_LIB_DIR) $(APP_LDLIBS)
+++ /dev/null
---- a/build/cc-auto.mak.in
-+++ b/build/cc-auto.mak.in
-@@ -2,7 +2,7 @@ export CC = @CC@ -c
- export CXX = @CXX@ -c
- export AR = @AR@
- export AR_FLAGS = @AR_FLAGS@
--export LD = @LD@
-+export LD = @CXX@
- export LDOUT = -o
- export RANLIB = @RANLIB@
-
--- /dev/null
+commit c3c1bf45cae2a35003aa16c267d59f97027f9c5e
+Author: Kevin Harwell <kharwell@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
+
+--- 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_sess
+ (*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);
+ }
--- /dev/null
+commit 40dd48d10911f4ff9b8dfbf16428fbc9acc434ba
+Author: Riza Sulistyo <trengginas@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.
+
+--- 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;
+
+--- 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;
+ }
--- /dev/null
+From 78683646c8bc670ec730a42494e075f671a08e28 Mon Sep 17 00:00:00 2001
+From: Guido Falsi <mad@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(-)
+
+--- 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),$<)
+--- a/pjsip/build/Makefile
++++ b/pjsip/build/Makefile
+@@ -261,7 +261,7 @@ $(PJSUA_LIB_LIB) $(PJSUA_LIB_SONAME): $(
+
+ 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)
--- /dev/null
+--- a/pjmedia/src/pjmedia/sdp_neg.c
++++ b/pjmedia/src/pjmedia/sdp_neg.c
+@@ -906,7 +906,7 @@ static pj_status_t process_m_answer( pj_
+ * 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 @@ static pj_status_t process_answer(pj_poo
+ 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,
--- /dev/null
+From ce18018cc17bef8f80c08686e3a7b28384ef3ba5 Mon Sep 17 00:00:00 2001
+From: sauwming <ming@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(-)
+
+--- 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_c
+ 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.
+ */
--- /dev/null
+--- 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_modi
+ {
+ 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_modi
+ /* 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);
+
--- /dev/null
+From bdbeb7c4b2b11efc2e59f5dee7aa4360a2bc9fff Mon Sep 17 00:00:00 2001
+From: sauwming <ming@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@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
+
+--- 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
+ 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
+ {
+ 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
+ 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_reini
+ {
+ 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_reini
+ */
+ 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_reini
+ */
+ 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_reini
+
+ /* 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;
+--- /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@localhost --username=a --realm=* --registrar=$SIPP_URI"]
++
++PJSUA_EXPECTS = [[0, "registration success", ""]]
+--- /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>
++
--- /dev/null
+commit f0ff5817d0647bdecd1ec99488db9378e304cf83
+Author: sauwming <ming@teluu.com>
+Date: Mon May 17 09:56:27 2021 +0800
+
+ Fix double free of stun session (#2709)
+
+--- 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. */
+
+--- 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_dat
+ 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_dat
+ /* "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_he
+ 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;
+ }
--- /dev/null
+From bb92c97ea512aa0ef316c9b2335c7d57b84dfc9a Mon Sep 17 00:00:00 2001
+From: Nanang Izzuddin <nanang@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(-)
+
+--- 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(p
+
+ /* 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(p
+ 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(p
+
+ 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_complet
+ 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_complet
+ 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 */
+--- 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_
+ 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_
+ 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(¶m, sizeof(param));
+@@ -1401,6 +1420,8 @@ static pj_bool_t on_accept_complete2(pj_
+ 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(¶m, sizeof(param));
--- /dev/null
+From 68c69f516f95df1faa42e5647e9ce7cfdc41ac38 Mon Sep 17 00:00:00 2001
+From: Nanang Izzuddin <nanang@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(-)
+
+--- a/pjlib/src/pj/ssl_sock_imp_common.c
++++ b/pjlib/src/pj/ssl_sock_imp_common.c
+@@ -949,6 +949,7 @@ static pj_bool_t asock_on_accept_complet
+
+ /* 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;
+@@ -964,7 +965,7 @@ static pj_bool_t asock_on_accept_complet
+ 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);
+ }
+--- 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(c
+ 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(
+ /* 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 nu
+ }
+
+
+-/* 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, X
+ 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 *s
+ 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
--- /dev/null
+From 2ae784030b0d9cf217c3d562af20e4967f19a3dc Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@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(-)
+
+--- 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
+
+ /* 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;
+ }
+++ /dev/null
---- a/build/rules.mak
-+++ b/build/rules.mak
-@@ -13,7 +13,7 @@ SHLIB = $($(APP)_SHLIB)
- SONAME = $($(APP)_SONAME)
-
- ifeq ($(SHLIB_SUFFIX),so)
--SHLIB_OPT := -shared -Wl,-soname,$(SHLIB)
-+SHLIB_OPT := -shared
- else ifeq ($(SHLIB_SUFFIX),dylib)
- SHLIB_OPT := -dynamiclib -undefined dynamic_lookup -flat_namespace
- else ifeq ($(SHLIB_SUFFIX),dll)
+++ /dev/null
---- a/pjlib/src/pj/os_core_unix.c
-+++ b/pjlib/src/pj/os_core_unix.c
-@@ -1139,7 +1139,7 @@ static pj_status_t init_mutex(pj_mutex_t
- return PJ_RETURN_OS_ERROR(rc);
-
- if (type == PJ_MUTEX_SIMPLE) {
--#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
-+#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
- defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
- #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
-@@ -1149,7 +1149,7 @@ static pj_status_t init_mutex(pj_mutex_t
- rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
- #endif
- } else {
--#if (defined(PJ_LINUX) && PJ_LINUX!=0) || \
-+#if (defined(PJ_LINUX) && PJ_LINUX!=0 && defined(__GLIBC__)) || \
- defined(PJ_HAS_PTHREAD_MUTEXATTR_SETTYPE)
- rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- #elif (defined(PJ_RTEMS) && PJ_RTEMS!=0) || \
+++ /dev/null
---- /dev/null
-+++ b/pjlib/include/pj/config_site.h
-@@ -0,0 +1,79 @@
-+/*
-+ * Asterisk config_site.h
-+ */
-+
-+#include <sys/select.h>
-+
-+/*
-+ * Defining PJMEDIA_HAS_SRTP to 0 does NOT disable Asterisk's ability to use srtp.
-+ * It only disables the pjmedia srtp transport which Asterisk doesn't use.
-+ * The reason for the disable is that while Asterisk works fine with older libsrtp
-+ * versions, newer versions of pjproject won't compile with them.
-+ */
-+#define PJMEDIA_HAS_SRTP 0
-+
-+#define PJ_HAS_IPV6 1
-+#define NDEBUG 1
-+
-+#define PJ_MAX_HOSTNAME (256)
-+#define PJSIP_MAX_URL_SIZE (512)
-+#ifdef PJ_HAS_LINUX_EPOLL
-+#define PJ_IOQUEUE_MAX_HANDLES (5000)
-+#else
-+#define PJ_IOQUEUE_MAX_HANDLES (FD_SETSIZE)
-+#endif
-+#define PJ_IOQUEUE_HAS_SAFE_UNREG 1
-+#define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16)
-+
-+#define PJ_SCANNER_USE_BITWISE 0
-+#define PJ_OS_HAS_CHECK_STACK 0
-+
-+#ifndef PJ_LOG_MAX_LEVEL
-+#define PJ_LOG_MAX_LEVEL 6
-+#endif
-+
-+#define PJ_ENABLE_EXTRA_CHECK 1
-+#define PJSIP_MAX_TSX_COUNT ((64*1024)-1)
-+#define PJSIP_MAX_DIALOG_COUNT ((64*1024)-1)
-+#define PJSIP_UDP_SO_SNDBUF_SIZE (512*1024)
-+#define PJSIP_UDP_SO_RCVBUF_SIZE (512*1024)
-+#define PJ_DEBUG 0
-+#define PJSIP_SAFE_MODULE 0
-+#define PJ_HAS_STRICMP_ALNUM 0
-+
-+/*
-+ * Do not ever enable PJ_HASH_USE_OWN_TOLOWER because the algorithm is
-+ * inconsistently used when calculating the hash value and doesn't
-+ * convert the same characters as pj_tolower()/tolower(). Thus you
-+ * can get different hash values if the string hashed has certain
-+ * characters in it. (ASCII '@', '[', '\\', ']', '^', and '_')
-+ */
-+#undef PJ_HASH_USE_OWN_TOLOWER
-+
-+/*
-+ It is imperative that PJSIP_UNESCAPE_IN_PLACE remain 0 or undefined.
-+ Enabling it will result in SEGFAULTS when URIs containing escape sequences are encountered.
-+*/
-+#undef PJSIP_UNESCAPE_IN_PLACE
-+#define PJSIP_MAX_PKT_LEN 32000
-+
-+#undef PJ_TODO
-+#define PJ_TODO(x)
-+
-+/* Defaults too low for WebRTC */
-+#define PJ_ICE_MAX_CAND 32
-+#define PJ_ICE_MAX_CHECKS (PJ_ICE_MAX_CAND * PJ_ICE_MAX_CAND)
-+
-+/* Increase limits to allow more formats */
-+#define PJMEDIA_MAX_SDP_FMT 64
-+#define PJMEDIA_MAX_SDP_BANDW 4
-+#define PJMEDIA_MAX_SDP_ATTR (PJMEDIA_MAX_SDP_FMT*2 + 4)
-+#define PJMEDIA_MAX_SDP_MEDIA 16
-+
-+/*
-+ * Turn off the periodic sending of CRLNCRLN. Default is on (90 seconds),
-+ * which conflicts with the global section's keep_alive_interval option in
-+ * pjsip.conf.
-+ */
-+#define PJSIP_TCP_KEEP_ALIVE_INTERVAL 0
-+#define PJSIP_TLS_KEEP_ALIVE_INTERVAL 0
+++ /dev/null
---- a/build.mak.in
-+++ b/build.mak.in
-@@ -292,7 +292,6 @@ export APP_LDLIBS := $(PJSUA_LIB_LDLIB)
- $(PJLIB_LDLIB) \
- @LIBS@
- export APP_LDXXLIBS := $(PJSUA2_LIB_LDLIB) \
-- -lstdc++ \
- $(APP_LDLIBS)
-
- # Here are the variabels to use if application is using the library
---- a/pjsip/build/Makefile
-+++ b/pjsip/build/Makefile
-@@ -152,8 +152,7 @@ export PJSUA2_LIB_LDFLAGS += $(PJSUA_LIB
- $(PJNATH_LDLIB) \
- $(PJLIB_UTIL_LDLIB) \
- $(PJLIB_LDLIB) \
-- $(_LDFLAGS) \
-- -lstdc++
-+ $(_LDFLAGS)
-
-
- ###############################################################################
+++ /dev/null
-From 42e5ee52e1113d24b7125e29669022c35e87693f Mon Sep 17 00:00:00 2001
-From: Sauw Ming <ming@teluu.com>
-Date: Wed, 26 Sep 2018 00:56:51 +0000
-Subject: [PATCH] Re #2147 (misc): Fixed build error of undefined reference to
- `pjmedia_srtp_enum_crypto' if PJMEDIA_HAS_SRTP is disabled.
-
-Thanks to Alexei Gradinari for the patch
-
-
-
-git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5891 74dad513-b988-da41-8d7b-12977e46ad98
----
- pjsip/src/pjsua2/endpoint.cpp | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/pjsip/src/pjsua2/endpoint.cpp
-+++ b/pjsip/src/pjsua2/endpoint.cpp
-@@ -2145,14 +2145,16 @@ void Endpoint::resetVideoCodecParam(cons
- */
- StringVector Endpoint::srtpCryptoEnum() throw(Error)
- {
-+ StringVector result;
-+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
- unsigned cnt = PJMEDIA_SRTP_MAX_CRYPTOS;
- pjmedia_srtp_crypto cryptos[PJMEDIA_SRTP_MAX_CRYPTOS];
-- StringVector result;
-
- PJSUA2_CHECK_EXPR(pjmedia_srtp_enum_crypto(&cnt, cryptos));
-
- for (unsigned i = 0; i < cnt; ++i)
- result.push_back(pj2Str(cryptos[i].name));
-+#endif
-
- return result;
- }
+++ /dev/null
---- a/pjsip/src/pjsip-ua/sip_inv.c
-+++ b/pjsip/src/pjsip-ua/sip_inv.c
-@@ -4185,6 +4185,29 @@ static void inv_on_state_calling( pjsip_
-
- if (tsx->status_code != 100) {
-
-+ if (inv->role == PJSIP_ROLE_UAC) {
-+ pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
-+ pjsip_allow_hdr *allow = NULL;
-+ pjsip_msg *msg = rdata->msg_info.msg;
-+
-+ if (msg) {
-+ allow = (pjsip_allow_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_ALLOW,
-+ NULL);
-+ }
-+ if (allow) {
-+ unsigned i;
-+ const pj_str_t STR_UPDATE = { "UPDATE", 6 };
-+
-+ for (i=0; i<allow->count; ++i) {
-+ if (pj_stricmp(&allow->values[i], &STR_UPDATE)==0) {
-+ /* UPDATE is present in Allow */
-+ inv->options |= PJSIP_INV_SUPPORT_UPDATE;
-+ break;
-+ }
-+ }
-+ }
-+ }
-+
- if (dlg->remote.info->tag.slen)
- inv_set_state(inv, PJSIP_INV_STATE_EARLY, e);
-
+++ /dev/null
-From 1fed39fe1488abd654a5488b5e6ad59b4b973331 Mon Sep 17 00:00:00 2001
-From: nanang <nanang@localhost>
-Date: Tue, 8 Jan 2019 09:07:47 +0000
-Subject: [PATCH 1/5] Fixed #2172: Avoid double reference counter decrements in
- timer in the scenario of race condition between pj_timer_heap_cancel() and
- pj_timer_heap_poll().
-
----
- pjlib/src/pj/timer.c | 17 ++++++++++-------
- 1 file changed, 10 insertions(+), 7 deletions(-)
-
---- a/pjlib/src/pj/timer.c
-+++ b/pjlib/src/pj/timer.c
-@@ -580,13 +580,16 @@ static int cancel_timer(pj_timer_heap_t
-
- lock_timer_heap(ht);
- count = cancel(ht, entry, flags | F_DONT_CALL);
-- if (flags & F_SET_ID) {
-- entry->id = id_val;
-- }
-- if (entry->_grp_lock) {
-- pj_grp_lock_t *grp_lock = entry->_grp_lock;
-- entry->_grp_lock = NULL;
-- pj_grp_lock_dec_ref(grp_lock);
-+ if (count > 0) {
-+ /* Timer entry found & cancelled */
-+ if (flags & F_SET_ID) {
-+ entry->id = id_val;
-+ }
-+ if (entry->_grp_lock) {
-+ pj_grp_lock_t *grp_lock = entry->_grp_lock;
-+ entry->_grp_lock = NULL;
-+ pj_grp_lock_dec_ref(grp_lock);
-+ }
- }
- unlock_timer_heap(ht);
-
+++ /dev/null
-From 9f57a5728aaec1949908bf7bbd15768fce74e315 Mon Sep 17 00:00:00 2001
-From: Nanang Izzuddin <nanang@teluu.com>
-Date: Wed, 13 Feb 2019 06:51:09 +0000
-Subject: [PATCH] Re #2176: Removed pop_freelist() + push_freelist() after
- remove_node() as they are not only unnecessary, they cause problem.
-
-git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5934 74dad513-b988-da41-8d7b-12977e46ad98
----
- pjlib/src/pj/timer.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/pjlib/src/pj/timer.c
-+++ b/pjlib/src/pj/timer.c
-@@ -633,7 +633,8 @@ PJ_DEF(unsigned) pj_timer_heap_poll( pj_
- {
- pj_timer_entry *node = remove_node(ht, 0);
- /* Avoid re-use of this timer until the callback is done. */
-- pj_timer_id_t node_timer_id = pop_freelist(ht);
-+ ///Not necessary, even causes problem (see also #2176).
-+ ///pj_timer_id_t node_timer_id = pop_freelist(ht);
- pj_grp_lock_t *grp_lock;
-
- ++count;
-@@ -653,7 +654,7 @@ PJ_DEF(unsigned) pj_timer_heap_poll( pj_
-
- lock_timer_heap(ht);
- /* Now, the timer is really free for re-use. */
-- push_freelist(ht, node_timer_id);
-+ ///push_freelist(ht, node_timer_id);
- }
- if (ht->cur_size && next_delay) {
- *next_delay = ht->heap[0]->_timer_value;
+++ /dev/null
-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);
-