Re #1474: Merged all changes from 1.12 - HEAD (from the 1.x branch)
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@3999 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
fb28b6a7ac
commit
28d3c56283
13246
aconfigure
13246
aconfigure
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
AC_INIT(pjproject,1.x)
|
||||
AC_INIT(pjproject,2.x)
|
||||
|
||||
host_orig="$host"
|
||||
|
||||
|
@ -92,6 +92,19 @@ case $host in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(ac_shlib_suffix)
|
||||
case $target in
|
||||
*mingw* | *cygw* | *win32* | *w32* )
|
||||
ac_shlib_suffix=dll
|
||||
;;
|
||||
*darwin*)
|
||||
ac_shlib_suffix=dylib
|
||||
;;
|
||||
*)
|
||||
ac_shlib_suffix=so
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CHECK_LIB(pthread,pthread_create)
|
||||
AC_CHECK_LIB(wsock32,puts)
|
||||
AC_CHECK_LIB(ws2_32,puts)
|
||||
|
@ -774,6 +787,18 @@ AC_ARG_ENABLE(libsamplerate,
|
|||
AC_MSG_RESULT([Skipping libsamplerate detection])
|
||||
)
|
||||
|
||||
dnl # Include libsamplerate
|
||||
AC_SUBST(ac_resample_dll)
|
||||
AC_ARG_ENABLE(resample_dll,
|
||||
AC_HELP_STRING([--enable-resample-dll],
|
||||
[Build libresample as shared library]),
|
||||
[if test "$enable_resample_dll" = "yes"; then
|
||||
[ac_resample_dll=1]
|
||||
AC_MSG_RESULT([Building libresample as shared library... yes])
|
||||
fi],
|
||||
AC_MSG_RESULT([Building libresample as shared library... no])
|
||||
)
|
||||
|
||||
dnl # SDL alt prefix
|
||||
AC_ARG_WITH(sdl,
|
||||
AC_HELP_STRING([--with-sdl=DIR],
|
||||
|
@ -1216,7 +1241,6 @@ AC_ARG_ENABLE(opencore_amrnb,
|
|||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl ##########################################
|
||||
dnl #
|
||||
dnl # MANUAL CONFIG
|
||||
|
|
20
build.mak.in
20
build.mak.in
|
@ -1,3 +1,7 @@
|
|||
export PJDIR := @ac_pjdir@
|
||||
include $(PJDIR)/version.mak
|
||||
export PJ_DIR := $(PJDIR)
|
||||
|
||||
# @configure_input@
|
||||
export MACHINE_NAME := auto
|
||||
export OS_NAME := auto
|
||||
|
@ -6,15 +10,25 @@ export CC_NAME := gcc
|
|||
export TARGET_NAME := @target@
|
||||
export CROSS_COMPILE := @ac_cross_compile@
|
||||
export LINUX_POLL := @ac_linux_poll@
|
||||
export SHLIB_SUFFIX := @ac_shlib_suffix@
|
||||
|
||||
export ac_prefix := @prefix@
|
||||
|
||||
LIB_SUFFIX = $(TARGET_NAME).a
|
||||
|
||||
# Determine which party libraries to use
|
||||
export APP_THIRD_PARTY_LIBS := -lresample-$(TARGET_NAME) -lmilenage-$(TARGET_NAME) -lsrtp-$(TARGET_NAME)
|
||||
export APP_THIRD_PARTY_LIBS := -lmilenage-$(TARGET_NAME) -lsrtp-$(TARGET_NAME)
|
||||
export APP_THIRD_PARTY_EXT :=
|
||||
export APP_THIRD_PARTY_LIB_FILES = $(PJ_DIR)/third_party/lib/libresample-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libmilenage-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libsrtp-$(LIB_SUFFIX)
|
||||
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libmilenage-$(LIB_SUFFIX) $(PJ_DIR)/third_party/lib/libsrtp-$(LIB_SUFFIX)
|
||||
|
||||
ifeq (@ac_resample_dll@,1)
|
||||
export PJ_RESAMPLE_DLL := 1
|
||||
export APP_THIRD_PARTY_LIBS := -lresample $(APP_THIRD_PARTY_LIBS)
|
||||
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFIX).$(PJ_VERSION_MAJOR) $(PJ_DIR)/third_party/lib/libresample.$(SHLIB_SUFFIX) $(APP_THIRD_PARTY_LIB_FILES)
|
||||
else
|
||||
export APP_THIRD_PARTY_LIBS := -lresample-$(TARGET_NAME) $(APP_THIRD_PARTY_LIBS)
|
||||
export APP_THIRD_PARTY_LIB_FILES := $(PJ_DIR)/third_party/lib/libresample-$(LIB_SUFFIX) $(APP_THIRD_PARTY_LIB_FILES)
|
||||
endif
|
||||
|
||||
ifneq (@ac_no_gsm_codec@,1)
|
||||
ifeq (@ac_external_gsm@,1)
|
||||
|
@ -89,7 +103,6 @@ PJ_VIDEO_LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS)
|
|||
|
||||
|
||||
# CFLAGS, LDFLAGS, and LIBS to be used by applications
|
||||
export PJDIR := @ac_pjdir@
|
||||
export APP_CC := @CC@
|
||||
export APP_CXX := @CXX@
|
||||
export APP_CFLAGS := -DPJ_AUTOCONF=1\
|
||||
|
@ -138,7 +151,6 @@ export APP_LIB_FILES = $(PJ_DIR)/pjsip/lib/libpjsua-$(LIB_SUFFIX) \
|
|||
|
||||
# Here are the variabels to use if application is using the library
|
||||
# from within the source distribution
|
||||
export PJ_DIR := $(PJDIR)
|
||||
export PJ_CC := $(APP_CC)
|
||||
export PJ_CXX := $(APP_CXX)
|
||||
export PJ_CFLAGS := $(APP_CFLAGS)
|
||||
|
|
|
@ -10,6 +10,11 @@ endif
|
|||
#
|
||||
LIB = $($(APP)_LIB)
|
||||
|
||||
#
|
||||
# The full path of output lib file (e.g. ../lib/libapp.a).
|
||||
#
|
||||
SHLIB = $($(APP)_SHLIB)
|
||||
|
||||
#
|
||||
# The full path of output executable file (e.g. ../bin/app.exe).
|
||||
#
|
||||
|
@ -82,6 +87,11 @@ $(LIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
|
|||
$(AR) $(LIB) $(OBJS)
|
||||
$(RANLIB) $(LIB)
|
||||
|
||||
$(SHLIB): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
|
||||
if test ! -d $(LIBDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(LIBDIR)),$(HOST_MKDIR)); fi
|
||||
$(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$(SHLIB)) \
|
||||
$(subst /,$(HOST_PSEP),$(OBJS)) $($(APP)_LDFLAGS)
|
||||
|
||||
$(EXE): $(OBJDIRS) $(OBJS) $($(APP)_EXTRA_DEP)
|
||||
if test ! -d $(BINDIR); then $(subst @@,$(subst /,$(HOST_PSEP),$(BINDIR)),$(HOST_MKDIR)); fi
|
||||
$(LD) $(LDOUT)$(subst /,$(HOST_PSEP),$(EXE)) \
|
||||
|
|
|
@ -25,7 +25,10 @@ fi
|
|||
|
||||
# Set the main iPhone developer directory, if not set
|
||||
if test "x${DEVPATH}" = "x"; then
|
||||
DEVPATH=/Developer/Platforms/iPhoneOS.platform/Developer
|
||||
DEVPATH=/Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer
|
||||
if test ! -d $DEVPATH; then
|
||||
DEVPATH=/Developer/Platforms/iPhoneOS.platform/Developer
|
||||
fi
|
||||
echo "$F: DEVPATH is not specified, using ${DEVPATH}"
|
||||
fi
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
|
|||
{
|
||||
unsigned srv_cnt;
|
||||
pj_sockaddr_in srv_addr[2];
|
||||
int i, send_cnt = 0;
|
||||
int i, send_cnt = 0, nfds;
|
||||
pj_pool_t *pool;
|
||||
struct query_rec {
|
||||
struct {
|
||||
|
@ -113,6 +113,17 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
|
|||
|
||||
TRACE_((THIS_FILE, " Done initialization."));
|
||||
|
||||
#if defined(PJ_SELECT_NEEDS_NFDS) && PJ_SELECT_NEEDS_NFDS!=0
|
||||
nfds = -1;
|
||||
for (i=0; i<sock_cnt; ++i) {
|
||||
if (sock[i] > nfds) {
|
||||
nfds = sock[i];
|
||||
}
|
||||
}
|
||||
#else
|
||||
nfds = PJ_IOQUEUE_MAX_HANDLES-1;
|
||||
#endif
|
||||
|
||||
/* Main retransmission loop. */
|
||||
for (send_cnt=0; send_cnt<MAX_REQUEST; ++send_cnt) {
|
||||
pj_time_val next_tx, now;
|
||||
|
@ -170,7 +181,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
|
|||
PJ_FD_SET(sock[i], &r);
|
||||
}
|
||||
|
||||
select_rc = pj_sock_select(PJ_IOQUEUE_MAX_HANDLES, &r, NULL, NULL, &timeout);
|
||||
select_rc = pj_sock_select(nfds+1, &r, NULL, NULL, &timeout);
|
||||
TRACE_((THIS_FILE, " select() rc=%d", select_rc));
|
||||
if (select_rc < 1)
|
||||
continue;
|
||||
|
|
|
@ -100,13 +100,13 @@ static pj_xml_node *xml_parse_node( pj_pool_t *pool, pj_scanner *scanner)
|
|||
pj_scan_get_char(scanner);
|
||||
|
||||
/* Get node name. */
|
||||
pj_scan_get_until_chr( scanner, " />\t", &node->name);
|
||||
pj_scan_get_until_chr( scanner, " />\t\r\n", &node->name);
|
||||
|
||||
/* Get attributes. */
|
||||
while (*scanner->curptr != '>' && *scanner->curptr != '/') {
|
||||
pj_xml_attr *attr = alloc_attr(pool);
|
||||
|
||||
pj_scan_get_until_chr( scanner, "=> \t", &attr->name);
|
||||
pj_scan_get_until_chr( scanner, "=> \t\r\n", &attr->name);
|
||||
if (*scanner->curptr == '=') {
|
||||
pj_scan_get_char( scanner );
|
||||
pj_scan_get_quotes(scanner, "\"'", "\"'", 2, &attr->value);
|
||||
|
|
|
@ -331,16 +331,38 @@ PJ_DECL(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
|
|||
unsigned *cipher_num);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the specified cipher is supported by SSL/TLS backend.
|
||||
*
|
||||
* @param cipher The cipher.
|
||||
*
|
||||
* @return PJ_TRUE when supported.
|
||||
*/
|
||||
PJ_DECL(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher);
|
||||
|
||||
|
||||
/**
|
||||
* Get cipher name string.
|
||||
*
|
||||
* @param cipher The cipher.
|
||||
*
|
||||
* @return The cipher name or NULL if cipher is not recognized.
|
||||
* @return The cipher name or NULL if cipher is not recognized/
|
||||
* supported.
|
||||
*/
|
||||
PJ_DECL(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher);
|
||||
|
||||
|
||||
/**
|
||||
* Get cipher ID from cipher name string.
|
||||
*
|
||||
* @param cipher_name The cipher name string.
|
||||
*
|
||||
* @return The cipher ID or PJ_TLS_UNKNOWN_CIPHER if the cipher
|
||||
* name string is not recognized/supported.
|
||||
*/
|
||||
PJ_DECL(pj_ssl_cipher) pj_ssl_cipher_id(const char *cipher_name);
|
||||
|
||||
|
||||
/**
|
||||
* This structure contains the callbacks to be called by the secure socket.
|
||||
*/
|
||||
|
|
|
@ -290,6 +290,9 @@ typedef int pj_exception_id_t;
|
|||
* in random string generation, and to initialize operating system dependent
|
||||
* functionality (such as WSAStartup() in Windows).
|
||||
*
|
||||
* Apart from calling pj_init(), application typically should also initialize
|
||||
* the random seed by calling pj_srand().
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pj_init(void);
|
||||
|
|
|
@ -75,6 +75,9 @@ struct pj_sem_t
|
|||
int max;
|
||||
};
|
||||
|
||||
/* Flag and reference counter for PJLIB instance */
|
||||
static int initialized;
|
||||
|
||||
/* Flags to indicate which TLS variables have been used */
|
||||
static int tls_vars[PJ_MAX_TLS];
|
||||
|
||||
|
@ -83,8 +86,6 @@ static unsigned atexit_count;
|
|||
static void (*atexit_func[32])(void);
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CPjTimeoutTimer implementation
|
||||
|
@ -335,6 +336,12 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
char stack_ptr;
|
||||
pj_status_t status;
|
||||
|
||||
/* Check if PJLIB have been initialized */
|
||||
if (initialized) {
|
||||
++initialized;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
pj_ansi_strcpy(main_thread.obj_name, "pjthread");
|
||||
|
||||
// Init main thread
|
||||
|
@ -368,6 +375,10 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
stack_ptr = '\0';
|
||||
#endif
|
||||
|
||||
/* Flag PJLIB as initialized */
|
||||
++initialized;
|
||||
pj_assert(initialized == 1);
|
||||
|
||||
PJ_LOG(5,(THIS_FILE, "PJLIB initialized."));
|
||||
return PJ_SUCCESS;
|
||||
|
||||
|
@ -390,6 +401,11 @@ PJ_DEF(pj_status_t) pj_atexit(pj_exit_callback func)
|
|||
|
||||
PJ_DEF(void) pj_shutdown(void)
|
||||
{
|
||||
/* Only perform shutdown operation when 'initialized' reaches zero */
|
||||
pj_assert(initialized > 0);
|
||||
if (--initialized != 0)
|
||||
return;
|
||||
|
||||
/* Call atexit() functions */
|
||||
while (atexit_count > 0) {
|
||||
(*atexit_func[atexit_count-1])();
|
||||
|
|
|
@ -102,6 +102,11 @@ struct pj_event_t
|
|||
#endif /* PJ_HAS_EVENT_OBJ */
|
||||
|
||||
|
||||
/*
|
||||
* Flag and reference counter for PJLIB instance.
|
||||
*/
|
||||
static int initialized;
|
||||
|
||||
#if PJ_HAS_THREADS
|
||||
static pj_thread_t main_thread;
|
||||
static long thread_tls_id;
|
||||
|
@ -127,6 +132,12 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
pj_str_t guid;
|
||||
pj_status_t rc;
|
||||
|
||||
/* Check if PJLIB have been initialized */
|
||||
if (initialized) {
|
||||
++initialized;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
#if PJ_HAS_THREADS
|
||||
/* Init this thread's TLS. */
|
||||
if ((rc=pj_thread_init()) != 0) {
|
||||
|
@ -167,6 +178,10 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Flag PJLIB as initialized */
|
||||
++initialized;
|
||||
pj_assert(initialized == 1);
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",
|
||||
PJ_VERSION));
|
||||
|
||||
|
@ -192,6 +207,11 @@ PJ_DEF(void) pj_shutdown()
|
|||
{
|
||||
int i;
|
||||
|
||||
/* Only perform shutdown operation when 'initialized' reaches zero */
|
||||
pj_assert(initialized > 0);
|
||||
if (--initialized != 0)
|
||||
return;
|
||||
|
||||
/* Call atexit() functions */
|
||||
for (i=atexit_count-1; i>=0; --i) {
|
||||
(*atexit_func[i])();
|
||||
|
|
|
@ -116,6 +116,11 @@ struct pj_atomic_t
|
|||
long value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Flag and reference counter for PJLIB instance.
|
||||
*/
|
||||
static int initialized;
|
||||
|
||||
/*
|
||||
* Static global variables.
|
||||
*/
|
||||
|
@ -142,6 +147,12 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
pj_str_t guid;
|
||||
pj_status_t rc;
|
||||
|
||||
/* Check if PJLIB have been initialized */
|
||||
if (initialized) {
|
||||
++initialized;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
/* Init Winsock.. */
|
||||
if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
|
||||
return PJ_RETURN_OS_ERROR(WSAGetLastError());
|
||||
|
@ -187,6 +198,10 @@ PJ_DEF(pj_status_t) pj_init(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Flag PJLIB as initialized */
|
||||
++initialized;
|
||||
pj_assert(initialized == 1);
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "pjlib %s for win32 initialized",
|
||||
PJ_VERSION));
|
||||
|
||||
|
@ -213,6 +228,11 @@ PJ_DEF(void) pj_shutdown()
|
|||
{
|
||||
int i;
|
||||
|
||||
/* Only perform shutdown operation when 'initialized' reaches zero */
|
||||
pj_assert(initialized > 0);
|
||||
if (--initialized != 0)
|
||||
return;
|
||||
|
||||
/* Display stack usage */
|
||||
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
|
||||
{
|
||||
|
|
|
@ -21,89 +21,6 @@
|
|||
#include <pj/errno.h>
|
||||
#include <pj/string.h>
|
||||
|
||||
/* Cipher name structure */
|
||||
typedef struct cipher_name_t {
|
||||
pj_ssl_cipher cipher;
|
||||
const char *name;
|
||||
} cipher_name_t;
|
||||
|
||||
/* Cipher name constants */
|
||||
static cipher_name_t cipher_names[] =
|
||||
{
|
||||
{PJ_TLS_NULL_WITH_NULL_NULL, "NULL"},
|
||||
|
||||
/* TLS/SSLv3 */
|
||||
{PJ_TLS_RSA_WITH_NULL_MD5, "TLS_RSA_WITH_NULL_MD5"},
|
||||
{PJ_TLS_RSA_WITH_NULL_SHA, "TLS_RSA_WITH_NULL_SHA"},
|
||||
{PJ_TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"},
|
||||
{PJ_TLS_RSA_WITH_RC4_128_MD5, "TLS_RSA_WITH_RC4_128_MD5"},
|
||||
{PJ_TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA"},
|
||||
{PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_anon_WITH_RC4_128_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"},
|
||||
{PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
|
||||
|
||||
/* TLS (deprecated) */
|
||||
{PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
|
||||
{PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
|
||||
{PJ_TLS_RSA_WITH_IDEA_CBC_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"},
|
||||
{PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_DES_CBC_SHA, "TLS_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_DES_CBC_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_DES_CBC_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"},
|
||||
{PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_DES_CBC_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"},
|
||||
|
||||
/* SSLv3 */
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA, "SSL_FORTEZZA_KEA_WITH_NULL_SHA"},
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"},
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"},
|
||||
|
||||
/* SSLv2 */
|
||||
{PJ_SSL_CK_RC4_128_WITH_MD5, "SSL_CK_RC4_128_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5, "SSL_CK_RC4_128_EXPORT40_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC2_128_CBC_WITH_MD5, "SSL_CK_RC2_128_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"},
|
||||
{PJ_SSL_CK_IDEA_128_CBC_WITH_MD5, "SSL_CK_IDEA_128_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_DES_64_CBC_WITH_MD5, "SSL_CK_DES_64_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5, "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the SSL socket configuration with the default values.
|
||||
*/
|
||||
|
@ -129,23 +46,6 @@ PJ_DEF(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param)
|
|||
}
|
||||
|
||||
|
||||
/* Get cipher name string */
|
||||
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i, n;
|
||||
|
||||
n = PJ_ARRAY_SIZE(cipher_names);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (cipher == cipher_names[i].cipher)
|
||||
return cipher_names[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings(
|
||||
pj_uint32_t verify_status,
|
||||
const char *error_strings[],
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
/* Workaround for ticket #985 */
|
||||
#define DELAYED_CLOSE_TIMEOUT 200
|
||||
|
||||
/* Maximum ciphers */
|
||||
#define MAX_CIPHERS 100
|
||||
|
||||
/*
|
||||
* Include OpenSSL headers
|
||||
*/
|
||||
|
@ -269,8 +272,11 @@ static pj_str_t ssl_strerror(pj_status_t status,
|
|||
static int openssl_init_count;
|
||||
|
||||
/* OpenSSL available ciphers */
|
||||
static pj_ssl_cipher openssl_ciphers[100];
|
||||
static unsigned openssl_cipher_num;
|
||||
static struct openssl_ciphers_t {
|
||||
pj_ssl_cipher id;
|
||||
const char *name;
|
||||
} openssl_ciphers[MAX_CIPHERS];
|
||||
|
||||
/* OpenSSL application data index */
|
||||
static int sslsock_idx;
|
||||
|
@ -329,9 +335,9 @@ static pj_status_t init_openssl(void)
|
|||
for (i = 0; i < n; ++i) {
|
||||
SSL_CIPHER *c;
|
||||
c = sk_SSL_CIPHER_value(sk_cipher,i);
|
||||
openssl_ciphers[i] = (pj_ssl_cipher)
|
||||
(pj_uint32_t)c->id & 0x00FFFFFF;
|
||||
//printf("%3u: %08x=%s\n", i+1, c->id, SSL_CIPHER_get_name(c));
|
||||
openssl_ciphers[i].id = (pj_ssl_cipher)
|
||||
(pj_uint32_t)c->id & 0x00FFFFFF;
|
||||
openssl_ciphers[i].name = SSL_CIPHER_get_name(c);
|
||||
}
|
||||
|
||||
SSL_free(ssl);
|
||||
|
@ -1705,18 +1711,57 @@ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[],
|
|||
shutdown_openssl();
|
||||
}
|
||||
|
||||
if (openssl_cipher_num == 0)
|
||||
if (openssl_cipher_num == 0) {
|
||||
*cipher_num = 0;
|
||||
return PJ_ENOTFOUND;
|
||||
}
|
||||
|
||||
*cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num);
|
||||
|
||||
for (i = 0; i < *cipher_num; ++i)
|
||||
ciphers[i] = openssl_ciphers[i];
|
||||
ciphers[i] = openssl_ciphers[i].id;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Get cipher name string */
|
||||
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (openssl_cipher_num == 0) {
|
||||
init_openssl();
|
||||
shutdown_openssl();
|
||||
}
|
||||
|
||||
for (i = 0; i < openssl_cipher_num; ++i) {
|
||||
if (cipher == openssl_ciphers[i].id)
|
||||
return openssl_ciphers[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if the specified cipher is supported by SSL/TLS backend. */
|
||||
PJ_DEF(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (openssl_cipher_num == 0) {
|
||||
init_openssl();
|
||||
shutdown_openssl();
|
||||
}
|
||||
|
||||
for (i = 0; i < openssl_cipher_num; ++i) {
|
||||
if (cipher == openssl_ciphers[i].id)
|
||||
return PJ_TRUE;
|
||||
}
|
||||
|
||||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create SSL socket instance.
|
||||
*/
|
||||
|
|
|
@ -32,6 +32,104 @@
|
|||
|
||||
#define THIS_FILE "ssl_sock_symbian.cpp"
|
||||
|
||||
|
||||
/* Cipher name structure */
|
||||
typedef struct cipher_name_t {
|
||||
pj_ssl_cipher cipher;
|
||||
const char *name;
|
||||
} cipher_name_t;
|
||||
|
||||
/* Cipher name constants */
|
||||
static cipher_name_t cipher_names[] =
|
||||
{
|
||||
{PJ_TLS_NULL_WITH_NULL_NULL, "NULL"},
|
||||
|
||||
/* TLS/SSLv3 */
|
||||
{PJ_TLS_RSA_WITH_NULL_MD5, "TLS_RSA_WITH_NULL_MD5"},
|
||||
{PJ_TLS_RSA_WITH_NULL_SHA, "TLS_RSA_WITH_NULL_SHA"},
|
||||
{PJ_TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"},
|
||||
{PJ_TLS_RSA_WITH_RC4_128_MD5, "TLS_RSA_WITH_RC4_128_MD5"},
|
||||
{PJ_TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_RC4_128_SHA"},
|
||||
{PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
|
||||
{PJ_TLS_DH_anon_WITH_RC4_128_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"},
|
||||
{PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"},
|
||||
{PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"},
|
||||
|
||||
/* TLS (deprecated) */
|
||||
{PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"},
|
||||
{PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"},
|
||||
{PJ_TLS_RSA_WITH_IDEA_CBC_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"},
|
||||
{PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_RSA_WITH_DES_CBC_SHA, "TLS_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_DSS_WITH_DES_CBC_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_RSA_WITH_DES_CBC_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"},
|
||||
{PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"},
|
||||
{PJ_TLS_DH_anon_WITH_DES_CBC_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"},
|
||||
|
||||
/* SSLv3 */
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA, "SSL_FORTEZZA_KEA_WITH_NULL_SHA"},
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"},
|
||||
{PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"},
|
||||
|
||||
/* SSLv2 */
|
||||
{PJ_SSL_CK_RC4_128_WITH_MD5, "SSL_CK_RC4_128_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5, "SSL_CK_RC4_128_EXPORT40_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC2_128_CBC_WITH_MD5, "SSL_CK_RC2_128_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"},
|
||||
{PJ_SSL_CK_IDEA_128_CBC_WITH_MD5, "SSL_CK_IDEA_128_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_DES_64_CBC_WITH_MD5, "SSL_CK_DES_64_CBC_WITH_MD5"},
|
||||
{PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5, "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"}
|
||||
};
|
||||
|
||||
|
||||
/* Get cipher name string */
|
||||
static const char* get_cipher_name(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i, n;
|
||||
|
||||
n = PJ_ARRAY_SIZE(cipher_names);
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (cipher == cipher_names[i].cipher)
|
||||
return cipher_names[i].name;
|
||||
}
|
||||
|
||||
return "CIPHER_UNKNOWN";
|
||||
}
|
||||
|
||||
typedef void (*CPjSSLSocket_cb)(int err, void *key);
|
||||
|
||||
class CPjSSLSocketReader : public CActive
|
||||
|
@ -115,7 +213,8 @@ public:
|
|||
|
||||
int Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr,
|
||||
const TInetAddr &rem_addr,
|
||||
const TDesC8 &servername = TPtrC8(NULL,0));
|
||||
const TDesC8 &servername = TPtrC8(NULL,0),
|
||||
const TDesC8 &ciphers = TPtrC8(NULL,0));
|
||||
int Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, TUint flags);
|
||||
int SendSync(const TDesC8 &aDesc, TUint flags);
|
||||
|
||||
|
@ -146,6 +245,7 @@ private:
|
|||
TBuf<32> ssl_proto_;
|
||||
TInetAddr rem_addr_;
|
||||
TPtrC8 servername_;
|
||||
TPtrC8 ciphers_;
|
||||
TInetAddr local_addr_;
|
||||
TSockXfrLength sent_len_;
|
||||
|
||||
|
@ -186,7 +286,8 @@ private:
|
|||
int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,
|
||||
const TInetAddr &local_addr,
|
||||
const TInetAddr &rem_addr,
|
||||
const TDesC8 &servername)
|
||||
const TDesC8 &servername,
|
||||
const TDesC8 &ciphers)
|
||||
{
|
||||
pj_status_t status;
|
||||
|
||||
|
@ -213,7 +314,11 @@ int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,
|
|||
cb_ = cb;
|
||||
key_ = key;
|
||||
rem_addr_ = rem_addr;
|
||||
|
||||
/* Note: the following members only keep the pointer, not the data */
|
||||
servername_.Set(servername);
|
||||
ciphers_.Set(ciphers);
|
||||
|
||||
rSock.Connect(rem_addr_, iStatus);
|
||||
SetActive();
|
||||
state_ = SSL_STATE_CONNECTING;
|
||||
|
@ -318,6 +423,8 @@ void CPjSSLSocket::RunL()
|
|||
if (servername_.Length() > 0)
|
||||
securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL,
|
||||
servername_);
|
||||
if (ciphers_.Length() > 0)
|
||||
securesock_->SetAvailableCipherSuites(ciphers_);
|
||||
|
||||
// FlushSessionCache() seems to also fire signals to all
|
||||
// completed AOs (something like CActiveScheduler::RunIfReady())
|
||||
|
@ -441,9 +548,8 @@ struct pj_ssl_sock_t
|
|||
|
||||
pj_ssl_sock_proto proto;
|
||||
pj_time_val timeout;
|
||||
unsigned ciphers_num;
|
||||
pj_ssl_cipher *ciphers;
|
||||
pj_str_t servername;
|
||||
pj_str_t ciphers;
|
||||
pj_ssl_cert_info remote_cert_info;
|
||||
};
|
||||
|
||||
|
@ -579,15 +685,20 @@ static void update_certs_info(pj_ssl_sock_t *ssock)
|
|||
}
|
||||
|
||||
|
||||
/* Available ciphers */
|
||||
static unsigned ciphers_num_ = 0;
|
||||
static struct ciphers_t
|
||||
{
|
||||
pj_ssl_cipher id;
|
||||
const char *name;
|
||||
} ciphers_[64];
|
||||
|
||||
/*
|
||||
* Get cipher list supported by SSL/TLS backend.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[],
|
||||
unsigned *cipher_num)
|
||||
{
|
||||
/* Available ciphers */
|
||||
static pj_ssl_cipher ciphers_[64];
|
||||
static unsigned ciphers_num_ = 0;
|
||||
unsigned i;
|
||||
|
||||
PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL);
|
||||
|
@ -605,25 +716,69 @@ PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[],
|
|||
ciphers_num_ = ciphers_buf.Length() / 2;
|
||||
if (ciphers_num_ > PJ_ARRAY_SIZE(ciphers_))
|
||||
ciphers_num_ = PJ_ARRAY_SIZE(ciphers_);
|
||||
for (i = 0; i < ciphers_num_; ++i)
|
||||
ciphers_[i] = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +
|
||||
ciphers_buf[i*2+1]);
|
||||
for (i = 0; i < ciphers_num_; ++i) {
|
||||
ciphers_[i].id = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +
|
||||
ciphers_buf[i*2+1]);
|
||||
ciphers_[i].name = get_cipher_name(ciphers_[i].id);
|
||||
}
|
||||
}
|
||||
|
||||
delete secure_sock;
|
||||
}
|
||||
|
||||
if (ciphers_num_ == 0) {
|
||||
*cipher_num = 0;
|
||||
return PJ_ENOTFOUND;
|
||||
}
|
||||
|
||||
*cipher_num = PJ_MIN(*cipher_num, ciphers_num_);
|
||||
for (i = 0; i < *cipher_num; ++i)
|
||||
ciphers[i] = ciphers_[i];
|
||||
ciphers[i] = ciphers_[i].id;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Get cipher name string */
|
||||
PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (ciphers_num_ == 0) {
|
||||
pj_ssl_cipher c[1];
|
||||
i = 0;
|
||||
pj_ssl_cipher_get_availables(c, &i);
|
||||
}
|
||||
|
||||
for (i = 0; i < ciphers_num_; ++i) {
|
||||
if (cipher == ciphers_[i].id)
|
||||
return ciphers_[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Check if the specified cipher is supported by SSL/TLS backend. */
|
||||
PJ_DEF(pj_bool_t) pj_ssl_cipher_is_supported(pj_ssl_cipher cipher)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (ciphers_num_ == 0) {
|
||||
pj_ssl_cipher c[1];
|
||||
i = 0;
|
||||
pj_ssl_cipher_get_availables(c, &i);
|
||||
}
|
||||
|
||||
for (i = 0; i < ciphers_num_; ++i) {
|
||||
if (cipher == ciphers_[i].id)
|
||||
return PJ_TRUE;
|
||||
}
|
||||
|
||||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create SSL socket instance.
|
||||
*/
|
||||
|
@ -652,14 +807,15 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
|
|||
ssock->cb = param->cb;
|
||||
ssock->user_data = param->user_data;
|
||||
ssock->timeout = param->timeout;
|
||||
ssock->ciphers_num = param->ciphers_num;
|
||||
if (param->ciphers_num > 0) {
|
||||
unsigned i;
|
||||
ssock->ciphers = (pj_ssl_cipher*)
|
||||
pj_pool_calloc(pool, param->ciphers_num,
|
||||
sizeof(pj_ssl_cipher));
|
||||
for (i = 0; i < param->ciphers_num; ++i)
|
||||
ssock->ciphers[i] = param->ciphers[i];
|
||||
/* Cipher list in Symbian is represented as array of two-octets. */
|
||||
ssock->ciphers.slen = param->ciphers_num*2;
|
||||
ssock->ciphers.ptr = (char*)pj_pool_alloc(pool, ssock->ciphers.slen);
|
||||
pj_uint8_t *c = (pj_uint8_t*)ssock->ciphers.ptr;
|
||||
for (unsigned i = 0; i < param->ciphers_num; ++i) {
|
||||
*c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF00) >> 8;
|
||||
*c++ = (pj_uint8_t)(param->ciphers[i] & 0xFF);
|
||||
}
|
||||
}
|
||||
pj_strdup_with_null(pool, &ssock->servername, ¶m->server_name);
|
||||
|
||||
|
@ -1246,9 +1402,13 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect (pj_ssl_sock_t *ssock,
|
|||
TPtrC8 servername_((TUint8*)ssock->servername.ptr,
|
||||
ssock->servername.slen);
|
||||
|
||||
/* Convert cipher list to Symbian descriptor */
|
||||
TPtrC8 ciphers_((TUint8*)ssock->ciphers.ptr,
|
||||
ssock->ciphers.slen);
|
||||
|
||||
/* Try to connect */
|
||||
status = sock->Connect(&connect_cb, ssock, localaddr_, remaddr_,
|
||||
servername_);
|
||||
servername_, ciphers_);
|
||||
if (status != PJ_SUCCESS && status != PJ_EPENDING) {
|
||||
delete sock;
|
||||
return status;
|
||||
|
|
|
@ -453,6 +453,19 @@
|
|||
# define PJMEDIA_RTCP_STAT_HAS_RAW_JITTER 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Specify the factor with wich RTCP RTT statistics should be normalized
|
||||
* if exceptionally high. For e.g. mobile networks with potentially large
|
||||
* fluctuations, this might be unwanted.
|
||||
*
|
||||
* Use (0) to disable this feature.
|
||||
*
|
||||
* Default: 3.
|
||||
*/
|
||||
#ifndef PJMEDIA_RTCP_NORMALIZE_FACTOR
|
||||
# define PJMEDIA_RTCP_NORMALIZE_FACTOR 3
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Specify whether RTCP statistics includes IP Delay Variation statistics.
|
||||
|
@ -476,7 +489,7 @@
|
|||
* if it is enabled on run-time on per stream basis. See
|
||||
* PJMEDIA_STREAM_ENABLE_XR setting for more info.
|
||||
*
|
||||
* Default: 1 (yes).
|
||||
* Default: 0 (no).
|
||||
*/
|
||||
#ifndef PJMEDIA_HAS_RTCP_XR
|
||||
# define PJMEDIA_HAS_RTCP_XR 0
|
||||
|
@ -494,6 +507,19 @@
|
|||
# define PJMEDIA_STREAM_ENABLE_XR 0
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Specify the buffer length for storing any received RTCP SDES text
|
||||
* in a stream session. Usually RTCP contains only the mandatory SDES
|
||||
* field, i.e: CNAME.
|
||||
*
|
||||
* Default: 64 bytes.
|
||||
*/
|
||||
#ifndef PJMEDIA_RTCP_RX_SDES_BUF_LEN
|
||||
# define PJMEDIA_RTCP_RX_SDES_BUF_LEN 64
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Specify how long (in miliseconds) the stream should suspend the
|
||||
* silence detector/voice activity detector (VAD) during the initial
|
||||
|
|
|
@ -60,6 +60,12 @@ typedef enum pjmedia_endpt_flag
|
|||
} pjmedia_endpt_flag;
|
||||
|
||||
|
||||
/**
|
||||
* Type of callback to register to pjmedia_endpt_atexit().
|
||||
*/
|
||||
typedef void (*pjmedia_endpt_exit_callback)(pjmedia_endpt *endpt);
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance of media endpoint.
|
||||
*
|
||||
|
@ -260,6 +266,23 @@ PJ_DECL(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt,
|
|||
PJ_DECL(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt);
|
||||
|
||||
|
||||
/**
|
||||
* Register cleanup function to be called by media endpoint when
|
||||
* #pjmedia_endpt_destroy() is called. Note that application should not
|
||||
* use or access any endpoint resource (such as pool, ioqueue) from within
|
||||
* the callback as such resource may have been released when the callback
|
||||
* function is invoked.
|
||||
*
|
||||
* @param endpt The media endpoint.
|
||||
* @param func The function to be registered.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_endpt_atexit(pjmedia_endpt *endpt,
|
||||
pjmedia_endpt_exit_callback func);
|
||||
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
|
||||
|
|
|
@ -54,29 +54,26 @@ PJ_BEGIN_DECL
|
|||
* #pjmedia_stream_get_stat() function.
|
||||
*/
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/**
|
||||
* RTCP sender report.
|
||||
*/
|
||||
struct pjmedia_rtcp_sr
|
||||
typedef struct pjmedia_rtcp_sr
|
||||
{
|
||||
pj_uint32_t ntp_sec; /**< NTP time, seconds part. */
|
||||
pj_uint32_t ntp_frac; /**< NTP time, fractions part. */
|
||||
pj_uint32_t rtp_ts; /**< RTP timestamp. */
|
||||
pj_uint32_t sender_pcount; /**< Sender packet cound. */
|
||||
pj_uint32_t sender_bcount; /**< Sender octet/bytes count. */
|
||||
};
|
||||
} pjmedia_rtcp_sr;
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_sr
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_sr pjmedia_rtcp_sr;
|
||||
|
||||
/**
|
||||
* RTCP receiver report.
|
||||
*/
|
||||
struct pjmedia_rtcp_rr
|
||||
typedef struct pjmedia_rtcp_rr
|
||||
{
|
||||
pj_uint32_t ssrc; /**< SSRC identification. */
|
||||
#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
|
||||
|
@ -94,18 +91,13 @@ struct pjmedia_rtcp_rr
|
|||
pj_uint32_t jitter; /**< Jitter. */
|
||||
pj_uint32_t lsr; /**< Last SR. */
|
||||
pj_uint32_t dlsr; /**< Delay since last SR. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_rr
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_rr pjmedia_rtcp_rr;
|
||||
} pjmedia_rtcp_rr;
|
||||
|
||||
|
||||
/**
|
||||
* RTCP common header.
|
||||
*/
|
||||
struct pjmedia_rtcp_common
|
||||
typedef struct pjmedia_rtcp_common
|
||||
{
|
||||
#if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0
|
||||
unsigned version:2; /**< packet type */
|
||||
|
@ -120,12 +112,8 @@ struct pjmedia_rtcp_common
|
|||
#endif
|
||||
unsigned length:16; /**< packet length */
|
||||
pj_uint32_t ssrc; /**< SSRC identification */
|
||||
};
|
||||
} pjmedia_rtcp_common;
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_common
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_common pjmedia_rtcp_common;
|
||||
|
||||
/**
|
||||
* This structure declares default RTCP packet (SR) that is sent by pjmedia.
|
||||
|
@ -152,26 +140,35 @@ typedef struct pjmedia_rtcp_rr_pkt
|
|||
#pragma pack()
|
||||
|
||||
|
||||
/**
|
||||
* RTCP SDES structure.
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_sdes
|
||||
{
|
||||
pj_str_t cname; /**< RTCP SDES type CNAME. */
|
||||
pj_str_t name; /**< RTCP SDES type NAME. */
|
||||
pj_str_t email; /**< RTCP SDES type EMAIL. */
|
||||
pj_str_t phone; /**< RTCP SDES type PHONE. */
|
||||
pj_str_t loc; /**< RTCP SDES type LOC. */
|
||||
pj_str_t tool; /**< RTCP SDES type TOOL. */
|
||||
pj_str_t note; /**< RTCP SDES type NOTE. */
|
||||
} pjmedia_rtcp_sdes;
|
||||
|
||||
|
||||
/**
|
||||
* NTP time representation.
|
||||
*/
|
||||
struct pjmedia_rtcp_ntp_rec
|
||||
typedef struct pjmedia_rtcp_ntp_rec
|
||||
{
|
||||
pj_uint32_t hi; /**< High order 32-bit part. */
|
||||
pj_uint32_t lo; /**< Lo order 32-bit part. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_ntp_rec
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_ntp_rec pjmedia_rtcp_ntp_rec;
|
||||
|
||||
} pjmedia_rtcp_ntp_rec;
|
||||
|
||||
|
||||
/**
|
||||
* Unidirectional RTP stream statistics.
|
||||
*/
|
||||
struct pjmedia_rtcp_stream_stat
|
||||
typedef struct pjmedia_rtcp_stream_stat
|
||||
{
|
||||
pj_time_val update; /**< Time of last update. */
|
||||
unsigned update_cnt; /**< Number of updates (to calculate avg) */
|
||||
|
@ -190,20 +187,14 @@ struct pjmedia_rtcp_stream_stat
|
|||
} loss_type; /**< Types of loss detected. */
|
||||
|
||||
pj_math_stat jitter; /**< Jitter statistics (in usec) */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_stream_stat
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_stream_stat pjmedia_rtcp_stream_stat;
|
||||
|
||||
} pjmedia_rtcp_stream_stat;
|
||||
|
||||
|
||||
/**
|
||||
* Bidirectional RTP stream statistics.
|
||||
*/
|
||||
struct pjmedia_rtcp_stat
|
||||
typedef struct pjmedia_rtcp_stat
|
||||
{
|
||||
pj_time_val start; /**< Time when session was created */
|
||||
|
||||
|
@ -226,20 +217,19 @@ struct pjmedia_rtcp_stat
|
|||
receiving direction
|
||||
(in usec). */
|
||||
#endif
|
||||
};
|
||||
|
||||
pjmedia_rtcp_sdes peer_sdes; /**< Peer SDES. */
|
||||
char peer_sdes_buf_[PJMEDIA_RTCP_RX_SDES_BUF_LEN];
|
||||
/**< Peer SDES buffer. */
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_stat
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_stat pjmedia_rtcp_stat;
|
||||
} pjmedia_rtcp_stat;
|
||||
|
||||
|
||||
/**
|
||||
* RTCP session is used to monitor the RTP session of one endpoint. There
|
||||
* should only be one RTCP session for a bidirectional RTP streams.
|
||||
*/
|
||||
struct pjmedia_rtcp_session
|
||||
typedef struct pjmedia_rtcp_session
|
||||
{
|
||||
char *name; /**< Name identification. */
|
||||
pjmedia_rtcp_sr_pkt rtcp_sr_pkt;/**< Cached RTCP SR packet. */
|
||||
|
@ -278,12 +268,7 @@ struct pjmedia_rtcp_session
|
|||
*/
|
||||
pjmedia_rtcp_xr_session xr_session;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* @see pjmedia_rtcp_session
|
||||
*/
|
||||
typedef struct pjmedia_rtcp_session pjmedia_rtcp_session;
|
||||
} pjmedia_rtcp_session;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -438,6 +423,46 @@ PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session,
|
|||
void **rtcp_pkt, int *len);
|
||||
|
||||
|
||||
/**
|
||||
* Build an RTCP SDES (source description) packet. This packet can be
|
||||
* appended to other RTCP packets, e.g: RTCP RR/SR, to compose a compound
|
||||
* RTCP packet.
|
||||
*
|
||||
* @param session The RTCP session.
|
||||
* @param buf The buffer to receive RTCP SDES packet.
|
||||
* @param length On input, it will contain the buffer length.
|
||||
* On output, it will contain the generated RTCP SDES
|
||||
* packet length.
|
||||
* @param sdes The source description, see #pjmedia_rtcp_sdes.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_sdes(
|
||||
pjmedia_rtcp_session *session,
|
||||
void *buf,
|
||||
pj_size_t *length,
|
||||
const pjmedia_rtcp_sdes *sdes);
|
||||
|
||||
/**
|
||||
* Build an RTCP BYE packet. This packet can be appended to other RTCP
|
||||
* packets, e.g: RTCP RR/SR, to compose a compound RTCP packet.
|
||||
*
|
||||
* @param session The RTCP session.
|
||||
* @param buf The buffer to receive RTCP BYE packet.
|
||||
* @param length On input, it will contain the buffer length.
|
||||
* On output, it will contain the generated RTCP BYE
|
||||
* packet length.
|
||||
* @param reason Optional, the BYE reason.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_rtcp_build_rtcp_bye(
|
||||
pjmedia_rtcp_session *session,
|
||||
void *buf,
|
||||
pj_size_t *length,
|
||||
const pj_str_t *reason);
|
||||
|
||||
|
||||
/**
|
||||
* Call this function if RTCP XR needs to be enabled/disabled in the
|
||||
* RTCP session.
|
||||
|
|
|
@ -200,6 +200,17 @@ typedef struct pjmedia_rtcp_xr_rb_voip_mtc
|
|||
jitter buffer */
|
||||
} pjmedia_rtcp_xr_rb_voip_mtc;
|
||||
|
||||
|
||||
/**
|
||||
* Constant of RTCP-XR content size.
|
||||
*/
|
||||
#define PJMEDIA_RTCP_XR_BUF_SIZE \
|
||||
sizeof(pjmedia_rtcp_xr_rb_rr_time) + \
|
||||
sizeof(pjmedia_rtcp_xr_rb_dlrr) + \
|
||||
sizeof(pjmedia_rtcp_xr_rb_stats) + \
|
||||
sizeof(pjmedia_rtcp_xr_rb_voip_mtc)
|
||||
|
||||
|
||||
/**
|
||||
* This structure declares RTCP XR (Extended Report) packet.
|
||||
*/
|
||||
|
@ -221,7 +232,8 @@ typedef struct pjmedia_rtcp_xr_pkt
|
|||
pj_uint32_t ssrc; /**< SSRC identification */
|
||||
} common;
|
||||
|
||||
pj_int8_t buf[PJMEDIA_MAX_MTU];/**< Content buffer */
|
||||
pj_int8_t buf[PJMEDIA_RTCP_XR_BUF_SIZE];
|
||||
/**< Content buffer */
|
||||
} pjmedia_rtcp_xr_pkt;
|
||||
|
||||
#pragma pack()
|
||||
|
|
|
@ -200,8 +200,12 @@ typedef struct pjmedia_srtp_info
|
|||
* will also invoke this function. This function will also register SRTP
|
||||
* library deinitialization to #pj_atexit(), so the deinitialization
|
||||
* of SRTP library will be performed automatically by PJLIB destructor.
|
||||
*
|
||||
* @param endpt The media endpoint instance.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(void);
|
||||
PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1086,11 +1086,14 @@ static pj_status_t write_frame(struct conf_port *cport_dst,
|
|||
while (f_start < f_end) {
|
||||
unsigned nsamples_to_copy, nsamples_req;
|
||||
|
||||
/* Copy frame to listener's TX buffer. */
|
||||
/* Copy frame to listener's TX buffer.
|
||||
* Note that if the destination is port 0, just copy the whole
|
||||
* available samples.
|
||||
*/
|
||||
nsamples_to_copy = f_end - f_start;
|
||||
nsamples_req = cport_dst->samples_per_frame -
|
||||
(frm_dst->size>>1);
|
||||
if (nsamples_to_copy > nsamples_req)
|
||||
if (cport_dst->slot && nsamples_to_copy > nsamples_req)
|
||||
nsamples_to_copy = nsamples_req;
|
||||
|
||||
/* Adjust TX level. */
|
||||
|
@ -1123,16 +1126,19 @@ static pj_status_t write_frame(struct conf_port *cport_dst,
|
|||
|
||||
/* Check if it's time to deliver the TX buffer to listener,
|
||||
* i.e: samples count in TX buffer equal to listener's
|
||||
* samples per frame.
|
||||
* samples per frame. Note that for destination port 0 this
|
||||
* function will just populate all samples in the TX buffer.
|
||||
*/
|
||||
if ((frm_dst->size >> 1) == cport_dst->samples_per_frame)
|
||||
if (cport_dst->slot == 0) {
|
||||
/* Update TX timestamp. */
|
||||
pj_add_timestamp32(&cport_dst->ts_tx, nsamples_to_copy);
|
||||
} else if ((frm_dst->size >> 1) ==
|
||||
cport_dst->samples_per_frame)
|
||||
{
|
||||
if (cport_dst->slot) {
|
||||
pjmedia_port_put_frame(cport_dst->port, frm_dst);
|
||||
pjmedia_port_put_frame(cport_dst->port, frm_dst);
|
||||
|
||||
/* Reset TX buffer. */
|
||||
frm_dst->size = 0;
|
||||
}
|
||||
/* Reset TX buffer. */
|
||||
frm_dst->size = 0;
|
||||
|
||||
/* Update TX timestamp. */
|
||||
pj_add_timestamp32(&cport_dst->ts_tx,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <pjmedia-audiodev/audiodev.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/ioqueue.h>
|
||||
#include <pj/lock.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/os.h>
|
||||
#include <pj/pool.h>
|
||||
|
@ -57,6 +58,14 @@ static int PJ_THREAD_FUNC worker_proc(void*);
|
|||
#define MAX_THREADS 16
|
||||
|
||||
|
||||
/* List of media endpoint exit callback. */
|
||||
typedef struct exit_cb
|
||||
{
|
||||
PJ_DECL_LIST_MEMBER (struct exit_cb);
|
||||
pjmedia_endpt_exit_callback func;
|
||||
} exit_cb;
|
||||
|
||||
|
||||
/** Concrete declaration of media endpoint. */
|
||||
struct pjmedia_endpt
|
||||
{
|
||||
|
@ -86,6 +95,9 @@ struct pjmedia_endpt
|
|||
|
||||
/** Is telephone-event enable */
|
||||
pj_bool_t has_telephone_event;
|
||||
|
||||
/** List of exit callback. */
|
||||
exit_cb exit_cb_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -129,6 +141,9 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
|
|||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
||||
/* Initialize exit callback list. */
|
||||
pj_list_init(&endpt->exit_cb_list);
|
||||
|
||||
/* Create ioqueue if none is specified. */
|
||||
if (endpt->ioqueue == NULL) {
|
||||
|
||||
|
@ -189,6 +204,7 @@ PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
|
|||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
|
||||
{
|
||||
exit_cb *ecb;
|
||||
unsigned i;
|
||||
|
||||
PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
|
||||
|
@ -214,6 +230,14 @@ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
|
|||
|
||||
pjmedia_codec_mgr_destroy(&endpt->codec_mgr);
|
||||
pjmedia_aud_subsys_shutdown();
|
||||
|
||||
/* Call all registered exit callbacks */
|
||||
ecb = endpt->exit_cb_list.next;
|
||||
while (ecb != &endpt->exit_cb_list) {
|
||||
(*ecb->func)(endpt);
|
||||
ecb = ecb->next;
|
||||
}
|
||||
|
||||
pj_pool_release (endpt->pool);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
@ -434,7 +458,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt,
|
|||
rtpmap.param.slen = 1;
|
||||
|
||||
} else {
|
||||
rtpmap.param.ptr = NULL;
|
||||
rtpmap.param.ptr = "";
|
||||
rtpmap.param.slen = 0;
|
||||
}
|
||||
|
||||
|
@ -896,3 +920,23 @@ PJ_DEF(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt)
|
|||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_endpt_atexit( pjmedia_endpt *endpt,
|
||||
pjmedia_endpt_exit_callback func)
|
||||
{
|
||||
exit_cb *new_cb;
|
||||
|
||||
PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
|
||||
|
||||
if (endpt->quit_flag)
|
||||
return PJ_EINVALIDOP;
|
||||
|
||||
new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
|
||||
new_cb->func = func;
|
||||
|
||||
pj_enter_critical_section();
|
||||
pj_list_push_back(&endpt->exit_cb_list, new_cb);
|
||||
pj_leave_critical_section();
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,21 @@
|
|||
|
||||
#define RTCP_SR 200
|
||||
#define RTCP_RR 201
|
||||
#define RTCP_SDES 202
|
||||
#define RTCP_BYE 203
|
||||
#define RTCP_XR 207
|
||||
|
||||
enum {
|
||||
RTCP_SDES_NULL = 0,
|
||||
RTCP_SDES_CNAME = 1,
|
||||
RTCP_SDES_NAME = 2,
|
||||
RTCP_SDES_EMAIL = 3,
|
||||
RTCP_SDES_PHONE = 4,
|
||||
RTCP_SDES_LOC = 5,
|
||||
RTCP_SDES_TOOL = 6,
|
||||
RTCP_SDES_NOTE = 7
|
||||
};
|
||||
|
||||
#if PJ_HAS_HIGH_RES_TIMER==0
|
||||
# error "High resolution timer needs to be enabled"
|
||||
#endif
|
||||
|
@ -473,9 +486,9 @@ PJ_DEF(void) pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *sess,
|
|||
}
|
||||
|
||||
|
||||
PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess,
|
||||
const void *pkt,
|
||||
pj_size_t size)
|
||||
static void parse_rtcp_report( pjmedia_rtcp_session *sess,
|
||||
const void *pkt,
|
||||
pj_size_t size)
|
||||
{
|
||||
pjmedia_rtcp_common *common = (pjmedia_rtcp_common*) pkt;
|
||||
const pjmedia_rtcp_rr *rr = NULL;
|
||||
|
@ -615,19 +628,21 @@ PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess,
|
|||
goto end_rtt_calc;
|
||||
}
|
||||
|
||||
/* "Normalize" rtt value that is exceptionally high.
|
||||
* For such values, "normalize" the rtt to be three times
|
||||
* the average value.
|
||||
#if defined(PJMEDIA_RTCP_NORMALIZE_FACTOR) && PJMEDIA_RTCP_NORMALIZE_FACTOR!=0
|
||||
/* "Normalize" rtt value that is exceptionally high. For such
|
||||
* values, "normalize" the rtt to be PJMEDIA_RTCP_NORMALIZE_FACTOR
|
||||
* times the average value.
|
||||
*/
|
||||
if (rtt > ((unsigned)sess->stat.rtt.mean*3) && sess->stat.rtt.n!=0)
|
||||
if (rtt > ((unsigned)sess->stat.rtt.mean *
|
||||
PJMEDIA_RTCP_NORMALIZE_FACTOR) && sess->stat.rtt.n!=0)
|
||||
{
|
||||
unsigned orig_rtt = rtt;
|
||||
rtt = sess->stat.rtt.mean*3;
|
||||
PJ_LOG(5,(sess->name,
|
||||
rtt = sess->stat.rtt.mean * PJMEDIA_RTCP_NORMALIZE_FACTOR;
|
||||
PJ_LOG(5,(sess->name,
|
||||
"RTT value %d usec is normalized to %d usec",
|
||||
orig_rtt, rtt));
|
||||
}
|
||||
|
||||
#endif
|
||||
TRACE_((sess->name, "RTCP RTT is set to %d usec", rtt));
|
||||
|
||||
/* Update RTT stat */
|
||||
|
@ -650,6 +665,142 @@ end_rtt_calc:
|
|||
}
|
||||
|
||||
|
||||
static void parse_rtcp_sdes(pjmedia_rtcp_session *sess,
|
||||
const void *pkt,
|
||||
pj_size_t size)
|
||||
{
|
||||
pjmedia_rtcp_sdes *sdes = &sess->stat.peer_sdes;
|
||||
char *p, *p_end;
|
||||
char *b, *b_end;
|
||||
|
||||
p = (char*)pkt + 8;
|
||||
p_end = (char*)pkt + size;
|
||||
|
||||
pj_bzero(sdes, sizeof(*sdes));
|
||||
b = sess->stat.peer_sdes_buf_;
|
||||
b_end = b + sizeof(sess->stat.peer_sdes_buf_);
|
||||
|
||||
while (p < p_end) {
|
||||
pj_uint8_t sdes_type, sdes_len;
|
||||
pj_str_t sdes_value = {NULL, 0};
|
||||
|
||||
sdes_type = *p++;
|
||||
|
||||
/* Check for end of SDES item list */
|
||||
if (sdes_type == RTCP_SDES_NULL || p == p_end)
|
||||
break;
|
||||
|
||||
sdes_len = *p++;
|
||||
|
||||
/* Check for corrupted SDES packet */
|
||||
if (p + sdes_len > p_end)
|
||||
break;
|
||||
|
||||
/* Get SDES item */
|
||||
if (b + sdes_len < b_end) {
|
||||
pj_memcpy(b, p, sdes_len);
|
||||
sdes_value.ptr = b;
|
||||
sdes_value.slen = sdes_len;
|
||||
b += sdes_len;
|
||||
} else {
|
||||
/* Insufficient SDES buffer */
|
||||
PJ_LOG(5, (sess->name,
|
||||
"Unsufficient buffer to save RTCP SDES type %d:%.*s",
|
||||
sdes_type, sdes_len, p));
|
||||
p += sdes_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (sdes_type) {
|
||||
case RTCP_SDES_CNAME:
|
||||
sdes->cname = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_NAME:
|
||||
sdes->name = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_EMAIL:
|
||||
sdes->email = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_PHONE:
|
||||
sdes->phone = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_LOC:
|
||||
sdes->loc = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_TOOL:
|
||||
sdes->tool = sdes_value;
|
||||
break;
|
||||
case RTCP_SDES_NOTE:
|
||||
sdes->note = sdes_value;
|
||||
break;
|
||||
default:
|
||||
TRACE_((sess->name, "Received unknown RTCP SDES type %d:%.*s",
|
||||
sdes_type, sdes_value.slen, sdes_value.ptr));
|
||||
break;
|
||||
}
|
||||
|
||||
p += sdes_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void parse_rtcp_bye(pjmedia_rtcp_session *sess,
|
||||
const void *pkt,
|
||||
pj_size_t size)
|
||||
{
|
||||
pj_str_t reason = {"-", 1};
|
||||
|
||||
/* Check and get BYE reason */
|
||||
if (size > 8) {
|
||||
reason.slen = *((pj_uint8_t*)pkt+8);
|
||||
pj_memcpy(sess->stat.peer_sdes_buf_, ((pj_uint8_t*)pkt+9),
|
||||
reason.slen);
|
||||
reason.ptr = sess->stat.peer_sdes_buf_;
|
||||
}
|
||||
|
||||
/* Just print RTCP BYE log */
|
||||
PJ_LOG(5, (sess->name, "Received RTCP BYE, reason: %.*s",
|
||||
reason.slen, reason.ptr));
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(void) pjmedia_rtcp_rx_rtcp( pjmedia_rtcp_session *sess,
|
||||
const void *pkt,
|
||||
pj_size_t size)
|
||||
{
|
||||
pj_uint8_t *p, *p_end;
|
||||
|
||||
p = (pj_uint8_t*)pkt;
|
||||
p_end = p + size;
|
||||
while (p < p_end) {
|
||||
pjmedia_rtcp_common *common = (pjmedia_rtcp_common*)p;
|
||||
unsigned len;
|
||||
|
||||
len = (pj_ntohs((pj_uint16_t)common->length)+1) * 4;
|
||||
switch(common->pt) {
|
||||
case RTCP_SR:
|
||||
case RTCP_RR:
|
||||
case RTCP_XR:
|
||||
parse_rtcp_report(sess, p, len);
|
||||
break;
|
||||
case RTCP_SDES:
|
||||
parse_rtcp_sdes(sess, p, len);
|
||||
break;
|
||||
case RTCP_BYE:
|
||||
parse_rtcp_bye(sess, p, len);
|
||||
break;
|
||||
default:
|
||||
/* Ignore unknown RTCP */
|
||||
TRACE_((sess->name, "Received unknown RTCP packet type=%d",
|
||||
common->pt));
|
||||
break;
|
||||
}
|
||||
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
|
||||
void **ret_p_pkt, int *len)
|
||||
{
|
||||
|
@ -802,6 +953,128 @@ PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *sess,
|
|||
sess->stat.rx.update_cnt++;
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_sdes(
|
||||
pjmedia_rtcp_session *session,
|
||||
void *buf,
|
||||
pj_size_t *length,
|
||||
const pjmedia_rtcp_sdes *sdes)
|
||||
{
|
||||
pjmedia_rtcp_common *hdr;
|
||||
pj_uint8_t *p;
|
||||
unsigned len;
|
||||
|
||||
PJ_ASSERT_RETURN(session && buf && length && sdes, PJ_EINVAL);
|
||||
|
||||
/* Verify SDES item length */
|
||||
if (sdes->cname.slen > 255 || sdes->name.slen > 255 ||
|
||||
sdes->email.slen > 255 || sdes->phone.slen > 255 ||
|
||||
sdes->loc.slen > 255 || sdes->tool.slen > 255 ||
|
||||
sdes->note.slen > 255)
|
||||
{
|
||||
return PJ_EINVAL;
|
||||
}
|
||||
|
||||
/* Verify buffer length */
|
||||
len = sizeof(*hdr);
|
||||
if (sdes->cname.slen) len += sdes->cname.slen + 2;
|
||||
if (sdes->name.slen) len += sdes->name.slen + 2;
|
||||
if (sdes->email.slen) len += sdes->email.slen + 2;
|
||||
if (sdes->phone.slen) len += sdes->phone.slen + 2;
|
||||
if (sdes->loc.slen) len += sdes->loc.slen + 2;
|
||||
if (sdes->tool.slen) len += sdes->tool.slen + 2;
|
||||
if (sdes->note.slen) len += sdes->note.slen + 2;
|
||||
len++; /* null termination */
|
||||
len = ((len+3)/4) * 4;
|
||||
if (len > *length)
|
||||
return PJ_ETOOSMALL;
|
||||
|
||||
/* Build RTCP SDES header */
|
||||
hdr = (pjmedia_rtcp_common*)buf;
|
||||
pj_memcpy(hdr, &session->rtcp_sr_pkt.common, sizeof(*hdr));
|
||||
hdr->pt = RTCP_SDES;
|
||||
hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
|
||||
|
||||
/* Build RTCP SDES items */
|
||||
p = (pj_uint8_t*)hdr + sizeof(*hdr);
|
||||
#define BUILD_SDES_ITEM(SDES_NAME, SDES_TYPE) \
|
||||
if (sdes->SDES_NAME.slen) { \
|
||||
*p++ = SDES_TYPE; \
|
||||
*p++ = (pj_uint8_t)sdes->SDES_NAME.slen; \
|
||||
pj_memcpy(p, sdes->SDES_NAME.ptr, sdes->SDES_NAME.slen); \
|
||||
p += sdes->SDES_NAME.slen; \
|
||||
}
|
||||
BUILD_SDES_ITEM(cname, RTCP_SDES_CNAME);
|
||||
BUILD_SDES_ITEM(name, RTCP_SDES_NAME);
|
||||
BUILD_SDES_ITEM(email, RTCP_SDES_EMAIL);
|
||||
BUILD_SDES_ITEM(phone, RTCP_SDES_PHONE);
|
||||
BUILD_SDES_ITEM(loc, RTCP_SDES_LOC);
|
||||
BUILD_SDES_ITEM(tool, RTCP_SDES_TOOL);
|
||||
BUILD_SDES_ITEM(note, RTCP_SDES_NOTE);
|
||||
#undef BUILD_SDES_ITEM
|
||||
|
||||
/* Null termination */
|
||||
*p++ = 0;
|
||||
|
||||
/* Pad to 32bit */
|
||||
while ((p-(pj_uint8_t*)buf) % 4)
|
||||
*p++ = 0;
|
||||
|
||||
/* Finally */
|
||||
pj_assert((int)len == p-(pj_uint8_t*)buf);
|
||||
*length = len;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_rtcp_build_rtcp_bye(pjmedia_rtcp_session *session,
|
||||
void *buf,
|
||||
pj_size_t *length,
|
||||
const pj_str_t *reason)
|
||||
{
|
||||
pjmedia_rtcp_common *hdr;
|
||||
pj_uint8_t *p;
|
||||
unsigned len;
|
||||
|
||||
PJ_ASSERT_RETURN(session && buf && length, PJ_EINVAL);
|
||||
|
||||
/* Verify BYE reason length */
|
||||
if (reason && reason->slen > 255)
|
||||
return PJ_EINVAL;
|
||||
|
||||
/* Verify buffer length */
|
||||
len = sizeof(*hdr);
|
||||
if (reason && reason->slen) len += reason->slen + 1;
|
||||
len = ((len+3)/4) * 4;
|
||||
if (len > *length)
|
||||
return PJ_ETOOSMALL;
|
||||
|
||||
/* Build RTCP BYE header */
|
||||
hdr = (pjmedia_rtcp_common*)buf;
|
||||
pj_memcpy(hdr, &session->rtcp_sr_pkt.common, sizeof(*hdr));
|
||||
hdr->pt = RTCP_BYE;
|
||||
hdr->length = pj_htons((pj_uint16_t)(len/4 - 1));
|
||||
|
||||
/* Write RTCP BYE reason */
|
||||
p = (pj_uint8_t*)hdr + sizeof(*hdr);
|
||||
if (reason && reason->slen) {
|
||||
*p++ = (pj_uint8_t)reason->slen;
|
||||
pj_memcpy(p, reason->ptr, reason->slen);
|
||||
p += reason->slen;
|
||||
}
|
||||
|
||||
/* Pad to 32bit */
|
||||
while ((p-(pj_uint8_t*)buf) % 4)
|
||||
*p++ = 0;
|
||||
|
||||
pj_assert((int)len == p-(pj_uint8_t*)buf);
|
||||
*length = len;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_rtcp_enable_xr( pjmedia_rtcp_session *sess,
|
||||
pj_bool_t enable)
|
||||
{
|
||||
|
|
|
@ -441,7 +441,6 @@ PJ_DEF(pj_status_t) pjmedia_snd_port_create2(pj_pool_t *pool,
|
|||
snd_port->dir = prm->base.dir;
|
||||
snd_port->rec_id = prm->base.rec_id;
|
||||
snd_port->play_id = prm->base.play_id;
|
||||
snd_port->dir = PJMEDIA_DIR_CAPTURE_PLAYBACK;
|
||||
snd_port->clock_rate = prm->base.clock_rate;
|
||||
snd_port->channel_count = prm->base.channel_count;
|
||||
snd_port->samples_per_frame = prm->base.samples_per_frame;
|
||||
|
|
|
@ -155,6 +155,9 @@ struct pjmedia_stream
|
|||
pj_uint32_t rtcp_interval; /**< Interval, in timestamp. */
|
||||
pj_bool_t initial_rr; /**< Initial RTCP RR sent */
|
||||
pj_bool_t rtcp_sdes_bye_disabled;/**< Send RTCP SDES/BYE?*/
|
||||
void *out_rtcp_pkt; /**< Outgoing RTCP packet. */
|
||||
unsigned out_rtcp_pkt_size;
|
||||
/**< Outgoing RTCP packet size. */
|
||||
|
||||
/* RFC 2833 DTMF transmission queue: */
|
||||
int tx_event_pt; /**< Outgoing pt for dtmf. */
|
||||
|
@ -245,6 +248,12 @@ static void stream_perror(const char *sender, const char *title,
|
|||
}
|
||||
|
||||
|
||||
static pj_status_t send_rtcp(pjmedia_stream *stream,
|
||||
pj_bool_t with_sdes,
|
||||
pj_bool_t with_bye,
|
||||
pj_bool_t with_xr);
|
||||
|
||||
|
||||
#if TRACE_JB
|
||||
|
||||
PJ_INLINE(int) trace_jb_print_timestamp(char **buf, pj_ssize_t len)
|
||||
|
@ -425,8 +434,7 @@ static void send_keep_alive_packet(pjmedia_stream *stream)
|
|||
pkt_len);
|
||||
|
||||
/* Send RTCP */
|
||||
pjmedia_rtcp_build_rtcp(&stream->rtcp, &pkt, &pkt_len);
|
||||
pjmedia_transport_send_rtcp(stream->transport, pkt, pkt_len);
|
||||
send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE);
|
||||
|
||||
#elif PJMEDIA_STREAM_ENABLE_KA == PJMEDIA_STREAM_KA_USER
|
||||
|
||||
|
@ -913,6 +921,114 @@ static void create_dtmf_payload(pjmedia_stream *stream,
|
|||
}
|
||||
|
||||
|
||||
static pj_status_t send_rtcp(pjmedia_stream *stream,
|
||||
pj_bool_t with_sdes,
|
||||
pj_bool_t with_bye,
|
||||
pj_bool_t with_xr)
|
||||
{
|
||||
void *sr_rr_pkt;
|
||||
pj_uint8_t *pkt;
|
||||
int len, max_len;
|
||||
pj_status_t status;
|
||||
|
||||
/* Build RTCP RR/SR packet */
|
||||
pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
|
||||
|
||||
#if !defined(PJMEDIA_HAS_RTCP_XR) || (PJMEDIA_HAS_RTCP_XR == 0)
|
||||
with_xr = PJ_FALSE;
|
||||
#endif
|
||||
|
||||
if (with_sdes || with_bye || with_xr) {
|
||||
pkt = (pj_uint8_t*) stream->out_rtcp_pkt;
|
||||
pj_memcpy(pkt, sr_rr_pkt, len);
|
||||
max_len = stream->out_rtcp_pkt_size;
|
||||
} else {
|
||||
pkt = sr_rr_pkt;
|
||||
max_len = len;
|
||||
}
|
||||
|
||||
/* Build RTCP SDES packet */
|
||||
if (with_sdes) {
|
||||
pjmedia_rtcp_sdes sdes;
|
||||
pj_size_t sdes_len;
|
||||
|
||||
pj_bzero(&sdes, sizeof(sdes));
|
||||
sdes.cname = stream->cname;
|
||||
sdes_len = max_len - len;
|
||||
status = pjmedia_rtcp_build_rtcp_sdes(&stream->rtcp, pkt+len,
|
||||
&sdes_len, &sdes);
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, status,
|
||||
"Error generating RTCP SDES"));
|
||||
} else {
|
||||
len += sdes_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build RTCP XR packet */
|
||||
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
|
||||
if (with_xr) {
|
||||
int i;
|
||||
pjmedia_jb_state jb_state;
|
||||
void *xr_pkt;
|
||||
int xr_len;
|
||||
|
||||
/* Update RTCP XR with current JB states */
|
||||
pjmedia_jbuf_get_state(stream->jb, &jb_state);
|
||||
|
||||
i = jb_state.avg_delay;
|
||||
status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_NOM, i);
|
||||
pj_assert(status == PJ_SUCCESS);
|
||||
|
||||
i = jb_state.max_delay;
|
||||
status = pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_MAX, i);
|
||||
pj_assert(status == PJ_SUCCESS);
|
||||
|
||||
pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,
|
||||
&xr_pkt, &xr_len);
|
||||
|
||||
if (xr_len + len <= max_len) {
|
||||
pj_memcpy(pkt+len, xr_pkt, xr_len);
|
||||
len += xr_len;
|
||||
|
||||
/* Send the RTCP XR to third-party destination if specified */
|
||||
if (stream->rtcp_xr_dest_len) {
|
||||
pjmedia_transport_send_rtcp2(stream->transport,
|
||||
&stream->rtcp_xr_dest,
|
||||
stream->rtcp_xr_dest_len,
|
||||
xr_pkt, xr_len);
|
||||
}
|
||||
|
||||
} else {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, PJ_ETOOBIG,
|
||||
"Error generating RTCP-XR"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build RTCP BYE packet */
|
||||
if (with_bye) {
|
||||
pj_size_t bye_len;
|
||||
|
||||
bye_len = max_len - len;
|
||||
status = pjmedia_rtcp_build_rtcp_bye(&stream->rtcp, pkt+len,
|
||||
&bye_len, NULL);
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, status,
|
||||
"Error generating RTCP BYE"));
|
||||
} else {
|
||||
len += bye_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send! */
|
||||
status = pjmedia_transport_send_rtcp(stream->transport, pkt, len);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* check_tx_rtcp()
|
||||
*
|
||||
|
@ -926,133 +1042,38 @@ static void check_tx_rtcp(pjmedia_stream *stream, pj_uint32_t timestamp)
|
|||
* or get_frame().
|
||||
*/
|
||||
|
||||
|
||||
if (stream->rtcp_last_tx == 0) {
|
||||
|
||||
stream->rtcp_last_tx = timestamp;
|
||||
|
||||
} else if (timestamp - stream->rtcp_last_tx >= stream->rtcp_interval) {
|
||||
|
||||
void *rtcp_pkt;
|
||||
int len;
|
||||
pj_bool_t with_xr = PJ_FALSE;
|
||||
pj_status_t status;
|
||||
|
||||
pjmedia_rtcp_build_rtcp(&stream->rtcp, &rtcp_pkt, &len);
|
||||
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
|
||||
if (stream->rtcp.xr_enabled) {
|
||||
if (stream->rtcp_xr_last_tx == 0) {
|
||||
stream->rtcp_xr_last_tx = timestamp;
|
||||
} else if (timestamp - stream->rtcp_xr_last_tx >=
|
||||
stream->rtcp_xr_interval)
|
||||
{
|
||||
with_xr = PJ_TRUE;
|
||||
|
||||
pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len);
|
||||
/* Update last tx RTCP XR */
|
||||
stream->rtcp_xr_last_tx = timestamp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled, PJ_FALSE,
|
||||
with_xr);
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, status,
|
||||
"Error sending RTCP"));
|
||||
}
|
||||
|
||||
stream->rtcp_last_tx = timestamp;
|
||||
}
|
||||
|
||||
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
|
||||
if (stream->rtcp.xr_enabled) {
|
||||
|
||||
if (stream->rtcp_xr_last_tx == 0) {
|
||||
|
||||
stream->rtcp_xr_last_tx = timestamp;
|
||||
|
||||
} else if (timestamp - stream->rtcp_xr_last_tx >=
|
||||
stream->rtcp_xr_interval)
|
||||
{
|
||||
int i;
|
||||
pjmedia_jb_state jb_state;
|
||||
void *rtcp_pkt;
|
||||
int len;
|
||||
|
||||
/* Update RTCP XR with current JB states */
|
||||
pjmedia_jbuf_get_state(stream->jb, &jb_state);
|
||||
|
||||
i = jb_state.avg_delay;
|
||||
pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_NOM,
|
||||
i);
|
||||
|
||||
i = jb_state.max_delay;
|
||||
pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_MAX,
|
||||
i);
|
||||
|
||||
/* Build RTCP XR packet */
|
||||
pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,
|
||||
&rtcp_pkt, &len);
|
||||
|
||||
/* Send the RTCP XR to remote address */
|
||||
pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len);
|
||||
|
||||
/* Send the RTCP XR to third-party destination if specified */
|
||||
if (stream->rtcp_xr_dest_len) {
|
||||
pjmedia_transport_send_rtcp2(stream->transport,
|
||||
&stream->rtcp_xr_dest,
|
||||
stream->rtcp_xr_dest_len,
|
||||
rtcp_pkt, len);
|
||||
}
|
||||
|
||||
/* Update last tx RTCP XR */
|
||||
stream->rtcp_xr_last_tx = timestamp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Build RTCP SDES packet */
|
||||
static unsigned create_rtcp_sdes(pjmedia_stream *stream, pj_uint8_t *pkt,
|
||||
unsigned max_len)
|
||||
{
|
||||
pjmedia_rtcp_common hdr;
|
||||
pj_uint8_t *p = pkt;
|
||||
|
||||
/* SDES header */
|
||||
hdr.version = 2;
|
||||
hdr.p = 0;
|
||||
hdr.count = 1;
|
||||
hdr.pt = 202;
|
||||
hdr.length = 2 + (4+stream->cname.slen+3)/4 - 1;
|
||||
if (max_len < (hdr.length << 2)) {
|
||||
pj_assert(!"Not enough buffer for SDES packet");
|
||||
return 0;
|
||||
}
|
||||
hdr.length = pj_htons((pj_uint16_t)hdr.length);
|
||||
hdr.ssrc = stream->enc->rtp.out_hdr.ssrc;
|
||||
pj_memcpy(p, &hdr, sizeof(hdr));
|
||||
p += sizeof(hdr);
|
||||
|
||||
/* CNAME item */
|
||||
*p++ = 1;
|
||||
*p++ = (pj_uint8_t)stream->cname.slen;
|
||||
pj_memcpy(p, stream->cname.ptr, stream->cname.slen);
|
||||
p += stream->cname.slen;
|
||||
|
||||
/* END */
|
||||
*p++ = '\0';
|
||||
*p++ = '\0';
|
||||
|
||||
/* Pad to 32bit */
|
||||
while ((p-pkt) % 4)
|
||||
*p++ = '\0';
|
||||
|
||||
return (p - pkt);
|
||||
}
|
||||
|
||||
/* Build RTCP BYE packet */
|
||||
static unsigned create_rtcp_bye(pjmedia_stream *stream, pj_uint8_t *pkt,
|
||||
unsigned max_len)
|
||||
{
|
||||
pjmedia_rtcp_common hdr;
|
||||
|
||||
/* BYE header */
|
||||
hdr.version = 2;
|
||||
hdr.p = 0;
|
||||
hdr.count = 1;
|
||||
hdr.pt = 203;
|
||||
hdr.length = 1;
|
||||
if (max_len < (hdr.length << 2)) {
|
||||
pj_assert(!"Not enough buffer for SDES packet");
|
||||
return 0;
|
||||
}
|
||||
hdr.length = pj_htons((pj_uint16_t)hdr.length);
|
||||
hdr.ssrc = stream->enc->rtp.out_hdr.ssrc;
|
||||
pj_memcpy(pkt, &hdr, sizeof(hdr));
|
||||
|
||||
return sizeof(hdr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1348,8 +1369,13 @@ static pj_status_t put_frame_imp( pjmedia_port *port,
|
|||
stream->is_streaming = PJ_TRUE;
|
||||
|
||||
/* Send the RTP packet to the transport. */
|
||||
pjmedia_transport_send_rtp(stream->transport, channel->out_pkt,
|
||||
frame_out.size + sizeof(pjmedia_rtp_hdr));
|
||||
status = pjmedia_transport_send_rtp(stream->transport, channel->out_pkt,
|
||||
frame_out.size +
|
||||
sizeof(pjmedia_rtp_hdr));
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, status,
|
||||
"Error sending RTP"));
|
||||
}
|
||||
|
||||
/* Update stat */
|
||||
pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size);
|
||||
|
@ -1819,32 +1845,14 @@ on_return:
|
|||
|
||||
/* Send RTCP RR and SDES after we receive some RTP packets */
|
||||
if (stream->rtcp.received >= 10 && !stream->initial_rr) {
|
||||
void *sr_rr_pkt;
|
||||
pj_uint8_t *pkt;
|
||||
int len;
|
||||
|
||||
/* Build RR or SR */
|
||||
pjmedia_rtcp_build_rtcp(&stream->rtcp, &sr_rr_pkt, &len);
|
||||
|
||||
if (!stream->rtcp_sdes_bye_disabled) {
|
||||
pkt = (pj_uint8_t*) stream->enc->out_pkt;
|
||||
pj_memcpy(pkt, sr_rr_pkt, len);
|
||||
pkt += len;
|
||||
|
||||
/* Append SDES */
|
||||
len = create_rtcp_sdes(stream, (pj_uint8_t*)pkt,
|
||||
stream->enc->out_pkt_size - len);
|
||||
if (len > 0) {
|
||||
pkt += len;
|
||||
len = ((pj_uint8_t*)pkt) - ((pj_uint8_t*)stream->enc->out_pkt);
|
||||
pjmedia_transport_send_rtcp(stream->transport,
|
||||
stream->enc->out_pkt, len);
|
||||
}
|
||||
} else {
|
||||
pjmedia_transport_send_rtcp(stream->transport, sr_rr_pkt, len);
|
||||
}
|
||||
|
||||
stream->initial_rr = PJ_TRUE;
|
||||
status = send_rtcp(stream, !stream->rtcp_sdes_bye_disabled,
|
||||
PJ_FALSE, PJ_FALSE);
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_PERROR(4,(stream->port.info.name.ptr, status,
|
||||
"Error sending initial RTCP RR"));
|
||||
} else {
|
||||
stream->initial_rr = PJ_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1882,7 +1890,6 @@ static pj_status_t create_channel( pj_pool_t *pool,
|
|||
{
|
||||
pjmedia_channel *channel;
|
||||
pj_status_t status;
|
||||
unsigned min_out_pkt_size;
|
||||
|
||||
/* Allocate memory for channel descriptor */
|
||||
|
||||
|
@ -1914,15 +1921,6 @@ static pj_status_t create_channel( pj_pool_t *pool,
|
|||
return PJ_ENOTSUP;
|
||||
}
|
||||
|
||||
/* It should big enough to hold (minimally) RTCP SR with an SDES. */
|
||||
min_out_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) +
|
||||
sizeof(pjmedia_rtcp_common) +
|
||||
(4 + stream->cname.slen) +
|
||||
32;
|
||||
|
||||
if (channel->out_pkt_size < min_out_pkt_size)
|
||||
channel->out_pkt_size = min_out_pkt_size;
|
||||
|
||||
channel->out_pkt = pj_pool_alloc(pool, channel->out_pkt_size);
|
||||
PJ_ASSERT_RETURN(channel->out_pkt != NULL, PJ_ENOMEM);
|
||||
|
||||
|
@ -2265,8 +2263,31 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt,
|
|||
#endif
|
||||
|
||||
pjmedia_rtcp_init2(&stream->rtcp, &rtcp_setting);
|
||||
|
||||
if (info->rtp_seq_ts_set) {
|
||||
stream->rtcp.stat.rtp_tx_last_seq = info->rtp_seq;
|
||||
stream->rtcp.stat.rtp_tx_last_ts = info->rtp_ts;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate outgoing RTCP buffer, should be enough to hold SR/RR, SDES,
|
||||
* BYE, and XR.
|
||||
*/
|
||||
stream->out_rtcp_pkt_size = sizeof(pjmedia_rtcp_sr_pkt) +
|
||||
sizeof(pjmedia_rtcp_common) +
|
||||
(4 + stream->cname.slen) +
|
||||
32;
|
||||
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
|
||||
if (info->rtcp_xr_enabled) {
|
||||
stream->out_rtcp_pkt_size += sizeof(pjmedia_rtcp_xr_pkt);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (stream->out_rtcp_pkt_size > PJMEDIA_MAX_MTU)
|
||||
stream->out_rtcp_pkt_size = PJMEDIA_MAX_MTU;
|
||||
|
||||
stream->out_rtcp_pkt = pj_pool_alloc(pool, stream->out_rtcp_pkt_size);
|
||||
|
||||
/* Only attach transport when stream is ready. */
|
||||
status = pjmedia_transport_attach(tp, stream, &info->rem_addr,
|
||||
&info->rem_rtcp,
|
||||
|
@ -2391,47 +2412,9 @@ PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream )
|
|||
{
|
||||
PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL);
|
||||
|
||||
#if defined(PJMEDIA_HAS_RTCP_XR) && (PJMEDIA_HAS_RTCP_XR != 0)
|
||||
/* Send RTCP XR on stream destroy */
|
||||
if (stream->rtcp.xr_enabled) {
|
||||
int i;
|
||||
pjmedia_jb_state jb_state;
|
||||
void *rtcp_pkt;
|
||||
int len;
|
||||
|
||||
/* Update RTCP XR with current JB states */
|
||||
pjmedia_jbuf_get_state(stream->jb, &jb_state);
|
||||
|
||||
i = jb_state.avg_delay;
|
||||
pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_NOM,
|
||||
i);
|
||||
|
||||
i = jb_state.max_delay;
|
||||
pjmedia_rtcp_xr_update_info(&stream->rtcp.xr_session,
|
||||
PJMEDIA_RTCP_XR_INFO_JB_MAX,
|
||||
i);
|
||||
|
||||
/* Build RTCP XR packet */
|
||||
pjmedia_rtcp_build_rtcp_xr(&stream->rtcp.xr_session, 0,
|
||||
&rtcp_pkt, &len);
|
||||
|
||||
/* Send the RTCP XR to remote address */
|
||||
pjmedia_transport_send_rtcp(stream->transport, rtcp_pkt, len);
|
||||
|
||||
/* Send the RTCP XR to third-party destination if specified */
|
||||
if (stream->rtcp_xr_dest_len) {
|
||||
pjmedia_transport_send_rtcp2(stream->transport,
|
||||
&stream->rtcp_xr_dest,
|
||||
stream->rtcp_xr_dest_len,
|
||||
rtcp_pkt, len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send RTCP BYE */
|
||||
/* Send RTCP BYE (also SDES & XR) */
|
||||
if (!stream->rtcp_sdes_bye_disabled) {
|
||||
pjmedia_stream_send_rtcp_bye(stream);
|
||||
send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_TRUE);
|
||||
}
|
||||
|
||||
/* Detach from transport
|
||||
|
@ -2799,18 +2782,9 @@ PJ_DEF(pj_status_t) pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream,
|
|||
PJ_DEF(pj_status_t)
|
||||
pjmedia_stream_send_rtcp_sdes( pjmedia_stream *stream )
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
|
||||
|
||||
len = create_rtcp_sdes(stream, (pj_uint8_t*)stream->enc->out_pkt,
|
||||
stream->enc->out_pkt_size);
|
||||
if (len != 0) {
|
||||
return pjmedia_transport_send_rtcp(stream->transport,
|
||||
stream->enc->out_pkt, len);
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
return send_rtcp(stream, PJ_TRUE, PJ_FALSE, PJ_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2822,14 +2796,7 @@ pjmedia_stream_send_rtcp_bye( pjmedia_stream *stream )
|
|||
PJ_ASSERT_RETURN(stream, PJ_EINVAL);
|
||||
|
||||
if (stream->enc && stream->transport) {
|
||||
unsigned len;
|
||||
|
||||
len = create_rtcp_bye(stream, (pj_uint8_t*)stream->enc->out_pkt,
|
||||
stream->enc->out_pkt_size);
|
||||
if (len != 0) {
|
||||
return pjmedia_transport_send_rtcp(stream->transport,
|
||||
stream->enc->out_pkt, len);
|
||||
}
|
||||
return send_rtcp(stream, PJ_TRUE, PJ_TRUE, PJ_FALSE);
|
||||
}
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
|
|
@ -419,7 +419,9 @@ static pj_status_t encode_session_in_sdp(struct transport_ice *tp_ice,
|
|||
* the session, in this case we will answer with full ICE SDP and
|
||||
* new ufrag/pwd pair.
|
||||
*/
|
||||
if (!restart_session && pj_ice_strans_sess_is_complete(tp_ice->ice_st)) {
|
||||
if (!restart_session && pj_ice_strans_sess_is_complete(tp_ice->ice_st) &&
|
||||
pj_ice_strans_get_state(tp_ice->ice_st) != PJ_ICE_STRANS_STATE_FAILED)
|
||||
{
|
||||
const pj_ice_sess_check *check;
|
||||
char *attr_buf;
|
||||
pjmedia_sdp_conn *conn;
|
||||
|
@ -549,7 +551,10 @@ static pj_status_t encode_session_in_sdp(struct transport_ice *tp_ice,
|
|||
pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
|
||||
}
|
||||
|
||||
} else if (pj_ice_strans_has_sess(tp_ice->ice_st)) {
|
||||
} else if (pj_ice_strans_has_sess(tp_ice->ice_st) &&
|
||||
pj_ice_strans_get_state(tp_ice->ice_st) !=
|
||||
PJ_ICE_STRANS_STATE_FAILED)
|
||||
{
|
||||
/* Encode all candidates to SDP media */
|
||||
char *attr_buf;
|
||||
unsigned comp;
|
||||
|
|
|
@ -270,9 +270,9 @@ const char* get_libsrtp_errstr(int err)
|
|||
}
|
||||
|
||||
static pj_bool_t libsrtp_initialized;
|
||||
static void pjmedia_srtp_deinit_lib(void);
|
||||
static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt);
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
|
||||
PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt)
|
||||
{
|
||||
if (libsrtp_initialized == PJ_FALSE) {
|
||||
err_status_t err;
|
||||
|
@ -284,7 +284,8 @@ PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
|
|||
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
|
||||
}
|
||||
|
||||
if (pj_atexit(pjmedia_srtp_deinit_lib) != PJ_SUCCESS) {
|
||||
if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS)
|
||||
{
|
||||
/* There will be memory leak when it fails to schedule libsrtp
|
||||
* deinitialization, however the memory leak could be harmless,
|
||||
* since in modern OS's memory used by an application is released
|
||||
|
@ -299,10 +300,19 @@ PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
|
|||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
static void pjmedia_srtp_deinit_lib(void)
|
||||
static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt)
|
||||
{
|
||||
err_status_t err;
|
||||
|
||||
/* Note that currently this SRTP init/deinit is not equipped with
|
||||
* reference counter, it should be safe as normally there is only
|
||||
* one single instance of media endpoint and even if it isn't, the
|
||||
* pjmedia_transport_srtp_create() will invoke SRTP init (the only
|
||||
* drawback should be the delay described by #788).
|
||||
*/
|
||||
|
||||
PJ_UNUSED_ARG(endpt);
|
||||
|
||||
err = srtp_deinit();
|
||||
if (err != err_status_ok) {
|
||||
PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s",
|
||||
|
@ -410,7 +420,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_srtp_create(
|
|||
}
|
||||
|
||||
/* Init libsrtp. */
|
||||
status = pjmedia_srtp_init_lib();
|
||||
status = pjmedia_srtp_init_lib(endpt);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
@ -907,19 +917,22 @@ static void srtp_rtp_cb( void *user_data, void *pkt, pj_ssize_t size)
|
|||
(err == err_status_replay_old || err == err_status_replay_fail))
|
||||
{
|
||||
/* Handle such condition that stream is updated (RTP seq is reinited
|
||||
* & SRTP is restarted), but some old packets are still coming
|
||||
* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
|
||||
* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
|
||||
* will returning err_status_replay_*. Restarting SRTP can resolve
|
||||
* this.
|
||||
*/
|
||||
if (pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
|
||||
&srtp->tx_policy, &srtp->rx_policy)
|
||||
!= PJ_SUCCESS)
|
||||
{
|
||||
* & SRTP is restarted), but some old packets are still coming
|
||||
* so SRTP is learning wrong RTP seq. While the newly inited RTP seq
|
||||
* comes, SRTP thinks the RTP seq is replayed, so srtp_unprotect()
|
||||
* will return err_status_replay_*. Restarting SRTP can resolve this.
|
||||
*/
|
||||
pjmedia_srtp_crypto tx, rx;
|
||||
pj_status_t status;
|
||||
|
||||
tx = srtp->tx_policy;
|
||||
rx = srtp->rx_policy;
|
||||
status = pjmedia_transport_srtp_start((pjmedia_transport*)srtp,
|
||||
&tx, &rx);
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJ_LOG(5,(srtp->pool->obj_name, "Failed to restart SRTP, err=%s",
|
||||
get_libsrtp_errstr(err)));
|
||||
} else {
|
||||
} else if (!srtp->bypass_srtp) {
|
||||
err = srtp_unprotect(srtp->srtp_rx_ctx, (pj_uint8_t*)pkt, &len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2854,6 +2854,8 @@ PJ_DEF(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice,
|
|||
pj_status_t status = PJ_SUCCESS;
|
||||
pj_ice_sess_comp *comp;
|
||||
pj_ice_sess_cand *cand;
|
||||
pj_uint8_t transport_id;
|
||||
pj_sockaddr addr;
|
||||
|
||||
PJ_ASSERT_RETURN(ice && comp_id, PJ_EINVAL);
|
||||
|
||||
|
@ -2869,22 +2871,29 @@ PJ_DEF(pj_status_t) pj_ice_sess_send_data(pj_ice_sess *ice,
|
|||
comp = find_comp(ice, comp_id);
|
||||
if (comp == NULL) {
|
||||
status = PJNATH_EICEINCOMPID;
|
||||
pj_mutex_unlock(ice->mutex);
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
if (comp->valid_check == NULL) {
|
||||
status = PJNATH_EICEINPROGRESS;
|
||||
pj_mutex_unlock(ice->mutex);
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
cand = comp->valid_check->lcand;
|
||||
status = (*ice->cb.on_tx_pkt)(ice, comp_id, cand->transport_id,
|
||||
transport_id = cand->transport_id;
|
||||
pj_sockaddr_cp(&addr, &comp->valid_check->rcand->addr);
|
||||
|
||||
/* Release the mutex now to avoid deadlock (see ticket #1451). */
|
||||
pj_mutex_unlock(ice->mutex);
|
||||
|
||||
status = (*ice->cb.on_tx_pkt)(ice, comp_id, transport_id,
|
||||
data, data_len,
|
||||
&comp->valid_check->rcand->addr,
|
||||
&addr,
|
||||
sizeof(pj_sockaddr_in));
|
||||
|
||||
on_return:
|
||||
pj_mutex_unlock(ice->mutex);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -1180,8 +1180,11 @@ PJ_DEF(pj_status_t) pj_ice_strans_sendto( pj_ice_strans *ice_st,
|
|||
|
||||
/* If ICE is available, send data with ICE, otherwise send with the
|
||||
* default candidate selected during initialization.
|
||||
*
|
||||
* https://trac.pjsip.org/repos/ticket/1416:
|
||||
* Once ICE has failed, also send data with the default candidate.
|
||||
*/
|
||||
if (ice_st->ice) {
|
||||
if (ice_st->ice && ice_st->state < PJ_ICE_STRANS_STATE_FAILED) {
|
||||
if (comp->turn_sock) {
|
||||
pj_turn_sock_lock(comp->turn_sock);
|
||||
}
|
||||
|
@ -1406,6 +1409,11 @@ static pj_bool_t stun_on_rx_data(pj_stun_sock *stun_sock,
|
|||
pj_status_t status;
|
||||
|
||||
comp = (pj_ice_strans_comp*) pj_stun_sock_get_user_data(stun_sock);
|
||||
if (comp == NULL) {
|
||||
/* We have disassociated ourselves from the STUN socket */
|
||||
return PJ_FALSE;
|
||||
}
|
||||
|
||||
ice_st = comp->ice_st;
|
||||
|
||||
sess_add_ref(ice_st);
|
||||
|
|
|
@ -504,7 +504,7 @@ static pj_status_t get_mapped_addr(pj_stun_sock *stun_sock)
|
|||
PJ_FALSE, PJ_TRUE, &stun_sock->srv_addr,
|
||||
pj_sockaddr_get_len(&stun_sock->srv_addr),
|
||||
tdata);
|
||||
if (status != PJ_SUCCESS)
|
||||
if (status != PJ_SUCCESS && status != PJ_EPENDING)
|
||||
goto on_error;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
3A3479871154EC4E00D51880 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479861154EC4E00D51880 /* AudioToolbox.framework */; };
|
||||
3A34799A1154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A3479991154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a */; };
|
||||
3A34799C1154ECB100D51880 /* libresample-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A34799B1154ECB100D51880 /* libresample-arm-apple-darwin9.a */; };
|
||||
3ABE0507147CA00B00A57A62 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ABE0506147CA00B00A57A62 /* CFNetwork.framework */; };
|
||||
3AC6435E1162192900B7A751 /* tock8.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3AC6435D1162192900B7A751 /* tock8.wav */; };
|
||||
3ADA4AB911572300008D95FE /* input.8.wav in Resources */ = {isa = PBXBuildFile; fileRef = 3ADA4AB811572300008D95FE /* input.8.wav */; };
|
||||
3AE90E9B115F7A4F00FAEAA5 /* libg7221codec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90E95115F7A4E00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */; };
|
||||
|
@ -73,8 +74,9 @@
|
|||
3A3479861154EC4E00D51880 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
3A3479991154ECA300D51880 /* libgsmcodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libgsmcodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libgsmcodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
3A34799B1154ECB100D51880 /* libresample-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libresample-arm-apple-darwin9.a"; path = "../../../third_party/lib/libresample-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
3ABE0506147CA00B00A57A62 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
|
||||
3AC6435D1162192900B7A751 /* tock8.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = tock8.wav; path = ../../../tests/pjsua/wavs/tock8.wav; sourceTree = SOURCE_ROOT; };
|
||||
3ADA4AB811572300008D95FE /* input.8.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = input.8.wav; path = ../../../../../tests/pjsua/wavs/input.8.wav; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3ADA4AB811572300008D95FE /* input.8.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = input.8.wav; path = "../../../../../../../../teluu/pjproject-new-iphone/tests/pjsua/wavs/input.8.wav"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3AE90E95115F7A4E00FAEAA5 /* libg7221codec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libg7221codec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libg7221codec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
3AE90E96115F7A4F00FAEAA5 /* libilbccodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libilbccodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libilbccodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
3AE90E97115F7A4F00FAEAA5 /* libmilenage-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmilenage-arm-apple-darwin9.a"; path = "../../../third_party/lib/libmilenage-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -111,6 +113,7 @@
|
|||
3AE90E9E115F7A4F00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */,
|
||||
3AE90E9F115F7A4F00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */,
|
||||
3AE90EA0115F7A4F00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */,
|
||||
3ABE0507147CA00B00A57A62 /* CFNetwork.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -177,6 +180,7 @@
|
|||
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3ABE0506147CA00B00A57A62 /* CFNetwork.framework */,
|
||||
3A3479861154EC4E00D51880 /* AudioToolbox.framework */,
|
||||
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
|
||||
1D30AB110D05D00D00671497 /* Foundation.framework */,
|
||||
|
@ -250,6 +254,7 @@
|
|||
};
|
||||
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ipjsystest" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
English,
|
||||
|
@ -307,6 +312,7 @@
|
|||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = ipjsystest_Prefix.pch;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "PJ_AUTOCONF=1";
|
||||
INFOPLIST_FILE = "ipjsystest-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -318,6 +324,7 @@
|
|||
"\"$(SRCROOT)/../../../third_party/lib\"",
|
||||
);
|
||||
PRODUCT_NAME = ipjsystest;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -328,6 +335,7 @@
|
|||
COPY_PHASE_STRIP = YES;
|
||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||
GCC_PREFIX_HEADER = ipjsystest_Prefix.pch;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "PJ_AUTOCONF=1";
|
||||
INFOPLIST_FILE = "ipjsystest-Info.plist";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -339,6 +347,7 @@
|
|||
"\"$(SRCROOT)/../../../third_party/lib\"",
|
||||
);
|
||||
PRODUCT_NAME = ipjsystest;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -269,6 +269,8 @@ static void usage(void)
|
|||
puts (" May be specified multiple times");
|
||||
puts (" --stun-srv=FORMAT Set STUN server host or domain. This option may be");
|
||||
puts (" specified more than once. FORMAT is hostdom[:PORT]");
|
||||
|
||||
#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
|
||||
puts ("");
|
||||
puts ("TLS Options:");
|
||||
puts (" --use-tls Enable TLS transport (default=no)");
|
||||
|
@ -280,6 +282,9 @@ static void usage(void)
|
|||
puts (" --tls-verify-client Verify client's certificate (default=no)");
|
||||
puts (" --tls-neg-timeout Specify TLS negotiation timeout (default=no)");
|
||||
puts (" --tls-srv-name Specify TLS server name for multihosting server");
|
||||
puts (" --tls-cipher Specify prefered TLS cipher (optional).");
|
||||
puts (" May be specified multiple times");
|
||||
#endif
|
||||
|
||||
puts ("");
|
||||
puts ("Audio Options:");
|
||||
|
@ -560,7 +565,7 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
OPT_NOREFERSUB, OPT_ACCEPT_REDIRECT,
|
||||
OPT_USE_TLS, OPT_TLS_CA_FILE, OPT_TLS_CERT_FILE, OPT_TLS_PRIV_FILE,
|
||||
OPT_TLS_PASSWORD, OPT_TLS_VERIFY_SERVER, OPT_TLS_VERIFY_CLIENT,
|
||||
OPT_TLS_NEG_TIMEOUT, OPT_TLS_SRV_NAME,
|
||||
OPT_TLS_NEG_TIMEOUT, OPT_TLS_CIPHER,
|
||||
OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV,
|
||||
OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE,
|
||||
OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS,
|
||||
|
@ -662,6 +667,7 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
{ "max-calls", 1, 0, OPT_MAX_CALLS},
|
||||
{ "duration", 1, 0, OPT_DURATION},
|
||||
{ "thread-cnt", 1, 0, OPT_THREAD_CNT},
|
||||
#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
|
||||
{ "use-tls", 0, 0, OPT_USE_TLS},
|
||||
{ "tls-ca-file",1, 0, OPT_TLS_CA_FILE},
|
||||
{ "tls-cert-file",1,0, OPT_TLS_CERT_FILE},
|
||||
|
@ -670,7 +676,8 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
{ "tls-verify-server", 0, 0, OPT_TLS_VERIFY_SERVER},
|
||||
{ "tls-verify-client", 0, 0, OPT_TLS_VERIFY_CLIENT},
|
||||
{ "tls-neg-timeout", 1, 0, OPT_TLS_NEG_TIMEOUT},
|
||||
{ "tls-srv-name", 1, 0, OPT_TLS_SRV_NAME},
|
||||
{ "tls-cipher", 1, 0, OPT_TLS_CIPHER},
|
||||
#endif
|
||||
{ "capture-dev", 1, 0, OPT_CAPTURE_DEV},
|
||||
{ "playback-dev", 1, 0, OPT_PLAYBACK_DEV},
|
||||
{ "capture-lat", 1, 0, OPT_CAPTURE_LAT},
|
||||
|
@ -1345,28 +1352,17 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
}
|
||||
break;
|
||||
|
||||
#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
|
||||
case OPT_USE_TLS:
|
||||
cfg->use_tls = PJ_TRUE;
|
||||
#if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0
|
||||
PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured"));
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_TLS_CA_FILE:
|
||||
cfg->udp_cfg.tls_setting.ca_list_file = pj_str(pj_optarg);
|
||||
#if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0
|
||||
PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured"));
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_TLS_CERT_FILE:
|
||||
cfg->udp_cfg.tls_setting.cert_file = pj_str(pj_optarg);
|
||||
#if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0
|
||||
PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured"));
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_TLS_PRIV_FILE:
|
||||
|
@ -1375,10 +1371,6 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
|
||||
case OPT_TLS_PASSWORD:
|
||||
cfg->udp_cfg.tls_setting.password = pj_str(pj_optarg);
|
||||
#if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0
|
||||
PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured"));
|
||||
return -1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OPT_TLS_VERIFY_SERVER:
|
||||
|
@ -1394,9 +1386,39 @@ static pj_status_t parse_args(int argc, char *argv[],
|
|||
cfg->udp_cfg.tls_setting.timeout.sec = atoi(pj_optarg);
|
||||
break;
|
||||
|
||||
case OPT_TLS_SRV_NAME:
|
||||
cfg->udp_cfg.tls_setting.server_name = pj_str(pj_optarg);
|
||||
break;
|
||||
case OPT_TLS_CIPHER:
|
||||
{
|
||||
pj_ssl_cipher cipher;
|
||||
|
||||
if (pj_ansi_strnicmp(pj_optarg, "0x", 2) == 0) {
|
||||
pj_str_t cipher_st = pj_str(pj_optarg + 2);
|
||||
cipher = pj_strtoul2(&cipher_st, NULL, 16);
|
||||
} else {
|
||||
cipher = atoi(pj_optarg);
|
||||
}
|
||||
|
||||
if (pj_ssl_cipher_is_supported(cipher)) {
|
||||
static pj_ssl_cipher tls_ciphers[128];
|
||||
|
||||
tls_ciphers[cfg->udp_cfg.tls_setting.ciphers_num++] = cipher;
|
||||
cfg->udp_cfg.tls_setting.ciphers = tls_ciphers;
|
||||
} else {
|
||||
pj_ssl_cipher ciphers[128];
|
||||
unsigned j, ciphers_cnt;
|
||||
|
||||
ciphers_cnt = PJ_ARRAY_SIZE(ciphers);
|
||||
pj_ssl_cipher_get_availables(ciphers, &ciphers_cnt);
|
||||
|
||||
PJ_LOG(1,(THIS_FILE, "Cipher \"%s\" is not supported by "
|
||||
"TLS/SSL backend.", pj_optarg));
|
||||
printf("Available TLS/SSL ciphers (%d):\n", ciphers_cnt);
|
||||
for (j=0; j<ciphers_cnt; ++j)
|
||||
printf("- 0x%06X: %s\n", ciphers[j], pj_ssl_cipher_name(ciphers[j]));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* PJSIP_HAS_TLS_TRANSPORT */
|
||||
|
||||
case OPT_CAPTURE_DEV:
|
||||
cfg->vid.vcapture_dev = atoi(pj_optarg);
|
||||
|
@ -1834,6 +1856,7 @@ static int write_settings(const struct app_config *config,
|
|||
pj_strcat2(&cfg, line);
|
||||
}
|
||||
|
||||
#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0)
|
||||
/* TLS */
|
||||
if (config->use_tls)
|
||||
pj_strcat2(&cfg, "--use-tls\n");
|
||||
|
@ -1863,13 +1886,6 @@ static int write_settings(const struct app_config *config,
|
|||
pj_strcat2(&cfg, line);
|
||||
}
|
||||
|
||||
if (config->udp_cfg.tls_setting.server_name.slen) {
|
||||
pj_ansi_sprintf(line, "--tls-srv-name %.*s\n",
|
||||
(int)config->udp_cfg.tls_setting.server_name.slen,
|
||||
config->udp_cfg.tls_setting.server_name.ptr);
|
||||
pj_strcat2(&cfg, line);
|
||||
}
|
||||
|
||||
if (config->udp_cfg.tls_setting.verify_server)
|
||||
pj_strcat2(&cfg, "--tls-verify-server\n");
|
||||
|
||||
|
@ -1882,6 +1898,14 @@ static int write_settings(const struct app_config *config,
|
|||
pj_strcat2(&cfg, line);
|
||||
}
|
||||
|
||||
for (i=0; i<config->udp_cfg.tls_setting.ciphers_num; ++i) {
|
||||
pj_ansi_sprintf(line, "--tls-cipher 0x%06X # %s\n",
|
||||
config->udp_cfg.tls_setting.ciphers[i],
|
||||
pj_ssl_cipher_name(config->udp_cfg.tls_setting.ciphers[i]));
|
||||
pj_strcat2(&cfg, line);
|
||||
}
|
||||
#endif
|
||||
|
||||
pj_strcat2(&cfg, "\n#\n# Media settings:\n#\n");
|
||||
|
||||
/* Video & extra audio */
|
||||
|
@ -3211,6 +3235,11 @@ static void on_transport_state(pjsip_transport *tp,
|
|||
const char *verif_msgs[32];
|
||||
unsigned verif_msg_cnt;
|
||||
|
||||
/* Dump server TLS cipher */
|
||||
PJ_LOG(4,(THIS_FILE, "TLS cipher used: 0x%06X/%s",
|
||||
ssl_sock_info->cipher,
|
||||
pj_ssl_cipher_name(ssl_sock_info->cipher) ));
|
||||
|
||||
/* Dump server TLS certificate */
|
||||
pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, " ",
|
||||
buf, sizeof(buf));
|
||||
|
|
|
@ -2347,7 +2347,7 @@ static PyObject *py_pjsua_conf_get_port_info(PyObject *pSelf, PyObject *pArgs)
|
|||
ret = (PyObj_pjsua_conf_port_info *)
|
||||
conf_port_info_new(&PyTyp_pjsua_conf_port_info, NULL, NULL);
|
||||
ret->bits_per_sample = info.bits_per_sample;
|
||||
ret->channel_count = info.bits_per_sample;
|
||||
ret->channel_count = info.channel_count;
|
||||
ret->clock_rate = info.clock_rate;
|
||||
ret->name = PyString_FromPJ(&info.name);
|
||||
ret->samples_per_frame = info.samples_per_frame;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
from distutils.core import setup, Extension
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
|
||||
# find pjsip version
|
||||
pj_version=""
|
||||
|
@ -58,9 +59,12 @@ for line in f:
|
|||
f.close()
|
||||
|
||||
# Mac OS X depedencies
|
||||
if sys.platform == 'darwin':
|
||||
if platform.system() == 'Darwin':
|
||||
extra_link_args = ["-framework", "CoreFoundation",
|
||||
"-framework", "AudioToolbox"]
|
||||
# OS X Lion support
|
||||
if platform.mac_ver()[0].startswith("10.7"):
|
||||
extra_link_args += ["-framework", "AudioUnit"]
|
||||
else:
|
||||
extra_link_args = []
|
||||
|
||||
|
|
|
@ -58,9 +58,6 @@
|
|||
#define ENABLE_SIP_TCP 0 // experimental
|
||||
#define ENABLE_SIP_TLS 0 // experimental
|
||||
|
||||
#define TLS_SRV_NAME "pjsip.org" // TLS servername (required for
|
||||
// TLS transport)
|
||||
|
||||
//
|
||||
// Configure nameserver if DNS SRV is to be used with both SIP
|
||||
// or STUN (for STUN see other settings below)
|
||||
|
@ -490,7 +487,6 @@ static pj_status_t app_startup()
|
|||
tcfg.qos_params.dscp_val = SIP_QOS_DSCP;
|
||||
tcfg.tls_setting.qos_params = tcfg.qos_params;
|
||||
}
|
||||
tcfg.tls_setting.server_name = pj_str(TLS_SRV_NAME);
|
||||
status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid);
|
||||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Error creating TLS transport", status);
|
||||
|
|
|
@ -81,6 +81,13 @@ typedef struct pjsip_cfg_t
|
|||
* Disable rport in request.
|
||||
*/
|
||||
pj_bool_t disable_rport;
|
||||
|
||||
/**
|
||||
* Disable automatic switching from UDP to TCP if outgoing request
|
||||
* is greater than 1300 bytes. See PJSIP_DONT_SWITCH_TO_TCP.
|
||||
*/
|
||||
pj_bool_t disable_tcp_switch;
|
||||
|
||||
} endpt;
|
||||
|
||||
/** Transaction layer settings. */
|
||||
|
@ -251,6 +258,9 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
|
|||
* Disable the behavior of automatic switching to TCP whenever UDP packet
|
||||
* size exceeds the threshold defined in PJSIP_UDP_SIZE_THRESHOLD.
|
||||
*
|
||||
* This option can also be controlled at run-time by the \a disable_tcp_switch
|
||||
* setting in pjsip_cfg_t.
|
||||
*
|
||||
* Default is 0 (no).
|
||||
*/
|
||||
#ifndef PJSIP_DONT_SWITCH_TO_TCP
|
||||
|
@ -420,10 +430,10 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
|
|||
* Idle timeout interval to be applied to transports with no usage
|
||||
* before the transport is destroyed. Value is in seconds.
|
||||
*
|
||||
* Default: 600
|
||||
* Default: 30
|
||||
*/
|
||||
#ifndef PJSIP_TRANSPORT_IDLE_TIME
|
||||
# define PJSIP_TRANSPORT_IDLE_TIME 600
|
||||
# define PJSIP_TRANSPORT_IDLE_TIME 30
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -62,6 +62,13 @@ PJ_BEGIN_DECL
|
|||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Type of callback to register to pjsip_endpt_atexit().
|
||||
*/
|
||||
typedef void (*pjsip_endpt_exit_callback)(pjsip_endpoint *endpt);
|
||||
|
||||
|
||||
/**
|
||||
* Create an instance of SIP endpoint from the specified pool factory.
|
||||
* The pool factory reference then will be kept by the endpoint, so that
|
||||
|
@ -511,6 +518,21 @@ PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_request_headers(pjsip_endpoint *e);
|
|||
PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail );
|
||||
|
||||
|
||||
/**
|
||||
* Register cleanup function to be called by SIP endpoint when
|
||||
* #pjsip_endpt_destroy() is called. Note that application should not
|
||||
* use or access any endpoint resource (such as pool, ioqueue, timer heap)
|
||||
* from within the callback as such resource may have been released when
|
||||
* the callback function is invoked.
|
||||
*
|
||||
* @param endpt The SIP endpoint.
|
||||
* @param func The function to be registered.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjsip_endpt_atexit(pjsip_endpoint *endpt,
|
||||
pjsip_endpt_exit_callback func);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
@ -573,6 +573,13 @@ struct pjsip_tx_data
|
|||
*/
|
||||
pjsip_tpselector tp_sel;
|
||||
|
||||
/**
|
||||
* Special flag to indicate that this transmit data is a request that has
|
||||
* been updated with proper authentication response and is ready to be
|
||||
* sent for retry.
|
||||
*/
|
||||
pj_bool_t auth_retry;
|
||||
|
||||
/**
|
||||
* Arbitrary data attached by PJSIP modules.
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <pjsip/sip_transport.h>
|
||||
#include <pj/pool.h>
|
||||
#include <pj/ssl_sock.h>
|
||||
#include <pj/string.h>
|
||||
#include <pj/sock_qos.h>
|
||||
|
@ -106,20 +107,19 @@ typedef struct pjsip_tls_setting
|
|||
int method;
|
||||
|
||||
/**
|
||||
* TLS cipher list string in OpenSSL format. If empty, then default
|
||||
* cipher list of the backend will be used.
|
||||
* Number of ciphers contained in the specified cipher preference.
|
||||
* If this is set to zero, then default cipher list of the backend
|
||||
* will be used.
|
||||
*
|
||||
* Default: 0 (zero).
|
||||
*/
|
||||
pj_str_t ciphers;
|
||||
unsigned ciphers_num;
|
||||
|
||||
/**
|
||||
* Optionally specify the server name instance to be contacted when
|
||||
* making outgoing TLS connection. This setting is useful when the
|
||||
* server is hosting multiple domains for the same TLS listening
|
||||
* socket.
|
||||
*
|
||||
* Default: empty.
|
||||
* Ciphers and order preference. The #pj_ssl_cipher_get_availables()
|
||||
* can be used to check the available ciphers supported by backend.
|
||||
*/
|
||||
pj_str_t server_name;
|
||||
pj_ssl_cipher *ciphers;
|
||||
|
||||
/**
|
||||
* Specifies TLS transport behavior on the server TLS certificate
|
||||
|
@ -246,7 +246,13 @@ PJ_INLINE(void) pjsip_tls_setting_copy(pj_pool_t *pool,
|
|||
pj_strdup_with_null(pool, &dst->cert_file, &src->cert_file);
|
||||
pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file);
|
||||
pj_strdup_with_null(pool, &dst->password, &src->password);
|
||||
pj_strdup_with_null(pool, &dst->ciphers, &src->ciphers);
|
||||
if (src->ciphers_num) {
|
||||
unsigned i;
|
||||
dst->ciphers = (pj_ssl_cipher*) pj_pool_calloc(pool, src->ciphers_num,
|
||||
sizeof(pj_ssl_cipher));
|
||||
for (i=0; i<src->ciphers_num; ++i)
|
||||
dst->ciphers[i] = src->ciphers[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -4886,7 +4886,7 @@ PJ_DECL(pj_status_t) pjsua_im_typing(pjsua_acc_id acc_id,
|
|||
{
|
||||
pjsua_player_id player_id;
|
||||
|
||||
status = pjsua_player_create("mysong.wav", 0, NULL, &player_id);
|
||||
status = pjsua_player_create("mysong.wav", 0, &player_id);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
|
|
|
@ -212,7 +212,16 @@ void inv_set_state(pjsip_inv_session *inv, pjsip_inv_state state,
|
|||
* otherwise disconnect the session.
|
||||
*/
|
||||
if (state == PJSIP_INV_STATE_CONFIRMED) {
|
||||
if (pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE) {
|
||||
struct tsx_inv_data *tsx_inv_data = NULL;
|
||||
|
||||
if (inv->invite_tsx) {
|
||||
tsx_inv_data = (struct tsx_inv_data*)
|
||||
inv->invite_tsx->mod_data[mod_inv.mod.id];
|
||||
}
|
||||
|
||||
if (pjmedia_sdp_neg_get_state(inv->neg)!=PJMEDIA_SDP_NEG_STATE_DONE &&
|
||||
(tsx_inv_data && !tsx_inv_data->sdp_done) )
|
||||
{
|
||||
pjsip_tx_data *bye;
|
||||
|
||||
PJ_LOG(4,(inv->obj_name, "SDP offer/answer incomplete, ending the "
|
||||
|
@ -3952,6 +3961,32 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
|
|||
status = pjsip_dlg_send_response(dlg, tsx, tdata);
|
||||
if (status != PJ_SUCCESS) return;
|
||||
|
||||
} else if (tsx->role == PJSIP_ROLE_UAS &&
|
||||
tsx->state == PJSIP_TSX_STATE_TRYING &&
|
||||
pjsip_method_cmp(&tsx->method, &pjsip_invite_method)==0)
|
||||
{
|
||||
pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
|
||||
pjsip_tx_data *tdata;
|
||||
pj_status_t status;
|
||||
|
||||
/* See https://trac.pjsip.org/repos/ticket/1455
|
||||
* Handle incoming re-INVITE before current INVITE is confirmed.
|
||||
* According to RFC 5407:
|
||||
* - answer with 200 if we don't have pending offer-answer
|
||||
* - answer with 491 if we *have* pending offer-answer
|
||||
*
|
||||
* But unfortunately accepting the re-INVITE would mean we have
|
||||
* two outstanding INVITEs, and we don't support that because
|
||||
* we will get confused when we handle the ACK.
|
||||
*/
|
||||
status = pjsip_dlg_create_response(inv->dlg, rdata,
|
||||
PJSIP_SC_REQUEST_PENDING,
|
||||
NULL, &tdata);
|
||||
if (status != PJ_SUCCESS)
|
||||
return;
|
||||
pjsip_timer_update_resp(inv, tdata);
|
||||
status = pjsip_dlg_send_response(dlg, tsx, tdata);
|
||||
|
||||
} else if (tsx->role == PJSIP_ROLE_UAS &&
|
||||
tsx->state == PJSIP_TSX_STATE_TRYING &&
|
||||
pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0)
|
||||
|
@ -3986,6 +4021,7 @@ static void inv_on_state_connecting( pjsip_inv_session *inv, pjsip_event *e)
|
|||
|
||||
/* Generic handling for UAC tsx completion */
|
||||
handle_uac_tsx_response(inv, e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -162,8 +162,10 @@ static pjsip_hdr *parse_hdr_replaces(pjsip_parse_ctx *ctx)
|
|||
|
||||
|
||||
/* Deinitialize Replaces */
|
||||
static void pjsip_replaces_deinit_module(void)
|
||||
static void pjsip_replaces_deinit_module(pjsip_endpoint *endpt)
|
||||
{
|
||||
PJ_TODO(provide_initialized_flag_for_each_endpoint);
|
||||
PJ_UNUSED_ARG(endpt);
|
||||
is_initialized = PJ_FALSE;
|
||||
}
|
||||
|
||||
|
@ -191,7 +193,8 @@ PJ_DEF(pj_status_t) pjsip_replaces_init_module(pjsip_endpoint *endpt)
|
|||
1, &STR_REPLACES);
|
||||
|
||||
/* Register deinit module to be executed when PJLIB shutdown */
|
||||
if (pj_atexit(&pjsip_replaces_deinit_module) != PJ_SUCCESS) {
|
||||
if (pjsip_endpt_atexit(endpt, &pjsip_replaces_deinit_module) != PJ_SUCCESS)
|
||||
{
|
||||
/* Failure to register this function may cause this module won't
|
||||
* work properly when the stack is restarted (without quitting
|
||||
* application).
|
||||
|
|
|
@ -495,8 +495,10 @@ static void stop_timer(pjsip_inv_session *inv)
|
|||
}
|
||||
|
||||
/* Deinitialize Session Timers */
|
||||
static void pjsip_timer_deinit_module(void)
|
||||
static void pjsip_timer_deinit_module(pjsip_endpoint *endpt)
|
||||
{
|
||||
PJ_TODO(provide_initialized_flag_for_each_endpoint);
|
||||
PJ_UNUSED_ARG(endpt);
|
||||
is_initialized = PJ_FALSE;
|
||||
}
|
||||
|
||||
|
@ -531,7 +533,7 @@ PJ_DEF(pj_status_t) pjsip_timer_init_module(pjsip_endpoint *endpt)
|
|||
return status;
|
||||
|
||||
/* Register deinit module to be executed when PJLIB shutdown */
|
||||
if (pj_atexit(&pjsip_timer_deinit_module) != PJ_SUCCESS) {
|
||||
if (pjsip_endpt_atexit(endpt, &pjsip_timer_deinit_module) != PJ_SUCCESS) {
|
||||
/* Failure to register this function may cause this module won't
|
||||
* work properly when the stack is restarted (without quitting
|
||||
* application).
|
||||
|
|
|
@ -152,22 +152,39 @@ PJ_DEF(pj_status_t) pjsip_auth_create_aka_response(
|
|||
&auth->uri, &chal->realm, &aka_cred, method);
|
||||
|
||||
} else if (aka_version == 2) {
|
||||
|
||||
/*
|
||||
* For AKAv2, password is base64 encoded [1] parameters:
|
||||
* PRF(RES||IK||CK,"http-digest-akav2-password")
|
||||
*
|
||||
* The pseudo-random function (PRF) is HMAC-MD5 in this case.
|
||||
*
|
||||
* Hmmm.. but those above doesn't seem to work, and this below does!
|
||||
*/
|
||||
aka_cred.data.slen = PJSIP_AKA_RESLEN + PJSIP_AKA_IKLEN +
|
||||
PJSIP_AKA_CKLEN;
|
||||
aka_cred.data.ptr = pj_pool_alloc(pool, aka_cred.data.slen);
|
||||
|
||||
pj_memcpy(aka_cred.data.ptr + 0, res, PJSIP_AKA_RESLEN);
|
||||
pj_memcpy(aka_cred.data.ptr + PJSIP_AKA_RESLEN, ik, PJSIP_AKA_IKLEN);
|
||||
pj_memcpy(aka_cred.data.ptr + PJSIP_AKA_RESLEN + PJSIP_AKA_IKLEN,
|
||||
ck, PJSIP_AKA_CKLEN);
|
||||
|
||||
pj_str_t resikck;
|
||||
const pj_str_t AKAv2_Passwd = { "http-digest-akav2-password", 26 };
|
||||
pj_uint8_t hmac_digest[16];
|
||||
char tmp_buf[48];
|
||||
int hmac64_len;
|
||||
|
||||
resikck.slen = PJSIP_AKA_RESLEN + PJSIP_AKA_IKLEN + PJSIP_AKA_CKLEN;
|
||||
pj_assert(resikck.slen <= PJ_ARRAY_SIZE(tmp_buf));
|
||||
resikck.ptr = tmp_buf;
|
||||
pj_memcpy(resikck.ptr + 0, res, PJSIP_AKA_RESLEN);
|
||||
pj_memcpy(resikck.ptr + PJSIP_AKA_RESLEN, ik, PJSIP_AKA_IKLEN);
|
||||
pj_memcpy(resikck.ptr + PJSIP_AKA_RESLEN + PJSIP_AKA_IKLEN,
|
||||
ck, PJSIP_AKA_CKLEN);
|
||||
|
||||
pj_hmac_md5((const pj_uint8_t*)AKAv2_Passwd.ptr, AKAv2_Passwd.slen,
|
||||
(const pj_uint8_t*)resikck.ptr, resikck.slen,
|
||||
hmac_digest);
|
||||
|
||||
aka_cred.data.slen = hmac64_len =
|
||||
PJ_BASE256_TO_BASE64_LEN(PJ_ARRAY_SIZE(hmac_digest));
|
||||
pj_assert(aka_cred.data.slen+1 <= PJ_ARRAY_SIZE(tmp_buf));
|
||||
aka_cred.data.ptr = tmp_buf;
|
||||
pj_base64_encode(hmac_digest, PJ_ARRAY_SIZE(hmac_digest),
|
||||
aka_cred.data.ptr, &len);
|
||||
aka_cred.data.slen = hmac64_len;
|
||||
|
||||
pjsip_auth_create_digest(&auth->response, &chal->nonce,
|
||||
&auth->nc, &auth->cnonce, &auth->qop,
|
||||
|
|
|
@ -1103,7 +1103,8 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess,
|
|||
PJSIP_EINVALIDSTATUS);
|
||||
|
||||
tdata = old_request;
|
||||
|
||||
tdata->auth_retry = PJ_FALSE;
|
||||
|
||||
/*
|
||||
* Respond to each authentication challenge.
|
||||
*/
|
||||
|
@ -1174,6 +1175,9 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reinit_req( pjsip_auth_clt_sess *sess,
|
|||
/* Must invalidate the message! */
|
||||
pjsip_tx_data_invalidate_msg(tdata);
|
||||
|
||||
/* Retrying.. */
|
||||
tdata->auth_retry = PJ_TRUE;
|
||||
|
||||
/* Increment reference counter. */
|
||||
pjsip_tx_data_add_ref(tdata);
|
||||
|
||||
|
|
|
@ -25,7 +25,9 @@ pjsip_cfg_t pjsip_sip_cfg_var =
|
|||
{
|
||||
/* Global settings */
|
||||
{
|
||||
PJSIP_ALLOW_PORT_IN_FROMTO_HDR
|
||||
PJSIP_ALLOW_PORT_IN_FROMTO_HDR,
|
||||
0,
|
||||
PJSIP_DONT_SWITCH_TO_TCP
|
||||
},
|
||||
|
||||
/* Transaction settings */
|
||||
|
|
|
@ -40,6 +40,15 @@
|
|||
|
||||
#define MAX_METHODS 32
|
||||
|
||||
|
||||
/* List of SIP endpoint exit callback. */
|
||||
typedef struct exit_cb
|
||||
{
|
||||
PJ_DECL_LIST_MEMBER (struct exit_cb);
|
||||
pjsip_endpt_exit_callback func;
|
||||
} exit_cb;
|
||||
|
||||
|
||||
/**
|
||||
* The SIP endpoint.
|
||||
*/
|
||||
|
@ -86,6 +95,9 @@ struct pjsip_endpoint
|
|||
|
||||
/** Additional request headers. */
|
||||
pjsip_hdr req_hdr;
|
||||
|
||||
/** List of exit callback. */
|
||||
exit_cb exit_cb_list;
|
||||
};
|
||||
|
||||
|
||||
|
@ -445,6 +457,9 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
|
|||
/* Init modules list. */
|
||||
pj_list_init(&endpt->module_list);
|
||||
|
||||
/* Initialize exit callback list. */
|
||||
pj_list_init(&endpt->exit_cb_list);
|
||||
|
||||
/* Create R/W mutex for module manipulation. */
|
||||
status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex);
|
||||
if (status != PJ_SUCCESS)
|
||||
|
@ -559,6 +574,7 @@ on_error:
|
|||
PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
|
||||
{
|
||||
pjsip_module *mod;
|
||||
exit_cb *ecb;
|
||||
|
||||
PJ_LOG(5, (THIS_FILE, "Destroying endpoing instance.."));
|
||||
|
||||
|
@ -592,6 +608,13 @@ PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
|
|||
/* Destroy timer heap */
|
||||
pj_timer_heap_destroy(endpt->timer_heap);
|
||||
|
||||
/* Call all registered exit callbacks */
|
||||
ecb = endpt->exit_cb_list.next;
|
||||
while (ecb != &endpt->exit_cb_list) {
|
||||
(*ecb->func)(endpt);
|
||||
ecb = ecb->next;
|
||||
}
|
||||
|
||||
/* Delete endpoint mutex. */
|
||||
pj_mutex_destroy(endpt->mutex);
|
||||
|
||||
|
@ -1182,3 +1205,20 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pjsip_endpt_atexit( pjsip_endpoint *endpt,
|
||||
pjsip_endpt_exit_callback func)
|
||||
{
|
||||
exit_cb *new_cb;
|
||||
|
||||
PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
|
||||
|
||||
new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
|
||||
new_cb->func = func;
|
||||
|
||||
pj_mutex_lock(endpt->mutex);
|
||||
pj_list_push_back(&endpt->exit_cb_list, new_cb);
|
||||
pj_mutex_unlock(endpt->mutex);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -714,23 +714,17 @@ static pj_status_t mod_tsx_layer_stop(void)
|
|||
}
|
||||
|
||||
pj_mutex_unlock(mod_tsx_layer.mutex);
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "Stopped transaction layer module"));
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* This module callback is called when module is being unloaded by
|
||||
* endpoint.
|
||||
*/
|
||||
static pj_status_t mod_tsx_layer_unload(void)
|
||||
/* Destroy this module */
|
||||
static void tsx_layer_destroy(pjsip_endpoint *endpt)
|
||||
{
|
||||
/* Only self destroy when there's no transaction in the table.
|
||||
* Transaction may refuse to destroy when it has pending
|
||||
* transmission. If we destroy the module now, application will
|
||||
* crash when the pending transaction finally got error response
|
||||
* from transport and when it tries to unregister itself.
|
||||
*/
|
||||
if (pj_hash_count(mod_tsx_layer.htable) != 0)
|
||||
return PJ_EBUSY;
|
||||
PJ_UNUSED_ARG(endpt);
|
||||
|
||||
/* Destroy mutex. */
|
||||
pj_mutex_destroy(mod_tsx_layer.mutex);
|
||||
|
@ -745,6 +739,31 @@ static pj_status_t mod_tsx_layer_unload(void)
|
|||
mod_tsx_layer.endpt = NULL;
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "Transaction layer module destroyed"));
|
||||
}
|
||||
|
||||
|
||||
/* This module callback is called when module is being unloaded by
|
||||
* endpoint.
|
||||
*/
|
||||
static pj_status_t mod_tsx_layer_unload(void)
|
||||
{
|
||||
/* Only self destroy when there's no transaction in the table.
|
||||
* Transaction may refuse to destroy when it has pending
|
||||
* transmission. If we destroy the module now, application will
|
||||
* crash when the pending transaction finally got error response
|
||||
* from transport and when it tries to unregister itself.
|
||||
*/
|
||||
if (pj_hash_count(mod_tsx_layer.htable) != 0) {
|
||||
if (pjsip_endpt_atexit(mod_tsx_layer.endpt, &tsx_layer_destroy) !=
|
||||
PJ_SUCCESS)
|
||||
{
|
||||
PJ_LOG(3,(THIS_FILE, "Failed to register transaction layer "
|
||||
"module destroy."));
|
||||
}
|
||||
return PJ_EBUSY;
|
||||
}
|
||||
|
||||
tsx_layer_destroy(mod_tsx_layer.endpt);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -3239,7 +3258,10 @@ static pj_status_t tsx_on_state_destroyed(pjsip_transaction *tsx,
|
|||
{
|
||||
PJ_UNUSED_ARG(tsx);
|
||||
PJ_UNUSED_ARG(event);
|
||||
pj_assert(!"Not expecting any events!!");
|
||||
return PJ_EBUG;
|
||||
|
||||
// See https://trac.pjsip.org/repos/ticket/1432
|
||||
//pj_assert(!"Not expecting any events!!");
|
||||
|
||||
return PJ_EIGNORED;
|
||||
}
|
||||
|
||||
|
|
|
@ -293,6 +293,8 @@ PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
|
|||
ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN;
|
||||
if (ssock_param.read_buffer_size < PJSIP_MAX_PKT_LEN)
|
||||
ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN;
|
||||
ssock_param.ciphers_num = listener->tls_setting.ciphers_num;
|
||||
ssock_param.ciphers = listener->tls_setting.ciphers;
|
||||
ssock_param.qos_type = listener->tls_setting.qos_type;
|
||||
ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error;
|
||||
pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params,
|
||||
|
@ -862,7 +864,6 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
|
|||
ssock_param.cb.on_data_sent = &on_data_sent;
|
||||
ssock_param.async_cnt = 1;
|
||||
ssock_param.ioqueue = pjsip_endpt_get_ioqueue(listener->endpt);
|
||||
PJ_TODO(synchronize_tls_cipher_type_with_ssl_sock_cipher_type);
|
||||
ssock_param.server_name = remote_name;
|
||||
ssock_param.timeout = listener->tls_setting.timeout;
|
||||
ssock_param.user_data = NULL; /* pending, must be set later */
|
||||
|
@ -872,6 +873,8 @@ static pj_status_t lis_create_transport(pjsip_tpfactory *factory,
|
|||
ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN;
|
||||
if (ssock_param.read_buffer_size < PJSIP_MAX_PKT_LEN)
|
||||
ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN;
|
||||
ssock_param.ciphers_num = listener->tls_setting.ciphers_num;
|
||||
ssock_param.ciphers = listener->tls_setting.ciphers;
|
||||
ssock_param.qos_type = listener->tls_setting.qos_type;
|
||||
ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error;
|
||||
pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params,
|
||||
|
|
|
@ -1248,14 +1248,14 @@ stateless_send_resolver_callback( pj_status_t status,
|
|||
}
|
||||
pj_assert(tdata->dest_info.addr.count != 0);
|
||||
|
||||
#if !defined(PJSIP_DONT_SWITCH_TO_TCP) || PJSIP_DONT_SWITCH_TO_TCP==0
|
||||
/* RFC 3261 section 18.1.1:
|
||||
* If a request is within 200 bytes of the path MTU, or if it is larger
|
||||
* than 1300 bytes and the path MTU is unknown, the request MUST be sent
|
||||
* using an RFC 2914 [43] congestion controlled transport protocol, such
|
||||
* as TCP.
|
||||
*/
|
||||
if (tdata->msg->type == PJSIP_REQUEST_MSG &&
|
||||
if (pjsip_cfg()->endpt.disable_tcp_switch==0 &&
|
||||
tdata->msg->type == PJSIP_REQUEST_MSG &&
|
||||
tdata->dest_info.addr.count > 0 &&
|
||||
tdata->dest_info.addr.entry[0].type == PJSIP_TRANSPORT_UDP)
|
||||
{
|
||||
|
@ -1297,7 +1297,6 @@ stateless_send_resolver_callback( pj_status_t status,
|
|||
tdata->dest_info.addr.count = count * 2;
|
||||
}
|
||||
}
|
||||
#endif /* !PJSIP_DONT_SWITCH_TO_TCP */
|
||||
|
||||
/* Process the addresses. */
|
||||
stateless_send_transport_cb( stateless_data, tdata, -PJ_EPENDING);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define NULL_SND_DEV_ID -99
|
||||
|
||||
/*****************************************************************************
|
||||
/*
|
||||
*
|
||||
* Prototypes
|
||||
*/
|
||||
/* Open sound dev */
|
||||
|
@ -43,7 +43,7 @@ static pj_status_t create_aud_param(pjmedia_aud_param *param,
|
|||
unsigned bits_per_sample);
|
||||
|
||||
/*****************************************************************************
|
||||
/*
|
||||
*
|
||||
* Call API that are closely tied to PJMEDIA
|
||||
*/
|
||||
/*
|
||||
|
@ -223,7 +223,7 @@ on_return:
|
|||
|
||||
|
||||
/*****************************************************************************
|
||||
/*
|
||||
*
|
||||
* Audio media with PJMEDIA backend
|
||||
*/
|
||||
|
||||
|
@ -806,13 +806,13 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
|
|||
source, sink));
|
||||
pj_log_push_indent();
|
||||
|
||||
/* If sound device idle timer is active, cancel it first. */
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* If sound device idle timer is active, cancel it first. */
|
||||
if (pjsua_var.snd_idle_timer.id) {
|
||||
pjsip_endpt_cancel_timer(pjsua_var.endpt, &pjsua_var.snd_idle_timer);
|
||||
pjsua_var.snd_idle_timer.id = PJ_FALSE;
|
||||
}
|
||||
PJSUA_UNLOCK();
|
||||
|
||||
|
||||
/* For audio switchboard (i.e. APS-Direct):
|
||||
|
@ -910,8 +910,6 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
|
|||
if (pjsua_var.snd_port==NULL && pjsua_var.null_snd==NULL &&
|
||||
!pjsua_var.no_snd)
|
||||
{
|
||||
pj_status_t status;
|
||||
|
||||
status = pjsua_set_snd_dev(pjsua_var.cap_dev, pjsua_var.play_dev);
|
||||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Error opening sound device", status);
|
||||
|
@ -926,9 +924,13 @@ PJ_DEF(pj_status_t) pjsua_conf_connect( pjsua_conf_port_id source,
|
|||
}
|
||||
}
|
||||
|
||||
status = pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);
|
||||
|
||||
on_return:
|
||||
PJSUA_UNLOCK();
|
||||
|
||||
if (status == PJ_SUCCESS) {
|
||||
status = pjmedia_conf_connect_port(pjsua_var.mconf, source, sink, 0);
|
||||
}
|
||||
|
||||
pj_log_pop_indent();
|
||||
return status;
|
||||
}
|
||||
|
@ -1851,8 +1853,11 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
|
|||
capture_dev, playback_dev));
|
||||
pj_log_push_indent();
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* Null-sound */
|
||||
if (capture_dev==NULL_SND_DEV_ID && playback_dev==NULL_SND_DEV_ID) {
|
||||
PJSUA_UNLOCK();
|
||||
status = pjsua_set_null_snd_dev();
|
||||
pj_log_pop_indent();
|
||||
return status;
|
||||
|
@ -1903,10 +1908,12 @@ PJ_DEF(pj_status_t) pjsua_set_snd_dev( int capture_dev,
|
|||
pjsua_var.no_snd = PJ_FALSE;
|
||||
pjsua_var.snd_is_on = PJ_TRUE;
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
return PJ_SUCCESS;
|
||||
|
||||
on_error:
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
return status;
|
||||
}
|
||||
|
@ -1920,6 +1927,8 @@ on_error:
|
|||
PJ_DEF(pj_status_t) pjsua_get_snd_dev(int *capture_dev,
|
||||
int *playback_dev)
|
||||
{
|
||||
PJSUA_LOCK();
|
||||
|
||||
if (capture_dev) {
|
||||
*capture_dev = pjsua_var.cap_dev;
|
||||
}
|
||||
|
@ -1927,6 +1936,7 @@ PJ_DEF(pj_status_t) pjsua_get_snd_dev(int *capture_dev,
|
|||
*playback_dev = pjsua_var.play_dev;
|
||||
}
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1942,6 +1952,7 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
|
|||
PJ_LOG(4,(THIS_FILE, "Setting null sound device.."));
|
||||
pj_log_push_indent();
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* Close existing sound device */
|
||||
close_snd_dev();
|
||||
|
@ -1969,6 +1980,7 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
|
|||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Unable to create null sound device",
|
||||
status);
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
return status;
|
||||
}
|
||||
|
@ -1983,6 +1995,7 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
|
|||
pjsua_var.no_snd = PJ_FALSE;
|
||||
pjsua_var.snd_is_on = PJ_TRUE;
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -1994,10 +2007,14 @@ PJ_DEF(pj_status_t) pjsua_set_null_snd_dev(void)
|
|||
*/
|
||||
PJ_DEF(pjmedia_port*) pjsua_set_no_snd_dev(void)
|
||||
{
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* Close existing sound device */
|
||||
close_snd_dev();
|
||||
|
||||
pjsua_var.no_snd = PJ_TRUE;
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
|
||||
return pjmedia_conf_get_master_port(pjsua_var.mconf);
|
||||
}
|
||||
|
||||
|
@ -2007,13 +2024,18 @@ PJ_DEF(pjmedia_port*) pjsua_set_no_snd_dev(void)
|
|||
*/
|
||||
PJ_DEF(pj_status_t) pjsua_set_ec(unsigned tail_ms, unsigned options)
|
||||
{
|
||||
pj_status_t status = PJ_SUCCESS;
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
pjsua_var.media_cfg.ec_tail_len = tail_ms;
|
||||
|
||||
if (pjsua_var.snd_port)
|
||||
return pjmedia_snd_port_set_ec( pjsua_var.snd_port, pjsua_var.pool,
|
||||
tail_ms, options);
|
||||
status = pjmedia_snd_port_set_ec(pjsua_var.snd_port, pjsua_var.pool,
|
||||
tail_ms, options);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
PJSUA_UNLOCK();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2050,6 +2072,8 @@ PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap,
|
|||
return PJMEDIA_EAUD_INVCAP;
|
||||
}
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* If sound is active, set it immediately */
|
||||
if (pjsua_snd_is_active()) {
|
||||
pjmedia_aud_stream *strm;
|
||||
|
@ -2060,8 +2084,10 @@ PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap,
|
|||
status = PJ_SUCCESS;
|
||||
}
|
||||
|
||||
if (status != PJ_SUCCESS)
|
||||
if (status != PJ_SUCCESS) {
|
||||
PJSUA_UNLOCK();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Save in internal param for later device open */
|
||||
if (keep) {
|
||||
|
@ -2069,6 +2095,7 @@ PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap,
|
|||
cap, pval);
|
||||
}
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -2078,6 +2105,10 @@ PJ_DEF(pj_status_t) pjsua_snd_set_setting( pjmedia_aud_dev_cap cap,
|
|||
PJ_DEF(pj_status_t) pjsua_snd_get_setting( pjmedia_aud_dev_cap cap,
|
||||
void *pval)
|
||||
{
|
||||
pj_status_t status;
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
/* If sound device has never been opened before, open it to
|
||||
* retrieve the initial setting from the device (e.g. audio
|
||||
* volume)
|
||||
|
@ -2093,12 +2124,15 @@ PJ_DEF(pj_status_t) pjsua_snd_get_setting( pjmedia_aud_dev_cap cap,
|
|||
pjmedia_aud_stream *strm;
|
||||
|
||||
strm = pjmedia_snd_port_get_snd_stream(pjsua_var.snd_port);
|
||||
return pjmedia_aud_stream_get_cap(strm, cap, pval);
|
||||
status = pjmedia_aud_stream_get_cap(strm, cap, pval);
|
||||
} else {
|
||||
/* Otherwise retrieve from internal param */
|
||||
return pjmedia_aud_param_get_cap(&pjsua_var.aud_param,
|
||||
cap, pval);
|
||||
status = pjmedia_aud_param_get_cap(&pjsua_var.aud_param,
|
||||
cap, pval);
|
||||
}
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* PJSUA_MEDIA_HAS_PJMEDIA */
|
||||
|
|
|
@ -2929,12 +2929,10 @@ static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
|
|||
pjsua_call *call;
|
||||
|
||||
pj_log_push_indent();
|
||||
PJSUA_LOCK();
|
||||
|
||||
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
|
||||
|
||||
if (!call) {
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
return;
|
||||
}
|
||||
|
@ -3077,21 +3075,21 @@ static void pjsua_call_on_state_changed(pjsip_inv_session *inv,
|
|||
/* Destroy media session when invite session is disconnected. */
|
||||
if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
|
||||
|
||||
pj_assert(call != NULL);
|
||||
|
||||
if (call)
|
||||
pjsua_media_channel_deinit(call->index);
|
||||
PJSUA_LOCK();
|
||||
|
||||
pjsua_media_channel_deinit(call->index);
|
||||
|
||||
/* Free call */
|
||||
call->inv = NULL;
|
||||
|
||||
pj_assert(pjsua_var.call_cnt > 0);
|
||||
--pjsua_var.call_cnt;
|
||||
|
||||
/* Reset call */
|
||||
reset_call(call->index);
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
}
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
}
|
||||
|
||||
|
@ -3202,7 +3200,6 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
|
|||
//const pj_str_t st_update = {"UPDATE", 6};
|
||||
|
||||
pj_log_push_indent();
|
||||
PJSUA_LOCK();
|
||||
|
||||
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
|
||||
|
||||
|
@ -3279,7 +3276,6 @@ static void pjsua_call_on_media_update(pjsip_inv_session *inv,
|
|||
pjsua_var.ua_cfg.cb.on_call_media_state(call->index);
|
||||
|
||||
on_return:
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
}
|
||||
|
||||
|
@ -3392,8 +3388,6 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
|
|||
unsigned i;
|
||||
pj_status_t status;
|
||||
|
||||
PJSUA_LOCK();
|
||||
|
||||
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
|
||||
|
||||
/* Supply candidate answer */
|
||||
|
@ -3480,7 +3474,6 @@ static void pjsua_call_on_rx_offer(pjsip_inv_session *inv,
|
|||
}
|
||||
|
||||
on_return:
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
}
|
||||
|
||||
|
@ -3495,7 +3488,6 @@ static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
|
|||
pj_status_t status;
|
||||
|
||||
pj_log_push_indent();
|
||||
PJSUA_LOCK();
|
||||
|
||||
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
|
||||
|
||||
|
@ -3520,7 +3512,6 @@ static void pjsua_call_on_create_offer(pjsip_inv_session *inv,
|
|||
}
|
||||
|
||||
on_return:
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
}
|
||||
|
||||
|
@ -3983,7 +3974,6 @@ static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
|
|||
pjsua_call *call;
|
||||
|
||||
pj_log_push_indent();
|
||||
PJSUA_LOCK();
|
||||
|
||||
call = (pjsua_call*) inv->dlg->mod_data[pjsua_var.mod.id];
|
||||
|
||||
|
@ -3999,6 +3989,17 @@ static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
|
|||
goto on_return;
|
||||
}
|
||||
|
||||
/* https://trac.pjsip.org/repos/ticket/1452:
|
||||
* If a request is retried due to 401/407 challenge, don't process the
|
||||
* transaction first but wait until we've retried it.
|
||||
*/
|
||||
if (tsx->role == PJSIP_ROLE_UAC &&
|
||||
(tsx->status_code==401 || tsx->status_code==407) &&
|
||||
tsx->last_tx && tsx->last_tx->auth_retry)
|
||||
{
|
||||
goto on_return;
|
||||
}
|
||||
|
||||
/* Notify application callback first */
|
||||
if (pjsua_var.ua_cfg.cb.on_call_tsx_state) {
|
||||
(*pjsua_var.ua_cfg.cb.on_call_tsx_state)(call->index, tsx, e);
|
||||
|
@ -4124,8 +4125,6 @@ static void pjsua_call_on_tsx_state_changed(pjsip_inv_session *inv,
|
|||
}
|
||||
|
||||
on_return:
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
}
|
||||
|
||||
|
@ -4139,7 +4138,6 @@ static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
|
|||
pjsip_redirect_op op;
|
||||
|
||||
pj_log_push_indent();
|
||||
PJSUA_LOCK();
|
||||
|
||||
if (pjsua_var.ua_cfg.cb.on_call_redirected) {
|
||||
op = (*pjsua_var.ua_cfg.cb.on_call_redirected)(call->index,
|
||||
|
@ -4152,7 +4150,6 @@ static pjsip_redirect_op pjsua_call_on_redirected(pjsip_inv_session *inv,
|
|||
op = PJSIP_REDIRECT_STOP;
|
||||
}
|
||||
|
||||
PJSUA_UNLOCK();
|
||||
pj_log_pop_indent();
|
||||
|
||||
return op;
|
||||
|
|
|
@ -413,7 +413,6 @@ static void dump_media_session(const char *indent,
|
|||
const char *type2 = pj_ice_get_cand_type_name(ii->comp[jj].rcand_type);
|
||||
char addr1[PJ_INET6_ADDRSTRLEN+10];
|
||||
char addr2[PJ_INET6_ADDRSTRLEN+10];
|
||||
const char *comp_name[2] = {"rtp ", "rtcp"};
|
||||
|
||||
if (pj_sockaddr_has_addr(&ii->comp[jj].lcand_addr))
|
||||
pj_sockaddr_print(&ii->comp[jj].lcand_addr, addr1, sizeof(addr1), 3);
|
||||
|
|
|
@ -97,8 +97,8 @@ pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg)
|
|||
goto on_error;
|
||||
|
||||
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
|
||||
/* Initialize SRTP library. */
|
||||
status = pjmedia_srtp_init_lib();
|
||||
/* Initialize SRTP library (ticket #788). */
|
||||
status = pjmedia_srtp_init_lib(pjsua_var.med_endpt);
|
||||
if (status != PJ_SUCCESS) {
|
||||
pjsua_perror(THIS_FILE, "Error initializing SRTP library",
|
||||
status);
|
||||
|
|
|
@ -5,7 +5,6 @@ export LIBDIR := ../../lib
|
|||
|
||||
RULES_MAK := $(PJDIR)/build/rules.mak
|
||||
|
||||
export RESAMPLE_LIB := ../../lib/libresample-$(TARGET_NAME)$(LIBEXT)
|
||||
|
||||
###############################################################################
|
||||
# Gather all flags.
|
||||
|
@ -22,6 +21,9 @@ export RESAMPLE_SRCDIR = ../../resample/src
|
|||
export RESAMPLE_OBJS = resamplesubs.o
|
||||
export RESAMPLE_CFLAGS = $(_CFLAGS)
|
||||
|
||||
SHLIB_NAME := libresample.$(SHLIB_SUFFIX)
|
||||
export RESAMPLE_SHLIB := ../../lib/$(SHLIB_NAME).$(PJ_VERSION_MAJOR)
|
||||
export RESAMPLE_LIB := ../../lib/libresample-$(TARGET_NAME)$(LIBEXT)
|
||||
|
||||
export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
|
||||
###############################################################################
|
||||
|
@ -29,7 +31,18 @@ export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
|
|||
#
|
||||
# $(TARGET) is defined in os-$(OS_NAME).mak file in current directory.
|
||||
#
|
||||
ifeq ($(PJ_RESAMPLE_DLL),1)
|
||||
TARGETS := ../../lib/$(SHLIB_NAME)
|
||||
ifeq ($(SHLIB_SUFFIX),so)
|
||||
SHLIB_OPT := -Wl,-soname,$(SHLIB_NAME).$(PJ_VERSION_MAJOR)
|
||||
else
|
||||
SHLIB_OPT :=
|
||||
endif
|
||||
export RESAMPLE_CFLAGS := -fPIC $(RESAMPLE_CFLAGS)
|
||||
export RESAMPLE_LDFLAGS := -shared $(SHLIB_OPT) $(RESAMPLE_LDFLAGS)
|
||||
else
|
||||
TARGETS := libresample
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
|
@ -44,12 +57,18 @@ distclean: realclean
|
|||
libresample:
|
||||
$(MAKE) -f $(RULES_MAK) APP=RESAMPLE app=libresample $(RESAMPLE_LIB)
|
||||
|
||||
../../lib/$(SHLIB_NAME): $(RESAMPLE_SHLIB)
|
||||
ln -s $(SHLIB_NAME).$(PJ_VERSION_MAJOR) $@
|
||||
|
||||
$(RESAMPLE_SHLIB):
|
||||
$(MAKE) -f $(RULES_MAK) APP=RESAMPLE app=libresample $(RESAMPLE_SHLIB)
|
||||
|
||||
clean print_lib:
|
||||
$(MAKE) -f $(RULES_MAK) APP=RESAMPLE app=libresample $@
|
||||
|
||||
realclean:
|
||||
$(subst @@,$(subst /,$(HOST_PSEP),.ilbc-$(TARGET_NAME).depend),$(HOST_RMR))
|
||||
|
||||
$(subst @@,$(subst /,$(HOST_PSEP),../../lib/$(SHLIB_NAME)),$(HOST_RMR))
|
||||
$(subst @@,$(subst /,$(HOST_PSEP),$(RESAMPLE_SHLIB)),$(HOST_RMR))
|
||||
$(MAKE) -f $(RULES_MAK) APP=RESAMPLE app=libresample $@
|
||||
|
||||
depend:
|
||||
|
|
16
version.mak
16
version.mak
|
@ -1 +1,15 @@
|
|||
export PJ_VERSION := 2.0-beta-svn
|
||||
export PJ_VERSION_MAJOR := 2
|
||||
export PJ_VERSION_MINOR := 0
|
||||
export PJ_VERSION_REV :=
|
||||
export PJ_VERSION_SUFFIX := beta-svn
|
||||
|
||||
export PJ_VERSION := $(PJ_VERSION_MAJOR).$(PJ_VERSION_MINOR)
|
||||
|
||||
ifneq ($(PJ_VERSION_REV),)
|
||||
export PJ_VERSION := $(PJ_VERSION).$(PJ_VERSION_REV)
|
||||
endif
|
||||
|
||||
ifneq ($(PJ_VERSION_SUFFIX),)
|
||||
export PJ_VERSION := $(PJ_VERSION)-$(PJ_VERSION_SUFFIX)
|
||||
endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue