From 483805f79570115ab95c69698792d238c1719b1b Mon Sep 17 00:00:00 2001 From: Jason Parker Date: Mon, 11 Mar 2013 15:09:56 -0500 Subject: Import pjproject-2.1 --- aconfigure | 300 +++++- aconfigure.ac | 130 ++- build.symbian/pjlibU.def | 385 ++++---- configure-bb10 | 2 +- configure-iphone | 2 +- pjlib-util/build/Makefile | 2 +- pjlib-util/include/pjlib-util/stun_simple.h | 77 +- pjlib-util/src/pjlib-util/resolver.c | 150 ++- pjlib-util/src/pjlib-util/scanner.c | 3 +- pjlib-util/src/pjlib-util/stun_simple_client.c | 39 +- pjlib/build/Makefile | 2 +- pjlib/include/pj/activesock.h | 9 +- pjlib/include/pj/addr_resolv.h | 27 +- pjlib/include/pj/config.h | 22 +- pjlib/include/pj/config_site_sample.h | 6 +- pjlib/include/pj/errno.h | 7 +- pjlib/include/pj/guid.h | 21 +- pjlib/include/pj/hash.h | 40 +- pjlib/include/pj/ioqueue.h | 15 +- pjlib/include/pj/lock.h | 254 ++++- pjlib/include/pj/pool.h | 4 +- pjlib/include/pj/pool_i.h | 4 +- pjlib/include/pj/sock.h | 20 +- pjlib/include/pj/timer.h | 68 +- pjlib/include/pj/types.h | 5 +- pjlib/src/pj/activesock.c | 58 +- pjlib/src/pj/errno.c | 5 +- pjlib/src/pj/guid.c | 23 +- pjlib/src/pj/hash.c | 95 +- pjlib/src/pj/ioqueue_common_abs.c | 116 ++- pjlib/src/pj/ioqueue_common_abs.h | 3 +- pjlib/src/pj/ioqueue_epoll.c | 20 +- pjlib/src/pj/ioqueue_select.c | 83 +- pjlib/src/pj/ioqueue_symbian.cpp | 15 +- pjlib/src/pj/ip_helper_generic.c | 20 +- pjlib/src/pj/lock.c | 519 +++++++++- pjlib/src/pj/os_core_unix.c | 123 ++- pjlib/src/pj/os_info.c | 5 +- pjlib/src/pj/pool.c | 6 +- pjlib/src/pj/pool_caching.c | 10 +- pjlib/src/pj/sock_bsd.c | 7 +- pjlib/src/pj/sock_common.c | 111 ++- pjlib/src/pj/ssl_sock_ossl.c | 436 ++++++--- pjlib/src/pj/timer.c | 119 ++- pjlib/src/pj/timer_symbian.cpp | 31 +- pjlib/src/pjlib-test/activesock.c | 3 +- pjlib/src/pjlib-test/ioq_tcp.c | 14 +- pjlib/src/pjlib-test/ioq_udp.c | 7 +- pjlib/src/pjlib-test/ssl_sock.c | 25 +- pjmedia/build/Makefile | 6 +- pjmedia/build/os-auto.mak.in | 11 +- pjmedia/build/pjmedia_codec.vcproj | 12 +- pjmedia/include/pjmedia-audiodev/audiodev.h | 8 +- pjmedia/include/pjmedia-codec.h | 5 +- pjmedia/include/pjmedia-codec/config.h | 48 +- pjmedia/include/pjmedia-codec/config_auto.h.in | 11 +- pjmedia/include/pjmedia-codec/opencore_amr.h | 146 +++ pjmedia/include/pjmedia-codec/opencore_amrnb.h | 89 -- pjmedia/include/pjmedia-codec/silk.h | 133 +++ pjmedia/include/pjmedia-codec/types.h | 30 +- pjmedia/include/pjmedia-videodev/config.h | 13 +- pjmedia/include/pjmedia/codec.h | 15 +- pjmedia/include/pjmedia/config.h | 34 +- pjmedia/include/pjmedia/sdp.h | 19 +- pjmedia/include/pjmedia/transport.h | 27 +- pjmedia/include/pjmedia/transport_ice.h | 8 +- pjmedia/src/pjmedia-audiodev/alsa_dev.c | 4 +- pjmedia/src/pjmedia-audiodev/bb10_dev.c | 364 +++++-- pjmedia/src/pjmedia-audiodev/symb_aps_dev.cpp | 58 +- pjmedia/src/pjmedia-audiodev/symb_vas_dev.cpp | 62 +- pjmedia/src/pjmedia-codec/audio_codecs.c | 15 +- pjmedia/src/pjmedia-codec/ffmpeg_vid_codecs.c | 17 +- pjmedia/src/pjmedia-codec/opencore_amr.c | 1031 ++++++++++++++++++++ pjmedia/src/pjmedia-codec/opencore_amrnb.c | 831 ---------------- pjmedia/src/pjmedia-codec/silk.c | 953 ++++++++++++++++++ pjmedia/src/pjmedia-videodev/dshow_dev.c | 17 +- pjmedia/src/pjmedia-videodev/sdl_dev.c | 6 +- pjmedia/src/pjmedia-videodev/v4l2_dev.c | 5 +- pjmedia/src/pjmedia/codec.c | 52 +- pjmedia/src/pjmedia/conference.c | 6 +- pjmedia/src/pjmedia/converter.c | 4 +- pjmedia/src/pjmedia/endpoint.c | 10 +- pjmedia/src/pjmedia/g711.c | 7 +- pjmedia/src/pjmedia/jbuf.c | 9 +- pjmedia/src/pjmedia/rtcp.c | 5 +- pjmedia/src/pjmedia/rtp.c | 4 +- pjmedia/src/pjmedia/sdp.c | 14 +- pjmedia/src/pjmedia/sdp_neg.c | 4 +- pjmedia/src/pjmedia/stream.c | 104 +- pjmedia/src/pjmedia/transport_ice.c | 8 +- pjmedia/src/pjmedia/transport_srtp.c | 69 +- pjmedia/src/pjmedia/transport_udp.c | 8 +- pjmedia/src/pjmedia/types.c | 6 +- pjmedia/src/pjmedia/vid_codec_util.c | 290 ++++-- pjmedia/src/pjmedia/vid_port.c | 13 +- pjmedia/src/pjmedia/vid_stream.c | 21 +- pjmedia/src/pjmedia/vid_stream_info.c | 5 +- pjmedia/src/test/mips_test.c | 45 +- pjnath/build/Makefile | 4 +- pjnath/build/pjnath_test.vcproj | 58 ++ pjnath/include/pjnath/config.h | 13 +- pjnath/include/pjnath/ice_session.h | 8 +- pjnath/include/pjnath/stun_config.h | 10 +- pjnath/include/pjnath/stun_session.h | 27 +- pjnath/include/pjnath/stun_sock.h | 27 +- pjnath/include/pjnath/stun_transaction.h | 15 +- pjnath/include/pjnath/turn_session.h | 8 +- pjnath/include/pjnath/turn_sock.h | 34 +- pjnath/src/pjnath-test/concur_test.c | 367 +++++++ pjnath/src/pjnath-test/ice_test.c | 241 ++++- pjnath/src/pjnath-test/sess_auth.c | 6 +- pjnath/src/pjnath-test/stun_sock_test.c | 14 +- pjnath/src/pjnath-test/test.c | 35 +- pjnath/src/pjnath-test/test.h | 6 +- pjnath/src/pjnath/ice_session.c | 409 ++++---- pjnath/src/pjnath/ice_strans.c | 211 ++-- pjnath/src/pjnath/nat_detect.c | 4 +- pjnath/src/pjnath/stun_session.c | 377 +++---- pjnath/src/pjnath/stun_sock.c | 217 ++-- pjnath/src/pjnath/stun_transaction.c | 157 +-- pjnath/src/pjnath/turn_session.c | 184 ++-- pjnath/src/pjnath/turn_sock.c | 173 ++-- pjnath/src/pjturn-srv/allocation.c | 4 +- pjnath/src/pjturn-srv/server.c | 5 +- pjsip-apps/src/pjsua/pjsua_app.c | 359 ++++--- pjsip-apps/src/python/setup.py | 7 +- pjsip-apps/src/samples/icedemo.c | 3 +- pjsip-apps/src/samples/pjsip-perf.c | 14 +- pjsip-apps/src/samples/proxy.h | 8 +- pjsip-apps/src/symbian_ua_gui/src/symbian_ua.cpp | 1 - pjsip/build/Makefile | 2 +- pjsip/include/pjsip/sip_auth.h | 79 +- pjsip/include/pjsip/sip_config.h | 50 +- pjsip/include/pjsip/sip_endpoint.h | 73 +- pjsip/include/pjsip/sip_transport.h | 110 ++- pjsip/include/pjsip/sip_transport_tls.h | 42 +- pjsip/include/pjsip/sip_types.h | 7 +- pjsip/include/pjsip/sip_uri.h | 10 +- pjsip/include/pjsip/sip_util.h | 9 +- pjsip/include/pjsua-lib/pjsua.h | 346 ++++++- pjsip/include/pjsua-lib/pjsua_internal.h | 31 +- pjsip/src/pjsip-simple/publishc.c | 9 +- pjsip/src/pjsip-ua/sip_100rel.c | 6 +- pjsip/src/pjsip-ua/sip_inv.c | 100 +- pjsip/src/pjsip-ua/sip_reg.c | 11 +- pjsip/src/pjsip-ua/sip_replaces.c | 19 +- pjsip/src/pjsip-ua/sip_timer.c | 29 +- pjsip/src/pjsip/sip_auth_client.c | 17 +- pjsip/src/pjsip/sip_auth_server.c | 47 +- pjsip/src/pjsip/sip_config.c | 4 +- pjsip/src/pjsip/sip_dialog.c | 23 +- pjsip/src/pjsip/sip_endpoint.c | 160 ++- pjsip/src/pjsip/sip_parser.c | 11 +- pjsip/src/pjsip/sip_tel_uri.c | 6 +- pjsip/src/pjsip/sip_transaction.c | 43 +- pjsip/src/pjsip/sip_transport.c | 243 ++++- pjsip/src/pjsip/sip_transport_tcp.c | 174 ++-- pjsip/src/pjsip/sip_transport_tls.c | 191 ++-- pjsip/src/pjsip/sip_ua_layer.c | 50 +- pjsip/src/pjsip/sip_uri.c | 7 +- pjsip/src/pjsip/sip_util_proxy.c | 4 +- pjsip/src/pjsua-lib/pjsua_acc.c | 290 +++++- pjsip/src/pjsua-lib/pjsua_aud.c | 36 +- pjsip/src/pjsua-lib/pjsua_call.c | 724 +++++++++----- pjsip/src/pjsua-lib/pjsua_core.c | 178 +++- pjsip/src/pjsua-lib/pjsua_dump.c | 30 +- pjsip/src/pjsua-lib/pjsua_media.c | 767 +++++++++++---- pjsip/src/pjsua-lib/pjsua_pres.c | 76 +- pjsip/src/pjsua-lib/pjsua_vid.c | 32 +- pjsip/src/test/tsx_uac_test.c | 34 +- pjsip/src/test/tsx_uas_test.c | 76 +- pjsip/src/test/uri_test.c | 24 +- pkgconfig.py | 4 +- .../scripts-sipp/uas-reinv-with-less-media.py | 8 + .../scripts-sipp/uas-reinv-with-less-media.xml | 155 +++ third_party/BaseClasses/wxutil.cpp | 6 +- version.mak | 4 +- 177 files changed, 11489 insertions(+), 3984 deletions(-) create mode 100644 pjmedia/include/pjmedia-codec/opencore_amr.h delete mode 100644 pjmedia/include/pjmedia-codec/opencore_amrnb.h create mode 100644 pjmedia/include/pjmedia-codec/silk.h create mode 100644 pjmedia/src/pjmedia-codec/opencore_amr.c delete mode 100644 pjmedia/src/pjmedia-codec/opencore_amrnb.c create mode 100644 pjmedia/src/pjmedia-codec/silk.c create mode 100644 pjnath/src/pjnath-test/concur_test.c create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py create mode 100644 tests/pjsua/scripts-sipp/uas-reinv-with-less-media.xml diff --git a/aconfigure b/aconfigure index ac15b36..33ed0be 100755 --- a/aconfigure +++ b/aconfigure @@ -623,8 +623,16 @@ LIBOBJS ac_main_obj ac_host ac_linux_poll +silk_present +silk_h_present +ac_no_silk +opencore_amrwb_dec_present +opencore_amrwb_dec_h_present +opencore_amrwb_enc_present +opencore_amrwb_enc_h_present opencore_amrnb_present opencore_amrnb_h_present +ac_no_opencore_amrwb ac_no_opencore_amrnb libcrypto_present libssl_present @@ -778,7 +786,11 @@ with_ipp_arch with_ssl enable_ssl with_opencore_amrnb -enable_opencore_amrnb +with_opencore_amr +with_opencore_amrwbenc +enable_opencore_amr +with_silk +enable_silk ' ac_precious_vars='build_alias host_alias @@ -1435,10 +1447,12 @@ Optional Features: --with-ipp-samples options --disable-ssl Exclude SSL support the build (default: autodetect) - --disable-opencore-amrnb - Exclude OpenCORE AMR-NB support from the build + --disable-opencore-amr Exclude OpenCORE AMR support from the build (default: autodetect) + --disable-silk Exclude SILK support from the build (default: + autodetect) + Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1466,7 +1480,12 @@ Optional Packages: "em64t. Default is blank for IA32" --with-ssl=DIR Specify alternate libssl prefix --with-opencore-amrnb=DIR - Specify alternate libopencore-amrnb prefix + This option is obsolete and replaced by + --with-opencore-amr=DIR + --with-opencore-amr=DIR Specify alternate libopencore-amr prefix + --with-opencore-amrwbenc=DIR + Specify alternate libvo-amrwbenc prefix + --with-silk=DIR Specify alternate SILK prefix Some influential environment variables: CC C compiler command @@ -7100,38 +7119,70 @@ fi # Check whether --with-opencore-amrnb was given. if test "${with_opencore_amrnb+set}" = set; then : - withval=$with_opencore_amrnb; + withval=$with_opencore_amrnb; as_fn_error $? "This option is obsolete and replaced by --with-opencore-amr=DIR" "$LINENO" 5 +fi + + + +# Check whether --with-opencore-amr was given. +if test "${with_opencore_amr+set}" = set; then : + withval=$with_opencore_amr; else - with_opencore_amrnb=no + with_opencore_amr=no fi -if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrnb" = "xno"; then - enable_opencore_amrnb=no +if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amr" = "xno"; then + enable_opencore_amr=no +fi + + +# Check whether --with-opencore-amrwbenc was given. +if test "${with_opencore_amrwbenc+set}" = set; then : + withval=$with_opencore_amrwbenc; +else + with_opencore_amrwbenc=no + fi -# Check whether --enable-opencore_amrnb was given. -if test "${enable_opencore_amrnb+set}" = set; then : - enableval=$enable_opencore_amrnb; - if test "$enable_opencore_amrnb" = "no"; then +if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrwbenc" = "xno"; then + enable_opencore_amrwbenc=no +fi + + + + +# Check whether --enable-opencore_amr was given. +if test "${enable_opencore_amr+set}" = set; then : + enableval=$enable_opencore_amr; + if test "$enable_opencore_amr" = "no"; then ac_no_opencore_amrnb=1 + ac_no_opencore_amrwb=1 $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenCORE AMR-NB support is disabled... yes" >&5 -$as_echo "Checking if OpenCORE AMR-NB support is disabled... yes" >&6; } + $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 0" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenCORE AMR support is disabled... yes" >&5 +$as_echo "Checking if OpenCORE AMR support is disabled... yes" >&6; } fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OpenCORE AMR-NB installations.." >&5 -$as_echo "checking for OpenCORE AMR-NB installations.." >&6; } - if test "x$with_opencore_amrnb" != "xno" -a "x$with_opencore_amrnb" != "x"; then - CFLAGS="$CFLAGS -I$with_opencore_amrnb/include" - LDFLAGS="$LDFLAGS -L$with_opencore_amrnb/lib" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMR-NB prefix... $with_opencore_amrnb" >&5 -$as_echo "Using OpenCORE AMR-NB prefix... $with_opencore_amrnb" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for OpenCORE AMR installations.." >&5 +$as_echo "checking for OpenCORE AMR installations.." >&6; } + if test "x$with_opencore_amr" != "xno" -a "x$with_opencore_amr" != "x"; then + CFLAGS="$CFLAGS -I$with_opencore_amr/include" + LDFLAGS="$LDFLAGS -L$with_opencore_amr/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMR prefix... $with_opencore_amr" >&5 +$as_echo "Using OpenCORE AMR prefix... $with_opencore_amr" >&6; } + fi + if test "x$with_opencore_amrwbenc" != "xno" -a "x$with_opencore_amrwbenc" != "x"; then + CFLAGS="$CFLAGS -I$with_opencore_amrwbenc/include" + LDFLAGS="$LDFLAGS -L$with_opencore_amrwbenc/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc" >&5 +$as_echo "Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc" >&6; } fi @@ -7192,9 +7243,216 @@ $as_echo "OpenCORE AMR-NB library found, AMR-NB support enabled" >&6; } fi + + + + ac_fn_c_check_header_mongrel "$LINENO" "vo-amrwbenc/enc_if.h" "ac_cv_header_vo_amrwbenc_enc_if_h" "$ac_includes_default" +if test "x$ac_cv_header_vo_amrwbenc_enc_if_h" = xyes; then : + opencore_amrwb_enc_h_present=1 fi + ac_fn_c_check_header_mongrel "$LINENO" "opencore-amrwb/dec_if.h" "ac_cv_header_opencore_amrwb_dec_if_h" "$ac_includes_default" +if test "x$ac_cv_header_opencore_amrwb_dec_if_h" = xyes; then : + opencore_amrwb_dec_h_present=1 +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for D_IF_init in -lopencore-amrwb" >&5 +$as_echo_n "checking for D_IF_init in -lopencore-amrwb... " >&6; } +if ${ac_cv_lib_opencore_amrwb_D_IF_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopencore-amrwb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char D_IF_init (); +int +main () +{ +return D_IF_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_opencore_amrwb_D_IF_init=yes +else + ac_cv_lib_opencore_amrwb_D_IF_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_opencore_amrwb_D_IF_init" >&5 +$as_echo "$ac_cv_lib_opencore_amrwb_D_IF_init" >&6; } +if test "x$ac_cv_lib_opencore_amrwb_D_IF_init" = xyes; then : + opencore_amrwb_dec_present=1 && LIBS="$LIBS -lopencore-amrwb" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for E_IF_init in -lvo-amrwbenc" >&5 +$as_echo_n "checking for E_IF_init in -lvo-amrwbenc... " >&6; } +if ${ac_cv_lib_vo_amrwbenc_E_IF_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lvo-amrwbenc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char E_IF_init (); +int +main () +{ +return E_IF_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_vo_amrwbenc_E_IF_init=yes +else + ac_cv_lib_vo_amrwbenc_E_IF_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vo_amrwbenc_E_IF_init" >&5 +$as_echo "$ac_cv_lib_vo_amrwbenc_E_IF_init" >&6; } +if test "x$ac_cv_lib_vo_amrwbenc_E_IF_init" = xyes; then : + opencore_amrwb_enc_present=1 && LIBS="$LIBS -lvo-amrwbenc" +fi + + if test "x$opencore_amrwb_enc_h_present" = "x1" -a "x$opencore_amrwb_dec_h_present" = "x1" -a "x$opencore_amrwb_enc_present" = "x1" -a "x$opencore_amrwb_dec_present" = "x1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: OpenCORE AMR-WB library found, AMR-WB support enabled" >&5 +$as_echo "OpenCORE AMR-WB library found, AMR-WB support enabled" >&6; } + $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 1" >>confdefs.h + + else + ac_no_opencore_amrwb=1 + $as_echo "#define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 0" >>confdefs.h + + fi + + +fi + + + +# Check whether --with-silk was given. +if test "${with_silk+set}" = set; then : + withval=$with_silk; +else + with_silk=no + +fi + + +if test "x$ac_cross_compile" != "x" -a "x$with_silk" = "xno"; then + enable_silk=no +fi + + +# Check whether --enable-silk was given. +if test "${enable_silk+set}" = set; then : + enableval=$enable_silk; + if test "$enable_silk" = "no"; then + ac_no_silk=1 + $as_echo "#define PJMEDIA_HAS_SILK_CODEC 0" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if SILK support is disabled... yes" >&5 +$as_echo "Checking if SILK support is disabled... yes" >&6; } + fi + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for SILK installations.." >&5 +$as_echo "checking for SILK installations.." >&6; } + if test "x$with_silk" != "xno" -a "x$with_silk" != "x"; then + CFLAGS="$CFLAGS -I$with_silk/interface" + CPPFLAGS="$CPPFLAGS -I$with_silk/interface" + LDFLAGS="$LDFLAGS -L$with_silk" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using SILK prefix... $with_silk" >&5 +$as_echo "Using SILK prefix... $with_silk" >&6; } + fi + + + ac_fn_c_check_header_mongrel "$LINENO" "SKP_Silk_SDK_API.h" "ac_cv_header_SKP_Silk_SDK_API_h" "$ac_includes_default" +if test "x$ac_cv_header_SKP_Silk_SDK_API_h" = xyes; then : + silk_h_present=1 +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SKP_Silk_SDK_get_version in -lSKP_SILK_SDK" >&5 +$as_echo_n "checking for SKP_Silk_SDK_get_version in -lSKP_SILK_SDK... " >&6; } +if ${ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSKP_SILK_SDK $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char SKP_Silk_SDK_get_version (); +int +main () +{ +return SKP_Silk_SDK_get_version (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version=yes +else + ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version" >&5 +$as_echo "$ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version" >&6; } +if test "x$ac_cv_lib_SKP_SILK_SDK_SKP_Silk_SDK_get_version" = xyes; then : + silk_present=1 && LIBS="$LIBS -lSKP_SILK_SDK" +fi + + if test "x$silk_h_present" = "x1" -a "x$silk_present" = "x1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: SILK library found, SILK support enabled" >&5 +$as_echo "SILK library found, SILK support enabled" >&6; } + $as_echo "#define PJMEDIA_HAS_SILK_CODEC 1" >>confdefs.h + + else + ac_no_silk=1 + $as_echo "#define PJMEDIA_HAS_SILK_CODEC 0" >>confdefs.h + + fi + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if select() needs correct nfds" >&5 diff --git a/aconfigure.ac b/aconfigure.ac index be2f2ae..9afce8d 100644 --- a/aconfigure.ac +++ b/aconfigure.ac @@ -1320,39 +1320,69 @@ AC_ARG_ENABLE(ssl, fi ]) -dnl # opencore-amrnb alt prefix +dnl # Obsolete option --with-opencore-amrnb AC_ARG_WITH(opencore-amrnb, AC_HELP_STRING([--with-opencore-amrnb=DIR], - [Specify alternate libopencore-amrnb prefix]), + [This option is obsolete and replaced by --with-opencore-amr=DIR]), + [AC_MSG_ERROR(This option is obsolete and replaced by --with-opencore-amr=DIR)], + [] + ) + +dnl # opencore-amr alt prefix +AC_ARG_WITH(opencore-amr, + AC_HELP_STRING([--with-opencore-amr=DIR], + [Specify alternate libopencore-amr prefix]), + [], + [with_opencore_amr=no] + ) + +dnl # Do not use default opencore-amr installation if we are cross-compiling +if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amr" = "xno"; then + enable_opencore_amr=no +fi + +dnl # vo-amrwbenc alt prefix +AC_ARG_WITH(opencore-amrwbenc, + AC_HELP_STRING([--with-opencore-amrwbenc=DIR], + [Specify alternate libvo-amrwbenc prefix]), [], - [with_opencore_amrnb=no] + [with_opencore_amrwbenc=no] ) -dnl # Do not use default opencore-amrnb installation if we are cross-compiling -if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrnb" = "xno"; then - enable_opencore_amrnb=no +dnl # Do not use default vo-amrwbenc installation if we are cross-compiling +if test "x$ac_cross_compile" != "x" -a "x$with_opencore_amrwbenc" = "xno"; then + enable_opencore_amrwbenc=no fi -dnl # Include opencore-amrnb support + +dnl # Include opencore-amr support AC_SUBST(ac_no_opencore_amrnb) -AC_ARG_ENABLE(opencore_amrnb, - AC_HELP_STRING([--disable-opencore-amrnb], - [Exclude OpenCORE AMR-NB support from the build (default: autodetect)]) +AC_SUBST(ac_no_opencore_amrwb) +AC_ARG_ENABLE(opencore_amr, + AC_HELP_STRING([--disable-opencore-amr], + [Exclude OpenCORE AMR support from the build (default: autodetect)]) , [ - if test "$enable_opencore_amrnb" = "no"; then + if test "$enable_opencore_amr" = "no"; then [ac_no_opencore_amrnb=1] + [ac_no_opencore_amrwb=1] AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0) - AC_MSG_RESULT([Checking if OpenCORE AMR-NB support is disabled... yes]) + AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,0) + AC_MSG_RESULT([Checking if OpenCORE AMR support is disabled... yes]) fi ], [ - AC_MSG_RESULT([checking for OpenCORE AMR-NB installations..]) - if test "x$with_opencore_amrnb" != "xno" -a "x$with_opencore_amrnb" != "x"; then - CFLAGS="$CFLAGS -I$with_opencore_amrnb/include" - LDFLAGS="$LDFLAGS -L$with_opencore_amrnb/lib" - AC_MSG_RESULT([Using OpenCORE AMR-NB prefix... $with_opencore_amrnb]) - fi + AC_MSG_RESULT([checking for OpenCORE AMR installations..]) + if test "x$with_opencore_amr" != "xno" -a "x$with_opencore_amr" != "x"; then + CFLAGS="$CFLAGS -I$with_opencore_amr/include" + LDFLAGS="$LDFLAGS -L$with_opencore_amr/lib" + AC_MSG_RESULT([Using OpenCORE AMR prefix... $with_opencore_amr]) + fi + if test "x$with_opencore_amrwbenc" != "xno" -a "x$with_opencore_amrwbenc" != "x"; then + CFLAGS="$CFLAGS -I$with_opencore_amrwbenc/include" + LDFLAGS="$LDFLAGS -L$with_opencore_amrwbenc/lib" + AC_MSG_RESULT([Using OpenCORE AMRWB-enc prefix... $with_opencore_amrwbenc]) + fi AC_SUBST(opencore_amrnb_h_present) AC_SUBST(opencore_amrnb_present) AC_CHECK_HEADER(opencore-amrnb/interf_enc.h,[opencore_amrnb_h_present=1]) @@ -1364,8 +1394,72 @@ AC_ARG_ENABLE(opencore_amrnb, [ac_no_opencore_amrnb=1] AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRNB_CODEC,0) fi + AC_SUBST(opencore_amrwb_enc_h_present) + AC_SUBST(opencore_amrwb_enc_present) + AC_SUBST(opencore_amrwb_dec_h_present) + AC_SUBST(opencore_amrwb_dec_present) + AC_CHECK_HEADER(vo-amrwbenc/enc_if.h,[opencore_amrwb_enc_h_present=1]) + AC_CHECK_HEADER(opencore-amrwb/dec_if.h,[opencore_amrwb_dec_h_present=1]) + AC_CHECK_LIB(opencore-amrwb,D_IF_init,[opencore_amrwb_dec_present=1 && LIBS="$LIBS -lopencore-amrwb"]) + AC_CHECK_LIB(vo-amrwbenc,E_IF_init,[opencore_amrwb_enc_present=1 && LIBS="$LIBS -lvo-amrwbenc"]) + if test "x$opencore_amrwb_enc_h_present" = "x1" -a "x$opencore_amrwb_dec_h_present" = "x1" -a "x$opencore_amrwb_enc_present" = "x1" -a "x$opencore_amrwb_dec_present" = "x1"; then + AC_MSG_RESULT([OpenCORE AMR-WB library found, AMR-WB support enabled]) + AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,1) + else + [ac_no_opencore_amrwb=1] + AC_DEFINE(PJMEDIA_HAS_OPENCORE_AMRWB_CODEC,0) + fi + + ]) + +dnl # SILK prefix +AC_ARG_WITH(silk, + AC_HELP_STRING([--with-silk=DIR], + [Specify alternate SILK prefix]), + [], + [with_silk=no] + ) + +dnl # Do not use default SILK installation if we are cross-compiling +if test "x$ac_cross_compile" != "x" -a "x$with_silk" = "xno"; then + enable_silk=no +fi + +dnl # Include SILK support +AC_SUBST(ac_no_silk) +AC_ARG_ENABLE(silk, + AC_HELP_STRING([--disable-silk], + [Exclude SILK support from the build (default: autodetect)]) + , + [ + if test "$enable_silk" = "no"; then + [ac_no_silk=1] + AC_DEFINE(PJMEDIA_HAS_SILK_CODEC,0) + AC_MSG_RESULT([Checking if SILK support is disabled... yes]) + fi + ], + [ + AC_MSG_RESULT([checking for SILK installations..]) + if test "x$with_silk" != "xno" -a "x$with_silk" != "x"; then + CFLAGS="$CFLAGS -I$with_silk/interface" + CPPFLAGS="$CPPFLAGS -I$with_silk/interface" + LDFLAGS="$LDFLAGS -L$with_silk" + AC_MSG_RESULT([Using SILK prefix... $with_silk]) + fi + AC_SUBST(silk_h_present) + AC_SUBST(silk_present) + AC_CHECK_HEADER(SKP_Silk_SDK_API.h,[silk_h_present=1]) + AC_CHECK_LIB(SKP_SILK_SDK,SKP_Silk_SDK_get_version,[silk_present=1 && LIBS="$LIBS -lSKP_SILK_SDK"]) + if test "x$silk_h_present" = "x1" -a "x$silk_present" = "x1"; then + AC_MSG_RESULT([SILK library found, SILK support enabled]) + AC_DEFINE(PJMEDIA_HAS_SILK_CODEC,1) + else + [ac_no_silk=1] + AC_DEFINE(PJMEDIA_HAS_SILK_CODEC,0) + fi ]) + dnl ########################################## dnl # dnl # MANUAL CONFIG diff --git a/build.symbian/pjlibU.def b/build.symbian/pjlibU.def index 3ddcb40..6dbffdf 100644 --- a/build.symbian/pjlibU.def +++ b/build.symbian/pjlibU.def @@ -130,194 +130,197 @@ EXPORTS pj_ioqueue_recv @ 129 NONAME pj_ioqueue_recvfrom @ 130 NONAME pj_ioqueue_register_sock @ 131 NONAME - pj_ioqueue_send @ 132 NONAME - pj_ioqueue_sendto @ 133 NONAME - pj_ioqueue_set_lock @ 134 NONAME - pj_ioqueue_set_user_data @ 135 NONAME - pj_ioqueue_unregister @ 136 NONAME - pj_leave_critical_section @ 137 NONAME - pj_list_erase @ 138 NONAME - pj_list_find_node @ 139 NONAME - pj_list_insert_after @ 140 NONAME - pj_list_insert_before @ 141 NONAME - pj_list_insert_nodes_after @ 142 NONAME - pj_list_insert_nodes_before @ 143 NONAME - pj_list_merge_first @ 144 NONAME - pj_list_merge_last @ 145 NONAME - pj_list_search @ 146 NONAME - pj_list_size @ 147 NONAME - pj_lock_acquire @ 148 NONAME - pj_lock_create_null_mutex @ 149 NONAME - pj_lock_create_recursive_mutex @ 150 NONAME - pj_lock_create_semaphore @ 151 NONAME - pj_lock_create_simple_mutex @ 152 NONAME - pj_lock_destroy @ 153 NONAME - pj_lock_release @ 154 NONAME - pj_lock_tryacquire @ 155 NONAME - pj_log @ 156 NONAME - pj_log_1 @ 157 NONAME - pj_log_2 @ 158 NONAME - pj_log_3 @ 159 NONAME - pj_log_4 @ 160 NONAME - pj_log_5 @ 161 NONAME - pj_log_get_decor @ 162 NONAME - pj_log_get_level @ 163 NONAME - pj_log_get_log_func @ 164 NONAME - pj_log_set_decor @ 165 NONAME - pj_log_set_level @ 166 NONAME - pj_log_set_log_func @ 167 NONAME - pj_log_write @ 168 NONAME - pj_mutex_create @ 169 NONAME - pj_mutex_create_recursive @ 170 NONAME - pj_mutex_create_simple @ 171 NONAME - pj_mutex_destroy @ 172 NONAME - pj_mutex_lock @ 173 NONAME - pj_mutex_trylock @ 174 NONAME - pj_mutex_unlock @ 175 NONAME - pj_ntohl @ 176 NONAME - pj_ntohs @ 177 NONAME - pj_pool_alloc @ 178 NONAME - pj_pool_alloc_from_block @ 179 NONAME - pj_pool_allocate_find @ 180 NONAME - pj_pool_calloc @ 181 NONAME - pj_pool_create @ 182 NONAME - pj_pool_create_int @ 183 NONAME - pj_pool_create_on_buf @ 184 NONAME - pj_pool_destroy_int @ 185 NONAME - pj_pool_factory_default_policy @ 186 NONAME - pj_pool_factory_get_default_policy @ 187 NONAME - pj_pool_get_capacity @ 188 NONAME - pj_pool_get_used_size @ 189 NONAME - pj_pool_getobjname @ 190 NONAME - pj_pool_init_int @ 191 NONAME - pj_pool_release @ 192 NONAME - pj_pool_reset @ 193 NONAME - pj_rand @ 194 NONAME - pj_rbtree_erase @ 195 NONAME - pj_rbtree_find @ 196 NONAME - pj_rbtree_first @ 197 NONAME - pj_rbtree_init @ 198 NONAME - pj_rbtree_insert @ 199 NONAME - pj_rbtree_last @ 200 NONAME - pj_rbtree_max_height @ 201 NONAME - pj_rbtree_min_height @ 202 NONAME - pj_rbtree_next @ 203 NONAME - pj_rbtree_prev @ 204 NONAME - pj_register_strerror @ 205 NONAME - pj_rwmutex_create @ 206 NONAME - pj_rwmutex_destroy @ 207 NONAME - pj_rwmutex_lock_read @ 208 NONAME - pj_rwmutex_lock_write @ 209 NONAME - pj_rwmutex_unlock_read @ 210 NONAME - pj_rwmutex_unlock_write @ 211 NONAME - pj_sem_create @ 212 NONAME - pj_sem_destroy @ 213 NONAME - pj_sem_post @ 214 NONAME - pj_sem_trywait @ 215 NONAME - pj_sem_wait @ 216 NONAME - pj_set_netos_error @ 217 NONAME - pj_set_os_error @ 218 NONAME - pj_shutdown @ 219 NONAME - pj_sock_accept @ 220 NONAME - pj_sock_bind @ 221 NONAME - pj_sock_bind_in @ 222 NONAME - pj_sock_close @ 223 NONAME - pj_sock_connect @ 224 NONAME - pj_sock_getpeername @ 225 NONAME - pj_sock_getsockname @ 226 NONAME - pj_sock_getsockopt @ 227 NONAME - pj_sock_listen @ 228 NONAME - pj_sock_recv @ 229 NONAME - pj_sock_recvfrom @ 230 NONAME - pj_sock_select @ 231 NONAME - pj_sock_send @ 232 NONAME - pj_sock_sendto @ 233 NONAME - pj_sock_setsockopt @ 234 NONAME - pj_sock_shutdown @ 235 NONAME - pj_sock_socket @ 236 NONAME - pj_sockaddr_cmp @ 237 NONAME - pj_sockaddr_copy_addr @ 238 NONAME - pj_sockaddr_get_addr @ 239 NONAME - pj_sockaddr_get_addr_len @ 240 NONAME - pj_sockaddr_get_len @ 241 NONAME - pj_sockaddr_get_port @ 242 NONAME - pj_sockaddr_has_addr @ 243 NONAME - pj_sockaddr_in_get_addr @ 244 NONAME - pj_sockaddr_in_get_port @ 245 NONAME - pj_sockaddr_in_init @ 246 NONAME - pj_sockaddr_in_set_addr @ 247 NONAME - pj_sockaddr_in_set_port @ 248 NONAME - pj_sockaddr_in_set_str_addr @ 249 NONAME - pj_sockaddr_init @ 250 NONAME - pj_sockaddr_print @ 251 NONAME - pj_sockaddr_set_port @ 252 NONAME - pj_sockaddr_set_str_addr @ 253 NONAME - pj_srand @ 254 NONAME - pj_str @ 255 NONAME - pj_strassign @ 256 NONAME - pj_strcat @ 257 NONAME - pj_strcat2 @ 258 NONAME - pj_strcmp @ 259 NONAME - pj_strcmp2 @ 260 NONAME - pj_strcpy @ 261 NONAME - pj_strcpy2 @ 262 NONAME - pj_strdup @ 263 NONAME - pj_strdup2 @ 264 NONAME - pj_strdup2_with_null @ 265 NONAME - pj_strdup3 @ 266 NONAME - pj_strdup_with_null @ 267 NONAME - pj_strerror @ 268 NONAME - pj_stricmp @ 269 NONAME - pj_stricmp2 @ 270 NONAME - pj_strltrim @ 271 NONAME - pj_strncmp @ 272 NONAME - pj_strncmp2 @ 273 NONAME - pj_strncpy @ 274 NONAME - pj_strncpy_with_null @ 275 NONAME - pj_strnicmp @ 276 NONAME - pj_strnicmp2 @ 277 NONAME - pj_strrtrim @ 278 NONAME - pj_strtoul @ 279 NONAME - pj_strtoul2 @ 280 NONAME - pj_strtrim @ 281 NONAME - pj_symbianos_poll @ 282 NONAME - pj_symbianos_set_params @ 283 NONAME - pj_thread_check_stack @ 284 NONAME - pj_thread_create @ 285 NONAME - pj_thread_destroy @ 286 NONAME - pj_thread_get_name @ 287 NONAME - pj_thread_get_os_handle @ 288 NONAME - pj_thread_get_stack_info @ 289 NONAME - pj_thread_get_stack_max_usage @ 290 NONAME - pj_thread_is_registered @ 291 NONAME - pj_thread_join @ 292 NONAME - pj_thread_local_alloc @ 293 NONAME - pj_thread_local_free @ 294 NONAME - pj_thread_local_get @ 295 NONAME - pj_thread_local_set @ 296 NONAME - pj_thread_register @ 297 NONAME - pj_thread_resume @ 298 NONAME - pj_thread_sleep @ 299 NONAME - pj_thread_this @ 300 NONAME - pj_time_decode @ 301 NONAME - pj_time_encode @ 302 NONAME - pj_time_gmt_to_local @ 303 NONAME - pj_time_local_to_gmt @ 304 NONAME - pj_time_val_normalize @ 305 NONAME - pj_timer_entry_init @ 306 NONAME - pj_timer_heap_cancel @ 307 NONAME - pj_timer_heap_count @ 308 NONAME - pj_timer_heap_create @ 309 NONAME - pj_timer_heap_destroy @ 310 NONAME - pj_timer_heap_earliest_time @ 311 NONAME - pj_timer_heap_mem_size @ 312 NONAME - pj_timer_heap_poll @ 313 NONAME - pj_timer_heap_schedule @ 314 NONAME - pj_timer_heap_set_lock @ 315 NONAME - pj_timer_heap_set_max_timed_out_per_poll @ 316 NONAME - pj_unicode_to_ansi @ 317 NONAME - pj_utoa @ 318 NONAME - pj_utoa_pad @ 319 NONAME - platform_strerror @ 320 NONAME - snprintf @ 321 NONAME - vsnprintf @ 322 NONAME + pj_ioqueue_register_sock2 @ 132 NONAME + pj_ioqueue_send @ 133 NONAME + pj_ioqueue_sendto @ 134 NONAME + pj_ioqueue_set_lock @ 135 NONAME + pj_ioqueue_set_user_data @ 136 NONAME + pj_ioqueue_unregister @ 137 NONAME + pj_leave_critical_section @ 138 NONAME + pj_list_erase @ 139 NONAME + pj_list_find_node @ 140 NONAME + pj_list_insert_after @ 141 NONAME + pj_list_insert_before @ 142 NONAME + pj_list_insert_nodes_after @ 143 NONAME + pj_list_insert_nodes_before @ 144 NONAME + pj_list_merge_first @ 145 NONAME + pj_list_merge_last @ 146 NONAME + pj_list_search @ 147 NONAME + pj_list_size @ 148 NONAME + pj_lock_acquire @ 149 NONAME + pj_lock_create_null_mutex @ 150 NONAME + pj_lock_create_recursive_mutex @ 151 NONAME + pj_lock_create_semaphore @ 152 NONAME + pj_lock_create_simple_mutex @ 153 NONAME + pj_lock_destroy @ 154 NONAME + pj_lock_release @ 155 NONAME + pj_lock_tryacquire @ 156 NONAME + pj_log @ 157 NONAME + pj_log_1 @ 158 NONAME + pj_log_2 @ 159 NONAME + pj_log_3 @ 160 NONAME + pj_log_4 @ 161 NONAME + pj_log_5 @ 162 NONAME + pj_log_get_decor @ 163 NONAME + pj_log_get_level @ 164 NONAME + pj_log_get_log_func @ 165 NONAME + pj_log_set_decor @ 166 NONAME + pj_log_set_level @ 167 NONAME + pj_log_set_log_func @ 168 NONAME + pj_log_write @ 169 NONAME + pj_mutex_create @ 170 NONAME + pj_mutex_create_recursive @ 171 NONAME + pj_mutex_create_simple @ 172 NONAME + pj_mutex_destroy @ 173 NONAME + pj_mutex_lock @ 174 NONAME + pj_mutex_trylock @ 175 NONAME + pj_mutex_unlock @ 176 NONAME + pj_ntohl @ 177 NONAME + pj_ntohs @ 178 NONAME + pj_pool_alloc @ 179 NONAME + pj_pool_alloc_from_block @ 180 NONAME + pj_pool_allocate_find @ 181 NONAME + pj_pool_calloc @ 182 NONAME + pj_pool_create @ 183 NONAME + pj_pool_create_int @ 184 NONAME + pj_pool_create_on_buf @ 185 NONAME + pj_pool_destroy_int @ 186 NONAME + pj_pool_factory_default_policy @ 187 NONAME + pj_pool_factory_get_default_policy @ 188 NONAME + pj_pool_get_capacity @ 189 NONAME + pj_pool_get_used_size @ 190 NONAME + pj_pool_getobjname @ 191 NONAME + pj_pool_init_int @ 192 NONAME + pj_pool_release @ 193 NONAME + pj_pool_reset @ 194 NONAME + pj_rand @ 195 NONAME + pj_rbtree_erase @ 196 NONAME + pj_rbtree_find @ 197 NONAME + pj_rbtree_first @ 198 NONAME + pj_rbtree_init @ 199 NONAME + pj_rbtree_insert @ 200 NONAME + pj_rbtree_last @ 201 NONAME + pj_rbtree_max_height @ 202 NONAME + pj_rbtree_min_height @ 203 NONAME + pj_rbtree_next @ 204 NONAME + pj_rbtree_prev @ 205 NONAME + pj_register_strerror @ 206 NONAME + pj_rwmutex_create @ 207 NONAME + pj_rwmutex_destroy @ 208 NONAME + pj_rwmutex_lock_read @ 209 NONAME + pj_rwmutex_lock_write @ 210 NONAME + pj_rwmutex_unlock_read @ 211 NONAME + pj_rwmutex_unlock_write @ 212 NONAME + pj_sem_create @ 213 NONAME + pj_sem_destroy @ 214 NONAME + pj_sem_post @ 215 NONAME + pj_sem_trywait @ 216 NONAME + pj_sem_wait @ 217 NONAME + pj_set_netos_error @ 218 NONAME + pj_set_os_error @ 219 NONAME + pj_shutdown @ 220 NONAME + pj_sock_accept @ 221 NONAME + pj_sock_bind @ 222 NONAME + pj_sock_bind_in @ 223 NONAME + pj_sock_close @ 224 NONAME + pj_sock_connect @ 225 NONAME + pj_sock_getpeername @ 226 NONAME + pj_sock_getsockname @ 227 NONAME + pj_sock_getsockopt @ 228 NONAME + pj_sock_listen @ 229 NONAME + pj_sock_recv @ 230 NONAME + pj_sock_recvfrom @ 231 NONAME + pj_sock_select @ 232 NONAME + pj_sock_send @ 233 NONAME + pj_sock_sendto @ 234 NONAME + pj_sock_setsockopt @ 235 NONAME + pj_sock_shutdown @ 236 NONAME + pj_sock_socket @ 237 NONAME + pj_sockaddr_cmp @ 238 NONAME + pj_sockaddr_copy_addr @ 239 NONAME + pj_sockaddr_get_addr @ 240 NONAME + pj_sockaddr_get_addr_len @ 241 NONAME + pj_sockaddr_get_len @ 242 NONAME + pj_sockaddr_get_port @ 243 NONAME + pj_sockaddr_has_addr @ 244 NONAME + pj_sockaddr_in_get_addr @ 245 NONAME + pj_sockaddr_in_get_port @ 246 NONAME + pj_sockaddr_in_init @ 247 NONAME + pj_sockaddr_in_set_addr @ 248 NONAME + pj_sockaddr_in_set_port @ 249 NONAME + pj_sockaddr_in_set_str_addr @ 250 NONAME + pj_sockaddr_init @ 251 NONAME + pj_sockaddr_print @ 252 NONAME + pj_sockaddr_set_port @ 253 NONAME + pj_sockaddr_set_str_addr @ 254 NONAME + pj_srand @ 255 NONAME + pj_str @ 256 NONAME + pj_strassign @ 257 NONAME + pj_strcat @ 258 NONAME + pj_strcat2 @ 259 NONAME + pj_strcmp @ 260 NONAME + pj_strcmp2 @ 261 NONAME + pj_strcpy @ 262 NONAME + pj_strcpy2 @ 263 NONAME + pj_strdup @ 264 NONAME + pj_strdup2 @ 265 NONAME + pj_strdup2_with_null @ 266 NONAME + pj_strdup3 @ 267 NONAME + pj_strdup_with_null @ 268 NONAME + pj_strerror @ 269 NONAME + pj_stricmp @ 270 NONAME + pj_stricmp2 @ 271 NONAME + pj_strltrim @ 272 NONAME + pj_strncmp @ 273 NONAME + pj_strncmp2 @ 274 NONAME + pj_strncpy @ 275 NONAME + pj_strncpy_with_null @ 276 NONAME + pj_strnicmp @ 277 NONAME + pj_strnicmp2 @ 278 NONAME + pj_strrtrim @ 279 NONAME + pj_strtoul @ 280 NONAME + pj_strtoul2 @ 281 NONAME + pj_strtrim @ 282 NONAME + pj_symbianos_poll @ 283 NONAME + pj_symbianos_set_params @ 284 NONAME + pj_thread_check_stack @ 285 NONAME + pj_thread_create @ 286 NONAME + pj_thread_destroy @ 287 NONAME + pj_thread_get_name @ 288 NONAME + pj_thread_get_os_handle @ 289 NONAME + pj_thread_get_stack_info @ 290 NONAME + pj_thread_get_stack_max_usage @ 291 NONAME + pj_thread_is_registered @ 292 NONAME + pj_thread_join @ 293 NONAME + pj_thread_local_alloc @ 294 NONAME + pj_thread_local_free @ 295 NONAME + pj_thread_local_get @ 296 NONAME + pj_thread_local_set @ 297 NONAME + pj_thread_register @ 298 NONAME + pj_thread_resume @ 299 NONAME + pj_thread_sleep @ 300 NONAME + pj_thread_this @ 301 NONAME + pj_time_decode @ 302 NONAME + pj_time_encode @ 303 NONAME + pj_time_gmt_to_local @ 304 NONAME + pj_time_local_to_gmt @ 305 NONAME + pj_time_val_normalize @ 306 NONAME + pj_timer_entry_init @ 307 NONAME + pj_timer_heap_cancel @ 308 NONAME + pj_timer_heap_cancel_if_active @ 309 NONAME + pj_timer_heap_count @ 310 NONAME + pj_timer_heap_create @ 311 NONAME + pj_timer_heap_destroy @ 312 NONAME + pj_timer_heap_earliest_time @ 313 NONAME + pj_timer_heap_mem_size @ 314 NONAME + pj_timer_heap_poll @ 315 NONAME + pj_timer_heap_schedule @ 316 NONAME + pj_timer_heap_schedule_w_grp_lock @ 317 NONAME + pj_timer_heap_set_lock @ 318 NONAME + pj_timer_heap_set_max_timed_out_per_poll @ 319 NONAME + pj_unicode_to_ansi @ 320 NONAME + pj_utoa @ 321 NONAME + pj_utoa_pad @ 322 NONAME + platform_strerror @ 323 NONAME + snprintf @ 324 NONAME + vsnprintf @ 325 NONAME \ No newline at end of file diff --git a/configure-bb10 b/configure-bb10 index 4d1a5dd..e29f52f 100755 --- a/configure-bb10 +++ b/configure-bb10 @@ -32,7 +32,7 @@ RANLIB="${QNX_HOST}/usr/bin/nto${TARGET_ARCH}-ranlib " CPP="${QNX_HOST}/usr/bin/qcc -V4.6.3,gcc_nto${TARGET_ARCHEND}_cpp -E " CC="${QNX_HOST}/usr/bin/qcc -V4.6.3,gcc_nto${TARGET_ARCHEND}_cpp " LD="${QNX_HOST}/usr/bin/nto${TARGET_ARCH}-ld " -export LDFLAGS=" -L${QNX_TARGET}/${LIBDIR}/usr/lib -L${QNX_TARGET}/${LIBDIR}/lib -L${QNX_HOST}/usr/lib/gcc/${TARGET_HOST}/4.6.3 -lgcc -lasound " +export LDFLAGS=" -L${QNX_TARGET}/${LIBDIR}/usr/lib -L${QNX_TARGET}/${LIBDIR}/lib -L${QNX_HOST}/usr/lib/gcc/${TARGET_HOST}/4.6.3 -lgcc -lasound -laudio_manager" export CFLAGS=" -g -fPIC -DPJMEDIA_AUDIO_DEV_HAS_BB10=1 " ./configure --host=${TARGET_HOST} --disable-oss $* diff --git a/configure-iphone b/configure-iphone index 742dce0..79bf226 100755 --- a/configure-iphone +++ b/configure-iphone @@ -133,7 +133,7 @@ if test "1" = "1"; then fi # And finally invoke the configure script itself -./aconfigure --host=arm-apple-darwin9 --disable-floating-point --disable-sdl $* +./aconfigure --host=arm-apple-darwin9 --disable-sdl $* if test "$?" = "0"; then echo "Done configuring for `basename $SDKPATH`" diff --git a/pjlib-util/build/Makefile b/pjlib-util/build/Makefile index fba93bb..d2ad65a 100644 --- a/pjlib-util/build/Makefile +++ b/pjlib-util/build/Makefile @@ -74,7 +74,7 @@ distclean: realclean pjlib-util: $(MAKE) -f $(RULES_MAK) APP=PJLIB_UTIL app=pjlib-util $(PJLIB_UTIL_LIB) -pjlib-util-test: +pjlib-util-test: pjlib-util $(MAKE) -f $(RULES_MAK) APP=UTIL_TEST app=pjlib-util-test $(UTIL_TEST_EXE) .PHONY: ../lib/pjlib-util.ko diff --git a/pjlib-util/include/pjlib-util/stun_simple.h b/pjlib-util/include/pjlib-util/stun_simple.h index 3d10379..a0b1b69 100644 --- a/pjlib-util/include/pjlib-util/stun_simple.h +++ b/pjlib-util/include/pjlib-util/stun_simple.h @@ -1,4 +1,4 @@ -/* $Id: stun_simple.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: stun_simple.h 4224 2012-08-09 05:21:25Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -199,6 +199,81 @@ PJ_DECL(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, const pj_str_t *srv2, int port2, pj_sockaddr_in mapped_addr[]); + +/* + * This structre describes configurable setting for requesting mapped address. + */ +typedef struct pjstun_setting +{ + /** + * Specifies whether STUN request generated by old STUN library should + * insert magic cookie (specified in RFC 5389) in the transaction ID. + */ + pj_bool_t use_stun2; + + /** + * Host name or IP address string of the first STUN server. + */ + pj_str_t srv1; + + /** + * The port number of the first STUN server. + */ + int port1; + + /** + * Host name or IP address string of the second STUN server. + */ + pj_str_t srv2; + + /** + * The port number of the second STUN server. + */ + int port2; + +} pjstun_setting; + + +/** + * Another version of mapped address resolution of local sockets to multiple + * STUN servers configured in #pjstun_setting. This function is able to find + * the mapped addresses of multiple sockets simultaneously, and for each + * socket, two requests will be sent to two different STUN servers to see if + * both servers get the same public address for the same socket. (Note that + * application can specify the same address for the two servers, but still + * two requests will be sent for each server). + * + * This function will perform necessary retransmissions of the requests if + * response is not received within a predetermined period. When all responses + * have been received, the function will compare the mapped addresses returned + * by the servers, and when both are equal, the address will be returned in + * \a mapped_addr argument. + * + * @param pf The pool factory where memory will be allocated from. + * @param opt The STUN settings. + * @param sock_cnt Number of sockets in the socket array. + * @param sock Array of local UDP sockets which public addresses are + * to be queried from the STUN servers. + * @param mapped_addr Array to receive the mapped public address of the local + * UDP sockets, when the function returns PJ_SUCCESS. + * + * @return This functions returns PJ_SUCCESS if responses are + * received from all servers AND all servers returned the + * same mapped public address. Otherwise this function may + * return one of the following error codes: + * - PJLIB_UTIL_ESTUNNOTRESPOND: no respons from servers. + * - PJLIB_UTIL_ESTUNSYMMETRIC: different mapped addresses + * are returned by servers. + * - etc. + * + */ +PJ_DECL(pj_status_t) pjstun_get_mapped_addr2( pj_pool_factory *pf, + const pjstun_setting *opt, + int sock_cnt, + pj_sock_t sock[], + pj_sockaddr_in mapped_addr[]); + + PJ_END_DECL /** diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c index 4be5350..25c6067 100644 --- a/pjlib-util/src/pjlib-util/resolver.c +++ b/pjlib-util/src/pjlib-util/resolver.c @@ -1,4 +1,4 @@ -/* $Id: resolver.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: resolver.c 4333 2013-01-23 09:53:39Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -180,7 +180,8 @@ struct pj_dns_resolver unsigned char udp_rx_pkt[UDPSZ];/**< UDP receive buffer. */ unsigned char udp_tx_pkt[UDPSZ];/**< UDP receive buffer. */ pj_ssize_t udp_len; /**< Length of received packet. */ - pj_ioqueue_op_key_t udp_op_key; /**< UDP read operation key. */ + pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */ + pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */ pj_sockaddr_in udp_src_addr; /**< Source address of packet */ int udp_addr_len; /**< Source address length. */ @@ -223,6 +224,63 @@ static pj_status_t select_nameservers(pj_dns_resolver *resolver, unsigned servers[]); +/* Close UDP socket */ +static void close_sock(pj_dns_resolver *resv) +{ + /* Close existing socket */ + if (resv->udp_key != NULL) { + pj_ioqueue_unregister(resv->udp_key); + resv->udp_key = NULL; + resv->udp_sock = PJ_INVALID_SOCKET; + } else if (resv->udp_sock != PJ_INVALID_SOCKET) { + pj_sock_close(resv->udp_sock); + resv->udp_sock = PJ_INVALID_SOCKET; + } +} + + +/* Initialize UDP socket */ +static pj_status_t init_sock(pj_dns_resolver *resv) +{ + pj_ioqueue_callback socket_cb; + pj_status_t status; + + /* Create the UDP socket */ + status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock); + if (status != PJ_SUCCESS) + return status; + + /* Bind to any address/port */ + status = pj_sock_bind_in(resv->udp_sock, 0, 0); + if (status != PJ_SUCCESS) + return status; + + /* Register to ioqueue */ + pj_bzero(&socket_cb, sizeof(socket_cb)); + socket_cb.on_read_complete = &on_read_complete; + status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue, + resv->udp_sock, resv, &socket_cb, + &resv->udp_key); + if (status != PJ_SUCCESS) + return status; + + pj_ioqueue_op_key_init(&resv->udp_op_rx_key, sizeof(resv->udp_op_rx_key)); + pj_ioqueue_op_key_init(&resv->udp_op_tx_key, sizeof(resv->udp_op_tx_key)); + + /* Start asynchronous read to the UDP socket */ + resv->udp_len = sizeof(resv->udp_rx_pkt); + resv->udp_addr_len = sizeof(resv->udp_src_addr); + status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key, + resv->udp_rx_pkt, &resv->udp_len, + PJ_IOQUEUE_ALWAYS_ASYNC, + &resv->udp_src_addr, &resv->udp_addr_len); + if (status != PJ_EPENDING) + return status; + + return PJ_SUCCESS; +} + + /* Initialize DNS settings with default values */ PJ_DEF(void) pj_dns_settings_default(pj_dns_settings *s) { @@ -247,7 +305,6 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf, { pj_pool_t *pool; pj_dns_resolver *resv; - pj_ioqueue_callback socket_cb; pj_status_t status; /* Sanity check */ @@ -302,37 +359,11 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf, resv->hquerybyres = pj_hash_create(pool, Q_HASH_TABLE_SIZE); pj_list_init(&resv->query_free_nodes); - /* Create the UDP socket */ - status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock); - if (status != PJ_SUCCESS) - goto on_error; - - /* Bind to any address/port */ - status = pj_sock_bind_in(resv->udp_sock, 0, 0); + /* Initialize the UDP socket */ + status = init_sock(resv); if (status != PJ_SUCCESS) goto on_error; - /* Register to ioqueue */ - pj_bzero(&socket_cb, sizeof(socket_cb)); - socket_cb.on_read_complete = &on_read_complete; - status = pj_ioqueue_register_sock(pool, resv->ioqueue, resv->udp_sock, - resv, &socket_cb, &resv->udp_key); - if (status != PJ_SUCCESS) - goto on_error; - - pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key)); - - /* Start asynchronous read to the UDP socket */ - resv->udp_len = sizeof(resv->udp_rx_pkt); - resv->udp_addr_len = sizeof(resv->udp_src_addr); - status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key, - resv->udp_rx_pkt, &resv->udp_len, - PJ_IOQUEUE_ALWAYS_ASYNC, - &resv->udp_src_addr, &resv->udp_addr_len); - if (status != PJ_EPENDING) - goto on_error; - - /* Looks like everything is okay */ *p_resolver = resv; return PJ_SUCCESS; @@ -392,14 +423,7 @@ PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver, resolver->timer = NULL; } - if (resolver->udp_key != NULL) { - pj_ioqueue_unregister(resolver->udp_key); - resolver->udp_key = NULL; - resolver->udp_sock = PJ_INVALID_SOCKET; - } else if (resolver->udp_sock != PJ_INVALID_SOCKET) { - pj_sock_close(resolver->udp_sock); - resolver->udp_sock = PJ_INVALID_SOCKET; - } + close_sock(resolver); if (resolver->own_ioqueue && resolver->ioqueue) { pj_ioqueue_destroy(resolver->ioqueue); @@ -561,15 +585,6 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver, pj_time_val delay; pj_status_t status; - /* Create DNS query packet */ - pkt_size = sizeof(resolver->udp_tx_pkt); - name = pj_str(q->key.name); - status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size, - q->id, q->key.qtype, &name); - if (status != PJ_SUCCESS) { - return status; - } - /* Select which nameserver(s) to send requests to. */ server_cnt = PJ_ARRAY_SIZE(servers); status = select_nameservers(resolver, &server_cnt, servers); @@ -595,6 +610,28 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver, return status; } + /* Check if the socket is available for sending */ + if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) { + ++q->transmit_cnt; + PJ_LOG(4,(resolver->name.ptr, + "Socket busy in transmitting DNS %s query for %s%s", + pj_dns_get_type_name(q->key.qtype), + q->key.name, + (q->transmit_cnt < resolver->settings.qretr_count? + ", will try again later":""))); + return PJ_SUCCESS; + } + + /* Create DNS query packet */ + pkt_size = sizeof(resolver->udp_tx_pkt); + name = pj_str(q->key.name); + status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size, + q->id, q->key.qtype, &name); + if (status != PJ_SUCCESS) { + pj_timer_heap_cancel(resolver->timer, &q->timer_entry); + return status; + } + /* Get current time. */ pj_gettimeofday(&now); @@ -603,13 +640,16 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver, pj_ssize_t sent = (pj_ssize_t) pkt_size; struct nameserver *ns = &resolver->ns[servers[i]]; - pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, &sent, 0, - &resolver->ns[servers[i]].addr, sizeof(pj_sockaddr_in)); + status = pj_ioqueue_sendto(resolver->udp_key, + &resolver->udp_op_tx_key, + resolver->udp_tx_pkt, &sent, 0, + &resolver->ns[servers[i]].addr, + sizeof(pj_sockaddr_in)); - PJ_LOG(4,(resolver->name.ptr, + PJ_PERROR(4,(resolver->name.ptr, status, "%s %d bytes to NS %d (%s:%d): DNS %s query for %s", (q->transmit_cnt==0? "Transmitting":"Re-transmitting"), - (int)sent, servers[i], + (int)pkt_size, servers[i], pj_inet_ntoa(ns->addr.sin_addr), (int)pj_ntohs(ns->addr.sin_port), pj_dns_get_type_name(q->key.qtype), @@ -1248,6 +1288,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap, pj_hash_set(NULL, resolver->hquerybyid, &q->id, sizeof(q->id), 0, NULL); pj_hash_set(NULL, resolver->hquerybyres, &q->key, sizeof(q->key), 0, NULL); + /* Workaround for deadlock problem in #1565 (similar to #1108) */ + pj_mutex_unlock(resolver->mutex); + /* Call application callback, if any. */ if (q->cb) (*q->cb)(q->user_data, PJ_ETIMEDOUT, NULL); @@ -1260,6 +1303,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap, cq = cq->next; } + /* Workaround for deadlock problem in #1565 (similar to #1108) */ + pj_mutex_lock(resolver->mutex); + /* Clear data */ q->timer_entry.id = 0; q->user_data = NULL; diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c index d8e1c8e..ba1152e 100644 --- a/pjlib-util/src/pjlib-util/scanner.c +++ b/pjlib-util/src/pjlib-util/scanner.c @@ -1,4 +1,4 @@ -/* $Id: scanner.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: scanner.c 4209 2012-07-18 10:21:00Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -393,7 +393,6 @@ PJ_DEF(void) pj_scan_get_quotes(pj_scanner *scanner, } /* break from main loop if we have odd number of backslashes */ if (((unsigned)(q-r) & 0x01) == 1) { - ++s; break; } ++s; diff --git a/pjlib-util/src/pjlib-util/stun_simple_client.c b/pjlib-util/src/pjlib-util/stun_simple_client.c index 345d121..2a59ae1 100644 --- a/pjlib-util/src/pjlib-util/stun_simple_client.c +++ b/pjlib-util/src/pjlib-util/stun_simple_client.c @@ -1,4 +1,4 @@ -/* $Id: stun_simple_client.c 3999 2012-03-30 07:10:13Z bennylp $ */ +/* $Id: stun_simple_client.c 4297 2012-11-13 08:46:42Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -41,8 +41,28 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, const pj_str_t *srv1, int port1, const pj_str_t *srv2, int port2, pj_sockaddr_in mapped_addr[]) +{ + pjstun_setting opt; + + pj_bzero(&opt, sizeof(opt)); + opt.use_stun2 = PJ_FALSE; + opt.srv1 = *srv1; + opt.port1 = port1; + opt.srv2 = *srv2; + opt.port2 = port2; + + return pjstun_get_mapped_addr2(pf, &opt, sock_cnt, sock, mapped_addr); +} + +PJ_DEF(pj_status_t) pjstun_get_mapped_addr2(pj_pool_factory *pf, + const pjstun_setting *opt, + int sock_cnt, + pj_sock_t sock[], + pj_sockaddr_in mapped_addr[]) { unsigned srv_cnt; + const pj_str_t *srv1, *srv2; + int port1, port2; pj_sockaddr_in srv_addr[2]; int i, send_cnt = 0, nfds; pj_pool_t *pool; @@ -59,6 +79,11 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, PJ_CHECK_STACK(); + srv1 = &opt->srv1; + port1 = opt->port1; + srv2 = &opt->srv1; + port2 = opt->port2; + TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()")); /* Create pool. */ @@ -82,6 +107,12 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, if (status != PJ_SUCCESS) goto on_error; + /* Insert magic cookie (specified in RFC 5389) when requested to. */ + if (opt->use_stun2) { + pjstun_msg_hdr *hdr = (pjstun_msg_hdr*)out_msg; + hdr->tsx[0] = pj_htonl(STUN_MAGIC); + } + TRACE_((THIS_FILE, " Binding request created.")); /* Resolve servers. */ @@ -162,15 +193,15 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, TRACE_((THIS_FILE, " Request(s) sent, counter=%d", send_cnt)); /* Calculate time of next retransmission. */ - pj_gettimeofday(&next_tx); + pj_gettickcount(&next_tx); next_tx.sec += (stun_timer[send_cnt]/1000); next_tx.msec += (stun_timer[send_cnt]%1000); pj_time_val_normalize(&next_tx); - for (pj_gettimeofday(&now), select_rc=1; + for (pj_gettickcount(&now), select_rc=1; status==PJ_SUCCESS && select_rc>=1 && wait_resp>0 && PJ_TIME_VAL_LT(now, next_tx); - pj_gettimeofday(&now)) + pj_gettickcount(&now)) { pj_time_val timeout; diff --git a/pjlib/build/Makefile b/pjlib/build/Makefile index 9183644..a36f5f4 100644 --- a/pjlib/build/Makefile +++ b/pjlib/build/Makefile @@ -87,7 +87,7 @@ pjlib: ../include/pj/config_site.h ../include/pj/config_site.h: touch ../include/pj/config_site.h -pjlib-test: +pjlib-test: pjlib $(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test $(TEST_EXE) .PHONY: ../lib/pjlib.ko diff --git a/pjlib/include/pj/activesock.h b/pjlib/include/pj/activesock.h index 0c30c01..6d3b0d0 100644 --- a/pjlib/include/pj/activesock.h +++ b/pjlib/include/pj/activesock.h @@ -1,4 +1,4 @@ -/* $Id: activesock.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: activesock.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -173,6 +173,11 @@ typedef struct pj_activesock_cb */ typedef struct pj_activesock_cfg { + /** + * Optional group lock to be assigned to the ioqueue key. + */ + pj_grp_lock_t *grp_lock; + /** * Number of concurrent asynchronous operations that is to be supported * by the active socket. This value only affects socket receive and @@ -290,7 +295,6 @@ PJ_DECL(pj_status_t) pj_activesock_create_udp(pj_pool_t *pool, pj_activesock_t **p_asock, pj_sockaddr *bound_addr); - /** * Close the active socket. This will unregister the socket from the * ioqueue and ultimately close the socket. @@ -548,6 +552,7 @@ PJ_DECL(pj_status_t) pj_activesock_start_connect(pj_activesock_t *asock, const pj_sockaddr_t *remaddr, int addr_len); + #endif /* PJ_HAS_TCP */ /** diff --git a/pjlib/include/pj/addr_resolv.h b/pjlib/include/pj/addr_resolv.h index ae10337..41eacc8 100644 --- a/pjlib/include/pj/addr_resolv.h +++ b/pjlib/include/pj/addr_resolv.h @@ -1,4 +1,4 @@ -/* $Id: addr_resolv.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: addr_resolv.h 4218 2012-08-07 02:18:15Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -116,6 +116,31 @@ PJ_DECL(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he); PJ_DECL(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr); +/** + * Get the interface IP address to send data to the specified destination. + * + * @param af The desired address family to query. Valid values + * are pj_AF_INET() or pj_AF_INET6(). + * @param dst The destination host. + * @param itf_addr On successful resolution, the address family and address + * part of this socket address will be filled up with the host + * IP address, in network byte order. Other parts of the socket + * address should be ignored. + * @param allow_resolve If \a dst may contain hostname (instead of IP + * address), specify whether hostname resolution should + * be performed. If not, default interface address will + * be returned. + * @param p_dst_addr If not NULL, it will be filled with the IP address of + * the destination host. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_getipinterface(int af, + const pj_str_t *dst, + pj_sockaddr *itf_addr, + pj_bool_t allow_resolve, + pj_sockaddr *p_dst_addr); + /** * Get the IP address of the default interface. Default interface is the * interface of the default route. diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h index 629fa44..120e6ce 100644 --- a/pjlib/include/pj/config.h +++ b/pjlib/include/pj/config.h @@ -1,4 +1,4 @@ -/* $Id: config.h 4189 2012-07-03 03:11:24Z ming $ */ +/* $Id: config.h 4415 2013-03-05 08:34:45Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -487,6 +487,14 @@ #endif +/** + * Set this to 1 to enable debugging on the group lock. Default: 0 + */ +#ifndef PJ_GRP_LOCK_DEBUG +# define PJ_GRP_LOCK_DEBUG 0 +#endif + + /** * Specify this as \a stack_size argument in #pj_thread_create() to specify * that thread should use default stack size for the current platform. @@ -1121,6 +1129,14 @@ # define PJ_TODO(id) TODO___##id: #endif +/** + * Simulate race condition by sleeping the thread in strategic locations. + * Default: no! + */ +#ifndef PJ_RACE_ME +# define PJ_RACE_ME(x) +#endif + /** * Function attributes to inform that the function may throw exception. * @@ -1167,10 +1183,10 @@ PJ_BEGIN_DECL #define PJ_VERSION_NUM_MAJOR 2 /** PJLIB version minor number. */ -#define PJ_VERSION_NUM_MINOR 0 +#define PJ_VERSION_NUM_MINOR 1 /** PJLIB version revision number. */ -#define PJ_VERSION_NUM_REV 1 +#define PJ_VERSION_NUM_REV 0 /** * Extra suffix for the version (e.g. "-trunk"), or empty for diff --git a/pjlib/include/pj/config_site_sample.h b/pjlib/include/pj/config_site_sample.h index 0c7832f..845d1bb 100644 --- a/pjlib/include/pj/config_site_sample.h +++ b/pjlib/include/pj/config_site_sample.h @@ -302,8 +302,10 @@ * PJLIB settings. */ - /* Disable floating point support */ - #define PJ_HAS_FLOATING_POINT 0 + /* Both armv6 and armv7 has FP hardware support. + * See https://trac.pjsip.org/repos/ticket/1589 for more info + */ + #define PJ_HAS_FLOATING_POINT 1 /* * PJMEDIA settings diff --git a/pjlib/include/pj/errno.h b/pjlib/include/pj/errno.h index 98a735a..75aadbe 100644 --- a/pjlib/include/pj/errno.h +++ b/pjlib/include/pj/errno.h @@ -1,4 +1,4 @@ -/* $Id: errno.h 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: errno.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -422,6 +422,11 @@ PJ_DECL(pj_status_t) pj_register_strerror(pj_status_t start_code, * Unsupported address family */ #define PJ_EAFNOTSUP (PJ_ERRNO_START_STATUS + 22)/* 70022 */ +/** + * @hideinitializer + * Object no longer exists + */ +#define PJ_EGONE (PJ_ERRNO_START_STATUS + 23)/* 70023 */ /** @} */ /* pj_errnum */ diff --git a/pjlib/include/pj/guid.h b/pjlib/include/pj/guid.h index 991ce53..2a76af6 100644 --- a/pjlib/include/pj/guid.h +++ b/pjlib/include/pj/guid.h @@ -1,4 +1,4 @@ -/* $Id: guid.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: guid.h 4208 2012-07-18 07:52:33Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -82,6 +82,17 @@ PJ_DECL(unsigned) pj_GUID_STRING_LENGTH(void); */ PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str); +/** + * Create a globally unique string in lowercase, which length is + * PJ_GUID_STRING_LENGTH characters. Caller is responsible for preallocating + * the storage used in the string. + * + * @param str The string to store the result. + * + * @return The string. + */ +PJ_DECL(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str); + /** * Generate a unique string. * @@ -90,6 +101,14 @@ PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str); */ PJ_DECL(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str); +/** + * Generate a unique string in lowercase. + * + * @param pool Pool to allocate memory from. + * @param str The string. + */ +PJ_DECL(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str); + /** * @} diff --git a/pjlib/include/pj/hash.h b/pjlib/include/pj/hash.h index 75b46c1..5d9a2d9 100644 --- a/pjlib/include/pj/hash.h +++ b/pjlib/include/pj/hash.h @@ -1,4 +1,4 @@ -/* $Id: hash.h 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: hash.h 4208 2012-07-18 07:52:33Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -75,8 +75,8 @@ PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval, * string is stored in \c result. * * @param hval The initial hash value, normally zero. - * @param result Buffer to store the result, which must be enough to hold - * the string. + * @param result Optional. Buffer to store the result, which must be enough + * to hold the string. * @param key The input key to be converted and calculated. * * @return The hash value. @@ -115,6 +115,17 @@ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht, pj_uint32_t *hval ); +/** + * Variant of #pj_hash_get() with the key being converted to lowercase when + * calculating the hash value. + * + * @see pj_hash_get() + */ +PJ_DECL(void *) pj_hash_get_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t *hval ); + + /** * Associate/disassociate a value with the specified key. If value is not * NULL and entry already exists, the entry's value will be overwritten. @@ -141,6 +152,17 @@ PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, void *value ); +/** + * Variant of #pj_hash_set() with the key being converted to lowercase when + * calculating the hash value. + * + * @see pj_hash_set() + */ +PJ_DECL(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *value ); + + /** * Associate/disassociate a value with the specified key. This function works * like #pj_hash_set(), except that it doesn't use pool (hence the np -- no @@ -164,6 +186,18 @@ PJ_DECL(void) pj_hash_set_np(pj_hash_table_t *ht, pj_uint32_t hval, pj_hash_entry_buf entry_buf, void *value); +/** + * Variant of #pj_hash_set_np() with the key being converted to lowercase + * when calculating the hash value. + * + * @see pj_hash_set_np() + */ +PJ_DECL(void) pj_hash_set_np_lower(pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, + pj_hash_entry_buf entry_buf, + void *value); + /** * Get the total number of entries in the hash table. * diff --git a/pjlib/include/pj/ioqueue.h b/pjlib/include/pj/ioqueue.h index 068e7ba..853bf48 100644 --- a/pjlib/include/pj/ioqueue.h +++ b/pjlib/include/pj/ioqueue.h @@ -1,4 +1,4 @@ -/* $Id: ioqueue.h 3553 2011-05-05 06:14:19Z nanang $ +/* $Id: ioqueue.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) @@ -404,6 +404,19 @@ PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, const pj_ioqueue_callback *cb, pj_ioqueue_key_t **key ); +/** + * Variant of pj_ioqueue_register_sock() with additional group lock parameter. + * If group lock is set for the key, the key will add the reference counter + * when the socket is registered and decrease it when it is destroyed. + */ +PJ_DECL(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool, + pj_ioqueue_t *ioque, + pj_sock_t sock, + pj_grp_lock_t *grp_lock, + void *user_data, + const pj_ioqueue_callback *cb, + pj_ioqueue_key_t **key ); + /** * Unregister from the I/O Queue framework. Caller must make sure that * the key doesn't have any pending operations before calling this function, diff --git a/pjlib/include/pj/lock.h b/pjlib/include/pj/lock.h index f0d3bc5..e9b26c7 100644 --- a/pjlib/include/pj/lock.h +++ b/pjlib/include/pj/lock.h @@ -1,4 +1,4 @@ -/* $Id: lock.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: lock.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -147,6 +147,258 @@ PJ_DECL(pj_status_t) pj_lock_destroy( pj_lock_t *lock ); /** @} */ + +/** + * @defgroup PJ_GRP_LOCK Group Lock + * @ingroup PJ_LOCK + * @{ + * + * Group lock is a synchronization object to manage concurrency among members + * within the same logical group. Example of such groups are: + * + * - dialog, which has members such as the dialog itself, an invite session, + * and several transactions + * - ICE, which has members such as ICE stream transport, ICE session, STUN + * socket, TURN socket, and down to ioqueue key + * + * Group lock has three functions: + * + * - mutual exclusion: to protect resources from being accessed by more than + * one threads at the same time + * - session management: to make sure that the resource is not destroyed + * while others are still using or about to use it. + * - lock coordinator: to provide uniform lock ordering among more than one + * lock objects, which is necessary to avoid deadlock. + * + * The requirements of the group lock are: + * + * - must satisfy all the functions above + * - must allow members to join or leave the group (for example, + * transaction may be added or removed from a dialog) + * - must be able to synchronize with external lock (for example, a dialog + * lock must be able to sync itself with PJSUA lock) + * + * Please see https://trac.pjsip.org/repos/wiki/Group_Lock for more info. + */ + +/** + * Settings for creating the group lock. + */ +typedef struct pj_grp_lock_config +{ + /** + * Creation flags, currently must be zero. + */ + unsigned flags; + +} pj_grp_lock_config; + + +/** + * Initialize the config with the default values. + * + * @param cfg The config to be initialized. + */ +PJ_DECL(void) pj_grp_lock_config_default(pj_grp_lock_config *cfg); + +/** + * Create a group lock object. Initially the group lock will have reference + * counter of one. + * + * @param pool The group lock only uses the pool parameter to get + * the pool factory, from which it will create its own + * pool. + * @param cfg Optional configuration. + * @param p_grp_lock Pointer to receive the newly created group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_create(pj_pool_t *pool, + const pj_grp_lock_config *cfg, + pj_grp_lock_t **p_grp_lock); + +/** + * Forcibly destroy the group lock, ignoring the reference counter value. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_destroy( pj_grp_lock_t *grp_lock); + +/** + * Move the contents of the old lock to the new lock and destroy the + * old lock. + * + * @param old_lock The old group lock to be destroyed. + * @param new_lock The new group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_replace(pj_grp_lock_t *old_lock, + pj_grp_lock_t *new_lock); + +/** + * Acquire lock on the specified group lock. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_acquire( pj_grp_lock_t *grp_lock); + +/** + * Acquire lock on the specified group lock if it is available, otherwise + * return immediately wihout waiting. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_tryacquire( pj_grp_lock_t *grp_lock); + +/** + * Release the previously held lock. This may cause the group lock + * to be destroyed if it is the last one to hold the reference counter. + * In that case, the function will return PJ_EGONE. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_release( pj_grp_lock_t *grp_lock); + +/** + * Add a destructor handler, to be called by the group lock when it is + * about to be destroyed. + * + * @param grp_lock The group lock. + * @param pool Pool to allocate memory for the handler. + * @param member A pointer to be passed to the handler. + * @param handler The destroy handler. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_add_handler(pj_grp_lock_t *grp_lock, + pj_pool_t *pool, + void *member, + void (*handler)(void *member)); + +/** + * Remove previously registered handler. All parameters must be the same + * as when the handler was added. + * + * @param grp_lock The group lock. + * @param member A pointer to be passed to the handler. + * @param handler The destroy handler. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_del_handler(pj_grp_lock_t *grp_lock, + void *member, + void (*handler)(void *member)); + +/** + * Increment reference counter to prevent the group lock grom being destroyed. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +#if !PJ_GRP_LOCK_DEBUG +PJ_DECL(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *grp_lock); + +#define pj_grp_lock_add_ref_dbg(grp_lock, x, y) pj_grp_lock_add_ref(grp_lock) + +#else + +#define pj_grp_lock_add_ref(g) pj_grp_lock_add_ref_dbg(g, __FILE__, __LINE__) + +PJ_DECL(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *grp_lock, + const char *file, + int line); +#endif + +/** + * Decrement the reference counter. When the counter value reaches zero, the + * group lock will be destroyed and all destructor handlers will be called. + * + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +#if !PJ_GRP_LOCK_DEBUG +PJ_DECL(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *grp_lock); + +#define pj_grp_lock_dec_ref_dbg(grp_lock, x, y) pj_grp_lock_dec_ref(grp_lock) +#else + +#define pj_grp_lock_dec_ref(g) pj_grp_lock_dec_ref_dbg(g, __FILE__, __LINE__) + +PJ_DECL(pj_status_t) pj_grp_lock_dec_ref_dbg(pj_grp_lock_t *grp_lock, + const char *file, + int line); + +#endif + +/** + * Get current reference count value. This normally is only used for + * debugging purpose. + * + * @param grp_lock The group lock. + * + * @return The reference count value. + */ +PJ_DECL(int) pj_grp_lock_get_ref(pj_grp_lock_t *grp_lock); + + +/** + * Dump group lock info for debugging purpose. If group lock debugging is + * enabled (via PJ_GRP_LOCK_DEBUG) macro, this will print the group lock + * reference counter value along with the source file and line. If + * debugging is disabled, this will only print the reference counter. + * + * @param grp_lock The group lock. + */ +PJ_DECL(void) pj_grp_lock_dump(pj_grp_lock_t *grp_lock); + + +/** + * Synchronize an external lock with the group lock, by adding it to the + * list of locks to be acquired by the group lock when the group lock is + * acquired. + * + * The ''pos'' argument specifies the lock order and also the relative + * position with regard to lock ordering against the group lock. Locks with + * lower ''pos'' value will be locked first, and those with negative value + * will be locked before the group lock (the group lock's ''pos'' value is + * zero). + * + * @param grp_lock The group lock. + * @param ext_lock The external lock + * @param pos The position. + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_chain_lock(pj_grp_lock_t *grp_lock, + pj_lock_t *ext_lock, + int pos); + +/** + * Remove an external lock from group lock's list of synchronized locks. + * + * @param grp_lock The group lock. + * @param ext_lock The external lock + * + * @return PJ_SUCCESS or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_grp_lock_unchain_lock(pj_grp_lock_t *grp_lock, + pj_lock_t *ext_lock); + + +/** @} */ + + PJ_END_DECL diff --git a/pjlib/include/pj/pool.h b/pjlib/include/pj/pool.h index 5738d4f..73c8473 100644 --- a/pjlib/include/pj/pool.h +++ b/pjlib/include/pj/pool.h @@ -1,4 +1,4 @@ -/* $Id: pool.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: pool.h 4298 2012-11-22 05:00:01Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -509,7 +509,7 @@ PJ_INLINE(void*) pj_pool_zalloc(pj_pool_t *pool, pj_size_t size) * Internal functions */ PJ_IDECL(void*) pj_pool_alloc_from_block(pj_pool_block *block, pj_size_t size); -PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size); +PJ_DECL(void*) pj_pool_allocate_find(pj_pool_t *pool, pj_size_t size); diff --git a/pjlib/include/pj/pool_i.h b/pjlib/include/pj/pool_i.h index ea4fa2d..376fd6a 100644 --- a/pjlib/include/pj/pool_i.h +++ b/pjlib/include/pj/pool_i.h @@ -1,4 +1,4 @@ -/* $Id: pool_i.h 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: pool_i.h 4298 2012-11-22 05:00:01Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -47,7 +47,7 @@ PJ_IDEF(void*) pj_pool_alloc_from_block( pj_pool_block *block, pj_size_t size ) if (size & (PJ_POOL_ALIGNMENT-1)) { size = (size + PJ_POOL_ALIGNMENT) & ~(PJ_POOL_ALIGNMENT-1); } - if ((unsigned)(block->end - block->cur) >= size) { + if ((pj_size_t)(block->end - block->cur) >= size) { void *ptr = block->cur; block->cur += size; return ptr; diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h index 2fcd896..5692d61 100644 --- a/pjlib/include/pj/sock.h +++ b/pjlib/include/pj/sock.h @@ -1,4 +1,4 @@ -/* $Id: sock.h 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: sock.h 4343 2013-02-07 09:35:34Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -1166,6 +1166,24 @@ PJ_DECL(pj_status_t) pj_sock_bind_in( pj_sock_t sockfd, pj_uint32_t addr, pj_uint16_t port); +/** + * Bind the IP socket sockfd to the given address and a random port in the + * specified range. + * + * @param sockfd The socket desriptor. + * @param addr The local address and port to bind the socket to. + * @param port_range The port range, relative the to start port number + * specified in port field in #addr. Note that if the + * port is zero, this param will be ignored. + * @param max_try Maximum retries. + * + * @return Zero on success. + */ +PJ_DECL(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd, + const pj_sockaddr_t *addr, + pj_uint16_t port_range, + pj_uint16_t max_try); + #if PJ_HAS_TCP /** * Listen for incoming connection. This function only applies to connection diff --git a/pjlib/include/pj/timer.h b/pjlib/include/pj/timer.h index 1cc11cf..a89c30b 100644 --- a/pjlib/include/pj/timer.h +++ b/pjlib/include/pj/timer.h @@ -1,4 +1,4 @@ -/* $Id: timer.h 4154 2012-06-05 10:41:17Z bennylp $ */ +/* $Id: timer.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ */ #include +#include PJ_BEGIN_DECL @@ -118,6 +119,12 @@ typedef struct pj_timer_entry */ pj_time_val _timer_value; + /** + * Internal: the group lock used by this entry, set when + * pj_timer_heap_schedule_w_lock() is used. + */ + pj_grp_lock_t *_grp_lock; + #if PJ_TIMER_DEBUG const char *src_file; int src_line; @@ -229,7 +236,46 @@ PJ_DECL(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, #endif /* PJ_TIMER_DEBUG */ /** - * Cancel a previously registered timer. + * Schedule a timer entry which will expire AFTER the specified delay, and + * increment the reference counter of the group lock while the timer entry + * is active. The group lock reference counter will automatically be released + * after the timer callback is called or when the timer is cancelled. + * + * @param ht The timer heap. + * @param entry The entry to be registered. + * @param id_val The value to be set to the "id" field of the timer entry + * once the timer is scheduled. + * @param delay The interval to expire. + * @param grp_lock The group lock. + * + * @return PJ_SUCCESS, or the appropriate error code. + */ +#if PJ_TIMER_DEBUG +# define pj_timer_heap_schedule_w_grp_lock(ht,e,d,id,g) \ + pj_timer_heap_schedule_w_grp_lock_dbg(ht,e,d,id,g,__FILE__,__LINE__) + + PJ_DECL(pj_status_t) pj_timer_heap_schedule_w_grp_lock_dbg( + pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + int id_val, + pj_grp_lock_t *grp_lock, + const char *src_file, + int src_line); +#else +PJ_DECL(pj_status_t) pj_timer_heap_schedule_w_grp_lock( + pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + int id_val, + pj_grp_lock_t *grp_lock); +#endif /* PJ_TIMER_DEBUG */ + + +/** + * Cancel a previously registered timer. This will also decrement the + * reference counter of the group lock associated with the timer entry, + * if the entry was scheduled with one. * * @param ht The timer heap. * @param entry The entry to be cancelled. @@ -240,6 +286,24 @@ PJ_DECL(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, PJ_DECL(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, pj_timer_entry *entry); +/** + * Cancel only if the previously registered timer is active. This will + * also decrement the reference counter of the group lock associated + * with the timer entry, if the entry was scheduled with one. In any + * case, set the "id" to the specified value. + * + * @param ht The timer heap. + * @param entry The entry to be cancelled. + * @param id_val Value to be set to "id" + * + * @return The number of timer cancelled, which should be one if the + * entry has really been registered, or zero if no timer was + * cancelled. + */ +PJ_DECL(int) pj_timer_heap_cancel_if_active(pj_timer_heap_t *ht, + pj_timer_entry *entry, + int id_val); + /** * Get the number of timer entries. * diff --git a/pjlib/include/pj/types.h b/pjlib/include/pj/types.h index 99c54db..a615585 100644 --- a/pjlib/include/pj/types.h +++ b/pjlib/include/pj/types.h @@ -1,4 +1,4 @@ -/* $Id: types.h 4154 2012-06-05 10:41:17Z bennylp $ */ +/* $Id: types.h 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -231,6 +231,9 @@ typedef struct pj_thread_t pj_thread_t; /** Lock object. */ typedef struct pj_lock_t pj_lock_t; +/** Group lock */ +typedef struct pj_grp_lock_t pj_grp_lock_t; + /** Mutex handle. */ typedef struct pj_mutex_t pj_mutex_t; diff --git a/pjlib/src/pj/activesock.c b/pjlib/src/pj/activesock.c index 5c91383..3eaf027 100644 --- a/pjlib/src/pj/activesock.c +++ b/pjlib/src/pj/activesock.c @@ -1,4 +1,4 @@ -/* $Id: activesock.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: activesock.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -43,6 +43,13 @@ enum read_type TYPE_RECV_FROM }; +enum shutdown_dir +{ + SHUT_NONE = 0, + SHUT_RX = 1, + SHUT_TX = 2 +}; + struct read_op { pj_ioqueue_op_key_t op_key; @@ -77,6 +84,7 @@ struct pj_activesock_t pj_ioqueue_t *ioqueue; void *user_data; unsigned async_count; + unsigned shutdown; unsigned max_loop; pj_activesock_cb cb; #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ @@ -209,8 +217,9 @@ PJ_DEF(pj_status_t) pj_activesock_create( pj_pool_t *pool, ioq_cb.on_accept_complete = &ioqueue_on_accept_complete; #endif - status = pj_ioqueue_register_sock(pool, ioqueue, sock, asock, - &ioq_cb, &asock->key); + status = pj_ioqueue_register_sock2(pool, ioqueue, sock, + (opt? opt->grp_lock : NULL), + asock, &ioq_cb, &asock->key); if (status != PJ_SUCCESS) { pj_activesock_close(asock); return status; @@ -283,10 +292,10 @@ PJ_DEF(pj_status_t) pj_activesock_create_udp( pj_pool_t *pool, return PJ_SUCCESS; } - PJ_DEF(pj_status_t) pj_activesock_close(pj_activesock_t *asock) { PJ_ASSERT_RETURN(asock, PJ_EINVAL); + asock->shutdown = SHUT_RX | SHUT_TX; if (asock->key) { #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 @@ -448,6 +457,10 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key, asock = (pj_activesock_t*) pj_ioqueue_get_user_data(key); + /* Ignore if we've been shutdown */ + if (asock->shutdown & SHUT_RX) + return; + do { unsigned flags; @@ -569,6 +582,10 @@ static void ioqueue_on_read_complete(pj_ioqueue_key_t *key, if (!ret) return; + /* Also stop further read if we've been shutdown */ + if (asock->shutdown & SHUT_RX) + return; + /* Only stream oriented socket may leave data in the packet */ if (asock->stream_oriented) { r->size = remainder; @@ -648,6 +665,9 @@ PJ_DEF(pj_status_t) pj_activesock_send( pj_activesock_t *asock, { PJ_ASSERT_RETURN(asock && send_key && data && size, PJ_EINVAL); + if (asock->shutdown & SHUT_TX) + return PJ_EINVALIDOP; + send_key->activesock_data = NULL; if (asock->whole_data) { @@ -698,6 +718,9 @@ PJ_DEF(pj_status_t) pj_activesock_sendto( pj_activesock_t *asock, PJ_ASSERT_RETURN(asock && send_key && data && size && addr && addr_len, PJ_EINVAL); + if (asock->shutdown & SHUT_TX) + return PJ_EINVALIDOP; + return pj_ioqueue_sendto(asock->key, send_key, data, size, flags, addr, addr_len); } @@ -711,6 +734,13 @@ static void ioqueue_on_write_complete(pj_ioqueue_key_t *key, asock = (pj_activesock_t*) pj_ioqueue_get_user_data(key); + /* Ignore if we've been shutdown. This may cause data to be partially + * sent even when 'wholedata' was requested if the OS only sent partial + * buffer. + */ + if (asock->shutdown & SHUT_TX) + return; + if (bytes_sent > 0 && op_key->activesock_data) { /* whole_data is requested. Make sure we send all the data */ struct send_data *sd = (struct send_data*)op_key->activesock_data; @@ -756,6 +786,10 @@ PJ_DEF(pj_status_t) pj_activesock_start_accept(pj_activesock_t *asock, PJ_ASSERT_RETURN(asock, PJ_EINVAL); PJ_ASSERT_RETURN(asock->accept_op==NULL, PJ_EINVALIDOP); + /* Ignore if we've been shutdown */ + if (asock->shutdown) + return PJ_EINVALIDOP; + asock->accept_op = (struct accept_op*) pj_pool_calloc(pool, asock->async_count, sizeof(struct accept_op)); @@ -798,6 +832,10 @@ static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key, PJ_UNUSED_ARG(new_sock); + /* Ignore if we've been shutdown */ + if (asock->shutdown) + return; + do { if (status == asock->last_err && status != PJ_SUCCESS) { asock->err_counter++; @@ -835,6 +873,10 @@ static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key, pj_sock_close(accept_op->new_sock); } + /* Don't start another accept() if we've been shutdown */ + if (asock->shutdown) + return; + /* Prepare next accept() */ accept_op->new_sock = PJ_INVALID_SOCKET; accept_op->rem_addr_len = sizeof(accept_op->rem_addr); @@ -853,6 +895,10 @@ PJ_DEF(pj_status_t) pj_activesock_start_connect( pj_activesock_t *asock, int addr_len) { PJ_UNUSED_ARG(pool); + + if (asock->shutdown) + return PJ_EINVALIDOP; + return pj_ioqueue_connect(asock->key, remaddr, addr_len); } @@ -861,6 +907,10 @@ static void ioqueue_on_connect_complete(pj_ioqueue_key_t *key, { pj_activesock_t *asock = (pj_activesock_t*) pj_ioqueue_get_user_data(key); + /* Ignore if we've been shutdown */ + if (asock->shutdown) + return; + if (asock->cb.on_connect_complete) { pj_bool_t ret; diff --git a/pjlib/src/pj/errno.c b/pjlib/src/pj/errno.c index 1cb8e72..a0f7406 100644 --- a/pjlib/src/pj/errno.c +++ b/pjlib/src/pj/errno.c @@ -1,4 +1,4 @@ -/* $Id: errno.c 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: errno.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -77,7 +77,8 @@ static const struct PJ_BUILD_ERR(PJ_ETOOSMALL, "Size is too short"), PJ_BUILD_ERR(PJ_EIGNORED, "Ignored"), PJ_BUILD_ERR(PJ_EIPV6NOTSUP, "IPv6 is not supported"), - PJ_BUILD_ERR(PJ_EAFNOTSUP, "Unsupported address family") + PJ_BUILD_ERR(PJ_EAFNOTSUP, "Unsupported address family"), + PJ_BUILD_ERR(PJ_EGONE, "Object no longer exists") }; #endif /* PJ_HAS_ERROR_STRING */ diff --git a/pjlib/src/pj/guid.c b/pjlib/src/pj/guid.c index 8ad5f78..88b6c37 100644 --- a/pjlib/src/pj/guid.c +++ b/pjlib/src/pj/guid.c @@ -1,4 +1,4 @@ -/* $Id: guid.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: guid.c 4208 2012-07-18 07:52:33Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -17,11 +17,32 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include +PJ_DEF(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str) +{ + int i; + + pj_generate_unique_string(str); + for (i = 0; i < str->slen; i++) + str->ptr[i] = (char)pj_tolower(str->ptr[i]); + + return str; +} + PJ_DEF(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str) { str->ptr = (char*)pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH); pj_generate_unique_string(str); } + +PJ_DEF(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str) +{ + int i; + + pj_create_unique_string(pool, str); + for (i = 0; i < str->slen; i++) + str->ptr[i] = (char)pj_tolower(str->ptr[i]); +} diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c index 00f167f..b37e8ff 100644 --- a/pjlib/src/pj/hash.c +++ b/pjlib/src/pj/hash.c @@ -1,4 +1,4 @@ -/* $Id: hash.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: hash.c 4296 2012-11-07 04:56:26Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -79,16 +79,21 @@ PJ_DEF(pj_uint32_t) pj_hash_calc_tolower( pj_uint32_t hval, #if defined(PJ_HASH_USE_OWN_TOLOWER) && PJ_HASH_USE_OWN_TOLOWER != 0 for (i=0; islen; ++i) { pj_uint8_t c = key->ptr[i]; + char lower; if (c & 64) - result[i] = (char)(c | 32); + lower = (char)(c | 32); else - result[i] = (char)c; - hval = hval * PJ_HASH_MULTIPLIER + result[i]; + lower = (char)c; + if (result) + result[i] = lower; + hval = hval * PJ_HASH_MULTIPLIER + lower; } #else for (i=0; islen; ++i) { - result[i] = (char)pj_tolower(key->ptr[i]); - hval = hval * PJ_HASH_MULTIPLIER + result[i]; + char lower = (char)pj_tolower(key->ptr[i]); + if (result) + result[i] = lower; + hval = hval * PJ_HASH_MULTIPLIER + lower; } #endif @@ -128,7 +133,7 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size) static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, const void *key, unsigned keylen, void *val, pj_uint32_t *hval, - void *entry_buf) + void *entry_buf, pj_bool_t lower) { pj_uint32_t hash; pj_hash_entry **p_entry, *entry; @@ -146,14 +151,20 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, if (keylen==PJ_HASH_KEY_STRING) { const pj_uint8_t *p = (const pj_uint8_t*)key; for ( ; *p; ++p ) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + if (lower) + hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p); + else + hash = hash * PJ_HASH_MULTIPLIER + *p; } keylen = p - (const unsigned char*)key; } else { const pj_uint8_t *p = (const pj_uint8_t*)key, *end = p + keylen; for ( ; p!=end; ++p) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + if (lower) + hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p); + else + hash = hash * PJ_HASH_MULTIPLIER + *p; } } @@ -168,9 +179,11 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, p_entry = &entry->next, entry = *p_entry) { if (entry->hash==hash && entry->keylen==keylen && - pj_memcmp(entry->key, key, keylen)==0) + ((lower && pj_ansi_strnicmp((const char*)entry->key, + (const char*)key, keylen)==0) || + (!lower && pj_memcmp(entry->key, key, keylen)==0))) { - break; + break; } } @@ -214,17 +227,27 @@ PJ_DEF(void *) pj_hash_get( pj_hash_table_t *ht, pj_uint32_t *hval) { pj_hash_entry *entry; - entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL); + entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_FALSE); return entry ? entry->value : NULL; } -PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, - const void *key, unsigned keylen, pj_uint32_t hval, - void *value ) +PJ_DEF(void *) pj_hash_get_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t *hval) +{ + pj_hash_entry *entry; + entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_TRUE); + return entry ? entry->value : NULL; +} + +static void hash_set( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, pj_uint32_t hval, + void *value, void *entry_buf, pj_bool_t lower ) { pj_hash_entry **p_entry; - p_entry = find_entry( pool, ht, key, keylen, value, &hval, NULL); + p_entry = find_entry( pool, ht, key, keylen, value, &hval, entry_buf, + lower); if (*p_entry) { if (value == NULL) { /* delete entry */ @@ -241,29 +264,35 @@ PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, } } +PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, pj_uint32_t hval, + void *value ) +{ + hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_FALSE); +} + +PJ_DEF(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *value ) +{ + hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_TRUE); +} + PJ_DEF(void) pj_hash_set_np( pj_hash_table_t *ht, const void *key, unsigned keylen, pj_uint32_t hval, pj_hash_entry_buf entry_buf, void *value) { - pj_hash_entry **p_entry; + hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_FALSE); +} - p_entry = find_entry( NULL, ht, key, keylen, value, &hval, - (void*)entry_buf ); - if (*p_entry) { - if (value == NULL) { - /* delete entry */ - PJ_LOG(6, ("hashtbl", "%p: p_entry %p deleted", ht, *p_entry)); - *p_entry = (*p_entry)->next; - --ht->count; - - } else { - /* overwrite */ - (*p_entry)->value = value; - PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht, - *p_entry, value)); - } - } +PJ_DEF(void) pj_hash_set_np_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, + pj_hash_entry_buf entry_buf, + void *value) +{ + hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_TRUE); } PJ_DEF(unsigned) pj_hash_count( pj_hash_table_t *ht ) diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c index ee4506d..b8036a5 100644 --- a/pjlib/src/pj/ioqueue_common_abs.c +++ b/pjlib/src/pj/ioqueue_common_abs.c @@ -1,4 +1,4 @@ -/* $Id: ioqueue_common_abs.c 3666 2011-07-19 08:40:20Z nanang $ */ +/* $Id: ioqueue_common_abs.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -70,6 +70,7 @@ static pj_status_t ioqueue_init_key( pj_pool_t *pool, pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *key, pj_sock_t sock, + pj_grp_lock_t *grp_lock, void *user_data, const pj_ioqueue_callback *cb) { @@ -114,10 +115,18 @@ static pj_status_t ioqueue_init_key( pj_pool_t *pool, /* Create mutex for the key. */ #if !PJ_IOQUEUE_HAS_SAFE_UNREG - rc = pj_mutex_create_simple(pool, NULL, &key->mutex); + rc = pj_lock_create_simple_mutex(poll, NULL, &key->lock); #endif + if (rc != PJ_SUCCESS) + return rc; + + /* Group lock */ + key->grp_lock = grp_lock; + if (key->grp_lock) { + pj_grp_lock_add_ref_dbg(key->grp_lock, "ioqueue", 0); + } - return rc; + return PJ_SUCCESS; } /* @@ -189,10 +198,10 @@ PJ_INLINE(int) key_has_pending_connect(pj_ioqueue_key_t *key) void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) { /* Lock the key. */ - pj_mutex_lock(h->mutex); + pj_ioqueue_lock_key(h); if (IS_CLOSING(h)) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); return; } @@ -261,7 +270,7 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) * save it to a flag. */ has_lock = PJ_FALSE; - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } else { has_lock = PJ_TRUE; } @@ -272,7 +281,7 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) /* Unlock if we still hold the lock */ if (has_lock) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } /* Done. */ @@ -379,7 +388,8 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) * save it to a flag. */ has_lock = PJ_FALSE; - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); + PJ_RACE_ME(5); } else { has_lock = PJ_TRUE; } @@ -392,11 +402,11 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) } if (has_lock) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } else { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } /* Done. */ @@ -406,7 +416,7 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) * are signalled for the same event, but only one thread eventually * able to process the event. */ - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } @@ -415,10 +425,10 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) pj_status_t rc; /* Lock the key. */ - pj_mutex_lock(h->mutex); + pj_ioqueue_lock_key(h); if (IS_CLOSING(h)) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); return; } @@ -453,7 +463,8 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) * save it to a flag. */ has_lock = PJ_FALSE; - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); + PJ_RACE_ME(5); } else { has_lock = PJ_TRUE; } @@ -466,7 +477,7 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) } if (has_lock) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } else @@ -567,7 +578,8 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) * save it to a flag. */ has_lock = PJ_FALSE; - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); + PJ_RACE_ME(5); } else { has_lock = PJ_TRUE; } @@ -580,7 +592,7 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) } if (has_lock) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } else { @@ -589,7 +601,7 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h ) * are signalled for the same event, but only one thread eventually * able to process the event. */ - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } @@ -599,19 +611,19 @@ void ioqueue_dispatch_exception_event( pj_ioqueue_t *ioqueue, { pj_bool_t has_lock; - pj_mutex_lock(h->mutex); + pj_ioqueue_lock_key(h); if (!h->connecting) { /* It is possible that more than one thread was woken up, thus * the remaining thread will see h->connecting as zero because * it has been processed by other thread. */ - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); return; } if (IS_CLOSING(h)) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); return; } @@ -629,7 +641,8 @@ void ioqueue_dispatch_exception_event( pj_ioqueue_t *ioqueue, * save it to a flag. */ has_lock = PJ_FALSE; - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); + PJ_RACE_ME(5); } else { has_lock = PJ_TRUE; } @@ -651,7 +664,7 @@ void ioqueue_dispatch_exception_event( pj_ioqueue_t *ioqueue, } if (has_lock) { - pj_mutex_unlock(h->mutex); + pj_ioqueue_unlock_key(h); } } @@ -713,18 +726,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key, read_op->size = *length; read_op->flags = flags; - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous check * in multithreaded app. If we add bad handle to the set it will * corrupt the ioqueue set. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } pj_list_insert_before(&key->read_list, read_op); ioqueue_add_to_set(key->ioqueue, key, READABLE_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } @@ -789,18 +802,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key, read_op->rmt_addr = addr; read_op->rmt_addrlen = addrlen; - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous check * in multithreaded app. If we add bad handle to the set it will * corrupt the ioqueue set. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } pj_list_insert_before(&key->read_list, read_op); ioqueue_add_to_set(key->ioqueue, key, READABLE_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } @@ -903,18 +916,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key, write_op->written = 0; write_op->flags = flags; - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous check * in multithreaded app. If we add bad handle to the set it will * corrupt the ioqueue set. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } pj_list_insert_before(&key->write_list, write_op); ioqueue_add_to_set(key->ioqueue, key, WRITEABLE_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } @@ -1050,18 +1063,18 @@ retry_on_restart: pj_memcpy(&write_op->rmt_addr, addr, addrlen); write_op->rmt_addrlen = addrlen; - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous check * in multithreaded app. If we add bad handle to the set it will * corrupt the ioqueue set. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } pj_list_insert_before(&key->write_list, write_op); ioqueue_add_to_set(key->ioqueue, key, WRITEABLE_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } @@ -1127,18 +1140,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key, accept_op->addrlen= addrlen; accept_op->local_addr = local; - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous check * in multithreaded app. If we add bad handle to the set it will * corrupt the ioqueue set. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } pj_list_insert_before(&key->accept_list, accept_op); ioqueue_add_to_set(key->ioqueue, key, READABLE_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } @@ -1171,18 +1184,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key, } else { if (status == PJ_STATUS_FROM_OS(PJ_BLOCKING_CONNECT_ERROR_VAL)) { /* Pending! */ - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Check again. Handle may have been closed after the previous * check in multithreaded app. See #913 */ if (IS_CLOSING(key)) { - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_ECANCELLED; } key->connecting = PJ_TRUE; ioqueue_add_to_set(key->ioqueue, key, WRITEABLE_EVENT); ioqueue_add_to_set(key->ioqueue, key, EXCEPTION_EVENT); - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EPENDING; } else { /* Error! */ @@ -1228,7 +1241,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, * Find the operation key in all pending operation list to * really make sure that it's still there; then call the callback. */ - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Find the operation in the pending read list. */ op_rec = (struct generic_operation*)key->read_list.next; @@ -1236,7 +1249,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, if (op_rec == (void*)op_key) { pj_list_erase(op_rec); op_rec->op = PJ_IOQUEUE_OP_NONE; - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); (*key->cb.on_read_complete)(key, op_key, bytes_status); return PJ_SUCCESS; @@ -1250,7 +1263,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, if (op_rec == (void*)op_key) { pj_list_erase(op_rec); op_rec->op = PJ_IOQUEUE_OP_NONE; - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); (*key->cb.on_write_complete)(key, op_key, bytes_status); return PJ_SUCCESS; @@ -1264,7 +1277,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, if (op_rec == (void*)op_key) { pj_list_erase(op_rec); op_rec->op = PJ_IOQUEUE_OP_NONE; - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); (*key->cb.on_accept_complete)(key, op_key, PJ_INVALID_SOCKET, @@ -1274,7 +1287,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, op_rec = op_rec->next; } - pj_mutex_unlock(key->mutex); + pj_ioqueue_unlock_key(key); return PJ_EINVALIDOP; } @@ -1304,11 +1317,18 @@ PJ_DEF(pj_status_t) pj_ioqueue_set_concurrency(pj_ioqueue_key_t *key, PJ_DEF(pj_status_t) pj_ioqueue_lock_key(pj_ioqueue_key_t *key) { - return pj_mutex_lock(key->mutex); + if (key->grp_lock) + return pj_grp_lock_acquire(key->grp_lock); + else + return pj_lock_acquire(key->lock); } PJ_DEF(pj_status_t) pj_ioqueue_unlock_key(pj_ioqueue_key_t *key) { - return pj_mutex_unlock(key->mutex); + if (key->grp_lock) + return pj_grp_lock_release(key->grp_lock); + else + return pj_lock_release(key->lock); } + diff --git a/pjlib/src/pj/ioqueue_common_abs.h b/pjlib/src/pj/ioqueue_common_abs.h index 3a41051..3bdbb52 100644 --- a/pjlib/src/pj/ioqueue_common_abs.h +++ b/pjlib/src/pj/ioqueue_common_abs.h @@ -101,7 +101,8 @@ union operation_key #define DECLARE_COMMON_KEY \ PJ_DECL_LIST_MEMBER(struct pj_ioqueue_key_t); \ pj_ioqueue_t *ioqueue; \ - pj_mutex_t *mutex; \ + pj_grp_lock_t *grp_lock; \ + pj_lock_t *lock; \ pj_bool_t inside_callback; \ pj_bool_t destroy_requested; \ pj_bool_t allow_concurrent; \ diff --git a/pjlib/src/pj/ioqueue_epoll.c b/pjlib/src/pj/ioqueue_epoll.c index 27845f5..c2564d1 100644 --- a/pjlib/src/pj/ioqueue_epoll.c +++ b/pjlib/src/pj/ioqueue_epoll.c @@ -1,4 +1,4 @@ -/* $Id: ioqueue_epoll.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ioqueue_epoll.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -262,11 +262,11 @@ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, key = PJ_POOL_ALLOC_T(pool, pj_ioqueue_key_t); key->ref_count = 0; - rc = pj_mutex_create_recursive(pool, NULL, &key->mutex); + rc = pj_lock_create_recursive_mutex(pool, NULL, &key->lock); if (rc != PJ_SUCCESS) { key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } pj_mutex_destroy(ioqueue->ref_cnt_mutex); @@ -323,19 +323,19 @@ PJ_DEF(pj_status_t) pj_ioqueue_destroy(pj_ioqueue_t *ioqueue) /* Destroy reference counters */ key = ioqueue->active_list.next; while (key != &ioqueue->active_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } key = ioqueue->closing_list.next; while (key != &ioqueue->closing_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } @@ -422,7 +422,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, status = os_epoll_ctl(ioqueue->epfd, EPOLL_CTL_ADD, sock, &ev); if (status < 0) { rc = pj_get_os_error(); - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = NULL; TRACE_((THIS_FILE, "pj_ioqueue_register_sock error: os_epoll_ctl rc=%d", @@ -497,7 +497,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key) * the key. We need to lock the key before ioqueue here to prevent * deadlock. */ - pj_mutex_lock(key->mutex); + pj_lock_acquire(key->lock); /* Also lock ioqueue */ pj_lock_acquire(ioqueue->lock); @@ -531,9 +531,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key) decrement_counter(key); /* Done. */ - pj_mutex_unlock(key->mutex); + pj_lock_release(key->lock); #else - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); #endif return PJ_SUCCESS; diff --git a/pjlib/src/pj/ioqueue_select.c b/pjlib/src/pj/ioqueue_select.c index 74b87d8..1b08d28 100644 --- a/pjlib/src/pj/ioqueue_select.c +++ b/pjlib/src/pj/ioqueue_select.c @@ -1,4 +1,4 @@ -/* $Id: ioqueue_select.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ioqueue_select.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -39,6 +39,7 @@ #include #include #include +#include /* Now that we have access to OS'es , lets check again that * PJ_IOQUEUE_MAX_HANDLES is not greater than FD_SETSIZE @@ -237,11 +238,11 @@ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, key = PJ_POOL_ALLOC_T(pool, pj_ioqueue_key_t); key->ref_count = 0; - rc = pj_mutex_create_recursive(pool, NULL, &key->mutex); + rc = pj_lock_create_recursive_mutex(pool, NULL, &key->lock); if (rc != PJ_SUCCESS) { key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } pj_mutex_destroy(ioqueue->ref_cnt_mutex); @@ -284,19 +285,19 @@ PJ_DEF(pj_status_t) pj_ioqueue_destroy(pj_ioqueue_t *ioqueue) /* Destroy reference counters */ key = ioqueue->active_list.next; while (key != &ioqueue->active_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } key = ioqueue->closing_list.next; while (key != &ioqueue->closing_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { - pj_mutex_destroy(key->mutex); + pj_lock_destroy(key->lock); key = key->next; } @@ -312,9 +313,10 @@ PJ_DEF(pj_status_t) pj_ioqueue_destroy(pj_ioqueue_t *ioqueue) * * Register socket handle to ioqueue. */ -PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, +PJ_DEF(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool, pj_ioqueue_t *ioqueue, pj_sock_t sock, + pj_grp_lock_t *grp_lock, void *user_data, const pj_ioqueue_callback *cb, pj_ioqueue_key_t **p_key) @@ -358,7 +360,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, key = (pj_ioqueue_key_t*)pj_pool_zalloc(pool, sizeof(pj_ioqueue_key_t)); #endif - rc = ioqueue_init_key(pool, ioqueue, key, sock, user_data, cb); + rc = ioqueue_init_key(pool, ioqueue, key, sock, grp_lock, user_data, cb); if (rc != PJ_SUCCESS) { key = NULL; goto on_return; @@ -386,12 +388,27 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, on_return: /* On error, socket may be left in non-blocking mode. */ + if (rc != PJ_SUCCESS) { + if (key->grp_lock) + pj_grp_lock_dec_ref_dbg(key->grp_lock, "ioqueue", 0); + } *p_key = key; pj_lock_release(ioqueue->lock); return rc; } +PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, + pj_ioqueue_t *ioqueue, + pj_sock_t sock, + void *user_data, + const pj_ioqueue_callback *cb, + pj_ioqueue_key_t **p_key) +{ + return pj_ioqueue_register_sock2(pool, ioqueue, sock, NULL, user_data, + cb, p_key); +} + #if PJ_IOQUEUE_HAS_SAFE_UNREG /* Increment key's reference counter */ static void increment_counter(pj_ioqueue_key_t *key) @@ -446,7 +463,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key) * the key. We need to lock the key before ioqueue here to prevent * deadlock. */ - pj_mutex_lock(key->mutex); + pj_ioqueue_lock_key(key); /* Also lock ioqueue */ pj_lock_acquire(ioqueue->lock); @@ -485,9 +502,34 @@ PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key) decrement_counter(key); /* Done. */ - pj_mutex_unlock(key->mutex); + if (key->grp_lock) { + /* just dec_ref and unlock. we will set grp_lock to NULL + * elsewhere */ + pj_grp_lock_t *grp_lock = key->grp_lock; + // Don't set grp_lock to NULL otherwise the other thread + // will crash. Just leave it as dangling pointer, but this + // should be safe + //key->grp_lock = NULL; + pj_grp_lock_dec_ref_dbg(grp_lock, "ioqueue", 0); + pj_grp_lock_release(grp_lock); + } else { + pj_ioqueue_unlock_key(key); + } #else - pj_mutex_destroy(key->mutex); + if (key->grp_lock) { + /* set grp_lock to NULL and unlock */ + pj_grp_lock_t *grp_lock = key->grp_lock; + // Don't set grp_lock to NULL otherwise the other thread + // will crash. Just leave it as dangling pointer, but this + // should be safe + //key->grp_lock = NULL; + pj_grp_lock_dec_ref_dbg(grp_lock, "ioqueue", 0); + pj_grp_lock_release(grp_lock); + } else { + pj_ioqueue_unlock_key(key); + } + + pj_lock_destroy(key->lock); #endif return PJ_SUCCESS; @@ -620,6 +662,10 @@ static void scan_closing_keys(pj_ioqueue_t *ioqueue) if (PJ_TIME_VAL_GTE(now, h->free_time)) { pj_list_erase(h); + // Don't set grp_lock to NULL otherwise the other thread + // will crash. Just leave it as dangling pointer, but this + // should be safe + //h->grp_lock = NULL; pj_list_push_back(&ioqueue->free_list, h); } h = next; @@ -781,7 +827,7 @@ on_error: PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) { pj_fd_set_t rfdset, wfdset, xfdset; - int count, counter; + int count, i, counter; pj_ioqueue_key_t *h; struct event { @@ -892,8 +938,17 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) #endif } + for (i=0; igrp_lock) + pj_grp_lock_add_ref_dbg(event[i].key->grp_lock, "ioqueue", 0); + } + + PJ_RACE_ME(5); + pj_lock_release(ioqueue->lock); + PJ_RACE_ME(5); + count = counter; /* Now process all events. The dispatch functions will take care @@ -918,6 +973,10 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) #if PJ_IOQUEUE_HAS_SAFE_UNREG decrement_counter(event[counter].key); #endif + + if (event[counter].key->grp_lock) + pj_grp_lock_dec_ref_dbg(event[counter].key->grp_lock, + "ioqueue", 0); } diff --git a/pjlib/src/pj/ioqueue_symbian.cpp b/pjlib/src/pj/ioqueue_symbian.cpp index 01f4db5..0b310d1 100644 --- a/pjlib/src/pj/ioqueue_symbian.cpp +++ b/pjlib/src/pj/ioqueue_symbian.cpp @@ -1,4 +1,4 @@ -/* $Id: ioqueue_symbian.cpp 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: ioqueue_symbian.cpp 4374 2013-02-27 07:15:57Z riza $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -528,6 +528,19 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, return PJ_SUCCESS; } +PJ_DEF(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool, + pj_ioqueue_t *ioqueue, + pj_sock_t sock, + pj_grp_lock_t *grp_lock, + void *user_data, + const pj_ioqueue_callback *cb, + pj_ioqueue_key_t **p_key) +{ + PJ_UNUSED_ARG(grp_lock); + + return pj_ioqueue_register_sock(pool, ioqueue, sock, user_data, cb, p_key); +} + /* * Unregister from the I/O Queue framework. */ diff --git a/pjlib/src/pj/ip_helper_generic.c b/pjlib/src/pj/ip_helper_generic.c index 3a43423..94d5a1f 100644 --- a/pjlib/src/pj/ip_helper_generic.c +++ b/pjlib/src/pj/ip_helper_generic.c @@ -1,4 +1,4 @@ -/* $Id: ip_helper_generic.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ip_helper_generic.c 4355 2013-02-19 16:27:37Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -165,9 +165,6 @@ static pj_status_t if_enum_by_af(int af, return PJ_RETURN_OS_ERROR(oserr); } - /* Done with socket */ - pj_sock_close(sock); - /* Interface interfaces */ ifr = (struct ifreq*) ifc.ifc_req; count = ifc.ifc_len / sizeof(struct ifreq); @@ -177,6 +174,7 @@ static pj_status_t if_enum_by_af(int af, *p_cnt = 0; for (i=0; iifr_addr; TRACE_((THIS_FILE, " checking interface %s", itf->ifr_name)); @@ -188,13 +186,19 @@ static pj_status_t if_enum_by_af(int af, continue; } - if ((itf->ifr_flags & IFF_UP)==0) { + if (ioctl(sock, SIOCGIFFLAGS, &iff) != 0) { + TRACE_((THIS_FILE, " ioctl(SIOCGIFFLAGS) failed: %s", + get_os_errmsg())); + continue; /* Failed to get flags, continue */ + } + + if ((iff.ifr_flags & IFF_UP)==0) { TRACE_((THIS_FILE, " interface is down")); continue; /* Skip when interface is down */ } #if PJ_IP_HELPER_IGNORE_LOOPBACK_IF - if (itf->ifr_flags & IFF_LOOPBACK) { + if (iff.ifr_flags & IFF_LOOPBACK) { TRACE_((THIS_FILE, " loopback interface")); continue; /* Skip loopback interface */ } @@ -220,10 +224,14 @@ static pj_status_t if_enum_by_af(int af, (*p_cnt)++; } + /* Done with socket */ + pj_sock_close(sock); + TRACE_((THIS_FILE, "done, found %d address(es)", *p_cnt)); return (*p_cnt != 0) ? PJ_SUCCESS : PJ_ENOTFOUND; } + #elif defined(PJ_HAS_NET_IF_H) && PJ_HAS_NET_IF_H != 0 /* Note: this does not work with IPv6 */ static pj_status_t if_enum_by_af(int af, unsigned *p_cnt, pj_sockaddr ifs[]) diff --git a/pjlib/src/pj/lock.c b/pjlib/src/pj/lock.c index a7879af..34e2d1e 100644 --- a/pjlib/src/pj/lock.c +++ b/pjlib/src/pj/lock.c @@ -1,4 +1,4 @@ -/* $Id: lock.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: lock.c 4412 2013-03-05 03:12:32Z riza $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -20,10 +20,12 @@ #include #include #include +#include #include #include #include +#define THIS_FILE "lock.c" typedef void LOCK_OBJ; @@ -196,3 +198,518 @@ PJ_DEF(pj_status_t) pj_lock_destroy( pj_lock_t *lock ) return (*lock->destroy)(lock->lock_object); } + +/****************************************************************************** + * Group lock + */ + +/* Individual lock in the group lock */ +typedef struct grp_lock_item +{ + PJ_DECL_LIST_MEMBER(struct grp_lock_item); + int prio; + pj_lock_t *lock; + +} grp_lock_item; + +/* Destroy callbacks */ +typedef struct grp_destroy_callback +{ + PJ_DECL_LIST_MEMBER(struct grp_destroy_callback); + void *comp; + void (*handler)(void*); +} grp_destroy_callback; + +#if PJ_GRP_LOCK_DEBUG +/* Store each add_ref caller */ +typedef struct grp_lock_ref +{ + PJ_DECL_LIST_MEMBER(struct grp_lock_ref); + const char *file; + int line; +} grp_lock_ref; +#endif + +/* The group lock */ +struct pj_grp_lock_t +{ + pj_lock_t base; + + pj_pool_t *pool; + pj_atomic_t *ref_cnt; + pj_lock_t *own_lock; + + pj_thread_t *owner; + int owner_cnt; + + grp_lock_item lock_list; + grp_destroy_callback destroy_list; + +#if PJ_GRP_LOCK_DEBUG + grp_lock_ref ref_list; + grp_lock_ref ref_free_list; +#endif +}; + + +PJ_DEF(void) pj_grp_lock_config_default(pj_grp_lock_config *cfg) +{ + pj_bzero(cfg, sizeof(*cfg)); +} + +static void grp_lock_set_owner_thread(pj_grp_lock_t *glock) +{ + if (!glock->owner) { + glock->owner = pj_thread_this(); + glock->owner_cnt = 1; + } else { + pj_assert(glock->owner == pj_thread_this()); + glock->owner_cnt++; + } +} + +static void grp_lock_unset_owner_thread(pj_grp_lock_t *glock) +{ + pj_assert(glock->owner == pj_thread_this()); + pj_assert(glock->owner_cnt > 0); + if (--glock->owner_cnt <= 0) { + glock->owner = NULL; + glock->owner_cnt = 0; + } +} + +static pj_status_t grp_lock_acquire(LOCK_OBJ *p) +{ + pj_grp_lock_t *glock = (pj_grp_lock_t*)p; + grp_lock_item *lck; + + pj_assert(pj_atomic_get(glock->ref_cnt) > 0); + + lck = glock->lock_list.next; + while (lck != &glock->lock_list) { + pj_lock_acquire(lck->lock); + lck = lck->next; + } + grp_lock_set_owner_thread(glock); + pj_grp_lock_add_ref(glock); + return PJ_SUCCESS; +} + +static pj_status_t grp_lock_tryacquire(LOCK_OBJ *p) +{ + pj_grp_lock_t *glock = (pj_grp_lock_t*)p; + grp_lock_item *lck; + + pj_assert(pj_atomic_get(glock->ref_cnt) > 0); + + lck = glock->lock_list.next; + while (lck != &glock->lock_list) { + pj_status_t status = pj_lock_tryacquire(lck->lock); + if (status != PJ_SUCCESS) { + lck = lck->prev; + while (lck != &glock->lock_list) { + pj_lock_release(lck->lock); + lck = lck->prev; + } + return status; + } + lck = lck->next; + } + grp_lock_set_owner_thread(glock); + pj_grp_lock_add_ref(glock); + return PJ_SUCCESS; +} + +static pj_status_t grp_lock_release(LOCK_OBJ *p) +{ + pj_grp_lock_t *glock = (pj_grp_lock_t*)p; + grp_lock_item *lck; + + grp_lock_unset_owner_thread(glock); + + lck = glock->lock_list.prev; + while (lck != &glock->lock_list) { + pj_lock_release(lck->lock); + lck = lck->prev; + } + return pj_grp_lock_dec_ref(glock); +} + +static pj_status_t grp_lock_destroy(LOCK_OBJ *p) +{ + pj_grp_lock_t *glock = (pj_grp_lock_t*)p; + pj_pool_t *pool = glock->pool; + grp_lock_item *lck; + grp_destroy_callback *cb; + + if (!glock->pool) { + /* already destroyed?! */ + return PJ_EINVAL; + } + + /* Release all chained locks */ + lck = glock->lock_list.next; + while (lck != &glock->lock_list) { + if (lck->lock != glock->own_lock) { + int i; + for (i=0; iowner_cnt; ++i) + pj_lock_release(lck->lock); + } + lck = lck->next; + } + + /* Call callbacks */ + cb = glock->destroy_list.next; + while (cb != &glock->destroy_list) { + grp_destroy_callback *next = cb->next; + cb->handler(cb->comp); + cb = next; + } + + pj_lock_destroy(glock->own_lock); + pj_atomic_destroy(glock->ref_cnt); + glock->pool = NULL; + pj_pool_release(pool); + + return PJ_SUCCESS; +} + + +PJ_DEF(pj_status_t) pj_grp_lock_create( pj_pool_t *pool, + const pj_grp_lock_config *cfg, + pj_grp_lock_t **p_grp_lock) +{ + pj_grp_lock_t *glock; + grp_lock_item *own_lock; + pj_status_t status; + + PJ_ASSERT_RETURN(pool && p_grp_lock, PJ_EINVAL); + + PJ_UNUSED_ARG(cfg); + + pool = pj_pool_create(pool->factory, "glck%p", 512, 512, NULL); + if (!pool) + return PJ_ENOMEM; + + glock = PJ_POOL_ZALLOC_T(pool, pj_grp_lock_t); + glock->base.lock_object = glock; + glock->base.acquire = &grp_lock_acquire; + glock->base.tryacquire = &grp_lock_tryacquire; + glock->base.release = &grp_lock_release; + glock->base.destroy = &grp_lock_destroy; + + glock->pool = pool; + pj_list_init(&glock->lock_list); + pj_list_init(&glock->destroy_list); +#if PJ_GRP_LOCK_DEBUG + pj_list_init(&glock->ref_list); + pj_list_init(&glock->ref_free_list); +#endif + + status = pj_atomic_create(pool, 0, &glock->ref_cnt); + if (status != PJ_SUCCESS) + goto on_error; + + status = pj_lock_create_recursive_mutex(pool, pool->obj_name, + &glock->own_lock); + if (status != PJ_SUCCESS) + goto on_error; + + own_lock = PJ_POOL_ZALLOC_T(pool, grp_lock_item); + own_lock->lock = glock->own_lock; + pj_list_push_back(&glock->lock_list, own_lock); + + *p_grp_lock = glock; + return PJ_SUCCESS; + +on_error: + grp_lock_destroy(glock); + return status; +} + +PJ_DEF(pj_status_t) pj_grp_lock_destroy( pj_grp_lock_t *grp_lock) +{ + return grp_lock_destroy(grp_lock); +} + +PJ_DEF(pj_status_t) pj_grp_lock_acquire( pj_grp_lock_t *grp_lock) +{ + return grp_lock_acquire(grp_lock); +} + +PJ_DEF(pj_status_t) pj_grp_lock_tryacquire( pj_grp_lock_t *grp_lock) +{ + return grp_lock_tryacquire(grp_lock); +} + +PJ_DEF(pj_status_t) pj_grp_lock_release( pj_grp_lock_t *grp_lock) +{ + return grp_lock_release(grp_lock); +} + +PJ_DEF(pj_status_t) pj_grp_lock_replace( pj_grp_lock_t *old_lock, + pj_grp_lock_t *new_lock) +{ + grp_destroy_callback *ocb; + + /* Move handlers from old to new */ + ocb = old_lock->destroy_list.next; + while (ocb != &old_lock->destroy_list) { + grp_destroy_callback *ncb; + + ncb = PJ_POOL_ALLOC_T(new_lock->pool, grp_destroy_callback); + ncb->comp = ocb->comp; + ncb->handler = ocb->handler; + pj_list_push_back(&new_lock->destroy_list, ncb); + + ocb = ocb->next; + } + + pj_list_init(&old_lock->destroy_list); + + grp_lock_destroy(old_lock); + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_grp_lock_add_handler( pj_grp_lock_t *glock, + pj_pool_t *pool, + void *comp, + void (*destroy)(void *comp)) +{ + grp_destroy_callback *cb; + + grp_lock_acquire(glock); + + if (pool == NULL) + pool = glock->pool; + + cb = PJ_POOL_ZALLOC_T(pool, grp_destroy_callback); + cb->comp = comp; + cb->handler = destroy; + pj_list_push_back(&glock->destroy_list, cb); + + grp_lock_release(glock); + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_grp_lock_del_handler( pj_grp_lock_t *glock, + void *comp, + void (*destroy)(void *comp)) +{ + grp_destroy_callback *cb; + + grp_lock_acquire(glock); + + cb = glock->destroy_list.next; + while (cb != &glock->destroy_list) { + if (cb->comp == comp && cb->handler == destroy) + break; + cb = cb->next; + } + + if (cb != &glock->destroy_list) + pj_list_erase(cb); + + grp_lock_release(glock); + return PJ_SUCCESS; +} + +static pj_status_t grp_lock_add_ref(pj_grp_lock_t *glock) +{ + pj_atomic_inc(glock->ref_cnt); + return PJ_SUCCESS; +} + +static pj_status_t grp_lock_dec_ref(pj_grp_lock_t *glock) +{ + int cnt; /* for debugging */ + if ((cnt=pj_atomic_dec_and_get(glock->ref_cnt)) == 0) { + grp_lock_destroy(glock); + return PJ_EGONE; + } + pj_assert(cnt > 0); + pj_grp_lock_dump(glock); + return PJ_SUCCESS; +} + +#if PJ_GRP_LOCK_DEBUG +PJ_DEF(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *glock, + const char *file, + int line) +{ + grp_lock_ref *ref; + pj_status_t status; + + pj_enter_critical_section(); + if (!pj_list_empty(&glock->ref_free_list)) { + ref = glock->ref_free_list.next; + pj_list_erase(ref); + } else { + ref = PJ_POOL_ALLOC_T(glock->pool, grp_lock_ref); + } + + ref->file = file; + ref->line = line; + pj_list_push_back(&glock->ref_list, ref); + + pj_leave_critical_section(); + + status = grp_lock_add_ref(glock); + + if (status != PJ_SUCCESS) { + pj_enter_critical_section(); + pj_list_erase(ref); + pj_list_push_back(&glock->ref_free_list, ref); + pj_leave_critical_section(); + } + + return status; +} + +PJ_DEF(pj_status_t) pj_grp_lock_dec_ref_dbg(pj_grp_lock_t *glock, + const char *file, + int line) +{ + grp_lock_ref *ref; + + pj_enter_critical_section(); + /* Find the same source file */ + ref = glock->ref_list.next; + while (ref != &glock->ref_list) { + if (strcmp(ref->file, file) == 0) { + pj_list_erase(ref); + pj_list_push_back(&glock->ref_free_list, ref); + break; + } + ref = ref->next; + } + pj_leave_critical_section(); + + if (ref == &glock->ref_list) { + PJ_LOG(2,(THIS_FILE, "pj_grp_lock_dec_ref_dbg() could not find " + "matching ref for %s", file)); + } + + return grp_lock_dec_ref(glock); +} +#else +PJ_DEF(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *glock) +{ + return grp_lock_add_ref(glock); +} + +PJ_DEF(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *glock) +{ + return grp_lock_dec_ref(glock); +} +#endif + +PJ_DEF(int) pj_grp_lock_get_ref(pj_grp_lock_t *glock) +{ + return pj_atomic_get(glock->ref_cnt); +} + +PJ_DEF(pj_status_t) pj_grp_lock_chain_lock( pj_grp_lock_t *glock, + pj_lock_t *lock, + int pos) +{ + grp_lock_item *lck, *new_lck; + int i; + + grp_lock_acquire(glock); + + for (i=0; iowner_cnt; ++i) + pj_lock_acquire(lock); + + lck = glock->lock_list.next; + while (lck != &glock->lock_list) { + if (lck->prio >= pos) + break; + lck = lck->next; + } + + new_lck = PJ_POOL_ZALLOC_T(glock->pool, grp_lock_item); + new_lck->prio = pos; + new_lck->lock = lock; + pj_list_insert_before(lck, new_lck); + + /* this will also release the new lock */ + grp_lock_release(glock); + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_grp_lock_unchain_lock( pj_grp_lock_t *glock, + pj_lock_t *lock) +{ + grp_lock_item *lck; + + grp_lock_acquire(glock); + + lck = glock->lock_list.next; + while (lck != &glock->lock_list) { + if (lck->lock == lock) + break; + lck = lck->next; + } + + if (lck != &glock->lock_list) { + int i; + + pj_list_erase(lck); + for (i=0; iowner_cnt; ++i) + pj_lock_release(lck->lock); + } + + grp_lock_release(glock); + return PJ_SUCCESS; +} + +PJ_DEF(void) pj_grp_lock_dump(pj_grp_lock_t *grp_lock) +{ +#if PJ_GRP_LOCK_DEBUG + grp_lock_ref *ref = grp_lock->ref_list.next; + char info_buf[1000]; + pj_str_t info; + + info.ptr = info_buf; + info.slen = 0; + + pj_grp_lock_acquire(grp_lock); + pj_enter_critical_section(); + + while (ref != &grp_lock->ref_list && info.slen < sizeof(info_buf)) { + char *start = info.ptr + info.slen; + int max_len = sizeof(info_buf) - info.slen; + int len; + + len = pj_ansi_snprintf(start, max_len, "%s:%d ", ref->file, ref->line); + if (len < 1 || len > max_len) { + len = strlen(ref->file); + if (len > max_len - 1) + len = max_len - 1; + + memcpy(start, ref->file, len); + start[len++] = ' '; + } + + info.slen += len; + + ref = ref->next; + } + + if (ref != &grp_lock->ref_list) { + int i; + for (i=0; i<4; ++i) + info_buf[sizeof(info_buf)-i-1] = '.'; + } + info.ptr[info.slen-1] = '\0'; + + pj_leave_critical_section(); + pj_grp_lock_release(grp_lock); + + PJ_LOG(4,(THIS_FILE, "Group lock %p, ref_cnt=%d. Reference holders: %s", + grp_lock, pj_grp_lock_get_ref(grp_lock), info.ptr)); +#else + PJ_UNUSED_ARG(grp_lock); +#endif +} diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c index 7810eb2..ff8ba68 100644 --- a/pjlib/src/pj/os_core_unix.c +++ b/pjlib/src/pj/os_core_unix.c @@ -1,4 +1,4 @@ -/* $Id: os_core_unix.c 3999 2012-03-30 07:10:13Z bennylp $ */ +/* $Id: os_core_unix.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -97,7 +97,18 @@ struct pj_sem_t #if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0 struct pj_event_t { - char obj_name[PJ_MAX_OBJ_NAME]; + enum event_state { + EV_STATE_OFF, + EV_STATE_SET, + EV_STATE_PULSED + } state; + + pj_mutex_t mutex; + pthread_cond_t cond; + + pj_bool_t auto_reset; + unsigned threads_waiting; + unsigned threads_to_release; }; #endif /* PJ_HAS_EVENT_OBJ */ @@ -1700,13 +1711,48 @@ PJ_DEF(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name, pj_bool_t manual_reset, pj_bool_t initial, pj_event_t **ptr_event) { - pj_assert(!"Not supported!"); - PJ_UNUSED_ARG(pool); - PJ_UNUSED_ARG(name); - PJ_UNUSED_ARG(manual_reset); - PJ_UNUSED_ARG(initial); - PJ_UNUSED_ARG(ptr_event); - return PJ_EINVALIDOP; + pj_event_t *event; + + event = PJ_POOL_ALLOC_T(pool, pj_event_t); + + init_mutex(&event->mutex, name, PJ_MUTEX_SIMPLE); + pthread_cond_init(&event->cond, 0); + event->auto_reset = !manual_reset; + event->threads_waiting = 0; + + if (initial) { + event->state = EV_STATE_SET; + event->threads_to_release = 1; + } else { + event->state = EV_STATE_OFF; + event->threads_to_release = 0; + } + + *ptr_event = event; + return PJ_SUCCESS; +} + +static void event_on_one_release(pj_event_t *event) +{ + if (event->state == EV_STATE_SET) { + if (event->auto_reset) { + event->threads_to_release = 0; + event->state = EV_STATE_OFF; + } else { + /* Manual reset remains on */ + } + } else { + if (event->auto_reset) { + /* Only release one */ + event->threads_to_release = 0; + event->state = EV_STATE_OFF; + } else { + event->threads_to_release--; + pj_assert(event->threads_to_release >= 0); + if (event->threads_to_release==0) + event->state = EV_STATE_OFF; + } + } } /* @@ -1714,8 +1760,14 @@ PJ_DEF(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name, */ PJ_DEF(pj_status_t) pj_event_wait(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pthread_mutex_lock(&event->mutex.mutex); + event->threads_waiting++; + while (event->state == EV_STATE_OFF) + pthread_cond_wait(&event->cond, &event->mutex.mutex); + event->threads_waiting--; + event_on_one_release(event); + pthread_mutex_unlock(&event->mutex.mutex); + return PJ_SUCCESS; } /* @@ -1723,8 +1775,16 @@ PJ_DEF(pj_status_t) pj_event_wait(pj_event_t *event) */ PJ_DEF(pj_status_t) pj_event_trywait(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pj_status_t status; + + pthread_mutex_lock(&event->mutex.mutex); + status = event->state != EV_STATE_OFF ? PJ_SUCCESS : -1; + if (status==PJ_SUCCESS) { + event_on_one_release(event); + } + pthread_mutex_unlock(&event->mutex.mutex); + + return status; } /* @@ -1732,8 +1792,15 @@ PJ_DEF(pj_status_t) pj_event_trywait(pj_event_t *event) */ PJ_DEF(pj_status_t) pj_event_set(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pthread_mutex_lock(&event->mutex.mutex); + event->threads_to_release = 1; + event->state = EV_STATE_SET; + if (event->auto_reset) + pthread_cond_signal(&event->cond); + else + pthread_cond_broadcast(&event->cond); + pthread_mutex_unlock(&event->mutex.mutex); + return PJ_SUCCESS; } /* @@ -1741,8 +1808,18 @@ PJ_DEF(pj_status_t) pj_event_set(pj_event_t *event) */ PJ_DEF(pj_status_t) pj_event_pulse(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pthread_mutex_lock(&event->mutex.mutex); + if (event->threads_waiting) { + event->threads_to_release = event->auto_reset ? 1 : + event->threads_waiting; + event->state = EV_STATE_PULSED; + if (event->threads_to_release==1) + pthread_cond_signal(&event->cond); + else + pthread_cond_broadcast(&event->cond); + } + pthread_mutex_unlock(&event->mutex.mutex); + return PJ_SUCCESS; } /* @@ -1750,8 +1827,11 @@ PJ_DEF(pj_status_t) pj_event_pulse(pj_event_t *event) */ PJ_DEF(pj_status_t) pj_event_reset(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pthread_mutex_lock(&event->mutex.mutex); + event->state = EV_STATE_OFF; + event->threads_to_release = 0; + pthread_mutex_unlock(&event->mutex.mutex); + return PJ_SUCCESS; } /* @@ -1759,8 +1839,9 @@ PJ_DEF(pj_status_t) pj_event_reset(pj_event_t *event) */ PJ_DEF(pj_status_t) pj_event_destroy(pj_event_t *event) { - PJ_UNUSED_ARG(event); - return PJ_EINVALIDOP; + pj_mutex_destroy(&event->mutex); + pthread_cond_destroy(&event->cond); + return PJ_SUCCESS; } #endif /* PJ_HAS_EVENT_OBJ */ diff --git a/pjlib/src/pj/os_info.c b/pjlib/src/pj/os_info.c index be67120..1d6e007 100644 --- a/pjlib/src/pj/os_info.c +++ b/pjlib/src/pj/os_info.c @@ -1,4 +1,4 @@ -/* $Id: os_info.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: os_info.c 4411 2013-03-04 04:34:38Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -242,6 +242,9 @@ PJ_DEF(const pj_sys_info*) pj_get_sys_info(void) } else { si.os_name = pj_str("Unknown"); } + + /* Avoid compile warning on Symbian. */ + goto get_sdk_info; } #endif diff --git a/pjlib/src/pj/pool.c b/pjlib/src/pj/pool.c index 9992df7..90443b9 100644 --- a/pjlib/src/pj/pool.c +++ b/pjlib/src/pj/pool.c @@ -1,4 +1,4 @@ -/* $Id: pool.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: pool.c 4298 2012-11-22 05:00:01Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -88,7 +88,7 @@ static pj_pool_block *pj_pool_create_block( pj_pool_t *pool, pj_size_t size) * If no space is available in all the blocks, a new block might be created * (depending on whether the pool is allowed to resize). */ -PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size) +PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, pj_size_t size) { pj_pool_block *block = pool->block_list.next; void *p; @@ -121,7 +121,7 @@ PJ_DEF(void*) pj_pool_allocate_find(pj_pool_t *pool, unsigned size) if (pool->increment_size < size + sizeof(pj_pool_block) + PJ_POOL_ALIGNMENT) { - unsigned count; + pj_size_t count; count = (size + pool->increment_size + sizeof(pj_pool_block) + PJ_POOL_ALIGNMENT) / pool->increment_size; diff --git a/pjlib/src/pj/pool_caching.c b/pjlib/src/pj/pool_caching.c index a15c3d9..60659ec 100644 --- a/pjlib/src/pj/pool_caching.c +++ b/pjlib/src/pj/pool_caching.c @@ -1,4 +1,4 @@ -/* $Id: pool_caching.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: pool_caching.c 4298 2012-11-22 05:00:01Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -178,7 +178,11 @@ static pj_pool_t* cpool_create_pool(pj_pool_factory *pf, pj_pool_init_int(pool, name, increment_sz, callback); /* Update pool manager's free capacity. */ - cp->capacity -= pj_pool_get_capacity(pool); + if (cp->capacity > pj_pool_get_capacity(pool)) { + cp->capacity -= pj_pool_get_capacity(pool); + } else { + cp->capacity = 0; + } PJ_LOG(6, (pool->obj_name, "pool reused, size=%u", pool->capacity)); } @@ -199,7 +203,7 @@ static pj_pool_t* cpool_create_pool(pj_pool_factory *pf, static void cpool_release_pool( pj_pool_factory *pf, pj_pool_t *pool) { pj_caching_pool *cp = (pj_caching_pool*)pf; - unsigned pool_capacity; + pj_size_t pool_capacity; unsigned i; PJ_CHECK_STACK(); diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c index ed9fde9..8ed2d5d 100644 --- a/pjlib/src/pj/sock_bsd.c +++ b/pjlib/src/pj/sock_bsd.c @@ -1,4 +1,4 @@ -/* $Id: sock_bsd.c 4170 2012-06-19 07:40:19Z bennylp $ */ +/* $Id: sock_bsd.c 4233 2012-08-21 11:16:06Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -723,7 +723,6 @@ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock, { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(buf && len, PJ_EINVAL); - PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL)); *len = recvfrom(sock, (char*)buf, *len, flags, (struct sockaddr*)from, (socklen_t*)fromlen); @@ -731,7 +730,9 @@ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock, if (*len < 0) return PJ_RETURN_OS_ERROR(pj_get_native_netos_error()); else { - PJ_SOCKADDR_RESET_LEN(from); + if (from) { + PJ_SOCKADDR_RESET_LEN(from); + } return PJ_SUCCESS; } } diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c index dd2ef6e..1528b5f 100644 --- a/pjlib/src/pj/sock_common.c +++ b/pjlib/src/pj/sock_common.c @@ -1,4 +1,4 @@ -/* $Id: sock_common.c 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: sock_common.c 4343 2013-02-07 09:35:34Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -956,42 +957,54 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) return PJ_SUCCESS; } -/* Get the default IP interface */ -PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) +/* Get IP interface for sending to the specified destination */ +PJ_DEF(pj_status_t) pj_getipinterface(int af, + const pj_str_t *dst, + pj_sockaddr *itf_addr, + pj_bool_t allow_resolve, + pj_sockaddr *p_dst_addr) { + pj_sockaddr dst_addr; pj_sock_t fd; - pj_str_t cp; - pj_sockaddr a; int len; pj_uint8_t zero[64]; pj_status_t status; - addr->addr.sa_family = (pj_uint16_t)af; - - status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd); + pj_sockaddr_init(af, &dst_addr, NULL, 53); + status = pj_inet_pton(af, dst, pj_sockaddr_get_addr(&dst_addr)); if (status != PJ_SUCCESS) { - return status; - } + /* "dst" is not an IP address. */ + if (allow_resolve) { + status = pj_sockaddr_init(af, &dst_addr, dst, 53); + } else { + pj_str_t cp; - if (af == PJ_AF_INET) { - cp = pj_str("1.1.1.1"); - } else { - cp = pj_str("1::1"); + if (af == PJ_AF_INET) { + cp = pj_str("1.1.1.1"); + } else { + cp = pj_str("1::1"); + } + status = pj_sockaddr_init(af, &dst_addr, &cp, 53); + } + + if (status != PJ_SUCCESS) + return status; } - status = pj_sockaddr_init(af, &a, &cp, 53); + + /* Create UDP socket and connect() to the destination IP */ + status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd); if (status != PJ_SUCCESS) { - pj_sock_close(fd); return status; } - status = pj_sock_connect(fd, &a, pj_sockaddr_get_len(&a)); + status = pj_sock_connect(fd, &dst_addr, pj_sockaddr_get_len(&dst_addr)); if (status != PJ_SUCCESS) { pj_sock_close(fd); return status; } - len = sizeof(a); - status = pj_sock_getsockname(fd, &a, &len); + len = sizeof(*itf_addr); + status = pj_sock_getsockname(fd, itf_addr, &len); if (status != PJ_SUCCESS) { pj_sock_close(fd); return status; @@ -1001,18 +1014,70 @@ PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) /* Check that the address returned is not zero */ pj_bzero(zero, sizeof(zero)); - if (pj_memcmp(pj_sockaddr_get_addr(&a), zero, - pj_sockaddr_get_addr_len(&a))==0) + if (pj_memcmp(pj_sockaddr_get_addr(itf_addr), zero, + pj_sockaddr_get_addr_len(itf_addr))==0) { return PJ_ENOTFOUND; } - pj_sockaddr_copy_addr(addr, &a); + if (p_dst_addr) + *p_dst_addr = dst_addr; - /* Success */ return PJ_SUCCESS; } +/* Get the default IP interface */ +PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) +{ + pj_str_t cp; + + if (af == PJ_AF_INET) { + cp = pj_str("1.1.1.1"); + } else { + cp = pj_str("1::1"); + } + + return pj_getipinterface(af, &cp, addr, PJ_FALSE, NULL); +} + + +/* + * Bind socket at random port. + */ +PJ_DEF(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd, + const pj_sockaddr_t *addr, + pj_uint16_t port_range, + pj_uint16_t max_try) +{ + pj_sockaddr bind_addr; + int addr_len; + pj_uint16_t base_port; + pj_status_t status = PJ_SUCCESS; + + PJ_CHECK_STACK(); + + PJ_ASSERT_RETURN(addr, PJ_EINVAL); + + pj_sockaddr_cp(&bind_addr, addr); + addr_len = pj_sockaddr_get_len(addr); + base_port = pj_sockaddr_get_port(addr); + + if (base_port == 0 || port_range == 0) { + return pj_sock_bind(sockfd, &bind_addr, addr_len); + } + + for (; max_try; --max_try) { + pj_uint16_t port; + port = (pj_uint16_t)(base_port + pj_rand() % (port_range + 1)); + pj_sockaddr_set_port(&bind_addr, port); + status = pj_sock_bind(sockfd, &bind_addr, addr_len); + if (status == PJ_SUCCESS) + break; + } + + return status; +} + /* Only need to implement these in DLL build */ #if defined(PJ_DLL) diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c index 82ad2a5..4b1d0a7 100644 --- a/pjlib/src/pj/ssl_sock_ossl.c +++ b/pjlib/src/pj/ssl_sock_ossl.c @@ -1,4 +1,4 @@ -/* $Id: ssl_sock_ossl.c 4146 2012-05-30 06:35:59Z nanang $ */ +/* $Id: ssl_sock_ossl.c 4349 2013-02-14 09:38:31Z nanang $ */ /* * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com) * @@ -105,9 +105,10 @@ typedef struct read_data_t ssock->param.read_buffer_size) /* - * Structure of SSL socket write buffer. + * Structure of SSL socket write data. */ typedef struct write_data_t { + PJ_DECL_LIST_MEMBER(struct write_data_t); pj_ioqueue_op_key_t key; pj_size_t record_len; pj_ioqueue_op_key_t *app_key; @@ -121,23 +122,14 @@ typedef struct write_data_t { } write_data_t; /* - * Structure of SSL socket write state. + * Structure of SSL socket write buffer (circular buffer). */ -typedef struct write_state_t { +typedef struct send_buf_t { char *buf; pj_size_t max_len; char *start; pj_size_t len; - write_data_t *last_data; -} write_state_t; - -/* - * Structure of write data pending. - */ -typedef struct write_pending_t { - PJ_DECL_LIST_MEMBER(struct write_pending_t); - write_data_t data; -} write_pending_t; +} send_buf_t; /* * Secure socket structure definition. @@ -173,10 +165,12 @@ struct pj_ssl_sock_t void **asock_rbuf; read_data_t *ssock_rbuf; - write_state_t write_state; - write_pending_t write_pending; - write_pending_t write_pending_empty; - pj_lock_t *write_mutex; /* protect write BIO and write_state */ + write_data_t write_pending;/* list of pending write to OpenSSL */ + write_data_t write_pending_empty; /* cache for write_pending */ + pj_bool_t flushing_write_pend; /* flag of flushing is ongoing*/ + send_buf_t send_buf; + write_data_t send_pending; /* list of pending write to network */ + pj_lock_t *write_mutex; /* protect write BIO and send_buf */ SSL_CTX *ossl_ctx; SSL *ossl_ssl; @@ -197,6 +191,8 @@ struct pj_ssl_cert_t }; +static write_data_t* alloc_send_data(pj_ssl_sock_t *ssock, pj_size_t len); +static void free_send_data(pj_ssl_sock_t *ssock, write_data_t *wdata); static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock); /* @@ -1054,6 +1050,179 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock, return PJ_TRUE; } +static write_data_t* alloc_send_data(pj_ssl_sock_t *ssock, pj_size_t len) +{ + send_buf_t *send_buf = &ssock->send_buf; + pj_size_t avail_len, skipped_len = 0; + char *reg1, *reg2; + pj_size_t reg1_len, reg2_len; + write_data_t *p; + + /* Check buffer availability */ + avail_len = send_buf->max_len - send_buf->len; + if (avail_len < len) + return NULL; + + /* If buffer empty, reset start pointer and return it */ + if (send_buf->len == 0) { + send_buf->start = send_buf->buf; + send_buf->len = len; + p = (write_data_t*)send_buf->start; + goto init_send_data; + } + + /* Free space may be wrapped/splitted into two regions, so let's + * analyze them if any region can hold the write data. + */ + reg1 = send_buf->start + send_buf->len; + if (reg1 >= send_buf->buf + send_buf->max_len) + reg1 -= send_buf->max_len; + reg1_len = send_buf->max_len - send_buf->len; + if (reg1 + reg1_len > send_buf->buf + send_buf->max_len) { + reg1_len = send_buf->buf + send_buf->max_len - reg1; + reg2 = send_buf->buf; + reg2_len = send_buf->start - send_buf->buf; + } else { + reg2 = NULL; + reg2_len = 0; + } + + /* More buffer availability check, note that the write data must be in + * a contigue buffer. + */ + avail_len = PJ_MAX(reg1_len, reg2_len); + if (avail_len < len) + return NULL; + + /* Get the data slot */ + if (reg1_len >= len) { + p = (write_data_t*)reg1; + } else { + p = (write_data_t*)reg2; + skipped_len = reg1_len; + } + + /* Update buffer length */ + send_buf->len += len + skipped_len; + +init_send_data: + /* Init the new send data */ + pj_bzero(p, sizeof(*p)); + pj_list_init(p); + pj_list_push_back(&ssock->send_pending, p); + + return p; +} + +static void free_send_data(pj_ssl_sock_t *ssock, write_data_t *wdata) +{ + send_buf_t *buf = &ssock->send_buf; + write_data_t *spl = &ssock->send_pending; + + pj_assert(!pj_list_empty(&ssock->send_pending)); + + /* Free slot from the buffer */ + if (spl->next == wdata && spl->prev == wdata) { + /* This is the only data, reset the buffer */ + buf->start = buf->buf; + buf->len = 0; + } else if (spl->next == wdata) { + /* This is the first data, shift start pointer of the buffer and + * adjust the buffer length. + */ + buf->start = (char*)wdata->next; + if (wdata->next > wdata) { + buf->len -= ((char*)wdata->next - buf->start); + } else { + /* Overlapped */ + unsigned right_len, left_len; + right_len = buf->buf + buf->max_len - (char*)wdata; + left_len = (char*)wdata->next - buf->buf; + buf->len -= (right_len + left_len); + } + } else if (spl->prev == wdata) { + /* This is the last data, just adjust the buffer length */ + if (wdata->prev < wdata) { + unsigned jump_len; + jump_len = (char*)wdata - + ((char*)wdata->prev + wdata->prev->record_len); + buf->len -= (wdata->record_len + jump_len); + } else { + /* Overlapped */ + unsigned right_len, left_len; + right_len = buf->buf + buf->max_len - + ((char*)wdata->prev + wdata->prev->record_len); + left_len = (char*)wdata + wdata->record_len - buf->buf; + buf->len -= (right_len + left_len); + } + } + /* For data in the middle buffer, just do nothing on the buffer. The slot + * will be freed later when freeing the first/last data. + */ + + /* Remove the data from send pending list */ + pj_list_erase(wdata); +} + +#if 0 +/* Just for testing send buffer alloc/free */ +#include +pj_status_t pj_ssl_sock_ossl_test_send_buf(pj_pool_t *pool) +{ + enum { MAX_CHUNK_NUM = 20 }; + unsigned chunk_size, chunk_cnt, i; + write_data_t *wdata[MAX_CHUNK_NUM] = {0}; + pj_time_val now; + pj_ssl_sock_t *ssock = NULL; + pj_ssl_sock_param param; + pj_status_t status; + + pj_gettimeofday(&now); + pj_srand((unsigned)now.sec); + + pj_ssl_sock_param_default(¶m); + status = pj_ssl_sock_create(pool, ¶m, &ssock); + if (status != PJ_SUCCESS) { + return status; + } + + if (ssock->send_buf.max_len == 0) { + ssock->send_buf.buf = (char*) + pj_pool_alloc(ssock->pool, + ssock->param.send_buffer_size); + ssock->send_buf.max_len = ssock->param.send_buffer_size; + ssock->send_buf.start = ssock->send_buf.buf; + ssock->send_buf.len = 0; + } + + chunk_size = ssock->param.send_buffer_size / MAX_CHUNK_NUM / 2; + chunk_cnt = 0; + for (i = 0; i < MAX_CHUNK_NUM; i++) { + wdata[i] = alloc_send_data(ssock, pj_rand() % chunk_size + 321); + if (wdata[i]) + chunk_cnt++; + else + break; + } + + while (chunk_cnt) { + i = pj_rand() % MAX_CHUNK_NUM; + if (wdata[i]) { + free_send_data(ssock, wdata[i]); + wdata[i] = NULL; + chunk_cnt--; + } + } + + if (ssock->send_buf.len != 0) + status = PJ_EBUG; + + pj_ssl_sock_close(ssock); + return status; +} +#endif + + /* Flush write BIO to network socket. Note that any access to write BIO * MUST be serialized, so mutex protection must cover any call to OpenSSL * API (that possibly generate data for write BIO) along with the call to @@ -1067,76 +1236,39 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock, { char *data; pj_ssize_t len; - - write_state_t *write_st = &ssock->write_state; write_data_t *wdata; - pj_size_t avail_len, needed_len, skipped_len = 0; + pj_size_t needed_len; pj_status_t status; + pj_lock_acquire(ssock->write_mutex); + /* Check if there is data in write BIO, flush it if any */ - if (!BIO_pending(ssock->ossl_wbio)) + if (!BIO_pending(ssock->ossl_wbio)) { + pj_lock_release(ssock->write_mutex); return PJ_SUCCESS; + } /* Get data and its length */ len = BIO_get_mem_data(ssock->ossl_wbio, &data); - if (len == 0) + if (len == 0) { + pj_lock_release(ssock->write_mutex); return PJ_SUCCESS; + } /* Calculate buffer size needed, and align it to 8 */ needed_len = len + sizeof(write_data_t); needed_len = ((needed_len + 7) >> 3) << 3; - /* Check buffer availability */ - avail_len = write_st->max_len - write_st->len; - if (avail_len < needed_len) + /* Allocate buffer for send data */ + wdata = alloc_send_data(ssock, needed_len); + if (wdata == NULL) { + pj_lock_release(ssock->write_mutex); return PJ_ENOMEM; - - /* More buffer availability check, note that the write data must be in - * a contigue buffer. - */ - if (write_st->len == 0) { - - write_st->start = write_st->buf; - wdata = (write_data_t*)write_st->start; - - } else { - - char *reg1, *reg2; - pj_size_t reg1_len, reg2_len; - - /* Unused slots may be wrapped/splitted into two regions, so let's - * analyze them if any region can hold the write data. - */ - reg1 = write_st->start + write_st->len; - if (reg1 >= write_st->buf + write_st->max_len) - reg1 -= write_st->max_len; - reg1_len = write_st->max_len - write_st->len; - if (reg1 + reg1_len > write_st->buf + write_st->max_len) { - reg1_len = write_st->buf + write_st->max_len - reg1; - reg2 = write_st->buf; - reg2_len = write_st->start - write_st->buf; - } else { - reg2 = NULL; - reg2_len = 0; - } - avail_len = PJ_MAX(reg1_len, reg2_len); - if (avail_len < needed_len) - return PJ_ENOMEM; - - /* Get write data pointer and update buffer length */ - if (reg1_len >= needed_len) { - wdata = (write_data_t*)reg1; - } else { - wdata = (write_data_t*)reg2; - /* Unused slot in region 1 is skipped as current write data - * doesn't fit it. - */ - skipped_len = reg1_len; - } } - /* Copy the data and set its properties into the buffer */ - pj_bzero(wdata, sizeof(write_data_t)); + /* Copy the data and set its properties into the send data */ + pj_ioqueue_op_key_init(&wdata->key, sizeof(pj_ioqueue_op_key_t)); + wdata->key.user_data = wdata; wdata->app_key = send_key; wdata->record_len = needed_len; wdata->data_len = len; @@ -1144,6 +1276,12 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock, wdata->flags = flags; pj_memcpy(&wdata->data, data, len); + /* Reset write BIO */ + BIO_reset(ssock->ossl_wbio); + + /* Ticket #1573: Don't hold mutex while calling PJLIB socket send(). */ + pj_lock_release(ssock->write_mutex); + /* Send it */ if (ssock->param.sock_type == pj_SOCK_STREAM()) { status = pj_activesock_send(ssock->asock, &wdata->key, @@ -1157,24 +1295,13 @@ static pj_status_t flush_write_bio(pj_ssl_sock_t *ssock, ssock->addr_len); } - /* Oh no, EWOULDBLOCK! */ - if (status == PJ_STATUS_FROM_OS(OSERR_EWOULDBLOCK)) { - /* Just return PJ_SUCCESS here, the pending data will be sent in next - * call of this function since the data is still stored in write BIO. + if (status != PJ_EPENDING) { + /* When the sending is not pending, remove the wdata from send + * pending list. */ - return PJ_SUCCESS; - } - - /* Reset write BIO after flushed */ - BIO_reset(ssock->ossl_wbio); - - if (status == PJ_EPENDING) { - /* Update write state */ - pj_assert(skipped_len==0 || write_st->last_data); - write_st->len += needed_len + skipped_len; - if (write_st->last_data) - write_st->last_data->record_len += skipped_len; - write_st->last_data = wdata; + pj_lock_acquire(ssock->write_mutex); + free_send_data(ssock, wdata); + pj_lock_release(ssock->write_mutex); } return status; @@ -1213,22 +1340,19 @@ static pj_status_t do_handshake(pj_ssl_sock_t *ssock) pj_status_t status; int err; - pj_lock_acquire(ssock->write_mutex); - /* Perform SSL handshake */ + pj_lock_acquire(ssock->write_mutex); err = SSL_do_handshake(ssock->ossl_ssl); + pj_lock_release(ssock->write_mutex); /* SSL_do_handshake() may put some pending data into SSL write BIO, * flush it if any. */ status = flush_write_bio(ssock, &ssock->handshake_op_key, 0, 0); if (status != PJ_SUCCESS && status != PJ_EPENDING) { - pj_lock_release(ssock->write_mutex); return status; } - pj_lock_release(ssock->write_mutex); - if (err < 0) { err = SSL_get_error(ssock->ossl_ssl, err); if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ) @@ -1356,9 +1480,15 @@ static pj_bool_t asock_on_data_read (pj_activesock_t *asock, /* Update certificates */ update_certs_info(ssock); - pj_lock_acquire(ssock->write_mutex); + // Ticket #1573: Don't hold mutex while calling + // PJLIB socket send(). + //pj_lock_acquire(ssock->write_mutex); status = flush_delayed_send(ssock); - pj_lock_release(ssock->write_mutex); + //pj_lock_release(ssock->write_mutex); + + /* If flushing is ongoing, treat it as success */ + if (status == PJ_EBUSY) + status = PJ_SUCCESS; if (status != PJ_SUCCESS && status != PJ_EPENDING) { PJ_PERROR(1,(ssock->pool->obj_name, status, @@ -1418,11 +1548,14 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock, } else if (send_key != &ssock->handshake_op_key) { /* Some data has been sent, notify application */ - write_data_t *wdata = (write_data_t*)send_key; + write_data_t *wdata = (write_data_t*)send_key->user_data; if (ssock->param.cb.on_data_sent) { pj_bool_t ret; + pj_ssize_t sent_len; + + sent_len = (sent > 0)? wdata->plain_data_len : sent; ret = (*ssock->param.cb.on_data_sent)(ssock, wdata->app_key, - wdata->plain_data_len); + sent_len); if (!ret) { /* We've been destroyed */ return PJ_FALSE; @@ -1431,12 +1564,7 @@ static pj_bool_t asock_on_data_sent (pj_activesock_t *asock, /* Update write buffer state */ pj_lock_acquire(ssock->write_mutex); - ssock->write_state.start += wdata->record_len; - ssock->write_state.len -= wdata->record_len; - if (ssock->write_state.last_data == wdata) { - pj_assert(ssock->write_state.len == 0); - ssock->write_state.last_data = NULL; - } + free_send_data(ssock, wdata); pj_lock_release(ssock->write_mutex); } else { @@ -1547,13 +1675,13 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, goto on_return; /* Prepare write/send state */ - pj_assert(ssock->write_state.max_len == 0); - ssock->write_state.buf = (char*) - pj_pool_alloc(ssock->pool, - ssock->param.send_buffer_size); - ssock->write_state.max_len = ssock->param.send_buffer_size; - ssock->write_state.start = ssock->write_state.buf; - ssock->write_state.len = 0; + pj_assert(ssock->send_buf.max_len == 0); + ssock->send_buf.buf = (char*) + pj_pool_alloc(ssock->pool, + ssock->param.send_buffer_size); + ssock->send_buf.max_len = ssock->param.send_buffer_size; + ssock->send_buf.start = ssock->send_buf.buf; + ssock->send_buf.len = 0; /* Start handshake timer */ if (ssock->param.timer_heap && (ssock->param.timeout.sec != 0 || @@ -1626,13 +1754,13 @@ static pj_bool_t asock_on_connect_complete (pj_activesock_t *asock, goto on_return; /* Prepare write/send state */ - pj_assert(ssock->write_state.max_len == 0); - ssock->write_state.buf = (char*) + pj_assert(ssock->send_buf.max_len == 0); + ssock->send_buf.buf = (char*) pj_pool_alloc(ssock->pool, ssock->param.send_buffer_size); - ssock->write_state.max_len = ssock->param.send_buffer_size; - ssock->write_state.start = ssock->write_state.buf; - ssock->write_state.len = 0; + ssock->send_buf.max_len = ssock->param.send_buffer_size; + ssock->send_buf.start = ssock->send_buf.buf; + ssock->send_buf.len = 0; #ifdef SSL_set_tlsext_host_name /* Set server name to connect */ @@ -1805,7 +1933,10 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool, ssock->ssl_state = SSL_STATE_NULL; pj_list_init(&ssock->write_pending); pj_list_init(&ssock->write_pending_empty); + pj_list_init(&ssock->send_pending); pj_timer_entry_init(&ssock->timer, 0, ssock, &on_timer); + pj_ioqueue_op_key_init(&ssock->handshake_op_key, + sizeof(pj_ioqueue_op_key_t)); /* Create secure socket mutex */ status = pj_lock_create_recursive_mutex(pool, pool->obj_name, @@ -2038,10 +2169,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_recvfrom2 (pj_ssl_sock_t *ssock, return PJ_ENOTSUP; } -/* Write plain data to SSL and flush write BIO. Note that accessing - * write BIO must be serialized, so a call to this function must be - * protected by write mutex of SSL socket. - */ +/* Write plain data to SSL and flush write BIO. */ static pj_status_t ssl_write(pj_ssl_sock_t *ssock, pj_ioqueue_op_key_t *send_key, const void *data, @@ -2056,7 +2184,9 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock, * negotitation may be on progress, so sending data should be delayed * until re-negotiation is completed. */ + pj_lock_acquire(ssock->write_mutex); nwritten = SSL_write(ssock->ossl_ssl, data, size); + pj_lock_release(ssock->write_mutex); if (nwritten == size) { /* All data written, flush write BIO to network socket */ @@ -2087,56 +2217,81 @@ static pj_status_t ssl_write(pj_ssl_sock_t *ssock, return status; } -/* Flush delayed data sending in the write pending list. Note that accessing - * write pending list must be serialized, so a call to this function must be - * protected by write mutex of SSL socket. - */ +/* Flush delayed data sending in the write pending list. */ static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock) { + /* Check for another ongoing flush */ + if (ssock->flushing_write_pend) + return PJ_EBUSY; + + pj_lock_acquire(ssock->write_mutex); + + /* Again, check for another ongoing flush */ + if (ssock->flushing_write_pend) { + pj_lock_release(ssock->write_mutex); + return PJ_EBUSY; + } + + /* Set ongoing flush flag */ + ssock->flushing_write_pend = PJ_TRUE; + while (!pj_list_empty(&ssock->write_pending)) { - write_pending_t *wp; + write_data_t *wp; pj_status_t status; wp = ssock->write_pending.next; - status = ssl_write(ssock, &wp->data.key, wp->data.data.ptr, - wp->data.plain_data_len, wp->data.flags); - if (status != PJ_SUCCESS) + /* Ticket #1573: Don't hold mutex while calling socket send. */ + pj_lock_release(ssock->write_mutex); + + status = ssl_write(ssock, &wp->key, wp->data.ptr, + wp->plain_data_len, wp->flags); + if (status != PJ_SUCCESS) { + /* Reset ongoing flush flag first. */ + ssock->flushing_write_pend = PJ_FALSE; return status; + } + pj_lock_acquire(ssock->write_mutex); pj_list_erase(wp); pj_list_push_back(&ssock->write_pending_empty, wp); } + /* Reset ongoing flush flag */ + ssock->flushing_write_pend = PJ_FALSE; + + pj_lock_release(ssock->write_mutex); + return PJ_SUCCESS; } -/* Sending is delayed, push back the sending data into pending list. Note that - * accessing write pending list must be serialized, so a call to this function - * must be protected by write mutex of SSL socket. - */ +/* Sending is delayed, push back the sending data into pending list. */ static pj_status_t delay_send (pj_ssl_sock_t *ssock, pj_ioqueue_op_key_t *send_key, const void *data, pj_ssize_t size, unsigned flags) { - write_pending_t *wp; + write_data_t *wp; + + pj_lock_acquire(ssock->write_mutex); /* Init write pending instance */ if (!pj_list_empty(&ssock->write_pending_empty)) { wp = ssock->write_pending_empty.next; pj_list_erase(wp); } else { - wp = PJ_POOL_ZALLOC_T(ssock->pool, write_pending_t); + wp = PJ_POOL_ZALLOC_T(ssock->pool, write_data_t); } - wp->data.app_key = send_key; - wp->data.plain_data_len = size; - wp->data.data.ptr = data; - wp->data.flags = flags; + wp->app_key = send_key; + wp->plain_data_len = size; + wp->data.ptr = data; + wp->flags = flags; pj_list_push_back(&ssock->write_pending, wp); + + pj_lock_release(ssock->write_mutex); /* Must return PJ_EPENDING */ return PJ_EPENDING; @@ -2156,14 +2311,15 @@ PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock, PJ_ASSERT_RETURN(ssock && data && size && (*size>0), PJ_EINVAL); PJ_ASSERT_RETURN(ssock->ssl_state==SSL_STATE_ESTABLISHED, PJ_EINVALIDOP); - pj_lock_acquire(ssock->write_mutex); + // Ticket #1573: Don't hold mutex while calling PJLIB socket send(). + //pj_lock_acquire(ssock->write_mutex); /* Flush delayed send first. Sending data might be delayed when * re-negotiation is on-progress. */ status = flush_delayed_send(ssock); if (status == PJ_EBUSY) { - /* Re-negotiation is on progress, delay sending */ + /* Re-negotiation or flushing is on progress, delay sending */ status = delay_send(ssock, send_key, data, *size, flags); goto on_return; } else if (status != PJ_SUCCESS) { @@ -2178,7 +2334,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_send (pj_ssl_sock_t *ssock, } on_return: - pj_lock_release(ssock->write_mutex); + //pj_lock_release(ssock->write_mutex); return status; } diff --git a/pjlib/src/pj/timer.c b/pjlib/src/pj/timer.c index e78cba3..7951955 100644 --- a/pjlib/src/pj/timer.c +++ b/pjlib/src/pj/timer.c @@ -1,4 +1,4 @@ -/* $Id: timer.c 4154 2012-06-05 10:41:17Z bennylp $ */ +/* $Id: timer.c 4359 2013-02-21 11:18:36Z bennylp $ */ /* * The PJLIB's timer heap is based (or more correctly, copied and modied) * from ACE library by Douglas C. Schmidt. ACE is an excellent OO framework @@ -35,6 +35,7 @@ #include #include #include +#include #define THIS_FILE "timer.c" @@ -451,20 +452,27 @@ PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry, entry->id = id; entry->user_data = user_data; entry->cb = cb; + entry->_grp_lock = NULL; return entry; } #if PJ_TIMER_DEBUG -PJ_DEF(pj_status_t) pj_timer_heap_schedule_dbg( pj_timer_heap_t *ht, - pj_timer_entry *entry, - const pj_time_val *delay, - const char *src_file, - int src_line) +static pj_status_t schedule_w_grp_lock_dbg(pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + pj_bool_t set_id, + int id_val, + pj_grp_lock_t *grp_lock, + const char *src_file, + int src_line) #else -PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, - pj_timer_entry *entry, - const pj_time_val *delay) +static pj_status_t schedule_w_grp_lock(pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + pj_bool_t set_id, + int id_val, + pj_grp_lock_t *grp_lock) #endif { pj_status_t status; @@ -485,13 +493,66 @@ PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, lock_timer_heap(ht); status = schedule_entry(ht, entry, &expires); + if (status == PJ_SUCCESS) { + if (set_id) + entry->id = id_val; + entry->_grp_lock = grp_lock; + if (entry->_grp_lock) { + pj_grp_lock_add_ref(entry->_grp_lock); + } + } unlock_timer_heap(ht); return status; } -PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, - pj_timer_entry *entry) + +#if PJ_TIMER_DEBUG +PJ_DEF(pj_status_t) pj_timer_heap_schedule_dbg( pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + const char *src_file, + int src_line) +{ + return schedule_w_grp_lock_dbg(ht, entry, delay, PJ_FALSE, 1, NULL, + src_file, src_line); +} + +PJ_DEF(pj_status_t) pj_timer_heap_schedule_w_grp_lock_dbg( + pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + int id_val, + pj_grp_lock_t *grp_lock, + const char *src_file, + int src_line) +{ + return schedule_w_grp_lock_dbg(ht, entry, delay, PJ_TRUE, id_val, + grp_lock, src_file, src_line); +} + +#else +PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay) +{ + return schedule_w_grp_lock(ht, entry, delay, PJ_FALSE, 1, NULL); +} + +PJ_DEF(pj_status_t) pj_timer_heap_schedule_w_grp_lock(pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + int id_val, + pj_grp_lock_t *grp_lock) +{ + return schedule_w_grp_lock(ht, entry, delay, PJ_TRUE, id_val, grp_lock); +} +#endif + +static int cancel_timer(pj_timer_heap_t *ht, + pj_timer_entry *entry, + pj_bool_t set_id, + int id_val) { int count; @@ -499,11 +560,32 @@ PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, lock_timer_heap(ht); count = cancel(ht, entry, 1); + if (set_id) { + entry->id = id_val; + } + if (entry->_grp_lock) { + pj_grp_lock_t *grp_lock = entry->_grp_lock; + entry->_grp_lock = NULL; + pj_grp_lock_dec_ref(grp_lock); + } unlock_timer_heap(ht); return count; } +PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, + pj_timer_entry *entry) +{ + return cancel_timer(ht, entry, PJ_FALSE, 0); +} + +PJ_DEF(int) pj_timer_heap_cancel_if_active(pj_timer_heap_t *ht, + pj_timer_entry *entry, + int id_val) +{ + return cancel_timer(ht, entry, PJ_TRUE, id_val); +} + PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay ) { @@ -512,25 +594,38 @@ PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, PJ_ASSERT_RETURN(ht, 0); + lock_timer_heap(ht); if (!ht->cur_size && next_delay) { next_delay->sec = next_delay->msec = PJ_MAXINT32; + unlock_timer_heap(ht); return 0; } count = 0; pj_gettickcount(&now); - lock_timer_heap(ht); while ( ht->cur_size && PJ_TIME_VAL_LTE(ht->heap[0]->_timer_value, now) && count < ht->max_entries_per_poll ) { pj_timer_entry *node = remove_node(ht, 0); + pj_grp_lock_t *grp_lock; + ++count; + grp_lock = node->_grp_lock; + node->_grp_lock = NULL; + unlock_timer_heap(ht); + + PJ_RACE_ME(5); + if (node->cb) (*node->cb)(ht, node); + + if (grp_lock) + pj_grp_lock_dec_ref(grp_lock); + lock_timer_heap(ht); } if (ht->cur_size && next_delay) { diff --git a/pjlib/src/pj/timer_symbian.cpp b/pjlib/src/pj/timer_symbian.cpp index 47aa984..8b18525 100644 --- a/pjlib/src/pj/timer_symbian.cpp +++ b/pjlib/src/pj/timer_symbian.cpp @@ -1,4 +1,4 @@ -/* $Id: timer_symbian.cpp 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: timer_symbian.cpp 4374 2013-02-27 07:15:57Z riza $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -392,6 +392,24 @@ PJ_DEF(pj_status_t) pj_timer_heap_schedule( pj_timer_heap_t *ht, return PJ_SUCCESS; } +PJ_DEF(pj_status_t) pj_timer_heap_schedule_w_grp_lock(pj_timer_heap_t *ht, + pj_timer_entry *entry, + const pj_time_val *delay, + int id_val, + pj_grp_lock_t *grp_lock) +{ + pj_status_t status; + + PJ_UNUSED_ARG(grp_lock); + + status = pj_timer_heap_schedule(ht, entry, delay); + + if (status == PJ_SUCCESS) + entry->id = id_val; + + return status; +} + PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, pj_timer_entry *entry) { @@ -411,6 +429,17 @@ PJ_DEF(int) pj_timer_heap_cancel( pj_timer_heap_t *ht, } } +PJ_DEF(int) pj_timer_heap_cancel_if_active(pj_timer_heap_t *ht, + pj_timer_entry *entry, + int id_val) +{ + int count = pj_timer_heap_cancel(ht, entry); + if (count == 1) + entry->id = id_val; + + return count; +} + PJ_DEF(unsigned) pj_timer_heap_poll( pj_timer_heap_t *ht, pj_time_val *next_delay ) { diff --git a/pjlib/src/pjlib-test/activesock.c b/pjlib/src/pjlib-test/activesock.c index 399cc29..6fe5091 100644 --- a/pjlib/src/pjlib-test/activesock.c +++ b/pjlib/src/pjlib-test/activesock.c @@ -1,4 +1,4 @@ -/* $Id: activesock.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: activesock.c 4238 2012-08-31 06:17:56Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -213,6 +213,7 @@ static int udp_ping_pong_test(void) for (i=0; i<10 && last_rx1 == srv1->rx_cnt && last_rx2 == srv2->rx_cnt; ++i) { pj_time_val delay = {0, 10}; #ifdef PJ_SYMBIAN + PJ_UNUSED_ARG(delay); pj_symbianos_poll(-1, 100); #else pj_ioqueue_poll(ioqueue, &delay); diff --git a/pjlib/src/pjlib-test/ioq_tcp.c b/pjlib/src/pjlib-test/ioq_tcp.c index 8ecbc0f..faf0646 100644 --- a/pjlib/src/pjlib-test/ioq_tcp.c +++ b/pjlib/src/pjlib-test/ioq_tcp.c @@ -1,4 +1,4 @@ -/* $Id: ioq_tcp.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ioq_tcp.c 4238 2012-08-31 06:17:56Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -363,7 +363,7 @@ static int compliance_test_0(pj_bool_t allow_concur) #ifdef PJ_SYMBIAN callback_call_count = 0; - pj_symbianos_poll(-1, 1000); + pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); status = callback_call_count; #else status = pj_ioqueue_poll(ioque, &timeout); @@ -412,7 +412,7 @@ static int compliance_test_0(pj_bool_t allow_concur) if (pending_op == 0) { pj_time_val timeout = {1, 0}; #ifdef PJ_SYMBIAN - status = pj_symbianos_poll(-1, 1000); + status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else status = pj_ioqueue_poll(ioque, &timeout); #endif @@ -542,7 +542,7 @@ static int compliance_test_1(pj_bool_t allow_concur) #ifdef PJ_SYMBIAN callback_call_count = 0; - pj_symbianos_poll(-1, 1000); + pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); status = callback_call_count; #else status = pj_ioqueue_poll(ioque, &timeout); @@ -576,7 +576,7 @@ static int compliance_test_1(pj_bool_t allow_concur) if (pending_op == 0) { pj_time_val timeout = {1, 0}; #ifdef PJ_SYMBIAN - status = pj_symbianos_poll(-1, 1000); + status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else status = pj_ioqueue_poll(ioque, &timeout); #endif @@ -771,7 +771,7 @@ static int compliance_test_2(pj_bool_t allow_concur) pj_time_val timeout = {1, 0}; #ifdef PJ_SYMBIAN - status = pj_symbianos_poll(-1, 1000); + status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else status = pj_ioqueue_poll(ioque, &timeout); #endif @@ -797,7 +797,7 @@ static int compliance_test_2(pj_bool_t allow_concur) if (pending_op == 0) { pj_time_val timeout = {1, 0}; #ifdef PJ_SYMBIAN - status = pj_symbianos_poll(-1, 1000); + status = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else status = pj_ioqueue_poll(ioque, &timeout); #endif diff --git a/pjlib/src/pjlib-test/ioq_udp.c b/pjlib/src/pjlib-test/ioq_udp.c index 6928641..8180e3d 100644 --- a/pjlib/src/pjlib-test/ioq_udp.c +++ b/pjlib/src/pjlib-test/ioq_udp.c @@ -1,4 +1,4 @@ -/* $Id: ioq_udp.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ioq_udp.c 4238 2012-08-31 06:17:56Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -267,7 +267,7 @@ static int compliance_test(pj_bool_t allow_concur) TRACE_("poll..."); #ifdef PJ_SYMBIAN - rc = pj_symbianos_poll(-1, 5000); + rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else rc = pj_ioqueue_poll(ioque, &timeout); #endif @@ -783,7 +783,7 @@ static int bench_test(pj_bool_t allow_concur, int bufsize, do { pj_time_val timeout = { 1, 0 }; #ifdef PJ_SYMBIAN - rc = pj_symbianos_poll(-1, 1000); + rc = pj_symbianos_poll(-1, PJ_TIME_VAL_MSEC(timeout)); #else rc = pj_ioqueue_poll(ioque, &timeout); #endif @@ -812,6 +812,7 @@ static int bench_test(pj_bool_t allow_concur, int bufsize, do { pj_time_val timeout = { 0, 10 }; #ifdef PJ_SYMBIAN + PJ_UNUSED_ARG(timeout); rc = pj_symbianos_poll(-1, 100); #else rc = pj_ioqueue_poll(ioque, &timeout); diff --git a/pjlib/src/pjlib-test/ssl_sock.c b/pjlib/src/pjlib-test/ssl_sock.c index d05a4db..d983eba 100644 --- a/pjlib/src/pjlib-test/ssl_sock.c +++ b/pjlib/src/pjlib-test/ssl_sock.c @@ -1,4 +1,4 @@ -/* $Id: ssl_sock.c 3553 2011-05-05 06:14:19Z nanang $ */ +/* $Id: ssl_sock.c 4247 2012-09-07 08:58:48Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -1329,11 +1329,34 @@ on_return: return status; } +#if 0 && (!defined(PJ_SYMBIAN) || PJ_SYMBIAN==0) +pj_status_t pj_ssl_sock_ossl_test_send_buf(pj_pool_t *pool); +static int ossl_test_send_buf() +{ + pj_pool_t *pool; + pj_status_t status; + + pool = pj_pool_create(mem, "send_buf", 256, 256, NULL); + status = pj_ssl_sock_ossl_test_send_buf(pool); + pj_pool_release(pool); + return status; +} +#else +static int ossl_test_send_buf() +{ + return 0; +} +#endif int ssl_sock_test(void) { int ret; + PJ_LOG(3,("", "..test ossl send buf")); + ret = ossl_test_send_buf(); + if (ret != 0) + return ret; + PJ_LOG(3,("", "..get cipher list test")); ret = get_cipher_list(); if (ret != 0) diff --git a/pjmedia/build/Makefile b/pjmedia/build/Makefile index 2f97296..026d89c 100644 --- a/pjmedia/build/Makefile +++ b/pjmedia/build/Makefile @@ -113,7 +113,7 @@ export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_vid_codecs.o \ h263_packetizer.o h264_packetizer.o \ $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ - ipp_codecs.o $(CODEC_OBJS) \ + ipp_codecs.o opencore_amr.o silk.o $(CODEC_OBJS) \ g7221_sdp_match.o amr_sdp_match.o export PJMEDIA_CODEC_CFLAGS += $(_CFLAGS) $(GSM_CFLAGS) $(SPEEX_CFLAGS) \ $(ILBC_CFLAGS) $(IPP_CFLAGS) $(G7221_CFLAGS) @@ -173,7 +173,9 @@ pjmedia-audiodev: pjsdp: $(MAKE) -f $(RULES_MAK) APP=PJSDP app=pjsdp $(PJSDP_LIB) -pjmedia-test: $(PJMEDIA_LIB) +$(PJMEDIA_LIB): pjmedia + +pjmedia-test: $(PJMEDIA_LIB) pjmedia $(MAKE) -f $(RULES_MAK) APP=PJMEDIA_TEST app=pjmedia-test $(PJMEDIA_TEST_EXE) .PHONY: ../lib/pjmedia.ko diff --git a/pjmedia/build/os-auto.mak.in b/pjmedia/build/os-auto.mak.in index 98ecf28..04224e8 100644 --- a/pjmedia/build/os-auto.mak.in +++ b/pjmedia/build/os-auto.mak.in @@ -58,6 +58,7 @@ AC_NO_ILBC_CODEC=@ac_no_ilbc_codec@ AC_NO_G722_CODEC=@ac_no_g722_codec@ AC_NO_G7221_CODEC=@ac_no_g7221_codec@ AC_NO_OPENCORE_AMRNB=@ac_no_opencore_amrnb@ +AC_NO_OPENCORE_AMRWB=@ac_no_opencore_amrwb@ export CODEC_OBJS= @@ -113,7 +114,15 @@ endif ifeq ($(AC_NO_OPENCORE_AMRNB),1) export CFLAGS += -DPJMEDIA_HAS_OPENCORE_AMRNB_CODEC=0 else -export CODEC_OBJS += opencore_amrnb.o +export CODEC_OBJS += opencore_amr.o +endif + +ifeq ($(AC_NO_OPENCORE_AMRWB),1) +export CFLAGS += -DPJMEDIA_HAS_OPENCORE_AMRWB_CODEC=0 +else +ifeq ($(AC_NO_OPENCORE_AMRNB),1) +export CODEC_OBJS += opencore_amr.o +endif endif diff --git a/pjmedia/build/pjmedia_codec.vcproj b/pjmedia/build/pjmedia_codec.vcproj index 158d43d..eddbc8c 100644 --- a/pjmedia/build/pjmedia_codec.vcproj +++ b/pjmedia/build/pjmedia_codec.vcproj @@ -2975,13 +2975,17 @@ + + @@ -3122,7 +3126,7 @@ > + + diff --git a/pjmedia/include/pjmedia-audiodev/audiodev.h b/pjmedia/include/pjmedia-audiodev/audiodev.h index f8edb0d..7e13d14 100644 --- a/pjmedia/include/pjmedia-audiodev/audiodev.h +++ b/pjmedia/include/pjmedia-audiodev/audiodev.h @@ -1,4 +1,4 @@ -/* $Id: audiodev.h 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: audiodev.h 4243 2012-08-31 11:42:17Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -424,6 +424,12 @@ typedef struct pjmedia_aud_param */ pj_bool_t cng_enabled; + /** + * Enable/disable VAD. This setting is optional, and will only be used + * if PJMEDIA_AUD_DEV_CAP_VAD is set in the flags. + */ + pj_bool_t vad_enabled; + } pjmedia_aud_param; diff --git a/pjmedia/include/pjmedia-codec.h b/pjmedia/include/pjmedia-codec.h index c666996..c63e46e 100644 --- a/pjmedia/include/pjmedia-codec.h +++ b/pjmedia/include/pjmedia-codec.h @@ -1,4 +1,4 @@ -/* $Id: pjmedia-codec.h 4049 2012-04-13 06:24:23Z ming $ */ +/* $Id: pjmedia-codec.h 4331 2013-01-23 06:18:18Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -34,8 +34,9 @@ #include #include #include +#include #include -#include +#include #endif /* __PJMEDIA_CODEC_PJMEDIA_CODEC_H__ */ diff --git a/pjmedia/include/pjmedia-codec/config.h b/pjmedia/include/pjmedia-codec/config.h index 2c71cc9..29350db 100644 --- a/pjmedia/include/pjmedia-codec/config.h +++ b/pjmedia/include/pjmedia-codec/config.h @@ -1,4 +1,4 @@ -/* $Id: config.h 4070 2012-04-23 13:48:10Z bennylp $ */ +/* $Id: config.h 4331 2013-01-23 06:18:18Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -322,9 +322,19 @@ # define PJMEDIA_HAS_OPENCORE_AMRNB_CODEC 0 #endif +/** + * Enable OpenCORE AMR-WB codec. + * See https://trac.pjsip.org/repos/ticket/1608 for some info. + * + * Default: 0 + */ +#ifndef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC +# define PJMEDIA_HAS_OPENCORE_AMRWB_CODEC 0 +#endif + /** * Link with libopencore-amrXX via pragma comment on Visual Studio. - * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC + * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB/WB_CODEC * is enabled. * * Default: 1 @@ -335,7 +345,7 @@ /** * Link with libopencore-amrXX.a that has been produced with gcc. - * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB_CODEC + * This option only makes sense if PJMEDIA_HAS_OPENCORE_AMRNB/WB_CODEC * and PJMEDIA_AUTO_LINK_OPENCORE_AMR_LIBS are enabled. * * Default: 1 @@ -377,6 +387,38 @@ #endif +/** + * Enable SILK codec. + * + * Default: 0 + */ +#ifndef PJMEDIA_HAS_SILK_CODEC +# define PJMEDIA_HAS_SILK_CODEC 0 +#endif + + +/** + * SILK codec default complexity setting, valid values are 0 (lowest), 1, + * and 2. + * + * Default: 2 + */ +#ifndef PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY +# define PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY 2 +#endif + +/** + * SILK codec default quality setting, valid values are ranging from + * 0 (lowest) to 10. Please note that pjsua-lib may override this setting + * via its codec quality setting (i.e PJSUA_DEFAULT_CODEC_QUALITY). + * + * Default: 10 + */ +#ifndef PJMEDIA_CODEC_SILK_DEFAULT_QUALITY +# define PJMEDIA_CODEC_SILK_DEFAULT_QUALITY 10 +#endif + + /** * Specify if FFMPEG codecs are available. * diff --git a/pjmedia/include/pjmedia-codec/config_auto.h.in b/pjmedia/include/pjmedia-codec/config_auto.h.in index 887d083..11da110 100644 --- a/pjmedia/include/pjmedia-codec/config_auto.h.in +++ b/pjmedia/include/pjmedia-codec/config_auto.h.in @@ -1,4 +1,4 @@ -/* $Id: config_auto.h.in 3841 2011-10-24 09:28:13Z ming $ */ +/* $Id: config_auto.h.in 4331 2013-01-23 06:18:18Z ming $ */ /* * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -74,6 +74,15 @@ #undef PJMEDIA_HAS_OPENCORE_AMRNB_CODEC #endif +/* OpenCORE AMR-WB codec */ +#ifndef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC +#undef PJMEDIA_HAS_OPENCORE_AMRWB_CODEC +#endif + +/* SILK codec */ +#ifndef PJMEDIA_HAS_SILK_CODEC +#undef PJMEDIA_HAS_SILK_CODEC +#endif #endif /* __PJMEDIA_CODEC_CONFIG_AUTO_H_ */ diff --git a/pjmedia/include/pjmedia-codec/opencore_amr.h b/pjmedia/include/pjmedia-codec/opencore_amr.h new file mode 100644 index 0000000..3d5049b --- /dev/null +++ b/pjmedia/include/pjmedia-codec/opencore_amr.h @@ -0,0 +1,146 @@ +/* $Id: opencore_amr.h 4335 2013-01-29 08:09:15Z ming $ */ +/* + * Copyright (C) 2011-2013 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2011 Dan Arrhenius + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_CODEC_OPENCORE_AMR_H__ +#define __PJMEDIA_CODEC_OPENCORE_AMR_H__ + +#include + +/** + * @defgroup PJMED_OC_AMR OpenCORE AMR Codec + * @ingroup PJMEDIA_CODEC_CODECS + * @brief AMRCodec wrapper for OpenCORE AMR codec + * @{ + */ + +PJ_BEGIN_DECL + +/** + * Bitmask options to be passed during AMR codec factory initialization. + */ +enum pjmedia_amr_options +{ + PJMEDIA_AMR_NO_NB = 1, /**< Disable narrowband mode. */ + PJMEDIA_AMR_NO_WB = 2, /**< Disable wideband mode. */ +}; + +/** + * Settings. Use #pjmedia_codec_opencore_amrnb/wb_set_config() to + * activate. + */ +typedef struct pjmedia_codec_amr_config +{ + /** + * Control whether to use octent align. + */ + pj_bool_t octet_align; + + /** + * Set the bitrate. + */ + unsigned bitrate; + +} pjmedia_codec_amr_config; + +typedef pjmedia_codec_amr_config pjmedia_codec_amrnb_config; +typedef pjmedia_codec_amr_config pjmedia_codec_amrwb_config; + +/** + * Initialize and register AMR codec factory to pjmedia endpoint. + * + * @param endpt The pjmedia endpoint. + * @param options Bitmask of pjmedia_amr_options (default=0). + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amr_init(pjmedia_endpt* endpt, + unsigned options); + +/** + * Initialize and register AMR codec factory using default settings to + * pjmedia endpoint. + * + * @param endpt The pjmedia endpoint. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_codec_opencore_amr_init_default(pjmedia_endpt* endpt); + +/** + * Unregister AMR codec factory from pjmedia endpoint and deinitialize + * the OpenCORE codec library. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amr_deinit(void); + +/** + * Initialize and register AMR-NB codec factory to pjmedia endpoint. Calling + * this function will automatically initialize AMR codec factory without + * the wideband mode (i.e. it is equivalent to calling + * #pjmedia_codec_opencore_amr_init() with PJMEDIA_AMR_NO_WB). Application + * should call #pjmedia_codec_opencore_amr_init() instead if wishing to use + * both modes. + * + * @param endpt The pjmedia endpoint. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_init(pjmedia_endpt* endpt); + +/** + * Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize + * the OpenCORE codec library. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void); + + +/** + * Set AMR-NB parameters. + * + * @param cfg The settings; + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_set_config( + const pjmedia_codec_amrnb_config* cfg); + + +/** + * Set AMR-WB parameters. + * + * @param cfg The settings; + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrwb_set_config( + const pjmedia_codec_amrwb_config* cfg); + +PJ_END_DECL + + +/** + * @} + */ + +#endif /* __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ */ + diff --git a/pjmedia/include/pjmedia-codec/opencore_amrnb.h b/pjmedia/include/pjmedia-codec/opencore_amrnb.h deleted file mode 100644 index aedb460..0000000 --- a/pjmedia/include/pjmedia-codec/opencore_amrnb.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $Id: opencore_amrnb.h 3841 2011-10-24 09:28:13Z ming $ */ -/* - * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) - * Copyright (C) 2011 Dan Arrhenius - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ -#define __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ - -#include - -/** - * @defgroup PJMED_OC_AMRNB OpenCORE AMR-NB Codec - * @ingroup PJMEDIA_CODEC_CODECS - * @brief AMRCodec wrapper for OpenCORE AMR-NB codec - * @{ - */ - -PJ_BEGIN_DECL - -/** - * Settings. Use #pjmedia_codec_opencore_amrnb_set_config() to - * activate. - */ -typedef struct pjmedia_codec_amrnb_config -{ - /** - * Control whether to use octent align. - */ - pj_bool_t octet_align; - - /** - * Set the bitrate. - */ - unsigned bitrate; - -} pjmedia_codec_amrnb_config; - - -/** - * Initialize and register AMR-NB codec factory to pjmedia endpoint. - * - * @param endpt The pjmedia endpoint. - * - * @return PJ_SUCCESS on success. - */ -PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_init(pjmedia_endpt* endpt); - -/** - * Unregister AMR-NB codec factory from pjmedia endpoint and deinitialize - * the OpenCORE codec library. - * - * @return PJ_SUCCESS on success. - */ -PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_deinit(void); - - -/** - * Set AMR-NB parameters. - * - * @param cfg The settings; - * - * @return PJ_SUCCESS on success. - */ -PJ_DECL(pj_status_t) pjmedia_codec_opencore_amrnb_set_config( - const pjmedia_codec_amrnb_config* cfg); - -PJ_END_DECL - - -/** - * @} - */ - -#endif /* __PJMEDIA_CODEC_OPENCORE_AMRNB_H__ */ - diff --git a/pjmedia/include/pjmedia-codec/silk.h b/pjmedia/include/pjmedia-codec/silk.h new file mode 100644 index 0000000..810faca --- /dev/null +++ b/pjmedia/include/pjmedia-codec/silk.h @@ -0,0 +1,133 @@ +/* $Id: silk.h 4264 2012-09-24 06:58:16Z nanang $ */ +/* + * Copyright (C) 2012-2012 Teluu Inc. (http://www.teluu.com) + * Contributed by Regis Montoya (aka r3gis - www.r3gis.fr) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_CODEC_SILK_H__ +#define __PJMEDIA_CODEC_SILK_H__ + +/** + * @file silk.h + * @brief SILK codec. + */ + +#include + +/** + * @defgroup PJMED_SILK SILK Codec Family + * @ingroup PJMEDIA_CODEC_CODECS + * @brief Implementation of SILK codecs (narrow/medium/wide/superwide-band). + * @{ + * + * This section describes functions to initialize and register SILK codec + * factory to the codec manager. After the codec factory has been registered, + * application can use @ref PJMEDIA_CODEC API to manipulate the codec. + * + * The SILK codec uses multiple bit rates, and supports super wideband + * (24 kHz sampling rate), wideband (16 kHz sampling rate), medium (12kHz + * sampling rate), and narrowband (telephone quality, 8 kHz sampling rate). + * + * By default, the SILK codec factory registers two SILK codecs: + * "SILK/8000" narrowband codec and "SILK/16000" wideband codec. This behavior + * can be changed by specifying #pjmedia_codec_silk_options flags during + * initialization. + * + * + * \section codec_setting Codec Settings + * + * \subsection general_setting General Settings + * + * General codec settings for this codec such as VAD and PLC can be + * manipulated through the setting field in #pjmedia_codec_param. + * Please see the documentation of #pjmedia_codec_param for more info. + * + * \subsection specific_setting Codec Specific Settings + * + * The following settings are applicable for this codec. + * + * \subsubsection quality_vs_complexity Quality vs Complexity + * + * The SILK codec quality versus computational complexity and bandwidth + * requirement can be adjusted by modifying the quality and complexity + * setting, by calling #pjmedia_codec_silk_set_config(). + * + * The default setting of quality is specified in + * #PJMEDIA_CODEC_SILK_DEFAULT_QUALITY. And the default setting of + * complexity is specified in #PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY. + */ + +PJ_BEGIN_DECL + +typedef struct pjmedia_codec_silk_setting +{ + pj_bool_t enabled; /**< Enable/disable. */ + int quality; /**< Encoding quality, or use -1 for default + (@see PJMEDIA_CODEC_SILK_DEFAULT_QUALITY). */ + int complexity; /**< Encoding complexity, or use -1 for default + (@see PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY)*/ +} pjmedia_codec_silk_setting; + + +/** + * Initialize and register SILK codec factory to pjmedia endpoint. By default, + * only narrowband (8kHz sampling rate) and wideband (16kHz sampling rate) + * will be enabled. Quality and complexity for those sampling rate modes + * will be set to the default values (see #PJMEDIA_CODEC_SILK_DEFAULT_QUALITY + * and #PJMEDIA_CODEC_SILK_DEFAULT_COMPLEXITY), application may modify these + * settings via #pjmedia_codec_silk_set_config(). + * + * @param endpt The pjmedia endpoint. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_silk_init(pjmedia_endpt *endpt); + + +/** + * Change the configuration setting of the SILK codec for the specified + * clock rate. + * + * @param clock_rate PCM sampling rate, in Hz, valid values are 8000, + * 12000, 16000 and 24000. + * @param opt The setting to be applied for the specified + * clock rate. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_silk_set_config( + unsigned clock_rate, + const pjmedia_codec_silk_setting *opt); + + +/** + * Unregister SILK codec factory from pjmedia endpoint and deinitialize + * the SILK codec library. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_codec_silk_deinit(void); + + +PJ_END_DECL + + +/** + * @} + */ + +#endif /* __PJMEDIA_CODEC_SILK_H__ */ + diff --git a/pjmedia/include/pjmedia-codec/types.h b/pjmedia/include/pjmedia-codec/types.h index a18fa30..53e71e1 100644 --- a/pjmedia/include/pjmedia-codec/types.h +++ b/pjmedia/include/pjmedia-codec/types.h @@ -1,4 +1,4 @@ -/* $Id: types.h 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: types.h 4264 2012-09-24 06:58:16Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -63,18 +63,10 @@ enum pjmedia_audio_pt PJMEDIA_RTP_PT_SPEEX_NB, /**< Speex narrowband/8KHz */ PJMEDIA_RTP_PT_SPEEX_WB, /**< Speex wideband/16KHz */ PJMEDIA_RTP_PT_SPEEX_UWB, /**< Speex 32KHz */ - PJMEDIA_RTP_PT_L16_8KHZ_MONO, /**< L16 @ 8KHz, mono */ - PJMEDIA_RTP_PT_L16_8KHZ_STEREO, /**< L16 @ 8KHz, stereo */ - //PJMEDIA_RTP_PT_L16_11KHZ_MONO, /**< L16 @ 11KHz, mono */ - //PJMEDIA_RTP_PT_L16_11KHZ_STEREO, /**< L16 @ 11KHz, stereo */ - PJMEDIA_RTP_PT_L16_16KHZ_MONO, /**< L16 @ 16KHz, mono */ - PJMEDIA_RTP_PT_L16_16KHZ_STEREO, /**< L16 @ 16KHz, stereo */ - //PJMEDIA_RTP_PT_L16_22KHZ_MONO, /**< L16 @ 22KHz, mono */ - //PJMEDIA_RTP_PT_L16_22KHZ_STEREO, /**< L16 @ 22KHz, stereo */ - //PJMEDIA_RTP_PT_L16_32KHZ_MONO, /**< L16 @ 32KHz, mono */ - //PJMEDIA_RTP_PT_L16_32KHZ_STEREO, /**< L16 @ 32KHz, stereo */ - //PJMEDIA_RTP_PT_L16_48KHZ_MONO, /**< L16 @ 48KHz, mono */ - //PJMEDIA_RTP_PT_L16_48KHZ_STEREO, /**< L16 @ 48KHz, stereo */ + PJMEDIA_RTP_PT_SILK_NB, /**< SILK narrowband/8KHz */ + PJMEDIA_RTP_PT_SILK_MB, /**< SILK mediumband/12KHz */ + PJMEDIA_RTP_PT_SILK_WB, /**< SILK wideband/16KHz */ + PJMEDIA_RTP_PT_SILK_SWB, /**< SILK 24KHz */ PJMEDIA_RTP_PT_ILBC, /**< iLBC (13.3/15.2Kbps) */ PJMEDIA_RTP_PT_AMR, /**< AMR (4.75 - 12.2Kbps) */ PJMEDIA_RTP_PT_AMRWB, /**< AMRWB (6.6 - 23.85Kbps)*/ @@ -91,6 +83,18 @@ enum pjmedia_audio_pt PJMEDIA_RTP_PT_G7221C_48, /**< G722.1 Annex C (48Kbps)*/ PJMEDIA_RTP_PT_G7221_RSV1, /**< G722.1 reserve */ PJMEDIA_RTP_PT_G7221_RSV2, /**< G722.1 reserve */ + PJMEDIA_RTP_PT_L16_8KHZ_MONO, /**< L16 @ 8KHz, mono */ + PJMEDIA_RTP_PT_L16_8KHZ_STEREO, /**< L16 @ 8KHz, stereo */ + //PJMEDIA_RTP_PT_L16_11KHZ_MONO, /**< L16 @ 11KHz, mono */ + //PJMEDIA_RTP_PT_L16_11KHZ_STEREO, /**< L16 @ 11KHz, stereo */ + PJMEDIA_RTP_PT_L16_16KHZ_MONO, /**< L16 @ 16KHz, mono */ + PJMEDIA_RTP_PT_L16_16KHZ_STEREO, /**< L16 @ 16KHz, stereo */ + //PJMEDIA_RTP_PT_L16_22KHZ_MONO, /**< L16 @ 22KHz, mono */ + //PJMEDIA_RTP_PT_L16_22KHZ_STEREO, /**< L16 @ 22KHz, stereo */ + //PJMEDIA_RTP_PT_L16_32KHZ_MONO, /**< L16 @ 32KHz, mono */ + //PJMEDIA_RTP_PT_L16_32KHZ_STEREO, /**< L16 @ 32KHz, stereo */ + //PJMEDIA_RTP_PT_L16_48KHZ_MONO, /**< L16 @ 48KHz, mono */ + //PJMEDIA_RTP_PT_L16_48KHZ_STEREO, /**< L16 @ 48KHz, stereo */ /* Caution! * Ensure the value of the last pt above is <= 127. diff --git a/pjmedia/include/pjmedia-videodev/config.h b/pjmedia/include/pjmedia-videodev/config.h index 12a251a..ef161eb 100644 --- a/pjmedia/include/pjmedia-videodev/config.h +++ b/pjmedia/include/pjmedia-videodev/config.h @@ -1,4 +1,4 @@ -/* $Id: config.h 4016 2012-04-04 05:05:50Z bennylp $ */ +/* $Id: config.h 4414 2013-03-05 08:21:02Z riza $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * @@ -132,6 +132,17 @@ PJ_BEGIN_DECL # define PJMEDIA_VIDEO_DEV_HAS_AVI 1 #endif +/** + * Specify the SDL library name to be linked with Visual Studio project. + * By default, the name is autodetected based on SDL version ("sdl.lib" or + * "sdl2.lib"), but application may explicitly specify the library name if this + * autodetection fails. Common names are: "sdl2.lib" or "sdl.lib". + * + * Default: undeclared. + */ +#ifndef PJMEDIA_SDL_LIB +# undef PJMEDIA_SDL_LIB +#endif /** * @} diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h index 62c79e0..58fa7a1 100644 --- a/pjmedia/include/pjmedia/codec.h +++ b/pjmedia/include/pjmedia/codec.h @@ -1,4 +1,4 @@ -/* $Id: codec.h 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: codec.h 4278 2012-10-05 10:04:54Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -276,6 +276,7 @@ typedef struct pjmedia_codec_param unsigned channel_cnt; /**< Channel count. */ pj_uint32_t avg_bps; /**< Average bandwidth in bits/sec */ pj_uint32_t max_bps; /**< Maximum bandwidth in bits/sec */ + unsigned max_rx_frame_size; /**< Maximum frame size */ pj_uint16_t frm_ptime; /**< Decoder frame ptime in msec. */ pj_uint16_t enc_ptime; /**< Encoder ptime, or zero if it's equal to decoder ptime. */ @@ -308,6 +309,18 @@ typedef struct pjmedia_codec_param } pjmedia_codec_param; +/** + * Duplicate codec parameter. + * + * @param pool The pool. + * @param src The codec parameter to be duplicated. + * + * @return Duplicated codec parameter. + */ +PJ_DECL(pjmedia_codec_param*) pjmedia_codec_param_clone( + pj_pool_t *pool, + const pjmedia_codec_param *src); + /* * Forward declaration for pjmedia_codec. diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index d5a598f..b229eca 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -1,4 +1,4 @@ -/* $Id: config.h 4130 2012-05-17 08:35:51Z nanang $ */ +/* $Id: config.h 4240 2012-08-31 09:03:36Z ming $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -371,13 +371,21 @@ /** - * Max packet size to support. + * Max packet size for transmitting direction. */ #ifndef PJMEDIA_MAX_MTU # define PJMEDIA_MAX_MTU 1500 #endif +/** + * Max packet size for receiving direction. + */ +#ifndef PJMEDIA_MAX_MRU +# define PJMEDIA_MAX_MRU 2000 +#endif + + /** * DTMF/telephone-event duration, in timestamp. */ @@ -676,6 +684,28 @@ #endif +/** + * This macro controls whether pjmedia should include SDP + * bandwidth modifier "TIAS" (RFC3890). + * + * Note that there is also a run-time variable to turn this setting + * on or off, defined in endpoint.c. To access this variable, use + * the following construct + * + \verbatim + extern pj_bool_t pjmedia_add_bandwidth_tias_in_sdp; + + // Do not enable bandwidth information inclusion in sdp + pjmedia_add_bandwidth_tias_in_sdp = PJ_FALSE; + \endverbatim + * + * Default: 1 (yes) + */ +#ifndef PJMEDIA_ADD_BANDWIDTH_TIAS_IN_SDP +# define PJMEDIA_ADD_BANDWIDTH_TIAS_IN_SDP 1 +#endif + + /** * This macro controls whether pjmedia should include SDP rtpmap * attribute for static payload types. SDP rtpmap for static diff --git a/pjmedia/include/pjmedia/sdp.h b/pjmedia/include/pjmedia/sdp.h index 2dc58d6..bababef 100644 --- a/pjmedia/include/pjmedia/sdp.h +++ b/pjmedia/include/pjmedia/sdp.h @@ -1,4 +1,4 @@ -/* $Id: sdp.h 3945 2012-01-27 09:12:59Z nanang $ */ +/* $Id: sdp.h 4367 2013-02-21 20:49:19Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -685,6 +685,23 @@ PJ_DECL(int) pjmedia_sdp_print( const pjmedia_sdp_session *sdp, PJ_DECL(pj_status_t) pjmedia_sdp_validate(const pjmedia_sdp_session *sdp); +/** + * Perform semantic validation for the specified SDP session descriptor. + * This function perform validation beyond just syntactic verification, + * such as to verify the value of network type and address type, check + * the connection line, and verify that \a rtpmap attribute is present + * when dynamic payload type is used. + * + * @param sdp The SDP session descriptor to validate. + * @param strict Flag whether the check should be strict, i.e: allow + * media without connection line when port is zero. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_sdp_validate2(const pjmedia_sdp_session *sdp, + pj_bool_t strict); + + /** * Clone SDP session descriptor. * diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h index dca9f29..e86c974 100644 --- a/pjmedia/include/pjmedia/transport.h +++ b/pjmedia/include/pjmedia/transport.h @@ -1,4 +1,4 @@ -/* $Id: transport.h 3664 2011-07-19 03:42:28Z nanang $ */ +/* $Id: transport.h 4345 2013-02-13 07:43:32Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -566,7 +566,7 @@ PJ_INLINE(void) pjmedia_transport_info_init(pjmedia_transport_info *info) * for example to fill in the "c=" and "m=" line of local SDP. * * @param tp The transport. - * @param info Media socket info to be initialized. + * @param info Media transport info to be initialized. * * @return PJ_SUCCESS on success. */ @@ -580,6 +580,29 @@ PJ_INLINE(pj_status_t) pjmedia_transport_get_info(pjmedia_transport *tp, } +/** + * Utility API to get transport type specific info from the specified media + * transport info. + * + * @param info Media transport info. + * @param type Media transport type. + * + * @return Pointer to media transport specific info, or NULL if + * specific info for the transport type is not found. + */ +PJ_INLINE(void*) pjmedia_transport_info_get_spc_info( + pjmedia_transport_info *info, + pjmedia_transport_type type) +{ + unsigned i; + for (i = 0; i < info->specific_info_cnt; ++i) { + if (info->spc_info[i].type == type) + return (void*)info->spc_info[i].buffer; + } + return NULL; +} + + /** * Attach callbacks to be called on receipt of incoming RTP/RTCP packets. * This is just a simple wrapper which calls attach() member of diff --git a/pjmedia/include/pjmedia/transport_ice.h b/pjmedia/include/pjmedia/transport_ice.h index 4500fae..417ee6d 100644 --- a/pjmedia/include/pjmedia/transport_ice.h +++ b/pjmedia/include/pjmedia/transport_ice.h @@ -1,4 +1,4 @@ -/* $Id: transport_ice.h 3872 2011-10-28 04:27:41Z bennylp $ */ +/* $Id: transport_ice.h 4350 2013-02-15 03:57:31Z nanang $ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono @@ -68,6 +68,12 @@ typedef struct pjmedia_ice_cb */ typedef struct pjmedia_ice_transport_info { + /** + * Specifies whether ICE is used, i.e. SDP offer and answer indicates + * that both parties support ICE and ICE should be used for the session. + */ + pj_bool_t active; + /** * ICE sesion state. */ diff --git a/pjmedia/src/pjmedia-audiodev/alsa_dev.c b/pjmedia/src/pjmedia-audiodev/alsa_dev.c index 72b995e..31b3b06 100644 --- a/pjmedia/src/pjmedia-audiodev/alsa_dev.c +++ b/pjmedia/src/pjmedia-audiodev/alsa_dev.c @@ -1,4 +1,4 @@ -/* $Id: alsa_dev.c 4130 2012-05-17 08:35:51Z nanang $ */ +/* $Id: alsa_dev.c 4283 2012-10-12 06:19:32Z ming $ */ /* * Copyright (C) 2009-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2007-2009 Keystream AB and Konftel AB, All rights reserved. @@ -232,7 +232,7 @@ static pj_status_t add_dev (struct alsa_factory *af, const char *dev_name) pj_bzero(adi, sizeof(*adi)); /* Set device name */ - strcpy(adi->name, dev_name); + strncpy(adi->name, dev_name, sizeof(adi->name)); /* Check the number of playback channels */ adi->output_count = (pb_result>=0) ? 1 : 0; diff --git a/pjmedia/src/pjmedia-audiodev/bb10_dev.c b/pjmedia/src/pjmedia-audiodev/bb10_dev.c index 418256d..f920080 100644 --- a/pjmedia/src/pjmedia-audiodev/bb10_dev.c +++ b/pjmedia/src/pjmedia-audiodev/bb10_dev.c @@ -1,4 +1,4 @@ -/* $Id: bb10_dev.c 4151 2012-06-01 04:49:57Z ming $ */ +/* $Id: bb10_dev.c 4340 2013-02-05 05:15:01Z bennylp $ */ /* * Copyright (C) 2008-2012 Teluu Inc. (http://www.teluu.com) * @@ -33,6 +33,11 @@ #if defined(PJMEDIA_AUDIO_DEV_HAS_BB10) && PJMEDIA_AUDIO_DEV_HAS_BB10 != 0 +#ifndef PJ_BBSDK_VER + /* Format: 0xMMNNRR: MM: major, NN: minor, RR: revision */ +# define PJ_BBSDK_VER 0x100006 +#endif + #include #include #include @@ -40,6 +45,9 @@ #include #include #include +#if PJ_BBSDK_VER >= 0x100006 +#include