diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 64d79eac98..2bd1954800 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Jan 17 17:00:56 EST 2007 +Wed Feb 7 16:58:19 EST 2007 diff --git a/libs/sofia-sip/Makefile.am b/libs/sofia-sip/Makefile.am index 844a503b7d..f97d028794 100644 --- a/libs/sofia-sip/Makefile.am +++ b/libs/sofia-sip/Makefile.am @@ -27,6 +27,10 @@ ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST += m4/sac-general.m4 m4/sac-su.m4 \ m4/sac-su2.m4 m4/sac-tport.m4 m4/sac-openssl.m4 +EXTRA_DIST += docs/build_system.txt \ + docs/devel_platform_notes.txt \ + docs/release_management.txt + dist_man_MANS = man/man1/sip-date.1 man/man1/sip-options.1 \ man/man1/localinfo.1 man/man1/addrinfo.1 \ man/man1/stunc.1 man/man1/sip-dig.1 @@ -44,7 +48,7 @@ endif CLEANFILES = $(dist_man_MANS) -coverage built-sources clean-built-sources doxygen: +coverage built-sources clean-built-sources valcheck doxygen: for i in libsofia-sip-ua $(GLIB_SUBDIRS) ; do $(MAKE) $(AM_MAKEFLAGS) -C $$i $@ ; done .PHONY: coverage built-sources clean-built-sources doxygen manpages diff --git a/libs/sofia-sip/Makefile.in b/libs/sofia-sip/Makefile.in index 1f5d36ca78..274dfabfcb 100644 --- a/libs/sofia-sip/Makefile.in +++ b/libs/sofia-sip/Makefile.in @@ -91,6 +91,7 @@ distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = -I m4 +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -137,8 +138,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -182,6 +187,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -245,7 +251,9 @@ DIST_SUBDIRS = libsofia-sip-ua libsofia-sip-ua-glib utils packages win32 @HAVE_GLIB_TRUE@GLIB_SUBDIRS = libsofia-sip-ua-glib EXTRA_DIST = AUTHORS COPYING COPYRIGHTS ChangeLog.ext-trees README \ README.developers RELEASE TODO m4/sac-general.m4 m4/sac-su.m4 \ - m4/sac-su2.m4 m4/sac-tport.m4 m4/sac-openssl.m4 + m4/sac-su2.m4 m4/sac-tport.m4 m4/sac-openssl.m4 \ + docs/build_system.txt docs/devel_platform_notes.txt \ + docs/release_management.txt dist_man_MANS = man/man1/sip-date.1 man/man1/sip-options.1 \ man/man1/localinfo.1 man/man1/addrinfo.1 \ man/man1/stunc.1 man/man1/sip-dig.1 @@ -496,7 +504,7 @@ distclean-tags: distdir: $(DISTFILES) $(am__remove_distdir) mkdir $(distdir) - $(mkdir_p) $(distdir)/libsofia-sip-ua/docs $(distdir)/libsofia-sip-ua/features/sofia-sip $(distdir)/libsofia-sip-ua/su/sofia-sip $(distdir)/m4 $(distdir)/man/man1 $(distdir)/packages $(distdir)/utils $(distdir)/win32 + $(mkdir_p) $(distdir)/docs $(distdir)/libsofia-sip-ua/docs $(distdir)/libsofia-sip-ua/features/sofia-sip $(distdir)/libsofia-sip-ua/su/sofia-sip $(distdir)/m4 $(distdir)/man/man1 $(distdir)/packages $(distdir)/utils $(distdir)/win32 @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -749,7 +757,7 @@ manpages: built-sources @HAVE_DOXYGEN_TRUE@ @rm -f man/man1/_*.1 @HAVE_DOXYGEN_FALSE@ -touch $(dist_man_MANS) -coverage built-sources clean-built-sources doxygen: +coverage built-sources clean-built-sources valcheck doxygen: for i in libsofia-sip-ua $(GLIB_SUBDIRS) ; do $(MAKE) $(AM_MAKEFLAGS) -C $$i $@ ; done .PHONY: coverage built-sources clean-built-sources doxygen manpages diff --git a/libs/sofia-sip/README b/libs/sofia-sip/README index f3ee2266d8..e560df5ed2 100644 --- a/libs/sofia-sip/README +++ b/libs/sofia-sip/README @@ -46,7 +46,6 @@ The Sofia-SIP su submodule also provides some small utilities: - localinfo (libsofia-sip-ua/su), prints information about local network interfaces - References ---------- diff --git a/libs/sofia-sip/RELEASE b/libs/sofia-sip/RELEASE index e2df85637a..c217713741 100644 --- a/libs/sofia-sip/RELEASE +++ b/libs/sofia-sip/RELEASE @@ -20,15 +20,36 @@ API/ABI changes and versioning other important information to developers; - and should be updated _continuously_! /> -**template**: New features in API are marked with Doxytag macro @VERSION_1_XX_X. +New features in API are marked with Doxytag macro @NEW_1_12_5. +Experimental features are marked with Doxytag macro @EXP_1_12_5. + +**template**: New features in API are marked with Doxytag macro @NEW_1_XX_X. libsofia-sip-ua: - **template**: Added foobar() function (sofia-sip/foobar.h). +- Added nua tags NUTAG_APPL_METHOD() and NUTAG_NEWSUB() +- Added nua_substate_make(), nua_substate_name() +- Added nta_incoming_create_response() function +- Added tport tags TPTAG_TOS(), TPTAG_DUMP(), TPTAG_LOG() +- Added tport predicate function tport_is_connected() +- Added authentication functions auc_info() and auc_has_authorization(), + added type msg_auth_info_t for Authentication-Info header +- Added msg_header_join_items() function - Added sip_is_allowed() function and k_bitmap field to the sip_allow_t structure +- Added sl_header_log implementation, updated its prototype +- Added experimental SIP headers and related functions, + enabled with ./configure option --enable-experimental - Added SIP header Refer-Sub and related functions - Added include file - Added auc_info() function (sofia-sip/auth_client.h) +- Added alternative implementations to event reactor object (su_port_t, + referenced by su_root_t) that can be changed at runtime using SU_PORT + environment variable, for instance + - Internal semantics of su_port_t reference counting have changed: + now su_port_create() has one reference, and su_root_create_with_port() + always consumes one reference +- Changed return type of bm_memmem() and bm_memcasemem() to non-const - This release is ABI/API compatible with applications linked against any 1.12.x release. However, applications built against this release won't work against an older library. The ABI has been tested with the nua module @@ -41,6 +62,8 @@ libsofia-sip-ua-glib: releases in the 1.12.x series. - ABI has been modified and applications built against 1.12.4 and earlier releases need to be rebuilt. +- Added su_glib_prefer_gsource() which makes glib-based su_port_t + implementation the default choice when su_root_create() is called Contributors to this release ---------------------------- @@ -56,22 +79,42 @@ Contributors to this release - **template**: First Surname (patch to nua/soa/msg) - Petteri Puolakka (patch to stun) - Mikhail Zabluev (patch to su-glib mainloop integration) +- Michael Jerris (patch to url parsing # in sip/sips userpart) +- Colin Whittaker (TPTAG_TOS()) +- Roman Filonenko (TPTAG_LOG(), TPTAG_DUMP(), + patch to query DNS-servers with IP-Helper on win32) See the AUTHORS file in the distribution package. Notes on new features --------------------- -RFC 4488 defines the Refer-Sub header. Its datatypes, related functions and -methods declared in include file. The Refer-Sub -header structure can be accessed from sip_t structure with sip_refer_sub() -method, e.g., +- nua now supports request queuing, for instance, an application can send + overlapping BYE and NOTIFY requests. The stack engine takes care of + sending the new request only after the previous one has been responded. + +- RFC 4488 defines the Refer-Sub header. Its datatypes, related functions and + methods declared in include file. The Refer-Sub + header structure can be accessed from sip_t structure with sip_refer_sub() + method, e.g., if (sip_refer_sub(sip) && strcasecmp("false", sip_refer_sub(sip)->rs_value) == 0) { /* Do not create implicit subscription */ } +- Unsolicited NOTIFYs are now supported. The application can accept incoming + NOTIFYs and send NOTIFYs without existing subscription. + +- Transport connections used for client registrations are now maintained + in a persistent fashion. For example a TCP connection used for + registration is not closed until client is unregisters, or the whole stack + is shut down. + +- New build time options have been added: ability to build without + STUN and HTTP support. See 'docs/devel_platform_notes.txt' for some + additional notes to distributors. + - **template**: #9499652 sf.net bug item title - +- Fixed problem in dialog matching. Problem reported by Fabio Margarido. +- Fixed #1624446 - su_wait_clone() (and nua_destroy()) blocking for ever if + the root object was created using su_glib +- Fixed #1626330 - leak in nta.c which happened if INVITE never got a final + response nor timed out. +- Fixed handle leak (pthread_*_init without pthread_*_destroy). Problem + reported by Maxim Zaikin. - Fixed crash when nua_bye() was called while a NOTIFY client transaction was in progress. Problem reported by Anthony Minnessale. - Not using close() with sockets in sres.c. Problem reported by @@ -100,3 +149,6 @@ Bugs fixed in this release - Improved glib mainloop integration to avoid warnings about already active mainloop context, and potentially other issue. Patch by Mikhail Zabaluev. Closes sf.net item #1606786. +- Ignore harmless syntax errors in incoming requests/responses by default +- If a TCP connection cannot be made within SIP T4 (because of a + firewall, for instance) nta now tries to use UDP instead. diff --git a/libs/sofia-sip/aclocal.m4 b/libs/sofia-sip/aclocal.m4 index 352b19c937..158d7a8986 100644 --- a/libs/sofia-sip/aclocal.m4 +++ b/libs/sofia-sip/aclocal.m4 @@ -13,7 +13,7 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# serial 47 AC_PROG_LIBTOOL +# serial 48 AC_PROG_LIBTOOL # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) @@ -123,7 +123,7 @@ esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' +Xsed='sed -e 1s/^X//' [sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] # Same as above, but do not quote variable references. @@ -143,7 +143,7 @@ rm="rm -f" default_ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" @@ -163,6 +163,7 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" @@ -182,15 +183,17 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) - old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi +_LT_CC_BASENAME([$compiler]) + # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) @@ -231,11 +234,56 @@ AC_DEFUN([_LT_AC_SYS_COMPILER], # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_AC_SYS_COMPILER +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + # _LT_AC_SYS_LIBPATH_AIX # ---------------------- # Links a minimal program and checks the executable @@ -308,15 +356,15 @@ fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. -if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break @@ -485,7 +533,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then - case "`/usr/bin/file conftest.o`" in + case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) @@ -536,6 +584,22 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) CFLAGS="$SAVE_CFLAGS" fi ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], [*-*-cygwin* | *-*-mingw* | *-*-pw32*) AC_CHECK_TOOL(DLLTOOL, dlltool, false) @@ -567,7 +631,7 @@ AC_CACHE_CHECK([$1], [$2], # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) @@ -577,8 +641,10 @@ AC_CACHE_CHECK([$1], [$2], echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi @@ -604,11 +670,16 @@ AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], LDFLAGS="$LDFLAGS $3" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized + # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi else $2=yes fi @@ -667,11 +738,55 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; - *) + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && @@ -697,7 +812,7 @@ fi # _LT_AC_CHECK_DLFCN -# -------------------- +# ------------------ AC_DEFUN([_LT_AC_CHECK_DLFCN], [AC_CHECK_HEADERS(dlfcn.h)dnl ])# _LT_AC_CHECK_DLFCN @@ -705,7 +820,7 @@ AC_DEFUN([_LT_AC_CHECK_DLFCN], # _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ------------------------------------------------------------------ +# --------------------------------------------------------------------- AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "$cross_compiling" = yes; then : @@ -771,17 +886,19 @@ int main () else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } + else + puts (dlerror ()); exit (status); }] EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; - x$lt_unknown|x*) $3 ;; + x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed @@ -793,7 +910,7 @@ rm -fr conftest* # AC_LIBTOOL_DLOPEN_SELF -# ------------------- +# ---------------------- AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl if test "x$enable_dlopen" != xyes; then @@ -864,7 +981,7 @@ else test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" @@ -877,7 +994,7 @@ else ]) if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_AC_TRY_DLOPEN_SELF( @@ -925,7 +1042,7 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) @@ -937,11 +1054,13 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - if test ! -s out/conftest.err; then + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi - chmod u+w . + chmod u+w . 2>&AS_MESSAGE_LOG_FD $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -1005,8 +1124,8 @@ AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_AC_TAGVAR(hardcode_action, $1)= if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ - test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ - test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existant directories. if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && @@ -1173,7 +1292,7 @@ beos*) shlibpath_var=LIBRARY_PATH ;; -bsdi4*) +bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -1201,7 +1320,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -1231,7 +1351,7 @@ cygwin* | mingw* | pw32*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; @@ -1254,7 +1374,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -1289,8 +1409,17 @@ kfreebsd*-gnu) dynamic_linker='GNU ld.so' ;; -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -1308,14 +1437,19 @@ freebsd*) freebsd2*) shlibpath_overrides_runpath=yes ;; - freebsd3.[01]* | freebsdelf3.[01]*) + freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; - *) # from 3.2 on + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; esac ;; @@ -1335,7 +1469,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -1375,6 +1509,18 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; @@ -1432,27 +1578,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -1513,8 +1642,13 @@ nto-qnx*) openbsd*) version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - need_version=yes + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH @@ -1552,13 +1686,6 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - solaris*) version_type=linux need_lib_prefix=no @@ -1584,7 +1711,7 @@ sunos4*) need_version=yes ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -1617,6 +1744,29 @@ sysv4*MP*) fi ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -1630,6 +1780,11 @@ uts4*) esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi ])# AC_LIBTOOL_SYS_DYNAMIC_LINKER @@ -1654,6 +1809,9 @@ if test -f "$ltmain" && test -n "$tagnames"; then AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) fi fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. @@ -1680,7 +1838,9 @@ if test -f "$ltmain" && test -n "$tagnames"; then case $tagname in CXX) - if test -n "$CXX" && test "X$CXX" != "Xno"; then + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then AC_LIBTOOL_LANG_CXX_CONFIG else tagname="" @@ -1742,7 +1902,7 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN], # AC_LIBTOOL_WIN32_DLL # -------------------- -# declare package support for building win32 dll's +# declare package support for building win32 DLLs AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) ])# AC_LIBTOOL_WIN32_DLL @@ -1780,7 +1940,7 @@ AC_ARG_ENABLE([shared], # AC_DISABLE_SHARED # ----------------- -#- set the default shared flag to --disable-shared +# set the default shared flag to --disable-shared AC_DEFUN([AC_DISABLE_SHARED], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_SHARED(no) @@ -1916,7 +2076,7 @@ dnl not every word. This closes a longstanding sh security hole. if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then @@ -2026,7 +2186,7 @@ AC_CACHE_VAL(lt_cv_path_LD, if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. + # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; @@ -2163,7 +2332,7 @@ gnu*) hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file - case "$host_cpu" in + case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so @@ -2179,6 +2348,11 @@ hpux10.20* | hpux11*) esac ;; +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; @@ -2191,15 +2365,6 @@ irix5* | irix6* | nonstopux*) # This must be Linux ELF. linux*) - case $host_cpu in - alpha*|hppa*|i*86|ia64*|m68*|mips*|powerpc*|sparc*|s390*|sh*|x86_64*) - lt_cv_deplibs_check_method=pass_all ;; - *) - # glibc up to 2.1.1 does not perform some relocations on ARM - # this will be overridden with pass_all, but let us keep it just in case - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; - esac - lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` lt_cv_deplibs_check_method=pass_all ;; @@ -2222,12 +2387,10 @@ nto-qnx*) ;; openbsd*) - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else - lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; @@ -2235,15 +2398,11 @@ osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; -sco3.2v5*) - lt_cv_deplibs_check_method=pass_all - ;; - solaris*) lt_cv_deplibs_check_method=pass_all ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' @@ -2264,10 +2423,13 @@ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) siemens) lt_cv_deplibs_check_method=pass_all ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; esac ;; -sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac @@ -2287,36 +2449,43 @@ AC_DEFUN([AC_PROG_NM], # Let the user override the test. lt_cv_path_NM="$NM" else - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/${ac_tool_prefix}nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" break ;; *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac ;; esac - esac - fi + fi + done + IFS="$lt_save_ifs" done - IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" @@ -2348,13 +2517,13 @@ esac # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl convenience library and # LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will -# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with -# '${top_srcdir}/' (note the single quotes!). If your package is not -# flat and you're not using automake, define top_builddir and -# top_srcdir appropriately in the Makefiles. +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in @@ -2373,13 +2542,13 @@ AC_DEFUN([AC_LIBLTDL_CONVENIENCE], # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl installable library and # LTDLINCL to the include flags for the libltdl header and adds -# --enable-ltdl-install to the configure arguments. Note that LIBLTDL -# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If -# DIRECTORY is not provided and an installed libltdl is not found, it is -# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' -# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single -# quotes!). If your package is not flat and you're not using automake, -# define top_builddir and top_srcdir appropriately in the Makefiles. +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl @@ -2417,10 +2586,21 @@ AC_DEFUN([AC_LIBTOOL_CXX], # --------------- AC_DEFUN([_LT_AC_LANG_CXX], [AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) ])# _LT_AC_LANG_CXX +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP # AC_LIBTOOL_F77 # -------------- @@ -2460,7 +2640,7 @@ _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) # AC_LIBTOOL_RC -# -------------- +# ------------- # enable support for Windows resource files AC_DEFUN([AC_LIBTOOL_RC], [AC_REQUIRE([LT_AC_PROG_RC]) @@ -2493,36 +2673,9 @@ lt_simple_link_test_code='int main(){return(0);}\n' _LT_AC_SYS_COMPILER -# -# Check for any special shared library compilation flags. -# -_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= -if test "$GCC" = no; then - case $host_os in - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' - ;; - esac -fi -if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then - AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) - if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then : - else - AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) - _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no - fi -fi - - -# -# Check to make sure the static flag actually works. -# -AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], - _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), - $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), - [], - [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) - +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) @@ -2532,9 +2685,9 @@ AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) +AC_LIBTOOL_DLOPEN_SELF -# Report which librarie types wil actually be built +# Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) @@ -2543,7 +2696,7 @@ test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. -case "$host_os" in +case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then @@ -2555,43 +2708,6 @@ aix3*) aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no - fi - ;; - darwin* | rhapsody*) - if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - output_verbose_link_cmd='echo' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' - _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac @@ -2618,7 +2734,7 @@ AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], [AC_LANG_PUSH(C++) AC_REQUIRE([AC_PROG_CXX]) -AC_REQUIRE([AC_PROG_CXXCPP]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= @@ -2630,6 +2746,7 @@ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= @@ -2647,7 +2764,7 @@ _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= # Source file extension for C++ test sources. -ac_ext=cc +ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o @@ -2657,11 +2774,15 @@ _LT_AC_TAGVAR(objext, $1)=$objext lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD @@ -2672,18 +2793,18 @@ lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else - unset lt_cv_prog_gnu_ld + $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else - unset lt_cv_path_LD + $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` +_LT_CC_BASENAME([$compiler]) # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately @@ -2772,6 +2893,7 @@ case $host_os in ;; esac done + ;; esac exp_sym_flag='-bexport' @@ -2790,7 +2912,7 @@ case $host_os in _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) + case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` @@ -2809,8 +2931,12 @@ case $host_os in _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi + ;; esac shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi else # not using gcc if test "$host_cpu" = ia64; then @@ -2837,12 +2963,12 @@ case $host_os in _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX @@ -2851,16 +2977,26 @@ case $host_os in # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + chorus*) case $cc_basename in *) @@ -2879,7 +3015,7 @@ case $host_os in _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -2888,70 +3024,81 @@ case $host_os in echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; - - darwin* | rhapsody*) - if test "$GXX" = yes; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_automatic, $1)=yes - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' - _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; dgux*) case $cc_basename in - ec++) + ec++*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - ghcx) + ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no @@ -2962,14 +3109,14 @@ case $host_os in ;; esac ;; - freebsd[12]*) + freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before switch to ELF _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes @@ -2986,11 +3133,11 @@ case $host_os in # location of the library. case $cc_basename in - CC) + CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - aCC) + aCC*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -3000,7 +3147,7 @@ case $host_os in # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then @@ -3014,34 +3161,23 @@ case $host_os in ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi - case "$host_cpu" in - hppa*64*) + case $host_cpu in + hppa*64*|ia64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; - ia64*) - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, @@ -3051,14 +3187,17 @@ case $host_os in esac case $cc_basename in - CC) + CC*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - aCC) - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' @@ -3077,9 +3216,12 @@ case $host_os in *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then - case "$host_cpu" in - ia64*|hppa*64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' @@ -3093,11 +3235,25 @@ case $host_os in ;; esac ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; irix5* | irix6*) case $cc_basename in - CC) + CC*) # SGI C++ - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -3108,7 +3264,7 @@ case $host_os in *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi @@ -3121,7 +3277,7 @@ case $host_os in ;; linux*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -3146,17 +3302,41 @@ case $host_os in # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - icpc) + icpc*) # Intel C++ with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; - cxx) + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) # Compaq C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' @@ -3187,7 +3367,7 @@ case $host_os in ;; mvs*) case $cc_basename in - cxx) + cxx*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; @@ -3208,9 +3388,25 @@ case $host_os in # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; osf3*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -3226,14 +3422,14 @@ case $host_os in _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - RCC) + RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - cxx) + cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: @@ -3251,7 +3447,7 @@ case $host_os in *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: @@ -3270,7 +3466,7 @@ case $host_os in ;; osf4* | osf5*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -3285,17 +3481,17 @@ case $host_os in # the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - RCC) + RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - cxx) + cxx*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -3314,7 +3510,7 @@ case $host_os in *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: @@ -3335,27 +3531,14 @@ case $host_os in # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - sco*) - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_AC_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; sunos4*) case $cc_basename in - CC) + CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - lcc) + lcc*) # Lucid # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no @@ -3368,36 +3551,33 @@ case $host_os in ;; solaris*) case $cc_basename in - CC) + CC*) # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in - solaris2.[0-5] | solaris2.[0-5].*) ;; + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system - # linker. + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -3405,7 +3585,7 @@ case $host_os in # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; - gcx) + gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' @@ -3443,12 +3623,63 @@ case $host_os in ;; esac ;; - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac ;; tandem*) case $cc_basename in - NCC) + NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no @@ -3481,8 +3712,6 @@ AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) AC_LIBTOOL_CONFIG($1) @@ -3500,7 +3729,7 @@ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld ])# AC_LIBTOOL_LANG_CXX_CONFIG # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) -# ------------------------ +# ------------------------------------ # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary @@ -3554,7 +3783,7 @@ if AC_TRY_EVAL(ac_compile); then # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. - output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in @@ -3630,13 +3859,37 @@ fi $rm -f confest.$objext +# PORTME: override above test on systems where it is broken +ifelse([$1],[CXX], +[case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_AC_TAGVAR(predep_objects,$1)= + _LT_AC_TAGVAR(postdep_objects,$1)= + _LT_AC_TAGVAR(postdeps,$1)= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun' + ;; + esac + ;; +esac +]) + case " $_LT_AC_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac ])# AC_LIBTOOL_POSTDEP_PREDEP # AC_LIBTOOL_LANG_F77_CONFIG -# ------------------------ +# -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. @@ -3680,12 +3933,16 @@ lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` +_LT_CC_BASENAME([$compiler]) AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) @@ -3695,7 +3952,7 @@ test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. -case "$host_os" in +case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then @@ -3704,7 +3961,9 @@ aix3*) fi ;; aix4* | aix5*) - test "$enable_shared" = yes && enable_static=no + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi ;; esac AC_MSG_RESULT([$enable_shared]) @@ -3714,8 +3973,6 @@ AC_MSG_CHECKING([whether to build static libraries]) test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) -test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - _LT_AC_TAGVAR(GCC, $1)="$G77" _LT_AC_TAGVAR(LD, $1)="$LD" @@ -3725,8 +3982,6 @@ AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP - AC_LIBTOOL_CONFIG($1) @@ -3755,20 +4010,27 @@ _LT_AC_TAGVAR(objext, $1)=$objext lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds + AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) @@ -3776,8 +4038,6 @@ AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) -AC_LIBTOOL_SYS_LIB_STRIP -AC_LIBTOOL_DLOPEN_SELF($1) AC_LIBTOOL_CONFIG($1) @@ -3787,7 +4047,7 @@ CC="$lt_save_CC" # AC_LIBTOOL_LANG_RC_CONFIG -# -------------------------- +# ------------------------- # Ensure that the configuration vars for the Windows resource compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. @@ -3811,11 +4071,16 @@ lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes AC_LIBTOOL_CONFIG($1) @@ -3845,7 +4110,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -3951,7 +4216,7 @@ ifelse([$1], [], # # 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. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -3962,11 +4227,11 @@ ifelse([$1], [], SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e s/^X//" +Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= @@ -3997,6 +4262,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -4008,6 +4279,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) @@ -4073,7 +4347,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -4347,9 +4621,6 @@ symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" @@ -4371,15 +4642,31 @@ hpux*) # Its linker distinguishes data from code symbols lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; -solaris* | sysv5*) +solaris*) symcode='[[BDRT]]' ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; sysv4) symcode='[[DFNSTU]]' ;; @@ -4402,8 +4689,11 @@ esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no @@ -4559,6 +4849,10 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic @@ -4567,7 +4861,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) ;; *) @@ -4592,18 +4886,28 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; chorus*) case $cc_basename in - cxch68) + cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; dgux*) case $cc_basename in - ec++) + ec++*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; - ghcx) + ghcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; @@ -4611,22 +4915,22 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; esac ;; - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in - CC) + CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; - aCC) + aCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - case "$host_cpu" in + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -4639,9 +4943,13 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; esac ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; irix5* | irix6* | nonstopux*) case $cc_basename in - CC) + CC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. @@ -4652,18 +4960,24 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; linux*) case $cc_basename in - KCC) + KCC*) # KAI C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; - icpc) + icpc* | ecpc*) # Intel C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; - cxx) + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. @@ -4680,7 +4994,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; mvs*) case $cc_basename in - cxx) + cxx*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) @@ -4691,14 +5005,14 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; osf3* | osf4* | osf5*) case $cc_basename in - KCC) + KCC*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; - RCC) + RCC*) # Rational C++ 2.4.1 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; - cxx) + cxx*) # Digital/Compaq C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha @@ -4712,24 +5026,15 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; psos*) ;; - sco*) - case $cc_basename in - CC) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - *) - ;; - esac - ;; solaris*) case $cc_basename in - CC) + CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; - gcx) + gcx*) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; @@ -4739,12 +5044,12 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; sunos4*) case $cc_basename in - CC) + CC*) # Sun C++ 4.x _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; - lcc) + lcc*) # Lucid _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; @@ -4754,7 +5059,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; tandem*) case $cc_basename in - NCC) + NCC*) # NonStop-UX NCC 3.20 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; @@ -4762,7 +5067,14 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; esac ;; - unixware*) + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac ;; vxworks*) ;; @@ -4809,6 +5121,11 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. @@ -4825,7 +5142,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -4851,6 +5168,16 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being @@ -4862,7 +5189,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -4886,12 +5213,19 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) ;; linux*) - case $CC in + case $cc_basename in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; ccc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. @@ -4906,15 +5240,15 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - sco3.2v5*) - _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' - _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' - ;; - solaris*) - _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac ;; sunos4*) @@ -4923,7 +5257,7 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' @@ -4936,6 +5270,17 @@ AC_MSG_CHECKING([for $compiler option to produce PIC]) fi ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + uts4*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' @@ -4963,7 +5308,7 @@ if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi -case "$host_os" in +case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= @@ -4972,6 +5317,16 @@ case "$host_os" in _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" ;; esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) ]) @@ -4996,7 +5351,7 @@ ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' @@ -5039,7 +5394,8 @@ ifelse([$1],[CXX],[ # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= - + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time @@ -5049,6 +5405,10 @@ ifelse([$1],[CXX],[ with_gnu_ld=no fi ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; openbsd*) with_gnu_ld=no ;; @@ -5059,6 +5419,27 @@ ifelse([$1],[CXX],[ # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) @@ -5109,10 +5490,10 @@ EOF _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -5121,9 +5502,55 @@ EOF echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else - ld_shlibs=no + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; @@ -5137,7 +5564,7 @@ EOF fi ;; - solaris* | sysv5*) + solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 @@ -5158,6 +5585,33 @@ EOF fi ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + sunos4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= @@ -5165,31 +5619,6 @@ EOF _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" - fi - else - _LT_AC_TAGVAR(ld_shlibs, $1)=no - fi - ;; - *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' @@ -5200,16 +5629,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ ;; esac - if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then - runpath_var=LD_RUN_PATH - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= - fi + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) @@ -5221,7 +5645,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported @@ -5255,6 +5679,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ break fi done + ;; esac exp_sym_flag='-bexport' @@ -5273,7 +5698,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) + case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` @@ -5292,8 +5717,12 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi + ;; esac shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi else # not using gcc if test "$host_cpu" = ia64; then @@ -5301,11 +5730,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then + if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' - fi + fi fi fi @@ -5319,12 +5748,12 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX @@ -5333,13 +5762,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds it's shared libraries. - _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -5352,7 +5779,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; - bsdi4*) + bsdi[[45]]*) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; @@ -5373,57 +5800,57 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) - if test "$GXX" = yes ; then - _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no - case "$host_os" in - rhapsody* | darwin1.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[[012]]) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' - ;; - 10.*) - _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' - ;; - esac - fi - ;; + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else - _LT_AC_TAGVAR(ld_shlibs, $1)=no + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac fi ;; @@ -5457,7 +5884,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes @@ -5480,47 +5907,62 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; - hpux10* | hpux11*) + hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else - case "$host_cpu" in - hppa*64*|ia64*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - ia64*) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_AC_TAGVAR(hardcode_direct, $1)=no - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' @@ -5568,6 +6010,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else @@ -5613,7 +6056,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5621,21 +6064,15 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; - sco3.2v5*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - solaris*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' if test "$GCC" = yes; then + wlarc='${wl}' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else + wlarc='' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' @@ -5644,8 +6081,18 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; @@ -5702,36 +6149,45 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ fi ;; - sysv4.2uw2*) - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(hardcode_direct, $1)=yes - _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; + runpath_var='LD_RUN_PATH' - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) - _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' if test "$GCC" = yes; then - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi - runpath_var='LD_RUN_PATH' - _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; - sysv5*) - _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi ;; uts4*) @@ -5749,11 +6205,6 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - # # Do we need to explicitly link libc? # @@ -5781,6 +6232,7 @@ x|xyes) libobjs=conftest.$ac_objext deplibs= wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= @@ -5906,7 +6358,7 @@ lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && break + test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -5931,8 +6383,8 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do fi done done -SED=$lt_cv_path_SED ]) +SED=$lt_cv_path_SED AC_MSG_RESULT([$SED]) ]) diff --git a/libs/sofia-sip/config.guess b/libs/sofia-sip/config.guess index 7d0185e019..e3ef63f6cb 100755 --- a/libs/sofia-sip/config.guess +++ b/libs/sofia-sip/config.guess @@ -1,9 +1,9 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. -timestamp='2004-09-07' +timestamp='2005-12-13' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -17,13 +17,15 @@ timestamp='2004-09-07' # # 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. +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. + # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. @@ -53,7 +55,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -66,11 +68,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -123,7 +125,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ;' +esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) @@ -196,55 +198,20 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" - exit 0 ;; - amd64:OpenBSD:*:*) - echo x86_64-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - cats:OpenBSD:*:*) - echo arm-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - luna88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - macppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvmeppc:OpenBSD:*:*) - echo powerpc-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips64-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sun3:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} - exit 0 ;; + exit ;; macppc:MirBSD:*:*) echo powerppc-unknown-mirbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} - exit 0 ;; + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -297,37 +264,43 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; + exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix - exit 0 ;; + exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 - exit 0 ;; + exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 - exit 0;; + exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; + exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos - exit 0 ;; + exit ;; *:OS/390:*:*) echo i370-ibm-openedition - exit 0 ;; + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; *:OS400:*:*) echo powerpc-ibm-os400 - exit 0 ;; + exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp - exit 0;; + exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then @@ -335,32 +308,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in else echo pyramid-pyramid-bsd fi - exit 0 ;; + exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 - exit 0 ;; + exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 - exit 0 ;; - DRS?6000:UNIX_SV:4.2*:7*) + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in - sparc) echo sparc-icl-nx7 && exit 0 ;; + sparc) echo sparc-icl-nx7; exit ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) @@ -369,10 +342,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; + exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 @@ -384,10 +357,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo sparc-sun-sunos${UNAME_RELEASE} ;; esac - exit 0 ;; + exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; + exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor @@ -398,40 +371,40 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; + exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; + exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 - exit 0 ;; + exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; + exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; + exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -455,32 +428,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c \ - && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && exit 0 + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; + exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax - exit 0 ;; + exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax - exit 0 ;; + exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax - exit 0 ;; + exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix - exit 0 ;; + exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 - exit 0 ;; + exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 - exit 0 ;; + exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` @@ -496,29 +470,29 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit 0 ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 - exit 0 ;; + exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 - exit 0 ;; + exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 - exit 0 ;; + exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd - exit 0 ;; + exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; + exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix - exit 0 ;; + exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` @@ -526,7 +500,7 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build @@ -541,14 +515,18 @@ EOF exit(0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 - echo rs6000-ibm-aix3.2.5 + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi - exit 0 ;; + exit ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then @@ -562,28 +540,28 @@ EOF IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; + exit ;; *:AIX:*:*) echo rs6000-ibm-aix - exit 0 ;; + exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 - exit 0 ;; + exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 + exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx - exit 0 ;; + exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 - exit 0 ;; + exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd - exit 0 ;; + exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 - exit 0 ;; + exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in @@ -645,9 +623,19 @@ EOF esac if [ ${HP_ARCH} = "hppa2.0w" ] then - # avoid double evaluation of $set_cc_for_build - test -n "$CC_FOR_BUILD" || eval $set_cc_for_build - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else @@ -655,11 +643,11 @@ EOF fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; + exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -687,158 +675,166 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 - exit 0 ;; + exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd - exit 0 ;; + exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd - exit 0 ;; + exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix - exit 0 ;; + exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf - exit 0 ;; + exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf - exit 0 ;; + exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi - exit 0 ;; + exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites - exit 0 ;; + exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit 0 ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit 0 ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit 0 ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit 0 ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; + exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; + exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; + exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; + exit ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; + exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; + exit ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - x86:Interix*:[34]*) + exit ;; + x86:Interix*:[345]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' - exit 0 ;; + exit ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks - exit 0 ;; + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix - exit 0 ;; + exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin - exit 0 ;; + exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; + exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; + exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu - exit 0 ;; + exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; + exit ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu - exit 0 ;; + exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu - exit 0 ;; + exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu - exit 0 ;; + exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c @@ -855,8 +851,8 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; mips64:Linux:*:*) eval $set_cc_for_build @@ -874,15 +870,18 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` - test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^CPU/{s: ::g;p;}'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu - exit 0 ;; + exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu - exit 0 ;; + exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -896,7 +895,7 @@ EOF objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} - exit 0 ;; + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -904,25 +903,28 @@ EOF PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac - exit 0 ;; + exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu - exit 0 ;; + exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; + exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu - exit 0 ;; + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu - exit 0 ;; + exit ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent @@ -940,15 +942,15 @@ EOF ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit 0 ;; + exit ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit 0 ;; + exit ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit 0 ;; + exit ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build @@ -965,7 +967,7 @@ EOF LIBC=gnulibc1 # endif #else - #ifdef __INTEL_COMPILER + #if defined(__INTEL_COMPILER) || defined(__PGI) LIBC=gnu #else LIBC=gnuaout @@ -975,16 +977,19 @@ EOF LIBC=dietlibc #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` - test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '/^LIBC/{s: ::g;p;}'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 - exit 0 ;; + exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... @@ -992,27 +997,27 @@ EOF # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; + exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; + exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos - exit 0 ;; - i*86:syllable:*:*) + exit ;; + i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable - exit 0 ;; + exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; + exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then @@ -1020,15 +1025,16 @@ EOF else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi - exit 0 ;; - i*86:*:5:[78]*) + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; + exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi - exit 0 ;; + exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv - exit 0 ;; + exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv - exit 0 ;; + exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix - exit 0 ;; + exit ;; M68*:*:R3V[5678]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; + && { echo i486-ncr-sysv4; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 - exit 0 ;; + exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; + exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; + exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 - exit 0 ;; + exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` @@ -1120,69 +1126,72 @@ EOF else echo ns32k-sni-sysv fi - exit 0 ;; + exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 - exit 0 ;; + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 - exit 0 ;; + exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 - exit 0 ;; + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos - exit 0 ;; + exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; + exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 - exit 0 ;; + exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi - exit 0 ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos - exit 0 ;; + exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos - exit 0 ;; + exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos - exit 0 ;; + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} - exit 0 ;; + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in - *86) UNAME_PROCESSOR=i686 ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} - exit 0 ;; + exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then @@ -1190,22 +1199,25 @@ EOF UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} - exit 0 ;; + exit ;; *:QNX:*:4*) echo i386-pc-qnx - exit 0 ;; + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; + exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux - exit 0 ;; + exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv - exit 0 ;; + exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; + exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 @@ -1216,38 +1228,47 @@ EOF UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; + exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 - exit 0 ;; + exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex - exit 0 ;; + exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 - exit 0 ;; + exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 - exit 0 ;; + exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 - exit 0 ;; + exit ;; *:ITS:*:*) echo pdp10-unknown-its - exit 0 ;; + exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} - exit 0 ;; + exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; + exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in - A*) echo alpha-dec-vms && exit 0 ;; - I*) echo ia64-dec-vms && exit 0 ;; - V*) echo vax-dec-vms && exit 0 ;; - esac + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1279,7 +1300,7 @@ main () #endif #if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); + printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) @@ -1368,11 +1389,12 @@ main () } EOF -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) @@ -1381,22 +1403,22 @@ then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd - exit 0 ;; + exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit 0 ;; + exit ;; c34*) echo c34-convex-bsd - exit 0 ;; + exit ;; c38*) echo c38-convex-bsd - exit 0 ;; + exit ;; c4*) echo c4-convex-bsd - exit 0 ;; + exit ;; esac fi @@ -1407,7 +1429,9 @@ This script, last modified $timestamp, has failed to recognize the operating system you are using. It is advised that you download the most up to date version of the config scripts from - ftp://ftp.gnu.org/pub/gnu/config/ + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess +and + http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub If the version you run ($0) is already up to date, please send the following data and any information you think might be diff --git a/libs/sofia-sip/config.h.in b/libs/sofia-sip/config.h.in index 43ebb2383f..037243edb1 100644 --- a/libs/sofia-sip/config.h.in +++ b/libs/sofia-sip/config.h.in @@ -1,5 +1,13 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + /* Define to the random number source name. */ #undef DEV_URANDOM @@ -9,6 +17,13 @@ /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H @@ -193,6 +208,9 @@ /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL +/* Define to 1 if you use poll in su_port. */ +#undef HAVE_POLL_PORT + /* Define to 1 if you have /proc/net/if_inet6 control file */ #undef HAVE_PROC_NET_IF_INET6 @@ -221,6 +239,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SIGCOMP_H +/* Define to 1 if you have the `signal' function. */ +#undef HAVE_SIGNAL + /* Define to 1 if you have SIGPIPE */ #undef HAVE_SIGPIPE @@ -233,6 +254,9 @@ /* Define to 1 if you have the `socketpair' function. */ #undef HAVE_SOCKETPAIR +/* Define to 1 if we use NTH library */ +#undef HAVE_SOFIA_NTH + /* Define to 1 if we use NTLM library */ #undef HAVE_SOFIA_NTLM @@ -278,6 +302,9 @@ /* Define to 1 if your CC supports C99 struct initialization */ #undef HAVE_STRUCT_KEYWORDS +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EPOLL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H @@ -362,6 +389,14 @@ /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/libs/sofia-sip/config.sub b/libs/sofia-sip/config.sub index edb6b663ca..285164700d 100755 --- a/libs/sofia-sip/config.sub +++ b/libs/sofia-sip/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. -timestamp='2004-08-29' +timestamp='2005-12-11' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -21,14 +21,15 @@ timestamp='2004-08-29' # # 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. - +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. + # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # @@ -70,7 +71,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO @@ -83,11 +84,11 @@ Try \`$me --help' for more information." while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; + echo "$timestamp" ; exit ;; --version | -v ) - echo "$version" ; exit 0 ;; + echo "$version" ; exit ;; --help | --h* | -h ) - echo "$usage"; exit 0 ;; + echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. @@ -99,7 +100,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. echo $1 - exit 0;; + exit ;; * ) break ;; @@ -118,8 +119,9 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ - kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -170,6 +172,10 @@ case $os in -hiux*) os=-hiuxwe2 ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -186,6 +192,10 @@ case $os in # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -231,13 +241,14 @@ case $basic_machine in | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m32rle | m68000 | m68k | m88k | mcore \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -246,6 +257,7 @@ case $basic_machine in | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ @@ -254,23 +266,28 @@ case $basic_machine in | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | mt \ | msp430 \ | ns16k | ns32k \ - | openrisc | or32 \ + | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ - | x86 | xscale | xstormy16 | xtensa \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; + m32c) + basic_machine=$basic_machine-unknown + ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown @@ -278,6 +295,9 @@ case $basic_machine in ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; + ms1) + basic_machine=mt-unknown + ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and @@ -298,7 +318,7 @@ case $basic_machine in | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ - | bs2000-* \ + | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ @@ -310,7 +330,7 @@ case $basic_machine in | ip2k-* | iq2000-* \ | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ @@ -319,6 +339,7 @@ case $basic_machine in | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ @@ -327,6 +348,7 @@ case $basic_machine in | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ + | mt-* \ | msp430-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ @@ -334,20 +356,23 @@ case $basic_machine in | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ - | xtensa-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ | ymp-* \ | z8k-*) ;; + m32c-*) + ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) @@ -489,6 +514,10 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx @@ -679,6 +708,9 @@ case $basic_machine in basic_machine=i386-pc os=-msdos ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; mvs) basic_machine=i370-ibm os=-mvs @@ -754,9 +786,8 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; - or32 | or32-*) + openrisc | openrisc-*) basic_machine=or32-unknown - os=-coff ;; os400) basic_machine=powerpc-ibm @@ -843,6 +874,10 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; rom68k) basic_machine=m68k-rom68k os=-coff @@ -1029,6 +1064,10 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; xps | xps100) basic_machine=xps100-honeywell ;; @@ -1078,12 +1117,9 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; @@ -1164,13 +1200,15 @@ case $os in | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1188,7 +1226,7 @@ case $os in os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) @@ -1297,6 +1335,9 @@ case $os in -kaos*) os=-kaos ;; + -zvmoe) + os=-zvmoe + ;; -none) ;; *) @@ -1374,6 +1415,9 @@ case $basic_machine in *-be) os=-beos ;; + *-haiku) + os=-haiku + ;; *-ibm) os=-aix ;; @@ -1545,7 +1589,7 @@ case $basic_machine in esac echo $basic_machine$os -exit 0 +exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) diff --git a/libs/sofia-sip/configure b/libs/sofia-sip/configure index 4142c0fa01..0f1986eaee 100755 --- a/libs/sofia-sip/configure +++ b/libs/sofia-sip/configure @@ -278,15 +278,15 @@ fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. -if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if (echo_test_string="`eval $cmd`") 2>/dev/null && - echo_test_string="`eval $cmd`" && + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break @@ -463,7 +463,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS VER_LIBSOFIA_SIP_UA_MAJOR_MINOR include_sofiadir LIBVER_SOFIA_SIP_UA_CUR LIBVER_SOFIA_SIP_UA_REV LIBVER_SOFIA_SIP_UA_AGE LIBVER_SOFIA_SIP_UA_SOVER LIBVER_SOFIA_SIP_UA_GLIB_CUR LIBVER_SOFIA_SIP_UA_GLIB_REV LIBVER_SOFIA_SIP_UA_GLIB_AGE LIBVER_SOFIA_SIP_UA_GLIB_SOVER build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE MINGW_ENVIRONMENT HAVE_MINGW32_TRUE HAVE_MINGW32_FALSE CWFLAG SOFIA_CFLAGS ENABLE_COVERAGE_TRUE ENABLE_COVERAGE_FALSE MOSTLYCLEANFILES CPP ETAGS AR ac_ct_AR LD ac_ct_LD EGREP LN_S ECHO RANLIB ac_ct_RANLIB CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL NDEBUG_TRUE NDEBUG_FALSE TESTS_ENVIRONMENT EXPENSIVE_CHECKS_TRUE EXPENSIVE_CHECKS_FALSE ACLOCAL_AMFLAGS DOXYGEN HAVE_DOXYGEN_TRUE HAVE_DOXYGEN_FALSE COREFOUNDATION_TRUE COREFOUNDATION_FALSE PKG_CONFIG GLIB_CFLAGS GLIB_LIBS HAVE_GLIB_TRUE HAVE_GLIB_FALSE GLIB_VERSION SOFIA_GLIB_PKG_REQUIRES REPLACE_LIBADD HAVE_TLS_TRUE HAVE_TLS_FALSE HAVE_NTLM_TRUE HAVE_NTLM_FALSE LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS VER_LIBSOFIA_SIP_UA_MAJOR_MINOR include_sofiadir LIBVER_SOFIA_SIP_UA_CUR LIBVER_SOFIA_SIP_UA_REV LIBVER_SOFIA_SIP_UA_AGE LIBVER_SOFIA_SIP_UA_SOVER LIBVER_SOFIA_SIP_UA_GLIB_CUR LIBVER_SOFIA_SIP_UA_GLIB_REV LIBVER_SOFIA_SIP_UA_GLIB_AGE LIBVER_SOFIA_SIP_UA_GLIB_SOVER build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE MINGW_ENVIRONMENT HAVE_MINGW32_TRUE HAVE_MINGW32_FALSE CWFLAG SOFIA_CFLAGS SOFIA_COVERAGE ENABLE_COVERAGE_TRUE ENABLE_COVERAGE_FALSE MOSTLYCLEANFILES CPP ETAGS AR ac_ct_AR LD ac_ct_LD EGREP LN_S ECHO RANLIB ac_ct_RANLIB CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL NDEBUG_TRUE NDEBUG_FALSE TESTS_ENVIRONMENT EXPENSIVE_CHECKS_TRUE EXPENSIVE_CHECKS_FALSE ACLOCAL_AMFLAGS DOXYGEN HAVE_DOXYGEN_TRUE HAVE_DOXYGEN_FALSE COREFOUNDATION_TRUE COREFOUNDATION_FALSE PKG_CONFIG GLIB_CFLAGS GLIB_LIBS HAVE_GLIB_TRUE HAVE_GLIB_FALSE GLIB_VERSION SOFIA_GLIB_PKG_REQUIRES ALLOCA REPLACE_LIBADD HAVE_TLS_TRUE HAVE_TLS_FALSE HAVE_STUN_TRUE HAVE_STUN_FALSE HAVE_NTH_TRUE HAVE_NTH_FALSE HAVE_NTLM_TRUE HAVE_NTLM_FALSE LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -1044,9 +1044,14 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --enable-ndebug compile with NDEBUG (disabled) --enable-expensive-checks run also expensive checks (disabled) + --enable-experimental enable experimental features (disabled) --disable-size-compat use compatibility size_t types (enabled) --enable-corefoundation compile with OSX COREFOUNDATION (disabled) + --disable-poll-port disable su_poll_port (enabled) + Use this option in systems emulating poll + with select --disable-stun disable stun module (enabled) + --disable-nth disable nth and http modules (enabled) --enable-ntlm enable NTLM support (disabled) Optional Packages: @@ -4385,7 +4390,8 @@ fi; if test X$enable_coverage != Xno ; then case "${CC-cc}" in *gcc*) - SOFIA_CFLAGS="$SOFIA_CFLAGS -fprofile-arcs -ftest-coverage" + SOFIA_COVERAGE="-fprofile-arcs -ftest-coverage" + ;; *) { { echo "$as_me:$LINENO: error: --enable-coverage requires gcc" >&5 echo "$as_me: error: --enable-coverage requires gcc" >&2;} @@ -5013,7 +5019,7 @@ lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && break + test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in @@ -5038,10 +5044,10 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do fi done done -SED=$lt_cv_path_SED fi +SED=$lt_cv_path_SED echo "$as_me:$LINENO: result: $SED" >&5 echo "${ECHO_T}$SED" >&6 @@ -5118,7 +5124,7 @@ else if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. + # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - # I'd rather use --version here, but apparently some GNU ld's only accept -v. + # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 @@ -5192,36 +5207,43 @@ else # Let the user override the test. lt_cv_path_NM="$NM" else - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/${ac_tool_prefix}nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" break ;; *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac ;; esac - esac - fi + fi + done + IFS="$lt_save_ifs" done - IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi @@ -5268,7 +5290,7 @@ beos*) lt_cv_deplibs_check_method=pass_all ;; -bsdi4*) +bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so @@ -5291,13 +5313,13 @@ darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | kfreebsd*-gnu) +freebsd* | kfreebsd*-gnu | dragonfly*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; @@ -5313,7 +5335,7 @@ gnu*) hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file - case "$host_cpu" in + case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so @@ -5329,6 +5351,11 @@ hpux10.20* | hpux11*) esac ;; +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; @@ -5341,15 +5368,6 @@ irix5* | irix6* | nonstopux*) # This must be Linux ELF. linux*) - case $host_cpu in - alpha*|hppa*|i*86|ia64*|m68*|mips*|powerpc*|sparc*|s390*|sh*|x86_64*) - lt_cv_deplibs_check_method=pass_all ;; - *) - # glibc up to 2.1.1 does not perform some relocations on ARM - # this will be overridden with pass_all, but let us keep it just in case - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; - esac - lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` lt_cv_deplibs_check_method=pass_all ;; @@ -5372,12 +5390,10 @@ nto-qnx*) ;; openbsd*) - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else - lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; @@ -5385,15 +5401,11 @@ osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; -sco3.2v5*) - lt_cv_deplibs_check_method=pass_all - ;; - solaris*) lt_cv_deplibs_check_method=pass_all ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' @@ -5414,10 +5426,13 @@ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) siemens) lt_cv_deplibs_check_method=pass_all ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; esac ;; -sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*) +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac @@ -5435,6 +5450,9 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC @@ -5470,7 +5488,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 5473 "configure"' > conftest.$ac_ext + echo '#line 5491 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -5513,7 +5531,7 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then - case "`/usr/bin/file conftest.o`" in + case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*linux*) @@ -5626,6 +5644,26 @@ echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 CFLAGS="$SAVE_CFLAGS" fi ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + esac @@ -6485,7 +6523,12 @@ else fi -ac_ext=cc + + +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' @@ -6715,6 +6758,8 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +fi + ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' @@ -6808,7 +6853,7 @@ fi # Provide some information about the compiler. -echo "$as_me:6811:" \ +echo "$as_me:6856:" \ "checking for Fortran 77 compiler version" >&5 ac_compiler=`set X $ac_compile; echo $2` { (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 @@ -6998,11 +7043,55 @@ else lt_cv_sys_max_cmd_len=8192; ;; - *) + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while (test "X"`$CONFIG_SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ = "XX$teststring") >/dev/null 2>&1 && new_result=`expr "X$teststring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && @@ -7048,9 +7137,6 @@ symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' -# Transform the above into a raw symbol and a C symbol. -symxfrm='\1 \2\3 \3' - # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" @@ -7072,15 +7158,31 @@ hpux*) # Its linker distinguishes data from code symbols lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; -solaris* | sysv5*) +solaris*) symcode='[BDRT]' ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; sysv4) symcode='[DFNSTU]' ;; @@ -7103,8 +7205,11 @@ esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + # Write the raw and C identifiers. - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no @@ -7266,7 +7371,7 @@ esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. -Xsed='sed -e s/^X//' +Xsed='sed -e 1s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. @@ -7286,7 +7391,7 @@ rm="rm -f" default_ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except M$VC, +# All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" @@ -7543,6 +7648,7 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" @@ -7562,15 +7668,26 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) - old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) - old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + + # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) @@ -7596,7 +7713,7 @@ else if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then @@ -7658,7 +7775,7 @@ else if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) - file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then @@ -7753,68 +7870,25 @@ lt_simple_link_test_code='int main(){return(0);}\n' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC -# -# Check for any special shared library compilation flags. -# -lt_prog_cc_shlib= -if test "$GCC" = no; then - case $host_os in - sco3.2v5*) - lt_prog_cc_shlib='-belf' - ;; - esac -fi -if test -n "$lt_prog_cc_shlib"; then - { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 -echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} - if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then : - else - { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 -echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} - lt_cv_prog_cc_can_build_shared=no - fi -fi - - -# -# Check to make sure the static flag actually works. -# -echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5 -echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static works... $ECHO_C" >&6 -if test "${lt_prog_compiler_static_works+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - lt_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $lt_prog_compiler_static" - printf "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&5 - else - lt_prog_compiler_static_works=yes - fi - fi - $rm conftest* - LDFLAGS="$save_LDFLAGS" - -fi -echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 -echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 - -if test x"$lt_prog_compiler_static_works" = xyes; then - : -else - lt_prog_compiler_static= -fi +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* @@ -7839,18 +7913,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7845: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7919: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7849: \$? = $ac_status" >&5 + echo "$as_me:7923: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi @@ -7911,6 +7987,11 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_pic='-fno-common' ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. @@ -7927,7 +8008,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -7953,6 +8034,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being @@ -7964,7 +8055,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -7988,12 +8079,19 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; linux*) - case $CC in + case $cc_basename in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. @@ -8008,15 +8106,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static='-non_shared' ;; - sco3.2v5*) - lt_prog_compiler_pic='-Kpic' - lt_prog_compiler_static='-dn' - ;; - solaris*) - lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac ;; sunos4*) @@ -8025,7 +8123,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static='-Bstatic' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' @@ -8038,6 +8136,17 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 fi ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' @@ -8072,18 +8181,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8078: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8187: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8082: \$? = $ac_status" >&5 + echo "$as_me:8191: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works=yes fi fi @@ -8104,7 +8215,7 @@ else fi fi -case "$host_os" in +case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= @@ -8114,6 +8225,48 @@ case "$host_os" in ;; esac +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works=yes + fi + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o+set}" = set; then @@ -8132,23 +8285,25 @@ else # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8138: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8291: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8142: \$? = $ac_status" >&5 + echo "$as_me:8295: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - if test ! -s out/conftest.err; then + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi - chmod u+w . + chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -8224,6 +8379,16 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) @@ -8234,6 +8399,10 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar with_gnu_ld=no fi ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; openbsd*) with_gnu_ld=no ;; @@ -8244,6 +8413,27 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) @@ -8294,10 +8484,10 @@ EOF allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -8306,7 +8496,53 @@ EOF echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + interix3*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi else ld_shlibs=no fi @@ -8322,7 +8558,7 @@ EOF fi ;; - solaris* | sysv5*) + solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 @@ -8343,6 +8579,33 @@ EOF fi ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= @@ -8350,31 +8613,6 @@ EOF hardcode_shlibpath_var=no ;; - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds="$tmp_archive_cmds" - fi - else - ld_shlibs=no - fi - ;; - *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' @@ -8385,16 +8623,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ ;; esac - if test "$ld_shlibs" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec= - fi + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) @@ -8406,7 +8639,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -8440,6 +8673,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ break fi done + ;; esac exp_sym_flag='-bexport' @@ -8458,7 +8692,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ link_all_deplibs=yes if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) + case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` @@ -8477,8 +8711,12 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi + ;; esac shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi else # not using gcc if test "$host_cpu" = ia64; then @@ -8486,11 +8724,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then + if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' - fi + fi fi fi @@ -8555,12 +8793,12 @@ rm -f conftest.err conftest.$ac_objext \ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF @@ -8620,13 +8858,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols=yes # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec=' ' + whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -8639,7 +8875,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ld_shlibs=no ;; - bsdi4*) + bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; @@ -8665,52 +8901,52 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag='-undefined dynamic_lookup' - ;; - esac - fi - ;; + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='-all_load $convenience' + whole_archive_flag_spec='' link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else - ld_shlibs=no + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac fi ;; @@ -8744,7 +8980,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -8767,47 +9003,62 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec='${wl}-E' ;; - hpux10* | hpux11*) + hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; + ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld='+b $libdir' - hardcode_libdir_separator=: - hardcode_direct=no - hardcode_shlibpath_var=no - ;; - ia64*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=no - hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_direct=no + hardcode_shlibpath_var=no ;; *) - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' @@ -8855,6 +9106,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else @@ -8900,7 +9152,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -8908,21 +9160,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_separator=: ;; - sco3.2v5*) - archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var=no - export_dynamic_flag_spec='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then + wlarc='${wl}' archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else + wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' @@ -8931,8 +9177,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; esac link_all_deplibs=yes ;; @@ -8989,36 +9245,45 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4.2uw2*) - archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct=yes - hardcode_minus_L=no + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; + runpath_var='LD_RUN_PATH' - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var=no ;; - sysv5*) - no_undefined_flag=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec= + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi ;; uts4*) @@ -9037,11 +9302,6 @@ echo "$as_me:$LINENO: result: $ld_shlibs" >&5 echo "${ECHO_T}$ld_shlibs" >&6 test "$ld_shlibs" = no && can_build_shared=no -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - # # Do we need to explicitly link libc? # @@ -9074,6 +9334,7 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >& libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= @@ -9206,7 +9467,7 @@ beos*) shlibpath_var=LIBRARY_PATH ;; -bsdi4*) +bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -9234,7 +9495,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -9264,7 +9526,7 @@ cygwin* | mingw* | pw32*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; @@ -9287,7 +9549,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -9322,8 +9584,17 @@ kfreebsd*-gnu) dynamic_linker='GNU ld.so' ;; -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -9341,14 +9612,19 @@ freebsd*) freebsd2*) shlibpath_overrides_runpath=yes ;; - freebsd3.01* | freebsdelf3.01*) + freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; - *) # from 3.2 on + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; esac ;; @@ -9368,7 +9644,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -9408,6 +9684,18 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; @@ -9465,31 +9753,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 9472 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -9550,8 +9817,13 @@ nto-qnx*) openbsd*) version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - need_version=yes + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH @@ -9589,13 +9861,6 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - solaris*) version_type=linux need_lib_prefix=no @@ -9621,7 +9886,7 @@ sunos4*) need_version=yes ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -9654,6 +9919,29 @@ sysv4*MP*) fi ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -9669,12 +9957,17 @@ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ - test -n "$runpath_var " || \ - test "X$hardcode_automatic"="Xyes" ; then + test -n "$runpath_var" || \ + test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && @@ -10324,7 +10617,7 @@ fi test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" @@ -10340,7 +10633,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null + (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed @@ -10426,7 +10721,7 @@ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 echo "${ECHO_T}$lt_cv_dlopen_self" >&6 if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 if test "${lt_cv_dlopen_self_static+set}" = set; then @@ -10438,7 +10733,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null + (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed @@ -10542,7 +10839,7 @@ echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 fi -# Report which librarie types wil actually be built +# Report which library types will actually be built echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 echo "$as_me:$LINENO: result: $can_build_shared" >&5 @@ -10554,7 +10851,7 @@ test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. -case "$host_os" in +case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then @@ -10566,43 +10863,6 @@ aix3*) aix4* | aix5*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no - fi - ;; - darwin* | rhapsody*) - if test "$GCC" = yes; then - archive_cmds_need_lc=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag='-undefined dynamic_lookup' - ;; - esac - fi - ;; - esac - output_verbose_link_cmd='echo' - archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' - module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct=no - hardcode_automatic=yes - hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='-all_load $convenience' - link_all_deplibs=yes - else - ld_shlibs=no fi ;; esac @@ -10629,7 +10889,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -10733,7 +10993,7 @@ echo "$as_me: creating $ofile" >&6;} # # 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. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -10744,11 +11004,11 @@ echo "$as_me: creating $ofile" >&6;} SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. -Xsed="$SED -e s/^X//" +Xsed="$SED -e 1s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. -if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH # The names of the tagged configurations supported by this script. available_tags= @@ -10778,6 +11038,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -10789,6 +11055,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_compiler @@ -10854,7 +11123,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -11119,6 +11388,9 @@ echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. @@ -11149,7 +11421,9 @@ echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} case $tagname in CXX) - if test -n "$CXX" && test "X$CXX" != "Xno"; then + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then ac_ext=cc ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -11169,6 +11443,7 @@ hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= @@ -11186,7 +11461,7 @@ postdeps_CXX= compiler_lib_search_path_CXX= # Source file extension for C++ test sources. -ac_ext=cc +ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o @@ -11196,17 +11471,34 @@ objext_CXX=$objext lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests -lt_simple_link_test_code='int main(int, char *) { return(0); }\n' +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD @@ -11217,18 +11509,27 @@ lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else - unset lt_cv_prog_gnu_ld + $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else - unset lt_cv_path_LD + $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately @@ -11299,7 +11600,7 @@ else if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some GNU ld's only accept -v. + # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &6 if test "${lt_cv_prog_gnu_ld+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - # I'd rather use --version here, but apparently some GNU ld's only accept -v. + # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 conftest.$ac_ext <<_ACEOF @@ -11605,16 +11911,26 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_CXX=yes # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_CXX=' ' + whole_archive_flag_spec_CXX='$convenience' archive_cmds_need_lc_CXX=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + chorus*) case $cc_basename in *) @@ -11633,7 +11949,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -11642,70 +11958,81 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs_CXX=no fi ;; - - darwin* | rhapsody*) - if test "$GXX" = yes; then - archive_cmds_need_lc_CXX=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_CXX='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_CXX='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_CXX='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_CXX='-undefined dynamic_lookup' - ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - fi - ;; - esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_CXX='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_CXX='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - hardcode_direct_CXX=no - hardcode_automatic_CXX=yes - hardcode_shlibpath_var_CXX=unsupported - whole_archive_flag_spec_CXX='-all_load $convenience' - link_all_deplibs_CXX=yes - else - ld_shlibs_CXX=no - fi - ;; + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; dgux*) case $cc_basename in - ec++) + ec++*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - ghcx) + ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no @@ -11716,14 +12043,14 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; esac ;; - freebsd12*) + freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes @@ -11740,11 +12067,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # location of the library. case $cc_basename in - CC) + CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - aCC) + aCC*) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when @@ -11754,7 +12081,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then @@ -11768,34 +12095,23 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) hardcode_libdir_flag_spec_ld_CXX='+b $libdir' - hardcode_libdir_separator_CXX=: - ;; - ia64*) - hardcode_libdir_flag_spec_CXX='-L$libdir' ;; *) - hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi - case "$host_cpu" in - hppa*64*) + case $host_cpu in + hppa*64*|ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; - ia64*) - hardcode_direct_CXX=no - hardcode_shlibpath_var_CXX=no - hardcode_minus_L_CXX=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, @@ -11805,14 +12121,17 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi esac case $cc_basename in - CC) + CC*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - aCC) - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' @@ -11831,9 +12150,12 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then - case "$host_cpu" in - ia64*|hppa*64*) - archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' @@ -11847,11 +12169,25 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; esac ;; + interix3*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; irix5* | irix6*) case $cc_basename in - CC) + CC*) # SGI C++ - archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -11862,7 +12198,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then - archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi @@ -11875,7 +12211,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; linux*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -11900,17 +12236,41 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; - icpc) + icpc*) # Intel C++ with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac archive_cmds_need_lc_CXX=no - archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; - cxx) + pgCC*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' @@ -11941,7 +12301,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; mvs*) case $cc_basename in - cxx) + cxx*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; @@ -11962,9 +12322,25 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; osf3*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -11980,14 +12356,14 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; - RCC) + RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - cxx) + cxx*) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: @@ -12005,7 +12381,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: @@ -12024,7 +12400,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; osf4* | osf5*) case $cc_basename in - KCC) + KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file @@ -12039,17 +12415,17 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; - RCC) + RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - cxx) + cxx*) allow_undefined_flag_CXX=' -expect_unresolved \*' - archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' @@ -12068,7 +12444,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: @@ -12089,27 +12465,14 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - sco*) - archive_cmds_need_lc_CXX=no - case $cc_basename in - CC) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - *) - # FIXME: insert proper C++ library support - ld_shlibs_CXX=no - ;; - esac - ;; sunos4*) case $cc_basename in - CC) + CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; - lcc) + lcc*) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no @@ -12122,36 +12485,33 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; solaris*) case $cc_basename in - CC) + CC*) # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes no_undefined_flag_CXX=' -zdefs' - archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in - solaris2.0-5 | solaris2.0-5.*) ;; + solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system - # linker. + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; esac link_all_deplibs_CXX=yes - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -12159,7 +12519,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; - gcx) + gcx*) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' @@ -12197,12 +12557,63 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; esac ;; - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac ;; tandem*) case $cc_basename in - NCC) + NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no @@ -12255,7 +12666,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. - output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" + output_verbose_link_cmd=`$echo "X$output_verbose_link_cmd" | $Xsed -e "$no_glob_subst"` for p in `eval $output_verbose_link_cmd`; do case $p in @@ -12331,6 +12742,29 @@ fi $rm -f confest.$objext +# PORTME: override above test on systems where it is broken +case $host_os in +interix3*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +solaris*) + case $cc_basename in + CC*) + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + postdeps_CXX='-lCstd -lCrun' + ;; + esac + ;; +esac + + case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac @@ -12378,6 +12812,10 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic @@ -12386,7 +12824,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) ;; *) @@ -12411,18 +12849,28 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; chorus*) case $cc_basename in - cxch68) + cxch68*) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_CXX='-qnocommon' + lt_prog_compiler_wl_CXX='-Wl,' + ;; + esac + ;; dgux*) case $cc_basename in - ec++) + ec++*) lt_prog_compiler_pic_CXX='-KPIC' ;; - ghcx) + ghcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; @@ -12430,22 +12878,22 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; esac ;; - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in - CC) + CC*) lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; - aCC) + aCC*) lt_prog_compiler_wl_CXX='-Wl,' - lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" - case "$host_cpu" in + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -12458,9 +12906,13 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; esac ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; irix5* | irix6* | nonstopux*) case $cc_basename in - CC) + CC*) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. @@ -12471,18 +12923,24 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; linux*) case $cc_basename in - KCC) + KCC*) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; - icpc) + icpc* | ecpc*) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; - cxx) + pgCC*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. @@ -12499,7 +12957,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; mvs*) case $cc_basename in - cxx) + cxx*) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) @@ -12510,14 +12968,14 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; osf3* | osf4* | osf5*) case $cc_basename in - KCC) + KCC*) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; - RCC) + RCC*) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; - cxx) + cxx*) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha @@ -12531,24 +12989,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; psos*) ;; - sco*) - case $cc_basename in - CC) - lt_prog_compiler_pic_CXX='-fPIC' - ;; - *) - ;; - esac - ;; solaris*) case $cc_basename in - CC) + CC*) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; - gcx) + gcx*) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; @@ -12558,12 +13007,12 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; sunos4*) case $cc_basename in - CC) + CC*) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; - lcc) + lcc*) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; @@ -12573,7 +13022,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; tandem*) case $cc_basename in - NCC) + NCC*) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; @@ -12581,7 +13030,14 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; esac ;; - unixware*) + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac ;; vxworks*) ;; @@ -12614,18 +13070,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12620: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13076: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:12624: \$? = $ac_status" >&5 + echo "$as_me:13080: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_CXX=yes fi fi @@ -12646,7 +13104,7 @@ else fi fi -case "$host_os" in +case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= @@ -12656,6 +13114,48 @@ case "$host_os" in ;; esac +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_CXX=yes + fi + else + lt_prog_compiler_static_works_CXX=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6 + +if test x"$lt_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then @@ -12674,23 +13174,25 @@ else # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:12680: $lt_compile\"" >&5) + (eval echo "\"\$as_me:13180: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:12684: \$? = $ac_status" >&5 + echo "$as_me:13184: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - if test ! -s out/conftest.err; then + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_CXX=yes fi fi - chmod u+w . + chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -12745,7 +13247,7 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) - export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' @@ -12756,11 +13258,6 @@ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 echo "${ECHO_T}$ld_shlibs_CXX" >&6 test "$ld_shlibs_CXX" = no && can_build_shared=no -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - # # Do we need to explicitly link libc? # @@ -12793,6 +13290,7 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >& libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX compiler_flags=-v linker_flags=-v verstring= @@ -12925,7 +13423,7 @@ beos*) shlibpath_var=LIBRARY_PATH ;; -bsdi4*) +bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -12953,7 +13451,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -12983,7 +13482,7 @@ cygwin* | mingw* | pw32*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; @@ -13006,7 +13505,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -13041,8 +13540,17 @@ kfreebsd*-gnu) dynamic_linker='GNU ld.so' ;; -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -13060,14 +13568,19 @@ freebsd*) freebsd2*) shlibpath_overrides_runpath=yes ;; - freebsd3.01* | freebsdelf3.01*) + freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; - *) # from 3.2 on + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; esac ;; @@ -13087,7 +13600,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -13127,6 +13640,18 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; @@ -13184,31 +13709,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 13191 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -13269,8 +13773,13 @@ nto-qnx*) openbsd*) version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - need_version=yes + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH @@ -13308,13 +13817,6 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - solaris*) version_type=linux need_lib_prefix=no @@ -13340,7 +13842,7 @@ sunos4*) need_version=yes ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -13373,6 +13875,29 @@ sysv4*MP*) fi ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -13388,12 +13913,17 @@ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ - test -n "$runpath_var CXX" || \ - test "X$hardcode_automatic_CXX"="Xyes" ; then + test -n "$runpath_var_CXX" || \ + test "X$hardcode_automatic_CXX" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && @@ -13425,841 +13955,6 @@ elif test "$shlibpath_overrides_runpath" = yes || enable_fast_install=needless fi -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_cxx_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh @@ -14274,7 +13969,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -14375,6 +14070,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -14386,6 +14087,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_compiler_CXX @@ -14451,7 +14155,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -14728,16 +14432,42 @@ lt_simple_link_test_code=" program t\n end\n" # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC -cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 @@ -14750,7 +14480,7 @@ test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. -case "$host_os" in +case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then @@ -14759,7 +14489,9 @@ aix3*) fi ;; aix4* | aix5*) - test "$enable_shared" = yes && enable_static=no + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi ;; esac echo "$as_me:$LINENO: result: $enable_shared" >&5 @@ -14772,8 +14504,6 @@ test "$enable_shared" = yes || enable_static=yes echo "$as_me:$LINENO: result: $enable_static" >&5 echo "${ECHO_T}$enable_static" >&6 -test "$ld_shlibs_F77" = no && can_build_shared=no - GCC_F77="$G77" LD_F77="$LD" @@ -14820,6 +14550,11 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_pic_F77='-fno-common' ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. @@ -14836,7 +14571,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -14862,6 +14597,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being @@ -14873,7 +14618,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -14897,12 +14642,19 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; linux*) - case $CC in + case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. @@ -14917,15 +14669,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_F77='-non_shared' ;; - sco3.2v5*) - lt_prog_compiler_pic_F77='-Kpic' - lt_prog_compiler_static_F77='-dn' - ;; - solaris*) - lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; + esac ;; sunos4*) @@ -14934,7 +14686,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_F77='-Bstatic' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' @@ -14947,6 +14699,17 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 fi ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_can_build_shared_F77=no + ;; + uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' @@ -14981,18 +14744,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14987: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14750: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14991: \$? = $ac_status" >&5 + echo "$as_me:14754: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_F77=yes fi fi @@ -15013,7 +14778,7 @@ else fi fi -case "$host_os" in +case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= @@ -15023,6 +14788,48 @@ case "$host_os" in ;; esac +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_F77=yes + fi + else + lt_prog_compiler_static_works_F77=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6 + +if test x"$lt_prog_compiler_static_works_F77" = xyes; then + : +else + lt_prog_compiler_static_F77= +fi + + echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then @@ -15041,23 +14848,25 @@ else # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15047: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14854: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15051: \$? = $ac_status" >&5 + echo "$as_me:14858: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - if test ! -s out/conftest.err; then + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_F77=yes fi fi - chmod u+w . + chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -15133,6 +14942,16 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) @@ -15143,6 +14962,10 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar with_gnu_ld=no fi ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; openbsd*) with_gnu_ld=no ;; @@ -15153,6 +14976,27 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) @@ -15203,10 +15047,10 @@ EOF allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes - export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -15215,9 +15059,55 @@ EOF echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else - ld_shlibs=no + ld_shlibs_F77=no + fi + ;; + + interix3*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_F77=no fi ;; @@ -15231,7 +15121,7 @@ EOF fi ;; - solaris* | sysv5*) + solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <&2 @@ -15252,6 +15142,33 @@ EOF fi ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_F77=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + ;; + sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= @@ -15259,31 +15176,6 @@ EOF hardcode_shlibpath_var_F77=no ;; - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds_F77="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds_F77="$tmp_archive_cmds" - fi - else - ld_shlibs_F77=no - fi - ;; - *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' @@ -15294,16 +15186,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ ;; esac - if test "$ld_shlibs_F77" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_F77='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_F77= - fi + if test "$ld_shlibs_F77" = no; then + runpath_var= + hardcode_libdir_flag_spec_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= fi else # PORTME fill in a description of your system's linker (not GNU ld) @@ -15315,7 +15202,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported @@ -15349,6 +15236,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ break fi done + ;; esac exp_sym_flag='-bexport' @@ -15367,7 +15255,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ link_all_deplibs_F77=yes if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) + case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` @@ -15386,8 +15274,12 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi + ;; esac shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi else # not using gcc if test "$host_cpu" = ia64; then @@ -15395,11 +15287,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then + if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' - fi + fi fi fi @@ -15454,12 +15346,12 @@ rm -f conftest.err conftest.$ac_objext \ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF @@ -15509,13 +15401,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_F77=yes # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_F77=' ' + whole_archive_flag_spec_F77='$convenience' archive_cmds_need_lc_F77=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -15528,7 +15418,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ld_shlibs_F77=no ;; - bsdi4*) + bsdi[45]*) export_dynamic_flag_spec_F77=-rdynamic ;; @@ -15549,57 +15439,57 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc_F77=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_F77='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_F77='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_F77='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_F77='-undefined dynamic_lookup' - ;; - esac - fi - ;; + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_F77='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_F77='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds_need_lc_F77=no hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported - whole_archive_flag_spec_F77='-all_load $convenience' + whole_archive_flag_spec_F77='' link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else - ld_shlibs_F77=no + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac fi ;; @@ -15633,7 +15523,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes @@ -15656,47 +15546,62 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec_F77='${wl}-E' ;; - hpux10* | hpux11*) + hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; + ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + case $host_cpu in + hppa*64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + archive_cmds_F77='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld_F77='+b $libdir' - hardcode_libdir_separator_F77=: - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no - ;; - ia64*) - hardcode_libdir_flag_spec_F77='-L$libdir' - hardcode_direct_F77=no - hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_F77=yes + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no ;; *) - hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' @@ -15744,6 +15649,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else @@ -15789,7 +15695,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' @@ -15797,21 +15703,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_separator_F77=: ;; - sco3.2v5*) - archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_F77=no - export_dynamic_flag_spec_F77='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then + wlarc='${wl}' archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else + wlarc='' archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' @@ -15820,8 +15720,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; esac link_all_deplibs_F77=yes ;; @@ -15878,36 +15788,45 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4.2uw2*) - archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_F77=yes - hardcode_minus_L_F77=no + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; + runpath_var='LD_RUN_PATH' - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag_F77='${wl}-z ${wl}text' if test "$GCC" = yes; then - archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_F77='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_F77=no ;; - sysv5*) - no_undefined_flag_F77=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec_F77= + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_F77='${wl}-z,text' + allow_undefined_flag_F77='${wl}-z,nodefs' + archive_cmds_need_lc_F77=no hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi ;; uts4*) @@ -15926,11 +15845,6 @@ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 echo "${ECHO_T}$ld_shlibs_F77" >&6 test "$ld_shlibs_F77" = no && can_build_shared=no -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - # # Do we need to explicitly link libc? # @@ -15963,6 +15877,7 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >& libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 + pic_flag=$lt_prog_compiler_pic_F77 compiler_flags=-v linker_flags=-v verstring= @@ -16095,7 +16010,7 @@ beos*) shlibpath_var=LIBRARY_PATH ;; -bsdi4*) +bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -16123,7 +16038,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -16153,7 +16069,7 @@ cygwin* | mingw* | pw32*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; @@ -16176,7 +16092,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -16211,8 +16127,17 @@ kfreebsd*-gnu) dynamic_linker='GNU ld.so' ;; -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -16230,14 +16155,19 @@ freebsd*) freebsd2*) shlibpath_overrides_runpath=yes ;; - freebsd3.01* | freebsdelf3.01*) + freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; - *) # from 3.2 on + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; esac ;; @@ -16257,7 +16187,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -16297,6 +16227,18 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; @@ -16354,31 +16296,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 16361 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -16439,8 +16360,13 @@ nto-qnx*) openbsd*) version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - need_version=yes + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH @@ -16478,13 +16404,6 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - solaris*) version_type=linux need_lib_prefix=no @@ -16510,7 +16429,7 @@ sunos4*) need_version=yes ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -16543,6 +16462,29 @@ sysv4*MP*) fi ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -16558,12 +16500,17 @@ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ - test -n "$runpath_var F77" || \ - test "X$hardcode_automatic_F77"="Xyes" ; then + test -n "$runpath_var_F77" || \ + test "X$hardcode_automatic_F77" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && @@ -16595,36 +16542,6 @@ elif test "$shlibpath_overrides_runpath" = yes || enable_fast_install=needless fi -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - - # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh @@ -16639,7 +16556,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -16740,6 +16657,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -16751,6 +16674,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_compiler_F77 @@ -16816,7 +16742,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -17054,26 +16980,55 @@ objext_GCJ=$objext lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n' +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no +old_archive_cmds_GCJ=$old_archive_cmds + lt_prog_compiler_no_builtin_flag_GCJ= @@ -17096,18 +17051,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17102: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17057: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:17106: \$? = $ac_status" >&5 + echo "$as_me:17061: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi @@ -17168,6 +17125,11 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_pic_GCJ='-fno-common' ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. @@ -17184,7 +17146,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -17210,6 +17172,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being @@ -17221,7 +17193,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. - case "$host_cpu" in + case $host_cpu in hppa*64*|ia64*) # +Z the default ;; @@ -17245,12 +17217,19 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 ;; linux*) - case $CC in + case $cc_basename in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. @@ -17265,15 +17244,15 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_GCJ='-non_shared' ;; - sco3.2v5*) - lt_prog_compiler_pic_GCJ='-Kpic' - lt_prog_compiler_static_GCJ='-dn' - ;; - solaris*) - lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; + esac ;; sunos4*) @@ -17282,7 +17261,7 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 lt_prog_compiler_static_GCJ='-Bstatic' ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' @@ -17295,6 +17274,17 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 fi ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_can_build_shared_GCJ=no + ;; + uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' @@ -17329,18 +17319,20 @@ else # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17335: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17325: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:17339: \$? = $ac_status" >&5 + echo "$as_me:17329: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - if test ! -s conftest.err; then + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_prog_compiler_pic_works_GCJ=yes fi fi @@ -17361,7 +17353,7 @@ else fi fi -case "$host_os" in +case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= @@ -17371,6 +17363,48 @@ case "$host_os" in ;; esac +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" +echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_prog_compiler_static_works_GCJ=yes + fi + else + lt_prog_compiler_static_works_GCJ=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6 + +if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then + : +else + lt_prog_compiler_static_GCJ= +fi + + echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then @@ -17389,23 +17423,25 @@ else # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:17395: $lt_compile\"" >&5) + (eval echo "\"\$as_me:17429: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:17399: \$? = $ac_status" >&5 + echo "$as_me:17433: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - if test ! -s out/conftest.err; then + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi - chmod u+w . + chmod u+w . 2>&5 $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation @@ -17481,6 +17517,16 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` case $host_os in cygwin* | mingw* | pw32*) @@ -17491,6 +17537,10 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar with_gnu_ld=no fi ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; openbsd*) with_gnu_ld=no ;; @@ -17501,6 +17551,27 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) @@ -17551,10 +17622,10 @@ EOF allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes - export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then @@ -17563,9 +17634,55 @@ EOF echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else - ld_shlibs=no + ld_shlibs_GCJ=no + fi + ;; + + interix3*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_GCJ=no fi ;; @@ -17579,7 +17696,7 @@ EOF fi ;; - solaris* | sysv5*) + solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <&2 @@ -17600,6 +17717,33 @@ EOF fi ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs_GCJ=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + ;; + sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= @@ -17607,31 +17751,6 @@ EOF hardcode_shlibpath_var_GCJ=no ;; - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_cmds_GCJ="$tmp_archive_cmds" - supports_anon_versioning=no - case `$LD -v 2>/dev/null` in - *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - if test $supports_anon_versioning = yes; then - archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ -cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ -$echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - else - archive_expsym_cmds_GCJ="$tmp_archive_cmds" - fi - else - ld_shlibs_GCJ=no - fi - ;; - *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' @@ -17642,16 +17761,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ ;; esac - if test "$ld_shlibs_GCJ" = yes; then - runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' - export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - whole_archive_flag_spec_GCJ= - fi + if test "$ld_shlibs_GCJ" = no; then + runpath_var= + hardcode_libdir_flag_spec_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= fi else # PORTME fill in a description of your system's linker (not GNU ld) @@ -17663,7 +17777,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes - if test "$GCC" = yes && test -z "$link_static_flag"; then + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=unsupported @@ -17697,6 +17811,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ break fi done + ;; esac exp_sym_flag='-bexport' @@ -17715,7 +17830,7 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ link_all_deplibs_GCJ=yes if test "$GCC" = yes; then - case $host_os in aix4.012|aix4.012.*) + case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` @@ -17734,8 +17849,12 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi + ;; esac shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi else # not using gcc if test "$host_cpu" = ia64; then @@ -17743,11 +17862,11 @@ $echo "local: *; };" >> $output_objdir/$libname.ver~ # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then + if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' - fi + fi fi fi @@ -17812,12 +17931,12 @@ rm -f conftest.err conftest.$ac_objext \ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat >conftest.$ac_ext <<_ACEOF @@ -17877,13 +17996,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' - # -bexpall does not export symbols beginning with underscore (_) - always_export_symbols_GCJ=yes # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec_GCJ=' ' + whole_archive_flag_spec_GCJ='$convenience' archive_cmds_need_lc_GCJ=yes - # This is similar to how AIX traditionally builds it's shared libraries. - archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; @@ -17896,7 +18013,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ld_shlibs_GCJ=no ;; - bsdi4*) + bsdi[45]*) export_dynamic_flag_spec_GCJ=-rdynamic ;; @@ -17917,57 +18034,57 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) - if test "$GXX" = yes ; then - archive_cmds_need_lc_GCJ=no - case "$host_os" in - rhapsody* | darwin1.[012]) - allow_undefined_flag_GCJ='-undefined suppress' - ;; - *) # Darwin 1.3 on - if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then - allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' - else - case ${MACOSX_DEPLOYMENT_TARGET} in - 10.[012]) - allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' - ;; - 10.*) - allow_undefined_flag_GCJ='-undefined dynamic_lookup' - ;; - esac - fi - ;; + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; esac - lt_int_apple_cc_single_mod=no - output_verbose_link_cmd='echo' - if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then - lt_int_apple_cc_single_mod=yes - fi - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_cmds_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - else - archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' - fi - module_cmds_GCJ='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' - # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's - if test "X$lt_int_apple_cc_single_mod" = Xyes ; then - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - else - archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + archive_cmds_need_lc_GCJ=no hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported - whole_archive_flag_spec_GCJ='-all_load $convenience' + whole_archive_flag_spec_GCJ='' link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else - ld_shlibs_GCJ=no + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac fi ;; @@ -18001,7 +18118,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | kfreebsd*-gnu) + freebsd* | kfreebsd*-gnu | dragonfly*) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes @@ -18024,47 +18141,62 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi export_dynamic_flag_spec_GCJ='${wl}-E' ;; - hpux10* | hpux11*) + hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*|ia64*) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; + ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else - case "$host_cpu" in - hppa*64*|ia64*) - archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + case $host_cpu in + hppa*64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + archive_cmds_GCJ='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then - case "$host_cpu" in - hppa*64*) - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' - hardcode_libdir_separator_GCJ=: - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no - ;; - ia64*) - hardcode_libdir_flag_spec_GCJ='-L$libdir' - hardcode_direct_GCJ=no - hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L_GCJ=yes + case $host_cpu in + hppa*64*|ia64*) + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no ;; *) - hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' - hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' @@ -18112,6 +18244,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else @@ -18157,7 +18290,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ - $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' @@ -18165,21 +18298,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_separator_GCJ=: ;; - sco3.2v5*) - archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - hardcode_shlibpath_var_GCJ=no - export_dynamic_flag_spec_GCJ='${wl}-Bexport' - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - ;; - solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then + wlarc='${wl}' archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else + wlarc='' archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' @@ -18188,8 +18315,18 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; - *) # Supported since Solaris 2.6 (maybe 2.5.1?) - whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + *) + whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; esac link_all_deplibs_GCJ=yes ;; @@ -18246,36 +18383,45 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi fi ;; - sysv4.2uw2*) - archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' - hardcode_direct_GCJ=yes - hardcode_minus_L_GCJ=no + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no - hardcode_runpath_var=yes - runpath_var=LD_RUN_PATH - ;; + runpath_var='LD_RUN_PATH' - sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) - no_undefined_flag_GCJ='${wl}-z ${wl}text' if test "$GCC" = yes; then - archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds_GCJ='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi - runpath_var='LD_RUN_PATH' - hardcode_shlibpath_var_GCJ=no ;; - sysv5*) - no_undefined_flag_GCJ=' -z text' - # $CC -shared without GNU ld will not create a library from C++ - # object files and a static libstdc++, better avoid it by now - archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' - hardcode_libdir_flag_spec_GCJ= + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_GCJ='${wl}-z,text' + allow_undefined_flag_GCJ='${wl}-z,nodefs' + archive_cmds_need_lc_GCJ=no hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi ;; uts4*) @@ -18294,11 +18440,6 @@ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 echo "${ECHO_T}$ld_shlibs_GCJ" >&6 test "$ld_shlibs_GCJ" = no && can_build_shared=no -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - # # Do we need to explicitly link libc? # @@ -18331,6 +18472,7 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >& libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ + pic_flag=$lt_prog_compiler_pic_GCJ compiler_flags=-v linker_flags=-v verstring= @@ -18463,7 +18605,7 @@ beos*) shlibpath_var=LIBRARY_PATH ;; -bsdi4*) +bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -18491,7 +18633,8 @@ cygwin* | mingw* | pw32*) dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname' + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' @@ -18521,7 +18664,7 @@ cygwin* | mingw* | pw32*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; @@ -18544,7 +18687,7 @@ darwin* | rhapsody*) soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` @@ -18579,8 +18722,17 @@ kfreebsd*-gnu) dynamic_linker='GNU ld.so' ;; -freebsd*) - objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) @@ -18598,14 +18750,19 @@ freebsd*) freebsd2*) shlibpath_overrides_runpath=yes ;; - freebsd3.01* | freebsdelf3.01*) + freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; - *) # from 3.2 on + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; esac ;; @@ -18625,7 +18782,7 @@ hpux9* | hpux10* | hpux11*) version_type=sunos need_lib_prefix=no need_version=no - case "$host_cpu" in + case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes @@ -18665,6 +18822,18 @@ hpux9* | hpux10* | hpux11*) postinstall_cmds='chmod 555 $lib' ;; +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; @@ -18722,31 +18891,10 @@ linux*) # before this can be enabled. hardcode_into_libs=yes - # find out which ABI we are using - libsuff= - case "$host_cpu" in - x86_64*|s390x*|powerpc64*) - echo '#line 18729 "configure"' > conftest.$ac_ext - if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - case `/usr/bin/file conftest.$ac_objext` in - *64-bit*) - libsuff=64 - sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" - ;; - esac - fi - rm -rf conftest* - ;; - esac - # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff} $lt_ld_extra" + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on @@ -18807,8 +18955,13 @@ nto-qnx*) openbsd*) version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no - need_version=yes + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH @@ -18846,13 +18999,6 @@ osf3* | osf4* | osf5*) sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; -sco3.2v5*) - version_type=osf - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - ;; - solaris*) version_type=linux need_lib_prefix=no @@ -18878,7 +19024,7 @@ sunos4*) need_version=yes ;; -sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) +sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' @@ -18911,6 +19057,29 @@ sysv4*MP*) fi ;; +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' @@ -18926,12 +19095,17 @@ echo "$as_me:$LINENO: result: $dynamic_linker" >&5 echo "${ECHO_T}$dynamic_linker" >&6 test "$dynamic_linker" = no && can_build_shared=no +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ - test -n "$runpath_var GCJ" || \ - test "X$hardcode_automatic_GCJ"="Xyes" ; then + test -n "$runpath_var_GCJ" || \ + test "X$hardcode_automatic_GCJ" = "Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && @@ -18963,841 +19137,6 @@ elif test "$shlibpath_overrides_runpath" = yes || enable_fast_install=needless fi -striplib= -old_striplib= -echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 -echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 -if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - ;; - *) - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - ;; - esac -fi - -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - -fi - - ;; - - *) - echo "$as_me:$LINENO: checking for shl_load" >&5 -echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 -if test "${ac_cv_func_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define shl_load to an innocuous variant, in case declares shl_load. - For example, HP-UX 11i declares gettimeofday. */ -#define shl_load innocuous_shl_load - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char shl_load (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef shl_load - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_shl_load) || defined (__stub___shl_load) -choke me -#else -char (*f) () = shl_load; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != shl_load; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 -echo "${ECHO_T}$ac_cv_func_shl_load" >&6 -if test $ac_cv_func_shl_load = yes; then - lt_cv_dlopen="shl_load" -else - echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 -echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_shl_load+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char shl_load (); -int -main () -{ -shl_load (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_shl_load=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_shl_load=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 -if test $ac_cv_lib_dld_shl_load = yes; then - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" -else - echo "$as_me:$LINENO: checking for dlopen" >&5 -echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 -if test "${ac_cv_func_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define dlopen to an innocuous variant, in case declares dlopen. - For example, HP-UX 11i declares gettimeofday. */ -#define dlopen innocuous_dlopen - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char dlopen (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef dlopen - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_dlopen) || defined (__stub___dlopen) -choke me -#else -char (*f) () = dlopen; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != dlopen; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 -echo "${ECHO_T}$ac_cv_func_dlopen" >&6 -if test $ac_cv_func_dlopen = yes; then - lt_cv_dlopen="dlopen" -else - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dl_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" -else - echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 -echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 -if test "${ac_cv_lib_svld_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsvld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dlopen (); -int -main () -{ -dlopen (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_svld_dlopen=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_svld_dlopen=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 -if test $ac_cv_lib_svld_dlopen = yes; then - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" -else - echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 -echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 -if test "${ac_cv_lib_dld_dld_link+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldld $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char dld_link (); -int -main () -{ -dld_link (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_dld_dld_link=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dld_dld_link=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 -echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 -if test $ac_cv_lib_dld_dld_link = yes; then - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" -fi - - -fi - - -fi - - -fi - - -fi - - -fi - - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 -echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self" >&6 - - if test "x$lt_cv_dlopen_self" = xyes; then - LDFLAGS="$LDFLAGS $link_static_flag" - echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 -echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 -if test "${lt_cv_dlopen_self_static+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then : - lt_cv_dlopen_self_static=cross -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext < -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" void exit (int); -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - - exit (status); -} -EOF - if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; - x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; - esac - else : - # compilation failed - lt_cv_dlopen_self_static=no - fi -fi -rm -fr conftest* - - -fi -echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 -echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi - # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh @@ -19812,7 +19151,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -19913,6 +19252,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -19924,6 +19269,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_compiler_GCJ @@ -19989,7 +19337,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -20233,15 +19581,42 @@ lt_simple_link_test_code="$lt_simple_compile_test_code" # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + # Allow CC to be a program name with arguments. compiler=$CC +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* + +ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* + + # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` + lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the @@ -20257,7 +19632,7 @@ if test -f "$ltmain"; then # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. - for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \ + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC LTCFLAGS NM \ SED SHELL STRIP \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ @@ -20358,6 +19733,12 @@ fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os # An echo program that does not interpret backslashes. echo=$lt_echo @@ -20369,6 +19750,9 @@ AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + # A language-specific compiler. CC=$lt_compiler_RC @@ -20434,7 +19818,7 @@ max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC -# Must we lock files when doing compilation ? +# Must we lock files when doing compilation? need_locks=$lt_need_locks # Do we need the lib prefix for modules? @@ -20729,7 +20113,6 @@ else NDEBUG_FALSE= fi -SOFIA_CFLAGS="$SOFIA_CFLAGS -DNDEBUG" # Check whether --enable-expensive-checks or --disable-expensive-checks was given. @@ -21978,6 +21361,22 @@ _AXEOF fi +# Check whether --enable-experimental or --disable-experimental was given. +if test "${enable_experimental+set}" = set; then + enableval="$enable_experimental" + +else + enable_experimental=no +fi; + +if test $enable_experimental = yes ; then + +cat >>confdefs.h <<\_AXEOF +#define SU_HAVE_EXPERIMENTAL 1 +_AXEOF + +fi + @@ -22966,6 +22365,7 @@ _ACEOF else + cat >>confdefs.h <<\_AXEOF #define SU_HAVE_BSDSOCK 1 _AXEOF @@ -22975,8 +22375,9 @@ _AXEOF + for ac_header in sys/socket.h sys/ioctl.h sys/filio.h sys/sockio.h \ - sys/select.h + sys/select.h sys/epoll.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then @@ -24678,6 +24079,364 @@ if test "$ac_cv_search_getaddrinfo" != no; then fi +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo "$as_me:$LINENO: checking for working alloca.h" >&5 +echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6 +if test "${ac_cv_working_alloca_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_working_alloca_h=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_working_alloca_h=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5 +echo "${ECHO_T}$ac_cv_working_alloca_h" >&6 +if test $ac_cv_working_alloca_h = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA_H 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for alloca" >&5 +echo $ECHO_N "checking for alloca... $ECHO_C" >&6 +if test "${ac_cv_func_alloca_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_alloca_works=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_alloca_works=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5 +echo "${ECHO_T}$ac_cv_func_alloca_works" >&6 + +if test $ac_cv_func_alloca_works = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_ALLOCA 1 +_ACEOF + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=alloca.$ac_objext + +cat >>confdefs.h <<\_ACEOF +#define C_ALLOCA 1 +_ACEOF + + +echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5 +echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6 +if test "${ac_cv_os_cray+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5 +echo "${ECHO_T}$ac_cv_os_cray" >&6 +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_func" >&5 +echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 +if eval "test \"\${$as_ac_var+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +char (*f) () = $ac_func; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != $ac_func; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_var=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_var=no" +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 +if test `eval echo '${'$as_ac_var'}'` = yes; then + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +echo "$as_me:$LINENO: checking stack direction for C alloca" >&5 +echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6 +if test "${ac_cv_c_stack_direction+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +int +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} + +int +main () +{ + exit (find_stack_direction () < 0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_stack_direction=1 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_c_stack_direction=-1 +fi +rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5 +echo "${ECHO_T}$ac_cv_c_stack_direction" >&6 + +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi @@ -24701,9 +24460,13 @@ fi -for ac_func in gettimeofday strerror random initstate tcsetattr flock alarm \ + + + +for ac_func in gettimeofday strerror random initstate tcsetattr flock \ socketpair gethostname gethostbyname getipnodebyname \ poll epoll_create select if_nameindex \ + signal alarm \ getaddrinfo getnameinfo freeaddrinfo gai_strerror getifaddrs \ getline getdelim getpass do @@ -24816,7 +24579,8 @@ _AXEOF fi -if test $ac_cv_func_epoll_create = yes ; then +if test $ac_cv_func_epoll_create = yes && test $ac_cv_header_sys_epoll_h = yes +then cat >>confdefs.h <<\_ACEOF #define HAVE_EPOLL 1 @@ -24947,8 +24711,9 @@ fi + for ac_func in memmem memccpy memspn memcspn strcasestr strtoull \ - inet_ntop inet_pton + inet_ntop inet_pton poll do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 @@ -25061,6 +24826,104 @@ done : +if test $ac_cv_func_signal = yes ; then +echo "$as_me:$LINENO: checking whether SIGPIPE is declared" >&5 +echo $ECHO_N "checking whether SIGPIPE is declared... $ECHO_C" >&6 +if test "${ac_cv_have_decl_SIGPIPE+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include + + +int +main () +{ +#ifndef SIGPIPE + char *p = (char *) SIGPIPE; +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_have_decl_SIGPIPE=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_have_decl_SIGPIPE=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGPIPE" >&5 +echo "${ECHO_T}$ac_cv_have_decl_SIGPIPE" >&6 +if test $ac_cv_have_decl_SIGPIPE = yes; then + + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SIGPIPE 1 +_ACEOF + +fi + +fi + +# =========================================================================== +# Check how to implement su_port +# =========================================================================== + +# Check whether --enable-poll-port or --disable-poll-port was given. +if test "${enable_poll_port+set}" = set; then + enableval="$enable_poll_port" + +else + enable_poll_port=maybe +fi; + +if test $enable_poll_port = maybe ; then + if test $ac_cv_func_poll = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_POLL_PORT 1 +_ACEOF + + fi +elif test $enable_poll_port = yes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_POLL_PORT 1 +_ACEOF + +fi # =========================================================================== # Check pthread_rwlock_unlock() @@ -26147,6 +26010,41 @@ _ACEOF fi + +if test "x$enable_stun" = xyes; then + HAVE_STUN_TRUE= + HAVE_STUN_FALSE='#' +else + HAVE_STUN_TRUE='#' + HAVE_STUN_FALSE= +fi + + +# Check whether --enable-nth or --disable-nth was given. +if test "${enable_nth+set}" = set; then + enableval="$enable_nth" + +else + enable_nth=yes +fi; + + +if test "x$enable_nth" = xyes; then + HAVE_NTH_TRUE= + HAVE_NTH_FALSE='#' +else + HAVE_NTH_TRUE='#' + HAVE_NTH_FALSE= +fi + +if test x$enable_nth = xyes ; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_SOFIA_NTH 1 +_ACEOF + +fi + # Check whether --enable-ntlm or --disable-ntlm was given. if test "${enable_ntlm+set}" = set; then enableval="$enable_ntlm" @@ -26356,74 +26254,6 @@ fi ### checks for declarations ### ----------------------- -echo "$as_me:$LINENO: checking whether SIGPIPE is declared" >&5 -echo $ECHO_N "checking whether SIGPIPE is declared... $ECHO_C" >&6 -if test "${ac_cv_have_decl_SIGPIPE+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -#include - - -int -main () -{ -#ifndef SIGPIPE - char *p = (char *) SIGPIPE; -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_have_decl_SIGPIPE=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_have_decl_SIGPIPE=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_have_decl_SIGPIPE" >&5 -echo "${ECHO_T}$ac_cv_have_decl_SIGPIPE" >&6 -if test $ac_cv_have_decl_SIGPIPE = yes; then - - -cat >>confdefs.h <<\_ACEOF -#define HAVE_SIGPIPE 1 -_ACEOF - -fi - ### checks for types ### ---------------- @@ -27730,6 +27560,20 @@ echo "$as_me: error: conditional \"HAVE_TLS\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi +if test -z "${HAVE_STUN_TRUE}" && test -z "${HAVE_STUN_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_STUN\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_STUN\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi +if test -z "${HAVE_NTH_TRUE}" && test -z "${HAVE_NTH_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"HAVE_NTH\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"HAVE_NTH\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${HAVE_NTLM_TRUE}" && test -z "${HAVE_NTLM_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"HAVE_NTLM\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -28373,6 +28217,7 @@ s,@HAVE_MINGW32_TRUE@,$HAVE_MINGW32_TRUE,;t t s,@HAVE_MINGW32_FALSE@,$HAVE_MINGW32_FALSE,;t t s,@CWFLAG@,$CWFLAG,;t t s,@SOFIA_CFLAGS@,$SOFIA_CFLAGS,;t t +s,@SOFIA_COVERAGE@,$SOFIA_COVERAGE,;t t s,@ENABLE_COVERAGE_TRUE@,$ENABLE_COVERAGE_TRUE,;t t s,@ENABLE_COVERAGE_FALSE@,$ENABLE_COVERAGE_FALSE,;t t s,@MOSTLYCLEANFILES@,$MOSTLYCLEANFILES,;t t @@ -28416,9 +28261,14 @@ s,@HAVE_GLIB_TRUE@,$HAVE_GLIB_TRUE,;t t s,@HAVE_GLIB_FALSE@,$HAVE_GLIB_FALSE,;t t s,@GLIB_VERSION@,$GLIB_VERSION,;t t s,@SOFIA_GLIB_PKG_REQUIRES@,$SOFIA_GLIB_PKG_REQUIRES,;t t +s,@ALLOCA@,$ALLOCA,;t t s,@REPLACE_LIBADD@,$REPLACE_LIBADD,;t t s,@HAVE_TLS_TRUE@,$HAVE_TLS_TRUE,;t t s,@HAVE_TLS_FALSE@,$HAVE_TLS_FALSE,;t t +s,@HAVE_STUN_TRUE@,$HAVE_STUN_TRUE,;t t +s,@HAVE_STUN_FALSE@,$HAVE_STUN_FALSE,;t t +s,@HAVE_NTH_TRUE@,$HAVE_NTH_TRUE,;t t +s,@HAVE_NTH_FALSE@,$HAVE_NTH_FALSE,;t t s,@HAVE_NTLM_TRUE@,$HAVE_NTLM_TRUE,;t t s,@HAVE_NTLM_FALSE@,$HAVE_NTLM_FALSE,;t t s,@LIBOBJS@,$LIBOBJS,;t t diff --git a/libs/sofia-sip/configure.ac b/libs/sofia-sip/configure.ac index 7e94cd4e64..fead869c00 100644 --- a/libs/sofia-sip/configure.ac +++ b/libs/sofia-sip/configure.ac @@ -83,6 +83,15 @@ elif test x${HAVE_OPENSSL} != x1 ; then else AC_DEFINE([HAVE_SOFIA_STUN], 1, [Define to 1 if we use STUN library]) fi +AM_CONDITIONAL([HAVE_STUN], [test "x$enable_stun" = xyes]) + +AC_ARG_ENABLE(nth, +[ --disable-nth disable nth and http modules (enabled)], + , enable_nth=yes) +AM_CONDITIONAL([HAVE_NTH], [test "x$enable_nth" = xyes]) +if test x$enable_nth = xyes ; then + AC_DEFINE([HAVE_SOFIA_NTH], 1, [Define to 1 if we use NTH library]) +fi dnl Disable NTLM support by default AC_ARG_ENABLE(ntlm, @@ -104,10 +113,6 @@ AC_HEADER_STDC ### checks for declarations ### ----------------------- -AC_CHECK_DECL([SIGPIPE], [ -AC_DEFINE([HAVE_SIGPIPE], 1, [Define to 1 if you have SIGPIPE])],,[ -#include -]) ### checks for types ### ---------------- diff --git a/libs/sofia-sip/docs/build_system.txt b/libs/sofia-sip/docs/build_system.txt index ea057852a3..ae9db27714 100644 --- a/libs/sofia-sip/docs/build_system.txt +++ b/libs/sofia-sip/docs/build_system.txt @@ -38,6 +38,11 @@ Makefile target notes separately in ``DIST_SOURCES`` variable (otherwise ``make dist`` will fail) +Makefile fragments +------------------ + +Some common makefile rules are in 'rules' subdirectory. + Maintainer mode --------------- @@ -54,13 +59,16 @@ option '--enable-maintainer-mode'. Running tests ============= -Sofia-SIP has quite complete suite of test cases. It is prudent to -run them while making changes and before committing them to revision -control system. However, running certain tests takes quite a long -time. Therefore, they are run only if the environment variable +Sofia-SIP has quite complete suite of test cases. It is prudent to run +them while making changes and before committing them to revision control +system. However, running certain tests takes quite a long time to +execture. Therefore, they are run only if the environment variable EXPENSIVE_CHECKS has been set. EXPENSIVE_CHECKS is also set by the build system if configure option '--enable-expensive-checks' has been used. +On hosts with i386 architecture, it is possible to run tests under +valgrind. Use the make target 'valcheck' for that purpose. + Code-tree layout ================ diff --git a/libs/sofia-sip/docs/devel_platform_notes.txt b/libs/sofia-sip/docs/devel_platform_notes.txt index 0b8b418025..9d7cc4f1af 100644 --- a/libs/sofia-sip/docs/devel_platform_notes.txt +++ b/libs/sofia-sip/docs/devel_platform_notes.txt @@ -11,14 +11,30 @@ up-to-date autotools. Autoconf should be at least 2.57 and automake should be at least 1.7. You can avoid running autoreconf explicitly if you use ./configure option --enable-maintainer-mode. +Notes to distributors +---------------------- + +Build options such as "--disable-stun" (HAVE_SOFIA_STUN) and +"--disable-nth" (HAVE_SOFIA_NTH) modify the public library API/ABI, +by omitting certain interfaces from the resulting library and installed +header files. + +Options such as '--disable-size-compat' modify the library +ABI by changing the types used in public library function +signatures. + Generic POSIX (GNU/Linux, BSD, ...) ----------------------------------- Sofia-SIP should compile out-of-the-box on generic POSIX machines. Use the standard GNU autotool 'configure+make' -procedure to build the software. See top-level INSTALL +procedure to build the software. See top-level README file for more information. +The configure script accepts various options. See "./configure --help" +for the full list. + + Mac OS X -------- diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am b/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am index 12defa1a27..25491ef500 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am @@ -31,16 +31,6 @@ EXTRA_DIST = docs/Doxyfile.aliases \ docs/Doxyfile.conf \ docs/Doxyfile.version -built-sources: built-sources-recursive -clean-built-sources: clean-built-sources-recursive - -built-sources-recursive clean-built-sources-recursive: - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $@ in $$subdir"; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ - done; - doxygen: built-sources @cd ${srcdir} ;\ mkdir -p docs docs/html &&\ @@ -53,4 +43,6 @@ doxygen: built-sources done cd ${srcdir}/docs/html && ../../${top_srcdir}/libsofia-sip-ua/docs/hide_emails.sh +include $(top_srcdir)/rules/recursive.am + .PHONY: built-sources built-sources-am doxygen diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.in b/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.in index 922946dfd7..273446e6cc 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.in @@ -22,6 +22,9 @@ # Licensed under LGPL. See file COPYING. # +# Recursive Makefile targets +# -------------------------- + SOURCES = $(libsofia_sip_ua_glib_la_SOURCES) srcdir = @srcdir@ @@ -48,8 +51,9 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ @HAVE_GLIB_TRUE@am__append_1 = libsofia-sip-ua-glib.la +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/recursive.am ChangeLog subdir = libsofia-sip-ua-glib -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 $(top_srcdir)/m4/sac-su.m4 \ @@ -100,6 +104,7 @@ DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -146,8 +151,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -191,6 +200,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -261,10 +271,19 @@ EXTRA_DIST = docs/Doxyfile.aliases \ docs/Doxyfile.conf \ docs/Doxyfile.version +@ENABLE_COVERAGE_TRUE@COVERAGE_RECURSIVE = coverage-recursive +SOFIA_RECURSIVE = \ + valcheck-recursive \ + $(COVERAGE_RECURSIVE) + +SOFIA_DIST_RECURSIVE = \ + built-sources-recursive \ + clean-built-sources-recursive + all: all-recursive .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/recursive.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -460,7 +479,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/docs + $(mkdir_p) $(distdir)/../rules $(distdir)/docs @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -602,16 +621,6 @@ uninstall-info: uninstall-info-recursive uninstall-info-am uninstall-libLTLIBRARIES -built-sources: built-sources-recursive -clean-built-sources: clean-built-sources-recursive - -built-sources-recursive clean-built-sources-recursive: - target=`echo $@ | sed s/-recursive//`; \ - list='$(SUBDIRS)'; for subdir in $$list; do \ - echo "Making $@ in $$subdir"; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ - done; - doxygen: built-sources @cd ${srcdir} ;\ mkdir -p docs docs/html &&\ @@ -623,6 +632,44 @@ doxygen: built-sources && popd > /dev/null ; \ done cd ${srcdir}/docs/html && ../../${top_srcdir}/libsofia-sip-ua/docs/hide_emails.sh +@ENABLE_COVERAGE_TRUE@coverage: $(COVERAGE_RECURSIVE) + +all-recursive: built-sources-recursive +built-sources: built-sources-recursive +clean-built-sources: clean-built-sources-recursive +valcheck: valcheck-recursive + +$(SOFIA_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ + || eval $$failcom; \ + done; \ + test -z "$$fail" + +$(SOFIA_DIST_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ + || eval $$failcom; \ + done; \ + test -z "$$fail" .PHONY: built-sources built-sources-am doxygen # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.am b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.am index c5f0ae94d6..85d6ad89e4 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.am @@ -58,4 +58,4 @@ AUTOMAKE_OPTIONS = foreign # ---------------------------------------------------------------------- # Sofia specific rules -include ../../libsofia-sip-ua/sofia.am +include $(top_srcdir)/rules/sofia.am diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in index f62aead346..3e3c6515e3 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/Makefile.in @@ -25,11 +25,36 @@ # ---------------------------------------------------------------------- # Headers -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. -SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c +SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c torture_su_glib_timer.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -54,14 +79,18 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -check_PROGRAMS = su_source_test$(EXEEXT) +check_PROGRAMS = su_source_test$(EXEEXT) \ + torture_su_glib_timer$(EXEEXT) @HAVE_GLIB_TRUE@am__append_1 = \ @HAVE_GLIB_TRUE@ sofia-sip/su_source.h \ @HAVE_GLIB_TRUE@ sofia-sip/su_glib.h DIST_COMMON = $(am__nobase_include_sofia_HEADERS_DIST) \ - $(srcdir)/../../libsofia-sip-ua/sofia.am $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_2 = -DNDEBUG subdir = libsofia-sip-ua-glib/su-glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -84,6 +113,11 @@ su_source_test_LDADD = $(LDADD) am__DEPENDENCIES_1 = su_source_test_DEPENDENCIES = libsu-glib.la \ ../../libsofia-sip-ua/libsofia-sip-ua.la $(am__DEPENDENCIES_1) +torture_su_glib_timer_SOURCES = torture_su_glib_timer.c +torture_su_glib_timer_OBJECTS = torture_su_glib_timer.$(OBJEXT) +torture_su_glib_timer_LDADD = $(LDADD) +torture_su_glib_timer_DEPENDENCIES = libsu-glib.la \ + ../../libsofia-sip-ua/libsofia-sip-ua.la $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -95,8 +129,10 @@ LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c -DIST_SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c +SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c \ + torture_su_glib_timer.c +DIST_SOURCES = $(libsu_glib_la_SOURCES) su_source_test.c \ + torture_su_glib_timer.c am__nobase_include_sofia_HEADERS_DIST = sofia-sip/su_source.h \ sofia-sip/su_glib.h am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -112,6 +148,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -158,8 +195,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -203,6 +244,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -267,7 +309,7 @@ noinst_LTLIBRARIES = libsu-glib.la # ---------------------------------------------------------------------- # Tests -TESTS = su_source_test +TESTS = su_source_test torture_su_glib_timer # ---------------------------------------------------------------------- # Rules for building the targets @@ -288,7 +330,7 @@ EXTRA_DIST = Doxyfile su_glib.docs # ---------------------------------------------------------------------- # Automake options AUTOMAKE_OPTIONS = foreign -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_2) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -314,11 +356,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../../libsofia-sip-ua/sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -368,6 +412,9 @@ clean-checkPROGRAMS: su_source_test$(EXEEXT): $(su_source_test_OBJECTS) $(su_source_test_DEPENDENCIES) @rm -f su_source_test$(EXEEXT) $(LINK) $(su_source_test_LDFLAGS) $(su_source_test_OBJECTS) $(su_source_test_LDADD) $(LIBS) +torture_su_glib_timer$(EXEEXT): $(torture_su_glib_timer_OBJECTS) $(torture_su_glib_timer_DEPENDENCIES) + @rm -f torture_su_glib_timer$(EXEEXT) + $(LINK) $(torture_su_glib_timer_LDFLAGS) $(torture_su_glib_timer_OBJECTS) $(torture_su_glib_timer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -377,6 +424,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_source.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_source_test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_su_glib_timer.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @@ -550,7 +598,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/../../libsofia-sip-ua $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -698,6 +746,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h index e202f343a5..f6f2448de2 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h +++ b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h @@ -43,6 +43,7 @@ SOFIA_BEGIN_DECLS SOFIAPUBFUN su_root_t *su_glib_root_create(su_root_magic_t *) __attribute__((__malloc__)); SOFIAPUBFUN GSource *su_glib_root_gsource(su_root_t *); +SOFIAPUBFUN void su_glib_prefer_gsource(void); SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c index 2e45a32254..a2b4380dd5 100644 --- a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c +++ b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c @@ -25,7 +25,11 @@ /** * @file su_source.c * @brief Wrapper for glib GSource. - * * + * + * Refs: + * - http://sofia-sip.sourceforge.net/refdocs/su/group__su__wait.html + * - http://developer.gnome.org/doc/API/glib/glib-the-main-event-loop.html + * * @author Pekka Pessi . * * @date Created: Thu Mar 4 15:15:15 2004 ppessi @@ -36,12 +40,6 @@ #include "config.h" #endif -#include -#include -#include -#include -#include - #include #define SU_PORT_IMPLEMENTATION 1 @@ -57,16 +55,26 @@ #include "su_port.h" #include "sofia-sip/su_alloc.h" -static su_port_t *su_source_create(void) __attribute__((__malloc__)); +#include +#include +#include +#include +#include + +#if 1 +#define PORT_LOCK_DEBUG(x) ((void)0) +#else +#define PORT_LOCK_DEBUG(x) printf x +#endif + +static su_port_t *su_source_port_create(void) __attribute__((__malloc__)); static gboolean su_source_prepare(GSource *gs, gint *return_tout); static gboolean su_source_check(GSource *gs); static gboolean su_source_dispatch(GSource *gs, - GSourceFunc callback, - gpointer user_data); + GSourceFunc callback, + gpointer user_data); static void su_source_finalize(GSource *source); -static int su_source_getmsgs(su_port_t *self); - static GSourceFuncs su_source_funcs[1] = {{ su_source_prepare, @@ -106,21 +114,22 @@ static void su_source_break(su_port_t *self); static su_duration_t su_source_step(su_port_t *self, su_duration_t tout); static int su_source_own_thread(su_port_t const *port); static int su_source_add_prepoll(su_port_t *port, - su_root_t *root, - su_prepoll_f *, - su_prepoll_magic_t *); + su_root_t *root, + su_prepoll_f *, + su_prepoll_magic_t *); static int su_source_remove_prepoll(su_port_t *port, su_root_t *root); -static su_timer_t **su_source_timers(su_port_t *port); static int su_source_multishot(su_port_t *self, int multishot); -static int su_source_threadsafe(su_port_t *port); -static -su_port_vtable_t const su_source_vtable[1] = +static char const *su_source_name(su_port_t const *self); + +static +su_port_vtable_t const su_source_port_vtable[1] = {{ - /* su_vtable_size: */ sizeof su_source_vtable, + /* su_vtable_size: */ sizeof su_source_port_vtable, su_source_lock, su_source_unlock, + su_source_incref, su_source_decref, @@ -138,32 +147,38 @@ su_port_vtable_t const su_source_vtable[1] = su_source_own_thread, su_source_add_prepoll, su_source_remove_prepoll, - su_source_timers, + su_base_port_timers, su_source_multishot, - su_source_threadsafe - + su_base_port_threadsafe, + /*su_source_yield*/ NULL, + /*su_source_wait_events*/ NULL, + su_base_port_getmsgs, + su_base_port_getmsgs_from, + su_source_name, + su_base_port_start_shared, + su_base_port_wait, + NULL, }}; +static char const *su_source_name(su_port_t const *self) +{ + return "GSource"; +} + /** * Port is a per-thread reactor. * * Multiple root objects executed by single thread share a su_port_t object. */ struct su_source_s { - su_home_t sup_home[1]; - su_port_vtable_t const *sup_vtable; + su_base_port_t sup_base[1]; GThread *sup_tid; GStaticMutex sup_mutex[1]; - GStaticRWLock sup_ref[1]; - GSource *sup_source; - GMainLoop *sup_main_loop; + GSource *sup_source; /**< Backpointer to source */ + GMainLoop *sup_main_loop; /**< Reference to mainloop while running */ - /* Message list - this is protected by lock */ - su_msg_t *sup_head; - su_msg_t **sup_tail; - /* Waits */ unsigned sup_registers; /** Counter incremented by su_port_register() or @@ -177,9 +192,6 @@ struct su_source_s { su_wakeup_f *sup_wait_cbs; su_wakeup_arg_t**sup_wait_args; su_root_t **sup_wait_roots; - - /* Timer list */ - su_timer_t *sup_timers; }; typedef struct _SuSource @@ -194,10 +206,6 @@ typedef struct _SuSource #define SU_SOURCE_INCREF(p, f) (g_source_ref(p->sup_source)) #define SU_SOURCE_DECREF(p, f) (g_source_unref(p->sup_source)) -#define SU_SOURCE_INITLOCK(p) (g_static_mutex_init((p)->sup_mutex)) -#define SU_SOURCE_LOCK(p, f) (g_static_mutex_lock((p)->sup_mutex)) -#define SU_SOURCE_UNLOCK(p, f) (g_static_mutex_unlock((p)->sup_mutex)) - #else /* Debugging versions */ @@ -205,15 +213,6 @@ typedef struct _SuSource #define SU_SOURCE_DECREF(p, f) do { printf("decref(%p) by %s\n", (p), f), \ g_source_unref(p->sup_source); } while(0) -#define SU_SOURCE_INITLOCK(p) \ - (g_static_mutex_init((p)->sup_mutex), printf("init_lock(%p)\n", p)) - -#define SU_SOURCE_LOCK(p, f) \ - (printf("%ld at %s locking(%p)...", g_thread_self(), f, p), g_static_mutex_lock((p)->sup_mutex), printf(" ...%ld at %s locked(%p)...", g_thread_self(), f, p)) - -#define SU_SOURCE_UNLOCK(p, f) \ - (g_static_mutex_unlock((p)->sup_mutex), printf(" ...%ld at %s unlocked(%p)\n", g_thread_self(), f, p)) - #endif #if HAVE_FUNC @@ -229,7 +228,7 @@ typedef struct _SuSource /** Create a root that uses GSource as reactor */ su_root_t *su_glib_root_create(su_root_magic_t *magic) { - return su_root_create_with_port(magic, su_source_create()); + return su_root_create_with_port(magic, su_source_port_create()); } /** Deprecated */ @@ -238,6 +237,15 @@ su_root_t *su_root_source_create(su_root_magic_t *magic) return su_glib_root_create(magic); } +/** + * Returns a GSource object for the root + * + * Note that you need to unref the GSource with g_source_unref() + * before destroying the root object. + * + * @return NULL on error (for instance if root was not created with + * su_glib_root_create()) + */ GSource *su_glib_root_gsource(su_root_t *root) { g_assert(root); @@ -246,41 +254,20 @@ GSource *su_glib_root_gsource(su_root_t *root) /*=============== Private function definitions ===============*/ -/**@internal - * - * Allocates and initializes a reactor and message port object. - * - * @return - * If successful a pointer to the new message port is returned, otherwise - * NULL is returned. - */ -su_port_t *su_source_create(void) +/** Initialize source port */ +int su_source_port_init(su_port_t *self, + GSource *gs, + su_port_vtable_t const *vtable) { - SuSource *ss; + if (su_base_port_init(self, vtable) < 0) + return -1; - SU_DEBUG_9(("su_source_create() called\n")); + self->sup_source = gs; + self->sup_tid = g_thread_self(); - ss = (SuSource *)g_source_new(su_source_funcs, (sizeof *ss)); - - if (ss) { - su_port_t *self = ss->ss_port; - - self->sup_vtable = su_source_vtable; - self->sup_source = ss->ss_source; - - SU_SOURCE_INITLOCK(self); - - self->sup_tail = &self->sup_head; - self->sup_tid = g_thread_self(); - - SU_DEBUG_9(("su_source_with_main_context() returns %p\n", self)); - - return self; - } else { - su_perror("su_source_with_main_context(): su_home_clone"); - SU_DEBUG_9(("su_source_with_main_context() fails\n")); - return NULL; - } + g_static_mutex_init(self->sup_mutex); + + return 0; } /** @internal Destroy a port. */ @@ -294,23 +281,70 @@ void su_source_finalize(GSource *gs) SU_DEBUG_9(("su_source_finalize() called\n")); - if (self->sup_waits) - free(self->sup_waits), self->sup_waits = NULL; - if (self->sup_wait_cbs) - free(self->sup_wait_cbs), self->sup_wait_cbs = NULL; - if (self->sup_wait_args) - free(self->sup_wait_args), self->sup_wait_args = NULL; - if (self->sup_wait_roots) - free(self->sup_wait_roots), self->sup_wait_roots = NULL; - if (self->sup_indices) - free(self->sup_indices), self->sup_indices = NULL; + g_static_mutex_free(self->sup_mutex); - su_home_deinit(self->sup_home); + su_base_port_deinit(self); + + su_home_deinit(self->sup_base->sup_home); } +void su_source_port_lock(su_port_t *self, char const *who) +{ + PORT_LOCK_DEBUG(("%p at %s locking(%p)...", + (void *)g_thread_self(), who, self)); + + g_static_mutex_lock(self->sup_mutex); + + PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...", + (void *)g_thread_self(), who, self)); +} + +void su_source_port_unlock(su_port_t *self, char const *who) +{ + g_static_mutex_unlock(self->sup_mutex); + + PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n", + (void *)g_thread_self(), who, self)); +} + +/** @internal Send a message to the port. */ +int su_source_send(su_port_t *self, su_msg_r rmsg) +{ + int wakeup = su_base_port_send(self, rmsg); + GMainContext *gmc; + + if (wakeup < 0) + return -1; + if (wakeup == 0) + return 0; + + gmc = g_source_get_context(self->sup_source); + + if (gmc) + g_main_context_wakeup(gmc); + + return 0; +} + +/** @internal + * Checks if the calling thread owns the port object. + * + * @param self pointer to a port object + * + * @retval true (nonzero) if the calling thread owns the port, + * @retval false (zero) otherwise. + */ +int su_source_own_thread(su_port_t const *self) +{ + return self == NULL || SU_SOURCE_OWN_THREAD(self); +} + +/* -- Registering and unregistering ------------------------------------- */ + /* Seconds from 1.1.1900 to 1.1.1970 */ #define NTP_EPOCH 2208988800UL +/** Prepare to wait - calculate time to next timer */ static gboolean su_source_prepare(GSource *gs, gint *return_tout) { @@ -319,12 +353,12 @@ gboolean su_source_prepare(GSource *gs, gint *return_tout) enter; - if (self->sup_head) { + if (self->sup_base->sup_head) { *return_tout = 0; return TRUE; } - if (self->sup_timers) { + if (self->sup_base->sup_timers) { su_time_t now; GTimeVal gtimeval; su_duration_t tout; @@ -333,7 +367,7 @@ gboolean su_source_prepare(GSource *gs, gint *return_tout) now.tv_sec = gtimeval.tv_sec + 2208988800UL; now.tv_usec = gtimeval.tv_usec; - tout = su_timer_next_expires(self->sup_timers, now); + tout = su_timer_next_expires(self->sup_base->sup_timers, now); *return_tout = (tout < 0 || tout > (su_duration_t)G_MAXINT)? -1 : (gint)tout; @@ -376,10 +410,10 @@ gboolean su_source_dispatch(GSource *gs, enter; - if (self->sup_head) - su_source_getmsgs(self); + if (self->sup_base->sup_head) + su_base_port_getmsgs(self); - if (self->sup_timers) { + if (self->sup_base->sup_timers) { su_time_t now; GTimeVal gtimeval; su_duration_t tout; @@ -392,7 +426,7 @@ gboolean su_source_dispatch(GSource *gs, now.tv_sec = gtimeval.tv_sec + 2208988800UL; now.tv_usec = gtimeval.tv_usec; - timers = su_timer_expire(&self->sup_timers, &tout, now); + timers = su_timer_expire(&self->sup_base->sup_timers, &tout, now); } #if SU_HAVE_POLL @@ -424,12 +458,20 @@ gboolean su_source_dispatch(GSource *gs, static void su_source_lock(su_port_t *self, char const *who) { - SU_SOURCE_LOCK(self, who); + PORT_LOCK_DEBUG(("%p at %s locking(%p)...", + (void *)g_thread_self(), who, self)); + g_static_mutex_lock(self->sup_mutex); + + PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...", + (void *)g_thread_self(), who, self)); } static void su_source_unlock(su_port_t *self, char const *who) { - SU_SOURCE_UNLOCK(self, who); + g_static_mutex_unlock(self->sup_mutex); + + PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n", + (void *)g_thread_self(), who, self)); } static void su_source_incref(su_port_t *self, char const *who) @@ -448,81 +490,6 @@ GSource *su_source_gsource(su_port_t *self) return self->sup_source; } -/** @internal Send a message to the port. */ -int su_source_send(su_port_t *self, su_msg_r rmsg) -{ - enter; - - if (self) { - su_msg_t *msg; - GMainContext *gmc; - - SU_SOURCE_LOCK(self, "su_source_send"); - - msg = rmsg[0]; rmsg[0] = NULL; - *self->sup_tail = msg; - self->sup_tail = &msg->sum_next; - - SU_SOURCE_UNLOCK(self, "su_source_send"); - - gmc = g_source_get_context(self->sup_source); - - if (gmc) - g_main_context_wakeup(gmc); - - return 0; - } - else { - su_msg_destroy(rmsg); - return -1; - } -} - -/** @internal - * Execute the messages in the incoming queue until the queue is empty.. - * - * @param self - pointer to a port object - * - * @retval 0 if there was a signal to handle, - * @retval -1 otherwise. - */ -static -int su_source_getmsgs(su_port_t *self) -{ - enter; - - if (self && self->sup_head) { - su_root_t *root; - su_msg_f f; - - SU_SOURCE_INCREF(self, "su_source_getmsgs"); - SU_SOURCE_LOCK(self, "su_source_getmsgs"); - - while (self->sup_head) { - su_msg_t *msg = self->sup_head; - self->sup_head = msg->sum_next; - if (!self->sup_head) { - assert(self->sup_tail == &msg->sum_next); - self->sup_tail = &self->sup_head; - } - root = msg->sum_to->sut_root; - f = msg->sum_func; - SU_SOURCE_UNLOCK(self, "su_source_getmsgs"); - if (f) - f(su_root_magic(root), &msg, msg->sum_data); - su_msg_delivery_report(&msg); - SU_SOURCE_LOCK(self, "su_source_getmsgs"); - } - - SU_SOURCE_UNLOCK(self, "su_source_getmsgs"); - SU_SOURCE_DECREF(self, "su_source_getmsgs"); - - return 0; - } - else - return -1; -} - /** @internal * * Register a @c su_wait_t object. The wait object, a callback function and @@ -914,13 +881,6 @@ int su_source_multishot(su_port_t *self, int multishot) return (errno = EINVAL), -1; } -/** @internal Enable threadsafe operation. */ -static -int su_source_threadsafe(su_port_t *port) -{ - return su_home_threadsafe(port->sup_home); -} - /** @internal Main loop. * @@ -1019,18 +979,19 @@ su_duration_t su_source_step(su_port_t *self, su_duration_t tout) return 0; } - -/** @internal - * Checks if the calling thread owns the port object. - * - * @param self pointer to a port object - * - * @retval true (nonzero) if the calling thread owns the port, - * @retval false (zero) otherwise. - */ -int su_source_own_thread(su_port_t const *self) +static int su_source_add_prepoll(su_port_t *port, + su_root_t *root, + su_prepoll_f *prepoll, + su_prepoll_magic_t *magic) { - return self == NULL || SU_SOURCE_OWN_THREAD(self); + /* We could call prepoll in su_source_prepare()?? */ + return -1; +} + +static int su_source_remove_prepoll(su_port_t *port, + su_root_t *root) +{ + return -1; } #if 0 @@ -1061,52 +1022,44 @@ void su_source_dump(su_port_t const *self, FILE *f) #endif -/* ========================================================================= - * Pre-poll() callback +/**@internal + * + * Allocates and initializes a reactor and message port object. + * + * @return + * If successful a pointer to the new message port is returned, otherwise + * NULL is returned. */ - -int su_source_add_prepoll(su_port_t *port, - su_root_t *root, - su_prepoll_f *callback, - su_prepoll_magic_t *magic) +static su_port_t *su_source_port_create(void) { -#if 0 - if (port->sup_prepoll) - return -1; + SuSource *ss; + su_port_t *self = NULL; - port->sup_prepoll = callback; - port->sup_pp_magic = magic; - port->sup_pp_root = root; + SU_DEBUG_9(("su_source_port_create() called\n")); - return 0; -#else - return -1; -#endif + ss = (SuSource *)g_source_new(su_source_funcs, (sizeof *ss)); + + if (ss) { + self = ss->ss_port; + if (su_source_port_init(self, ss->ss_source, su_source_port_vtable) < 0) + g_source_unref(ss->ss_source), self = NULL; + } else { + su_perror("su_source_port_create(): g_source_new"); + } + + SU_DEBUG_1(("su_source_port_create() returns %p\n", (void *)self)); + + return self; } -int su_source_remove_prepoll(su_port_t *port, - su_root_t *root) -{ -#if 0 - if (port->sup_pp_root != root) - return -1; +/* No su_source_port_start */ - port->sup_prepoll = NULL; - port->sup_pp_magic = NULL; - port->sup_pp_root = NULL; - - return 0; -#else - return -1; -#endif -} - -/* ========================================================================= - * Timers +/** Use su_source implementation when su_root_create() is called. + * + * @NEW_1_12_5 */ - -static -su_timer_t **su_source_timers(su_port_t *self) +void su_glib_prefer_gsource(void) { - return &self->sup_timers; + su_port_prefer(su_source_port_create, NULL); } + diff --git a/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/torture_su_glib_timer.c b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/torture_su_glib_timer.c new file mode 100644 index 0000000000..13fb84c20c --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua-glib/su-glib/torture_su_glib_timer.c @@ -0,0 +1,269 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005,2006 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * @brief Test program for su-glib timers + * + * Based on torture_su_timer.c of libsofia-sip-ua. + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @internal + * + * @date Created: Fri Oct 19 08:53:55 2001 pessi + */ + +#include "config.h" + +#include +#include +#include +#include + +#include + +struct tester; + +#define SU_ROOT_MAGIC_T struct tester +#define SU_INTERNAL_P su_root_t * +#define SU_TIMER_ARG_T struct timing + +#include "sofia-sip/su.h" +#include "sofia-sip/su_wait.h" +#include "sofia-sip/su_log.h" + +#include + +struct timing +{ + int t_run; + int t_times; + su_time_t t_prev; +}; + +struct tester +{ + su_root_t *root; + su_timer_t *t, *t1; + unsigned times; + void *sentinel; +}; + +void +print_stamp(struct tester *x, su_timer_t *t, struct timing *ti) +{ + su_time_t now = su_now(), prev = ti->t_prev; + + ti->t_prev = now; + + printf("timer interval %f\n", 1000 * su_time_diff(now, prev)); + + if (!ti->t_run) + su_timer_set(t, print_stamp, ti); + + if (++ti->t_times >= 10) + su_timer_reset(t); +} + +void +print_X(struct tester *x, su_timer_t *t1, struct timing *ti) +{ + su_timer_set(t1, print_X, ti); + putchar('X'); fflush(stdout); +} + +su_msg_r intr_msg = SU_MSG_R_INIT; + +static RETSIGTYPE intr_handler(int signum) +{ + su_msg_send(intr_msg); +} + +static void test_break(struct tester *tester, su_msg_r msg, su_msg_arg_t *arg) +{ + su_root_break(tester->root); +} + +void +end_test(struct tester *tester, su_timer_t *t, struct timing *ti) +{ + printf("ending test\n"); + su_timer_destroy(t); + su_timer_reset(tester->t); + su_timer_reset(tester->t1); + su_root_break(tester->root); +} + +void +increment(struct tester *tester, su_timer_t *t, struct timing *ti) +{ + tester->times++; + + if ((void *)ti == (void*)tester->sentinel) + su_root_break(tester->root); +} + +void +usage(char const *name) +{ + fprintf(stderr, "usage: %s [-1r] [-Nnum] [interval]\n", name); + exit(1); +} + +/* + * test su_timer functionality: + * + * Create a timer, executing print_stamp() in every 20 ms + */ +int main(int argc, char *argv[]) +{ + su_root_t *root; + su_timer_t *t, *t1, *t_end; + su_timer_t **timers; + su_duration_t interval = 60; + char *argv0 = argv[0]; + char *s; + int use_t1 = 0; + su_time_t now, started; + intptr_t i, N = 500; + GSource *source; + + struct timing timing[1] = {{ 0 }}; + struct tester tester[1] = {{ 0 }}; + + while (argv[1] && argv[1][0] == '-') { + char *o = argv[1] + 1; + while (*o) { + if (*o == '1') + o++, use_t1 = 1; + else if (*o == 'r') + o++, timing->t_run = 1; + else if (*o == 'N') { + if (o[1]) + N = strtoul(o + 1, &o, 0); + else if (argv[2]) + N = strtoul(argv++[2], &o, 0); + break; + } + else + break; + + } + if (*o) + usage(argv0); + argv++; + } + + if (argv[1]) { + interval = strtoul(argv[1], &s, 10); + + if (interval == 0 || s == argv[1]) + usage(argv0); + } + + su_init(); atexit(su_deinit); + + tester->root = root = su_glib_root_create(tester); + + source = su_root_gsource(tester->root); + g_source_attach(source, NULL /*g_main_context_default ()*/); + + su_msg_create(intr_msg, + su_root_task(root), + su_root_task(root), + test_break, 0); + + signal(SIGINT, intr_handler); +#if HAVE_SIGPIPE + signal(SIGPIPE, intr_handler); + signal(SIGQUIT, intr_handler); + signal(SIGHUP, intr_handler); +#endif + + t = su_timer_create(su_root_task(root), interval); + t1 = su_timer_create(su_root_task(root), 1); + t_end = su_timer_create(su_root_task(root), 20 * interval); + + if (t == NULL || t1 == NULL || t_end == NULL) + su_perror("su_timer_create"), exit(1); + + tester->t = t, tester->t1 = t1; + + timing->t_prev = su_now(); + + if (timing->t_run) + su_timer_run(t, print_stamp, timing); + else + su_timer_set(t, print_stamp, timing); + + if (use_t1) + su_timer_set(t1, print_X, NULL); + + su_timer_set(t_end, end_test, NULL); + + su_root_run(root); + + su_msg_destroy(intr_msg); + + su_timer_destroy(t); + su_timer_destroy(t1); + + if (timing->t_times != 10) { + fprintf(stderr, "%s: t expired %d times (expecting 10)\n", + argv0, timing->t_times); + return 1; + } + + /* Insert timers in order */ + timers = calloc(N, sizeof *timers); + if (!timers) { perror("calloc"); exit(1); } + + now = started = su_now(); + + for (i = 0; i < N; i++) { + t = su_timer_create(su_root_task(root), 1000); + if (!t) { perror("su_timer_create"); exit(1); } + if (++now.tv_usec == 0) ++now.tv_sec; + su_timer_set_at(t, increment, (void *)i, now); + timers[i] = t; + } + + tester->sentinel = (void*)(i - 1); + + su_root_run(root); + + printf("Processing %u timers took %f millisec (%f expected)\n", + (unsigned)i, su_time_diff(su_now(), started) * 1000, (double)i / 1000); + + for (i = 0; i < N; i++) { + su_timer_destroy(timers[i]); + } + + su_root_destroy(root); + + su_deinit(); + + return 0; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/Makefile.am index 2001bd2eb0..4c46c8833c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/Makefile.am @@ -9,12 +9,25 @@ AUTOMAKE_OPTIONS = foreign +# select whicn optional sofia-sip modules have been enabled +# in the build +OPT_LIBADD = +OPT_SUBDIRS_STUN = +OPT_SUBDIRS_NTH = +if HAVE_STUN +OPT_LIBADD += stun/libstun.la +OPT_SUBDIRS_STUN += stun +endif +if HAVE_NTH +OPT_LIBADD += nth/libnth.la http/libhttp.la +OPT_SUBDIRS_NTH += nth http +endif + # note: order does matter in the subdir list -SUBDIRS = su features bnf sresolv sdp url msg sip stun ipt soa \ - tport http nta nea iptsec nth nua +SUBDIRS = su features bnf sresolv sdp url msg sip $(OPT_SUBDIRS_STUN) ipt soa \ + tport nta nea iptsec $(OPT_SUBDIRS_NTH) nua DIST_SUBDIRS = $(SUBDIRS) docs -EXTRA_DIST = sofia.am DOXYGEN = doxygen lib_LTLIBRARIES = libsofia-sip-ua.la @@ -27,37 +40,22 @@ libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ msg/libmsg.la \ nea/libnea.la \ nta/libnta.la \ - nth/libnth.la \ nua/libnua.la \ - http/libhttp.la \ sdp/libsdp.la \ sip/libsip.la \ soa/libsoa.la \ sresolv/libsresolv.la \ su/libsu.la \ - stun/libstun.la \ tport/libtport.la \ - url/liburl.la + url/liburl.la \ + $(OPT_LIBADD) + # set the libtool version info version:revision:age for libsofia-sip-ua # - soname to 'libsofia-sip-ua.so.(CUR-AGE)' libsofia_sip_ua_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) -if ENABLE_COVERAGE -COVERAGE_RECURSIVE = coverage-recursive -coverage: $(COVERAGE_RECURSIVE) -endif - -all-recursive: built-sources-recursive -built-sources: built-sources-recursive -clean-built-sources: clean-built-sources-recursive - -built-sources-recursive clean-built-sources-recursive $(COVERAGE_RECURSIVE): - target=`echo $@ | sed s/-recursive//`; \ - list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - echo "Making $@ in $$subdir"; \ - (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ - done; +include $(top_srcdir)/rules/recursive.am doxygen: built-sources @echo Generating empty doxytags diff --git a/libs/sofia-sip/libsofia-sip-ua/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/Makefile.in index d12ac8df6d..a44a8a8a72 100644 --- a/libs/sofia-sip/libsofia-sip-ua/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/Makefile.in @@ -23,6 +23,9 @@ # # ref: http://www.gnu.org/software/automake/manual/automake.html +# Recursive Makefile targets +# -------------------------- + SOURCES = $(libsofia_sip_ua_la_SOURCES) srcdir = @srcdir@ @@ -48,8 +51,13 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ +@HAVE_STUN_TRUE@am__append_1 = stun/libstun.la +@HAVE_STUN_TRUE@am__append_2 = stun +@HAVE_NTH_TRUE@am__append_3 = nth/libnth.la http/libhttp.la +@HAVE_NTH_TRUE@am__append_4 = nth http +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/recursive.am ChangeLog subdir = libsofia-sip-ua -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ $(top_srcdir)/m4/sac-openssl.m4 $(top_srcdir)/m4/sac-su.m4 \ @@ -70,12 +78,15 @@ am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) +@HAVE_STUN_TRUE@am__DEPENDENCIES_1 = stun/libstun.la +@HAVE_NTH_TRUE@am__DEPENDENCIES_2 = nth/libnth.la http/libhttp.la +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) libsofia_sip_ua_la_DEPENDENCIES = bnf/libbnf.la \ features/libfeatures.la ipt/libipt.la iptsec/libiptsec.la \ - msg/libmsg.la nea/libnea.la nta/libnta.la nth/libnth.la \ - nua/libnua.la http/libhttp.la sdp/libsdp.la sip/libsip.la \ - soa/libsoa.la sresolv/libsresolv.la su/libsu.la \ - stun/libstun.la tport/libtport.la url/liburl.la + msg/libmsg.la nea/libnea.la nta/libnta.la nua/libnua.la \ + sdp/libsdp.la sip/libsip.la soa/libsoa.la \ + sresolv/libsresolv.la su/libsu.la tport/libtport.la \ + url/liburl.la $(am__DEPENDENCIES_3) am_libsofia_sip_ua_la_OBJECTS = libsofia_sip_ua_la_OBJECTS = $(am_libsofia_sip_ua_la_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip @@ -99,6 +110,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -145,8 +157,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -190,6 +206,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -246,12 +263,17 @@ target_os = @target_os@ target_vendor = @target_vendor@ AUTOMAKE_OPTIONS = foreign +# select whicn optional sofia-sip modules have been enabled +# in the build +OPT_LIBADD = $(am__append_1) $(am__append_3) +OPT_SUBDIRS_STUN = $(am__append_2) +OPT_SUBDIRS_NTH = $(am__append_4) + # note: order does matter in the subdir list -SUBDIRS = su features bnf sresolv sdp url msg sip stun ipt soa \ - tport http nta nea iptsec nth nua +SUBDIRS = su features bnf sresolv sdp url msg sip $(OPT_SUBDIRS_STUN) ipt soa \ + tport nta nea iptsec $(OPT_SUBDIRS_NTH) nua DIST_SUBDIRS = $(SUBDIRS) docs -EXTRA_DIST = sofia.am lib_LTLIBRARIES = libsofia-sip-ua.la libsofia_sip_ua_la_SOURCES = libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ @@ -261,17 +283,16 @@ libsofia_sip_ua_la_LIBADD = bnf/libbnf.la \ msg/libmsg.la \ nea/libnea.la \ nta/libnta.la \ - nth/libnth.la \ nua/libnua.la \ - http/libhttp.la \ sdp/libsdp.la \ sip/libsip.la \ soa/libsoa.la \ sresolv/libsresolv.la \ su/libsu.la \ - stun/libstun.la \ tport/libtport.la \ - url/liburl.la + url/liburl.la \ + $(OPT_LIBADD) + # set the libtool version info version:revision:age for libsofia-sip-ua # - soname to 'libsofia-sip-ua.so.(CUR-AGE)' @@ -279,10 +300,18 @@ libsofia_sip_ua_la_LDFLAGS = \ -version-info $(LIBVER_SOFIA_SIP_UA_CUR):$(LIBVER_SOFIA_SIP_UA_REV):$(LIBVER_SOFIA_SIP_UA_AGE) @ENABLE_COVERAGE_TRUE@COVERAGE_RECURSIVE = coverage-recursive +SOFIA_RECURSIVE = \ + valcheck-recursive \ + $(COVERAGE_RECURSIVE) + +SOFIA_DIST_RECURSIVE = \ + built-sources-recursive \ + clean-built-sources-recursive + all: all-recursive .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/recursive.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -478,6 +507,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) + $(mkdir_p) $(distdir)/../rules @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -623,13 +653,39 @@ uninstall-info: uninstall-info-recursive all-recursive: built-sources-recursive built-sources: built-sources-recursive clean-built-sources: clean-built-sources-recursive +valcheck: valcheck-recursive -built-sources-recursive clean-built-sources-recursive $(COVERAGE_RECURSIVE): +$(SOFIA_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ + || eval $$failcom; \ + done; \ + test -z "$$fail" + +$(SOFIA_DIST_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ target=`echo $@ | sed s/-recursive//`; \ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ - echo "Making $@ in $$subdir"; \ + echo "Making $$target in $$subdir"; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ - done; + || eval $$failcom; \ + done; \ + test -z "$$fail" doxygen: built-sources @echo Generating empty doxytags @@ -662,7 +718,7 @@ doxygen: built-sources for d in $(DIST_SUBDIRS); do \ test -r $$d/Doxyfile \ && pushd $$d > /dev/null \ - && echo running ${DOXYGEN} in second time in $$d \ + && echo running ${DOXYGEN} second time in $$d \ && ${DOXYGEN} 2>&1 \ | egrep -v -i -e 'Warning: Unsupported (xml/)?html tag' \ ; popd > /dev/null ; \ diff --git a/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.am index 3957b1be0d..5fc5406f87 100644 --- a/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.am @@ -43,4 +43,5 @@ TESTS = torture_bnf # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.in index ae9dbef766..1739e07389 100644 --- a/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/bnf/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libbnf_la_SOURCES) torture_bnf.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = torture_bnf$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/bnf ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -102,6 +131,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -148,8 +178,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -193,6 +227,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -268,7 +303,7 @@ EXTRA_DIST = Doxyfile bnf.docs # ---------------------------------------------------------------------- # Tests TESTS = torture_bnf -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -294,11 +329,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -530,7 +567,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -678,6 +715,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/bnf/bnf.c b/libs/sofia-sip/libsofia-sip-ua/bnf/bnf.c index a82b63aa57..361b0af01d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/bnf/bnf.c +++ b/libs/sofia-sip/libsofia-sip-ua/bnf/bnf.c @@ -825,9 +825,9 @@ static size_t convert_ip_address(char const *s, { size_t len; int canonize = 0; + char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; #if SU_HAVE_IN6 - char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; len = span_ip6_reference(s); if (len) { diff --git a/libs/sofia-sip/libsofia-sip-ua/docs/Doxyfile.aliases b/libs/sofia-sip/libsofia-sip-ua/docs/Doxyfile.aliases index bfd981efdb..db0ddeb5b3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/docs/Doxyfile.aliases +++ b/libs/sofia-sip/libsofia-sip-ua/docs/Doxyfile.aliases @@ -45,4 +45,5 @@ ALIASES = \ "VERSION_1_12_4=1.12.4" \ "VERSION_1_12_5=1.12.5" \ "NEW_1_12_5=@since New in 1.12.5" \ + "EXP_1_12_5=@since Experimental in 1.12.5, available if --enable-experimental configuration option is given" \ diff --git a/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.am index ef489f31a3..112632432d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.am @@ -47,4 +47,4 @@ CLEANFILES = Doxyfile.rfc # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am \ No newline at end of file +include $(top_srcdir)/rules/sofia.am diff --git a/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.in index f07b8a0508..4488d543c8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/docs/Makefile.in @@ -14,8 +14,33 @@ @SET_MAKE@ -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ @@ -39,9 +64,13 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -DIST_COMMON = $(srcdir)/../sofia.am $(srcdir)/Doxyfile.version.in \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/sofia-footer.html.in ChangeLog +DIST_COMMON = $(srcdir)/Doxyfile.version.in $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/sofia-footer.html.in \ + $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am \ + ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/docs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -59,6 +88,7 @@ DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -105,8 +135,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -150,6 +184,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -235,7 +270,7 @@ EXTRA_DIST = Doxyfile Doxyfile.aliases Doxyfile.conf \ BUILT_SOURCES = Doxyfile.rfc CLEANFILES = Doxyfile.rfc -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -261,11 +296,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -316,7 +353,7 @@ CTAGS: distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/pictures + $(mkdir_p) $(distdir)/../../rules $(distdir)/pictures @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -467,6 +504,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/features/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/features/Makefile.am index 527ec0c6b9..8f96fb05c6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/features/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/features/Makefile.am @@ -31,4 +31,5 @@ EXTRA_DIST = Doxyfile features.docs # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/features/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/features/Makefile.in index d1a2134327..316be7663e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/features/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/features/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libfeatures_la_SOURCES) @@ -53,8 +78,12 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/features ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -97,6 +126,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -143,8 +173,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -188,6 +222,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -258,7 +293,7 @@ libfeatures_la_SOURCES = features.c # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile features.docs -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -284,11 +319,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -436,7 +473,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -581,6 +618,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/http/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/http/Makefile.am index 4914e18933..12e81b1cbe 100644 --- a/libs/sofia-sip/libsofia-sip-ua/http/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/http/Makefile.am @@ -64,7 +64,7 @@ EXTRA_DIST = Doxyfile http.docs \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = DLLREF=1 diff --git a/libs/sofia-sip/libsofia-sip-ua/http/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/http/Makefile.in index b6b663c62e..3ddf0adeb0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/http/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/http/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libhttp_la_SOURCES) test_http.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_http$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/http ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -106,6 +135,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -152,8 +182,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -197,6 +231,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -295,7 +330,7 @@ EXTRA_DIST = Doxyfile http.docs \ http_parser_table.c.in \ http_tag.c.in -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -321,6 +356,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -332,7 +369,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -572,7 +609,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -723,6 +760,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + sofia-sip/http_tag.h: sofia-sip/http_tag.h.in $(MSG_PARSER_AWK) sofia-sip/http_protos.h: sofia-sip/http_protos.h.in $(MSG_PARSER_AWK) http_tag.c: http_tag.c.in $(MSG_PARSER_AWK) diff --git a/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.am index 107546af7a..90c7cc242b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.am @@ -51,4 +51,5 @@ EXTRA_DIST += Doxyfile ipt.docs # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.in index 715afef1ae..7aa6bcc3a2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libipt_la_SOURCES) torture_base64.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = torture_base64$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/ipt ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -103,6 +132,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -149,8 +179,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -194,6 +228,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -275,7 +310,7 @@ LDADD = libipt.la \ ../su/libsu.la torture_base64_LDFLAGS = -static -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -301,11 +336,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -539,7 +576,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -687,6 +724,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/ipt/sofia-sip/base64.h b/libs/sofia-sip/libsofia-sip-ua/ipt/sofia-sip/base64.h index dff6dc4be1..9f4b1e7487 100644 --- a/libs/sofia-sip/libsofia-sip-ua/ipt/sofia-sip/base64.h +++ b/libs/sofia-sip/libsofia-sip-ua/ipt/sofia-sip/base64.h @@ -57,6 +57,9 @@ SOFIAPUBFUN isize_t base64_e(char buf[], isize_t bsiz, void *data, isize_t dsiz) /** Calculate size of n bytes encoded in base64 */ #define BASE64_SIZE(n) ((((n) + 2) / 3) * 4) +/** Calculate size of n bytes encoded in base64 sans trailing =. @NEW_1_12_5 */ +#define BASE64_MINSIZE(n) ((n * 4 + 2) / 3) + SOFIA_END_DECLS #endif /* !BASE_64 */ diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.am index 4c84e805a4..7a9c9316e9 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.am @@ -31,6 +31,12 @@ TESTS = test_auth_digest BUILT_SOURCES = auth_tag_ref.c +HTTP_SRC = auth_module_http.c +if HAVE_NTH +USE_HTTP_SRC = $(HTTP_SRC) +OPT_LDDD = ../http/libhttp.la +endif + nobase_include_sofia_HEADERS = \ sofia-sip/auth_common.h \ sofia-sip/auth_client.h sofia-sip/auth_digest.h \ @@ -42,8 +48,9 @@ libiptsec_la_SOURCES = iptsec_debug.h \ auth_client.c auth_common.c auth_digest.c \ auth_module.c auth_tag.c auth_tag_ref.c \ auth_plugin.c auth_plugin_delayed.c \ - auth_module_http.c auth_module_sip.c \ + auth_module_sip.c \ $(NTLM_SOURCE) \ + $(USE_HTTP_SOURCE) \ iptsec_debug.c NTLM_HEADER = sofia-sip/auth_ntlm.h @@ -57,7 +64,7 @@ EXTRA_libiptsec_la_SOURCES = \ COVERAGE_INPUT = $(libiptsec_la_SOURCES) $(include_sofia_HEADERS) LDADD = libiptsec.la \ - ../http/libhttp.la \ + $(OPT_LDADD) \ ../nta/libnta.la \ ../sip/libsip.la \ ../msg/libmsg.la \ @@ -72,9 +79,10 @@ test_auth_digest_LDFLAGS = -static # Install and distribution rules EXTRA_DIST = Doxyfile iptsec.docs testpasswd \ - auth_module_sip.c auth_module_http.c $(BUILT_SOURCES) + auth_module_sip.c $(HTTP_SRC) $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.in index ca48822195..1c49b5b7dd 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libiptsec_la_SOURCES) $(EXTRA_libiptsec_la_SOURCES) test_auth_digest.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_auth_digest$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/iptsec ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -73,22 +102,21 @@ libiptsec_la_LIBADD = am__libiptsec_la_SOURCES_DIST = iptsec_debug.h auth_client.c \ auth_common.c auth_digest.c auth_module.c auth_tag.c \ auth_tag_ref.c auth_plugin.c auth_plugin_delayed.c \ - auth_module_http.c auth_module_sip.c auth_ntlm.c \ - auth_client_ntlm.c auth_plugin_ntlm.c iptsec_debug.c + auth_module_sip.c auth_ntlm.c auth_client_ntlm.c \ + auth_plugin_ntlm.c iptsec_debug.c @HAVE_NTLM_TRUE@am__objects_1 = auth_ntlm.lo auth_client_ntlm.lo \ @HAVE_NTLM_TRUE@ auth_plugin_ntlm.lo am_libiptsec_la_OBJECTS = auth_client.lo auth_common.lo auth_digest.lo \ auth_module.lo auth_tag.lo auth_tag_ref.lo auth_plugin.lo \ - auth_plugin_delayed.lo auth_module_http.lo auth_module_sip.lo \ - $(am__objects_1) iptsec_debug.lo + auth_plugin_delayed.lo auth_module_sip.lo $(am__objects_1) \ + iptsec_debug.lo libiptsec_la_OBJECTS = $(am_libiptsec_la_OBJECTS) test_auth_digest_SOURCES = test_auth_digest.c test_auth_digest_OBJECTS = test_auth_digest.$(OBJEXT) test_auth_digest_LDADD = $(LDADD) -test_auth_digest_DEPENDENCIES = libiptsec.la ../http/libhttp.la \ - ../nta/libnta.la ../sip/libsip.la ../msg/libmsg.la \ - ../url/liburl.la ../bnf/libbnf.la ../ipt/libipt.la \ - ../su/libsu.la +test_auth_digest_DEPENDENCIES = libiptsec.la ../nta/libnta.la \ + ../sip/libsip.la ../msg/libmsg.la ../url/liburl.la \ + ../bnf/libbnf.la ../ipt/libipt.la ../su/libsu.la DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) -I$(top_builddir)/libsofia-sip-ua/su/sofia-sip depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -117,6 +145,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -163,8 +192,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -208,6 +241,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -280,6 +314,9 @@ TESTS = test_auth_digest # ---------------------------------------------------------------------- # Rules for building the targets BUILT_SOURCES = auth_tag_ref.c +HTTP_SRC = auth_module_http.c +@HAVE_NTH_TRUE@USE_HTTP_SRC = $(HTTP_SRC) +@HAVE_NTH_TRUE@OPT_LDDD = ../http/libhttp.la nobase_include_sofia_HEADERS = \ sofia-sip/auth_common.h \ sofia-sip/auth_client.h sofia-sip/auth_digest.h \ @@ -291,8 +328,9 @@ libiptsec_la_SOURCES = iptsec_debug.h \ auth_client.c auth_common.c auth_digest.c \ auth_module.c auth_tag.c auth_tag_ref.c \ auth_plugin.c auth_plugin_delayed.c \ - auth_module_http.c auth_module_sip.c \ + auth_module_sip.c \ $(NTLM_SOURCE) \ + $(USE_HTTP_SOURCE) \ iptsec_debug.c NTLM_HEADER = sofia-sip/auth_ntlm.h @@ -302,7 +340,7 @@ EXTRA_libiptsec_la_SOURCES = \ COVERAGE_INPUT = $(libiptsec_la_SOURCES) $(include_sofia_HEADERS) LDADD = libiptsec.la \ - ../http/libhttp.la \ + $(OPT_LDADD) \ ../nta/libnta.la \ ../sip/libsip.la \ ../msg/libmsg.la \ @@ -316,9 +354,9 @@ test_auth_digest_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile iptsec.docs testpasswd \ - auth_module_sip.c auth_module_http.c $(BUILT_SOURCES) + auth_module_sip.c $(HTTP_SRC) $(BUILT_SOURCES) -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -344,12 +382,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -411,7 +451,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_digest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module_http.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_module_sip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_ntlm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_plugin.Plo@am__quote@ @@ -594,7 +633,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -745,6 +784,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c index 5c7dd4b1c2..cc1f99ec2b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_client.c @@ -210,6 +210,8 @@ int ca_challenge(auth_client_t *ca, * @retval number of challenges to updated * @retval 0 when there was no challenge to update * @retval -1 upon an error + * + * @NEW_1_12_5 */ int auc_info(auth_client_t **auc_list, msg_auth_info_t const *ai, @@ -495,6 +497,8 @@ int ca_clear_credentials(auth_client_t *ca, * * @retval 1 when authorization can proceed * @retval 0 when there is not enough credentials + * + * @NEW_1_12_5 */ int auc_has_authorization(auth_client_t **auc_list) { @@ -766,22 +770,13 @@ static int auc_digest_challenge(auth_client_t *ca, msg_auth_t const *ch) if (ac->ac_qop && (cda->cda_cnonce == NULL || ac->ac_stale)) { su_guid_t guid[1]; char *cnonce; - char *e; - + size_t b64len = BASE64_MINSIZE(sizeof(guid)) + 1; if (cda->cda_cnonce != NULL) /* Free the old one if we are updating after stale=true */ su_free(home, (void *)cda->cda_cnonce); su_guid_generate(guid); - cda->cda_cnonce = cnonce = su_alloc(home, BASE64_SIZE(sizeof(guid)) + 1); - base64_e(cnonce, BASE64_SIZE(sizeof(guid)) + 1, guid, sizeof(guid)); - /* somewhere else in the code the '=' chars are stripped in the header - we need to strip it now before the digest is created or we're in trouble - cos they won't match..... - */ - e = cnonce + strlen(cnonce) - 1; - while(*e == '=') { - *e-- = '\0'; - } + cda->cda_cnonce = cnonce = su_alloc(home, b64len); + base64_e(cnonce, b64len, guid, sizeof(guid)); cda->cda_ncount = 0; } diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c index 5205185a5e..0974b311b5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c @@ -76,6 +76,7 @@ static char const __func__[] = "auth_mod"; char const auth_internal_server_error[] = "Internal server error"; +static void auth_call_scheme_destructor(void *); static void auth_md5_hmac_key(auth_mod_t *am); HTABLE_PROTOS_WITH(auth_htable, aht, auth_passwd_t, usize_t, unsigned); @@ -94,7 +95,7 @@ auth_mod_t *auth_mod_alloc(auth_scheme_t *scheme, if ((am = su_home_new(scheme->asch_size))) { am->am_scheme = scheme; - am->am_refcount = 1; + su_home_destructor(am->am_home, auth_call_scheme_destructor); } return am; @@ -246,10 +247,14 @@ int auth_init_default(auth_mod_t *am, /** Destroy (a reference to) an authentication module. */ void auth_mod_destroy(auth_mod_t *am) { - if (am && am->am_refcount != 0 && --am->am_refcount == 0) { - am->am_scheme->asch_destroy(am); - su_home_zap(am->am_home); - } + su_home_unref(am->am_home); +} + +/** Call scheme-specific destructor function. */ +static void auth_call_scheme_destructor(void *arg) +{ + auth_mod_t *am = arg; + am->am_scheme->asch_destroy(am); } /** Do-nothing destroy function. @@ -264,18 +269,13 @@ void auth_destroy_default(auth_mod_t *am) /** Create a new reference to authentication module. */ auth_mod_t *auth_mod_ref(auth_mod_t *am) { - if (!am || am->am_refcount == 0) - return NULL; - - am->am_refcount++; - - return am; + return (auth_mod_t *)su_home_ref(am->am_home); } /** Destroy a reference to an authentication module. */ void auth_mod_unref(auth_mod_t *am) { - auth_mod_destroy(am); + su_home_unref(am->am_home); } /** Get authenticatin module name. @NEW_1_12_4. */ @@ -608,7 +608,7 @@ struct nonce { uint8_t digest[6]; }; -#define AUTH_DIGEST_NONCE_LEN (BASE64_SIZE(sizeof (struct nonce)) + 1) +#define AUTH_DIGEST_NONCE_LEN (BASE64_MINSIZE(sizeof (struct nonce)) + 1) /** Authenticate a request with @b Digest authentication scheme. * @@ -950,7 +950,8 @@ int auth_readdb_if_needed(auth_mod_t *am) #include #endif -#define auth_apw_local auth_readdb_internal +/* This is just a magic value */ +#define auth_apw_local ((void *)(intptr_t)auth_readdb_internal) /** Read authentication database */ static diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_plugin_delayed.c b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_plugin_delayed.c index d60c41a281..69178a1c51 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_plugin_delayed.c +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/auth_plugin_delayed.c @@ -126,7 +126,7 @@ static int delayed_auth_init(auth_mod_t *am, struct auth_splugin_t { - void const *asp_tag; + void const *asp_cookie; auth_splugin_t *asp_next; auth_splugin_t **asp_prev; auth_mod_t *asp_am; @@ -136,6 +136,8 @@ struct auth_splugin_t int asp_canceled; }; +/* This is unique identifier */ +#define delayed_asp_cookie ((void const *)(intptr_t)delayed_auth_cancel) static void delayed_auth_method_recv(su_root_magic_t *rm, su_msg_r msg, @@ -162,7 +164,7 @@ static void delayed_auth_method(auth_mod_t *am, asp = su_msg_data(mamc); assert(asp); - asp->asp_tag = delayed_auth_cancel; + asp->asp_cookie = delayed_asp_cookie; asp->asp_am = am; asp->asp_as = as; asp->asp_header = auth; @@ -216,7 +218,7 @@ static void delayed_auth_cancel(auth_mod_t *am, auth_status_t *as) (void)ap; /* xyzzy */ - if (as->as_plugin && as->as_plugin->asp_tag == delayed_auth_cancel) + if (as->as_plugin && as->as_plugin->asp_cookie == delayed_asp_cookie) as->as_plugin->asp_canceled = 1; as->as_status = 500, as->as_phrase = "Authentication canceled"; diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h b/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h index 517c80ddd6..97b10a8509 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h @@ -105,7 +105,7 @@ struct auth_scheme typedef struct { unsigned apw_index; /**< Key to hash table */ - void const *apw_type; /**< Magic pointer */ + void const *apw_type; /**< Magic identifier */ char const *apw_user; /**< Username */ char const *apw_realm; /**< Realm */ @@ -124,7 +124,7 @@ struct stat; struct auth_mod_t { su_home_t am_home[1]; - unsigned am_refcount; /**< Number of references to this module */ + unsigned _am_refcount; /**< Not used */ /* User database / cache */ char const *am_db; /**< User database file name */ diff --git a/libs/sofia-sip/libsofia-sip-ua/iptsec/test_auth_digest.c b/libs/sofia-sip/libsofia-sip-ua/iptsec/test_auth_digest.c index ee253a2fa9..b10d10a9d2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/iptsec/test_auth_digest.c +++ b/libs/sofia-sip/libsofia-sip-ua/iptsec/test_auth_digest.c @@ -769,8 +769,6 @@ int test_digest_client() { char const *nonce1, *nextnonce, *nonce2; - reinit_as(as); auth_mod_destroy(am); aucs = NULL; - TEST_1(am = auth_mod_create(NULL, AUTHTAG_METHOD("Digest"), AUTHTAG_REALM("ims3.so.noklab.net"), diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.am index 5accd41bc2..8ebf52a2e4 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.am @@ -77,7 +77,7 @@ TESTS = test_msg # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am MSG_PARSER_AWK = $(srcdir)/msg_parser.awk diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.in index 50994a28f0..a6ee91dc88 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/msg/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -57,8 +82,12 @@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = msg_name_hash$(EXEEXT) test_msg$(EXEEXT) DIST_COMMON = $(dist_pkgdata_SCRIPTS) $(nobase_include_sofia_HEADERS) \ - $(srcdir)/../sofia.am $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in ChangeLog + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am \ + ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/msg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -126,6 +155,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -172,8 +202,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -217,6 +251,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -327,7 +362,7 @@ EXTRA_DIST = Doxyfile msg.docs \ # ---------------------------------------------------------------------- # Tests TESTS = test_msg -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -353,6 +388,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -363,7 +400,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -639,7 +676,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -793,6 +830,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + test_protos.h: test_protos.h.in $(MSG_PARSER_AWK) test_table.c: test_table.c.in $(MSG_PARSER_AWK) diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.awk b/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.awk index 037b2c729d..1769d88bcb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.awk +++ b/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.awk @@ -54,11 +54,13 @@ BEGIN { split("", NAMES); split("", Comments); split("", COMMENTS); + split("", experimental); # indexed by the C name of the header split("", Since); # Non-NUL if extra split("", Extra); # Offset in extra headers + without_experimental = 0; template=""; template1=""; template2=""; @@ -155,11 +157,24 @@ function protos (name, comment, hash, since) Extra[name] = extra++; } + expr = (without_experimental > 0 && do_hash); + if (expr) { + printf "%s is experimental\n", Comment; + } + + experimental[N] = expr; + if (PR) { + if (expr) { + print "#if SU_HAVE_EXPERIMENTAL" > PR; + } replace(template, hash, name, NAME, comment, Comment, COMMENT, since); replace(template1, hash, name, NAME, comment, Comment, COMMENT, since); replace(template2, hash, name, NAME, comment, Comment, COMMENT, since); replace(template3, hash, name, NAME, comment, Comment, COMMENT, since); + if (expr) { + print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; + } } } @@ -210,8 +225,19 @@ function process_footer (text) for (i = 1; i <= n; i++) { l = lines[i]; if (match(tolower(l), /#(xxxxxx(x_xxxxxxx)?|hash)#/)) { + expr = 0; + for (j = 1; j <= N; j++) { l = lines[i]; + if (expr != experimental[j]) { + expr = experimental[j]; + if (expr) { + print "#if SU_HAVE_EXPERIMENTAL" > PR; + } + else { + print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; + } + } gsub(/#hash#/, hashes[j], l); gsub(/#xxxxxxx_xxxxxxx#/, comments[j], l); gsub(/#Xxxxxxx_Xxxxxxx#/, Comments[j], l); @@ -220,6 +246,10 @@ function process_footer (text) gsub(/#XXXXXX#/, NAMES[j], l); print l > PR; } + + if (expr) { + print "#endif /* SU_HAVE_EXPERIMENTAL */" > PR; + } } else { print l > PR; } @@ -333,10 +363,11 @@ function templates () } /^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); } +HLIST && /^#### EXPERIMENTAL HEADER LIST STARTS HERE ####$/ { + without_experimental=total; } HLIST && /^[a-z]/ { protos($1, $0, 0, $2); headers[total++] = $1; } /^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0; } - /^ *\/\* === Headers start here \*\// { in_header_list=1; templates(); } /^ *\/\* === Headers end here \*\// { in_header_list=0; } @@ -366,10 +397,13 @@ in_header_list && /^ (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ { END { if (failed) { exit }; + if (without_experimental == 0) + without_experimental = total; + if (!NO_LAST) { protos("unknown", "/**< Unknown headers */", -3); protos("error", "/**< Erroneous headers */", -4); - protos("separator", "/**< Separator line between headers and payload */", -5); + protos("separator", "/**< Separator line between headers and body */", -5); protos("payload", "/**< Message payload */", -6); if (multipart) protos("multipart", "/**< Multipart payload */", -7); @@ -426,7 +460,16 @@ END { if (extra > 0) { printf("struct %s {\n", extra_struct) > PT; printf(" %s base;\n", module_struct) > PT; - printf(" msg_header_t *extra[%u];\n", extra) > PT; + if (total - without_experimental < extra) { + printf(" msg_header_t *extra[%u];\n", + extra - (total - without_experimental)) > PT; + } + if (total - without_experimental > 0) { + print "#if SU_HAVE_EXPERIMENTAL" > PT; + printf(" msg_header_t *experimental[%u];\n", + total - without_experimental) > PT; + print "#endif" > PT; + } printf("};\n\n") > PT; module_struct = "struct " extra_struct; } @@ -465,7 +508,13 @@ END { else { printf(" NULL, \n") > PT; } - printf(" %d, %d, \n", MC_HASH_SIZE, total) > PT; + printf(" %d, \n", MC_HASH_SIZE) > PT; + printf ("#if SU_HAVE_EXPERIMENTAL\n" \ + " %d,\n" \ + "#else\n" \ + " %d,\n" \ + "#endif\n", \ + total, without_experimental) > PT; printf(" {\n") > PT; for (i = 0; i < total; i++) { @@ -484,6 +533,7 @@ END { } header_hash[j] = n; + experimental2[j] = (i >= without_experimental); } for (i = 0; i < MC_HASH_SIZE; i++) { @@ -492,14 +542,23 @@ END { n = header_hash[i]; flags = header_flags[n]; if (flags) flags = ",\n " flags; + if (experimental2[i]) { + print "#if SU_HAVE_EXPERIMENTAL" > PT; + } + if (Since[n]) { - printf(" { %s_%s_class, offsetof(struct %s, extra[%u])%s }%s\n", + printf(" { %s_%s_class,\n" \ + " offsetof(struct %s, extra[%u])%s }%s\n", tprefix, n, extra_struct, Extra[n], flags, c) > PT; } else { printf(" { %s_%s_class, offsetof(%s_t, %s_%s)%s }%s\n", tprefix, n, module, prefix, n, flags, c) > PT; } + + if (experimental2[i]) { + printf("#else\n { NULL, 0 }%s\n#endif\n", c) > PT; + } } else { printf(" { NULL, 0 }%s\n", c) > PT; diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h b/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h index 670d362987..75edea58d5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h +++ b/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h @@ -56,7 +56,8 @@ SOFIA_BEGIN_DECLS * 1) Header class definitions. */ -#if HAVE_STRUCT_KEYWORDS +/* Do not use keywords until you fix msg_kind_foo_critical thing! */ \ +#if HAVE_STRUCT_KEYWORDS && 0 /** Define a header class */ #define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \ {{ \ @@ -74,6 +75,7 @@ SOFIA_BEGIN_DECLS hc_kind: msg_kind_##kind, \ }} #else +/** Define a header class */ #define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd) \ {{ \ pr##c##_hash, \ diff --git a/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.am index 0a3aa763ea..5b27b9252e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.am @@ -59,4 +59,5 @@ EXTRA_DIST = Doxyfile nea.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.in index 548cfd1752..cd73c4c1a9 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/nea/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libnea_la_SOURCES) @@ -53,8 +78,12 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/nea ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -98,6 +127,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -144,8 +174,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -189,6 +223,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -286,7 +321,7 @@ LDADD = libnea.la \ # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile nea.docs $(BUILT_SOURCES) -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -312,12 +347,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -543,7 +580,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -693,6 +730,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/nea/nea_server.c b/libs/sofia-sip/libsofia-sip-ua/nea/nea_server.c index 52a774d74e..f4ec303f5b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nea/nea_server.c +++ b/libs/sofia-sip/libsofia-sip-ua/nea/nea_server.c @@ -496,14 +496,14 @@ nea_server_t *nea_server_create(nta_agent_t *agent, nes->nes_eventity_uri && (nes->nes_leg || leg == NULL) && nes->nes_timer) { - SU_DEBUG_5(("nea_server_create(%p): success\n", nes)); + SU_DEBUG_5(("nea_server_create(%p): success\n", (void *)nes)); su_timer_set(nes->nes_timer, nes_event_timer, nes); nes->nes_callback = callback; nes->nes_context = context; } else { - SU_DEBUG_5(("nea_server_create(%p): failed\n", nes)); + SU_DEBUG_5(("nea_server_create(%p): failed\n", (void *)nes)); nea_server_destroy(nes), nes = NULL; } } @@ -551,11 +551,11 @@ int nea_server_shutdown(nea_server_t *nes, return 500; if (nes->nes_in_callback) { - SU_DEBUG_5(("nea_server_shutdown(%p) while in callback\n", nes)); + SU_DEBUG_5(("nea_server_shutdown(%p) while in callback\n", (void *)nes)); return 100; } - SU_DEBUG_5(("nea_server_shutdown(%p)\n", nes)); + SU_DEBUG_5(("nea_server_shutdown(%p)\n", (void *)nes)); in_callback = nes->nes_in_callback; nes->nes_in_callback = 1; @@ -585,12 +585,12 @@ void nea_server_destroy(nea_server_t *nes) return; if (nes->nes_in_callback) { - SU_DEBUG_5(("nea_server_destroy(%p) while in callback\n", nes)); + SU_DEBUG_5(("nea_server_destroy(%p) while in callback\n", (void *)nes)); nes->nes_pending_destroy = 1; return; } - SU_DEBUG_5(("nea_server_destroy(%p)\n", nes)); + SU_DEBUG_5(("nea_server_destroy(%p)\n", (void *)nes)); nta_leg_destroy(nes->nes_leg), nes->nes_leg = NULL; @@ -837,8 +837,8 @@ int nea_view_update(nea_server_t *nes, if (evq->evq_content_type) nea_view_queue(nes, evv, evq); - SU_DEBUG_7(("nea_server_update(%p): %s (%s)\n", - nes, ev->ev_event->o_type, evv->evv_content_type->c_type)); + SU_DEBUG_7(("nea_server_update(%p): %s (%s)\n", (void *)nes, + ev->ev_event->o_type, evv->evv_content_type->c_type)); return 1; } @@ -1019,7 +1019,8 @@ int nea_server_notify(nea_server_t *nes, nea_event_t *ev) nea_sub_t *s; int notified = 0, throttled = nes->nes_throttled; - SU_DEBUG_7(("nea_server_notify(%p): %s\n", nes, ev ? ev->ev_event->o_type: "")); + SU_DEBUG_7(("nea_server_notify(%p): %s\n", (void *)nes, + ev ? ev->ev_event->o_type: "")); ++nes->nes_in_list; diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am index 4b9459db2a..ac86e31c6b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.am @@ -73,7 +73,7 @@ EXTRA_DIST = Doxyfile nta.docs sl_utils.docs \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am # Generate list of nta tags TAG_DLL_FLAGS = LIST=nta_tag_list \ No newline at end of file diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.in index 035f86a021..ce953ac12e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/nta/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -57,8 +82,12 @@ target_triplet = @target@ check_PROGRAMS = test_nta_api$(EXEEXT) test_nta$(EXEEXT) \ portbind$(EXEEXT) DIST_COMMON = $(dist_noinst_SCRIPTS) $(nobase_include_sofia_HEADERS) \ - $(srcdir)/../sofia.am $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in ChangeLog + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am \ + ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/nta ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -128,6 +157,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -174,8 +204,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -219,6 +253,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = $(SHELL) @@ -325,7 +360,7 @@ EXTRA_DIST = Doxyfile nta.docs sl_utils.docs \ agent.pem cafile.pem \ invite.msc $(BUILT_SOURCES) -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -351,6 +386,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -362,7 +399,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -608,7 +645,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -758,6 +795,92 @@ clean-built-sources: ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index de88d85322..69871d9d11 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -225,7 +225,7 @@ static inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip, static inline int incoming_merge(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport); static inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *); -static inline int incoming_timer(nta_agent_t *, su_duration_t); +static inline su_duration_t incoming_timer(nta_agent_t *, su_duration_t); static nta_reliable_t *reliable_mreply(nta_incoming_t *, nta_prack_f *, nta_reliable_magic_t *, @@ -259,7 +259,7 @@ static nta_outgoing_t *outgoing_find(nta_agent_t const *sa, sip_via_t const *v); static int outgoing_recv(nta_outgoing_t *orq, int status, msg_t *, sip_t *); static void outgoing_default_recv(nta_outgoing_t *, int, msg_t *, sip_t *); -static inline int outgoing_timer(nta_agent_t *, su_duration_t); +static inline su_duration_t outgoing_timer(nta_agent_t *, su_duration_t); static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip); /* Internal message passing */ @@ -369,8 +369,10 @@ nta_agent_t *nta_agent_create(su_root_t *root, agent->sa_flags = MSG_DO_CANONIC; agent->sa_maxsize = 2 * 1024 * 1024; /* 2 MB */ - agent->sa_bad_req_mask = (unsigned)(~(sip_mask_response | sip_mask_proxy)); - agent->sa_bad_resp_mask = (unsigned)(~(sip_mask_request | sip_mask_proxy)); + agent->sa_bad_req_mask = + (unsigned) ~(sip_mask_response | sip_mask_proxy); + agent->sa_bad_resp_mask = + (unsigned) ~(sip_mask_request | sip_mask_proxy); agent->sa_t1 = NTA_SIP_T1; agent->sa_t2 = NTA_SIP_T2; agent->sa_t4 = NTA_SIP_T4; @@ -667,53 +669,108 @@ static int agent_tag_init(nta_agent_t *self) static int agent_timer_init(nta_agent_t *agent) { - return su_timer_set(agent->sa_timer = - su_timer_create(su_root_task(agent->sa_root), - NTA_SIP_T1 / 8), + agent->sa_timer = su_timer_create(su_root_task(agent->sa_root), + NTA_SIP_T1 / 8); +#if 0 + return su_timer_set(agent->sa_timer, agent_timer, agent); +#endif + return -(agent->sa_timer == NULL); } +#define NEXT_TIMEOUT(next, p, f, now) \ + (p && p->f - (next) < 0 ? (p->f - (now) > 0 ? p->f : (now)) : (next)) + /** * Agent timer routine. */ static void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent) { - su_duration_t now = su_time_ms(agent->sa_now = su_now()); - int again; + su_time_t stamp = su_now(); + su_duration_t now = su_time_ms(stamp), next; now += now == 0; + agent->sa_now = stamp; agent->sa_millisec = now; + agent->sa_next = 0; + agent->sa_in_timer = 1; - again = outgoing_timer(agent, now); - again = incoming_timer(agent, now) || again; + next = now + SU_DURATION_MAX; + next = outgoing_timer(agent, next); + next = incoming_timer(agent, next); agent->sa_millisec = 0; + agent->sa_in_timer = 0; - if (again) - su_timer_set_at(timer, agent_timer, agent, su_time_add(su_now(), 1)); - else - su_timer_set(timer, agent_timer, agent); + if (agent->sa_next) + next = NEXT_TIMEOUT(next, agent, sa_next, now); + + if (next == now + SU_DURATION_MAX) { + /* Do not set timer */ + SU_DEBUG_9(("nta: timer not set\n")); + assert(!agent->sa_out.completed->q_head); + assert(!agent->sa_out.trying->q_head); + assert(!agent->sa_out.inv_calling->q_head); + assert(!agent->sa_out.re_list); + assert(!agent->sa_in.inv_confirmed->q_head); + assert(!agent->sa_in.preliminary->q_head); + assert(!agent->sa_in.completed->q_head); + assert(!agent->sa_in.inv_completed->q_head); + assert(!agent->sa_in.re_list); + return; + } + + if (next == now) if (++next == 0) ++next; + + SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set next", (long)(next - now))); + + agent->sa_next = next; + + su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now)); } -/** Calculate nonzero value for timer */ -static inline -su_duration_t set_timeout(nta_agent_t const *agent, su_duration_t offset) +/** Calculate nonzero value for timeout. + * + * Sets or adjusts agent timer when needed. + * + * @retval 0 if offset is 0 + * @retval timeout (millisecond counter) otherwise + */ +static +su_duration_t set_timeout(nta_agent_t *agent, su_duration_t offset) { - su_duration_t now; + su_time_t now; + su_duration_t next, ms; -#if 0 - if (agent->sa_millisec) - now = agent->sa_millisec; + if (offset == 0) + return 0; + + if (agent->sa_millisec) /* Avoid expensive call to su_timer_ms() */ + now = agent->sa_now, ms = agent->sa_millisec; else -#endif - now = (su_duration_t)su_time_ms(su_now()); + now = su_now(), ms = (su_duration_t)su_time_ms(now); + + next = ms + offset; if (next == 0) next = 1; - now += offset; + if (agent->sa_in_timer) + return next; - return now ? now : 1; + if (agent->sa_next == 0 || agent->sa_next - next - 5L > 0) { + /* Set timer */ + if (agent->sa_next) + SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset)); + else + SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset)); + + su_timer_set_at(agent->sa_timer, agent_timer, agent, + su_time_add(now, offset)); + agent->sa_next = next; + } + + return next; } @@ -1475,7 +1532,7 @@ int nta_agent_add_tport(nta_agent_t *self, (nta_compressor_vtable == NULL || strcasecmp(tpn->tpn_comp, nta_compressor_vtable->ncv_name) != 0)) { SU_DEBUG_1(("nta(%p): comp=%s not supported for " URL_PRINT_FORMAT "\n", - self, tpn->tpn_comp, URL_PRINT_ARGS(url))); + (void *)self, tpn->tpn_comp, URL_PRINT_ARGS(url))); } } @@ -1960,7 +2017,8 @@ static void agent_update_tport(nta_agent_t *self, tport_t *tport) } else { /* XXX - we should do something else? */ - SU_DEBUG_3(("nta(%p): transport address updated\n", self)); + SU_DEBUG_3(("%s(%p): %s\n", "nta", (void *)self, + "transport address updated")); } } @@ -3421,7 +3479,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent, leg_insert(agent, leg); - SU_DEBUG_9(("nta_leg_create(%p)\n", leg)); + SU_DEBUG_9(("nta_leg_create(%p)\n", (void *)leg)); return leg; @@ -3471,7 +3529,7 @@ void leg_insert(nta_agent_t *sa, nta_leg_t *leg) */ void nta_leg_destroy(nta_leg_t *leg) { - SU_DEBUG_9(("nta_leg_destroy(%p)\n", leg)); + SU_DEBUG_9(("nta_leg_destroy(%p)\n", (void *)leg)); if (leg) { leg_htable_t *leg_hash; @@ -3566,6 +3624,7 @@ char const *nta_leg_tag(nta_leg_t *leg, char const *tag) if (tag) { if (sip_to_tag(leg->leg_home, leg->leg_local, tag) < 0) return NULL; + leg->leg_tagged = 1; return leg->leg_local->a_tag; } @@ -3574,6 +3633,8 @@ char const *nta_leg_tag(nta_leg_t *leg, char const *tag) if (!tag || sip_to_add_param(leg->leg_home, leg->leg_local, tag) < 0) return NULL; + leg->leg_tagged = 1; + return leg->leg_local->a_tag; } @@ -3757,7 +3818,7 @@ void leg_recv(nta_leg_t *leg, msg_t *msg, sip_t *sip, tport_t *tport) if (!(irq = incoming_create(agent, msg, sip, tport, tag))) { SU_DEBUG_3(("nta: leg_recv(%p): cannot create transaction for %s\n", - leg, method_name)); + (void *)leg, method_name)); nta_msg_treply(agent, msg, SIP_500_INTERNAL_SERVER_ERROR, NTATAG_TPORT(tport), @@ -3783,12 +3844,12 @@ void leg_recv(nta_leg_t *leg, msg_t *msg, sip_t *sip, tport_t *tport) if (status < 100 || status > 699) { SU_DEBUG_3(("nta_leg(%p): invalid status %03d from callback\n", - leg, status)); + (void *)leg, status)); status = 500; } else if (method == sip_method_invite && status >= 200 && status < 300) { SU_DEBUG_3(("nta_leg(%p): invalid INVITE status %03d from callback\n", - leg, status)); + (void *)leg, status)); status = 500; } @@ -3922,6 +3983,14 @@ nta_leg_t *leg_find(nta_agent_t const *sa, /* Do not match if the incoming To has tag, but the local does not */ if (!local_tag && to_tag) continue; + + /* + * Do not match if incoming To has no tag and we have local tag + * and the tag has been there from the beginning. + */ + if (local_tag && !to_tag && !leg->leg_tagged) + continue; + /* Do not match if incoming From has no tag but remote has a tag */ if (remote_tag && !from_tag) continue; @@ -4153,7 +4222,7 @@ static inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *); static inline void incoming_remove(nta_incoming_t *irq); static inline void incoming_set_timer(nta_incoming_t *, unsigned interval); static inline void incoming_reset_timer(nta_incoming_t *); -static inline size_t incoming_mass_destroy(nta_agent_t *sa, incoming_queue_t *q); +static inline size_t incoming_mass_destroy(nta_agent_t *, incoming_queue_t *); static int incoming_set_params(nta_incoming_t *irq, tagi_t const *tags); static inline @@ -4436,7 +4505,7 @@ int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip) if (leg->leg_rseq > sip->sip_cseq->cs_seq) { SU_DEBUG_3(("nta_leg(%p): out-of-order %s (%u < %u)\n", - leg, method_name, seq, leg->leg_rseq)); + (void *)leg, method_name, seq, leg->leg_rseq)); return 500; } @@ -4531,10 +4600,7 @@ void incoming_queue(incoming_queue_t *queue, assert(*queue->q_tail == NULL); - if (queue->q_timeout) - irq->irq_timeout = set_timeout(irq->irq_agent, queue->q_timeout); - else - irq->irq_timeout = 0; + irq->irq_timeout = set_timeout(irq->irq_agent, queue->q_timeout); irq->irq_queue = queue; irq->irq_prev = queue->q_tail; @@ -4626,7 +4692,7 @@ void incoming_reset_timer(nta_incoming_t *irq) static void incoming_free(nta_incoming_t *irq) { - SU_DEBUG_9(("nta: incoming_free(%p)\n", irq)); + SU_DEBUG_9(("nta: incoming_free(%p)\n", (void *)irq)); incoming_cut_off(irq); incoming_reclaim(irq); @@ -4706,7 +4772,8 @@ void incoming_reclaim_queued(su_root_magic_t *rm, incoming_queue_t *q = u->a_incoming_queue; nta_incoming_t *irq, *irq_next; - SU_DEBUG_9(("incoming_reclaim_all(%p, %p, %p)\n", rm, msg, u)); + SU_DEBUG_9(("incoming_reclaim_all(%p, %p, %p)\n", + (void *)rm, (void *)msg, (void *)u)); for (irq = q->q_head; irq; irq = irq_next) { irq_next = irq->irq_next; @@ -5276,6 +5343,34 @@ int incoming_set_compartment(nta_incoming_t *irq, tport_t *tport, msg_t *msg, return 0; } +/** Add essential headers to the response message */ +static int nta_incoming_response_headers(nta_incoming_t *irq, + msg_t *msg, + sip_t *sip) +{ + int clone = 0; + su_home_t *home = msg_home(msg); + + if (!sip->sip_from) + clone = 1, sip->sip_from = sip_from_copy(home, irq->irq_from); + if (!sip->sip_to) + clone = 1, sip->sip_to = sip_to_copy(home, irq->irq_to); + if (!sip->sip_call_id) + clone = 1, sip->sip_call_id = sip_call_id_copy(home, irq->irq_call_id); + if (!sip->sip_cseq) + clone = 1, sip->sip_cseq = sip_cseq_copy(home, irq->irq_cseq); + if (!sip->sip_via) + clone = 1, sip->sip_via = sip_via_copy(home, irq->irq_via); + + if (clone) + msg_set_parent(msg, (msg_t *)irq->irq_home); + + if (!sip->sip_from || !sip->sip_to || !sip->sip_call_id || !sip->sip_cseq || !sip->sip_via) + return -1; + + return 0; +} + /** Complete a response message. * * @param irq server transaction object @@ -5297,7 +5392,6 @@ int nta_incoming_complete_response(nta_incoming_t *irq, { su_home_t *home = msg_home(msg); sip_t *sip = sip_object(msg); - int clone = 0; int retval; ta_list ta; @@ -5307,7 +5401,7 @@ int nta_incoming_complete_response(nta_incoming_t *irq, if (status != 0 && (status < 100 || status > 699)) return su_seterrno(EINVAL), -1; - if (!sip->sip_status) + if (status != 0 && !sip->sip_status) sip->sip_status = sip_status_create(home, status, phrase, NULL); ta_start(ta, tag, value); @@ -5320,42 +5414,54 @@ int nta_incoming_complete_response(nta_incoming_t *irq, if (irq->irq_default) return sip_complete_message(msg); - if (!sip->sip_from) - clone = 1, sip->sip_from = sip_from_copy(home, irq->irq_from); if (status > 100 && !irq->irq_tag) { if (sip->sip_to) nta_incoming_tag(irq, sip->sip_to->a_tag); else nta_incoming_tag(irq, NULL); } - if (!sip->sip_to) - clone = 1, sip->sip_to = sip_to_copy(home, irq->irq_to); - if (sip->sip_status && sip->sip_status->st_status > 100 && - irq->irq_tag && sip->sip_to && !sip->sip_to->a_tag) - sip_to_tag(home, sip->sip_to, irq->irq_tag); - if (!sip->sip_call_id) - clone = 1, sip->sip_call_id = sip_call_id_copy(home, irq->irq_call_id); - if (!sip->sip_cseq) - clone = 1, sip->sip_cseq = sip_cseq_copy(home, irq->irq_cseq); - if (!sip->sip_via) - clone = 1, sip->sip_via = sip_via_copy(home, irq->irq_via); - if (status < 300 && - !sip->sip_record_route && irq->irq_record_route) - sip_add_dup(msg, sip, (sip_header_t *)irq->irq_record_route); - if (clone) - msg_set_parent(msg, (msg_t *)irq->irq_home); - - if (retval < 0 || !sip->sip_from || !sip->sip_to || !sip->sip_call_id - || !sip->sip_cseq || !sip->sip_via - || (status < 300 && irq->irq_record_route && !sip->sip_record_route && - sip->sip_cseq && sip->sip_cseq->cs_method != sip_method_register)) + if (nta_incoming_response_headers(irq, msg, sip) < 0) return -1; + if (sip->sip_status && sip->sip_status->st_status > 100 && + irq->irq_tag && sip->sip_to && !sip->sip_to->a_tag) + if (sip_to_tag(home, sip->sip_to, irq->irq_tag) < 0) + return -1; + + if (status < 300 && !sip->sip_record_route && irq->irq_record_route) + if (sip_add_dup(msg, sip, (sip_header_t *)irq->irq_record_route) < 0) + return -1; + return sip_complete_message(msg); } +/** Create a response message for request. + * + * @NEW_1_12_5. + */ +msg_t *nta_incoming_create_response(nta_incoming_t *irq, + int status, char const *phrase) +{ + msg_t *msg = NULL; + sip_t *sip; + + if (irq) { + msg = nta_msg_create(irq->irq_agent, 0); + sip = sip_object(msg); + + if (status != 0) + sip->sip_status = sip_status_create(msg_home(msg), status, phrase, NULL); + + if (nta_incoming_response_headers(irq, msg, sip) < 0) + msg_destroy(msg), msg = NULL; + } + + return msg; +} + + /**Reply to an incoming transaction request. * * This function creates a response message to an incoming request and sends @@ -5744,8 +5850,9 @@ enum { /** @internal Timer routine for the incoming request. */ static inline -int incoming_timer(nta_agent_t *sa, su_duration_t now) +su_duration_t incoming_timer(nta_agent_t *sa, su_duration_t next) { + su_duration_t now = sa->sa_millisec; nta_incoming_t *irq, *irq_next; size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0; size_t unconfirmed = @@ -5762,8 +5869,9 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) /* Handle retry queue */ while ((irq = sa->sa_in.re_list)) { - if ((irq->irq_retry && irq->irq_retry - now > 0) || - retransmitted >= timer_max_retransmit) + if (irq->irq_retry - now > 0) + break; + if (retransmitted >= timer_max_retransmit) break; if (irq->irq_method == sip_method_invite && irq->irq_status >= 200) { @@ -5801,7 +5909,8 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) retransmitted++; incoming_retransmit_reply(irq, irq->irq_tport); } - } else { + } + else { /* Timer N1 */ SU_DEBUG_5(("nta: timer N1 fired, sending %u %s\n", SIP_100_TRYING)); incoming_reset_timer(irq); @@ -5809,6 +5918,8 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) } } + next = NEXT_TIMEOUT(next, irq, irq_retry, now); + while ((irq = sa->sa_in.final_failed->q_head)) { incoming_remove(irq); irq->irq_final_failed = 0; @@ -5841,8 +5952,9 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) assert(irq->irq_status < 200); assert(irq->irq_timeout); - if (irq->irq_timeout - now > 0 - || timeout >= timer_max_timeout) + if (irq->irq_timeout - now > 0) + break; + if (timeout >= timer_max_timeout) break; timeout++; @@ -5855,6 +5967,8 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) reliable_timeout(irq, 1); } + next = NEXT_TIMEOUT(next, irq, irq_timeout, now); + while ((irq = sa->sa_in.inv_completed->q_head)) { assert(irq->irq_status >= 200); assert(irq->irq_timeout); @@ -5883,13 +5997,14 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) } } + next = NEXT_TIMEOUT(next, irq, irq_timeout, now); + while ((irq = sa->sa_in.inv_confirmed->q_head)) { assert(irq->irq_timeout); assert(irq->irq_status >= 200); assert(irq->irq_method == sip_method_invite); - if (irq->irq_timeout - now > 0 || - terminated >= timer_max_terminate) + if (irq->irq_timeout - now > 0 || terminated >= timer_max_terminate) break; /* Timer I */ @@ -5905,13 +6020,14 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) incoming_free_queue(rq, irq); } + next = NEXT_TIMEOUT(next, irq, irq_timeout, now); + while ((irq = sa->sa_in.completed->q_head)) { assert(irq->irq_status >= 200); assert(irq->irq_timeout); assert(irq->irq_method != sip_method_invite); - if (irq->irq_timeout - now > 0 || - terminated >= timer_max_terminate) + if (irq->irq_timeout - now > 0 || terminated >= timer_max_terminate) break; /* Timer J */ @@ -5928,6 +6044,8 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) incoming_free_queue(rq, irq); } + next = NEXT_TIMEOUT(next, irq, irq_timeout, now); + for (irq = sa->sa_in.terminated->q_head; irq; irq = irq_next) { irq_next = irq->irq_next; if (irq->irq_destroyed) @@ -5947,10 +6065,7 @@ int incoming_timer(nta_agent_t *sa, su_duration_t now) terminated, unterminated, destroyed, total)); - return - retransmitted >= timer_max_retransmit - || timeout >= timer_max_timeout - || terminated >= timer_max_terminate; + return next; } /** Mass destroy server transactions */ @@ -6018,11 +6133,11 @@ static inline void outgoing_remove(nta_outgoing_t *orq); static inline void outgoing_set_timer(nta_outgoing_t *orq, unsigned interval); static inline void outgoing_reset_timer(nta_outgoing_t *orq); static size_t outgoing_timer_dk(outgoing_queue_t *q, - char const *timer, - su_duration_t now); + char const *timer, + su_duration_t now); static size_t outgoing_timer_bf(outgoing_queue_t *q, - char const *timer, - su_duration_t now); + char const *timer, + su_duration_t now); static void outgoing_ack(nta_outgoing_t *orq, msg_t *msg, sip_t *sip); static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *, @@ -6381,7 +6496,8 @@ void nta_outgoing_destroy(nta_outgoing_t *orq) return; if (orq->orq_destroyed) { - SU_DEBUG_1(("nta_outgoing_destroy(%p): already destroyed\n", orq)); + SU_DEBUG_1(("%s(%p): %s\n", "nta_outgoing_destroy", (void *)orq, + "already destroyed")); return; } @@ -7246,7 +7362,7 @@ void outgoing_queue(outgoing_queue_t *queue, assert(*queue->q_tail == NULL); orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout); - + orq->orq_queue = queue; orq->orq_prev = queue->q_tail; *queue->q_tail = orq; @@ -7305,6 +7421,7 @@ void outgoing_set_timer(nta_outgoing_t *orq, unsigned interval) orq->orq_retry = set_timeout(orq->orq_agent, orq->orq_interval = interval); + /* Shortcut into queue at SIP T1 */ rq = orq->orq_agent->sa_out.re_t1; if (!(*rq) || (*rq)->orq_retry - orq->orq_retry > 0) @@ -7343,7 +7460,7 @@ void outgoing_reset_timer(nta_outgoing_t *orq) static void outgoing_free(nta_outgoing_t *orq) { - SU_DEBUG_9(("nta: outgoing_free(%p)\n", orq)); + SU_DEBUG_9(("nta: outgoing_free(%p)\n", (void *)orq)); outgoing_cut_off(orq); outgoing_reclaim(orq); } @@ -7410,7 +7527,8 @@ void outgoing_reclaim_queued(su_root_magic_t *rm, outgoing_queue_t *q = u->a_outgoing_queue; nta_outgoing_t *orq, *orq_next; - SU_DEBUG_9(("outgoing_reclaim_all(%p, %p, %p)\n", rm, msg, u)); + SU_DEBUG_9(("outgoing_reclaim_all(%p, %p, %p)\n", + (void *)rm, (void *)msg, (void *)u)); for (orq = q->q_head; orq; orq = orq_next) { orq_next = orq->orq_next; @@ -7434,6 +7552,14 @@ void outgoing_destroy(nta_outgoing_t *orq) if (orq->orq_terminated || orq->orq_default) { outgoing_free(orq); } + /* We have to handle 200 OK statelessly => + kill transaction immediately */ + else if (orq->orq_method == sip_method_invite && !orq->orq_completed + /* (unless we have to wait to send CANCEL) */ + && !orq->orq_cancel) { + orq->orq_destroyed = 1; + outgoing_terminate(orq); + } else { orq->orq_destroyed = 1; orq->orq_callback = outgoing_default_cb; @@ -7441,24 +7567,29 @@ void outgoing_destroy(nta_outgoing_t *orq) } } -/** @internal Outgoing transaction timer routine. */ -static -int outgoing_timer(nta_agent_t *sa, su_duration_t now) +/** @internal Outgoing transaction timer routine. + * + */ +static inline +su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next) { + su_duration_t now = sa->sa_millisec; nta_outgoing_t *orq; outgoing_queue_t rq[1]; size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed; size_t total = sa->sa_outgoing->oht_used; size_t trying = sa->sa_out.re_length; - size_t pending = sa->sa_out.trying->q_length + sa->sa_out.inv_calling->q_length; + size_t pending = sa->sa_out.trying->q_length + + sa->sa_out.inv_calling->q_length; size_t completed = sa->sa_out.completed->q_length + sa->sa_out.inv_completed->q_length; outgoing_queue_init(sa->sa_out.free = rq, 0); while ((orq = sa->sa_out.re_list)) { - if ((orq->orq_retry && orq->orq_retry - now > 0) - || retransmitted >= timer_max_retransmit) + if (orq->orq_retry - now > 0) + break; + if (retransmitted >= timer_max_retransmit) break; if (orq->orq_reliable) { @@ -7494,14 +7625,22 @@ int outgoing_timer(nta_agent_t *sa, su_duration_t now) su_root_yield(sa->sa_root); /* Handle received packets */ } + next = NEXT_TIMEOUT(next, orq, orq_retry, now); + terminated = outgoing_timer_dk(sa->sa_out.inv_completed, "D", now) + outgoing_timer_dk(sa->sa_out.completed, "K", now); + next = NEXT_TIMEOUT(next, sa->sa_out.inv_completed->q_head, orq_timeout, now); + next = NEXT_TIMEOUT(next, sa->sa_out.completed->q_head, orq_timeout, now); + timeout = outgoing_timer_bf(sa->sa_out.inv_calling, "B", now) + outgoing_timer_bf(sa->sa_out.trying, "F", now); + next = NEXT_TIMEOUT(next, sa->sa_out.inv_calling->q_head, orq_timeout, now); + next = NEXT_TIMEOUT(next, sa->sa_out.trying->q_head, orq_timeout, now); + destroyed = outgoing_mass_destroy(sa, rq); sa->sa_out.free = NULL; @@ -7518,10 +7657,7 @@ int outgoing_timer(nta_agent_t *sa, su_duration_t now) destroyed, total)); } - return - retransmitted >= timer_max_retransmit || - terminated >= timer_max_terminate || - timeout >= timer_max_timeout; + return next; } /** @internal Retransmit the outgoing request. */ @@ -7558,16 +7694,12 @@ size_t outgoing_timer_bf(outgoing_queue_t *q, char const *timer, su_duration_t now) { + nta_outgoing_t *orq; size_t timeout = 0; - for (;;) { - nta_outgoing_t *orq = q->q_head; - - if (!orq - || !orq->orq_timeout - || orq->orq_timeout - now > 0 - || timeout >= timer_max_timeout) - return timeout; + while ((orq = q->q_head)) { + if (orq->orq_timeout - now > 0 || timeout >= timer_max_timeout) + break; timeout++; @@ -7579,6 +7711,8 @@ size_t outgoing_timer_bf(outgoing_queue_t *q, assert(q->q_head != orq || orq->orq_timeout - now > 0); } + + return timeout; } /** @internal Signal transaction timeout to the application. */ @@ -7587,7 +7721,8 @@ void outgoing_timeout(nta_outgoing_t *orq, su_duration_t now) nta_outgoing_t *cancel; if (outgoing_other_destinations(orq)) { - SU_DEBUG_5(("nta(%p): try next after timeout\n", orq)); + SU_DEBUG_5(("%s(%p): %s\n", "nta", (void *)orq, + "try next after timeout")); outgoing_try_another(orq); return; } @@ -7634,16 +7769,12 @@ size_t outgoing_timer_dk(outgoing_queue_t *q, char const *timer, su_duration_t now) { + nta_outgoing_t *orq; size_t terminated = 0; - for (;;) { - nta_outgoing_t *orq = q->q_head; - - if (!orq - || !orq->orq_timeout - || orq->orq_timeout - now > 0 - || terminated >= timer_max_terminate) - return terminated; + while ((orq = q->q_head)) { + if (orq->orq_timeout - now > 0 || terminated >= timer_max_terminate) + break; terminated++; @@ -7652,6 +7783,8 @@ size_t outgoing_timer_dk(outgoing_queue_t *q, outgoing_terminate(orq); } + + return terminated; } /** Terminate a client transaction. */ @@ -7835,6 +7968,16 @@ int outgoing_recv(nta_outgoing_t *orq, outgoing_send(cancel, 0); else outgoing_reply(cancel, SIP_481_NO_TRANSACTION, 0); + + if (status < 300 && orq->orq_destroyed && + orq->orq_method == sip_method_invite) { + outgoing_terminate(orq); /* We can now kill transaction */ + if (status == 100) { + msg_destroy(msg); + return 0; + } + return -1; + } } if (orq->orq_pending) { @@ -8167,7 +8310,8 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase, if (orq->orq_method == sip_method_ack) { if (status != delayed) - SU_DEBUG_3(("nta(%p): responding %u %s to ACK!\n", orq, status, phrase)); + SU_DEBUG_3(("nta(%p): responding %u %s to ACK!\n", + (void *)orq, status, phrase)); orq->orq_status = status; if (orq->orq_queue == NULL) outgoing_complete(orq); /* Timer D/K */ @@ -8447,8 +8591,8 @@ outgoing_resolve(nta_outgoing_t *orq) /* Nothing found */ if (!sr->sr_tports[0]) { - SU_DEBUG_3(("nta(%p): transport %s is not supported%s%s\n", orq, tpname, - ident ? " by interface " : "", ident ? ident : "")); + SU_DEBUG_3(("nta(%p): transport %s is not supported%s%s\n", (void *)orq, + tpname, ident ? " by interface " : "", ident ? ident : "")); outgoing_resolving_error(orq, SIPDNS_503_ERROR); return; } @@ -9062,10 +9206,10 @@ void outgoing_answer_aaaa(sres_context_t *orq, sres_query_t *q, inet_ntop(AF_INET6, &aaaa->aaaa_addr, addr, sizeof(addr)); if (j == 0) - SU_DEBUG_5(("nta(%p): %s IN AAAA %s\n", orq, + SU_DEBUG_5(("nta(%p): %s IN AAAA %s\n", (void *)orq, aaaa->aaaa_record->r_name, addr)); else - SU_DEBUG_5(("nta(%p): AAAA %s\n", orq, addr)); + SU_DEBUG_5(("nta(%p): AAAA %s\n", (void *)orq, addr)); assert(j < found); results[j++] = su_strdup(home, addr); @@ -9147,7 +9291,7 @@ void outgoing_answer_a(sres_context_t *orq, sres_query_t *q, if (j == 0) SU_DEBUG_5(("nta: %s IN A %s\n", a->a_record->r_name, addr)); else - SU_DEBUG_5(("nta(%p): A %s\n", orq, addr)); + SU_DEBUG_5(("nta(%p): A %s\n", (void *)orq, addr)); assert(j < found); results[j++] = su_strdup(home, addr); @@ -9171,7 +9315,7 @@ outgoing_query_results(nta_outgoing_t *orq, sq->sq_type != sr->sr_a_aaaa2) { sq->sq_type = sr->sr_a_aaaa2; - SU_DEBUG_7(("nta(%p): %s %s record still unresolved\n", orq, + SU_DEBUG_7(("nta(%p): %s %s record still unresolved\n", (void *)orq, sq->sq_domain, sq->sq_type == sres_type_a ? "A" : "AAAA")); /* @@ -9631,7 +9775,7 @@ void nta_reliable_destroy(nta_reliable_t *rel) return; if (rel->rel_callback == nta_reliable_destroyed) - SU_DEBUG_1(("%s(%p): already destroyed\n", __func__, rel)); + SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "already destroyed")); rel->rel_callback = nta_reliable_destroyed; @@ -9658,7 +9802,7 @@ int nta_reliable_destroyed(nta_reliable_magic_t *rmagic, if (!*prev) { assert(*prev); - SU_DEBUG_1(("%s(%p): not linked\n", __func__, rel)); + SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "not linked")); return 200; } @@ -9739,7 +9883,8 @@ nta_outgoing_t *nta_outgoing_tagged(nta_outgoing_t *orq, if (orq == NULL || to_tag == NULL) return NULL; if (orq->orq_to->a_tag) { - SU_DEBUG_1(("%s: transaction %p already in dialog\n", __func__, orq)); + SU_DEBUG_1(("%s: transaction %p already in dialog\n", __func__, + (void *)orq)); return NULL; } @@ -10147,8 +10292,12 @@ int nta_tport_keepalive(nta_outgoing_t *orq) assert(orq); (void)tp; +#if HAVE_SOFIA_STUN return tport_keepalive(orq->orq_tport, msg_addrinfo(orq->orq_request), TAG_END()); +#else + return -1; +#endif } /** Close all transports. @since Experimental in @VERSION_1_12_2. */ @@ -10168,7 +10317,7 @@ int nta_agent_close_tports(nta_agent_t *agent) orq->orq_pending = 0; tport_unref(orq->orq_tport), orq->orq_tport = NULL; - } + } for (i = iht->iht_size; i-- > 0;) diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c index 0094a89baa..9046154af4 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta_check.c @@ -343,8 +343,8 @@ int nta_check_accept(nta_incoming_t *irq, /**Check @SessionExpires header. * * If the proposed session-expiration time is smaller than @MinSE or our - * minimal session expiration time, respond with 422 containing our minimal - * session expiration time in @MinSE header. + * minimal session expiration time, respond with 422 containing shortest + * acceptable session expiration time in @MinSE header. * * @param irq incoming transaction object (may be NULL). * @param sip contents of the SIP message @@ -359,26 +359,28 @@ int nta_check_session_expires(nta_incoming_t *irq, sip_time_t my_min_se, tag_type_t tag, tag_value_t value, ...) { - if ((sip->sip_min_se && - sip->sip_session_expires->x_delta < sip->sip_min_se->min_delta) - || sip->sip_session_expires->x_delta < my_min_se) { + unsigned long min_se = my_min_se; + + if (sip->sip_min_se && min_se < sip->sip_min_se->min_delta) + min_se = sip->sip_min_se->min_delta; + + if (sip->sip_session_expires->x_delta >= min_se) + return 0; + + if (irq) { ta_list ta; + sip_min_se_t min_se0[1]; - sip_min_se_t min_se[1]; + ta_start(ta, tag, value); - sip_min_se_init(min_se)->min_delta = my_min_se; + sip_min_se_init(min_se0)->min_delta = min_se; - if (irq) { - ta_start(ta, tag, value); - nta_incoming_treply(irq, - SIP_422_SESSION_TIMER_TOO_SMALL, - SIPTAG_MIN_SE(min_se), - ta_tags(ta)); - ta_end(ta); - } - - return 422; + nta_incoming_treply(irq, + SIP_422_SESSION_TIMER_TOO_SMALL, + SIPTAG_MIN_SE(min_se0), + ta_tags(ta)); + ta_end(ta); } - return 0; + return 422; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h b/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h index e2e0979c0a..cf3ff53a8e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h @@ -98,14 +98,15 @@ struct nta_agent_s nta_agent_magic_t *sa_magic; nta_message_f *sa_callback; - uint32_t sa_nw_updates; /* Shall we enable network detector? */ - nta_update_magic_t *sa_update_magic; nta_update_tport_f *sa_update_tport; - su_time_t sa_now; /**< Timestamp in microsecond resolution. */ + su_duration_t sa_next; /**< Timestamp for next agent_timer. */ + su_time_t sa_now; /**< Timestamp in microsecond resolution. */ uint32_t sa_millisec; /**< Timestamp in milliseconds resolution. */ + uint32_t sa_nw_updates; /* Shall we enable network detector? */ + uint32_t sa_flags; /**< Message flags */ msg_mclass_t *sa_mclass; @@ -223,6 +224,9 @@ struct nta_agent_s /** If true, automatically create compartments */ unsigned sa_auto_comp:1; + /** Set when executing timer */ + unsigned sa_in_timer:1; + unsigned :0; /** Messages memory preload. */ @@ -342,6 +346,11 @@ struct nta_leg_s unsigned leg_loose_route : 1; /**< Topmost route in set is LR */ #endif unsigned leg_local_is_to : 1; /**< Backwards-compatibility. */ + unsigned leg_tagged : 1; /**< Tagged after creation. + * + * Request missing To tag matches it + * even after tagging. + */ unsigned:0; nta_request_f *leg_callback; nta_leg_magic_t *leg_magic; @@ -463,12 +472,17 @@ struct nta_outgoing_s sip_method_t orq_method; char const *orq_method_name; + url_t const *orq_url; /**< Original RequestURI */ + sip_from_t const *orq_from; sip_to_t const *orq_to; + char const *orq_tag; /**< Tag from final response. */ + sip_cseq_t const *orq_cseq; sip_call_id_t const *orq_call_id; - char const *orq_tag; /**< Tag from final response. */ + msg_t *orq_request; + msg_t *orq_response; su_time_t orq_sent; /**< When request was sent? */ unsigned orq_delay; /**< RTT estimate */ @@ -501,11 +515,9 @@ struct nta_outgoing_s unsigned orq_sigcomp_new:1; /**< Create compartment if needed */ unsigned orq_sigcomp_zap:1; /**< Reset SigComp after completing */ unsigned orq_must_100rel : 1; - unsigned orq_timestamp : 1; /**< insert @Timestamp header. */ + unsigned orq_timestamp : 1; /**< Insert @Timestamp header. */ unsigned : 0; /* pad */ - uint32_t orq_rseq; /**< Latest incoming rseq */ - #if HAVE_SOFIA_SRESOLV sipdns_resolver_t *orq_resolver; #endif @@ -522,12 +534,10 @@ struct nta_outgoing_s char const *orq_branch; /**< Transaction branch */ char const *orq_via_branch; /**< @Via branch */ - url_t const *orq_url; /**< Original RequestURI */ - - msg_t *orq_request; - msg_t *orq_response; nta_outgoing_t *orq_cancel; /**< CANCEL transaction */ + + uint32_t orq_rseq; /**< Latest incoming rseq */ }; /* Virtual function table for plugging in SigComp */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h index f6f2f5a7ac..ca921674d1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta.h @@ -299,6 +299,9 @@ int nta_incoming_complete_response(nta_incoming_t *irq, char const *phrase, tag_type_t tag, tag_value_t value, ...); +SOFIAPUBFUN +msg_t *nta_incoming_create_response(nta_incoming_t *irq, int status, char const *phrase); + SOFIAPUBFUN int nta_incoming_treply(nta_incoming_t *ireq, int status, char const *phrase, diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h index 6cc8f8f6d0..eaeee457c7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h @@ -464,43 +464,43 @@ NTA_DLL extern tag_typedef_t ntatag_rseq_ref; /* Tags for statistics. */ NTA_DLL extern tag_typedef_t ntatag_s_irq_hash; -#define NTATAG_S_IRQ_HASH(x) ntatag_s_irq_hash, tag_uint_v(x) +#define NTATAG_S_IRQ_HASH(x) ntatag_s_irq_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_ref; -#define NTATAG_S_IRQ_HASH_REF(x) ntatag_s_irq_hash_ref, tag_uint_vr(&(x)) +#define NTATAG_S_IRQ_HASH_REF(x) ntatag_s_irq_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash; -#define NTATAG_S_ORQ_HASH(x) ntatag_s_orq_hash, tag_uint_v(x) +#define NTATAG_S_ORQ_HASH(x) ntatag_s_orq_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_ref; -#define NTATAG_S_ORQ_HASH_REF(x) ntatag_s_orq_hash_ref, tag_uint_vr(&(x)) +#define NTATAG_S_ORQ_HASH_REF(x) ntatag_s_orq_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash; -#define NTATAG_S_LEG_HASH(x) ntatag_s_leg_hash, tag_uint_v(x) +#define NTATAG_S_LEG_HASH(x) ntatag_s_leg_hash, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_ref; -#define NTATAG_S_LEG_HASH_REF(x) ntatag_s_leg_hash_ref, tag_uint_vr(&(x)) +#define NTATAG_S_LEG_HASH_REF(x) ntatag_s_leg_hash_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_used; -#define NTATAG_S_IRQ_HASH_USED(x) ntatag_s_irq_hash_used, tag_uint_v(x) +#define NTATAG_S_IRQ_HASH_USED(x) ntatag_s_irq_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_used_ref; #define NTATAG_S_IRQ_HASH_USED_REF(x) \ -ntatag_s_irq_hash_used_ref, tag_uint_vr(&(x)) +ntatag_s_irq_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_used; -#define NTATAG_S_ORQ_HASH_USED(x) ntatag_s_orq_hash_used, tag_uint_v(x) +#define NTATAG_S_ORQ_HASH_USED(x) ntatag_s_orq_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_used_ref; #define NTATAG_S_ORQ_HASH_USED_REF(x) \ -ntatag_s_orq_hash_used_ref, tag_uint_vr(&(x)) +ntatag_s_orq_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used; -#define NTATAG_S_LEG_HASH_USED(x) ntatag_s_leg_hash_used, tag_uint_v(x) +#define NTATAG_S_LEG_HASH_USED(x) ntatag_s_leg_hash_used, tag_usize_v(x) NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used_ref; #define NTATAG_S_LEG_HASH_USED_REF(x) \ -ntatag_s_leg_hash_used_ref, tag_uint_vr(&(x)) +ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x)) NTA_DLL extern tag_typedef_t ntatag_s_recv_msg; #define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_uint_v(x) diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c index 0ac9be30ac..75f54a6f77 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c @@ -654,7 +654,7 @@ int readfile(FILE *f, void **contents) *contents = buffer; - return len; + return (int)len; } #if HAVE_DIRENT_H diff --git a/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.am index df670a55ef..6117959c58 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.am @@ -63,4 +63,4 @@ EXTRA_DIST = Doxyfile nth.docs $(BUILT_SOURCES) \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am diff --git a/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.in index c97ead7b27..8ed84abdc1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/nth/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libnth_la_SOURCES) http-client.c http-server.c test_nth.c @@ -55,8 +80,12 @@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_nth$(EXEEXT) http-client$(EXEEXT) \ http-server$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/nth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -125,6 +154,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -171,8 +201,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -216,6 +250,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -314,7 +349,7 @@ test_nth_LDFLAGS = -static EXTRA_DIST = Doxyfile nth.docs $(BUILT_SOURCES) \ agent.pem cafile.pem -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -340,12 +375,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -588,7 +625,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -739,6 +776,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/nth/http-server.c b/libs/sofia-sip/libsofia-sip-ua/nth/http-server.c index 13b058b81f..db359db234 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nth/http-server.c +++ b/libs/sofia-sip/libsofia-sip-ua/nth/http-server.c @@ -38,7 +38,10 @@ #include #include #include + +#if HAVE_SIGNAL #include +#endif typedef struct context_s context_t; #define NTH_SITE_MAGIC_T context_t @@ -77,7 +80,10 @@ static int request(context_t *context, http_t const *http, char const *path); su_msg_r server_intr_msg = SU_MSG_R_INIT; + +#if HAVE_SIGNAL static RETSIGTYPE server_intr_handler(int signum); +#endif static void server_break(context_t *c, su_msg_r msg, su_msg_arg_t *arg); static msg_payload_t *read_payload(su_home_t *home, char const *fname); @@ -140,12 +146,12 @@ int main(int argc, char *argv[]) su_root_task(context->c_root), server_break, 0); +#if HAVE_SIGNAL signal(SIGINT, server_intr_handler); - -#ifndef _WIN32 - signal(SIGPIPE, server_intr_handler); +#if HAVE_SIGQUIT signal(SIGQUIT, server_intr_handler); signal(SIGHUP, server_intr_handler); +#endif #endif if (context->c_root) { diff --git a/libs/sofia-sip/libsofia-sip-ua/nth/nth_client.c b/libs/sofia-sip/libsofia-sip-ua/nth/nth_client.c index 52a1fd5db1..94e35d57b5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nth/nth_client.c +++ b/libs/sofia-sip/libsofia-sip-ua/nth/nth_client.c @@ -1094,7 +1094,7 @@ int hc_reply(nth_client_t * hc, int status, char const *phrase) assert(status >= 400); - SU_DEBUG_5(("nth: hc_reply(%p, %u, %s)\n", hc, status, phrase)); + SU_DEBUG_5(("nth: hc_reply(%p, %u, %s)\n", (void *)hc, status, phrase)); if (hc->hc_pending) { tport_release(hc->hc_tport, hc->hc_pending, hc->hc_request, NULL, hc, diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am index 49b512c51a..7e42f91986 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.am @@ -96,6 +96,6 @@ EXTRA_DIST = Doxyfile nua.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = LIST=nua_tag_list diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.in index 1106498ba3..b489861d4e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/nua/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libnua_la_SOURCES) $(test_nua_SOURCES) @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_nua$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/nua ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -120,6 +149,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -166,8 +196,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -211,6 +245,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -341,7 +376,7 @@ test_nua_SOURCES = test_nua.c test_nua.h test_ops.c \ # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile nua.docs $(BUILT_SOURCES) -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -367,6 +402,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -376,7 +413,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -643,7 +680,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -794,6 +831,92 @@ clean-built-sources: ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua.c index a1e75fa0c8..07140603c9 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua.c @@ -67,7 +67,7 @@ char const nua_version[] = VERSION; * * The NUA_DEBUG environment variable is used to determine the debug logging * level for @nua module. The default level is 3. - * + * * @sa , nua_log, SOFIA_DEBUG */ extern char const NUA_DEBUG[]; @@ -76,8 +76,8 @@ extern char const NUA_DEBUG[]; #define SU_DEBUG 3 #endif -/**Debug log for @nua module. - * +/**Debug log for @nua module. + * * The nua_log is the log object used by @nua module. The level of * #nua_log is set using #NUA_DEBUG environment variable. */ @@ -104,16 +104,17 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) }; * NUTAG_UICC() \n * NUTAG_CERTIFICATE_DIR() \n * and all tags listed in nua_set_params(), \n - * and all relevant NTATAG_* are passed to NTA. + * and all relevant NTATAG_* are passed to NTA \n + * and all tport tags listed in * * @note - * From the @VERSION_1_12_2 all the nua_set_params() tags are processed. + * From the @VERSION_1_12_2 all the nua_set_params() tags are processed. * Previously all nutags except NUTAG_SOA_NAME() and NUTAG_MEDIA_ENABLE() * were ignored. * * @note * Both the NUTAG_URL() and NUTAG_SIPS_URL() are used to pass arguments to - * nta_agent_add_tport(). + * nta_agent_add_tport(). * * @par Events: * none @@ -187,9 +188,9 @@ void nua_shutdown(nua_t *nua) /** Destroy the @nua stack. * - * Before calling nua_destroy() the application + * Before calling nua_destroy() the application * should call nua_shutdown and wait for successful #nua_r_shutdown event. - * Shuts down and destroys the @nua stack. Ongoing calls, registrations, + * Shuts down and destroys the @nua stack. Ongoing calls, registrations, * and subscriptions are left as they are. * * @param nua Pointer to @nua stack object @@ -211,7 +212,8 @@ void nua_destroy(nua_t *nua) if (nua) { if (!nua->nua_shutdown_final) { - SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n", nua)); + SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n", + (void *)nua)); assert(nua->nua_shutdown); return; } @@ -242,7 +244,7 @@ nua_magic_t *nua_magic(nua_t *nua) /** Obtain default operation handle of the @nua stack object. * - * A default operation can be used for operations where the + * A default operation can be used for operations where the * ultimate result is not important or can be discarded. * * @param nua Pointer to @nua stack object @@ -262,7 +264,7 @@ nua_handle_t *nua_default(nua_t *nua) return nua ? nua->nua_handles : NULL; } -/** Create an operation handle +/** Create an operation handle * * Allocates a new operation handle and associated storage. * @@ -275,7 +277,7 @@ nua_handle_t *nua_default(nua_t *nua) * * @par Related tags: * Duplicates the provided tags for use with every operation. Note that - * NUTAG_URL() is converted to SIPTAG_TO() if there is no SIPTAG_TO(). + * NUTAG_URL() is converted to SIPTAG_TO() if there is no SIPTAG_TO(). * And also vice versa, request-URI is taken from SIPTAG_TO() if there * is no NUTAG_URL(). Note that certain SIP headers cannot be saved with * the handle. They include @ContentLength, @CSeq, @RSeq, @RAck, and @@ -302,7 +304,7 @@ nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic, ta_start(ta, tag, value); nh = nh_create_handle(nua, hmagic, ta_args(ta)); - + if (nh) nh->nh_ref_by_user = 1; @@ -312,7 +314,7 @@ nua_handle_t *nua_handle(nua_t *nua, nua_hmagic_t *hmagic, return nh; } -/** Bind a callback context to an operation handle. +/** Bind a callback context to an operation handle. * * @param nh Pointer to operation handle * @param hmagic Pointer to callback context @@ -334,7 +336,7 @@ void nua_handle_bind(nua_handle_t *nh, nua_hmagic_t *hmagic) nh->nh_magic = hmagic; } -/** Fetch a callback context from an operation handle. +/** Fetch a callback context from an operation handle. * * @param nh Pointer to operation handle * @@ -356,7 +358,7 @@ nua_hmagic_t *nua_handle_magic(nua_handle_t *nh) if (NH_IS_VALID(nh)) magic = nh->nh_magic; - + return magic; } @@ -369,8 +371,8 @@ nua_hmagic_t *nua_handle_magic(nua_handle_t *nh) * * @param nh Pointer to operation handle * - * @retval 0 no invite in operation or operation handle is invalid - * @retval 1 operation has invite + * @retval 0 no invite in operation or operation handle is invalid + * @retval 1 operation has invite * * @par Related tags: * none @@ -383,15 +385,15 @@ int nua_handle_has_invite(nua_handle_t const *nh) return nh ? nh->nh_has_invite : 0; } -/**Check if operation handle has active event subscriptions. +/**Check if operation handle has active event subscriptions. * * Active subscription can be established either by nua_subscribe() or * nua_refer() calls. * * @param nh Pointer to operation handle * - * @retval 0 no event subscriptions in operation or - * operation handle is invalid + * @retval 0 no event subscriptions in operation or + * operation handle is invalid * @retval !=0 operation has event subscriptions * * @par Related tags: @@ -416,7 +418,7 @@ int nua_handle_has_events(nua_handle_t const *nh) * * @param nh Pointer to operation handle * - * @retval 0 no active registration in operation or + * @retval 0 no active registration in operation or * operation handle is invalid * @retval 1 operation has registration * @@ -433,12 +435,12 @@ int nua_handle_has_registrations(nua_handle_t const *nh) return nh && nh->nh_ds->ds_has_register; } -/** Check if operation handle has been used with outgoing SUBSCRIBE of REFER request. +/** Check if operation handle has been used with outgoing SUBSCRIBE of REFER request. * * @param nh Pointer to operation handle * - * @retval 0 no active subscription in operation or - * operation handle is invalid + * @retval 0 no active subscription in operation or + * operation handle is invalid * @retval 1 operation has subscription. * * @par Related tags: @@ -470,7 +472,7 @@ int nua_handle_has_register(nua_handle_t const *nh) return nh ? nh->nh_has_register : 0; } -/** Check if operation handle has an active call +/** Check if operation handle has an active call * * @param nh Pointer to operation handle * @@ -488,17 +490,17 @@ int nua_handle_has_active_call(nua_handle_t const *nh) return nh ? nh->nh_active_call : 0; } -/** Check if operation handle has a call on hold +/** Check if operation handle has a call on hold * - * Please note that this status is not affected by remote end putting - * this end on hold. Remote end can put each media separately on hold - * and status is reflected on SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO() + * Please note that this status is not affected by remote end putting + * this end on hold. Remote end can put each media separately on hold + * and status is reflected on SOATAG_ACTIVE_AUDIO(), SOATAG_ACTIVE_VIDEO() * and SOATAG_ACTIVE_CHAT() tag values in #nua_i_state event. * * @param nh Pointer to operation handle * - * @retval 0 if no call on hold in operation or operation handle is invalid - * @retval 1 if operation has call on hold, for example nua_invite() or + * @retval 0 if no call on hold in operation or operation handle is invalid + * @retval 1 if operation has call on hold, for example nua_invite() or * nua_update() has been called with SOATAG_HOLD() with non-NULL * argument. * @@ -515,14 +517,14 @@ int nua_handle_has_call_on_hold(nua_handle_t const *nh) /** Get the remote address (From/To header) of operation handle * - * Remote address is used as To header in outgoing operations and + * Remote address is used as To header in outgoing operations and * derived from From: header in incoming operations. * * @param nh Pointer to operation handle * * @retval NULL no remote address for operation or operation handle invalid * @retval !=NULL pointer to remote address for operation - * + * * @par Related tags: * none * @@ -536,14 +538,14 @@ sip_to_t const *nua_handle_remote(nua_handle_t const *nh) /** Get the local address (From/To header) of operation handle * - * Local address is used as From header in outgoing operations and + * Local address is used as From header in outgoing operations and * derived from To: header in incoming operations. * * @param nh Pointer to operation handle * * @retval NULL no local address for operation or operation handle invalid * @retval !=NULL pointer to local address for operation - * + * * @par Related tags: * none * @@ -590,7 +592,7 @@ void nua_get_params(nua_t *nua, tag_type_t tag, tag_value_t value, ...) ta_end(ta); \ } \ else { \ - SU_DEBUG_1(("nua: " #event " with invalid handle %p\n", nh)); \ + SU_DEBUG_1(("nua: " #event " with invalid handle %p\n", (void *)nh)); \ } /* Documented with nua_stack_set_params() */ @@ -658,18 +660,18 @@ void nua_method(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) NUA_SIGNAL(nh, nua_r_method, tag, value); } -/** Send a chat message. +/** Send a chat message. * - * A chat channel can be established during call setup using "message" media. - * An active chat channel is indicated using #nua_i_state event containing - * SOATAG_ACTIVE_CHAT() tag. Chat messages can be sent using this channel with - * nua_chat() function. Currently this is implemented using SIP MESSAGE + * A chat channel can be established during call setup using "message" media. + * An active chat channel is indicated using #nua_i_state event containing + * SOATAG_ACTIVE_CHAT() tag. Chat messages can be sent using this channel with + * nua_chat() function. Currently this is implemented using SIP MESSAGE * requests but in future MSRP (message session protocol) will replace it. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * - * @return + * @return * nothing * * @par Related Tags: @@ -707,18 +709,18 @@ void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) /* nua_r_notify is documented with process_response_to_notify() */ -/** Create an event server. +/** Create an event server. * - * This function create an event server taking care of sending NOTIFY - * requests and responding to further SUBSCRIBE requests. The event - * server can accept multiple subscriptions from several sources and - * takes care for distributing the notifications. Unlike other functions + * This function create an event server taking care of sending NOTIFY + * requests and responding to further SUBSCRIBE requests. The event + * server can accept multiple subscriptions from several sources and + * takes care for distributing the notifications. Unlike other functions * this call only accepts the SIP tags listed below. * * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * - * @return + * @return * nothing * * @par Related Tags: @@ -736,7 +738,7 @@ void nua_notifier(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) NUA_SIGNAL(nh, nua_r_notifier, tag, value); } -/** Terminate an event server. +/** Terminate an event server. * * Terminate an event server with matching event and content type. The event * server was created earlier with nua_notifier() function. @@ -744,7 +746,7 @@ void nua_notifier(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * - * @return + * @return * nothing * * @par Related Tags: @@ -809,7 +811,7 @@ void nua_update(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * - * @return + * @return * nothing * * @par Related Tags: @@ -827,7 +829,7 @@ void nua_authenticate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) * * After creating a local presence server by nua_notifier(), an incoming * SUBSCRIBE request causes #nua_i_subscription event. Each subscriber is - * identified with NEATAG_SUB() tag in the #nua_i_subscription event. + * identified with NEATAG_SUB() tag in the #nua_i_subscription event. * Application can either authorize the subscriber with * NUTAG_SUBSTATE(#nua_substate_active) or terminate the subscription with * NUTAG_SUBSTATE(#nua_substate_terminated). @@ -835,7 +837,7 @@ void nua_authenticate(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...) * @param nh Pointer to operation handle * @param tag, value, ... List of tagged parameters * - * @return + * @return * nothing * * @par Related Tags: @@ -875,11 +877,11 @@ void nua_respond(nua_handle_t *nh, ta_end(ta); } else { - SU_DEBUG_1(("nua: respond with invalid handle %p\n", nh)); + SU_DEBUG_1(("nua: respond with invalid handle %p\n", (void *)nh)); } } -/** Destroy a handle +/** Destroy a handle * * Terminate the protocol state associated with an operation handle. The * stack discards resources and terminates the ongoing dialog usage, @@ -893,7 +895,7 @@ void nua_respond(nua_handle_t *nh, * * @param nh Pointer to operation handle * - * @return + * @return * nothing * * @par Related Tags: @@ -954,11 +956,14 @@ void nua_signal(nua_t *nua, nua_handle_t *nh, msg_t *msg, int always, e->e_status = status; e->e_phrase = phrase; - if (su_msg_send(sumsg) != 0) + SU_DEBUG_7(("nua(%p): signal %s\n", (void *)nh, + nua_event_name(event) + 4)); + + if (su_msg_send(sumsg) != 0 && event != nua_r_destroy) nua_handle_unref(nh); - } + } else { - /* XXX - we should return error code to application */ + /* XXX - we should return error code to application but we just abort() */ assert(ENOMEM == 0); } @@ -981,8 +986,16 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e) } if (!nh || !nh->nh_valid) { /* Handle has been destroyed */ + if (nua_log->log_level >= 7) { + char const *name = nua_event_name(e->e_event) + 4; + SU_DEBUG_7(("nua(%p): event %s dropped\n", (void *)nh, name)); + } if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { - SU_DEBUG_9(("nua(%p): freed by application\n", nh)); +#if HAVE_NUA_HANDLE_DEBUG + SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh)); +#else + SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); +#endif } if (e->e_msg) msg_destroy(e->e_msg), e->e_msg = NULL; @@ -1011,7 +1024,11 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e) e->e_tags); if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { - SU_DEBUG_9(("nua(%p): freed by application\n", nh)); +#if HAVE_NUA_HANDLE_DEBUG + SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh)); +#else + SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); +#endif } if (!su_msg_is_non_null(nua->nua_current)) @@ -1066,7 +1083,7 @@ void nua_destroy_event(nua_saved_event_t saved[1]) msg_destroy(e->e_msg), e->e_msg = NULL; if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) { - SU_DEBUG_9(("nua(%p): freed by application\n", nh)); + SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh)); } su_msg_destroy(saved); @@ -1093,21 +1110,36 @@ static int nua_stack_handle_make_replaces_call(void *arg) /**Generate a @Replaces header for handle. + * + * A @Replaces header contains the @CallID value, @From and @To tags + * corresponding to SIP dialog associated with handle @a nh. Note that the + * @Replaces matches with dialog of the remote peer, + * nua_handle_by_replaces() does not return same handle (unless you swap + * rp_from_tag and rp_to_tag in @Replaces header). + * + * A @Replaces header is used in attended transfer, among other things. + * + * @param nh pointer to operation handle + * @param home memory home used to allocate the header + * @param early_only if true, include "early-only" parameter in @Replaces, too + * + * @return A newly created @Replaces header. * * @since New in @VERSION_1_12_4. * - * @sa nua_handle_by_replaces(), @Replaces, @RFC3891, nua_refer(), - * #nua_i_refer, @ReferTo, nta_leg_make_replaces() + * @sa nua_handle_by_replaces(), @Replaces, @RFC3891, @RFC3515, nua_refer(), + * #nua_i_refer(), @ReferTo, nta_leg_make_replaces(), + * sip_headers_as_url_query() */ -sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh, +sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh, su_home_t *home, int early_only) { if (nh && nh->nh_valid && nh->nh_nua) { struct nua_stack_handle_make_replaces_args a = { NULL, nh, home, early_only }; - if (su_task_execute(nh->nh_nua->nua_server, - nua_stack_handle_make_replaces_call, (void *)&a, + if (su_task_execute(nh->nh_nua->nua_server, + nua_stack_handle_make_replaces_call, (void *)&a, NULL) == 0) { return a.retval; } @@ -1134,9 +1166,9 @@ static int nua_stack_handle_by_replaces_call(void *arg) * * @since New in @VERSION_1_12_4. * - * @note + * @note * You should release the reference with nua_handle_unref() when you are - * done with handle. + * done with the handle. * * @sa nua_handle_make_replaces(), @Replaces, @RFC3891, nua_refer(), * #nua_i_refer, @ReferTo, nta_leg_by_replaces() @@ -1146,8 +1178,8 @@ nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *r) if (nua) { struct nua_stack_handle_by_replaces_args a = { NULL, nua, r }; - if (su_task_execute(nua->nua_server, - nua_stack_handle_by_replaces_call, (void *)&a, + if (su_task_execute(nua->nua_server, + nua_stack_handle_by_replaces_call, (void *)&a, NULL) == 0) { nua_handle_t *nh = a.retval; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua.docs b/libs/sofia-sip/libsofia-sip-ua/nua/nua.docs index f259e78afb..1e9937cde0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua.docs +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua.docs @@ -1124,7 +1124,7 @@ follows: terminating Process answer - If there was an failure in SDP negotiation or other failure with media, + If there was a failure in SDP negotiation or other failure with media, the stack will automatically terminate the call. The BYE follows immediatelhy after the ACK. @@ -1262,7 +1262,7 @@ does not include the extensions like @b 100rel or @b UPDATE. | +---------------| | : | : | | +------------+ : | : | | | : | : - | | nua_respond/18X (2) : | : + | | nua_respond/18X (2a) : | : | | | : | : | | V V | : | | +------------+ | : @@ -2219,7 +2219,7 @@ NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side. * @param nh operation handle associated with the notifier * @param hmagic operation magic associated with the notifier * @param sip response to MESSAGE request or NULL upon an error - * (error code and message are in status an phrase parameters) + * (error code and message are in status and phrase parameters) * @param tags empty * * @sa nua_chat(), #nua_r_message diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c index f979ccc800..08db9ddf04 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c @@ -110,13 +110,14 @@ nua_handle_t *nh_create_handle(nua_t *nua, assert(nua->nua_home); if ((nh = su_home_clone(nua->nua_home, sizeof(*nh)))) { - nh->nh_valid = nua_handle; + nh->nh_valid = nua_valid_handle_cookie; nh->nh_nua = nua; nh->nh_magic = hmagic; nh->nh_prefs = nua->nua_dhandle->nh_prefs; if (nua_handle_save_tags(nh, tags) < 0) { - SU_DEBUG_5(("nua(%p): creating handle %p failed\n", nua, nh)); + SU_DEBUG_5(("nua(%p): creating handle %p failed\n", + (void *)nua, (void *)nh)); su_home_unref(nh->nh_home), nh = NULL; } @@ -136,7 +137,7 @@ nua_handle_t *nh_create_handle(nua_t *nua, } else { _handle_lifetime = 2; - SU_DEBUG_0(("nh_handle_create(%p)\n", nh)); + SU_DEBUG_0(("nh_handle_create(%p)\n", (void *)nh)); su_home_destructor(nh->nh_home, nh_destructor); } } @@ -159,10 +160,12 @@ extern char const _NUA_HANDLE_DEBUG[]; static void nh_destructor(void *arg) { nua_handle_t *nh = arg; - - SU_DEBUG_0(("nh_destructor(%p)\n", nh)); + SU_DEBUG_0(("nh_destructor(%p)\n", (void *)nh)); } +#undef nua_handle_ref +#undef nua_handle_unref + /** Make a new reference to handle. * * The handles use reference counting for memory management. In addition to @@ -180,7 +183,6 @@ nua_handle_t *nua_handle_ref(nua_handle_t *nh) return (nua_handle_t *)su_home_ref(nh->nh_home); } - /** Destroy reference to handle. * * The handles use reference counting for memory management. In addition to @@ -301,3 +303,34 @@ char const *nua_callstate_name(enum nua_callstate state) default: return "UNKNOWN"; } } + +/** Return name of subscription state. @NEW_1_12_5. */ +char const *nua_substate_name(enum nua_substate substate) +{ + switch (substate) { + case nua_substate_embryonic: + /*FALLTHROUGH*/ + case nua_substate_pending: + return "pending"; + case nua_substate_terminated: + return "terminated"; + case nua_substate_active: + /*FALLTHROUGH*/ + default: + return "active"; + } +} + +/** Convert string to enum nua_substate. @NEW_1_12_5. */ +enum nua_substate nua_substate_make(char const *sip_substate) +{ + if (sip_substate == NULL) + return nua_substate_active; + else if (strcasecmp(sip_substate, "terminated") == 0) + return nua_substate_terminated; + else if (strcasecmp(sip_substate, "pending") == 0) + return nua_substate_pending; + else /* if (strcasecmp(sip_substate, "active") == 0) */ + return nua_substate_active; +} + diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c index 781c89ef3f..dcb8aa6f70 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c @@ -269,7 +269,7 @@ nua_dialog_usage_t *nua_dialog_usage_add(nua_owner_t *own, du = *prev_du; if (du) { /* Already exists */ SU_DEBUG_5(("nua(%p): adding already existing %s usage%s%s\n", - own, nua_dialog_usage_name(du), + (void *)own, nua_dialog_usage_name(du), event ? " with event " : "", event ? event->o_type : "")); if (prev_du != &ds->ds_usage) { @@ -297,7 +297,7 @@ nua_dialog_usage_t *nua_dialog_usage_add(nua_owner_t *own, } SU_DEBUG_5(("nua(%p): adding %s usage%s%s\n", - own, nua_dialog_usage_name(du), + (void *)own, nua_dialog_usage_name(du), o ? " with event " : "", o ? o->o_type :"")); su_home_ref(own); @@ -345,6 +345,15 @@ void nua_dialog_usage_remove_at(nua_owner_t *own, nua_client_request_t *cr, *cr_next; nua_server_request_t *sr, *sr_next; + /* Destroy saved client request */ + if (nua_client_is_bound(du->du_cr)) { + nua_client_bind(cr = du->du_cr, NULL); + if (!nua_client_is_queued(cr) && + !nua_client_is_reporting(cr)) + nua_client_request_destroy(cr); + } + + /* Clean references from queued client requests */ for (cr = ds->ds_cr; cr; cr = cr_next) { cr_next = cr->cr_next; if (cr->cr_usage == du) @@ -362,10 +371,9 @@ void nua_dialog_usage_remove_at(nua_owner_t *own, o = du->du_event; SU_DEBUG_5(("nua(%p): removing %s usage%s%s\n", - own, nua_dialog_usage_name(du), + (void *)own, nua_dialog_usage_name(du), o ? " with event " : "", o ? o->o_type :"")); du->du_class->usage_remove(own, ds, du); - msg_destroy(du->du_msg), du->du_msg = NULL; su_home_unref(own); su_free(own, du); } @@ -412,7 +420,7 @@ void nua_dialog_log_usage(nua_owner_t *own, nua_dialog_state_t *ds) } } - SU_DEBUG_3(("nua(%p): handle with %s%s%s\n", own, + SU_DEBUG_3(("nua(%p): handle with %s%s%s\n", (void *)own, ds->ds_has_session ? "session and " : "", ds->ds_has_events ? "events " : "", buffer)); @@ -430,12 +438,11 @@ void nua_dialog_deinit(nua_owner_t *own, /** @internal Dialog has been terminated. Remove all usages. */ -void nua_dialog_terminated(nua_owner_t *own, - struct nua_dialog_state *ds, - int status, - char const *phrase) +void nua_dialog_remove_usages(nua_owner_t *own, + struct nua_dialog_state *ds, + int status, + char const *phrase) { - ds->ds_terminated = 1; while (ds->ds_usage) { @@ -449,6 +456,8 @@ void nua_dialog_terminated(nua_owner_t *own, #endif nua_dialog_usage_remove_at(own, ds, &ds->ds_usage); } + + nua_dialog_remove(own, ds, NULL); } /**@internal @@ -524,7 +533,8 @@ void nua_dialog_usage_refresh_range(nua_dialog_usage_t *du, /**@internal Do not refresh. */ void nua_dialog_usage_reset_refresh(nua_dialog_usage_t *du) { - du->du_refresh = 0; + if (du) + du->du_refresh = 0; } /** @internal Refresh usage or shutdown usage if @a now is 0. */ @@ -537,18 +547,43 @@ void nua_dialog_usage_refresh(nua_owner_t *owner, du->du_refresh = 0; if (now > 0) { - if (du->du_class->usage_refresh) { - du->du_class->usage_refresh(owner, ds, du, now); - return; - } + assert(du->du_class->usage_refresh); + du->du_class->usage_refresh(owner, ds, du, now); } else { du->du_shutdown = 1; - if (du->du_class->usage_shutdown) { - du->du_class->usage_shutdown(owner, ds, du); - return; - } + assert(du->du_class->usage_shutdown); + du->du_class->usage_shutdown(owner, ds, du); } } } +/** Terminate all dialog usages gracefully. */ +int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds) +{ + nua_dialog_usage_t *du; + + do { + for (du = ds->ds_usage; du; du = du->du_next) { + if (!du->du_shutdown) { + nua_dialog_usage_shutdown(owner, ds, du); + break; + } + } + } while (du); + + return 1; +} + +/** (Gracefully) terminate usage */ +void nua_dialog_usage_shutdown(nua_owner_t *owner, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du) +{ + if (du) { + du->du_refresh = 0; + du->du_shutdown = 1; + assert(du->du_class->usage_shutdown); + du->du_class->usage_shutdown(owner, ds, du); + } +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h index 2a23e56ea2..3c852b0b22 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h @@ -48,36 +48,72 @@ typedef NUA_OWNER_T nua_owner_t; #include #endif +typedef su_msg_r nua_saved_signal_t; + typedef struct nua_server_request nua_server_request_t; typedef struct nua_client_request nua_client_request_t; -/** Respond to an incoming request. */ -typedef int nua_server_respond_f(nua_server_request_t *, tagi_t const *); +typedef struct { + sip_method_t sm_method; + char const *sm_method_name; -/** Restart an outgoing request. */ -typedef void nua_creq_restart_f(nua_owner_t *, tagi_t *tags); + int sm_event; + + struct { + unsigned create_dialog:1, in_dialog:1, target_refresh:1, add_contact:1; + unsigned :0; + } sm_flags; + + /** Initialize server-side request. */ + int (*sm_init)(nua_server_request_t *sr); + + /** Preprocess server-side request (after handle has been created). */ + int (*sm_preprocess)(nua_server_request_t *sr); + + /** Update server-side request parameters */ + int (*sm_params)(nua_server_request_t *sr, tagi_t const *tags); + + /** Respond to server-side request. */ + int (*sm_respond)(nua_server_request_t *sr, tagi_t const *tags); + + /** Report server-side request to application. */ + int (*sm_report)(nua_server_request_t *sr, tagi_t const *tags); + +} nua_server_methods_t; /** Server side transaction */ struct nua_server_request { struct nua_server_request *sr_next, **sr_prev; + nua_server_methods_t const *sr_methods; + nua_owner_t *sr_owner; /**< Backpointer to handle */ nua_dialog_usage_t *sr_usage; /**< Backpointer to usage */ - /** When the application responds to an request with - * nua_respond(), the sr_respond() is called - */ - nua_server_respond_f *sr_respond; - nta_incoming_t *sr_irq; /**< Server transaction object */ - msg_t *sr_msg; /**< Request message */ + + struct { + msg_t *msg; /**< Request message */ + sip_t const *sip; /**< Headers in request message */ + } sr_request; + + struct { + msg_t *msg; /**< Response message */ + sip_t *sip; /**< Headers in response message */ + } sr_response; sip_method_t sr_method; /**< Request method */ + + int sr_application; /**< Status by application */ + int sr_status; /**< Status code */ char const *sr_phrase; /**< Status phrase */ - unsigned sr_auto:1; /**< Autoresponse - no event has been sent */ + unsigned sr_event:1; /**< Reported to application */ unsigned sr_initial:1; /**< Handle was created by this request */ + unsigned sr_add_contact:1; /**< Add Contact header to the response */ + unsigned sr_terminating:1; /**< Terminate usage after final response */ + unsigned sr_gracefully:1; /**< Terminate usage gracefully */ /* Flags used with offer-answer */ unsigned sr_offer_recv:1; /**< We have received an offer */ @@ -85,12 +121,11 @@ struct nua_server_request { unsigned sr_offer_sent:1; /**< We have offered SDP */ unsigned sr_answer_recv:1; /**< We have received SDP answer */ -}; + unsigned :0; -#define SR_INIT(sr) \ - ((void)memset((sr), 0, sizeof (sr)[0]), \ - (void)(SR_STATUS1((sr), SIP_100_TRYING)), \ - sr) + char const *sr_sdp; /**< SDP received from client */ + size_t sr_sdp_len; /**< ... and its length */ +}; #define SR_STATUS(sr, status, phrase) \ ((sr)->sr_phrase = (phrase), (sr)->sr_status = (status)) @@ -104,37 +139,177 @@ int sr_status(nua_server_request_t *sr, int status, char const *phrase) return (void)(sr->sr_phrase = phrase), (sr->sr_status = status); } +/** Methods for client request */ +typedef struct { + sip_method_t crm_method; + char const *crm_method_name; + size_t crm_extra; /**< Size of private data */ + + struct { + unsigned create_dialog:1, in_dialog:1, target_refresh:1; + unsigned:0; + } crm_flags; + + /** Generate a request message. + * + * @retval 1 when request message has been created + * @retval 0 when request message should be created in normal fashion + * @retval -1 upon an error + */ + int (*crm_template)(nua_client_request_t *cr, + msg_t **return_msg, + tagi_t const *tags); + + /**@a crm_init is called when a client request is sent first time. + * + * @retval 1 when request has been responded + * @retval 0 when request should be sent in normal fashion + * @retval -1 upon an error + */ + int (*crm_init)(nua_client_request_t *, msg_t *msg, sip_t *sip, + tagi_t const *tags); + + /** @a crm_send is called each time when a client request is sent. + * + * @retval 1 when request has been responded + * @retval 0 when request has been sent + * @retval -1 upon an error (request message has not been destroyed) + * @retval -2 upon an error (request message has been destroyed) + */ + int (*crm_send)(nua_client_request_t *, + msg_t *msg, sip_t *sip, + tagi_t const *tags); + + /** @a crm_check_restart is called each time when a response is received. + * + * It is used to restart reqquest after responses with method-specific + * status code or method-specific way of restarting the request. + * + * @retval 1 when request has been restarted + * @retval 0 when response should be processed normally + */ + int (*crm_check_restart)(nua_client_request_t *, + int status, char const *phrase, + sip_t const *sip); + + /** @a crm_recv is called each time a final response is received. + * + * A final response is in range 200 .. 699 (or internal response) and it + * cannot be restarted. + * + * crm_recv() should call nua_base_client_response() or + * nua_base_client_tresponse(). The return values below are documented with + * nua_base_client_response(), too. + * + * @retval 0 if response was preliminary + * @retval 1 if response was final + * @retval 2 if response destroyed the handle, too. + */ + int (*crm_recv)(nua_client_request_t *, + int status, char const *phrase, + sip_t const *sip); + + /** @a crm_preliminary is called each time a preliminary response is received. + * + * A preliminary response is in range 101 .. 199. + * + * crm_preliminary() should call nua_base_client_response() or + * nua_base_client_tresponse(). + * + * @retval 0 if response was preliminary + * @retval 1 if response was final + * @retval 2 if response destroyed the handle, too. + */ + int (*crm_preliminary)(nua_client_request_t *, + int status, char const *phrase, + sip_t const *sip); + + /** @a crm_report is called each time a response is received and it is + * reported to the application. + * + * The status and phrase may be different from the status and phrase + * received from the network, e.g., when the request is restarted. + * + * @return The return value should be 0. It is currently ignored. + */ + int (*crm_report)(nua_client_request_t *, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + + /** @a crm_deinit is called when a client-side request is destroyed. + * + * @return The return value should be 0. It is currently ignored. + */ + int (*crm_deinit)(nua_client_request_t *); + +} nua_client_methods_t; + +/* Client-side request. Documented by nua_client_create() */ struct nua_client_request { - nua_client_request_t *cr_next; /**< Linked list of requests */ - /*nua_event_t*/ int cr_event; /**< Request event */ - nua_creq_restart_f *cr_restart; - nta_outgoing_t *cr_orq; - msg_t *cr_msg; + nua_client_request_t *cr_next, **cr_prev; /**< Linked list of requests */ + nua_owner_t *cr_owner; nua_dialog_usage_t *cr_usage; + + nua_saved_signal_t cr_signal; + tagi_t const *cr_tags; + + nua_client_methods_t const *cr_methods; + + msg_t *cr_msg; + sip_t *cr_sip; + + nta_outgoing_t *cr_orq; + + /*nua_event_t*/ int cr_event; /**< Request event */ + sip_method_t cr_method; + char const *cr_method_name; + + url_t *cr_target; + + uint32_t cr_seq; + + unsigned short cr_status; /**< Latest status */ + unsigned short cr_retry_count; /**< Retry count for this request */ /* Flags used with offer-answer */ unsigned short cr_answer_recv; /**< Recv answer in response * with this status. */ - unsigned cr_offer_sent:1; /**< Sent offer in this request */ + unsigned cr_offer_sent:1; /**< Sent offer in this request */ - unsigned cr_offer_recv:1; /**< Recv offer in a response */ - unsigned cr_answer_sent:1; /**< Sent answer in (PR)ACK */ + unsigned cr_offer_recv:1; /**< Recv offer in a response */ + unsigned cr_answer_sent:1; /**< Sent answer in (PR)ACK */ - unsigned cr_has_contact:1; /**< Request has application contact */ + /* Lifelong flags? */ + unsigned cr_auto:1; /**< Request was generated by stack */ + unsigned cr_has_contact:1; /**< Request has user Contact */ + unsigned cr_contactize:1; /**< Request needs Contact */ + + /* Current state */ + unsigned cr_challenged:1; /**< Request was challenged, pending auth */ + unsigned cr_restarting:1; /**< Request is being restarted */ + unsigned cr_reporting:1; /**< Reporting in progress */ + unsigned cr_terminating:1; /**< Request terminates the usage */ + signed int cr_terminated:2; /**< Response terminated usage (1) or + whole dialog (-1) */ + unsigned cr_graceful:1; /**< Graceful termination required */ }; struct nua_dialog_state { - nua_client_request_t ds_cr[1]; - nua_server_request_t *ds_sr; - /** Dialog usages. */ nua_dialog_usage_t *ds_usage; + /** Client requests */ + nua_client_request_t *ds_cr; + /** Server requests */ + nua_server_request_t *ds_sr; + /* Dialog and subscription state */ unsigned ds_route:1; /**< We have route */ unsigned ds_terminated:1; /**< Being terminated */ @@ -143,7 +318,7 @@ struct nua_dialog_state unsigned ds_has_register:1; /**< We have registration */ unsigned ds_has_publish:1; /**< We have publish */ - unsigned ds_has_referrals:1; /**< We have (or have had) referrals */ + unsigned ds_got_referrals:1; /**< We have (or have had) referrals */ unsigned :0; @@ -196,8 +371,8 @@ typedef struct { struct nua_dialog_usage { nua_dialog_usage_t *du_next; nua_usage_class const *du_class; + nua_client_request_t *du_cr; /**< Client request bound with usage */ - unsigned du_terminating:1; /**< Now trying to terminate usage */ unsigned du_ready:1; /**< Established usage */ unsigned du_shutdown:1; /**< Shutdown in progress */ unsigned:0; @@ -212,7 +387,6 @@ struct nua_dialog_usage { sip_event_t const *du_event; /**< Event of usage */ - msg_t *du_msg; /**< Template message */ }; void nua_dialog_uac_route(nua_owner_t *, nua_dialog_state_t *ds, @@ -243,10 +417,12 @@ void nua_dialog_usage_remove(nua_owner_t *, void nua_dialog_deinit(nua_owner_t *own, nua_dialog_state_t *ds); -void nua_dialog_terminated(nua_owner_t *, - struct nua_dialog_state *ds, - int status, - char const *phrase); +int nua_dialog_shutdown(nua_owner_t *owner, nua_dialog_state_t *ds); + +void nua_dialog_remove_usages(nua_owner_t *, + struct nua_dialog_state *ds, + int status, + char const *phrase); void nua_dialog_usage_set_expires(nua_dialog_usage_t *du, unsigned delta); @@ -262,6 +438,10 @@ void nua_dialog_usage_refresh(nua_owner_t *owner, nua_dialog_usage_t *du, sip_time_t now); +void nua_dialog_usage_shutdown(nua_owner_t *owner, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du); + static inline int nua_dialog_is_established(nua_dialog_state_t const *ds) { @@ -287,18 +467,166 @@ nua_dialog_usage_t *nua_dialog_usage_public(void const *p) /* ---------------------------------------------------------------------- */ -void nua_server_request_destroy(nua_server_request_t *sr); +int nua_client_create(nua_owner_t *owner, + int event, + nua_client_methods_t const *methods, + tagi_t const *tags); -int nua_server_respond(nua_server_request_t *sr, - int status, char const *phrase, +int nua_client_tcreate(nua_owner_t *nh, + int event, + nua_client_methods_t const *methods, tag_type_t tag, tag_value_t value, ...); -msg_t *nua_server_response(nua_server_request_t *sr, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...); +static inline +void *nua_private_client_request(nua_client_request_t const *cr) +{ + return (void *)(cr + 1); +} -int nua_default_respond(nua_server_request_t *sr, - tagi_t const *tags); +void nua_client_request_destroy(nua_client_request_t *); +int nua_client_request_queue(nua_client_request_t *cr); + +static inline int nua_client_is_queued(nua_client_request_t const *cr) +{ + return cr && cr->cr_prev; +} + +nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr); + +int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du); + +static inline int nua_client_is_bound(nua_client_request_t const *cr) +{ + return cr && cr->cr_usage && cr->cr_usage->du_cr == cr; +} + +static inline int nua_client_is_reporting(nua_client_request_t const *cr) +{ + return cr && cr->cr_reporting; +} + +/** Mark client request as a terminating one */ +static inline void nua_client_terminating(nua_client_request_t *cr) +{ + cr->cr_terminating = 1; +} + +int nua_client_init_request(nua_client_request_t *cr); + +int nua_client_resend_request(nua_client_request_t *cr, + int terminating, + tagi_t const *tags); + +int nua_base_client_request(nua_client_request_t *cr, + msg_t *msg, + sip_t *sip, + tagi_t const *tags); + +int nua_base_client_trequest(nua_client_request_t *cr, + msg_t *msg, + sip_t *sip, + tag_type_t tag, tag_value_t value, ...); + +extern nta_response_f nua_client_orq_response; + +int nua_client_return(nua_client_request_t *cr, + int status, + char const *phrase, + msg_t *to_be_destroyed); + +int nua_client_response(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip); + +int nua_client_check_restart(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip); + +int nua_base_client_check_restart(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip); + +int nua_client_restart(nua_client_request_t *cr, + int status, char const *phrase); + +int nua_base_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + tagi_t const *tags); + +int nua_base_client_tresponse(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + tag_type_t tag, tag_value_t value, ...); + +int nua_client_set_target(nua_client_request_t *cr, url_t const *target); + +int nua_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +nua_client_request_t *nua_client_request_pending(nua_client_request_t const *); + +/* ---------------------------------------------------------------------- */ + +extern nua_server_methods_t const + nua_extension_server_methods, + nua_invite_server_methods, /**< INVITE */ + nua_bye_server_methods, /**< BYE */ + nua_options_server_methods, /**< OPTIONS */ + nua_register_server_methods, /**< REGISTER */ + nua_info_server_methods, /**< INFO */ + nua_prack_server_methods, /**< PRACK */ + nua_update_server_methods, /**< UPDATE */ + nua_message_server_methods, /**< MESSAGE */ + nua_subscribe_server_methods, /**< SUBSCRIBE */ + nua_notify_server_methods, /**< NOTIFY */ + nua_refer_server_methods, /**< REFER */ + nua_publish_server_methods; /**< PUBLISH */ + +static inline +int nua_server_request_is_pending(nua_server_request_t const *sr) +{ + return sr && sr->sr_response.msg; +} + +void nua_server_request_destroy(nua_server_request_t *sr); + +int nua_base_server_init(nua_server_request_t *sr); + +#define nua_base_server_init NULL + +int nua_base_server_preprocess(nua_server_request_t *sr); + +#define nua_base_server_preprocess NULL + +int nua_server_params(nua_server_request_t *sr, tagi_t const *tags); + +int nua_base_server_params(nua_server_request_t *sr, tagi_t const *tags); + +#define nua_base_server_params NULL + +int nua_server_trespond(nua_server_request_t *sr, + tag_type_t tag, tag_value_t value, ...); +int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags); + +int nua_base_server_trespond(nua_server_request_t *sr, + tag_type_t tag, tag_value_t value, ...); +int nua_base_server_respond(nua_server_request_t *sr, + tagi_t const *tags); + +int nua_server_report(nua_server_request_t *sr); + +int nua_base_server_treport(nua_server_request_t *sr, + tag_type_t tag, tag_value_t value, ...); +int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags); + +/* ---------------------------------------------------------------------- */ #endif /* NUA_DIALOG_H */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_event_server.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_event_server.c index bd8f9c0194..20ac4ebc3d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_event_server.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_event_server.c @@ -45,9 +45,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #define NEA_SMAGIC_T struct nua_handle_s #define NEA_EMAGIC_T struct nua_handle_s @@ -121,13 +118,13 @@ nua_stack_notifier(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *ta status = 900, phrase = "Error when notifying watchers"; else - nua_stack_event(nua, nh, NULL, e, status = SIP_200_OK, - SIPTAG_EVENT(event), - SIPTAG_CONTENT_TYPE(ct), - TAG_END()); + nua_stack_tevent(nua, nh, NULL, e, status = SIP_200_OK, + SIPTAG_EVENT(event), + SIPTAG_CONTENT_TYPE(ct), + TAG_END()); if (status != 200) - nua_stack_event(nua, nh, NULL, e, status, phrase, TAG_END()); + nua_stack_event(nua, nh, NULL, e, status, phrase, NULL); su_home_deinit(home); } @@ -223,7 +220,7 @@ void authorize_watcher(nea_server_t *nes, what = "active"; } - SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", nh, what)); + SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", (void *)nh, what)); nea_sub_auth(sn->sn_subscriber, substate, TAG_IF(substate == nua_substate_pending, NEATAG_FAKE(1)), @@ -235,13 +232,13 @@ void authorize_watcher(nea_server_t *nes, substate = nua_substate_terminated; nea_server_flush(nes, NULL); SU_DEBUG_7(("nua(%p): authorize_watcher: %s\n", - nh, "watcher is removed")); + (void *)nh, "watcher is removed")); } - nua_stack_event(nua, nh, msg, nua_i_subscription, status, phrase, - NUTAG_SUBSTATE(substate), - NEATAG_SUB(sn->sn_subscriber), - TAG_END()); + nua_stack_tevent(nua, nh, msg, nua_i_subscription, status, phrase, + NUTAG_SUBSTATE(substate), + NEATAG_SUB(sn->sn_subscriber), + TAG_END()); } /* ---------------------------------------------------------------------- */ @@ -262,12 +259,11 @@ void nua_stack_authorize(nua_t *nua, if (sub && state > 0) { nea_sub_auth(sub, state, TAG_NEXT(tags)); - nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END()); + nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); } else { - nua_stack_event(nua, nh, NULL, e, NUA_INTERNAL_ERROR, TAG_END()); + nua_stack_event(nua, nh, NULL, e, NUA_INTERNAL_ERROR, NULL); } - return; } /** @internal Shutdown notifier object */ @@ -347,5 +343,5 @@ void nua_stack_terminate(nua_t *nua, NEATAG_REASON("noresource"), TAG_NEXT(tags)); - nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END()); + nua_stack_event(nua, nh, NULL, e, SIP_200_OK, NULL); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c index b8c647cbd3..d623c72bf1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c @@ -43,17 +43,8 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #include "nua_stack.h" -static int process_response_to_method(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); -static void restart_method(nua_handle_t *nh, tagi_t *tags); -static int respond_to_method(nua_server_request_t *sr, tagi_t const *tags); - /** Send an extension request. * * Send an entension request message. @@ -78,32 +69,25 @@ static int respond_to_method(nua_server_request_t *sr, tagi_t const *tags); * @since New in @VERSION_1_12_4. */ +static nua_client_methods_t const nua_method_client_methods = { + SIP_METHOD_UNKNOWN, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 0, + /* target_refresh */ 0 + }, + /* nua_method_client_template */ NULL, + /* nua_method_client_init */ NULL, + /* nua_method_client_request */ NULL, + /* nua_method_client_check_restart */ NULL, + /* nua_method_client_response */ NULL +}; + int nua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - - if (cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_UNKNOWN, - TAG_NEXT(tags)); - if (msg) - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_method, nh, NULL, - msg, - SIPTAG_END(), - TAG_NEXT(tags)); - if (!cr->cr_orq) { - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } - - return cr->cr_event = e; + return nua_client_create(nh, e, &nua_method_client_methods, tags); } /** @NUA_EVENT nua_r_method @@ -127,20 +111,6 @@ nua_stack_method(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags * @END_NUA_EVENT */ -static int process_response_to_method(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_method)) - return 0; - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END()); -} - -void restart_method(nua_handle_t *nh, tagi_t *tags) -{ - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_method, tags); -} - /** @NUA_EVENT nua_i_method * * @brief Incoming extension request. @@ -165,40 +135,19 @@ void restart_method(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -int nua_stack_process_method(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_server_request_t *sr, sr0[1]; - - sr = SR_INIT(sr0); - - sr = nua_server_request(nua, nh, irq, sip, sr, sizeof *sr, - respond_to_method, 0); - - return nua_stack_server_event(nua, sr, nua_i_method, TAG_END()); -} - -static -int respond_to_method(nua_server_request_t *sr, tagi_t const *tags) -{ - nua_handle_t *nh = sr->sr_owner; - nua_t *nua = nh->nh_nua; - msg_t *msg; - - msg = nua_server_response(sr, sr->sr_status, sr->sr_phrase, TAG_NEXT(tags)); - - if (msg) { - nta_incoming_mreply(sr->sr_irq, msg); - } - else { - SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); - nua_stack_event(nua, nh, NULL, - nua_i_error, 900, "Response to Extension Method Fails", - TAG_END()); - } - - return sr->sr_status >= 200 ? sr->sr_status : 0; -} +nua_server_methods_t const nua_extension_server_methods = + { + SIP_METHOD_UNKNOWN, + nua_i_method, /* Event */ + { + 0, /* Do not create dialog */ + 0, /* Can be an initial request */ + 1, /* Perhaps a target refresh request? */ + 1, /* Add a contact? */ + }, + nua_base_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_base_server_report, + }; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_message.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_message.c index 2365b263cb..b58f60497c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_message.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_message.c @@ -43,9 +43,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #include "nua_stack.h" /* ======================================================================== */ @@ -72,48 +69,41 @@ * @sa #nua_i_message, @RFC3428 */ -static int process_response_to_message(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); +static int nua_message_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); + +static nua_client_methods_t const nua_message_client_methods = { + SIP_METHOD_MESSAGE, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 0, + /* target refresh */ 0 + }, + /* nua_message_client_template */ NULL, + nua_message_client_init, + /*nua_message_client_request*/ NULL, + /* nua_message_client_check_restart */ NULL, + /*nua_message_client_response*/ NULL +}; int -nua_stack_message(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) +nua_stack_message(nua_t *nua, + nua_handle_t *nh, + nua_event_t e, + tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - sip_t *sip; - - if (nh_is_special(nh)) { - return UA_EVENT2(e, 900, "Invalid handle for MESSAGE"); - } - else if (cr->cr_orq) { - return UA_EVENT2(e, 900, "Request already in progress"); - } - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_MESSAGE, - NUTAG_ADD_CONTACT(NH_PGET(nh, win_messenger_enable)), - TAG_NEXT(tags)); - sip = sip_object(msg); - - if (sip) - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_message, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - if (!cr->cr_orq) { - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } - - return cr->cr_event = e; + return nua_client_create(nh, e, &nua_message_client_methods, tags); } -void restart_message(nua_handle_t *nh, tagi_t *tags) +static int nua_message_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_message, tags); + if (NH_PGET(cr->cr_owner, win_messenger_enable)) + cr->cr_contactize = 1; + return 0; } /** @NUA_EVENT nua_r_message @@ -137,15 +127,6 @@ void restart_message(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_message(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_message)) - return 0; - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END()); -} - /** @NUA_EVENT nua_i_message * * @brief Incoming @b MESSAGE request. @@ -168,32 +149,39 @@ static int process_response_to_message(nua_handle_t *nh, * @END_NUA_EVENT */ -int nua_stack_process_message(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +int nua_message_server_init(nua_server_request_t *sr); +int nua_message_server_params(nua_server_request_t *, tagi_t const *); + +nua_server_methods_t const nua_message_server_methods = + { + SIP_METHOD_MESSAGE, + nua_i_message, /* Event */ + { + 0, /* Do not create dialog */ + 0, /* Can be initial request */ + 0, /* Perhaps a target refresh request? */ + 0, /* Do not add contact by default */ + }, + nua_message_server_init, + nua_base_server_preprocess, + nua_message_server_params, + nua_base_server_respond, + nua_base_server_report, + }; + +int nua_message_server_init(nua_server_request_t *sr) { - msg_t *msg; + if (!NH_PGET(sr->sr_owner, message_enable)) + return SR_STATUS1(sr, SIP_403_FORBIDDEN); - if (nh - ? !NH_PGET(nh, message_enable) - : !DNH_PGET(nua->nua_dhandle, message_enable)) - return 403; - - if (nh == NULL) - if (!(nh = nua_stack_incoming_handle(nua, irq, sip, 0))) - return 500; /* respond with 500 Internal Server Error */ - - msg = nta_incoming_getrequest(irq); - - nua_stack_event(nh->nh_nua, nh, msg, nua_i_message, SIP_200_OK, TAG_END()); - -#if 0 /* XXX */ - if (nh->nh_nua->nua_messageRespond) { - nh->nh_irq = irq; - return 0; - } -#endif - - return 200; + return 0; +} + +int nua_message_server_params(nua_server_request_t *sr, + tagi_t const *tags) +{ + if (NH_PGET(sr->sr_owner, win_messenger_enable)) + sr->sr_add_contact = 1; + + return 0; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c index ff5b276313..bcd658fd38 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c @@ -44,12 +44,12 @@ #include #include +#include #include #include #include - -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s +#include +#include #include "nua_stack.h" @@ -59,7 +59,14 @@ struct notifier_usage { enum nua_substate nu_substate; /**< Subscription state */ - sip_time_t nu_expires; + sip_time_t nu_expires; /**< Expiration time */ + sip_time_t nu_requested; /**< Requested expiration time */ +#if SU_HAVE_EXPERIMENTAL + char *nu_tag; /**< @ETag in last NOTIFY */ + unsigned nu_etags:1; /**< Subscriber supports etags */ + unsigned nu_appl_etags:1; /**< Application generates etags */ + unsigned nu_no_body:1; /**< Suppress body */ +#endif }; static char const *nua_notify_usage_name(nua_dialog_usage_t const *du); @@ -115,8 +122,6 @@ void nua_notify_usage_remove(nua_handle_t *nh, /* ====================================================================== */ /* SUBSCRIBE server */ -static int respond_to_subscribe(nua_server_request_t *sr, tagi_t const *tags); - /** @NUA_EVENT nua_i_subscribe * * Incoming @b SUBSCRIBE request. @@ -160,152 +165,185 @@ static int respond_to_subscribe(nua_server_request_t *sr, tagi_t const *tags); * @END_NUA_EVENT */ +static int nua_subscribe_server_init(nua_server_request_t *sr); +static int nua_subscribe_server_preprocess(nua_server_request_t *sr); +static int nua_subscribe_server_respond(nua_server_request_t*, tagi_t const *); +static int nua_subscribe_server_report(nua_server_request_t*, tagi_t const *); -/** @internal Process incoming SUBSCRIBE. */ -int nua_stack_process_subscribe(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +nua_server_methods_t const nua_subscribe_server_methods = + { + SIP_METHOD_SUBSCRIBE, + nua_i_subscribe, /* Event */ + { + 1, /* Create dialog */ + 0, /* Initial request */ + 1, /* Target refresh request */ + 1, /* Add Contact */ + }, + nua_subscribe_server_init, + nua_subscribe_server_preprocess, + nua_base_server_params, + nua_subscribe_server_respond, + nua_subscribe_server_report, + }; + +int nua_subscribe_server_init(nua_server_request_t *sr) { - nua_server_request_t *sr, sr0[1]; - nua_dialog_state_t *ds; - nua_dialog_usage_t *du = NULL; + nua_handle_t *nh = sr->sr_owner; + nua_dialog_state_t *ds = nh->nh_ds; + sip_allow_events_t const *allow_events = NH_PGET(nh, allow_events); + sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; char const *event = o ? o->o_type : NULL; - enum nua_substate substate = nua_substate_terminated; - - enter; - - if (nh) - du = nua_dialog_usage_get(ds = nh->nh_ds, nua_notify_usage, o); - - sr = SR_INIT(sr0); - - if (nh == NULL || du == NULL) { - sip_allow_events_t *allow_events = NUA_PGET(nua, nh, allow_events); - + if (sr->sr_initial || !nua_dialog_usage_get(ds, nua_notify_usage, o)) { if (event && str0cmp(event, "refer") == 0) /* refer event subscription should be initiated with REFER */ - SR_STATUS1(sr, SIP_403_FORBIDDEN); - else if (!event || !msg_header_find_param(allow_events->k_common, event)) - SR_STATUS1(sr, SIP_489_BAD_EVENT); - else - substate = nua_substate_embryonic; + return SR_STATUS1(sr, SIP_403_FORBIDDEN); + + /* XXX - event is case-sensitive, should use msg_header_find_item() */ + if (!event || !msg_header_find_param(allow_events->k_common, event)) + return SR_STATUS1(sr, SIP_489_BAD_EVENT); + } + + return 0; +} + +int nua_subscribe_server_preprocess(nua_server_request_t *sr) +{ + nua_handle_t *nh = sr->sr_owner; + nua_dialog_state_t *ds = nh->nh_ds; + nua_dialog_usage_t *du; + struct notifier_usage *nu; + sip_t const *sip = sr->sr_request.sip; + sip_event_t *o = sip->sip_event; + char const *event = o ? o->o_type : NULL; + /* Maximum expiration time */ + unsigned long expires = 3600; + + assert(nh && nh->nh_nua->nua_dhandle != nh); + + du = nua_dialog_usage_get(ds, nua_notify_usage, o); + + if (du == NULL) { + /* Create a new subscription */ + du = nua_dialog_usage_add(nh, ds, nua_notify_usage, o); + if (du == NULL) + return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } else { /* Refresh existing subscription */ - struct notifier_usage *nu = nua_dialog_usage_private(du); - unsigned long expires; - - assert(nh && du && nu); - - expires = str0cmp(event, "refer") ? 3600 : NH_PGET(nh, refer_expires); - - if (sip->sip_expires && sip->sip_expires->ex_delta < expires) - expires = sip->sip_expires->ex_delta; - - if (expires == 0) - nu->nu_substate = nua_substate_terminated; - - nu->nu_expires = sip_now() + expires; - substate = nu->nu_substate; - - /* XXX - send notify */ + if (str0cmp(event, "refer") == 0) + expires = NH_PGET(nh, refer_expires); SR_STATUS1(sr, SIP_200_OK); } - sr = nua_server_request(nua, nh, irq, sip, sr, sizeof *sr, - respond_to_subscribe, 1); + nu = nua_dialog_usage_private(du); - if (!du && substate == nua_substate_embryonic && sr->sr_status < 300) { - nh = sr->sr_owner; assert(nh && nh != nua->nua_dhandle); - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, sip->sip_event); - if (du) { - struct notifier_usage *nu = nua_dialog_usage_private(du); - unsigned long expires = 3600; /* XXX */ - - if (sip->sip_expires && sip->sip_expires->ex_delta < expires) - expires = sip->sip_expires->ex_delta; + if (sip->sip_expires && sip->sip_expires->ex_delta < expires) + expires = sip->sip_expires->ex_delta; + nu->nu_requested = sip_now() + expires; - nu->nu_expires = sip_now() + expires; - nu->nu_substate = substate; - } - else - SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - } - - if (substate == nua_substate_embryonic && sr->sr_status >= 300) - substate = nua_substate_terminated; +#if SU_HAVE_EXPERIMENTAL + nu->nu_etags = + sip_suppress_body_if_match(sip) || + sip_suppress_notify_if_match(sip) || + sip_has_feature(sr->sr_request.sip->sip_supported, "etags"); +#endif sr->sr_usage = du; - return nua_stack_server_event(nua, sr, nua_i_subscribe, - NUTAG_SUBSTATE(substate), TAG_END()); + return sr->sr_status <= 100 ? 0 : sr->sr_status; } -/** @internal Respond to an SUBSCRIBE request. +/** @internal Respond to a SUBSCRIBE request. * */ static -int respond_to_subscribe(nua_server_request_t *sr, tagi_t const *tags) +int nua_subscribe_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); + + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; + + if (200 <= sr->sr_status && sr->sr_status < 300) { + sip_expires_t ex[1]; + + sip_expires_init(ex); + + if (nu) { + sip_time_t now = sip_now(); + + if (nu->nu_requested) { + if (nu->nu_requested > nu->nu_expires) + nu->nu_expires = nu->nu_requested; + else if (nu->nu_expires <= now || nu->nu_requested <= now) + nu->nu_substate = nua_substate_terminated; + } + + if (nu->nu_expires > now) + ex->ex_delta = nu->nu_expires - now; + } + else { + /* Add header Expires: 0 */ + } + + if (!sip->sip_expires || sip->sip_expires->ex_delta > ex->ex_delta) + sip_add_dup(msg, sip, (sip_header_t *)ex); + } + + return nua_base_server_respond(sr, tags); +} + +static +int nua_subscribe_server_report(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; - nua_t *nua = nh->nh_nua; - struct notifier_usage *nu; - sip_allow_events_t *allow_events = NUA_PGET(nua, nh, allow_events); - sip_expires_t ex[1]; - sip_time_t now = sip_now(); - msg_t *msg; + struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); + enum nua_substate substate = nua_substate_terminated; + int notify = 0; + int retval; - sip_expires_init(ex); - - nu = nua_dialog_usage_private(sr->sr_usage); - if (nu && nu->nu_expires > now) - ex->ex_delta = nu->nu_expires - now; - - msg = nua_server_response(sr, - sr->sr_status, sr->sr_phrase, - NUTAG_ADD_CONTACT(sr->sr_status < 300), - TAG_IF(nu, SIPTAG_EXPIRES(ex)), - SIPTAG_SUPPORTED(NH_PGET(nh, supported)), - SIPTAG_ALLOW_EVENTS(allow_events), - TAG_NEXT(tags)); - - if (msg) { - sip_t *sip = sip_object(msg); - - if (nu && sip->sip_expires && sr->sr_status < 300) - nu->nu_expires = now + sip->sip_expires->ex_delta; - - nta_incoming_mreply(sr->sr_irq, msg); - - if (nu && nu->nu_substate != nua_substate_embryonic) - /* Send NOTIFY (and terminate subscription, when needed) */ - nua_dialog_usage_refresh(nh, ds, sr->sr_usage, sip_now()); + if (nu && !sr->sr_terminating) { + substate = nu->nu_substate; } - else { - /* XXX - send nua_i_error */ - SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); + + /* nu_requested is set by SUBSCRIBE and cleared when NOTIFY is sent */ + if (nu && nu->nu_requested && substate != nua_substate_embryonic) { +#if SU_HAVE_EXPERIMENTAL + sip_t const *sip = sr->sr_request.sip; + sip_suppress_notify_if_match_t *snim = sip_suppress_notify_if_match(sip); + sip_suppress_body_if_match_t *sbim = sip_suppress_body_if_match(sip); + + if (!nu->nu_tag) + notify = 1; + else if (snim && !strcasecmp(snim->snim_tag, nu->nu_tag)) + notify = 0; + else if (sbim && !strcasecmp(snim->snim_tag, nu->nu_tag)) + notify = 1, nu->nu_no_body = 1; + else +#endif + notify = 1; + } + + retval = nua_base_server_treport(sr, NUTAG_SUBSTATE(substate), TAG_END()); + + if (retval >= 2 || nu == NULL) + return retval; + + if (notify) { + /* Send NOTIFY (and terminate subscription, when needed) */ + nua_dialog_usage_refresh(nh, ds, sr->sr_usage, sip_now()); } - return sr->sr_status >= 200 ? sr->sr_status : 0; + return retval; } /* ======================================================================== */ -/* NOTIFY */ - -static int process_response_to_notify(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -static int nua_stack_notify2(nua_t *, nua_handle_t *, nua_event_t, - nua_dialog_usage_t *du, - tagi_t const *tags); - +/* NOTIFY client */ /**@fn void nua_notify(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * @@ -336,175 +374,271 @@ static int nua_stack_notify2(nua_t *, nua_handle_t *, nua_event_t, * @sa @RFC3265, #nua_i_subscribe, #nua_i_refer, NUTAG_ALLOW_EVENTS() */ +static int nua_notify_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_notify_client_init_etag(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_notify_client_request(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_notify_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +static nua_client_methods_t const nua_notify_client_methods = { + SIP_METHOD_NOTIFY, + 0, + { + /* create_dialog */ 1, + /* in_dialog */ 1, + /* target refresh */ 1 + }, + /* nua_notify_client_template */ NULL, + nua_notify_client_init, + nua_notify_client_request, + /* nua_notify_client_check_restart */ NULL, + /* nua_notify_client_response */ NULL, + /* nua_notify_client_preliminary */ NULL, + nua_notify_client_report +}; + /**@internal Send NOTIFY. */ int nua_stack_notify(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - return nua_stack_notify2(nua, nh, e, NULL, tags); + return nua_client_create(nh, e, &nua_notify_client_methods, tags); } - -int nua_stack_notify2(nua_t *nua, - nua_handle_t *nh, - nua_event_t e, - nua_dialog_usage_t *du, - tagi_t const *tags) +static int nua_notify_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du; struct notifier_usage *nu; - msg_t *msg; - sip_t *sip; - sip_event_t const *o; - sip_time_t now; - int refresh = du != NULL; - - if (cr->cr_orq) { - return UA_EVENT2(e, 900, "Request already in progress"); - } - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - if (refresh) { - assert(!cr->cr_msg); - if (cr->cr_msg) - msg_destroy(cr->cr_msg); - cr->cr_msg = msg_copy(du->du_msg); - } - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count || refresh, - SIP_METHOD_NOTIFY, - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - sip = sip_object(msg); - if (!sip) - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - - if (nh->nh_ds->ds_has_notifys == 1 && !sip->sip_event) + sip_event_t const *o = sip->sip_event; + sip_subscription_state_t *ss = sip->sip_subscription_state; + sip_time_t now = sip_now(); + + if (o == NULL && nh->nh_ds->ds_has_notifys == 1) o = NONE; - else - o = sip->sip_event; du = nua_dialog_usage_get(nh->nh_ds, nua_notify_usage, o); - nu = nua_dialog_usage_private(du); - if (du && du->du_event && !sip->sip_event) - sip_add_dup(msg, sip, (sip_header_t *)du->du_event); + if (!du) { + tagi_t const *newsub = tl_find_last(tags, nutag_newsub); - now = sip_now(); + if (!newsub || !newsub->t_value) + return 0; /* Rejected eventually by nua_notify_client_request() */ - if (!du) - ; - else if (sip->sip_subscription_state) { + /* Create new notifier */ + du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o); + if (du == NULL) + return -1; + + nu = nua_dialog_usage_private(du); + nu->nu_expires = now; + } + else + nu = nua_dialog_usage_private(du); + + + if (nu->nu_substate == nua_substate_terminated) { + /*Xyzzy*/; + } + else if (ss != NULL) { /* SIPTAG_SUBSCRIPTION_STATE() overrides NUTAG_SUBSTATE() */ - char const *ss_substate = sip->sip_subscription_state->ss_substate; + nu->nu_substate = nua_substate_make(ss->ss_substate); - if (strcasecmp(ss_substate, "terminated") == 0) - nu->nu_substate = nua_substate_terminated; - else if (strcasecmp(ss_substate, "pending") == 0) - nu->nu_substate = nua_substate_pending; - else /* if (strcasecmp(subs->ss_substate, "active") == 0) */ - nu->nu_substate = nua_substate_active; + if (ss->ss_expires) { + unsigned long expires = strtoul(ss->ss_expires, NULL, 10); + if (now + expires < now) + expires = SIP_TIME_MAX - now - 1; - if (sip->sip_subscription_state->ss_expires) { - unsigned long expires; - expires = strtoul(sip->sip_subscription_state->ss_expires, NULL, 10); - if (expires > 3600) - expires = 3600; - nu->nu_expires = now + expires; - } - else if (nu->nu_substate != nua_substate_terminated) { - sip_subscription_state_t *ss = sip->sip_subscription_state; - char *param; - - if (now < nu->nu_expires) - param = su_sprintf(msg_home(msg), "expires=%lu", nu->nu_expires - now); - else - param = "expires=0"; - - msg_header_add_param(msg_home(msg), ss->ss_common, param); + /* Notifier can only shorten the subscription time */ + if (nu->nu_requested == 0 || nu->nu_requested >= now + expires) + nu->nu_expires = nu->nu_requested = now + expires; } } else { - sip_subscription_state_t *ss; - enum nua_substate substate; - char const *name; + enum nua_substate substate = nu->nu_substate; - substate = nu->nu_substate; - - if (nu->nu_expires <= now) - substate = nua_substate_terminated; - - if (substate != nua_substate_terminated) { + if (nu->nu_expires > now) { tagi_t const *t = tl_find_last(tags, nutag_substate); if (t) - substate = (enum nua_substate)t->t_value; + substate = (enum nua_substate)t->t_value; } + else + substate = nua_substate_terminated; switch (substate) { case nua_substate_embryonic: /*FALLTHROUGH*/ case nua_substate_pending: - name = "pending"; nu->nu_substate = nua_substate_pending; break; case nua_substate_active: default: - name = "active"; nu->nu_substate = nua_substate_active; break; case nua_substate_terminated: - name = "terminated"; nu->nu_substate = nua_substate_terminated; break; } - - if (nu->nu_substate != nua_substate_terminated) { - unsigned long expires = nu->nu_expires - now; - ss = sip_subscription_state_format(msg_home(msg), "%s;expires=%lu", - name, expires); - } - else { - ss = sip_subscription_state_make(msg_home(msg), "terminated; " - "reason=noresource"); - } - - msg_header_insert(msg, (void *)sip, (void *)ss); } - if (du) { - if (nu->nu_substate == nua_substate_terminated) - du->du_terminating = 1; - - if (!du->du_terminating && !refresh) { - /* Save template */ - if (du->du_msg) - msg_destroy(du->du_msg); - du->du_msg = msg_ref_create(cr->cr_msg); - } - } - - /* NOTIFY outside a dialog */ - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_notify, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - - if (!cr->cr_orq) { - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } + if (nu->nu_substate == nua_substate_terminated) + cr->cr_terminating = 1; cr->cr_usage = du; - return cr->cr_event = e; + return nua_notify_client_init_etag(cr, msg, sip, tags); +} + +static int nua_notify_client_init_etag(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ +#if SU_HAVE_EXPERIMENTAL + nua_handle_t *nh = cr->cr_owner; + struct notifier_usage *nu = nua_dialog_usage_private(cr->cr_usage); + nua_server_request_t *sr; + + if (nu->nu_tag) + su_free(nh->nh_home, nu->nu_tag), nu->nu_tag = NULL; + nu->nu_no_body = 0; + + if (sip->sip_etag) { + nu->nu_appl_etags = 1; + nu->nu_tag = su_strdup(nh->nh_home, sip->sip_etag->g_string); + } + else if (!nu->nu_appl_etags && nu->nu_etags) { + su_md5_t md5[1]; + unsigned char digest[SU_MD5_DIGEST_SIZE]; + sip_payload_t pl[1] = { SIP_PAYLOAD_INIT() }; + char token[2 * 16]; + + su_md5_init(md5); + + if (sip->sip_payload) *pl = *sip->sip_payload; + + if (pl->pl_len) + su_md5_update(md5, pl->pl_data, pl->pl_len); + su_md5_update(md5, &pl->pl_len, sizeof(pl->pl_len)); + + if (sip->sip_content_type) + su_md5_striupdate(md5, sip->sip_content_type->c_type); + + su_md5_digest(md5, digest); + token64_e(token, sizeof token, digest, sizeof digest); + token[(sizeof token) - 1] = '\0'; + nu->nu_tag = su_strdup(nh->nh_home, token); + } + + if (!nu->nu_requested || !nu->nu_tag) + return 0; + + /* Check if SUBSCRIBE had matching suppression */ + for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) + if (sr->sr_usage == cr->cr_usage && sr->sr_method == sip_method_subscribe) + break; + + if (sr) { + sip_t const *sip = sr->sr_request.sip; + + sip_suppress_body_if_match_t *sbim; + sip_suppress_notify_if_match_t *snim; + + if (cr->cr_usage->du_ready) { + snim = sip_suppress_notify_if_match(sip); + + if (snim && !strcasecmp(snim->snim_tag, nu->nu_tag)) { + if (nu->nu_requested > nu->nu_expires) + nu->nu_expires = nu->nu_requested; + nu->nu_requested = 0; + return nua_client_return(cr, 202, "NOTIFY Suppressed", msg); + } + } + + sbim = sip_suppress_body_if_match(sip); + if (sbim && !strcasecmp(sbim->sbim_tag, nu->nu_tag)) + nu->nu_no_body = 1; + } +#endif + + return 0; } static -void restart_notify(nua_handle_t *nh, tagi_t *tags) +int nua_notify_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_notify, tags); + nua_dialog_usage_t *du = cr->cr_usage; + struct notifier_usage *nu = nua_dialog_usage_private(du); + su_home_t *home = msg_home(msg); + sip_time_t now = sip_now(); + sip_subscription_state_t *ss = sip->sip_subscription_state; + char const *expires; + + if (du == NULL) /* Subscription has been terminated */ + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); + + assert(du && nu); + + if (du && nua_client_bind(cr, du) < 0) + return -1; + + if (nu->nu_requested) + nu->nu_expires = nu->nu_requested; + nu->nu_requested = 0; + + if (nu->nu_expires <= now || du->du_shutdown) { + nu->nu_substate = nua_substate_terminated; + expires = "expires=0"; + } + else { + expires = su_sprintf(home, "expires=%lu", nu->nu_expires - now); + } + + if (ss == NULL || nua_substate_make(ss->ss_substate) != nu->nu_substate) { + if (nu->nu_substate == nua_substate_terminated) + expires = nu->nu_expires > now ? "noresource" : "timeout"; + + ss = sip_subscription_state_format(home, "%s;%s", + nua_substate_name(nu->nu_substate), + expires); + + msg_header_insert(msg, (void *)sip, (void *)ss); + } + else if (nu->nu_substate != nua_substate_terminated) { + msg_header_replace_param(home, ss->ss_common, expires); + } + +#if SU_HAVE_EXPERIMENTAL + if (nu->nu_tag && !sip->sip_etag) + msg_header_add_make(msg, (void *)sip, sip_etag_class, nu->nu_tag); + + if (nu->nu_no_body) { + nu->nu_no_body = 0; + msg_header_remove(msg, (void *)sip, (void *)sip->sip_payload); + msg_header_remove(msg, (void *)sip, (void *)sip->sip_content_length); + } +#endif + + if (nu->nu_substate == nua_substate_terminated) + cr->cr_terminating = 1; + + if (du->du_event && !sip->sip_event) + sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event); + + return nua_base_client_request(cr, msg, sip, tags); } /** @NUA_EVENT nua_r_notify @@ -527,30 +661,36 @@ void restart_notify(nua_handle_t *nh, tagi_t *tags) * (status code is in @a status and * descriptive message in @a phrase parameters) * @param tags NUTAG_SUBSTATE() indicating subscription state + * SIPTAG_EVENT() indicating subscription event * * @sa nua_notify(), @RFC3265, #nua_i_subscribe, #nua_i_refer * * @END_NUA_EVENT */ -static int process_response_to_notify(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) +static int nua_notify_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) { + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + struct notifier_usage *nu = nua_dialog_usage_private(du); enum nua_substate substate = nua_substate_terminated; - if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_notify)) - return 0; - - if (nh->nh_ds->ds_cr->cr_usage) { - struct notifier_usage *nu = nua_dialog_usage_private(nh->nh_ds->ds_cr->cr_usage); + if (nu && !cr->cr_terminated) substate = nu->nu_substate; - assert(substate != nua_substate_embryonic); - } - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, - NUTAG_SUBSTATE(substate), - TAG_END()); + nua_stack_tevent(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + NUTAG_SUBSTATE(substate), + SIPTAG_EVENT(du ? du->du_event : NULL), + TAG_NEXT(tags)); + + return 0; } @@ -559,30 +699,30 @@ static void nua_notify_usage_refresh(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now) { - struct notifier_usage *nu = nua_dialog_usage_private(du); + nua_client_request_t *cr = du->du_cr; + nua_event_t e = nua_r_notify; - if (nh->nh_ds->ds_cr->cr_usage == du) /* Already notifying. */ - return; + if (cr) { + int terminating; - if (now >= nu->nu_expires) { - sip_subscription_state_t ss[1]; - char const *params[] = { NULL, NULL }; - tagi_t tags[2] = { - { SIPTAG_SUBSCRIPTION_STATE(ss) }, { TAG_END() } - }; + if (nua_client_is_queued(cr)) /* Already notifying. */ + return; - sip_subscription_state_init(ss); + terminating = du->du_expires && du->du_expires <= now; - ss->ss_substate = "terminated"; - ss->ss_params = params; - params[0] = "reason=timeout"; - ss->ss_reason = "timeout"; - - nua_stack_notify2(nh->nh_nua, nh, nua_r_notify, du, tags); + if (nua_client_resend_request(cr, terminating, NULL) >= 0) + return; } else { - nua_stack_notify2(nh->nh_nua, nh, nua_r_notify, du, NULL); + if (nua_client_create(nh, e, &nua_notify_client_methods, NULL) >= 0) + return; } + + nua_stack_tevent(nh->nh_nua, nh, NULL, e, NUA_INTERNAL_ERROR, + NUTAG_SUBSTATE(nua_substate_terminated), + TAG_END()); + + nua_dialog_usage_remove(nh, ds, du); } /** @interal Shut down NOTIFY usage. @@ -595,26 +735,113 @@ static int nua_notify_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; + struct notifier_usage *nu = nua_dialog_usage_private(du); + nua_client_request_t *cr = du->du_cr; - if (!cr->cr_usage) { - /* Unnotify */ - /* Commenting this line out to supress an attended transfer bug (awaiting fix from pessi) */ - //nua_stack_notify2(nh->nh_nua, nh, nua_r_destroy, du, NULL); - return cr->cr_usage != du; + if (nua_client_is_queued(cr)) /* Already notifying. */ + return -1; /* Request in progress */ + + nu->nu_substate = nua_substate_terminated; + + if (cr) { + if (nua_client_resend_request(cr, 1, NULL) >= 0) + return 0; + } + else { + if (nua_client_create(nh, nua_r_notify, + &nua_notify_client_methods, NULL) >= 0) + return 0; } - if (!du->du_ready && !cr->cr_orq) - return 1; /* Unauthenticated NOTIFY? */ - - return -1; /* Request in progress */ + nua_dialog_usage_remove(nh, ds, du); + return 200; } - /* ======================================================================== */ /* REFER */ /* RFC 3515 */ +static int nua_refer_server_init(nua_server_request_t *sr); +static int nua_refer_server_preprocess(nua_server_request_t *sr); +static int nua_refer_server_respond(nua_server_request_t*, tagi_t const *); +static int nua_refer_server_report(nua_server_request_t*, tagi_t const *); + +nua_server_methods_t const nua_refer_server_methods = + { + SIP_METHOD_REFER, + nua_i_refer, /* Event */ + { + 1, /* Create dialog */ + 0, /* Initial request */ + 1, /* Target refresh request */ + 1, /* Add Contact */ + }, + nua_refer_server_init, + nua_refer_server_preprocess, + nua_base_server_params, + nua_refer_server_respond, + nua_refer_server_report, + }; + +static int nua_refer_server_init(nua_server_request_t *sr) +{ + return 0; +} + +static int nua_refer_server_preprocess(nua_server_request_t *sr) +{ + nua_handle_t *nh = sr->sr_owner; + sip_t const *sip = sr->sr_request.sip; + struct notifier_usage *nu; + sip_event_t *o; + + if (nh->nh_ds->ds_got_referrals || NH_PGET(nh, refer_with_id)) + o = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); + else + o = sip_event_make(nh->nh_home, "refer"); + + if (o) { + sr->sr_usage = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, o); + msg_header_free(nh->nh_home, (msg_header_t *)o); + } + + if (!sr->sr_usage) + return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + + nu = nua_dialog_usage_private(sr->sr_usage); + nu->nu_requested = sip_now() + NH_PGET(nh, refer_expires); + + return 0; +} + +static +int nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); + sip_refer_sub_t const *rs = sip_refer_sub(sr->sr_response.sip); + + if (sr->sr_status < 200 || nu == NULL) { + } + else if (sr->sr_status < 300 && + /* Application included Refer-Sub: false in response */ + (rs == NULL || str0casecmp("false", rs->rs_value))) { + sr->sr_usage->du_ready = 1; + + nu->nu_expires = sip_now() + NH_PGET(nh, refer_expires); + + if (sr->sr_application) /* Application responded to REFER */ + nu->nu_substate = nua_substate_active; + } + else { + /* Destroy the implicit subscription usage */ + sr->sr_terminating = 1; + } + + return nua_base_server_respond(sr, tags); +} + + /** @NUA_EVENT nua_i_refer * * Incoming @b REFER request used to transfer calls. @@ -635,89 +862,45 @@ static int nua_notify_usage_shutdown(nua_handle_t *nh, * @END_NUA_EVENT */ -/** @internal Process incoming REFER. */ -int nua_stack_process_refer(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +static +int nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags) { - nua_dialog_usage_t *du = NULL; - struct notifier_usage *nu; - sip_event_t *event; - sip_referred_by_t *by = NULL, default_by[1]; - msg_t *response; - sip_time_t expires; - int created = 0; + nua_handle_t *nh = sr->sr_owner; + struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); + sip_t const *sip = sr->sr_request.sip; + sip_referred_by_t *by = sip->sip_referred_by, default_by[1]; + sip_event_t const *o = sr->sr_usage->du_event; + enum nua_substate substate = nua_substate_terminated; + int initial = sr->sr_initial, retval; - if (nh == NULL) { - if (!(nh = nua_stack_incoming_handle(nua, irq, sip, 1))) - return 500; - created = 1; + if (nu) { + if (!sr->sr_terminating) + substate = nu->nu_substate; } - if (nh->nh_ds->ds_has_referrals || NH_PGET(nh, refer_with_id)) - event = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); - else - event = sip_event_make(nh->nh_home, "refer"); + if (by == NULL) { + by = sip_referred_by_init(default_by); - if (event) - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_notify_usage, event); - - if (!du || du->du_ready) { - if (du->du_ready) { - SU_DEBUG_1(("nua(%p): REFER with existing refer;id=%u\n", nh, - sip->sip_cseq->cs_seq)); - } - if (created) - nh_destroy(nua, nh); - return 500; + by->b_display = sip->sip_from->a_display; + *by->b_url = *sip->sip_from->a_url; } - nu = nua_dialog_usage_private(du); - du->du_ready = 1; - nh->nh_ds->ds_has_referrals = 1; + retval = nua_base_server_treport(sr, + NUTAG_SUBSTATE(substate), + NUTAG_REFER_EVENT(o), + TAG_IF(by, SIPTAG_REFERRED_BY(by)), + TAG_END()); - nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */ + if (retval >= 2 || nu == NULL) + return retval; - if (!sip->sip_referred_by) { - sip_from_t *a = sip->sip_from; - - sip_referred_by_init(by = default_by); - - *by->b_url = *a->a_url; - by->b_display = a->a_display; - } - - response = nh_make_response(nua, nh, irq, - SIP_202_ACCEPTED, - NUTAG_ADD_CONTACT(1), - TAG_END()); - - nta_incoming_mreply(irq, response); - - expires = NH_PGET(nh, refer_expires); - - if (sip->sip_expires && sip->sip_expires->ex_delta < expires) - expires = sip->sip_expires->ex_delta; - nu->nu_substate = nua_substate_pending; - nu->nu_expires = sip_now() + expires; - - /* Immediate notify in order to establish the dialog */ - if (!sip->sip_to->a_tag) + if (initial) nua_stack_post_signal(nh, nua_r_notify, - SIPTAG_EVENT(event), + SIPTAG_EVENT(o), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"), TAG_END()); - - nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq), - nua_i_refer, SIP_202_ACCEPTED, - NUTAG_REFER_EVENT(event), - TAG_IF(by, SIPTAG_REFERRED_BY(by)), - TAG_END()); - - su_free(nh->nh_home, event); - return 500; + return retval; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_options.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_options.c index 7398776873..e161e6423a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_options.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_options.c @@ -45,9 +45,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #include "nua_stack.h" /**@fn void nua_options(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); @@ -69,46 +66,6 @@ * @sa #nua_i_options, @RFC3261 section 10 */ -static int process_response_to_options(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -int -nua_stack_options(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) -{ - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - - if (nh_is_special(nh)) { - return UA_EVENT2(e, 900, "Invalid handle for OPTIONS"); - } - else if (cr->cr_orq) { - return UA_EVENT2(e, 900, "Request already in progress"); - } - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_OPTIONS, - TAG_NEXT(tags)); - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_options, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - if (!cr->cr_orq) { - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } - - return cr->cr_event = e; -} - -void restart_options(nua_handle_t *nh, tagi_t *tags) -{ - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_options, tags); -} - /** @NUA_EVENT nua_r_options * * Answer to outgoing OPTIONS. @@ -130,11 +87,25 @@ void restart_options(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_options(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_options)) - return 0; - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END()); +static nua_client_methods_t const nua_options_client_methods = { + SIP_METHOD_OPTIONS, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 0, + /* target refresh */ 0 + }, + /*nua_options_client_template*/ NULL, + /*nua_options_client_init*/ NULL, + /*nua_options_client_request*/ NULL, + /* nua_options_client_check_restart */ NULL, + /*nua_options_client_response*/ NULL +}; + +int nua_stack_options(nua_t *nua, + nua_handle_t *nh, + nua_event_t e, + tagi_t const *tags) +{ + return nua_client_create(nh, e, &nua_options_client_methods, tags); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c index fdcd77234e..67ad06a11a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c @@ -762,12 +762,6 @@ static int nhp_set_tags(su_home_t *home, else if (tag == nutag_enablemessenger) { NHP_SET(nhp, win_messenger_enable, value != 0); } -#if 0 - /* NUTAG_AUTORESPOND(autorespond) */ - else if (tag == nutag_autorespond) { - NHP_SET(nhp, autorespond, value); - } -#endif /* NUTAG_CALLEE_CAPS(callee_caps) */ else if (tag == nutag_callee_caps) { NHP_SET(nhp, callee_caps, value != 0); @@ -882,7 +876,8 @@ static int nhp_set_tags(su_home_t *home, sip_allow_class, &appl_method, (msg_list_t const *)nhp->nhp_appl_method, - NHP_ISSET(nhp, allow), /* already set by tags */ + /* already set by tags? */ + NHP_ISSET(nhp, appl_method), 0, /* dup it, don't make */ 1, /* merge with old value */ t->t_value); @@ -1171,10 +1166,10 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags) nh->nh_tags = tl_filtered_tlist(nh->nh_home, tagfilter, - SIPTAG_FROM(p_from), - TAG_FILTER(nua_handle_tags_filter), - SIPTAG_TO(p_to), - TAG_FILTER(nua_handle_tags_filter), + TAG_IF(p_from != SIP_NONE, SIPTAG_FROM(p_from)), + TAG_IF(p_from != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)), + TAG_IF(p_to != SIP_NONE, SIPTAG_TO(p_to)), + TAG_IF(p_to != SIP_NONE, TAG_FILTER(nua_handle_tags_filter)), TAG_NEXT(tags)); nh->nh_ptags = @@ -1366,7 +1361,8 @@ int nua_stack_set_smime_params(nua_t *nua, tagi_t const *tags) * application contact associated with the operation handle * when responding to nua_get_hparams() * @param sip NULL - * @param tags + * @param tags + * NUTAG_APPL_METHOD() \n * NUTAG_AUTOACK() \n * NUTAG_AUTOALERT() \n * NUTAG_AUTOANSWER() \n @@ -1559,6 +1555,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, TIF_STR(SIPTAG_SUPPORTED_STR, supported), TIF(SIPTAG_ALLOW, allow), TIF_STR(SIPTAG_ALLOW_STR, allow), + TIF_STR(NUTAG_APPL_METHOD, appl_method), TIF(SIPTAG_ALLOW_EVENTS, allow_events), TIF_STR(SIPTAG_ALLOW_EVENTS_STR, allow_events), TIF_SIP(SIPTAG_USER_AGENT, user_agent), @@ -1607,7 +1604,7 @@ int nua_stack_get_params(nua_t *nua, nua_handle_t *nh, nua_event_t e, TAG_NEXT(media_params)); - nua_stack_event(nua, nh, NULL, nua_r_get_params, SIP_200_OK, TAG_NEXT(lst)); + nua_stack_event(nua, nh, NULL, nua_r_get_params, SIP_200_OK, lst); su_home_deinit(tmphome); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c index 9c25d44ac3..6f9d74be83 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c @@ -45,9 +45,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #include "nua_stack.h" /* ====================================================================== */ @@ -55,6 +52,7 @@ struct publish_usage { sip_etag_t *pu_etag; + int pu_published; }; static char const *nua_publish_usage_name(nua_dialog_usage_t const *du); @@ -116,14 +114,6 @@ void nua_publish_usage_remove(nua_handle_t *nh, /* ======================================================================== */ /* PUBLISH */ -static int nua_stack_publish2(nua_t *nua, nua_handle_t *nh, nua_event_t e, - int refresh, tagi_t const *tags); - -static int process_response_to_publish(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - - /**@fn \ * void nua_publish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * @@ -237,213 +227,217 @@ void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * @END_NUA_EVENT */ -int nua_stack_publish(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags) +static int nua_publish_client_template(nua_client_request_t *cr, + msg_t **return_msg, + tagi_t const *tags); +static int nua_publish_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_publish_client_request(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_publish_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); + +static nua_client_methods_t const nua_publish_client_methods = { + SIP_METHOD_PUBLISH, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 0, + /* target refresh */ 0 + }, + nua_publish_client_template, + nua_publish_client_init, + nua_publish_client_request, + /* nua_publish_client_check_restart */ NULL, + nua_publish_client_response, + /* nua_publish_client_preliminary */ NULL +}; + +/**@internal Send PUBLISH. */ +int nua_stack_publish(nua_t *nua, + nua_handle_t *nh, + nua_event_t e, + tagi_t const *tags) { - return nua_stack_publish2(nua, nh, e, 0, tags); + return nua_client_create(nh, e, &nua_publish_client_methods, tags); } -static -int nua_stack_publish2(nua_t *nua, nua_handle_t *nh, nua_event_t e, - int refresh, - tagi_t const *tags) +static int nua_publish_client_template(nua_client_request_t *cr, + msg_t **return_msg, + tagi_t const *tags) { nua_dialog_usage_t *du; + + if (cr->cr_event == nua_r_publish) + return 0; + + du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_publish_usage, NULL); + if (du && du->du_cr) { + if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) + return -1; + *return_msg = msg_copy(du->du_cr->cr_msg); + return 1; + } + + return 0; +} + +static int nua_publish_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du; struct publish_usage *pu; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg = NULL; - sip_t *sip; - int remove_body = 0; - if (nua_stack_set_handle_special(nh, nh_has_nothing, nua_r_publish) < 0) - return UA_EVENT2(e, 900, "Invalid handle for PUBLISH"); - - if (cr->cr_orq) { - return UA_EVENT2(e, 900, "Request already in progress"); - } - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - if (e == nua_r_unpublish) { - du = nua_dialog_usage_get(nh->nh_ds, nua_publish_usage, NULL); - if (du) - refresh = 1; - else - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_publish_usage, NULL); - } - else if (!refresh) + if (cr->cr_event == nua_r_publish) { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_publish_usage, NULL); + if (!du) + return -1; + pu = nua_dialog_usage_private(du); + pu->pu_published = 0; + if (sip->sip_if_match) { + pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_if_match); + if (!pu->pu_etag) + return -1; + sip_header_remove(msg, sip, (sip_header_t *)sip->sip_if_match); + } + } else du = nua_dialog_usage_get(nh->nh_ds, nua_publish_usage, NULL); - if (!du) - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - - nua_dialog_usage_reset_refresh(du); - pu = nua_dialog_usage_private(du); assert(pu); - - if (refresh) { - if (cr->cr_msg) - msg_destroy(cr->cr_msg); - cr->cr_msg = msg_copy(du->du_msg); - remove_body = pu->pu_etag != NULL; - } - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count || refresh, - SIP_METHOD_PUBLISH, - NUTAG_ADD_CONTACT(0), - TAG_NEXT(tags)); - sip = sip_object(msg); - - if (!msg || !sip) - goto error; - - du->du_terminating = - e != nua_r_publish || - (sip->sip_expires && sip->sip_expires->ex_delta == 0); - - if (!du->du_terminating && !refresh) { - /* Save template */ - if (du->du_msg) - msg_destroy(du->du_msg); - du->du_msg = msg_ref_create(cr->cr_msg); - } - - cr->cr_orq = - nta_outgoing_mcreate(nua->nua_nta, - process_response_to_publish, nh, NULL, - msg, - SIPTAG_IF_MATCH(pu->pu_etag), - TAG_IF(remove_body, SIPTAG_PAYLOAD(NONE)), - TAG_IF(remove_body, SIPTAG_CONTENT_TYPE(NONE)), - TAG_IF(e != nua_r_publish, - SIPTAG_EXPIRES_STR("0")), - SIPTAG_END(), TAG_NEXT(tags)); - if (!cr->cr_orq) - goto error; - cr->cr_usage = du; - return cr->cr_event = e; - - error: - msg_destroy(msg); - if (!du->du_ready == 0) - nua_dialog_usage_remove(nh, nh->nh_ds, du); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); + return 0; } - -static void -restart_publish(nua_handle_t *nh, tagi_t *tags) -{ - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_publish, tags); -} - - static -int process_response_to_publish(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) +int nua_publish_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - int status = sip->sip_status->st_status; - nua_client_request_t *cr = nh->nh_ds->ds_cr; nua_dialog_usage_t *du = cr->cr_usage; - struct publish_usage *pu = nua_dialog_usage_private(du); - unsigned saved_retry_count = cr->cr_retry_count + 1; + int un, done; + sip_etag_t const *etag = NULL; - if (nua_creq_check_restart(nh, cr, orq, sip, restart_publish)) - return 0; + un = cr->cr_terminating || + cr->cr_event != nua_r_publish || + (du && du->du_shutdown) || + (sip->sip_expires && sip->sip_expires->ex_delta == 0); + cr->cr_terminating = un; + done = un; - if (status < 200 || pu == NULL) - return nua_stack_process_response(nh, cr, orq, sip, TAG_END()); + if (du) { + struct publish_usage *pu = nua_dialog_usage_private(du); - if (pu->pu_etag) - su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL; + if (nua_client_bind(cr, du) < 0) + return -1; + if (pu->pu_published) + done = 1; + etag = pu->pu_etag; + } - if (!du->du_terminating) { - int retry = 0, invalid_expiration = 0; + return nua_base_client_trequest(cr, msg, sip, + SIPTAG_IF_MATCH(etag), + TAG_IF(done, SIPTAG_PAYLOAD(NONE)), + TAG_IF(done, SIPTAG_CONTENT_TYPE(NONE)), + TAG_IF(un, SIPTAG_EXPIRES_STR("0")), + TAG_NEXT(tags)); +} - if (status < 300) { - if (!sip->sip_expires) - invalid_expiration = 1; - else if (sip->sip_expires->ex_delta == 0) - retry = 1, invalid_expiration = 1; +static int nua_publish_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + + if (!cr->cr_terminated && du && sip) { + struct publish_usage *pu = nua_dialog_usage_private(du); + sip_expires_t const *ex = sip->sip_expires; + + /* Reset state */ + pu->pu_published = 0; + if (pu->pu_etag) + su_free(nh->nh_home, pu->pu_etag), pu->pu_etag = NULL; + + if (status == 412) { + if (nua_client_restart(cr, 100, phrase)) + return 0; } - else if (status == 412) - retry = 1; + else if (status < 300) { + if (ex && ex->ex_delta == 0 && + nua_client_restart(cr, 100, "Trying re-PUBLISH")) + return 0; - if (status < 300 && !invalid_expiration && !retry) { + pu->pu_published = 1; pu->pu_etag = sip_etag_dup(nh->nh_home, sip->sip_etag); - du->du_ready = 1; - nua_dialog_usage_set_expires(du, sip->sip_expires->ex_delta); - } - else if (retry && saved_retry_count < NH_PGET(nh, retry_count)) { - msg_t *response = nta_outgoing_getresponse(orq); - nua_stack_event(nh->nh_nua, nh, response, cr->cr_event, - 100, "Trying re-PUBLISH", - TAG_END()); - nua_creq_deinit(cr, orq); - nua_stack_publish2(nh->nh_nua, nh, cr->cr_event, 1, NULL); - cr->cr_retry_count = saved_retry_count; - return 0; - } - else if (invalid_expiration) { - msg_t *response = nta_outgoing_getresponse(orq); - nua_stack_event(nh->nh_nua, nh, response, cr->cr_event, - 900, "Received Invalid Expiration Time", - TAG_END()); - nua_dialog_usage_remove(nh, nh->nh_ds, cr->cr_usage); - nua_creq_deinit(cr, orq); - cr->cr_usage = NULL; - return 0; + + if (!ex || ex->ex_delta == 0 || !pu->pu_etag) { + cr->cr_terminated = 1; + + if (!ex || ex->ex_delta == 0) + SET_STATUS(900, "Received Invalid Expiration Time"); + else + SET_STATUS1(NUA_INTERNAL_ERROR); + } } } - return nua_stack_process_response(nh, cr, orq, sip, TAG_END()); + return nua_base_client_response(cr, status, phrase, sip, NULL); } - static void nua_publish_usage_refresh(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du, - sip_time_t now) + nua_dialog_state_t *ds, + nua_dialog_usage_t *du, + sip_time_t now) { - if (ds->ds_cr->cr_usage == du) /* Already publishing. */ - return; - nua_stack_publish2(nh->nh_nua, nh, nua_r_publish, 1, NULL); + nua_client_request_t *cr = du->du_cr; + + if (cr) { + if (nua_client_is_queued(cr) /* Already publishing. */ + || nua_client_resend_request(cr, 0, NULL) >= 0) + return; + } + + nua_stack_event(nh->nh_nua, nh, NULL, + nua_r_publish, NUA_INTERNAL_ERROR, + NULL); + + nua_dialog_usage_remove(nh, ds, du); } -/** @interal Shut down PUBLISH usage. +/** @interal Shut down PUBLISH usage. * * @retval >0 shutdown done * @retval 0 shutdown in progress * @retval <0 try again later */ static int nua_publish_usage_shutdown(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du) + nua_dialog_state_t *ds, + nua_dialog_usage_t *du) { - nua_client_request_t *cr = ds->ds_cr; + nua_client_request_t *cr = du->du_cr; - if (!cr->cr_usage) { - /* Unpublish */ - nua_stack_publish2(nh->nh_nua, nh, nua_r_destroy, 1, NULL); - return cr->cr_usage != du; + if (cr) { + if (nua_client_is_queued(cr)) /* Already publishing. */ + return -1; + + if (nua_client_resend_request(cr, 1, NULL) >= 0) + return 0; } - if (!du->du_ready && !cr->cr_orq) - return 1; /* had unauthenticated initial request */ - - return -1; /* Request in progress */ + /* XXX - report to user */ + nua_dialog_usage_remove(nh, ds, du); + return 200; } /* ---------------------------------------------------------------------- */ /* Server side */ -static -int respond_to_publish(nua_server_request_t *sr, tagi_t const *tags); - /** @NUA_EVENT nua_i_publish * * Incoming PUBLISH request. @@ -481,48 +475,35 @@ int respond_to_publish(nua_server_request_t *sr, tagi_t const *tags); * @END_NUA_EVENT */ -int nua_stack_process_publish(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +int nua_publish_server_init(nua_server_request_t *sr); + +nua_server_methods_t const nua_publish_server_methods = + { + SIP_METHOD_PUBLISH, + nua_i_publish, /* Event */ + { + 0, /* Do not create dialog */ + 0, /* Initial request */ + 0, /* Not a target refresh request */ + 1, /* Add Contact */ + }, + nua_publish_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_base_server_report, + }; + +int nua_publish_server_init(nua_server_request_t *sr) { - nua_server_request_t *sr, sr0[1]; - sip_allow_events_t *allow_events = NUA_PGET(nua, nh, allow_events); - sip_event_t *o = sip->sip_event; + sip_allow_events_t *allow_events = NH_PGET(sr->sr_owner, allow_events); + sip_event_t *o = sr->sr_request.sip->sip_event; char const *event = o ? o->o_type : NULL; - sr = SR_INIT(sr0); - if (!allow_events) - SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED); + return SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED); else if (!event || !msg_header_find_param(allow_events->k_common, event)) - SR_STATUS1(sr, SIP_489_BAD_EVENT); + return SR_STATUS1(sr, SIP_489_BAD_EVENT); - sr = nua_server_request(nua, nh, irq, sip, sr, sizeof *sr, - respond_to_publish, 0); - - return nua_stack_server_event(nua, sr, nua_i_publish, TAG_END()); -} - -static -int respond_to_publish(nua_server_request_t *sr, tagi_t const *tags) -{ - nua_handle_t *nh = sr->sr_owner; - nua_t *nua = nh->nh_nua; - msg_t *msg; - - msg = nua_server_response(sr, sr->sr_status, sr->sr_phrase, TAG_NEXT(tags)); - - if (msg) { - nta_incoming_mreply(sr->sr_irq, msg); - } - else { - SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); - nua_stack_event(nua, nh, NULL, - nua_i_error, 900, "PUBLISH Response Fails", - TAG_END()); - } - - return sr->sr_status >= 200 ? sr->sr_status : 0; + return 0; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c index 57861555d4..51cc6d3891 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c @@ -27,6 +27,7 @@ * * @author Pekka Pessi * @author Martti Mela + * @author Kai Vehmanen * * @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi */ @@ -45,8 +46,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s #define NTA_UPDATE_MAGIC_T struct nua_s #include "nua_stack.h" @@ -220,14 +219,6 @@ static void nua_register_usage_peer_info(nua_dialog_usage_t *du, /* ======================================================================== */ /* REGISTER */ -static void restart_register(nua_handle_t *nh, tagi_t *tags); - -static int process_response_to_register(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -static void unregister_expires_contacts(msg_t *msg, sip_t *sip); - /* Interface towards outbound_t */ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, su_home_t *home, @@ -537,80 +528,131 @@ outbound_owner_vtable nua_stack_outbound_callbacks = { * @END_NUA_EVENT */ -int -nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags) +static int nua_register_client_template(nua_client_request_t *cr, + msg_t **return_msg, + tagi_t const *tags); +static int nua_register_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_register_client_request(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_register_client_check_restart(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_register_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); + +static nua_client_methods_t const nua_register_client_methods = { + SIP_METHOD_REGISTER, + 0, + { + /* create_dialog */ 1, + /* in_dialog */ 0, + /* target refresh */ 0 + }, + nua_register_client_template, + nua_register_client_init, + nua_register_client_request, + nua_register_client_check_restart, + nua_register_client_response +}; + +/**@internal Send REGISTER. */ +int nua_stack_register(nua_t *nua, + nua_handle_t *nh, + nua_event_t e, + tagi_t const *tags) +{ + return nua_client_create(nh, e, &nua_register_client_methods, tags); +} + +static int nua_register_client_template(nua_client_request_t *cr, + msg_t **return_msg, + tagi_t const *tags) { nua_dialog_usage_t *du; - nua_registration_t *nr = NULL; - outbound_t *ob = NULL; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg = NULL; - sip_t *sip; - int terminating = e != nua_r_register; - if (nua_stack_set_handle_special(nh, nh_has_register, nua_r_register) < 0) - return UA_EVENT2(e, 900, "Invalid handle for REGISTER"); - if (cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); + if (cr->cr_event == nua_r_register) + return 0; - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); + /* Use a copy of REGISTER message as the template for un-REGISTER */ + du = nua_dialog_usage_get(cr->cr_owner->nh_ds, nua_register_usage, NULL); + if (du && du->du_cr) { + if (nua_client_set_target(cr, du->du_cr->cr_target) < 0) + return -1; + *return_msg = msg_copy(du->du_cr->cr_msg); + return 1; + } + + return 0; +} + +static int nua_register_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du; + nua_registration_t *nr; + sip_to_t const *aor = sip->sip_to; + + int unreg; + + /* Explicit empty (NULL) contact - used for CPL store/remove? */ + if (!sip->sip_contact && cr->cr_has_contact) + /* Do not create any usage */ + return 0; + + unreg = cr->cr_event != nua_r_register || + (sip->sip_expires && sip->sip_expires->ex_delta == 0); + if (unreg) + nua_client_terminating(cr); du = nua_dialog_usage_add(nh, nh->nh_ds, nua_register_usage, NULL); - if (!du) - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - nr = nua_dialog_usage_private(du); assert(nr); + if (du == NULL) + return -1; + nr = nua_dialog_usage_private(du); + nua_registration_add(&nh->nh_nua->nua_registrations, nr); - if (!terminating && du->du_terminating) - return UA_EVENT2(e, 900, "Unregister in progress"); - if (cr->cr_msg) - msg_destroy(cr->cr_msg), cr->cr_msg = NULL; - /* Use original message as template when unregistering */ - if (terminating) - cr->cr_msg = msg_ref_create(du->du_msg); + if (nua_client_bind(cr, du) < 0) + return -1; - msg = nua_creq_msg(nua, nh, cr, cr->cr_msg != NULL, - SIP_METHOD_REGISTER, - TAG_IF(!terminating, NUTAG_USE_DIALOG(1)), - TAG_NEXT(tags)); - sip = sip_object(msg); - if (!msg || !sip) - goto error; + if (aor == NULL) + aor = sip->sip_from; + if (aor == NULL) + aor = nh->nh_nua->nua_from; - if (!nr->nr_aor) { - if (nua_registration_set_aor(nh->nh_home, nr, sip->sip_to) < 0) - goto error; + if (nua_registration_set_aor(nh->nh_home, nr, aor) < 0) + return -1; + + if (nua_registration_set_contact(nh, nr, sip->sip_contact, unreg) < 0) + return -1; + + if (!nr->nr_ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) { + nr->nr_ob = outbound_new(nh, &nua_stack_outbound_callbacks, + nh->nh_nua->nua_root, + nh->nh_nua->nua_nta, + NH_PGET(nh, instance)); + if (!nr->nr_ob) + return nua_client_return(cr, 900, "Cannot create outbound", msg); } - if (terminating) - /* Add Expires: 0 and remove the expire parameters from contacts */ - unregister_expires_contacts(msg, sip); + if (nr->nr_ob) { + outbound_t *ob = nr->nr_ob; + sip_contact_t *m; - if (!sip->sip_contact && cr->cr_has_contact) { - terminating = 1; - } - else if (nua_registration_set_contact(nh, nr, sip->sip_contact, terminating) - < 0) - goto error; + if (!unreg && sip->sip_contact) { + for (m = sip->sip_contact; m; m = m->m_next) + if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) + break; + + if (m == NULL) + unreg = 1; /* All contacts have expires=0 */ + } - du->du_terminating = terminating; - - if (du->du_msg == NULL && !terminating) - du->du_msg = msg_ref_create(cr->cr_msg); /* Save original message */ - - ob = nr->nr_ob; - - if (!ob && (NH_PGET(nh, outbound) || NH_PGET(nh, instance))) { - nr->nr_ob = ob = outbound_new(nh, &nua_stack_outbound_callbacks, - nh->nh_nua->nua_root, - nh->nh_nua->nua_nta, - NH_PGET(nh, instance)); - if (!ob) - goto error; - } - - if (ob) { outbound_set_options(ob, NH_PGET(nh, outbound), NH_PGET(nh, keepalive), @@ -618,304 +660,205 @@ nua_stack_register(nua_t *nua, nua_handle_t *nh, nua_event_t e, ? NH_PGET(nh, keepalive_stream) : NH_PGET(nh, keepalive)); nua_stack_outbound_features(nh, ob); - outbound_stop_keepalive(ob); - if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, terminating) < 0) - goto error; + if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0) + return nua_client_return(cr, 900, "Cannot set outbound contact", msg); } - /* This calls nta_outgoing_mcreate() but adds a few tags */ - cr->cr_orq = - outbound_register_request(ob, terminating, - nr->nr_by_stack ? nr->nr_contact : NULL, - nua->nua_nta, - process_response_to_register, nh, NULL, - msg, - SIPTAG_END(), - TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)), - TAG_IF(!terminating, NTATAG_COMP("sigcomp")), - TAG_NEXT(tags)); - - if (!cr->cr_orq) - goto error; - - cr->cr_usage = du; - return cr->cr_event = e; - - error: - msg_destroy(msg); - msg_destroy(cr->cr_msg), cr->cr_msg = NULL; - nua_dialog_usage_remove(nh, nh->nh_ds, du); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); + return 0; } -static void -restart_register(nua_handle_t *nh, tagi_t *tags) +static +int nua_register_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; + nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; - nua_registration_t *nr = nua_dialog_usage_private(du); - int terminating = du && du->du_terminating; + nua_registration_t *nr; + sip_contact_t *m = NULL, *contacts = sip->sip_contact, *previous = NULL; + int unreg; - cr->cr_restart = NULL; + (void)nh; - if (!cr->cr_msg) - return; + /* Explicit empty (NULL) contact - used for CPL store/remove? */ + if (!contacts && cr->cr_has_contact) + return nua_base_client_request(cr, msg, sip, tags); - msg = nua_creq_msg(nh->nh_nua, nh, cr, 1, - SIP_METHOD_UNKNOWN, - TAG_NEXT(tags)); + if ((du && du->du_shutdown) || + (sip->sip_expires && sip->sip_expires->ex_delta == 0)) + nua_client_terminating(cr); - if (!msg) - return; /* XXX - Uh-oh */ - - if (terminating) - unregister_expires_contacts(msg, sip_object(msg)); - - /* This calls nta_outgoing_mcreate() but adds a few tags */ - cr->cr_orq = - outbound_register_request(nr->nr_ob, terminating, - nr->nr_by_stack ? nr->nr_contact : NULL, - nh->nh_nua->nua_nta, - process_response_to_register, nh, NULL, - msg, - SIPTAG_END(), - TAG_IF(terminating, NTATAG_SIGCOMP_CLOSE(1)), - TAG_IF(!terminating, NTATAG_COMP("sigcomp")), - TAG_NEXT(tags)); - - if (!cr->cr_orq) - msg_destroy(msg); -} - -/** Refresh registration */ -static -void nua_register_usage_refresh(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du, - sip_time_t now) -{ - nua_t *nua = nh->nh_nua; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - nua_registration_t *nr = nua_dialog_usage_private(du); - msg_t *msg; - sip_t *sip; - - if (du->du_terminating || du->du_shutdown) - return; - - if (cr->cr_msg) { - /* Dialog is busy, delay of 5 .. 15 seconds */ - nua_dialog_usage_refresh_range(du, 5, 15); - return; - } - - outbound_stop_keepalive(nr->nr_ob); - - cr->cr_msg = msg_copy(du->du_msg); - msg = nua_creq_msg(nua, nh, cr, 1, - SIP_METHOD_REGISTER, - NUTAG_USE_DIALOG(1), - TAG_END()); - sip = sip_object(msg); - if (!msg || !sip) - goto error; - - cr->cr_orq = - outbound_register_request(nr->nr_ob, 0, - nr->nr_by_stack ? nr->nr_contact : NULL, - nh->nh_nua->nua_nta, - process_response_to_register, nh, NULL, - msg, - SIPTAG_END(), - NTATAG_COMP("sigcomp"), - TAG_END()); - if (!cr->cr_orq) - goto error; - - cr->cr_usage = du; - cr->cr_event = nua_r_register; - return; - - error: - msg_destroy(msg); - msg_destroy(cr->cr_msg); - UA_EVENT2(nua_r_register, NUA_INTERNAL_ERROR, TAG_END()); - return; -} - -/** Shutdown register usage. - * - * Called when stack is shut down or handle is destroyed. Unregister. - */ -static -int nua_register_usage_shutdown(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du) -{ - nua_t *nua = nh->nh_nua; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - nua_registration_t *nr = nua_dialog_usage_private(du); - msg_t *msg; - sip_t *sip; - - if (du->du_terminating) /* Already terminating? */ - return 100; - - du->du_terminating = 1; - - if (cr->cr_msg) /* Busy */ - return 100; - - outbound_stop_keepalive(nr->nr_ob); - - cr->cr_msg = msg_copy(du->du_msg); - msg = nua_creq_msg(nua, nh, cr, 1, - SIP_METHOD_REGISTER, - NUTAG_USE_DIALOG(1), - TAG_END()); - sip = sip_object(msg); - if (!msg || !sip) - goto error; - - unregister_expires_contacts(msg, sip); - - cr->cr_orq = - outbound_register_request(nr->nr_ob, 1, - nr->nr_by_stack ? nr->nr_contact : NULL, - nh->nh_nua->nua_nta, - process_response_to_register, nh, NULL, - msg, - SIPTAG_END(), - NTATAG_SIGCOMP_CLOSE(1), - TAG_END()); - if (!cr->cr_orq) - goto error; - - cr->cr_usage = du; - cr->cr_event = nua_r_destroy; - return 200; - - error: - nua_dialog_usage_remove(nh, nh->nh_ds, du); - msg_destroy(msg); - msg_destroy(cr->cr_msg); - return 500; -} - - -static -int process_response_to_register(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - nua_client_request_t *cr = nh->nh_ds->ds_cr; - nua_dialog_usage_t *du = cr->cr_usage; - nua_registration_t *nr = nua_dialog_usage_private(du); - int status, ready, reregister, terminating; - char const *phrase; - msg_t *_reqmsg = nta_outgoing_getrequest(orq); - sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg); - - assert(sip); - assert(du && du->du_class == nua_register_usage); - status = sip->sip_status->st_status; - phrase = sip->sip_status->st_phrase; - - if (status < 200 || !du) - return nua_stack_process_response(nh, cr, orq, sip, TAG_END()); - - terminating = du->du_terminating; - if (!terminating) - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - - reregister = outbound_register_response(nr->nr_ob, terminating, req, sip); - if (reregister < 0) - SET_STATUS1(NUA_INTERNAL_ERROR); - else if (reregister >= ob_reregister) { - /* Save msg otherwise nua_creq_check_restart() will zap it */ - msg_t *msg = msg_ref_create(cr->cr_msg); - - if (nua_creq_check_restart(nh, cr, orq, sip, restart_register)) { - msg_destroy(msg); - return 0; + if (contacts) { + if (!cr->cr_terminating) { + for (m = contacts; m; m = m->m_next) + if (!m->m_expires || strtoul(m->m_expires, NULL, 10) != 0) + break; + /* All contacts have expires=0 */ + if (m == NULL) + nua_client_terminating(cr); } - assert(cr->cr_msg == NULL); - cr->cr_msg = msg; - - if (reregister >= ob_reregister_now) { - /* We can try to reregister immediately */ - nua_creq_restart_with(nh, cr, orq, 100, "Updated Contact", - restart_register, - TAG_END()); - } - else { - /* Outbound will invoke refresh_register() later */ - nua_creq_save_restart(nh, cr, orq, 100, "Updated Contact", - restart_register); - } - return 0; - } - - if (status >= 300) - if (nua_creq_check_restart(nh, cr, orq, sip, restart_register)) - return 0; - - ready = !terminating && status < 300; - du->du_ready = ready; - - if (status < 300) { - if (!du->du_terminating) { - sip_time_t mindelta = 0; - sip_time_t now = sip_now(), delta, reqdelta; - sip_contact_t const *m, *sent; - - /** Search for lowest delta of SIP contacts we tried to register */ - mindelta = SIP_TIME_MAX; - - reqdelta = req->sip_expires ? req->sip_expires->ex_delta : 0; - + if (cr->cr_terminating) { + /* Remove the expire parameters from contacts */ for (m = sip->sip_contact; m; m = m->m_next) { - if (m->m_url->url_type != url_sip && - m->m_url->url_type != url_sips) - continue; - for (sent = req->sip_contact; sent; sent = sent->m_next) - if (url_cmp(m->m_url, sent->m_url) == 0) { - sip_time_t mdelta = reqdelta; - - if (sent->m_expires) - mdelta = strtoul(sent->m_expires, NULL, 10); - if (mdelta == 0) - mdelta = 3600; - - delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date, - mdelta, now); - if (delta > 0 && delta < mindelta) - mindelta = delta; - if (url_cmp_all(m->m_url, sent->m_url) == 0) - break; - } + if (m->m_url->url_type == url_any) { + /* If there is a '*' in contact list, remove everything else */ + while (m != sip->sip_contact) + sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact); + while (m->m_next) + sip_header_remove(msg, sip, (sip_header_t *)m->m_next); + contacts = m; + break; + } + msg_header_remove_param(m->m_common, "expires"); } - - if (mindelta == SIP_TIME_MAX) - mindelta = 3600; - nua_dialog_usage_set_expires(du, mindelta); } - else - nua_dialog_usage_set_expires(du, 0); } + unreg = cr->cr_terminating; + + if (du) { + nr = nua_dialog_usage_private(du); + + if (nr->nr_ob) { + outbound_stop_keepalive(nr->nr_ob); + outbound_start_registering(nr->nr_ob); + } + + if (nr->nr_by_stack) { + m = nr->nr_contact; + outbound_get_contacts(nr->nr_ob, &m, &previous); + } + } + + return nua_base_client_trequest(cr, msg, sip, + /* m is stack-generated contact */ + SIPTAG_CONTACT(m), + /* + * previous is outdated stack-generated contact + * which is now unregistered + */ + SIPTAG_CONTACT(previous), + TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")), +#if 0 + TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)), + TAG_IF(!unreg, NTATAG_COMP("sigcomp")), +#endif + TAG_NEXT(tags)); +} + +static int nua_register_client_check_restart(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + nua_registration_t *nr = nua_dialog_usage_private(cr->cr_usage); + unsigned short retry_count = cr->cr_retry_count; + int restart = 0, retry; + + if (nr && nr->nr_ob) { + msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); + sip_t *req = sip_object(_reqmsg); msg_destroy(_reqmsg); + + retry = outbound_register_response(nr->nr_ob, cr->cr_terminating, + req, sip); + + restart = retry >= ob_reregister_now; + + if (retry == ob_reregister) + /* outbound restarts REGISTER later */; + + if (retry < 0) + /* XXX - report an error? */; + } + + /* Check for status-specific reasons to retry */ + if (nua_base_client_check_restart(cr, status, phrase, sip)) + return 1; + + /* Restart only if nua_base_client_check_restart() did not try to restart */ + if (restart && retry_count == cr->cr_retry_count) + return nua_client_restart(cr, status, phrase); + + return 0; +} + +static int nua_register_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_registration_t *nr = nua_dialog_usage_private(du); + int ready; + + ready = du && !cr->cr_terminated && status < 300; + + if (ready) { + sip_time_t mindelta = 0; + sip_time_t now = sip_now(), delta, reqdelta, mdelta; + + sip_contact_t const *m, *sent; + + msg_t *_reqmsg = nta_outgoing_getrequest(cr->cr_orq); + sip_t *req = sip_object(_reqmsg); + + msg_destroy(_reqmsg); + + assert(nr); assert(sip); assert(req); + #if HAVE_SIGCOMP - if (ready) { - struct sigcomp_compartment *cc; - cc = nta_outgoing_compartment(orq); - sigcomp_compartment_unref(nr->nr_compartment); - nr->nr_compartment = cc; - } + { + struct sigcomp_compartment *cc; + cc = nta_outgoing_compartment(cr->cr_orq); + sigcomp_compartment_unref(nr->nr_compartment); + nr->nr_compartment = cc; + } #endif + /* XXX - if store/remove, remove + Content-Disposition + Content-Type + body + */ + + /** Search for lowest delta of SIP contacts we tried to register */ + mindelta = SIP_TIME_MAX; + + reqdelta = req->sip_expires ? req->sip_expires->ex_delta : 0; + + for (m = sip->sip_contact; m; m = m->m_next) { + if (m->m_url->url_type != url_sip && + m->m_url->url_type != url_sips) + continue; + + for (sent = req->sip_contact; sent; sent = sent->m_next) { + if (url_cmp(m->m_url, sent->m_url)) + continue; + + if (sent->m_expires) + mdelta = strtoul(sent->m_expires, NULL, 10); + else + mdelta = reqdelta; + + if (mdelta == 0) + mdelta = 3600; + + delta = sip_contact_expires(m, sip->sip_expires, sip->sip_date, + mdelta, now); + if (delta > 0 && delta < mindelta) + mindelta = delta; + + if (url_cmp_all(m->m_url, sent->m_url) == 0) + break; + } + } + + if (mindelta == SIP_TIME_MAX) + mindelta = 3600; + + nua_dialog_usage_set_expires(du, mindelta); + /* RFC 3608 Section 6.1 Procedures at the UA The UA performs a registration as usual. The REGISTER response may @@ -934,46 +877,104 @@ int process_response_to_register(nua_handle_t *nh, route for that address-of-record. */ - if (ready) { su_free(nh->nh_home, nr->nr_route); nr->nr_route = sip_route_dup(nh->nh_home, sip->sip_service_route); - } - else { - su_free(nh->nh_home, nr->nr_route); - nr->nr_route = NULL; - } - if (ready) { - /* RFC 3327 */ - /* Store last URI in Path header */ - sip_path_t *path = sip->sip_path; + { + /* RFC 3327 */ + /* Store last URI in Path header */ + sip_path_t *path = sip->sip_path; - while (path && path->r_next) - path = path->r_next; + while (path && path->r_next) + path = path->r_next; - if (!nr->nr_path || !path || - url_cmp_all(nr->nr_path->r_url, path->r_url)) { - su_free(nh->nh_home, nr->nr_path); - nr->nr_path = sip_path_dup(nh->nh_home, path); + if (!nr->nr_path || !path || + url_cmp_all(nr->nr_path->r_url, path->r_url)) { + su_free(nh->nh_home, nr->nr_path); + nr->nr_path = sip_path_dup(nh->nh_home, path); + } } - } - if (ready) if (sip->sip_to->a_url->url_type == url_sips) nr->nr_secure = 1; - if (nr->nr_ob) { - if (ready) { + if (nr->nr_ob) { outbound_gruuize(nr->nr_ob, sip); - outbound_start_keepalive(nr->nr_ob, orq); + outbound_start_keepalive(nr->nr_ob, cr->cr_orq); } - else - outbound_stop_keepalive(nr->nr_ob); + + /* persistant connection for registration */ + if (!nr->nr_tport) + /* note: nta_outgoing_transport() takes a ref */ + nr->nr_tport = nta_outgoing_transport (cr->cr_orq); + + nua_registration_set_ready(nr, 1); + } + else if (du) { + nua_dialog_usage_set_expires(du, 0); + + su_free(nh->nh_home, nr->nr_route); + nr->nr_route = NULL; + + outbound_stop_keepalive(nr->nr_ob); + + /* release the persistant transport for registration */ + if (nr->nr_tport) + tport_decref(&nr->nr_tport), nr->nr_tport = NULL; + + nua_registration_set_ready(nr, 0); } - nua_registration_set_ready(nr, ready); - return nua_stack_process_response(nh, cr, orq, sip, TAG_END()); + return nua_base_client_response(cr, status, phrase, sip, NULL); +} + +static void nua_register_usage_refresh(nua_handle_t *nh, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du, + sip_time_t now) +{ + nua_t *nua = nh->nh_nua; + nua_client_request_t *cr = du->du_cr; + + if (cr) { + if (nua_client_is_queued(cr) /* Already registering. */ + || nua_client_resend_request(cr, 0, NULL) >= 0) + return; + } + + /* Report that we have de-registered */ + nua_stack_event(nua, nh, NULL, nua_r_register, NUA_INTERNAL_ERROR, NULL); + nua_dialog_usage_remove(nh, ds, du); +} + +/** @interal Shut down REGISTER usage. + * + * @retval >0 shutdown done + * @retval 0 shutdown in progress + * @retval <0 try again later + */ +static int nua_register_usage_shutdown(nua_handle_t *nh, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du) +{ + nua_client_request_t *cr = du->du_cr; + nua_registration_t *nr = nua_dialog_usage_private(du); + + if (cr) { + if (nua_client_is_queued(cr)) /* Already registering. */ + return -1; + cr->cr_event = nua_r_unregister; + if (nua_client_resend_request(cr, 1, NULL) >= 0) + return 0; + } + + /* release the persistant transport for registration */ + if (nr->nr_tport) + tport_decref(&nr->nr_tport), nr->nr_tport = NULL; + + nua_dialog_usage_remove(nh, ds, du); + return 200; } /* ---------------------------------------------------------------------- */ @@ -984,7 +985,8 @@ int process_response_to_register(nua_handle_t *nh, #endif static void nua_stack_tport_update(nua_t *nua, nta_agent_t *nta); -static int nua_registration_add_contact_and_route(nua_registration_t *nr, +static int nua_registration_add_contact_and_route(nua_handle_t *nh, + nua_registration_t *nr, msg_t *msg, sip_t *sip, int add_contact, @@ -1081,9 +1083,7 @@ void nua_network_changed_cb(nua_t *nua, su_root_t *root) switch (nw_updates) { case NUA_NW_DETECT_ONLY_INFO: - nua_stack_event(nua, NULL, NULL, nua_i_network_changed, - SIP_200_OK, TAG_END()); - + nua_stack_event(nua, NULL, NULL, nua_i_network_changed, SIP_200_OK, NULL); break; case NUA_NW_DETECT_TRY_FULL: @@ -1095,10 +1095,10 @@ void nua_network_changed_cb(nua_t *nua, su_root_t *root) if (nua_stack_init_transport(nua, nua->nua_args) < 0) /* We are hosed */ nua_stack_event(nua, NULL, NULL, nua_i_network_changed, - 900, "Internal Error", TAG_END()); + 900, "Internal Error", NULL); else nua_stack_event(nua, NULL, NULL, nua_i_network_changed, - SIP_200_OK, TAG_END()); + SIP_200_OK, NULL); break; @@ -1482,7 +1482,7 @@ int nua_registration_add_contact_to_request(nua_handle_t *nh, if (nr == NULL) nr = nua_registration_for_request(nh->nh_nua->nua_registrations, sip); - return nua_registration_add_contact_and_route(nr, msg, sip, + return nua_registration_add_contact_and_route(nh, nr, msg, sip, add_contact, add_service_route); } @@ -1513,12 +1513,15 @@ int nua_registration_add_contact_to_response(nua_handle_t *nh, nr = nua_registration_for_response(nh->nh_nua->nua_registrations, sip, record_route, remote_contact); - return nua_registration_add_contact_and_route(nr, msg, sip, 1, 0); + return nua_registration_add_contact_and_route(nh, nr, msg, sip, + 1, + 0); } /** Add a Contact (and Route) header to request */ static -int nua_registration_add_contact_and_route(nua_registration_t *nr, +int nua_registration_add_contact_and_route(nua_handle_t *nh, + nua_registration_t *nr, msg_t *msg, sip_t *sip, int add_contact, @@ -1529,7 +1532,34 @@ int nua_registration_add_contact_and_route(nua_registration_t *nr, if (add_contact) { sip_contact_t const *m = nua_registration_contact(nr); - if (!m || msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)m) < 0) + + char const *m_display = NH_PGET(nh, m_display); + char const *m_username = NH_PGET(nh, m_username); + char const *m_params = NH_PGET(nh, m_params); + url_t const *u = m->m_url; + + if (!m) + return -1; + + if (str0cmp(m_params, u->url_params) == 0) + m_params = NULL; + + m = sip_contact_format(msg_home(msg), + "%s<%s:%s%s%s%s%s%s%s%s%s>", + m_display ? m_display : + m->m_display ? m->m_display : "", + u->url_scheme, + m_username ? m_username : "", + m_username ? "@" : "", + u->url_host, + u->url_port ? ":" : "", + u->url_port ? u->url_port : "", + u->url_params ? ";" : "", + u->url_params ? u->url_params : "", + m_params ? ";" : "", + m_params ? m_params : ""); + + if (msg_header_insert(msg, (msg_pub_t *)sip, (void *)m) < 0) return -1; } @@ -1639,8 +1669,10 @@ int nua_registration_set_contact(nua_handle_t *nh, /** Mark registration as ready */ void nua_registration_set_ready(nua_registration_t *nr, int ready) { - assert(!ready || nr->nr_contact); - nr->nr_ready = ready; + if (nr) { + assert(!ready || nr->nr_contact); + nr->nr_ready = ready; + } } /** @internal Hook for processing incoming request by registration. @@ -1670,48 +1702,6 @@ int nua_registration_process_request(nua_registration_t *list, return 481; /* Call/Transaction does not exist */ } -/**@internal - * Fix contacts for un-REGISTER. - * - * Remove (possible non-zero) "expires" parameters from contacts and extra - * contacts, add Expire: 0. - */ -static -void unregister_expires_contacts(msg_t *msg, sip_t *sip) -{ - sip_contact_t *m; - int unregister_all; - - if (msg == NULL || sip == NULL) - return; - - /* Remove payload */ - while (sip->sip_payload) - sip_header_remove(msg, sip, (sip_header_t *)sip->sip_payload); - while (sip->sip_content_type) - sip_header_remove(msg, sip, (sip_header_t *)sip->sip_content_type); - - for (m = sip->sip_contact; m; m = m->m_next) { - if (m->m_url->url_type == url_any) - break; - msg_header_remove_param(m->m_common, "expires"); -#if 0 - msg_header_add_param(msg_home(msg), m->m_common, "expires=0"); -#endif - } - - unregister_all = m && (m != sip->sip_contact || m->m_next); - - sip_add_tl(msg, sip, - /* Remove existing contacts */ - TAG_IF(unregister_all, SIPTAG_CONTACT(NONE)), - /* Add '*' contact: 0 */ - TAG_IF(unregister_all, SIPTAG_CONTACT_STR("*")), - SIPTAG_EXPIRES_STR("0"), - TAG_END()); -} - - /** Outbound requests us to refresh registration */ static int nua_stack_outbound_refresh(nua_handle_t *nh, outbound_t *ob) @@ -1758,7 +1748,7 @@ static int nua_stack_outbound_status(nua_handle_t *nh, outbound_t *ob, nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, - ta_tags(ta)); + ta_args(ta)); ta_end(ta); @@ -1775,7 +1765,7 @@ static int nua_stack_outbound_failed(nua_handle_t *nh, outbound_t *ob, nua_stack_event(nh->nh_nua, nh, NULL, nua_i_outbound, status, phrase, - ta_tags(ta)); + ta_args(ta)); ta_end(ta); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c index 847102b79f..6e7deb428b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_registrar.c @@ -44,8 +44,6 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s #define NTA_INCOMING_MAGIC_T struct nua_handle_s #define NTA_RELIABLE_MAGIC_T struct nua_handle_s @@ -89,15 +87,19 @@ * @END_NUA_EVENT */ -int nua_stack_process_register(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_server_request_t *sr, sr0[1]; - - sr = nua_server_request(nua, nh, irq, sip, SR_INIT(sr0), sizeof *sr, - nua_default_respond, 0); - - return nua_stack_server_event(nua, sr, nua_i_register, TAG_END()); -} +nua_server_methods_t const nua_register_server_methods = + { + SIP_METHOD_REGISTER, + nua_i_register, /* Event */ + { + 0, /* Do not create dialog */ + 0, /* Initial request */ + 0, /* Not a target refresh request */ + 0, /* Do not add Contact */ + }, + nua_base_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_base_server_report, + }; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index 60d4398f16..e5d2600def 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -45,9 +45,8 @@ #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s #define NTA_INCOMING_MAGIC_T struct nua_server_request +#define NTA_OUTGOING_MAGIC_T struct nua_client_request #define NTA_RELIABLE_MAGIC_T struct nua_handle_s #include "nua_stack.h" @@ -141,8 +140,7 @@ sip_response_terminates_dialog(). /** Session-related state */ typedef struct nua_session_usage { - /* enum nua_callstate */ - unsigned ss_state:4; /**< Session status (enum nua_callstate) */ + enum nua_callstate ss_state; /**< Session status (enum nua_callstate) */ unsigned ss_100rel:1; /**< Use 100rel, send 183 */ unsigned ss_alerting:1; /**< 180 is sent/received */ @@ -152,17 +150,16 @@ typedef struct nua_session_usage unsigned ss_precondition:1; /**< Precondition required */ unsigned ss_timer_set:1; /**< We have active session timer. */ + + unsigned ss_reporting:1; /**< True if reporting state */ unsigned : 0; unsigned ss_session_timer; /**< Value of Session-Expires (delta) */ unsigned ss_min_se; /**< Minimum session expires */ enum nua_session_refresher ss_refresher; /**< none, local or remote */ - char const *ss_ack_needed; /**< If non-null, need to send an ACK - * (do O/A, if "offer" or "answer") - */ - - nua_client_request_t ss_crequest[1]; /* Outgoing invite */ + char const *ss_oa_recv, *ss_oa_sent; + char const *ss_reason; /**< Reason for termination. */ } nua_session_usage_t; static char const *nua_session_usage_name(nua_dialog_usage_t const *du); @@ -202,14 +199,10 @@ int nua_session_usage_add(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { - nua_session_usage_t *ss = nua_dialog_usage_private(du); - if (ds->ds_has_session) return -1; ds->ds_has_session = 1; - nh->nh_ds->ds_cr->cr_next = ss->ss_crequest; - return 0; } @@ -221,11 +214,17 @@ void nua_session_usage_remove(nua_handle_t *nh, nua_session_usage_t *ss = nua_dialog_usage_private(du); ds->ds_has_session = 0; + + (void)ss; +} - if (ss->ss_crequest) - nua_creq_deinit(ss->ss_crequest, NULL); +static +nua_dialog_usage_t *nua_dialog_usage_for_session(nua_dialog_state_t const *ds) +{ + if (ds == ((nua_handle_t *)NULL)->nh_ds) + return NULL; - ds->ds_cr->cr_next = NULL; + return nua_dialog_usage_get(ds, nua_session_usage, NULL); } static @@ -241,38 +240,37 @@ nua_session_usage_t *nua_session_usage_get(nua_dialog_state_t const *ds) return (nua_session_usage_t *)nua_dialog_usage_private(du); } +/** Zap the session associated with the handle */ +static +void nua_session_usage_destroy(nua_handle_t *nh, + nua_session_usage_t *ss) +{ + nh->nh_has_invite = 0; + nh->nh_active_call = 0; + nh->nh_hold_remote = 0; + + if (nh->nh_soa) + soa_destroy(nh->nh_soa), nh->nh_soa = NULL; + + /* Remove usage */ + nua_dialog_usage_remove(nh, nh->nh_ds, nua_dialog_usage_public(ss)); + + SU_DEBUG_5(("nua: terminated session %p\n", (void *)nh)); +} + /* ======================================================================== */ /* INVITE and call (session) processing */ -static int nua_stack_invite2(nua_t *, nua_handle_t *, nua_event_t e, - int restarted, tagi_t const *tags); -static int process_response_to_invite(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); -static void - session_timeout(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now); - -static void restart_invite(nua_handle_t *nh, tagi_t *tags); - -static int process_100rel(nua_handle_t *nh, - nua_session_usage_t *ss, - nta_outgoing_t *orq, - sip_t const *sip); - int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags); -static int process_response_to_prack(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -static void nua_session_usage_destroy(nua_handle_t *, nua_session_usage_t *); - static void session_timer_preferences(nua_session_usage_t *ss, unsigned expires, unsigned min_se, enum nua_session_refresher refresher); + static int session_timer_is_supported(nua_handle_t const *nh); + static int prefer_session_timer(nua_handle_t const *nh); static int use_session_timer(nua_session_usage_t *ss, int uas, int always, @@ -280,24 +278,18 @@ static int use_session_timer(nua_session_usage_t *ss, int uas, int always, static int init_session_timer(nua_session_usage_t *ss, sip_t const *, int refresher); static void set_session_timer(nua_session_usage_t *ss); -static int -check_session_timer_restart(nua_handle_t *nh, - nua_session_usage_t *ss, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - nua_creq_restart_f *restart_function); +static int session_timer_check_restart(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); static int nh_referral_check(nua_handle_t *nh, tagi_t const *tags); static void nh_referral_respond(nua_handle_t *, int status, char const *phrase); static void signal_call_state_change(nua_handle_t *nh, - nua_session_usage_t *ss, - int status, char const *phrase, - enum nua_callstate next_state, - char const *oa_recv, - char const *oa_sent); + nua_session_usage_t *ss, + int status, char const *phrase, + enum nua_callstate next_state); static int session_get_description(sip_t const *sip, @@ -319,16 +311,9 @@ int session_make_description(su_home_t *home, sip_payload_t **return_pl); static -int session_process_response(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - char const **return_received); - -static -int respond_with_retry_after(nua_handle_t *nh, nta_incoming_t *irq, - int status, char const *phrase, - int min, int max); +int nua_server_retry_after(nua_server_request_t *sr, + int status, char const *phrase, + int min, int max); /**@fn void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * @@ -475,322 +460,442 @@ int respond_with_retry_after(nua_handle_t *nh, nta_incoming_t *irq, /* Tags not implemented * NUTAG_REFER_PAUSE() \n */ -int -nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags) + +static int nua_invite_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_invite_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_invite_client_preliminary(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_invite_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_session_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_invite_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags); +static int nua_invite_client_ack_msg(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); + +static int nua_invite_client_deinit(nua_client_request_t *cr); + +nua_client_methods_t const nua_invite_client_methods = { + SIP_METHOD_INVITE, + 0, + { + /* create_dialog */ 1, + /* in_dialog */ 1, + /* target refresh */ 1 + }, + NULL, + nua_invite_client_init, + nua_invite_client_request, + session_timer_check_restart, + nua_invite_client_response, + nua_invite_client_preliminary, + nua_invite_client_report, + nua_invite_client_deinit +}; + +extern nua_client_methods_t const nua_bye_client_methods; +extern nua_client_methods_t const nua_cancel_client_methods; +extern nua_client_methods_t const nua_info_client_methods; +extern nua_client_methods_t const nua_update_client_methods; +extern nua_client_methods_t const nua_prack_client_methods; + +int nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e, + tagi_t const *tags) { - char const *what; - - if (nh_is_special(nh) || - nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error)) - what = "Invalid handle for INVITE"; - else if (nh_referral_check(nh, tags) < 0) { - what = "Invalid referral"; - } - else if (nua_stack_init_handle(nua, nh, TAG_NEXT(tags)) < 0) { - what = "Handle initialization failed"; - } - else - return nua_stack_invite2(nua, nh, e, 0, tags); - - UA_EVENT2(e, 900, what); - - signal_call_state_change(nh, NULL, 900, what, nua_callstate_init, 0, 0); - - return e; + return nua_client_create(nh, e, &nua_invite_client_methods, tags); } -static int -nua_stack_invite2(nua_t *nua, nua_handle_t *nh, nua_event_t e, - int restarted, - tagi_t const *tags) +static int nua_invite_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { + nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du; - nua_session_usage_t *ss; - nua_client_request_t *cr; - int offer_sent = 0; - msg_t *msg = NULL; - sip_t *sip = NULL; + cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds); + + if (nh_is_special(nh) || + nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error)) + return nua_client_return(cr, 900, "Invalid handle for INVITE", msg); + else if (nh_referral_check(nh, tags) < 0) + return nua_client_return(cr, 900, "Invalid referral", msg); - char const *what; + if (!du) + du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL); + if (!du) + return -1; - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL); - ss = nua_dialog_usage_private(du); - cr = ss->ss_crequest; - what = nua_internal_error; /* Internal error */ + if (nua_client_bind(cr, du) < 0) + return nua_client_return(cr, 900, "INVITE already in progress", msg); - if (du == NULL) - goto failure; + session_timer_preferences(nua_dialog_usage_private(du), + NH_PGET(nh, session_timer), + NH_PGET(nh, min_se), + NH_PGET(nh, refresher)); - if (cr->cr_orq) { - what = "INVITE request already in progress"; - goto failure; - } + return 0; +} - if (ss->ss_state == nua_callstate_terminated) - ss->ss_state = nua_callstate_init; +static int nua_invite_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + int offer_sent = 0, retval; + sip_time_t invite_timeout; - if (!restarted) { - session_timer_preferences(ss, - NH_PGET(nh, session_timer), - NH_PGET(nh, min_se), - NH_PGET(nh, refresher)); - } + if (du == NULL) /* Call terminated */ + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); - if (restarted && !cr->cr_msg) { - if (du->du_msg) - cr->cr_msg = msg_dup(du->du_msg); - else - restarted = 0; - } + assert(ss); - msg = nua_creq_msg(nua, nh, cr, restarted, - SIP_METHOD_INVITE, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - sip = sip_object(msg); + invite_timeout = NH_PGET(nh, invite_timeout); + if (invite_timeout == 0) + invite_timeout = UINT_MAX; + /* Cancel if we don't get response within timeout*/ + nua_dialog_usage_set_expires(du, invite_timeout); + nua_dialog_usage_set_refresh(du, 0); - if (!sip) { - what = "Cannot Initialize Request"; - goto failure; - } + /* Add session timer headers */ + if (session_timer_is_supported(nh)) + use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip); - if (!restarted) { - msg_destroy(du->du_msg), du->du_msg = msg_dup(msg); - } + ss->ss_100rel = NH_PGET(nh, early_media); + ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition"); + if (ss->ss_precondition) + ss->ss_update_needed = ss->ss_100rel = 1; if (nh->nh_soa) { soa_init_offer_answer(nh->nh_soa); if (sip->sip_payload) - offer_sent = 0; + offer_sent = 0; /* XXX - kludge */ else if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) - offer_sent = -1; + return -1; else offer_sent = 1; } - if (offer_sent >= 0) { - sip_time_t invite_timeout = NH_PGET(nh, invite_timeout); - if (invite_timeout == 0) - invite_timeout = UINT_MAX; - /* Cancel if we don't get response within timeout*/ - nua_dialog_usage_set_expires(du, invite_timeout); - nua_dialog_usage_set_refresh(du, 0); + if (offer_sent > 0 && + session_include_description(nh->nh_soa, 1, msg, sip) < 0) + return nua_client_return(cr, 900, "Internal media error", msg); - /* Add session timer headers */ - if (session_timer_is_supported(nh)) - use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip); + if (nh->nh_soa && + NH_PGET(nh, media_features) && + !nua_dialog_is_established(nh->nh_ds) && + !sip->sip_accept_contact && !sip->sip_reject_contact) { + sip_accept_contact_t ac[1]; + sip_accept_contact_init(ac); - ss->ss_100rel = NH_PGET(nh, early_media); - ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition"); + ac->cp_params = (msg_param_t *) + soa_media_features(nh->nh_soa, 1, msg_home(msg)); - if (ss->ss_precondition) - ss->ss_update_needed = ss->ss_100rel = 1; - - if (offer_sent > 0 && - session_include_description(nh->nh_soa, 1, msg, sip) < 0) { - what = "Internal media error"; goto failure; - } - - if (nh->nh_soa && - NH_PGET(nh, media_features) && !nua_dialog_is_established(nh->nh_ds) && - !sip->sip_accept_contact && !sip->sip_reject_contact) { - sip_accept_contact_t ac[1]; - sip_accept_contact_init(ac); - - ac->cp_params = (msg_param_t *) - soa_media_features(nh->nh_soa, 1, msg_home(msg)); - - if (ac->cp_params) { - msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit"); - sip_add_dup(msg, sip, (sip_header_t *)ac); - } - } - - if (nh->nh_auth) { - if (auc_authorize(&nh->nh_auth, msg, sip) < 0) { - what = "Internal authentication error"; goto failure; - } - } - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_invite, nh, NULL, - msg, - NTATAG_REL100(ss->ss_100rel), - SIPTAG_END(), TAG_NEXT(tags)); - - if (cr->cr_orq) { - cr->cr_offer_sent = offer_sent; - cr->cr_usage = du; - du->du_refresh = 0; - signal_call_state_change(nh, ss, 0, "INVITE sent", - nua_callstate_calling, 0, - offer_sent ? "offer" : 0); - return cr->cr_event = e; + if (ac->cp_params) { + msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit"); + sip_add_dup(msg, sip, (sip_header_t *)ac); } } - failure: + retval = nua_base_client_trequest(cr, msg, sip, + NTATAG_REL100(ss->ss_100rel), + TAG_NEXT(tags)); + if (retval == 0) { + cr->cr_offer_sent = offer_sent; + ss->ss_oa_sent = offer_sent ? "offer" : NULL; - msg_destroy(msg); - if (du && !du->du_ready) - nua_dialog_usage_remove(nh, nh->nh_ds, du), ss = NULL; + if (!cr->cr_restarting) + signal_call_state_change(nh, ss, 0, "INVITE sent", + nua_callstate_calling); + } - UA_EVENT2(e, 900, what); - signal_call_state_change(nh, ss, 900, what, nua_callstate_init, 0, 0); - - return e; + return retval; } -/** @NUA_EVENT nua_r_invite - * - * Answer to outgoing INVITE. - * - * The INVITE may be sent explicitly by nua_invite() or - * implicitly by NUA state machine. - * - * @param status response status code - * (if the request is retried, @a status is 100, the @a - * sip->sip_status->st_status contain the real status code - * from the response message, e.g., 302, 401, or 407) - * @param phrase a short textual description of @a status code - * @param nh operation handle associated with the call - * @param hmagic application context associated with the call - * @param sip response message to INVITE or NULL upon an error - * (status code is in @a status and - * descriptive message in @a phrase parameters) - * @param tags empty - * - * @sa nua_invite(), @ref nua_call_model, #nua_i_state, #nua_i_invite, - * nua_ack(), NUTAG_AUTOACK() - * - * @END_NUA_EVENT - */ - -static int process_response_to_invite(nua_handle_t *nh, - nta_outgoing_t *orq, +static int nua_invite_client_response(nua_client_request_t *cr, + int status, char const *phrase, sip_t const *sip) { - nua_t *nua = nh->nh_nua; - nua_client_request_t *cr; - nua_dialog_usage_t *du; - nua_session_usage_t *ss; - int status = sip->sip_status->st_status; - char const *phrase = sip->sip_status->st_phrase; - int terminated = 0; - int gracefully = 1; - char const *received = NULL; + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); - cr = nua_client_request_by_orq(nh->nh_ds->ds_cr, orq); - du = cr ? cr->cr_usage : NULL; - ss = nua_dialog_usage_private(du); - - assert(cr && du && ss); - - if (ss->ss_state == nua_callstate_terminating && 200 <= status) { - /* - * If the call is being terminated but re-INVITE was responded with 2XX - * re-send the BYE, otherwise terminate the call. - */ - gracefully = status < 300, terminated = !gracefully; + if (ss == NULL || sip == NULL) { + /* Xyzzy */ } - else if (status >= 300) { - if (sip->sip_retry_after) - gracefully = 0; - - terminated = sip_response_terminates_dialog(status, sip_method_invite, - &gracefully); - - if (!terminated) { - if (check_session_timer_restart(nh, ss, cr, orq, sip, restart_invite)) - return 0; - - if (ss->ss_state < nua_callstate_ready) - terminated = 1; - } - } - else if (status >= 200) { + else if (status < 300) { du->du_ready = 1; - cr->cr_usage = NULL; - - /* XXX - check remote tag, handle forks */ - /* Set route, contact, nh_ds->ds_remote_tag */ - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); init_session_timer(ss, sip, NH_PGET(nh, refresher)); set_session_timer(ss); - - /* signal_call_state_change */ - if (session_process_response(nh, cr, orq, sip, &received) >= 0) { - ss->ss_ack_needed = received ? received : ""; - - if (NH_PGET(nh, auto_ack) || - /* Auto-ACK response to re-INVITE unless auto_ack is set to 0 */ - (ss->ss_state == nua_callstate_ready && - !NH_PISSET(nh, auto_ack))) - nua_stack_ack(nua, nh, nua_r_ack, NULL); - else - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_completing, received, 0); - nh_referral_respond(nh, SIP_200_OK); - return 0; - } - - status = 500, phrase = "Malformed Session in Response"; - - nua_stack_ack(nua, nh, nua_r_ack, NULL); - gracefully = 1; } - else if (sip->sip_rseq) { - /* Reliable provisional response */ - nh_referral_respond(nh, status, phrase); + + return nua_session_client_response(cr, status, phrase, sip); +} - return process_100rel(nh, ss, orq, sip); /* signal_call_state_change */ +static int nua_invite_client_preliminary(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + assert(sip); assert(ss); + + if (ss && sip && sip->sip_rseq) { + /* Handle 100rel responses */ + sip_rseq_t *rseq = sip->sip_rseq; + + /* Establish early dialog - we should fork here */ + if (!nua_dialog_is_established(nh->nh_ds)) { + nta_outgoing_t *tagged; + + nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); + nua_dialog_store_peer_info(nh, nh->nh_ds, sip); + + /* Tag the INVITE request */ + tagged = nta_outgoing_tagged(cr->cr_orq, + nua_client_orq_response, cr, + sip->sip_to->a_tag, sip->sip_rseq); + if (tagged) { + nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged; + } + else { + cr->cr_graceful = 1; + ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\""; + } + } + + if (!rseq) { + SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh)); + } + else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) { + SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh, + (unsigned)rseq->rs_response, + nta_outgoing_rseq(cr->cr_orq))); + return 1; /* Do not send event */ + } + else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) { + SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh, + (unsigned)rseq->rs_response)); + cr->cr_graceful = 1; + ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\""; + } + } + + return nua_session_client_response(cr, status, phrase, sip); +} + +/** Process response to a session request (INVITE, PRACK, UPDATE) */ +static int nua_session_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + char const *sdp = NULL; + size_t len; + char const *received = NULL; + +#define LOG3(m) \ + SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \ + (void *)nh, cr->cr_method_name, (m), \ + received ? received : "SDP", status, phrase)) +#define LOG5(m) \ + SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \ + (void *)nh, cr->cr_method_name, (m), received, status, phrase)) + + if (nh->nh_soa == NULL || !ss || !sip || 300 <= status) + /* Xyzzy */; + else if (!session_get_description(sip, &sdp, &len)) + /* No SDP */; + else if (cr->cr_answer_recv) { + /* Ignore spurious answers after completing O/A */ + LOG3("ignoring duplicate"); + sdp = NULL; + } + else if (cr->cr_offer_sent) { + /* case 1: incoming answer */ + cr->cr_answer_recv = status; + received = "answer"; + + if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { + LOG3("error parsing SDP"); + sdp = NULL; + cr->cr_graceful = 1; + ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; + } + else if (soa_process_answer(nh->nh_soa, NULL) < 0) { + LOG5("error processing SDP"); + /* XXX */ + sdp = NULL; + } + else if (soa_activate(nh->nh_soa, NULL) < 0) + /* XXX - what about errors? */ + LOG3("error activating media after"); + else + LOG5("processed SDP"); + } + else if (cr->cr_method != sip_method_invite) { + /* If non-invite request did not have offer, ignore SDP in response */ + LOG3("ignoring extra"); + sdp = NULL; } else { - /* Provisional response */ - nh_referral_respond(nh, status, phrase); - session_process_response(nh, cr, orq, sip, &received); - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_proceeding, received, 0); - return 0; + /* case 2: answer to our offer */ + cr->cr_offer_recv = 1, cr->cr_answer_sent = 0; + received = "offer"; + + if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { + LOG3("error parsing SDP"); + sdp = NULL; + cr->cr_graceful = 1; + ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\""; + } + else + LOG5("got SDP"); } - cr->cr_usage = NULL; + if (ss && received) + ss->ss_oa_recv = received; + + if (sdp) + return nua_base_client_tresponse(cr, status, phrase, sip, + NH_REMOTE_MEDIA_TAGS(1, nh->nh_soa), + TAG_END()); + else + return nua_base_client_response(cr, status, phrase, sip, NULL); +} + +static int nua_invite_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + unsigned next_state; + int error; nh_referral_respond(nh, status, phrase); - nua_stack_process_response(nh, cr, orq, sip, TAG_END()); - if (terminated) - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_terminated, 0, 0); + nua_stack_event(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + tags); - if (terminated < 0) { - nua_dialog_terminated(nh, nh->nh_ds, status, phrase); + if (orq != cr->cr_orq && status != 100) + return 1; + + ss->ss_reporting = 1; + + if (ss == NULL) { + next_state = nua_callstate_terminated; } - else if (terminated > 0) { - nua_dialog_usage_remove(nh, nh->nh_ds, du); + else if (status == 100) { + next_state = nua_callstate_calling; } - else if (gracefully) { - char *reason = - su_sprintf(NULL, "SIP;cause=%u;text=\"%s\"", - status > 699 ? 500 : status, phrase); + else if (status < 300 && cr->cr_graceful) { + next_state = nua_callstate_terminating; + if (200 <= status) { + nua_invite_client_ack(cr, NULL); + } + } + else if (status < 200) { + next_state = nua_callstate_proceeding; + if (sip && sip->sip_rseq) { + sip_rack_t rack[1]; - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_terminating, 0, 0); + sip_rack_init(rack); + rack->ra_response = sip->sip_rseq->rs_response; + rack->ra_cseq = sip->sip_cseq->cs_seq; + rack->ra_method = sip->sip_cseq->cs_method; + rack->ra_method_name = sip->sip_cseq->cs_method_name; - nua_stack_post_signal(nh, nua_r_bye, - SIPTAG_REASON_STR(reason), - TAG_END()); - - su_free(NULL, reason); + error = nua_client_tcreate(nh, nua_r_prack, &nua_prack_client_methods, + SIPTAG_RACK(rack), + TAG_END()); + if (error < 0) { + cr->cr_graceful = 1; + next_state = nua_callstate_terminating; + } + } + } + else if (status < 300) { + next_state = nua_callstate_completing; + } + else if (cr->cr_terminated) { + next_state = nua_callstate_terminated; + } + else if (cr->cr_graceful && ss->ss_state >= nua_callstate_completing) { + next_state = nua_callstate_terminating; + } + else { + next_state = nua_callstate_init; } - return 0; + if (next_state == nua_callstate_calling) { + if (sip && sip->sip_status && sip->sip_status->st_status == 100) { + ss->ss_reporting = 0; + return 1; + } + } + + if (next_state == nua_callstate_completing) { + if (NH_PGET(nh, auto_ack) || + /* Auto-ACK response to re-INVITE unless auto_ack is set to 0 */ + (ss->ss_state == nua_callstate_ready && + !NH_PISSET(nh, auto_ack))) { + + if (nua_invite_client_ack(cr, NULL) > 0) + next_state = nua_callstate_ready; + else + next_state = nua_callstate_terminating; + } + } + + if (next_state == nua_callstate_terminating) { + /* Send BYE or CANCEL */ + /* XXX - Forking - send BYE to early dialog?? */ + if (ss->ss_state > nua_callstate_proceeding || status >= 200) + error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); + else + error = nua_client_create(nh, nua_r_cancel, + &nua_cancel_client_methods, tags); + + if (error) { + next_state = nua_callstate_terminated; + cr->cr_terminated = 1; + } + cr->cr_graceful = 0; + } + + ss->ss_reporting = 0; + + signal_call_state_change(nh, ss, status, phrase, next_state); + + return 1; } /**@fn void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); @@ -798,7 +903,7 @@ static int process_response_to_invite(nua_handle_t *nh, * Acknowledge a succesful response to INVITE request. * * Acknowledge a successful response (200..299) to INVITE request with the - * SIP ACK request message. This function is need only if NUTAG_AUTOACK() + * SIP ACK request message. This function is needed only if NUTAG_AUTOACK() * parameter has been cleared. * * @param nh Pointer to operation handle @@ -812,7 +917,7 @@ static int process_response_to_invite(nua_handle_t *nh, * * @par Events: * #nua_i_media_error \n - * #nua_i_state (#nua_i_active, #nua_i_terminated) + * #nua_i_state (#nua_i_active, #nua_i_terminating, #nua_i_terminated) * * @sa NUTAG_AUTOACK(), @ref nua_call_model, #nua_i_state */ @@ -820,55 +925,147 @@ static int process_response_to_invite(nua_handle_t *nh, int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_session_usage_t *ss; - nua_client_request_t *cr; - nta_outgoing_t *ack = NULL; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + if (!du || + !du->du_cr || + du->du_cr->cr_orq == NULL || + du->du_cr->cr_status < 200) { + UA_EVENT2(nua_i_error, 900, "No response to ACK"); + return 1; + } + + if (tags) { + nua_stack_set_params(nua, nh, nua_i_error, tags); + if (nh->nh_soa) + soa_set_params(nh->nh_soa, TAG_NEXT(tags)); + } + + if (nua_invite_client_ack(du->du_cr, tags) < 0) { + int error; + ss->ss_reason = "SIP;cause=500;text=\"Internal Error\""; + ss->ss_reporting = 1; /* We report state here if BYE fails */ + error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); + ss->ss_reporting = 0; + signal_call_state_change(nh, ss, 500, "Internal Error", + error + ? nua_callstate_terminated + : nua_callstate_terminating); + } + + return 0; +} + +/** Send ACK, destroy INVITE transaction. + * + * @retval 1 if successful + * @retval < 0 if an error occurred + */ +static +int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_state_t *ds = nh->nh_ds; + msg_t *msg; sip_t *sip; + int error = -1; + sip_authorization_t *wa; + sip_proxy_authorization_t *pa; + sip_cseq_t *cseq; + + assert(ds->ds_leg); + assert(cr->cr_orq); + + msg = nta_outgoing_getrequest(cr->cr_orq); + sip = sip_object(msg); + if (!msg) + return -1; + + wa = sip_authorization(sip); + pa = sip_proxy_authorization(sip); + + msg_destroy(msg); + + msg = nta_msg_create(nh->nh_nua->nua_nta, 0); + sip = sip_object(msg); + if (!msg) + return -1; + + cseq = sip_cseq_create(msg_home(msg), cr->cr_seq, SIP_METHOD_ACK); + + if (!cseq) + ; + else if (nh->nh_tags && sip_add_tl(msg, sip, TAG_NEXT(nh->nh_tags)) < 0) + ; + else if (tags && sip_add_tl(msg, sip, TAG_NEXT(tags)) < 0) + ; + else if (wa && sip_add_dup(msg, sip, (sip_header_t *)wa) < 0) + ; + else if (pa && sip_add_dup(msg, sip, (sip_header_t *)pa) < 0) + ; + else if (sip_header_insert(msg, sip, (sip_header_t *)cseq) < 0) + ; + else if (nta_msg_request_complete(msg, ds->ds_leg, SIP_METHOD_ACK, NULL) < 0) + ; + else + error = nua_invite_client_ack_msg(cr, msg, sip, tags); + + nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; + + if (error == -1) + msg_destroy(msg); + + return error; +} + +/** Send ACK, destroy INVITE transaction. + * + * @retval 1 if successful + * @retval -2 if an error occurred + */ +static +int nua_invite_client_ack_msg(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + nta_outgoing_t *ack; int status = 200; - char const *phrase = "OK", *reason = NULL, *sent = NULL; - char const *received; + char const *phrase = "OK", *reason = NULL; - ss = nua_session_usage_get(nh->nh_ds); - cr = ss->ss_crequest; + /* Remove extra headers */ + while (sip->sip_allow) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_allow); + while (sip->sip_priority) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_priority); + while (sip->sip_proxy_require) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_proxy_require); + while (sip->sip_require) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_require); + while (sip->sip_subject) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_subject); + while (sip->sip_supported) + sip_header_remove(msg, sip, (sip_header_t*)sip->sip_supported); - received = ss ? ss->ss_ack_needed : NULL; - - if (!received) - return UA_EVENT2(nua_i_error, 900, "No response to ACK"); - - ss->ss_ack_needed = 0; - - if (!received[0]) - received = NULL; - - if (tags) - nua_stack_set_params(nua, nh, nua_i_error, tags); - - msg = nua_creq_msg(nua, nh, cr, 0, - SIP_METHOD_ACK, - /* NUTAG_COPY(0), */ - TAG_NEXT(tags)); - sip = sip_object(msg); - - if (sip && nh->nh_soa) { - if (tags) - soa_set_params(nh->nh_soa, TAG_NEXT(tags)); - - if (cr->cr_offer_recv && !cr->cr_answer_sent) { - if (soa_generate_answer(nh->nh_soa, NULL) < 0 || - session_include_description(nh->nh_soa, 1, msg, sip) < 0) { - reason = soa_error_as_sip_reason(nh->nh_soa); - status = 900, phrase = "Internal media error"; - reason = "SIP;cause=500;text=\"Internal media error\""; - } - else { - cr->cr_answer_sent = 1; - soa_activate(nh->nh_soa, NULL); - - /* signal that O/A round is complete */ - sent = "answer"; - } + if (!nh->nh_soa) + ; + else if (cr->cr_offer_recv && !cr->cr_answer_sent) { + if (soa_generate_answer(nh->nh_soa, NULL) < 0 || + session_include_description(nh->nh_soa, 1, msg, sip) < 0) { + status = 900, phrase = "Internal media error"; + reason = "SIP;cause=500;text=\"Internal media error\""; + /* reason = soa_error_as_sip_reason(nh->nh_soa); */ + } + else { + cr->cr_answer_sent = 1; + soa_activate(nh->nh_soa, NULL); + /* signal that O/A round is complete */ + ss->ss_oa_sent = "answer"; } if (!reason && @@ -880,135 +1077,238 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, } } - if (sip) { - msg_t *imsg = nta_outgoing_getrequest(cr->cr_orq); - sip_t const *isip = sip_object(imsg); - if (isip->sip_proxy_authorization) - sip_add_dup(msg, sip, (void *)isip->sip_proxy_authorization); - if (isip->sip_authorization) - sip_add_dup(msg, sip, (void *)isip->sip_authorization); - msg_destroy(imsg); + if ((ack = nta_outgoing_mcreate(nh->nh_nua->nua_nta, NULL, NULL, NULL, + msg, + SIPTAG_END(), + TAG_NEXT(tags)))) { + nta_outgoing_destroy(ack); /* TR engine keeps this around for T2 */ + } + else if (!reason) { + status = 900, phrase = "Cannot send ACK"; + reason = "SIP;cause=500;text=\"Internal Error\""; } - if (sip) - ack = nta_outgoing_mcreate(nua->nua_nta, NULL, NULL, NULL, msg, - SIPTAG_END(), TAG_NEXT(tags)); + if (ss) { + if (reason) + ss->ss_reason = reason; - if (!ack) { - if (!reason) { - status = 900, phrase = "Cannot send ACK"; - reason = "SIP;cause=500;text=\"Internal Error\""; - } - msg_destroy(msg); + if (!ss->ss_reporting && status < 300) + signal_call_state_change(nh, ss, status, phrase, nua_callstate_ready); } + + return status < 300 ? 1 : -2; +} - nua_creq_deinit(cr, NULL); /* Destroy INVITE transaction */ - nta_outgoing_destroy(ack); /* TR engine keeps this around for T2 */ - - if (status < 300) { - signal_call_state_change(nh, ss, status, phrase, nua_callstate_ready, - received, sent); - } - else { - signal_call_state_change(nh, ss, status, phrase, nua_callstate_terminating, - 0, 0); - nua_stack_post_signal(nh, nua_r_bye, - SIPTAG_REASON_STR(reason), - TAG_END()); - } +/** Deinitialize client request */ +static int nua_invite_client_deinit(nua_client_request_t *cr) +{ + if (cr->cr_orq == NULL) + /* Xyzzy */; + else if (cr->cr_status < 200) + nta_outgoing_cancel(cr->cr_orq); + else + nua_invite_client_ack(cr, NULL); return 0; } +/**@fn void nua_cancel(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); + * + * Cancel an INVITE operation + * + * @param nh Pointer to operation handle + * @param tag, value, ... List of tagged parameters + * + * @return + * nothing + * + * @par Related Tags: + * Tags in + * + * @par Events: + * #nua_r_cancel, #nua_i_state (#nua_i_active, #nua_i_terminated) + * + * @sa @ref nua_call_model, nua_invite(), #nua_i_cancel + */ -/* Process reliable provisional response */ -static int -process_100rel(nua_handle_t *nh, - nua_session_usage_t *ss, - nta_outgoing_t *orq, - sip_t const *sip) +static int nua_cancel_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); + +nua_client_methods_t const nua_cancel_client_methods = { + SIP_METHOD_CANCEL, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 1, + /* target refresh */ 0 + }, + NULL, + NULL, + nua_cancel_client_request, + /* nua_cancel_client_check_restart */ NULL, + /* nua_cancel_client_response */ NULL +}; + +int nua_stack_cancel(nua_t *nua, nua_handle_t *nh, nua_event_t e, + tagi_t const *tags) { - nua_client_request_t *cr_invite = ss->ss_crequest; - nua_client_request_t *cr_prack = nh->nh_ds->ds_cr; - - sip_rseq_t *rseq; - char const *recv = NULL; - int status; char const *phrase; + return nua_client_create(nh, e, &nua_cancel_client_methods, tags); +} - if (cr_prack->cr_orq) { - /* XXX - better luck next time */ - SU_DEBUG_3(("nua(%p): cannot send PRACK because %s is pending\n", nh, - nta_outgoing_method_name(cr_prack->cr_orq))); - return 0; /* Wait until this response is re-transmitted */ +static int nua_cancel_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); + + if (!du || !du->du_cr || !du->du_cr->cr_orq || + nta_outgoing_status(du->du_cr->cr_orq) >= 200) { + return nua_client_return(cr, 481, "No transaction to CANCEL", msg); } - if (!nua_dialog_is_established(nh->nh_ds)) { - /* Establish early dialog */ - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - - /* Tag the INVITE request */ - cr_invite->cr_orq = - nta_outgoing_tagged(orq, process_response_to_invite, nh, - sip->sip_to->a_tag, sip->sip_rseq); - nta_outgoing_destroy(orq); - orq = cr_invite->cr_orq; - } - - assert(sip); + cr->cr_orq = nta_outgoing_tcancel(du->du_cr->cr_orq, + nua_client_orq_response, cr, + TAG_NEXT(tags)); - status = sip->sip_status->st_status, phrase = sip->sip_status->st_phrase; - rseq = sip->sip_rseq; + return cr->cr_orq ? 0 : -1; +} - if (!rseq) { - SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", nh)); +/** @NUA_EVENT nua_r_cancel + * + * Answer to outgoing CANCEL. + * + * The CANCEL may be sent explicitly by nua_cancel() or implicitly by NUA + * state machine. + * + * @param status response status code + * @param phrase a short textual description of @a status code + * @param nh operation handle associated with the call + * @param hmagic application context associated with the call + * @param sip response to CANCEL request or NULL upon an error + * (status code is in @a status and + * descriptive message in @a phrase parameters) + * @param tags empty + * + * @sa nua_cancel(), @ref nua_uac_call_model, #nua_r_invite, nua_invite(), + * #nua_i_state + * + * @END_NUA_EVENT + */ + +static void nua_session_usage_refresh(nua_handle_t *nh, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du, + sip_time_t now) +{ + nua_session_usage_t *ss = nua_dialog_usage_private(du); + nua_client_request_t const *cr = du->du_cr; + nua_server_request_t const *sr; + + assert(cr); + + if (ss->ss_state >= nua_callstate_terminating || + /* No INVITE template */ + cr == NULL || + /* INVITE is in progress or being authenticated */ + cr->cr_orq || cr->cr_challenged) + return; + + /* UPDATE in progress or being authenticated */ + for (cr = ds->ds_cr; cr; cr = cr->cr_next) + if (cr->cr_method == sip_method_update) + return; + + /* INVITE or UPDATE in progress or being authenticated */ + for (sr = ds->ds_sr; sr; sr = sr->sr_next) + if (sr->sr_usage == du && + (sr->sr_method == sip_method_invite || + sr->sr_method == sip_method_update)) + return; + + if (!ss->ss_refresher) { + if (du->du_expires == 0 || now < du->du_expires) + /* Refresh contact & route set using re-INVITE */ + nua_client_resend_request(du->du_cr, 0, NULL); + else { + ss->ss_reason = "SIP;cause=408;text=\"Session timeout\""; + nua_stack_bye(nh->nh_nua, nh, nua_r_bye, NULL); + } } - else if (rseq->rs_response <= nta_outgoing_rseq(orq)) { - SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", nh, - (unsigned)rseq->rs_response, - nta_outgoing_rseq(orq))); - /* XXX - send nua_r_invite event or not? */ - return 0; + else if (NH_PGET(nh, update_refresh)) { + nua_stack_update(nh->nh_nua, nh, nua_r_update, NULL); } - else if (nta_outgoing_setrseq(orq, rseq->rs_response) < 0) { - SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", nh, - (unsigned)rseq->rs_response)); - } - else if (session_process_response(nh, cr_invite, orq, sip, &recv) < 0) { - assert(nh->nh_soa); - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_media_error, status, phrase, TAG_END()); - } - /* Here we could let application PRACK and just send state event */ else { - sip_rack_t rack[1]; - tagi_t tags[] = { - { TAG_SKIP(nua_stack_prack) }, /* this is autoprack */ - { NUTAG_STATUS(status), }, - { NUTAG_PHRASE(phrase), }, - { NUTAG_PHRASE(recv), }, - { SIPTAG_RACK(rack) }, - { TAG_END() } - }; + nua_client_resend_request(du->du_cr, 0, NULL); + } +} - sip_rack_init(rack); +/** @interal Shut down session usage. + * + * @retval >0 shutdown done + * @retval 0 shutdown in progress + * @retval <0 try again later + */ +static int nua_session_usage_shutdown(nua_handle_t *nh, + nua_dialog_state_t *ds, + nua_dialog_usage_t *du) +{ + nua_session_usage_t *ss = nua_dialog_usage_private(du); + nua_server_request_t *sr, *sr_next; + nua_client_request_t *cri; - rack->ra_response = sip->sip_rseq->rs_response; - rack->ra_cseq = sip->sip_cseq->cs_seq; - rack->ra_method = sip->sip_cseq->cs_method; - rack->ra_method_name = sip->sip_cseq->cs_method_name; + assert(ss == nua_session_usage_get(nh->nh_ds)); - nua_stack_prack(nh->nh_nua, nh, nua_r_prack, tags); + /* Zap server-side transactions */ + for (sr = ds->ds_sr; sr; sr = sr_next) { + sr_next = sr->sr_next; + if (sr->sr_usage == du) { + assert(sr->sr_usage == du); + sr->sr_usage = NULL; - return 0; + if (nua_server_request_is_pending(sr)) { + SR_STATUS1(sr, SIP_480_TEMPORARILY_UNAVAILABLE); + nua_server_respond(sr, NULL); + if (nua_server_report(sr) >= 2) + return 480; + } + else + nua_server_request_destroy(sr); + } } - /* XXX - CANCEL INVITE or BYE this session? */ - /* Because we don't do forking very well we just cancel INVITE */ - nua_stack_cancel(nh->nh_nua, nh, nua_r_cancel, NULL); + cri = du->du_cr; - return 0; + switch (ss->ss_state) { + case nua_callstate_calling: + case nua_callstate_proceeding: + return nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL); + + case nua_callstate_completing: + case nua_callstate_ready: + case nua_callstate_completed: + if (cri && cri->cr_orq) { + if (cri->cr_status < 200) + nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL); + else if (cri->cr_status < 300) + nua_invite_client_ack(cri, NULL); + } + if (nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL) != 0) + break; + return 0; + + case nua_callstate_terminating: + case nua_callstate_terminated: /* XXX */ + return 0; + + default: + break; + } + + nua_dialog_usage_remove(nh, ds, du); + + return 200; } /**@fn void nua_prack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); @@ -1052,437 +1352,172 @@ process_100rel(nua_handle_t *nh, * @END_NUA_EVENT */ +static int nua_prack_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_prack_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_prack_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_prack_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +nua_client_methods_t const nua_prack_client_methods = { + SIP_METHOD_PRACK, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 1, + /* target refresh */ 0 + }, + NULL, + nua_prack_client_init, + nua_prack_client_request, + /* nua_prack_client_check_restart */ NULL, + nua_prack_client_response, + NULL, + nua_prack_client_report +}; int nua_stack_prack(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags) + tagi_t const *tags) { - nua_session_usage_t *ss; - nua_client_request_t *cr; - msg_t *msg; - sip_t *sip; - int offer_sent_in_prack = 0, answer_sent_in_prack = 0; - - int status = 0; char const *phrase = "PRACK sent"; - char const *recv = NULL, *sent = NULL; - - int autoprack = /* XXX - should have common indication */ - tags && tags->t_tag == tag_skip && - tags->t_value == (tag_value_t)nua_stack_prack; - - if (autoprack) { - status = (int)tags[1].t_value; - phrase = (char const *)tags[2].t_value; - recv = (char const *)tags[3].t_value; - tags += 4; - } - - ss = nua_session_usage_get(nh->nh_ds); - - if (!ss || !ss->ss_crequest || !nta_outgoing_rseq(ss->ss_crequest->cr_orq)) - return UA_EVENT2(e, 900, "Nothing to PRACK"); - else if (nh->nh_ds->ds_cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - cr = nh->nh_ds->ds_cr; - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_PRACK, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - - sip = sip_object(msg); - - if (sip) { - nua_client_request_t *cri = ss->ss_crequest; - if (nh->nh_soa == NULL) - /* It is up to application to handle SDP */; - else if (sip->sip_payload) - /* XXX - we should just do MIME in session_include_description() */; - else if (cri->cr_offer_recv && !cri->cr_answer_sent) { - - if (soa_generate_answer(nh->nh_soa, NULL) < 0 || - session_include_description(nh->nh_soa, 1, msg, sip) < 0) { - - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - SU_DEBUG_3(("nua(%p): PRACK answer: %d %s\n", nh, status, phrase)); - nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_media_error, status, phrase, TAG_END()); - - goto error; - } - else { - answer_sent_in_prack = 1, sent = "answer"; - soa_activate(nh->nh_soa, NULL); - } - } - /* When 100rel response status was 183 fake support for preconditions */ - else if (autoprack && status == 183 && ss->ss_precondition) { - - if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || - session_include_description(nh->nh_soa, 1, msg, sip) < 0) { - - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - SU_DEBUG_3(("nua(%p): PRACK offer: %d %s\n", nh, status, phrase)); - nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_media_error, status, phrase, TAG_END()); - goto error; - } - else { - offer_sent_in_prack = 1, sent = "offer"; - } - } - - if (nh->nh_auth) { - if (auc_authorize(&nh->nh_auth, msg, sip) < 0) - /* xyzzy */; - } - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_prack, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - if (cr->cr_orq) { - cr->cr_usage = nua_dialog_usage_public(ss); - cr->cr_event = nua_r_prack; - - if (answer_sent_in_prack) - cri->cr_answer_sent = 1; - else if (offer_sent_in_prack) - cr->cr_offer_sent = 1; - - if (autoprack) - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_proceeding, recv, sent); - else - signal_call_state_change(nh, ss, 0, "PRACK sent", - nua_callstate_proceeding, NULL, sent); - - - return cr->cr_event = e; - } - } - - error: - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); + return nua_client_create(nh, e, &nua_prack_client_methods, tags); } -void restart_prack(nua_handle_t *nh, tagi_t *tags) +static int nua_prack_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_prack, tags); -} + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); - -static int -process_response_to_prack(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - nua_client_request_t *cr = nh->nh_ds->ds_cr; - nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage); - int status; - char const *phrase = "OK", *reason = NULL, *recv = NULL; - - assert(cr->cr_usage && cr->cr_usage->du_class == nua_session_usage); - - if (sip) - status = sip->sip_status->st_status, phrase = sip->sip_status->st_phrase; - else - status = 408, phrase = sip_408_Request_timeout; - - SU_DEBUG_5(("nua: process_response_to_prack: %u %s\n", status, phrase)); - - if (nua_creq_check_restart(nh, cr, orq, sip, restart_prack)) - return 0; - - if (status < 200) - return 0; - - cr->cr_usage = NULL; - - if (status < 300) { - if (session_process_response(nh, cr, orq, sip, &recv) < 0) { - status = 900, phrase = "Malformed Session in Response"; - reason = "SIP;status=400;phrase=\"Malformed Session in Response\""; - } - } - else - nua_stack_process_response(nh, cr, orq, sip, TAG_END()); - - if (recv) - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_proceeding, recv, NULL); - - if (status < 300 && ss->ss_update_needed) - nua_stack_update(nh->nh_nua, nh, nua_r_update, NULL); + cr->cr_usage = du; return 0; } -/** Refresh session usage */ -static void nua_session_usage_refresh(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du, - sip_time_t now) -{ - tagi_t const timer_tags[2] = { - { SIPTAG_SUBJECT_STR("Session refresh") }, - { TAG_END() } - }; - tagi_t const refresh_tags[2] = { - { SIPTAG_SUBJECT_STR("Dialog refresh") }, - { TAG_END() } - }; - - nua_session_usage_t const *ss = nua_dialog_usage_private(du); - nua_client_request_t const *cri = ss->ss_crequest, *cro = ds->ds_cr; - nua_server_request_t const *sr; - - for (sr = ds->ds_sr; sr; sr = sr->sr_next) - if (sr->sr_usage == du && - (sr->sr_method == sip_method_invite || - sr->sr_method == sip_method_update)) - break; - - /* INVITE or UPDATE in progress or being authenticated */ - if ((cri && cri->cr_orq) || sr) - return; - if (ss->ss_state >= nua_callstate_terminating) - return; - - if (!ss->ss_refresher) { - if (now >= du->du_expires) - session_timeout(nh, du, now); - else - /* Refreshing contact & route set */ - nua_stack_invite2(nh->nh_nua, nh, nua_r_invite, 1, refresh_tags); - } - else if (NH_PGET(nh, update_refresh)) { - if (!cro->cr_orq) - nua_stack_update(nh->nh_nua, nh, nua_r_update, timer_tags); - else - nua_dialog_usage_refresh_range(du, 5, 15); - } - else { - nua_stack_invite2(nh->nh_nua, nh, nua_r_invite, 1, timer_tags); - } -} - -static -char const reason_timeout[] = "SIP;cause=408;text=\"Session timeout\""; - -static void -session_timeout(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now) -{ - if (now > 1) { - nua_session_usage_t *ss = nua_dialog_usage_private(du); - - signal_call_state_change(nh, ss, 408, "Session Timeout", - nua_callstate_terminating, NULL, NULL); - - nua_stack_post_signal(nh, nua_r_bye, - SIPTAG_REASON_STR(reason_timeout), - TAG_END()); - } -} - -/** Terminate usage/dialog/handle/agent gracefully */ -static int nua_session_usage_shutdown(nua_handle_t *nh, - nua_dialog_state_t *ds, - nua_dialog_usage_t *du) +static int nua_prack_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; nua_session_usage_t *ss = nua_dialog_usage_private(du); - nua_client_request_t *cr; - nua_server_request_t *sr, *sr_next; - int status; + nua_client_request_t *cri; + int offer_sent = 0, answer_sent = 0, retval; + int status = 0; char const *phrase = "PRACK Sent"; + uint32_t rseq = 0; - /* Zap client-side invite transaction */ - if (ss->ss_crequest->cr_orq) { - cr = ss->ss_crequest; - status = nta_outgoing_status(cr->cr_orq); + if (du == NULL) /* Call terminated */ + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); + assert(ss); - if (status < 200) - nta_outgoing_tcancel(cr->cr_orq, NULL, NULL, TAG_END()); + cri = du->du_cr; - if (ss->ss_ack_needed) { - msg_t *ack = nua_creq_msg(nh->nh_nua, nh, cr, 0, - SIP_METHOD_ACK, - TAG_END()); - nta_outgoing_mcreate(nh->nh_nua->nua_nta, NULL, NULL, NULL, - ack, TAG_END()); + if (sip->sip_rack) + rseq = sip->sip_rack->ra_response; + + if (nh->nh_soa == NULL) + /* It is up to application to handle SDP */; + else if (sip->sip_payload) + /* XXX - we should just do MIME in session_include_description() */; + else if (cri->cr_offer_recv && !cri->cr_answer_sent) { + if (soa_generate_answer(nh->nh_soa, NULL) < 0 || + session_include_description(nh->nh_soa, 1, msg, sip) < 0) { + status = soa_error_as_sip_response(nh->nh_soa, &phrase); + SU_DEBUG_3(("nua(%p): local response to PRACK: %d %s\n", + (void *)nh, status, phrase)); + nua_stack_event(nh->nh_nua, nh, NULL, + nua_i_media_error, status, phrase, + NULL); + return nua_client_return(cr, status, phrase, msg); + } + else { + answer_sent = 1; + soa_activate(nh->nh_soa, NULL); } - - nua_creq_deinit(cr, NULL); } - - /* Zap server-side transactions */ - for (sr = ds->ds_sr; sr; sr = sr_next) { - sr_next = sr->sr_next; - if (sr->sr_usage == du) { - assert(sr->sr_usage == du); - sr->sr_usage = NULL; - if (sr->sr_respond) - nua_server_respond(sr, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END()); - else - nua_server_request_destroy(sr); + /* When 100rel response status was 183 fake support for preconditions */ + else if (cr->cr_auto && cri->cr_status == 183 && ss->ss_precondition) { + if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || + session_include_description(nh->nh_soa, 1, msg, sip) < 0) { + status = soa_error_as_sip_response(nh->nh_soa, &phrase); + SU_DEBUG_3(("nua(%p): PRACK offer: %d %s\n", (void *)nh, + status, phrase)); + nua_stack_event(nh->nh_nua, nh, NULL, + nua_i_media_error, status, phrase, NULL); + return nua_client_return(cr, status, phrase, msg); + } + else { + offer_sent = 1; } } - assert(ss == nua_session_usage_get(nh->nh_ds)); + retval = nua_base_client_request(cr, msg, sip, NULL); - switch (ss->ss_state) { - case nua_callstate_completing: - case nua_callstate_ready: - case nua_callstate_completed: - { - msg_t *bye; + if (retval == 0) { + cr->cr_offer_sent = offer_sent; + cr->cr_answer_sent = answer_sent; - cr = ds->ds_cr; - nua_creq_deinit(cr, NULL); - bye = nua_creq_msg(nh->nh_nua, nh, ds->ds_cr, 0, - SIP_METHOD_BYE, - TAG_END()); - cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta, - NULL, NULL, NULL, - bye, - TAG_END()); - nua_creq_deinit(cr, NULL); + if (!cr->cr_restarting) { + if (offer_sent) + ss->ss_oa_sent = "offer"; + else if (answer_sent) + ss->ss_oa_sent = "answer"; + + if (!ss->ss_reporting) + signal_call_state_change(nh, ss, status, phrase, ss->ss_state); } } - nua_dialog_usage_remove(nh, ds, du); - - return 0; + return retval; } -/** Restart invite (e.g., after 302 or 407) */ -void -restart_invite(nua_handle_t *nh, tagi_t *tags) +static int nua_prack_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) { - nua_stack_invite2(nh->nh_nua, nh, nua_r_invite, 1, tags); + /* XXX - fatal error cases? */ + + return nua_session_client_response(cr, status, phrase, sip); } -static int process_response_to_cancel(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -/**@fn void nua_cancel(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); - * - * Cancel an INVITE operation - * - * @param nh Pointer to operation handle - * @param tag, value, ... List of tagged parameters - * - * @return - * nothing - * - * @par Related Tags: - * Tags in - * - * @par Events: - * #nua_r_cancel, #nua_i_state (#nua_i_active, #nua_i_terminated) - * - * @sa @ref nua_call_model, nua_invite(), #nua_i_cancel - */ - -int -nua_stack_cancel(nua_t *nua, nua_handle_t *nh, nua_event_t e, - tagi_t const *tags) +static int nua_prack_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) { - nua_session_usage_t *ss; - nua_client_request_t *cri, *crc; + nua_handle_t *nh = cr->cr_owner; + nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage); - ss = nua_session_usage_get(nh->nh_ds); + nua_stack_event(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + tags); - if (!nh || !ss || !ss->ss_crequest->cr_usage || - nta_outgoing_status(ss->ss_crequest->cr_orq) >= 200) { - return UA_EVENT2(e, 481, "No transaction to CANCEL"); - } + if (!ss || orq != cr->cr_orq || cr->cr_terminated || cr->cr_graceful) + return 1; - cri = ss->ss_crequest; - crc = nh->nh_ds->ds_cr; + if (cr->cr_offer_sent) + signal_call_state_change(nh, ss, status, phrase, ss->ss_state); - if (tags) - nua_stack_set_params(nua, nh, nua_i_error, tags); - - if (nh && cri->cr_orq && cri->cr_usage) { - nta_outgoing_t *orq; - - /* nh_referral_respond(nh, SIP_487_REQUEST_TERMINATED); */ - - if (e) - orq = nta_outgoing_tcancel(cri->cr_orq, process_response_to_cancel, nh, - TAG_NEXT(tags)); - else - orq = nta_outgoing_tcancel(cri->cr_orq, NULL, NULL, TAG_NEXT(tags)); - - if (orq == NULL) - return nua_stack_event(nua, nh, NULL, e, 400, "Internal error", - TAG_END()); - - if (e && crc->cr_orq == NULL) - crc->cr_orq = orq, crc->cr_event = e; - } - - return 0; -} - -/** @NUA_EVENT nua_r_cancel - * - * Answer to outgoing CANCEL. - * - * The CANCEL may be sent explicitly by nua_cancel() or implicitly by NUA - * state machine. - * - * @param status response status code - * @param phrase a short textual description of @a status code - * @param nh operation handle associated with the call - * @param hmagic application context associated with the call - * @param sip response to CANCEL request or NULL upon an error - * (status code is in @a status and - * descriptive message in @a phrase parameters) - * @param tags empty - * - * @sa nua_cancel(), @ref nua_uac_call_model, #nua_r_invite, nua_invite(), - * #nua_i_state - * - * @END_NUA_EVENT - */ - - - -static int process_response_to_cancel(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END()); + if (ss->ss_update_needed && 200 <= status && status < 300) + nua_client_create(nh, nua_r_update, &nua_update_client_methods, NULL); + + return 1; } /* ---------------------------------------------------------------------- */ /* UAS side of INVITE */ -static int respond_to_invite(nua_server_request_t *sr, tagi_t const *tags); - -static int - preprocess_invite(nua_t *, nua_handle_t *, nua_server_request_t **, sip_t *), - session_check_request(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip), - process_invite(nua_t *, nua_handle_t *, nua_server_request_t *, sip_t *), - process_prack(nua_handle_t *, nta_reliable_t *, nta_incoming_t *, - sip_t const *); - -static int - process_ack_or_cancel(nua_server_request_t *, nta_incoming_t *, - sip_t const *), - process_ack(nua_server_request_t *, nta_incoming_t *, sip_t const *), - process_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), - process_timeout(nua_server_request_t *, nta_incoming_t *); - /** @NUA_EVENT nua_i_invite * * Indication of incoming call or re-INVITE request. @@ -1528,16 +1563,18 @@ static int * the 2XX response. If @soa is not disabled with NUTAG_MEDIA_ENABLE(0), the * SDP should be included in the SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() * parameter given to nua_respond(). If it is disabled, the SDP should be - * included in message + * included in the response message using SIPTAG_PAYLOAD() or + * SIPTAG_PAYLOAD_STR(). Also, the @ContentType should be set using + * SIPTAG_CONTENT_TYPE() or SIPTAG_CONTENT_TYPE_STR(). * * @par Preliminary Responses and 100rel * * Call progress can be signaled with preliminary responses (with status * code in the range 101..199). It is possible to conclude the SDP * Offer-Answer negotiation using preliminary responses, too. If - * SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() parameter is included with in - * a preliminary nua_response(), the SDP answer is generated and sent with - * the preliminary responses, too. + * NUTAG_EARLY_ANSWER(1), SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() + * parameter is included with in a preliminary nua_response(), the SDP + * answer is generated and sent with the preliminary responses, too. * * The preliminary responses are sent reliably if feature tag "100rel" is * included in the @Require header of the response or if @@ -1560,7 +1597,8 @@ static int * * @sa nua_respond(), @ref nua_uas_call_model, #nua_i_state, * NUTAG_MEDIA_ENABLE(), SOATAG_USER_SDP(), SOATAG_USER_SDP_STR(), - * @RFC3262, NUTAG_EARLY_MEDIA(), NUTAG_ONLY183_100REL(), + * @RFC3262, NUTAG_EARLY_ANSWER(), NUTAG_EARLY_MEDIA(), + * NUTAG_ONLY183_100REL(), * NUTAG_INCLUDE_EXTRA_SDP(), * #nua_i_prack, #nua_i_update, nua_update(), * nua_invite(), #nua_r_invite @@ -1579,119 +1617,184 @@ static int * @END_NUA_EVENT */ -/** @internal Process incoming INVITE. */ -int nua_stack_process_invite(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_server_request_t *sr, sr0[1]; - int status; - - sr = SR_INIT(sr0); - sr->sr_irq = irq; +static int nua_invite_server_init(nua_server_request_t *sr); +static int nua_session_server_init(nua_server_request_t *sr); +static int nua_invite_server_preprocess(nua_server_request_t *sr); +static int nua_invite_server_respond(nua_server_request_t *sr, tagi_t const *); +static int nua_invite_server_is_100rel(nua_server_request_t *, tagi_t const *); +static int nua_invite_server_report(nua_server_request_t *sr, tagi_t const *); - status = preprocess_invite(nua, nh, &sr, (sip_t *)sip); +static int + process_ack_or_cancel(nua_server_request_t *, nta_incoming_t *, + sip_t const *), + process_ack(nua_server_request_t *, nta_incoming_t *, sip_t const *), + process_cancel(nua_server_request_t *, nta_incoming_t *, sip_t const *), + process_timeout(nua_server_request_t *, nta_incoming_t *), + process_prack(nua_handle_t *nh, + nta_reliable_t *rel, + nta_incoming_t *irq, + sip_t const *sip); - if (status) { - if (sr->sr_status > 100) - nta_incoming_treply(irq, sr->sr_status, sr->sr_phrase, - SIPTAG_USER_AGENT_STR(NUA_PGET(nua, nh, user_agent)), - TAG_END()); - nua_server_request_destroy(sr); - /* if something has failed, respond with 500 Internal Server Error */ - return 500; - } +nua_server_methods_t const nua_invite_server_methods = + { + SIP_METHOD_INVITE, + nua_i_invite, /* Event */ + { + 1, /* Create dialog */ + 0, /* Initial request */ + 1, /* Target refresh request */ + 1, /* Add Contact */ + }, + nua_invite_server_init, + nua_invite_server_preprocess, + nua_base_server_params, + nua_invite_server_respond, + nua_invite_server_report, + }; - assert(sr != sr0); - - return process_invite(nua, sr->sr_owner, sr, (sip_t *)sip); -} /** @internal Preprocess incoming invite - sure we have a valid request. * - * @return 0 if request is valid, or error statuscode when request has been - * responded. + * @return 0 if request is valid, or error statuscode otherwise */ -static -int preprocess_invite(nua_t *nua, - nua_handle_t *nh, - nua_server_request_t **inout_sr, - sip_t *sip) +static int +nua_invite_server_init(nua_server_request_t *sr) { - nua_dialog_state_t *ds; - nua_server_request_t *sr = *inout_sr; - nua_server_request_t const *sr0; - nua_dialog_usage_t *du; - nua_session_usage_t *ss; - int have_sdp; - char const *sdp; - size_t len; - - if (nh) { - ds = nh->nh_ds; - du = nua_dialog_usage_get(ds, nua_session_usage, NULL); - ss = nua_dialog_usage_private(du); - } - else { - nh = nua->nua_dhandle, ds = NULL, du = NULL, ss = NULL; - } - - sr->sr_usage = du; + nua_handle_t *nh = sr->sr_owner; + nua_t *nua = nh->nh_nua; if (!NUA_PGET(nua, nh, invite_enable)) return SR_STATUS1(sr, SIP_403_FORBIDDEN); - if (session_check_request(nua, nh, sr->sr_irq, sip)) - return 500; + if (nua_session_server_init(sr)) + return sr->sr_status; + + if (sr->sr_usage) { + /* Existing session - check for overlap and glare */ - have_sdp = session_get_description(sip, &sdp, &len); + nua_server_request_t const *sr0; + nua_client_request_t const *cr; - if (ss) { - /* Existing session */ - - for (sr0 = ds->ds_sr; sr0; sr0 = sr0->sr_next) { + for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next) { /* Final response have not been sent to previous INVITE */ - if (sr0->sr_method == sip_method_invite && sr0->sr_respond) + if (sr0->sr_method == sip_method_invite && + nua_server_request_is_pending(sr0)) break; /* Or we have sent offer but have not received answer */ - if (have_sdp && sr0->sr_offer_sent && !sr0->sr_answer_recv) + if (sr->sr_sdp && sr0->sr_offer_sent && !sr0->sr_answer_recv) break; /* Or we have received request with offer but not sent answer */ - if (have_sdp && sr0->sr_offer_recv && !sr0->sr_answer_sent) + if (sr->sr_sdp && sr0->sr_offer_recv && !sr0->sr_answer_sent) break; } if (sr0) /* Overlapping invites - RFC 3261 14.2 */ - return respond_with_retry_after(nh, sr->sr_irq, - 500, "Overlapping Requests", - 0, 10); + return nua_server_retry_after(sr, 500, "Overlapping Requests", 0, 10); - if ((ss->ss_crequest && ss->ss_crequest->cr_orq) || - (have_sdp && ds && ds->ds_cr->cr_orq && ds->ds_cr->cr_offer_sent)) { - /* Glare - RFC 3261 14.2 and RFC 3311 section 5.2 */ - return SR_STATUS1(sr, SIP_491_REQUEST_PENDING); + for (cr = nh->nh_ds->ds_cr; cr; cr = cr->cr_next) { + if (cr->cr_usage == sr->sr_usage && cr->cr_orq && cr->cr_offer_sent) + /* Glare - RFC 3261 14.2 and RFC 3311 section 5.2 */ + return SR_STATUS1(sr, SIP_491_REQUEST_PENDING); } } - /* Create handle and server request structure when needed */ - sr = nua_server_request(nua, nh, sr->sr_irq, sip, sr, sizeof *sr, - respond_to_invite, create_dialog); - *inout_sr = sr; + return 0; +} + +/** Initialize session server request. + * + * Ensure that the request is valid. + */ +static int +nua_session_server_init(nua_server_request_t *sr) +{ + nua_handle_t *nh = sr->sr_owner; + nua_t *nua = nh->nh_nua; + + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; + + sip_t const *request = sr->sr_request.sip; + + unsigned min = NH_PGET(nh, min_se); + + if (!sr->sr_initial) + sr->sr_usage = nua_dialog_usage_get(nh->nh_ds, nua_session_usage, NULL); + + if (sr->sr_method != sip_method_invite && sr->sr_usage == NULL) { + /* UPDATE/PRACK sent within an existing dialog? */ + return SR_STATUS(sr, 481, "Call Does Not Exist"); + } + + if (nh->nh_soa) { + sip_accept_t *a = nua->nua_invite_accept; + + /* XXX - soa should know what it supports */ + sip_add_dup(msg, sip, (sip_header_t *)a); + + /* Make sure caller uses application/sdp without compression */ + if (nta_check_session_content(NULL, request, a, TAG_END())) { + sip_add_make(msg, sip, sip_accept_encoding_class, ""); + return SR_STATUS1(sr, SIP_415_UNSUPPORTED_MEDIA); + } + + /* Make sure caller accepts application/sdp */ + if (nta_check_accept(NULL, request, a, NULL, TAG_END())) { + sip_add_make(msg, sip, sip_accept_encoding_class, ""); + return SR_STATUS1(sr, SIP_406_NOT_ACCEPTABLE); + } + } + + if (request->sip_session_expires && + nta_check_session_expires(NULL, request, min, TAG_END())) { + sip_min_se_t *min_se, min_se0[1]; + + min_se = sip_min_se_init(min_se0); + min_se->min_delta = min; + + if (request->sip_min_se && request->sip_min_se->min_delta > min) + min_se = request->sip_min_se; + + sip_add_dup(msg, sip, (sip_header_t *)min_se); + + return SR_STATUS1(sr, SIP_422_SESSION_TIMER_TOO_SMALL); + } + + session_get_description(sr->sr_request.sip, &sr->sr_sdp, &sr->sr_sdp_len); + + return 0; +} + +/** Preprocess INVITE. + * + * This is called after a handle has been created for an incoming INVITE. + */ +int nua_invite_server_preprocess(nua_server_request_t *sr) +{ + nua_handle_t *nh = sr->sr_owner; + nua_dialog_state_t *ds = nh->nh_ds; + nua_session_usage_t *ss; +#ifndef NDEBUG + nua_t *nua = nh->nh_nua; +#endif + + sip_t const *request = sr->sr_request.sip; + + assert(sr->sr_status == 100); + assert(nh != nh->nh_nua->nua_dhandle); if (sr->sr_status > 100) return sr->sr_status; - nh = sr->sr_owner; assert(nh != nua->nua_dhandle); - ds = nh->nh_ds; - if (nh->nh_soa) { soa_init_offer_answer(nh->nh_soa); - if (have_sdp) { - if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { - SU_DEBUG_5(("nua(%p): error parsing SDP in INVITE\n", nh)); + if (sr->sr_sdp) { + if (soa_set_remote_sdp(nh->nh_soa, NULL, + sr->sr_sdp, sr->sr_sdp_len) < 0) { + SU_DEBUG_5(("nua(%p): %s server: error parsing SDP\n", (void *)nh, + "INVITE")); return SR_STATUS(sr, 400, "Bad Session Description"); } else @@ -1700,72 +1803,19 @@ int preprocess_invite(nua_t *nua, } /* Add the session usage */ - if (du == NULL) - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL); - - if (!du) - return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - - sr->sr_usage = du; - - return 0; -} - -static int -session_check_request(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - char const *user_agent = NUA_PGET(nua, nh, user_agent); - - if (nh->nh_soa) { - /* Make sure caller uses application/sdp without compression */ - if (nta_check_session_content(irq, sip, - nua->nua_invite_accept, - SIPTAG_USER_AGENT_STR(user_agent), - SIPTAG_ACCEPT_ENCODING_STR(""), - TAG_END())) - return 415; - - /* Make sure caller accepts application/sdp */ - if (nta_check_accept(irq, sip, - nua->nua_invite_accept, - NULL, - SIPTAG_USER_AGENT_STR(user_agent), - SIPTAG_ACCEPT_ENCODING_STR(""), - TAG_END())) - return 406; + if (sr->sr_usage == NULL) { + sr->sr_usage = nua_dialog_usage_add(nh, ds, nua_session_usage, NULL); + if (sr->sr_usage == NULL) + return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } - if (sip->sip_session_expires) { - unsigned min_se = NH_PGET(nh, min_se); - if (sip->sip_min_se && min_se < sip->sip_min_se->min_delta) - min_se = sip->sip_min_se->min_delta; - if (nta_check_session_expires(irq, sip, - min_se, - SIPTAG_USER_AGENT_STR(user_agent), - TAG_END())) - return 422; - } + ss = nua_dialog_usage_private(sr->sr_usage); - return 0; -} - -/** @internal Process incoming invite - initiate media, etc. */ -static -int process_invite(nua_t *nua, - nua_handle_t *nh, - nua_server_request_t *sr, - sip_t *sip) -{ - nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); - int status = sr->sr_status; char const *phrase = sr->sr_phrase; - - assert(ss); assert(status == 100); + if (sr->sr_offer_recv) + ss->ss_oa_recv = "offer"; ss->ss_100rel = NH_PGET(nh, early_media); - ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition"); + ss->ss_precondition = sip_has_feature(request->sip_require, "precondition"); if (ss->ss_precondition) ss->ss_100rel = 1; @@ -1776,11 +1826,7 @@ int process_invite(nua_t *nua, /* Session Timer negotiation */ if (sip_has_supported(NH_PGET(nh, supported), "timer")) - init_session_timer(ss, sip, ss->ss_refresher); - - nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */ - - nta_incoming_bind(sr->sr_irq, process_ack_or_cancel, sr); + init_session_timer(ss, request, ss->ss_refresher); assert(ss->ss_state >= nua_callstate_ready || ss->ss_state == nua_callstate_init); @@ -1793,269 +1839,236 @@ int process_invite(nua_t *nua, */ nh->nh_soa && !NH_PISSET(nh, auto_answer))) { - SET_STATUS1(SIP_200_OK); + SR_STATUS1(sr, SIP_200_OK); } else if (NH_PGET(nh, auto_alert)) { if (ss->ss_100rel && - (sip_has_feature(nh->nh_ds->ds_remote_ua->nr_supported, "100rel") || - sip_has_feature(nh->nh_ds->ds_remote_ua->nr_require, "100rel"))) { - SET_STATUS1(SIP_183_SESSION_PROGRESS); + (sip_has_feature(request->sip_supported, "100rel") || + sip_has_feature(request->sip_require, "100rel"))) { + SR_STATUS1(sr, SIP_183_SESSION_PROGRESS); } else { - SET_STATUS1(SIP_180_RINGING); + SR_STATUS1(sr, SIP_180_RINGING); } } - /* Magical value indicating autoanswer within respond_to_invite() */ -#define AUTOANSWER ((void*)-1) - - if (status > 100) { - sr->sr_auto = 1; - nua_server_respond(sr, status, phrase, TAG_END()); - sr->sr_auto = 0; - return 0; - } - - nta_incoming_treply(sr->sr_irq, SIP_100_TRYING, - SIPTAG_USER_AGENT_STR(NUA_PGET(nua, nh, user_agent)), - TAG_END()); - - nua_stack_event(nh->nh_nua, nh, - sr->sr_msg = nta_incoming_getrequest(sr->sr_irq), - nua_i_invite, SIP_100_TRYING, - NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), - TAG_END()); - - signal_call_state_change(nh, ss, SIP_100_TRYING, - nua_callstate_received, - sr->sr_offer_recv ? "offer" : 0, 0); - return 0; } + /** @internal Respond to an INVITE request. * - * XXX - use tags to indicate when to use reliable responses. - * XXX - change prototype. */ static -int respond_to_invite(nua_server_request_t *sr, tagi_t const *tags) +int nua_invite_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; - nua_t *nua = nh->nh_nua; - nua_dialog_state_t *ds = nh->nh_ds; - nua_dialog_usage_t *du; - nua_session_usage_t *ss; - msg_t *msg; - sip_t *sip; - int reliable; - int status = sr->sr_status; char const *phrase = sr->sr_phrase; - sip_warning_t *warning = NULL; + nua_dialog_usage_t *du = sr->sr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; - int offer = 0, answer = 0, early_answer = 0; + int reliable = 0, offer = 0, answer = 0, early_answer = 0, extra = 0; enter; - du = sr->sr_usage, ss = nua_dialog_usage_private(du); - - if (du == NULL) - return nua_default_respond(sr, tags); - - assert(ss == nua_session_usage_get(nh->nh_ds)); - - if (tags) { - nua_stack_set_params(nua, nh, nua_i_error, tags); - - if (!NHP_ISSET(nh->nh_prefs, early_answer) - && 100 < status && status < 200) { - sdp_session_t const *user_sdp = NULL; - char const *user_sdp_str = NULL; - - tl_gets(tags, - SOATAG_USER_SDP_REF(user_sdp), - SOATAG_USER_SDP_STR_REF(user_sdp_str), - TAG_END()); - - early_answer = user_sdp || user_sdp_str; - } - else - early_answer = NH_PGET(nh, early_answer); + if (du == NULL) { + if (sr->sr_status < 300) + sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); + return nua_base_server_respond(sr, tags); } - msg = nua_server_response(sr, - status, phrase, - TAG_IF(status < 300, NUTAG_ADD_CONTACT(1)), - SIPTAG_SUPPORTED(NH_PGET(nh, supported)), - TAG_NEXT(tags)); - sip = sip_object(msg); - - if (!sip) { - SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR), reliable = 0; - goto send_response; + if (nua_invite_server_is_100rel(sr, tags)) { + reliable = 1, early_answer = 1; } + else if (!nh->nh_soa || sr->sr_status >= 300) { + + } + else if (tags && 100 < sr->sr_status && sr->sr_status < 200 && + !NHP_ISSET(nh->nh_prefs, early_answer)) { + sdp_session_t const *user_sdp = NULL; + char const *user_sdp_str = NULL; - reliable = - (status >= 200) - || (status > 100 && sip->sip_require && - sip_has_feature(sip->sip_require, "100rel")) - || (status > 100 && - ds->ds_remote_ua->nr_require && - sip_has_feature(ds->ds_remote_ua->nr_require, "100rel")) - || (status > 100 && !NH_PGET(nh, only183_100rel) && - (NH_PGET(nh, early_media) || - (ds->ds_remote_ua->nr_require && - sip_has_feature(ds->ds_remote_ua->nr_require, "precondition"))) && - ds->ds_remote_ua->nr_supported && - sip_has_feature(ds->ds_remote_ua->nr_supported, "100rel")) - || (status == 183 && - ds->ds_remote_ua->nr_supported && - sip_has_feature(ds->ds_remote_ua->nr_supported, "100rel")) - || (status == 183 && - ds->ds_remote_ua->nr_require && - sip_has_feature(ds->ds_remote_ua->nr_require, "precondition")) - || (status > 100 && - ds->ds_remote_ua->nr_require && - sip_has_feature(ds->ds_remote_ua->nr_require, "precondition") && - sr->sr_offer_recv && !sr->sr_answer_sent); + tl_gets(tags, + SOATAG_USER_SDP_REF(user_sdp), + SOATAG_USER_SDP_STR_REF(user_sdp_str), + TAG_END()); - if (!nh->nh_soa) - /* Xyzzy */; - else if (status >= 300) { - soa_clear_remote_sdp(nh->nh_soa); + early_answer = user_sdp || user_sdp_str; } else { - int extra = 0; - - if (sr->sr_offer_sent && !sr->sr_answer_recv) - /* Wait for answer */; - else if (sr->sr_offer_recv && sr->sr_answer_sent > 1) { - /* We have sent answer */ - /* ... but we may want to send it again */ - tagi_t const *t = tl_find_last(tags, nutag_include_extra_sdp); - extra = t && t->t_value; - } - else if (sr->sr_offer_recv && !sr->sr_answer_sent && - (reliable || early_answer)) { - /* Generate answer */ - if (soa_generate_answer(nh->nh_soa, NULL) >= 0) { - answer = 1; - soa_activate(nh->nh_soa, NULL); - /* signal that O/A answer sent (answer to invite) */ - } - else if (status >= 200) { - int wcode; - char const *text; - char const *host = "invalid."; - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - - wcode = soa_get_warning(nh->nh_soa, &text); - if (wcode) { - if (sip->sip_contact) - host = sip->sip_contact->m_url->url_host; - warning = sip_warning_format(msg_home(msg), "%u %s \"%s\"", - wcode, host, text); - } - } - else { - /* 1xx - we don't have to send answer */ - } - } - else if (sr->sr_offer_recv && sr->sr_answer_sent == 1 && - (reliable || early_answer)) { - /* The answer was sent unreliably, keep sending it */ - answer = 1; - } - else if (!sr->sr_offer_recv && !sr->sr_offer_sent && reliable) { - /* Generate offer */ - if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - else - offer = 1; - } - - if (offer || answer || extra) { - if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) - SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR); - } + early_answer = NH_PGET(nh, early_answer); } - if (ss->ss_refresher && 200 <= status && status < 300) + if (!nh->nh_soa) { + /* Xyzzy */ + } + else if (sr->sr_status >= 300) { + soa_clear_remote_sdp(nh->nh_soa); + } + else if (sr->sr_offer_sent && !sr->sr_answer_recv) + /* Wait for answer */; + else if (sr->sr_offer_recv && sr->sr_answer_sent > 1) { + /* We have sent answer */ + /* ... but we may want to send it again */ + tagi_t const *t = tl_find_last(tags, nutag_include_extra_sdp); + extra = t && t->t_value; + } + else if (sr->sr_offer_recv && !sr->sr_answer_sent && early_answer) { + /* Generate answer */ + if (soa_generate_answer(nh->nh_soa, NULL) >= 0) { + answer = 1; + soa_activate(nh->nh_soa, NULL); + /* signal that O/A answer sent (answer to invite) */ + } + else if (sr->sr_status >= 200) { + sip_warning_t *warning = NULL; + int wcode; + char const *text; + char const *host = "invalid."; + + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); + + wcode = soa_get_warning(nh->nh_soa, &text); + + if (wcode) { + if (sip->sip_contact) + host = sip->sip_contact->m_url->url_host; + warning = sip_warning_format(msg_home(msg), "%u %s \"%s\"", + wcode, host, text); + sip_header_insert(msg, sip, (sip_header_t *)warning); + } + } + else { + /* 1xx - we don't have to send answer */ + } + } + else if (sr->sr_offer_recv && sr->sr_answer_sent == 1 && early_answer) { + /* The answer was sent unreliably, keep sending it */ + answer = 1; + } + else if (!sr->sr_offer_recv && !sr->sr_offer_sent && reliable) { + /* Generate offer */ + if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0) + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); + else + offer = 1; + } + + if (sr->sr_status < 300 && (offer || answer || extra)) { + if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + else if (offer) + sr->sr_offer_sent = 1, ss->ss_oa_sent = "offer"; + else if (answer) + sr->sr_answer_sent = 1 + reliable, ss->ss_oa_sent = "answer"; + } + + if (reliable && sr->sr_status < 200) { + sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; + if (nta_reliable_mreply(sr->sr_irq, process_prack, nh, msg) == NULL) + return -1; + return 0; + } + + if (ss->ss_refresher && 200 <= sr->sr_status && sr->sr_status < 300) if (session_timer_is_supported(nh)) use_session_timer(ss, 1, 1, msg, sip); - if (reliable && status < 200) { - nta_reliable_t *rel; - rel = nta_reliable_mreply(sr->sr_irq, - process_prack, nh, msg); - if (!rel) - SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR); + return nua_base_server_respond(sr, tags); +} + +/** Check if the response should be sent reliably. + * XXX - use tags to indicate when to use reliable responses ??? + */ +static +int nua_invite_server_is_100rel(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + sip_t const *sip = sr->sr_response.sip; + sip_require_t *require = sr->sr_request.sip->sip_require; + sip_supported_t *supported = sr->sr_request.sip->sip_supported; + + if (sr->sr_status >= 200) + return 1; + else if (sr->sr_status == 100) + return 0; + + if (sip_has_feature(sip->sip_require, "100rel")) + return 1; + + if (require == NULL && supported == NULL) + return 0; + + if (sip_has_feature(require, "100rel")) + return 1; + if (!sip_has_feature(supported, "100rel")) + return 0; + if (sr->sr_status == 183) + return 1; + + if (NH_PGET(nh, early_media) && !NH_PGET(nh, only183_100rel)) + return 1; + + if (sip_has_feature(require, "precondition")) { + if (!NH_PGET(nh, only183_100rel)) + return 1; + if (sr->sr_offer_recv && !sr->sr_answer_sent) + return 1; } - send_response: + return 0; +} - if (reliable && status < 200) - /* we are done */; - else if (status != sr->sr_status) { /* Error responding */ - assert(status >= 200); - sr->sr_respond = NULL; - nta_incoming_treply(sr->sr_irq, - status, phrase, - SIPTAG_WARNING(warning), - SIPTAG_USER_AGENT_STR(NH_PGET(nh, user_agent)), - TAG_END()); - msg_destroy(msg), msg = NULL; - } - else { - if (status >= 200) - sr->sr_respond = NULL; - nta_incoming_mreply(sr->sr_irq, msg); + +int nua_invite_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_dialog_usage_t *du = sr->sr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + int initial = sr->sr_initial && !sr->sr_event; + int application = sr->sr_application; + int status = sr->sr_status; char const *phrase = sr->sr_phrase; + int retval; + + if (!sr->sr_event && status < 300) { /* Not reported yet */ + nta_incoming_bind(sr->sr_irq, process_ack_or_cancel, sr); } - if (sr->sr_auto) { - msg_t *request = nta_incoming_getrequest(sr->sr_irq); - if (status < 200) - sr->sr_msg = request; - nua_stack_event(nh->nh_nua, nh, request, - nua_i_invite, status, phrase, - NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), - TAG_END()); + retval = nua_base_server_report(sr, tags), sr = NULL; /* destroys sr */ + + if (retval >= 2 || ss == NULL) { + /* Session has been terminated. */ + if (!initial) + signal_call_state_change(nh, NULL, status, phrase, + nua_callstate_terminated); + return retval; } - else if (status != sr->sr_status) - nua_stack_event(nua, nh, NULL, nua_i_error, status, phrase, TAG_END()); - sr->sr_status = status, sr->sr_phrase = phrase; - - if (status >= 300) - offer = 0, answer = 0; - - if (offer) - sr->sr_offer_sent = 1; - else if (answer) - sr->sr_answer_sent = 1 + reliable; - - /* Update session state */ + assert(ss); assert(ss->ss_state != nua_callstate_calling); assert(ss->ss_state != nua_callstate_proceeding); - signal_call_state_change(nh, ss, status, phrase, - status >= 300 - ? nua_callstate_init - : status >= 200 - ? nua_callstate_completed - : nua_callstate_early, - sr->sr_auto && sr->sr_offer_recv ? "offer" : 0, - offer ? "offer" : answer ? "answer" : 0); + /* Update session state */ + if (status < 300 || application != 0) + signal_call_state_change(nh, ss, status, phrase, + status >= 300 + ? nua_callstate_init + : status >= 200 + ? nua_callstate_completed + : status > 100 + ? nua_callstate_early + : nua_callstate_received); if (status == 180) ss->ss_alerting = 1; else if (status >= 200) ss->ss_alerting = 0; - if (status >= 200 && status < 300) { - du->du_ready = 1; + if (200 <= status && status < 300) { + du->du_ready = 1; } - else if (status >= 300) { - sr->sr_usage = NULL; + else if (300 <= status) { if (nh->nh_soa) soa_init_offer_answer(nh->nh_soa); } @@ -2065,10 +2078,9 @@ int respond_to_invite(nua_server_request_t *sr, tagi_t const *tags) nua_session_usage_destroy(nh, ss); } - return status >= 300 ? status : 0; + return retval; } - /** @internal Process ACK or CANCEL or timeout (no ACK) for incoming INVITE */ static int process_ack_or_cancel(nua_server_request_t *sr, @@ -2088,139 +2100,6 @@ int process_ack_or_cancel(nua_server_request_t *sr, return process_timeout(sr, irq); } -/** @NUA_EVENT nua_i_prack - * - * Incoming PRACK request. PRACK request is used to acknowledge reliable - * preliminary responses and it is usually sent automatically by the nua - * stack. - * - * @param status status code of response sent automatically by stack - * @param phrase a short textual description of @a status code - * @param nh operation handle associated with the call - * @param hmagic application context associated with the call - * @param sip incoming INFO request - * @param tags empty - * - * @sa nua_prack(), #nua_r_prack, @RFC3262, NUTAG_EARLY_MEDIA() - * - * @END_NUA_EVENT - */ - -/** @internal Process PRACK or (timeout from 100rel) */ -static -int process_prack(nua_handle_t *nh, - nta_reliable_t *rel, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_dialog_state_t *ds = nh->nh_ds; - nua_dialog_usage_t *du; - nua_session_usage_t *ss; - nua_server_request_t *sri; - int status = 200; char const *phrase = sip_200_OK; - char const *recv = NULL, *sent = NULL; - - nta_reliable_destroy(rel); - - ss = nua_session_usage_get(ds); du = nua_dialog_usage_public(ss); - - for (sri = ds->ds_sr; sri; sri = sri->sr_next) { - if (sri->sr_method == sip_method_invite && sri->sr_usage == du) - break; - } - - if (!sri || !sri->sr_respond) /* XXX */ - return 481; - - if (sip) - /* received PRACK */; - else if (!sri || irq == NULL) { /* Final response interrupted 100rel */ - /* Ignore */ - return 200; - } - else if (sip == NULL) { - SET_STATUS(504, "Reliable Response Timeout"); - - nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_error, status, phrase, - TAG_END()); - - nua_server_respond(sri, status, phrase, TAG_END()); - - return status; - } - - if (nh->nh_soa) { - msg_t *msg = nta_incoming_getrequest(irq); - char const *sdp; - size_t len; - - if (session_get_description(sip, &sdp, &len)) { - su_home_t home[1] = { SU_HOME_INIT(home) }; - - sip_content_disposition_t *cd = NULL; - sip_content_type_t *ct = NULL; - sip_payload_t *pl = NULL; - - if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { - SU_DEBUG_5(("nua(%p): error parsing SDP in INVITE\n", nh)); - msg_destroy(msg); - status = 400, phrase = "Bad Session Description"; - } - - /* Respond to PRACK */ - - if (status >= 300) - ; - else if (sri->sr_offer_sent) { - recv = "answer"; - sri->sr_answer_recv = 1; - if (soa_process_answer(nh->nh_soa, NULL) < 0) - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - } - else { - recv = "offer"; - if (soa_generate_answer(nh->nh_soa, NULL) < 0) { - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - } - else { - if (session_make_description(home, nh->nh_soa, 1, &cd, &ct, &pl) > 0) - sent = "answer"; - } - } - - if (nta_incoming_treply(irq, status, phrase, - SIPTAG_CONTENT_DISPOSITION(cd), - SIPTAG_CONTENT_TYPE(ct), - SIPTAG_PAYLOAD(pl), - TAG_END()) < 0) - /* Respond with 500 if nta_incoming_treply() failed */ - SET_STATUS1(SIP_500_INTERNAL_SERVER_ERROR); - - su_home_deinit(home); - } - - msg_destroy(msg); - } - - nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq), - nua_i_prack, status, phrase, TAG_END()); - - if (status >= 300) - return status; - - if (recv || sent) { - soa_activate(nh->nh_soa, NULL); - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_early, recv, sent); - } - - if (NH_PGET(nh, auto_alert) && !ss->ss_alerting && !ss->ss_precondition) - nua_server_respond(sri, SIP_180_RINGING, TAG_END()); - - return status; -} - /** @NUA_EVENT nua_i_ack * * Final response to INVITE has been acknowledged by UAC with ACK. @@ -2252,6 +2131,7 @@ int process_ack(nua_server_request_t *sr, if (nh->nh_soa && sr->sr_offer_sent && !sr->sr_answer_recv) { char const *sdp; size_t len; + int error; if (!session_get_description(sip, &sdp, &len) || !(recv = "answer") || @@ -2264,23 +2144,30 @@ int process_ack(nua_server_request_t *sr, reason = soa_error_as_sip_reason(nh->nh_soa); nua_stack_event(nh->nh_nua, nh, msg, - nua_i_ack, status, phrase, TAG_END()); + nua_i_ack, status, phrase, NULL); nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_media_error, status, phrase, TAG_END()); + nua_i_media_error, status, phrase, NULL); + + assert(ss->ss_oa_recv == NULL); + + ss->ss_oa_recv = recv; + + ss->ss_reporting = 1; /* We report state here if BYE fails */ + error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); + ss->ss_reporting = 0; signal_call_state_change(nh, ss, 488, "Offer-Answer Error", - nua_callstate_terminating, recv, 0); - nua_stack_post_signal(nh, nua_r_bye, - SIPTAG_REASON_STR(reason), - TAG_END()); + error + ? nua_callstate_terminated + : nua_callstate_terminating); return 0; } } soa_clear_remote_sdp(nh->nh_soa); - nua_stack_event(nh->nh_nua, nh, msg, nua_i_ack, SIP_200_OK, TAG_END()); - signal_call_state_change(nh, ss, 200, "OK", nua_callstate_ready, recv, 0); + nua_stack_event(nh->nh_nua, nh, msg, nua_i_ack, SIP_200_OK, NULL); + signal_call_state_change(nh, ss, 200, "OK", nua_callstate_ready); set_session_timer(ss); nua_server_request_destroy(sr); @@ -2314,12 +2201,16 @@ int process_cancel(nua_server_request_t *sr, nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); msg_t *cancel = nta_incoming_getrequest_ackcancel(irq); - assert(nta_incoming_status(irq) < 200); assert(sr->sr_respond); + assert(nta_incoming_status(irq) < 200); + assert(nua_server_request_is_pending(sr)); assert(ss); assert(ss == nua_session_usage_get(nh->nh_ds)); (void)ss; - nua_stack_event(nh->nh_nua, nh, cancel, nua_i_cancel, SIP_200_OK, TAG_END()); + nua_stack_event(nh->nh_nua, nh, cancel, nua_i_cancel, SIP_200_OK, NULL); - nua_server_respond(sr, SIP_487_REQUEST_TERMINATED, TAG_END()); + SR_STATUS1(sr, SIP_487_REQUEST_TERMINATED); + + nua_server_respond(sr, NULL); + nua_server_report(sr); return 0; } @@ -2331,31 +2222,41 @@ int process_timeout(nua_server_request_t *sr, { nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + char const *phrase = "ACK Timeout"; + char const *reason = "SIP;cause=408;text=\"ACK Timeout\""; + int error; assert(ss); assert(ss == nua_session_usage_get(nh->nh_ds)); - nua_stack_event(nh->nh_nua, nh, 0, nua_i_error, - 408, "Response timeout", - TAG_END()); + if (nua_server_request_is_pending(sr)) { + phrase = "PRACK Timeout"; + reason = "SIP;cause=504;text=\"PRACK Timeout\""; + } - if (sr->sr_respond) { + nua_stack_event(nh->nh_nua, nh, 0, nua_i_error, 408, phrase, NULL); + + if (nua_server_request_is_pending(sr)) { /* PRACK timeout */ - nua_server_respond(sr, SIP_504_GATEWAY_TIME_OUT, - SIPTAG_REASON_STR("SIP;cause=504;" - "text=\"PRACK Timeout\""), - TAG_END()); - ss = nua_session_usage_get(nh->nh_ds); + SR_STATUS1(sr, SIP_504_GATEWAY_TIME_OUT); + nua_server_trespond(sr, + SIPTAG_REASON_STR(reason), + TAG_END()); + if (nua_server_report(sr) >= 2) + return 0; /* Done */ sr = NULL; } - if (ss) { - /* send BYE, too if 200 OK (or 183 to re-INVITE) timeouts */ - signal_call_state_change(nh, ss, 0, "Timeout", - nua_callstate_terminating, 0, 0); - nua_stack_post_signal(nh, nua_r_bye, - SIPTAG_REASON_STR("SIP;cause=408;text=\"ACK Timeout\""), - TAG_END()); - } + /* send BYE, too, if 200 OK (or 183 to re-INVITE) timeouts */ + ss->ss_reason = reason; + + ss->ss_reporting = 1; /* We report state here if BYE fails */ + error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL); + ss->ss_reporting = 0; + + signal_call_state_change(nh, ss, 0, phrase, + error + ? nua_callstate_terminated + : nua_callstate_terminating); if (sr) nua_server_request_destroy(sr); @@ -2364,6 +2265,206 @@ int process_timeout(nua_server_request_t *sr, } +/** @NUA_EVENT nua_i_prack + * + * Incoming PRACK request. PRACK request is used to acknowledge reliable + * preliminary responses and it is usually sent automatically by the nua + * stack. + * + * @param status status code of response sent automatically by stack + * @param phrase a short textual description of @a status code + * @param nh operation handle associated with the call + * @param hmagic application context associated with the call + * @param sip incoming PRACK request + * @param tags empty + * + * @sa nua_prack(), #nua_r_prack, @RFC3262, NUTAG_EARLY_MEDIA() + * + * @END_NUA_EVENT + */ + +int nua_prack_server_init(nua_server_request_t *sr); +int nua_prack_server_preprocess(nua_server_request_t *sr); +int nua_prack_server_respond(nua_server_request_t *sr, tagi_t const *tags); +int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags); + +nua_server_methods_t const nua_prack_server_methods = + { + SIP_METHOD_PRACK, + nua_i_prack, /* Event */ + { + 0, /* Do not create dialog */ + 1, /* In-dialog request */ + 1, /* Target refresh request */ + 1, /* Add Contact */ + }, + nua_prack_server_init, + nua_prack_server_preprocess, + nua_base_server_params, + nua_prack_server_respond, + nua_prack_server_report, + }; + +/** @internal Process reliable response PRACK or (timeout from 100rel) */ +static int process_prack(nua_handle_t *nh, + nta_reliable_t *rel, + nta_incoming_t *irq, + sip_t const *sip) +{ + nua_dialog_state_t *ds = nh->nh_ds; + nua_dialog_usage_t *du; + nua_server_request_t *sr; + + nta_reliable_destroy(rel); + if (irq == NULL) + /* Final response interrupted 100rel, we did not actually receive PRACK */ + return 200; + + if (!nh->nh_ds->ds_leg) + return 481; + + du = nua_dialog_usage_for_session(ds); + + for (sr = ds->ds_sr; sr; sr = sr->sr_next) { + if (sr->sr_method == sip_method_invite && sr->sr_usage == du) + break; + } + + if (!nua_server_request_is_pending(sr)) /* There is no INVITE */ + return 481; + + if (sip == NULL) { + /* 100rel timeout */ + SR_STATUS(sr, 504, "Reliable Response Timeout"); + nua_stack_event(nh->nh_nua, nh, NULL, nua_i_error, + sr->sr_status, sr->sr_phrase, + NULL); + nua_server_trespond(sr, + SIPTAG_REASON_STR("SIP;cause=504;" + "text=\"PRACK Timeout\""), + TAG_END()); + nua_server_report(sr); + return 504; + } + + nta_incoming_bind(irq, NULL, (void *)sr); + + return nua_stack_process_request(nh, nh->nh_ds->ds_leg, irq, sip); +} + + +int nua_prack_server_init(nua_server_request_t *sr) +{ + nua_handle_t *nh = sr->sr_owner; + nua_server_request_t *sri = nta_incoming_magic(sr->sr_irq, NULL); + + if (sri == NULL) + return SR_STATUS(sr, 481, "No Such Preliminary Response"); + + if (nua_session_server_init(sr)) + return sr->sr_status; + + if (sr->sr_sdp) { + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + + /* XXX - check for overlap? */ + + if (sri->sr_offer_sent) + sr->sr_answer_recv = 1, ss->ss_oa_recv = "answer"; + else + sr->sr_offer_recv = 1, ss->ss_oa_recv = "offer"; + + if (nh->nh_soa && + soa_set_remote_sdp(nh->nh_soa, NULL, sr->sr_sdp, sr->sr_sdp_len) < 0) { + SU_DEBUG_5(("nua(%p): %s server: error parsing %s\n", (void *)nh, + "PRACK", "offer")); + return + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); + } + } + + return 0; +} + +int nua_prack_server_preprocess(nua_server_request_t *sr) +{ + return sr_status(sr, SIP_200_OK); /* For now */ +} + +int nua_prack_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + + if (sr->sr_status < 200 || 300 <= sr->sr_status) + return nua_base_server_respond(sr, tags); + + if (nh->nh_soa && sr->sr_sdp) { + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; + + if ((sr->sr_offer_recv && soa_generate_answer(nh->nh_soa, NULL) < 0) || + (sr->sr_answer_recv && soa_process_answer(nh->nh_soa, NULL) < 0)) { + SU_DEBUG_5(("nua(%p): %s server: %s %s\n", + (void *)nh, "PRACK", + "error processing", + sr->sr_offer_recv ? "offer" : "answer")); + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); + } + else if (sr->sr_offer_recv) { + if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) + sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); + else + sr->sr_answer_sent = 1, ss->ss_oa_sent = "answer"; + } + } + + return nua_base_server_respond(sr, tags); +} + +int nua_prack_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + int retval = nua_base_server_report(sr, tags); /* destroys sr */ + + if (retval >= 2 || ss == NULL) { + signal_call_state_change(nh, NULL, + sr->sr_status, sr->sr_phrase, + nua_callstate_terminated); + return retval; + } + + if (sr->sr_offer_recv || sr->sr_answer_sent) { + /* signal offer received, answer sent */ + signal_call_state_change(nh, ss, + sr->sr_status, sr->sr_phrase, + ss->ss_state); + soa_activate(nh->nh_soa, NULL); + } + + if (200 <= sr->sr_status && sr->sr_status < 300 + && ss->ss_state < nua_callstate_ready + && !ss->ss_alerting + && !ss->ss_precondition + && NH_PGET(nh, auto_alert)) { + nua_server_request_t *sri; + + for (sri = nh->nh_ds->ds_sr; sri; sri = sri->sr_next) + if (sri->sr_method == sip_method_invite && + nua_server_request_is_pending(sri)) + break; + + if (sri) { + SR_STATUS1(sr, SIP_180_RINGING); + nua_server_respond(sri, NULL); + nua_server_report(sri); + } + } + + return retval; +} + /* ---------------------------------------------------------------------- */ /* Session timer - RFC 4028 */ @@ -2481,6 +2582,24 @@ init_session_timer(nua_session_usage_t *ss, return 1; } +static int session_timer_check_restart(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) +{ + if (cr->cr_usage && status == 422) { + nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage); + + if (sip->sip_min_se && ss->ss_min_se < sip->sip_min_se->min_delta) + ss->ss_min_se = sip->sip_min_se->min_delta; + if (ss->ss_min_se > ss->ss_session_timer) + ss->ss_session_timer = ss->ss_min_se; + + return nua_client_restart(cr, 100, "Re-Negotiating Session Timer"); + } + + return nua_base_client_check_restart(cr, status, phrase, sip); +} + static void set_session_timer(nua_session_usage_t *ss) { @@ -2505,31 +2624,6 @@ set_session_timer(nua_session_usage_t *ss) } } -static int -check_session_timer_restart(nua_handle_t *nh, - nua_session_usage_t *ss, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - nua_creq_restart_f *restart_function) -{ - if (ss && sip && sip->sip_status->st_status == 422) { - if (sip->sip_min_se && ss->ss_min_se < sip->sip_min_se->min_delta) - ss->ss_min_se = sip->sip_min_se->min_delta; - if (ss->ss_min_se > ss->ss_session_timer) - ss->ss_session_timer = ss->ss_min_se; - - if (orq == cr->cr_orq) - cr->cr_orq = NULL; - - return nua_creq_restart_with(nh, cr, orq, - 100, "Re-Negotiating Session Timer", - restart_function, TAG_END()); - } - - return nua_creq_check_restart(nh, cr, orq, sip, restart_function); -} - static inline int is_session_timer_set(nua_session_usage_t *ss) { @@ -2611,7 +2705,7 @@ nh_referral_respond(nua_handle_t *nh, int status, char const *phrase) if (ref) { if (ref->ref_handle) SU_DEBUG_1(("nh_handle_referral: stale referral handle %p\n", - ref->ref_handle)); + (void *)ref->ref_handle)); ref->ref_handle = NULL; } return; @@ -2647,33 +2741,9 @@ nh_referral_respond(nua_handle_t *nh, int status, char const *phrase) nua_handle_unref(ref->ref_handle), ref->ref_handle = NULL; } - -/** Zap the session associated with the handle */ -static -void nua_session_usage_destroy(nua_handle_t *nh, - nua_session_usage_t *ss) -{ - nh->nh_has_invite = 0; - nh->nh_active_call = 0; - nh->nh_hold_remote = 0; - - if (nh->nh_soa) - soa_destroy(nh->nh_soa), nh->nh_soa = NULL; - - /* Remove usage */ - nua_dialog_usage_remove(nh, nh->nh_ds, nua_dialog_usage_public(ss)); - - SU_DEBUG_5(("nua: terminated session %p\n", nh)); -} - - /* ======================================================================== */ /* INFO */ -static int process_response_to_info(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - /**@fn void nua_info(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Send an INFO request. @@ -2696,41 +2766,59 @@ static int process_response_to_info(nua_handle_t *nh, * @sa #nua_i_info */ +static int nua_info_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); + +static int nua_info_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); + +nua_client_methods_t const nua_info_client_methods = { + SIP_METHOD_INFO, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 1, + /* target refresh */ 0 + }, + /*nua_info_client_template*/ NULL, + nua_info_client_init, + nua_info_client_request, + /*nua_info_client_check_restart*/ NULL, + /*nua_info_client_response*/ NULL +}; + int nua_stack_info(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - - if (nh_is_special(nh)) { - return UA_EVENT2(e, 900, "Invalid handle for INFO"); - } - else if (cr->cr_orq) { - return UA_EVENT2(e, 900, "Request already in progress"); - } - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_INFO , - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_info, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - if (!cr->cr_orq) { - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } - - return cr->cr_event = e; + return nua_client_create(nh, e, &nua_info_client_methods, tags); } -void restart_info(nua_handle_t *nh, tagi_t *tags) +static int nua_info_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_info, tags); + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + if (!ss || ss->ss_state >= nua_callstate_terminating) + return nua_client_return(cr, 900, "Invalid handle for INFO", msg); + + cr->cr_usage = du; + + return 0; +} + +static int nua_info_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + if (cr->cr_usage == NULL) + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); + else + return nua_base_client_request(cr, msg, sip, tags); } /** @NUA_EVENT nua_r_info @@ -2754,15 +2842,6 @@ void restart_info(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_info(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) -{ - if (nua_creq_check_restart(nh, nh->nh_ds->ds_cr, orq, sip, restart_info)) - return 0; - return nua_stack_process_response(nh, nh->nh_ds->ds_cr, orq, sip, TAG_END()); -} - /** @NUA_EVENT nua_i_info * * Incoming session INFO request. @@ -2779,25 +2858,26 @@ static int process_response_to_info(nua_handle_t *nh, * @END_NUA_EVENT */ -int nua_stack_process_info(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq), - nua_i_info, SIP_200_OK, TAG_END()); - - return 200; /* Respond automatically with 200 Ok */ -} - +nua_server_methods_t const nua_info_server_methods = + { + SIP_METHOD_INFO, + nua_i_info, /* Event */ + { + 0, /* Do not create dialog */ + 1, /* In-dialog request */ + 0, /* Not a target refresh request */ + 0, /* Do not add Contact */ + }, + nua_base_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_base_server_report, + }; /* ======================================================================== */ /* UPDATE */ -static int process_response_to_update(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - /**@fn void nua_update(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Update a session. @@ -2826,91 +2906,134 @@ static int process_response_to_update(nua_handle_t *nh, * @sa @ref nua_call_model, @RFC3311, nua_update(), #nua_i_update */ +static int nua_update_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_update_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_update_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); +static int nua_update_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +nua_client_methods_t const nua_update_client_methods = { + SIP_METHOD_UPDATE, + 0, /* size of private data */ + { + /* create_dialog */ 0, + /* in_dialog */ 1, + /* target refresh */ 1 + }, + NULL, + nua_update_client_init, + nua_update_client_request, + session_timer_check_restart, + nua_update_client_response, + NULL, + nua_update_client_report +}; + int nua_stack_update(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_dialog_state_t *ds = nh->nh_ds; - nua_session_usage_t *ss; - nua_client_request_t *cr; - msg_t *msg; - sip_t *sip; - char const *offer_sent = 0; + return nua_client_create(nh, e, &nua_update_client_methods, tags); +} - ss = nua_session_usage_get(ds); - cr = ds->ds_cr; +static int nua_update_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); - if (!ss) - return UA_EVENT2(e, 900, "Invalid handle for UPDATE"); - else if (cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); + cr->cr_usage = du; - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); + return 0; +} - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_UPDATE, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); +static int nua_update_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + nua_server_request_t *sr; + nua_client_request_t *cri; + int offer_sent = 0, retval; + + if (du == NULL) /* Call terminated */ + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); + assert(ss); - sip = sip_object(msg); + cri = du->du_cr; - if (sip) { - nua_client_request_t *cri = ss->ss_crequest; - nua_server_request_t *sr; - - for (sr = ds->ds_sr; sr; sr = sr->sr_next) - if ((sr->sr_offer_sent && !sr->sr_answer_recv) || - (sr->sr_offer_recv && !sr->sr_answer_sent)) - break; + for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) + if ((sr->sr_offer_sent && !sr->sr_answer_recv) || + (sr->sr_offer_recv && !sr->sr_answer_sent)) + break; - if (nh->nh_soa && !sip->sip_payload && - !sr && - !(cri && cri->cr_offer_sent && !cri->cr_answer_recv) && - !(cri && cri->cr_offer_recv && !cri->cr_answer_sent)) { - soa_init_offer_answer(nh->nh_soa); + if (nh->nh_soa && !sip->sip_payload && + !sr && + !(cri && cri->cr_offer_sent && !cri->cr_answer_recv) && + !(cri && cri->cr_offer_recv && !cri->cr_answer_sent)) { + soa_init_offer_answer(nh->nh_soa); - if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || - session_include_description(nh->nh_soa, 1, msg, sip) < 0) { - if (ss->ss_state < nua_callstate_ready) { - /* XXX */ - } - msg_destroy(msg); - return UA_EVENT2(e, 900, "Local media failed"); + if (soa_generate_offer(nh->nh_soa, 0, NULL) < 0 || + session_include_description(nh->nh_soa, 1, msg, sip) < 0) { + if (ss->ss_state < nua_callstate_ready) { + /* XXX - use soa_error_as_sip_reason(nh->nh_soa) */ + cr->cr_graceful = 1; + ss->ss_reason = "SIP;cause=400;text=\"Local media failure\""; } - - offer_sent = "offer"; + return nua_client_return(cr, 900, "Local media failed", msg); } + offer_sent = 1; + } - /* Add session timer headers */ - if (session_timer_is_supported(nh)) - use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip); + /* Add session timer headers */ + if (session_timer_is_supported(nh)) + use_session_timer(ss, 0, prefer_session_timer(nh), msg, sip); - if (nh->nh_auth) { - if (auc_authorize(&nh->nh_auth, msg, sip) < 0) - /* xyzzy */; - } + retval = nua_base_client_request(cr, msg, sip, NULL); - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_update, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - if (cr->cr_orq) { + if (retval == 0) { + cr->cr_offer_sent = offer_sent; + ss->ss_update_needed = 0; + + if (!cr->cr_restarting) { if (offer_sent) - cr->cr_offer_sent = 1; - ss->ss_update_needed = 0; - signal_call_state_change(nh, ss, 0, "UPDATE sent", - ss->ss_state, 0, offer_sent); - return cr->cr_event = e; + ss->ss_oa_sent = "offer"; + signal_call_state_change(nh, ss, 0, "UPDATE sent", ss->ss_state); } } - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); + return retval; } -void restart_update(nua_handle_t *nh, tagi_t *tags) +static int nua_update_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_update, tags); + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + + assert(200 <= status); + + if (ss && sip && status < 300) { + if (is_session_timer_set(ss)) { + init_session_timer(ss, sip, NH_PGET(nh, refresher)); + set_session_timer(ss); + } + } + + return nua_session_client_response(cr, status, phrase, sip); } /** @NUA_EVENT nua_r_update @@ -2937,134 +3060,75 @@ void restart_update(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_update(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) +static int nua_update_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) { - nua_t *nua = nh->nh_nua; - nua_session_usage_t *ss; - nua_client_request_t *cr = nh->nh_ds->ds_cr; + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); - int status = sip->sip_status->st_status; - char const *phrase = sip->sip_status->st_phrase; - char const *recv = NULL; - int terminate = 0, gracefully = 1; + nua_stack_event(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + tags); - ss = nua_session_usage_get(nh->nh_ds); assert(ss); + if (!ss || orq != cr->cr_orq || + cr->cr_terminated || cr->cr_graceful || !cr->cr_offer_sent) + return 1; - if (status >= 300) { - if (sip->sip_retry_after) - gracefully = 0; + signal_call_state_change(nh, ss, status, phrase, ss->ss_state); - terminate = sip_response_terminates_dialog(status, sip_method_update, - &gracefully); - - if (!terminate && - check_session_timer_restart(nh, ss, cr, orq, sip, restart_update)) { - return 0; - } - /* XXX - if we have a concurrent INVITE, what we do with it? */ - } - else if (status >= 200) { - /* XXX - check remote tag, handle forks */ - /* Set (route), contact, (remote tag) */ - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - - if (is_session_timer_set(ss)) { - init_session_timer(ss, sip, NH_PGET(nh, refresher)); - set_session_timer(ss); - } - - if (session_process_response(nh, cr, orq, sip, &recv) < 0) { - nua_stack_event(nua, nh, NULL, nua_i_error, - 400, "Bad Session Description", TAG_END()); - } - - signal_call_state_change(nh, ss, status, phrase, ss->ss_state, recv, 0); - - return 0; - } - else - gracefully = 0; - - nua_stack_process_response(nh, cr, orq, sip, TAG_END()); - - if (!terminate && !gracefully) - return 0; - - nh_referral_respond(nh, status, phrase); - - if (ss == NULL) { - - } - else if (terminate || - (ss->ss_state < nua_callstate_completed && - ss->ss_state != nua_callstate_completing)) { - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_terminated, recv, 0); - nua_session_usage_destroy(nh, ss); - } - else /* if (gracefully) */ { - signal_call_state_change(nh, ss, status, phrase, - nua_callstate_terminating, recv, 0); -#if 0 - if (nh->nh_ss->ss_crequest->cr_orq) - nua_stack_post_signal(nh, nua_r_cancel, TAG_END()); - else -#endif - nua_stack_post_signal(nh, nua_r_bye, TAG_END()); - } - - return 0; + return 1; } -int nua_stack_process_update(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +/* ---------------------------------------------------------------------- */ +/* UPDATE server */ + +int nua_update_server_init(nua_server_request_t *sr); +int nua_update_server_preprocess(nua_server_request_t *sr); +int nua_update_server_respond(nua_server_request_t *sr, tagi_t const *tags); +int nua_update_server_report(nua_server_request_t *, tagi_t const *); + +nua_server_methods_t const nua_update_server_methods = + { + SIP_METHOD_UPDATE, + nua_i_update, /* Event */ + { + 0, /* Do not create dialog */ + 1, /* In-dialog request */ + 1, /* Target refresh request */ + 1, /* Add Contact */ + }, + nua_update_server_init, + nua_update_server_preprocess, + nua_base_server_params, + nua_update_server_respond, + nua_update_server_report, + }; + +int nua_update_server_init(nua_server_request_t *sr) { - nua_dialog_state_t *ds = nh->nh_ds; + nua_handle_t *nh = sr->sr_owner; nua_session_usage_t *ss; - nua_dialog_usage_t *du; - msg_t *msg = nta_incoming_getrequest(irq); - char const *sdp; - size_t len; + sip_t const *request = sr->sr_request.sip; - int original_status = 200, status = 200; - char const *phrase = sip_200_OK; + if (nua_session_server_init(sr)) + return sr->sr_status; - char const *offer_recv = NULL, *answer_sent = NULL; - int use_timer = 0; - - msg_t *rmsg; - sip_t *rsip; - - ss = nua_session_usage_get(ds); du = nua_dialog_usage_public(ss); - if (!ss) { - /* RFC 3261 section 12.2.2: - If the UAS wishes to reject the request because it does not wish to - recreate the dialog, it MUST respond to the request with a 481 - (Call/Transaction Does Not Exist) status code and pass that to the - server transaction. - */ - return 481; - } - - if (session_check_request(nua, nh, irq, sip)) - return 501; + ss = nua_dialog_usage_private(sr->sr_usage); /* Do session timer negotiation */ - if (sip->sip_session_expires) { - use_timer = 1; - init_session_timer(ss, sip, NH_PGET(nh, refresher)); - } + if (request->sip_session_expires) + init_session_timer(ss, request, NH_PGET(nh, refresher)); - if (status < 300 && nh->nh_soa && - session_get_description(sip, &sdp, &len)) { + if (sr->sr_sdp) { /* Check for overlap */ nua_client_request_t *cr; - nua_server_request_t *sr; + nua_server_request_t *sr0; int overlap = 0; /* @@ -3082,70 +3146,76 @@ int nua_stack_process_update(nua_t *nua, reject the UPDATE with a 500 response, and MUST include a Retry-After header field with a randomly chosen value between 0 and 10 seconds. */ - for (cr = ds->ds_cr; cr && !overlap; cr = cr->cr_next) - overlap = cr->cr_offer_sent && !cr->cr_answer_recv; - for (sr = ds->ds_sr; sr && !overlap; sr = sr->sr_next) - overlap = (sr->sr_offer_recv && !sr->sr_answer_sent) || - (sr->sr_method == sip_method_update && sr->sr_respond); + for (cr = nh->nh_ds->ds_cr; cr; cr = cr->cr_next) + if ((overlap = cr->cr_offer_sent && !cr->cr_answer_recv)) + break; + + if (!overlap) + for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr0->sr_next) + if ((overlap = sr0->sr_offer_recv && !sr0->sr_answer_sent)) + break; if (overlap) - return respond_with_retry_after(nh, irq, - 500, "Overlapping Offer/Answer", - 0, 10); + return nua_server_retry_after(sr, 500, "Overlapping Offer/Answer", 1, 9); - offer_recv = "offer"; - - if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { - SU_DEBUG_5(("nua(%p): error parsing SDP in UPDATE\n", nh)); - msg_destroy(msg); - status = soa_error_as_sip_response(nh->nh_soa, &phrase); - offer_recv = NULL; + if (nh->nh_soa && + soa_set_remote_sdp(nh->nh_soa, NULL, sr->sr_sdp, sr->sr_sdp_len) < 0) { + SU_DEBUG_5(("nua(%p): %s server: error parsing %s\n", (void *)nh, + "UPDATE", "offer")); + return + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } - /* Respond to UPDATE */ - else if (soa_generate_answer(nh->nh_soa, NULL) < 0) { - SU_DEBUG_5(("nua(%p): error processing SDP in UPDATE\n", nh)); - msg_destroy(msg); - status = soa_error_as_sip_response(nh->nh_soa, &phrase); + + sr->sr_offer_recv = 1; + ss->ss_oa_recv = "offer"; + } + + return 0; +} + +int nua_update_server_preprocess(nua_server_request_t *sr) +{ + return sr_status(sr, SIP_200_OK); /* For now */ +} + +/** @internal Respond to an UPDATE request. + * + */ +int nua_update_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + soa_session_t *soa = nh->nh_soa; + + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; + + if (200 <= sr->sr_status && sr->sr_status < 300 && soa && sr->sr_sdp) { + if (soa_generate_answer(nh->nh_soa, NULL) < 0) { + SU_DEBUG_5(("nua(%p): %s server: %s %s\n", + (void *)nh, "UPDATE", "error processing", "offer")); + sr->sr_status = soa_error_as_sip_response(nh->nh_soa, &sr->sr_phrase); } else if (soa_activate(nh->nh_soa, NULL) < 0) { - SU_DEBUG_5(("nua(%p): error activating media after %s\n", - nh, "UPDATE")); + SU_DEBUG_5(("nua(%p): %s server: error activating media\n", + (void *)nh, "UPDATE")); /* XXX */ } - else { - answer_sent = "answer"; + else if (session_include_description(nh->nh_soa, 1, msg, sip) < 0) { + sr_status(sr, SIP_500_INTERNAL_SERVER_ERROR); } + else + sr->sr_answer_sent = 1, ss->ss_oa_sent = "answer"; } - rmsg = nh_make_response(nua, nh, irq, - status, phrase, - TAG_IF(status < 300, NUTAG_ADD_CONTACT(1)), - SIPTAG_SUPPORTED(NH_PGET(nh, supported)), - TAG_NEXT(NULL)); - rsip = sip_object(rmsg); - assert(sip); /* XXX */ + if (ss->ss_refresher && 200 <= sr->sr_status && sr->sr_status < 300) + if (session_timer_is_supported(nh)) { + use_session_timer(ss, 1, 1, msg, sip); + set_session_timer(ss); /* XXX */ + } - if (answer_sent && - session_include_description(nh->nh_soa, 1, rmsg, rsip) < 0) { - status = 500, phrase = sip_500_Internal_server_error; - answer_sent = NULL; - } - - if (200 <= status && status < 300 && session_timer_is_supported(nh)) { - use_session_timer(ss, 1, use_timer, rmsg, rsip); - set_session_timer(ss); - } - - if (status == original_status) { - if (nta_incoming_mreply(irq, rmsg) < 0) - status = 500, phrase = sip_500_Internal_server_error; - } - - if (status != original_status) { - nua_stack_event(nua, nh, NULL, nua_i_error, status, phrase, TAG_END()); - nta_incoming_treply(irq, status, phrase, TAG_END()); - msg_destroy(rmsg), rmsg = NULL; - } + return nua_base_server_respond(sr, tags); +} /** @NUA_EVENT nua_i_update * @@ -3163,39 +3233,52 @@ int nua_stack_process_update(nua_t *nua, * @END_NUA_EVENT */ - nua_stack_event(nh->nh_nua, nh, msg, nua_i_update, status, phrase, TAG_END()); +int nua_update_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_dialog_usage_t *du = sr->sr_usage; + nua_session_usage_t *ss = nua_dialog_usage_private(du); + int retval = nua_base_server_report(sr, tags); /* destroys sr */ - if (offer_recv || answer_sent) - /* signal offer received, answer sent */ - signal_call_state_change(nh, ss, 200, "OK", ss->ss_state, - offer_recv, answer_sent); - - if (NH_PGET(nh, auto_alert) - && ss->ss_state < nua_callstate_ready - && !ss->ss_alerting - && ss->ss_precondition) { - nua_server_request_t *sr; - - for (sr = ds->ds_sr; sr; sr = sr->sr_next) - if (sr->sr_method == sip_method_invite && - sr->sr_usage == du && sr->sr_respond) - break; - - if (sr) - nua_server_respond(sr, SIP_180_RINGING, TAG_END()); + if (retval >= 2 || ss == NULL) { + signal_call_state_change(nh, NULL, + sr->sr_status, sr->sr_phrase, + nua_callstate_terminated); + return retval; } - return status; -} + if (sr->sr_offer_recv || sr->sr_answer_sent) + /* signal offer received, answer sent */ + signal_call_state_change(nh, ss, + sr->sr_status, sr->sr_phrase, + ss->ss_state); + if (200 <= sr->sr_status && sr->sr_status < 300 + && ss->ss_state < nua_callstate_ready + && ss->ss_precondition + && !ss->ss_alerting + && NH_PGET(nh, auto_alert)) { + nua_server_request_t *sr; + + for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) + if (sr->sr_method == sip_method_invite && + nua_server_request_is_pending(sr)) + break; + + if (sr) { + SR_STATUS1(sr, SIP_180_RINGING); + nua_server_respond(sr, NULL); + nua_server_report(sr); + return retval; + } + } + + return retval; +} /* ======================================================================== */ /* BYE */ -static int process_response_to_bye(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - /**@fn void nua_bye(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...); * * Hangdown a call. @@ -3217,87 +3300,95 @@ static int process_response_to_bye(nua_handle_t *nh, * #nua_i_media_error */ +static int nua_bye_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_bye_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags); +static int nua_bye_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags); + +nua_client_methods_t const nua_bye_client_methods = { + SIP_METHOD_BYE, + 0, + { + /* create_dialog */ 0, + /* in_dialog */ 1, + /* target refresh */ 0 + }, + NULL, + nua_bye_client_init, + nua_bye_client_request, + /*nua_bye_client_check_restart*/ NULL, + /*nua_bye_client_response*/ NULL, + /*nua_bye_client_preliminary*/ NULL, + nua_bye_client_report +}; + int nua_stack_bye(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_session_usage_t *ss; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - nta_outgoing_t *orq; + nua_session_usage_t *ss = nua_session_usage_get(nh->nh_ds); - ss = nua_session_usage_get(nh->nh_ds); - - if (!ss || ss->ss_state >= nua_callstate_terminating) - return UA_EVENT2(e, 900, "Invalid handle for BYE"); + if (ss && + nua_callstate_calling <= ss->ss_state && + ss->ss_state <= nua_callstate_proceeding) + return nua_client_create(nh, e, &nua_cancel_client_methods, tags); + else + return nua_client_create(nh, e, &nua_bye_client_methods, tags); +} - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); +static int nua_bye_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); + nua_session_usage_t *ss = nua_dialog_usage_private(du); - if (!nua_dialog_is_established(nh->nh_ds)) { - nua_client_request_t *cri = ss->ss_crequest; + if (!ss || (ss->ss_state >= nua_callstate_terminating && !cr->cr_auto)) + return nua_client_return(cr, 900, "Invalid handle for BYE", msg); - if (cri->cr_orq == NULL) - return UA_EVENT2(e, 900, "No session to BYE"); + if (!cr->cr_auto) + /* Implicit state transition by nua_bye() */ + ss->ss_state = nua_callstate_terminating; - /* No (early) dialog. BYE is invalid action, do CANCEL instead */ - orq = nta_outgoing_tcancel(cri->cr_orq, - process_response_to_cancel, nh, - TAG_NEXT(tags)); - if (!cr->cr_orq) - cr->cr_orq = orq, cr->cr_event = e; - - return 0; - } - - if (cr->cr_orq) { - if (cr->cr_usage == nua_dialog_usage_public(ss)) { - nua_creq_deinit(cr, cr->cr_orq); - } - else { - cr = ss->ss_crequest; - if (cr->cr_orq) - nua_creq_deinit(cr, cr->cr_orq); - } - } - - assert(!cr->cr_orq); - - msg = nua_creq_msg(nua, nh, cr, 0, SIP_METHOD_BYE, TAG_NEXT(tags)); - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_bye, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - - ss->ss_state = nua_callstate_terminating; if (nh->nh_soa) soa_terminate(nh->nh_soa, 0); - - if (cr->cr_orq) { - cr->cr_event = e; - } - else { - msg_destroy(msg); - UA_EVENT2(e, 400, "Internal error"); - signal_call_state_change(nh, ss, 400, "Failure sending BYE", - nua_callstate_terminated, 0, 0); - nua_session_usage_destroy(nh, ss); - } + cr->cr_usage = du; return 0; } - -void restart_bye(nua_handle_t *nh, tagi_t *tags) +static int nua_bye_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) { - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_bye, tags); + nua_dialog_usage_t *du = cr->cr_usage; + nua_session_usage_t *ss; + char const *reason = NULL; + + if (du == NULL) + return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); + + ss = nua_dialog_usage_private(du); + reason = ss->ss_reason; + + return nua_base_client_trequest(cr, msg, sip, + SIPTAG_REASON_STR(reason), + TAG_NEXT(tags)); } /** @NUA_EVENT nua_r_bye * * Answer to outgoing BYE. * - * The BYE may be sent explicitly by nua_bye() or - * implicitly by NUA state machine. + * The BYE may be sent explicitly by nua_bye() or implicitly by NUA state + * machine. * * @param status response status code * (if the request is retried, @a status is 100, the @a @@ -3316,45 +3407,42 @@ void restart_bye(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_bye(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip) +static int nua_bye_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) { - nua_client_request_t *cr = NULL; - nua_session_usage_t *ss; - int status = sip ? sip->sip_status->st_status : 400; - char const *phrase = sip ? sip->sip_status->st_phrase : ""; + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; - cr = nua_client_request_by_orq(nh->nh_ds->ds_cr, orq); assert(cr); + nua_stack_event(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + tags); - if (cr) { - if (nua_creq_check_restart(nh, cr, orq, sip, restart_bye)) - return 0; - nua_stack_process_response(nh, cr, orq, sip, TAG_END()); + if (du == NULL) { + /* No more session */ } - else { /* No cr for BYE */ - msg_t *msg = nta_outgoing_getresponse(orq); - nua_stack_event(nh->nh_nua, nh, msg, nua_r_bye, status, phrase, TAG_END()); - nta_outgoing_destroy(orq); + else if (status < 200) { + /* Preliminary */ } + else { + nua_session_usage_t *ss = nua_dialog_usage_private(du); - ss = nua_session_usage_get(nh->nh_ds); + signal_call_state_change(nh, ss, status, "to BYE", + nua_callstate_terminated); - if (status >= 200 && ss) { - if (ss->ss_crequest->cr_orq) { - /* Do not destroy usage while INVITE is alive */ - } - else { - signal_call_state_change(nh, ss, status, "to BYE", - nua_callstate_terminated, 0, 0); + if (ss && !ss->ss_reporting && !nua_client_is_queued(du->du_cr)) { + /* Do not destroy session usage while INVITE is alive */ nua_session_usage_destroy(nh, ss); } } - return 0; + return 1; } - /** @NUA_EVENT nua_i_bye * * Incoming BYE request, call hangup. @@ -3371,48 +3459,82 @@ static int process_response_to_bye(nua_handle_t *nh, * @END_NUA_EVENT */ -int nua_stack_process_bye(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +int nua_bye_server_init(nua_server_request_t *sr); +int nua_bye_server_report(nua_server_request_t *sr, tagi_t const *tags); + +nua_server_methods_t const nua_bye_server_methods = + { + SIP_METHOD_BYE, + nua_i_bye, /* Event */ + { + 0, /* Do not create dialog */ + 1, /* In-dialog request */ + 0, /* Not a target refresh request */ + 0, /* Do not add Contact */ + }, + nua_bye_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_bye_server_report, + }; + + +int nua_bye_server_init(nua_server_request_t *sr) { - nua_dialog_state_t *ds = nh->nh_ds; - nua_session_usage_t *ss; - nua_server_request_t *sr, *sr_next; - int early = 0; + nua_handle_t *nh = sr->sr_owner; + nua_dialog_usage_t *du = nua_dialog_usage_for_session(nh->nh_ds); - ss = nua_session_usage_get(ds); - if (!ss) - return 481; + sr->sr_terminating = 1; - assert(nh && ss); + if (du) + sr->sr_usage = du; + else + return SR_STATUS(sr, 481, "No Such Call"); - nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq), - nua_i_bye, SIP_200_OK, TAG_END()); - nta_incoming_treply(irq, SIP_200_OK, TAG_END()); - nta_incoming_destroy(irq), irq = NULL; + return 0; +} - for (sr = ds->ds_sr; sr; sr = sr_next) { - sr_next = sr->sr_next; - if (sr->sr_respond && sr->sr_usage == nua_dialog_usage_public(ss)) { - char const *phrase; - early = ss->ss_state < nua_callstate_ready; - phrase = early ? "Early Session Terminated" : "Session Terminated"; - sr->sr_usage = NULL; - if (sr->sr_respond) - nua_server_respond(sr, 487, phrase, TAG_END()); - else - nua_server_request_destroy(sr); +int nua_bye_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_session_usage_t *ss = nua_dialog_usage_private(sr->sr_usage); + int early = 0, retval; + + if (sr->sr_status < 200) + return nua_base_server_report(sr, tags); + + if (ss) { + nua_server_request_t *sr0 = NULL, *sr_next; + char const *phrase; + + early = ss->ss_state < nua_callstate_ready; + phrase = early ? "Early Session Terminated" : "Session Terminated"; + + for (sr0 = nh->nh_ds->ds_sr; sr0; sr0 = sr_next) { + sr_next = sr0->sr_next; + + if (sr == sr0 || sr0->sr_usage != sr->sr_usage) + continue; + + if (nua_server_request_is_pending(sr0)) { + SR_STATUS(sr0, 487, phrase); + nua_server_respond(sr0, NULL); + } + nua_server_request_destroy(sr0); } } - signal_call_state_change(nh, ss, 200, - early ? "Received early BYE" : "Received BYE", - nua_callstate_terminated, 0, 0); + retval = nua_base_server_report(sr, tags); - nua_session_usage_destroy(nh, ss); + assert(2 <= retval && retval < 4); - return 0; + if (ss) + signal_call_state_change(nh, NULL, 200, + early ? "Received early BYE" : "Received BYE", + nua_callstate_terminated); + + return retval; } /* ---------------------------------------------------------------------- */ @@ -3430,35 +3552,46 @@ int nua_stack_process_bye(nua_t *nua, static void signal_call_state_change(nua_handle_t *nh, nua_session_usage_t *ss, int status, char const *phrase, - enum nua_callstate next_state, - char const *oa_recv, - char const *oa_sent) + enum nua_callstate next_state) { - enum nua_callstate ss_state; + enum nua_callstate ss_state = nua_callstate_init; sdp_session_t const *remote_sdp = NULL; char const *remote_sdp_str = NULL; sdp_session_t const *local_sdp = NULL; char const *local_sdp_str = NULL; + char const *oa_recv = NULL; + char const *oa_sent = NULL; int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0; - ss_state = ss ? ss->ss_state : nua_callstate_init; + if (ss && ss->ss_reporting) + return; + + if (ss) { + ss_state = ss->ss_state; + oa_recv = ss->ss_oa_recv, ss->ss_oa_recv = NULL; + oa_sent = ss->ss_oa_sent, ss->ss_oa_sent = NULL; + } if (ss_state < nua_callstate_ready || next_state > nua_callstate_ready) SU_DEBUG_5(("nua(%p): call state changed: %s -> %s%s%s%s%s\n", - nh, nua_callstate_name(ss_state), + (void *)nh, nua_callstate_name(ss_state), nua_callstate_name(next_state), oa_recv ? ", received " : "", oa_recv ? oa_recv : "", oa_sent && oa_recv ? ", and sent " : oa_sent ? ", sent " : "", oa_sent ? oa_sent : "")); else SU_DEBUG_5(("nua(%p): ready call updated: %s%s%s%s%s\n", - nh, nua_callstate_name(next_state), + (void *)nh, nua_callstate_name(next_state), oa_recv ? " received " : "", oa_recv ? oa_recv : "", oa_sent && oa_recv ? ", sent " : oa_sent ? " sent " : "", oa_sent ? oa_sent : "")); + if (next_state == nua_callstate_terminating && + ss_state >= nua_callstate_terminating) + return; + if (oa_recv) { soa_get_remote_sdp(nh->nh_soa, &remote_sdp, &remote_sdp_str, 0); offer_recv = strcasecmp(oa_recv, "offer") == 0; @@ -3483,12 +3616,20 @@ static void signal_call_state_change(nua_handle_t *nh, if (ss) { /* Update state variables */ - if (next_state > ss_state) + if (next_state == nua_callstate_init) { + if (ss_state < nua_callstate_ready) + ss->ss_state = next_state; + else + /* Do not change state - we are ready, terminating, or terminated */ + next_state = ss_state; + } + else if (next_state > ss_state) ss->ss_state = next_state; - else if (next_state == nua_callstate_init && ss_state < nua_callstate_ready) - ss->ss_state = nua_callstate_init, next_state = nua_callstate_terminated; } + if (next_state == nua_callstate_init) + next_state = nua_callstate_terminated; + if (ss && ss->ss_state == nua_callstate_ready) nh->nh_active_call = 1; else if (next_state == nua_callstate_terminated) @@ -3547,20 +3688,20 @@ static void signal_call_state_change(nua_handle_t *nh, * @END_NUA_EVENT */ - nua_stack_event(nh->nh_nua, nh, NULL, nua_i_state, - status, phrase, - NUTAG_CALLSTATE(next_state), - NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), - /* NUTAG_SOA_SESSION(nh->nh_soa), */ - TAG_IF(offer_recv, NUTAG_OFFER_RECV(offer_recv)), - TAG_IF(answer_recv, NUTAG_ANSWER_RECV(answer_recv)), - TAG_IF(offer_sent, NUTAG_OFFER_SENT(offer_sent)), - TAG_IF(answer_sent, NUTAG_ANSWER_SENT(answer_sent)), - TAG_IF(oa_recv, SOATAG_REMOTE_SDP(remote_sdp)), - TAG_IF(oa_recv, SOATAG_REMOTE_SDP_STR(remote_sdp_str)), - TAG_IF(oa_sent, SOATAG_LOCAL_SDP(local_sdp)), - TAG_IF(oa_sent, SOATAG_LOCAL_SDP_STR(local_sdp_str)), - TAG_END()); + nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_state, + status, phrase, + NUTAG_CALLSTATE(next_state), + NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), + /* NUTAG_SOA_SESSION(nh->nh_soa), */ + TAG_IF(offer_recv, NUTAG_OFFER_RECV(offer_recv)), + TAG_IF(answer_recv, NUTAG_ANSWER_RECV(answer_recv)), + TAG_IF(offer_sent, NUTAG_OFFER_SENT(offer_sent)), + TAG_IF(answer_sent, NUTAG_ANSWER_SENT(answer_sent)), + TAG_IF(oa_recv, SOATAG_REMOTE_SDP(remote_sdp)), + TAG_IF(oa_recv, SOATAG_REMOTE_SDP_STR(remote_sdp_str)), + TAG_IF(oa_sent, SOATAG_LOCAL_SDP(local_sdp)), + TAG_IF(oa_sent, SOATAG_LOCAL_SDP_STR(local_sdp_str)), + TAG_END()); /** @NUA_EVENT nua_i_active * @@ -3584,10 +3725,10 @@ static void signal_call_state_change(nua_handle_t *nh, */ if (next_state == nua_callstate_ready && ss_state <= nua_callstate_ready) { - nua_stack_event(nh->nh_nua, nh, NULL, nua_i_active, status, "Call active", - NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), - /* NUTAG_SOA_SESSION(nh->nh_soa), */ - TAG_END()); + nua_stack_tevent(nh->nh_nua, nh, NULL, nua_i_active, status, "Call active", + NH_ACTIVE_MEDIA_TAGS(1, nh->nh_soa), + /* NUTAG_SOA_SESSION(nh->nh_soa), */ + TAG_END()); } /** @NUA_EVENT nua_i_terminated @@ -3615,17 +3756,18 @@ static void signal_call_state_change(nua_handle_t *nh, */ else if (next_state == nua_callstate_terminated) { - nua_stack_event(nh->nh_nua, nh, NULL, nua_i_terminated, status, phrase, - TAG_END()); + nua_stack_event(nh->nh_nua, nh, NULL, + nua_i_terminated, status, phrase, + NULL); } } /* ======================================================================== */ static -int respond_with_retry_after(nua_handle_t *nh, nta_incoming_t *irq, - int status, char const *phrase, - int min, int max) +int nua_server_retry_after(nua_server_request_t *sr, + int status, char const *phrase, + int min, int max) { sip_retry_after_t af[1]; @@ -3633,12 +3775,9 @@ int respond_with_retry_after(nua_handle_t *nh, nta_incoming_t *irq, af->af_delta = (unsigned)su_randint(min, max); af->af_comment = phrase; - nta_incoming_treply(irq, status, phrase, - SIPTAG_RETRY_AFTER(af), - SIPTAG_USER_AGENT_STR(NH_PGET(nh, user_agent)), - TAG_END()); + sip_add_dup(sr->sr_response.msg, sr->sr_response.sip, (sip_header_t *)af); - return 500; + return sr_status(sr, status, phrase); } /* ======================================================================== */ @@ -3756,146 +3895,6 @@ int session_make_description(su_home_t *home, return retval; } -/** - * Stores and processes SDP from incoming response, then calls - * nua_stack_process_response(). - * - * @retval 1 if there was SDP to process. - */ -static -int session_process_response(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - char const **return_received) -{ - char const *method = nta_outgoing_method_name(orq); - msg_t *msg = nta_outgoing_getresponse(orq); - int retval = 0; - char const *sdp = NULL; - size_t len; - - if (nh->nh_soa == NULL) - /* Xyzzy */; - else if (!session_get_description(sip, &sdp, &len)) - /* No SDP */; - else if (cr->cr_answer_recv) { - /* Ignore spurious answers after completing O/A */ - SU_DEBUG_3(("nua(%p): %s: ignoring duplicate SDP in %u %s\n", - nh, method, - sip->sip_status->st_status, sip->sip_status->st_phrase)); - sdp = NULL; - } - else if (!cr->cr_offer_sent && - nta_outgoing_method(orq) != sip_method_invite) { - /* If non-invite request did not have offer, ignore SDP in response */ - SU_DEBUG_3(("nua(%p): %s: ignoring extra SDP in %u %s\n", - nh, method, - sip->sip_status->st_status, sip->sip_status->st_phrase)); - sdp = NULL; - } - else { - if (cr->cr_offer_sent) { - cr->cr_answer_recv = sip->sip_status->st_status; - *return_received = "answer"; - } - else { - cr->cr_offer_recv = 1, cr->cr_answer_sent = 0; - *return_received = "offer"; - } - - if (soa_set_remote_sdp(nh->nh_soa, NULL, sdp, len) < 0) { - SU_DEBUG_5(("nua(%p): %s: error parsing SDP in %u %s\n", - nh, method, - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - retval = -1; - sdp = NULL; - } - else if (cr->cr_offer_recv) { - /* note: case 1: incoming offer */ - SU_DEBUG_5(("nua(%p): %s: get SDP %s in %u %s\n", - nh, method, "offer", - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - retval = 1; - } - else if (soa_process_answer(nh->nh_soa, NULL) < 0) { - SU_DEBUG_5(("nua(%p): %s: error processing SDP answer in %u %s\n", - nh, method, - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - sdp = NULL; - } - else { - /* note: case 2: answer to our offer */ - if (soa_activate(nh->nh_soa, NULL) < 0) { - SU_DEBUG_3(("nua(%p): %s: error activating media after %u %s\n", - nh, method, - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - /* XXX */ - } - else { - SU_DEBUG_5(("nua(%p): %s: processed SDP answer in %u %s\n", - nh, method, - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - } - - assert(!cr->cr_offer_recv); - } - } - - msg_destroy(msg); /* unref */ - - nua_stack_process_response(nh, cr, orq, sip, - NH_REMOTE_MEDIA_TAGS(sdp != NULL, nh->nh_soa), - TAG_END()); - - return retval; -} - -#if 0 -/** Parse and store SDP from incoming request */ -static -int session_process_request(nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - char const *sdp = NULL; - isize_t len; - - if (nh->nh_soa) { - msg_t *msg = nta_outgoing_getresponse(irq); - - if (session_get_description(msg, sip, &sdp, &len)) { - if (soa_is_complete(nh->nh_soa)) { - /* Ignore spurious answers after completing O/A */ - SU_DEBUG_5(("nua: ignoring duplicate SDP in %u %s\n", - sip->sip_status->st_status, sip->sip_status->st_phrase)); - sdp = NULL; - } - else if (soa_parse_sdp(nh->nh_soa, sdp, len) < 0) { - SU_DEBUG_5(("nua: error parsing SDP in %u %s\n", - sip->sip_status->st_status, - sip->sip_status->st_phrase)); - sdp = NULL; - } - } - - msg_destroy(msg); - } - - return - nua_stack_process_response(nh, cr, orq, sip, - NH_REMOTE_MEDIA_TAGS(sdp != NULL, nh->nh_soa), - TAG_END()); -} -#endif - -static int respond_to_options(nua_server_request_t *sr, tagi_t const *tags); - /** @NUA_EVENT nua_i_options * * Incoming OPTIONS request. The user-agent should respond to an OPTIONS @@ -3924,50 +3923,38 @@ static int respond_to_options(nua_server_request_t *sr, tagi_t const *tags); * @END_NUA_EVENT */ -int nua_stack_process_options(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - nua_server_request_t *sr, sr0[1]; - int done; +int nua_options_server_respond(nua_server_request_t *sr, tagi_t const *tags); - /* Hook to outbound */ - done = nua_registration_process_request(nua->nua_registrations, irq, sip); - if (done) - return done; - - sr = nua_server_request(nua, nh, irq, sip, SR_INIT(sr0), sizeof *sr, - respond_to_options, 0); - - SR_STATUS1(sr, SIP_200_OK); - - return nua_stack_server_event(nua, sr, nua_i_options, TAG_END()); -} +nua_server_methods_t const nua_options_server_methods = + { + SIP_METHOD_OPTIONS, + nua_i_options, /* Event */ + { + 0, /* Do not create dialog */ + 0, /* Initial request */ + 0, /* Not a target refresh request */ + 1, /* Add Contact */ + }, + nua_base_server_init, + nua_base_server_preprocess, + nua_base_server_params, + nua_options_server_respond, + nua_base_server_report, + }; /** @internal Respond to an OPTIONS request. * */ -static int respond_to_options(nua_server_request_t *sr, tagi_t const *tags) +int nua_options_server_respond(nua_server_request_t *sr, tagi_t const *tags) { nua_handle_t *nh = sr->sr_owner; nua_t *nua = nh->nh_nua; - msg_t *msg; - int final; - msg = nua_server_response(sr, - sr->sr_status, sr->sr_phrase, - SIPTAG_ALLOW(NH_PGET(nh, allow)), - SIPTAG_SUPPORTED(NH_PGET(nh, supported)), - TAG_IF(NH_PGET(nh, path_enable), - SIPTAG_SUPPORTED_STR("path")), - SIPTAG_ACCEPT_STR(SDP_MIME_TYPE), - TAG_NEXT(tags)); + if (200 <= sr->sr_status && sr->sr_status < 300) { + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; - final = sr->sr_status >= 200; - - if (msg) { - sip_t *sip = sip_object(msg); + sip_add_tl(msg, sip, SIPTAG_ACCEPT_STR(SDP_MIME_TYPE), TAG_END()); if (!sip->sip_payload) { /* XXX - do MIME multipart? */ soa_session_t *soa = nh->nh_soa; @@ -3977,10 +3964,8 @@ static int respond_to_options(nua_server_request_t *sr, tagi_t const *tags) session_include_description(soa, 0, msg, sip); } - - if (nta_incoming_mreply(sr->sr_irq, msg) < 0) - final = 1; } - return final; + return nua_base_server_respond(sr, tags); } + diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c index 202b90b54c..3d3e994563 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -37,7 +37,7 @@ #include "config.h" #include -#include +#include #include #include #include @@ -51,8 +51,7 @@ #define NTA_AGENT_MAGIC_T struct nua_s #define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s -#define NTA_INCOMING_MAGIC_T struct nua_handle_s +#define NTA_OUTGOING_MAGIC_T struct nua_client_request #include #include @@ -95,6 +94,9 @@ static int nh_challenge(nua_handle_t *nh, sip_t const *sip); static void nua_stack_timer(nua_t *nua, su_timer_t *t, su_timer_arg_t *a); +inline int nua_client_request_queue(nua_client_request_t *cr); +inline nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr); + /* ---------------------------------------------------------------------- */ /* Constant data */ @@ -147,7 +149,7 @@ int nua_stack_init(su_root_t *root, nua_t *nua) return -1; dnh->nh_prefs = (void *)(dnh + 1); - dnh->nh_valid = nua_handle; + dnh->nh_valid = nua_valid_handle_cookie; dnh->nh_nua = nua; nua_handle_ref(dnh); dnh->nh_ref_by_stack = 1; nua_handle_ref(dnh); dnh->nh_ref_by_user = 1; @@ -226,29 +228,40 @@ void int nh_notifier_shutdown(nua_handle_t *nh, nea_event_t *ev, tag_type_t t, tag_value_t v, ...); +int nua_stack_tevent(nua_t *nua, nua_handle_t *nh, msg_t *msg, + nua_event_t event, int status, char const *phrase, + tag_type_t tag, tag_value_t value, ...) +{ + ta_list ta; + int retval; + ta_start(ta, tag, value); + retval = nua_stack_event(nua, nh, msg, event, status, phrase, ta_args(ta)); + ta_end(ta); + return retval; +} + /** @internal Send an event to the application. */ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...) + tagi_t const *tags) { su_msg_r sumsg = SU_MSG_R_INIT; - - ta_list ta; size_t e_len, len, xtra, p_len; if (event == nua_r_ack || event == nua_i_none) return event; - enter; + if (nh == nua->nua_dhandle) + nh = NULL; if (nua_log->log_level >= 5) { char const *name = nua_event_name(event) + 4; char const *p = phrase ? phrase : ""; if (status == 0) - SU_DEBUG_5(("nua(%p): %s %s\n", nh, name, p)); + SU_DEBUG_5(("nua(%p): event %s %s\n", (void *)nh, name, p)); else - SU_DEBUG_5(("nua(%p): %s %u %s\n", nh, name, status, p)); + SU_DEBUG_5(("nua(%p): event %s %u %s\n", (void *)nh, name, status, p)); } if (event == nua_r_destroy) { @@ -269,36 +282,45 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, return event; } - ta_start(ta, tag, value); - - e_len = offsetof(event_t, e_tags); - len = tl_len(ta_args(ta)); - xtra = tl_xtra(ta_args(ta), len); + if (tags) { + e_len = offsetof(event_t, e_tags); + len = tl_len(tags); + xtra = tl_xtra(tags, len); + } + else { + e_len = sizeof(event_t), len = 0, xtra = 0; + } p_len = phrase ? strlen(phrase) + 1 : 1; if (su_msg_create(sumsg, nua->nua_client, su_task_null, nua_event, e_len + len + xtra + p_len) == 0) { event_t *e = su_msg_data(sumsg); + void *p; - tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len); - void *b = t_end, *end = (char *)b + xtra; + if (tags) { + tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len); + void *b = t_end; +#ifndef NDEBUG + void *end = (char *)b + xtra; +#endif - t = tl_dup(t, ta_args(ta), &b); - assert(t == t_end); assert(b == end); + t = tl_dup(t, tags, &b); p = b; + assert(t == t_end); assert(b == end); (void)end; + } + else + p = e + 1; e->e_event = event; e->e_nh = nh ? nua_handle_ref(nh) : nua->nua_dhandle; e->e_status = status; - e->e_phrase = strcpy(end, phrase ? phrase : ""); + e->e_phrase = strcpy(p, phrase ? phrase : ""); if (msg) e->e_msg = msg, su_home_threadsafe(msg_home(msg)); - if (su_msg_send(sumsg) != 0) + if (su_msg_send(sumsg) != 0 && nh) nua_handle_unref(nh); } - ta_end(ta); - return event; } @@ -322,9 +344,16 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) { nua_handle_t *nh = e->e_nh; tagi_t *tags = e->e_tags; + nua_event_t event; + int error = 0; assert(tags); + if (nua_log->log_level >= 7) { + char const *name = nua_event_name(e->e_event) + 4; + SU_DEBUG_7(("nua(%p): recv %s\n", (void *)nh, name)); + } + if (nh) { if (!nh->nh_prev) nh_append(nua, nh); @@ -338,98 +367,105 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e) if (nua_log->log_level >= 5) { char const *name = nua_event_name(e->e_event); if (e->e_status == 0) - SU_DEBUG_5(("nua(%p): signal %s\n", nh, name + 4)); + SU_DEBUG_5(("nua(%p): signal %s\n", (void *)nh, name + 4)); else SU_DEBUG_5(("nua(%p): signal %s %u %s\n", - nh, name + 4, e->e_status, e->e_phrase ? e->e_phrase : "")); + (void *)nh, name + 4, + e->e_status, e->e_phrase ? e->e_phrase : "")); } su_msg_save(nua->nua_signal, msg); + event = e->e_event; + if (nua->nua_shutdown && !e->e_always) { /* Shutting down */ - nua_stack_event(nua, nh, NULL, e->e_event, + nua_stack_event(nua, nh, NULL, event, 901, "Stack is going down", - TAG_END()); + NULL); } - - else switch (e->e_event) { + else switch (event) { case nua_r_get_params: - nua_stack_get_params(nua, nh ? nh : nua->nua_dhandle, e->e_event, tags); + nua_stack_get_params(nua, nh ? nh : nua->nua_dhandle, event, tags); break; case nua_r_set_params: - nua_stack_set_params(nua, nh ? nh : nua->nua_dhandle, e->e_event, tags); + nua_stack_set_params(nua, nh ? nh : nua->nua_dhandle, event, tags); break; case nua_r_shutdown: nua_stack_shutdown(nua); break; case nua_r_register: case nua_r_unregister: - nua_stack_register(nua, nh, e->e_event, tags); + nua_stack_register(nua, nh, event, tags); break; case nua_r_invite: - nua_stack_invite(nua, nh, e->e_event, tags); + error = nua_stack_invite(nua, nh, event, tags); break; case nua_r_cancel: - nua_stack_cancel(nua, nh, e->e_event, tags); + error = nua_stack_cancel(nua, nh, event, tags); break; case nua_r_bye: - nua_stack_bye(nua, nh, e->e_event, tags); + error = nua_stack_bye(nua, nh, event, tags); break; case nua_r_options: - nua_stack_options(nua, nh, e->e_event, tags); + error = nua_stack_options(nua, nh, event, tags); break; case nua_r_refer: - nua_stack_refer(nua, nh, e->e_event, tags); + error = nua_stack_refer(nua, nh, event, tags); break; case nua_r_publish: case nua_r_unpublish: - nua_stack_publish(nua, nh, e->e_event, tags); + error = nua_stack_publish(nua, nh, event, tags); break; case nua_r_info: - nua_stack_info(nua, nh, e->e_event, tags); + error = nua_stack_info(nua, nh, event, tags); break; case nua_r_update: - nua_stack_update(nua, nh, e->e_event, tags); + error = nua_stack_update(nua, nh, event, tags); break; case nua_r_message: - nua_stack_message(nua, nh, e->e_event, tags); + error = nua_stack_message(nua, nh, event, tags); break; case nua_r_subscribe: case nua_r_unsubscribe: - nua_stack_subscribe(nua, nh, e->e_event, tags); + error = nua_stack_subscribe(nua, nh, event, tags); break; case nua_r_notify: - nua_stack_notify(nua, nh, e->e_event, tags); + error = nua_stack_notify(nua, nh, event, tags); break; case nua_r_notifier: - nua_stack_notifier(nua, nh, e->e_event, tags); + nua_stack_notifier(nua, nh, event, tags); break; case nua_r_terminate: - nua_stack_terminate(nua, nh, e->e_event, tags); + nua_stack_terminate(nua, nh, event, tags); break; case nua_r_method: - nua_stack_method(nua, nh, e->e_event, tags); + error = nua_stack_method(nua, nh, event, tags); break; case nua_r_authenticate: - nua_stack_authenticate(nua, nh, e->e_event, tags); + nua_stack_authenticate(nua, nh, event, tags); break; case nua_r_authorize: - nua_stack_authorize(nua, nh, e->e_event, tags); + nua_stack_authorize(nua, nh, event, tags); break; case nua_r_ack: - nua_stack_ack(nua, nh, e->e_event, tags); + error = nua_stack_ack(nua, nh, event, tags); break; case nua_r_respond: nua_stack_respond(nua, nh, e->e_status, e->e_phrase, tags); break; - case nua_r_destroy: + case nua_r_destroy: nua_stack_destroy_handle(nua, nh, tags); - break; + su_msg_destroy(nua->nua_signal); + return; default: break; } + if (error < 0) { + nua_stack_event(nh->nh_nua, nh, NULL, event, NUA_INTERNAL_ERROR, NULL); + } + if (su_msg_is_non_null(nua->nua_signal)) su_msg_destroy(nua->nua_signal); @@ -512,6 +548,7 @@ int nh_call_pending(nua_handle_t *nh, sip_time_t now) } + /* ====================================================================== */ /**Shutdown a @nua stack. @@ -581,15 +618,11 @@ void nua_stack_shutdown(nua_t *nua) for (sr = ds->ds_sr; sr; sr = sr_next) { sr_next = sr->sr_next; - if (sr->sr_respond) { - SR_STATUS1(sr, SIP_410_GONE); - sr->sr_usage = NULL; - sr->sr_respond(sr, NULL); - sr->sr_respond = NULL; - busy++; + if (nua_server_request_is_pending(sr)) { + SR_STATUS1(sr, SIP_410_GONE); /* 410 terminates dialog */ + nua_server_respond(sr, NULL); + nua_server_report(sr); } - - nua_server_request_destroy(sr); } busy += nh_call_pending(nh, 0); @@ -625,7 +658,7 @@ void nua_stack_shutdown(nua_t *nua) nta_agent_destroy(nua->nua_nta), nua->nua_nta = NULL; } - nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, TAG_END()); + nua_stack_event(nua, NULL, NULL, nua_r_shutdown, status, phrase, NULL); } /* ---------------------------------------------------------------------- */ @@ -650,7 +683,7 @@ nua_handle_t *nh_create(nua_t *nua, tag_type_t tag, tag_value_t value, ...) return nh; } -/** @internal Append an handle to the list of handles */ +/** @internal Append a handle to the list of handles */ void nh_append(nua_t *nua, nua_handle_t *nh) { nh->nh_next = NULL; @@ -673,17 +706,15 @@ nua_handle_t *nh_validate(nua_t *nua, nua_handle_t *maybe) void nua_stack_destroy_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags) { - nh_call_pending(nh, 0); /* Call pending operations with 0 */ - if (nh->nh_notifier) nua_stack_terminate(nua, nh, 0, NULL); -#if 0 + nua_dialog_shutdown(nh, nh->nh_ds); + if (nh->nh_ref_by_user) { nh->nh_ref_by_user = 0; nua_handle_unref(nh); } -#endif nh_destroy(nua, nh); } @@ -712,15 +743,17 @@ void nh_destroy(nua_t *nua, nua_handle_t *nh) { assert(nh); assert(nh != nua->nua_dhandle); - nh_enter; - if (nh->nh_notifier) nea_server_destroy(nh->nh_notifier), nh->nh_notifier = NULL; - nua_creq_deinit(nh->nh_ds->ds_cr, NULL); - nua_dialog_deinit(nh, nh->nh_ds); + while (nh->nh_ds->ds_cr) + nua_client_request_destroy(nh->nh_ds->ds_cr); + + while (nh->nh_ds->ds_sr) + nua_server_request_destroy(nh->nh_ds->ds_sr); + if (nh->nh_soa) soa_destroy(nh->nh_soa), nh->nh_soa = NULL; @@ -733,7 +766,7 @@ void nh_destroy(nua_t *nua, nua_handle_t *nh) /* ======================================================================== */ /**@internal - * Initialize handle Allow and authentication info, save parameters. + * Save handle parameters and initial authentication info. * * @retval -1 upon an error * @retval 0 when successful @@ -939,508 +972,6 @@ int nh_challenge(nua_handle_t *nh, sip_t const *sip) return server + proxy; } -#include - -/** Check if tag list has contact */ -int nua_tagis_have_contact_tag(tagi_t const *t) -{ - for (; t && t->t_tag; t = t_next(t)) - if (t->t_tag == siptag_contact || - t->t_tag == siptag_contact_str) - return 1; - return 0; -} - -/**@internal - * Create a request message. - * - * @param nua - * @param nh - * @param cr - * @param restart - * @param method - * @param name - * @param tag, value, ... list of tag-value pairs - */ -msg_t *nua_creq_msg(nua_t *nua, - nua_handle_t *nh, - nua_client_request_t *cr, - int restart, - sip_method_t method, char const *name, - tag_type_t tag, tag_value_t value, ...) -{ - struct nua_dialog_state *ds = nh->nh_ds; - msg_t *msg = NULL; - sip_t *sip; - ta_list ta; - url_string_t const *url = NULL; - long seq = -1; - int copy = 1; - - /* If restarting, use existing message */ - if (restart) { - msg = cr->cr_msg; sip = sip_object(msg); - - /* Trying to restart different method? */ - if (sip && method && sip->sip_request->rq_method != method) { - SU_DEBUG_3(("nua(%p): trying to %s " - "but there is already %s waiting to restart\n", - nh, name, sip->sip_request->rq_method_name)); - restart = 0, msg = NULL; sip = NULL; - } - - /* Remove CSeq */ - if (sip && sip->sip_cseq) - sip_header_remove(msg, sip, (sip_header_t *)sip->sip_cseq); - if (sip && sip->sip_request) - method = sip->sip_request->rq_method, - name = sip->sip_request->rq_method_name; - } - - if (!restart) { - if (cr->cr_msg) { - /* If method is ACK or CANCEL, use existing CSeq */ - if (method == sip_method_ack || method == sip_method_cancel) { - sip_t *nh_sip = sip_object(cr->cr_msg); - if (nh_sip && nh_sip->sip_cseq) - seq = nh_sip->sip_cseq->cs_seq; - /* ACK/CANCEL cannot be restarted so we do not copy message */ - copy = 0; - } - else - msg_destroy(cr->cr_msg), cr->cr_msg = NULL; - } - msg = nta_msg_create(nua->nua_nta, 0); - - /**@par Populating SIP Request Message with Tagged Arguments - * - * The tagged arguments can be used to pass values for any SIP headers - * to the stack. When the INVITE message (or any other SIP message) is - * created, the tagged values saved with nua_handle() are used first, - * next the tagged values given with the operation (nua_invite()) are - * added. - * - * When multiple tags for the same header are specified, the behaviour - * depends on the header type. If only a single header field can be - * included in a SIP message, the latest non-NULL value is used, e.g., - * @Subject. However, if the SIP header can consist of multiple lines or - * header fields separated by comma, e.g., @Accept, all the tagged - * values are concatenated. - * - * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), - * the values from previous tags are ignored. - */ - tl_gets(nh->nh_tags, NUTAG_URL_REF(url), TAG_END()); - sip_add_tl(msg, sip_object(msg), TAG_NEXT(nh->nh_tags)); - } - - ta_start(ta, tag, value); - - sip = sip_object(msg); - if (!sip) - goto error; - if (sip_add_tl(msg, sip, ta_tags(ta)) < 0) - goto error; - - if (method != sip_method_ack) { - /** - * Next, values previously set with nua_set_params() or nua_set_hparams() - * are used: @Allow, @Supported, @Organization, and @UserAgent headers are - * added to the request if they are not already set. - */ - if (!sip->sip_allow && !ds->ds_remote_tag) - sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow)); - - if (!sip->sip_supported && NH_PGET(nh, supported)) - sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)); - - if (method == sip_method_register && NH_PGET(nh, path_enable) && - !sip_has_feature(sip->sip_supported, "path") && - !sip_has_feature(sip->sip_require, "path")) - sip_add_make(msg, sip, sip_supported_class, "path"); - - if (!sip->sip_organization && NH_PGET(nh, organization)) - sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, organization)); - - if (!sip->sip_user_agent && NH_PGET(nh, user_agent)) - sip_add_make(msg, sip, sip_user_agent_class, NH_PGET(nh, user_agent)); - } - - { - int add_contact = 0, use_dialog = 0, add_service_route, has_contact = 0; - tagi_t const *t; - - for (t = ta_args(ta); t; t = t_next(t)) { - if (t->t_tag == siptag_contact || - t->t_tag == siptag_contact_str) - has_contact = 1; - else if (t->t_tag == nutag_url) - url = (url_string_t const *)t->t_value; - else if (t->t_tag == nutag_method && method == sip_method_unknown) - name = (char const *)t->t_value; - else if (t->t_tag == nutag_use_dialog) - use_dialog = t->t_value != 0; - else if (t->t_tag == _nutag_add_contact) - add_contact = t->t_value != 0; - } - - if (!restart) - cr->cr_has_contact = has_contact; - - if (has_contact) add_contact = 0; - - if (method == sip_method_register && url == NULL) - url = (url_string_t const *)NH_PGET(nh, registrar); - - if (seq != -1) { - sip_cseq_t *cseq; - - assert(method != sip_method_unknown || name || sip->sip_request); - - if (method || name) - cseq = sip_cseq_create(msg_home(msg), seq, method, name); - else - cseq = sip_cseq_create(msg_home(msg), seq, - sip->sip_request->rq_method, - sip->sip_request->rq_method_name); - - sip_header_insert(msg, sip, (sip_header_t *)cseq); - } - - /** - * Now, the target URI for the request needs to be determined. - * - * For initial requests, values from tags are used. If NUTAG_URL() is - * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, - * it is used as target URI. If neither is given, the complete request - * line already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() - * is used. At this point, the target URI is stored in the request line, - * together with method name and protocol version ("SIP/2.0"). The - * initial dialog information is also created: @CallID, @CSeq headers - * are generated, if they do not exist, and a tag is added to the @From - * header. - */ - if (!ds->ds_leg) { - nta_leg_t *leg = nua->nua_dhandle->nh_ds->ds_leg; - - if ((ds->ds_remote_tag && ds->ds_remote_tag[0] && - sip_to_tag(nh->nh_home, sip->sip_to, ds->ds_remote_tag) < 0) - || - (sip->sip_from == NULL && - sip_add_dup(msg, sip, (sip_header_t *)nua->nua_from) < 0)) - goto error; - - if (use_dialog) { - ds->ds_leg = nta_leg_tcreate(nua->nua_nta, - nua_stack_process_request, nh, - SIPTAG_CALL_ID(sip->sip_call_id), - SIPTAG_FROM(sip->sip_from), - SIPTAG_TO(sip->sip_to), - SIPTAG_CSEQ(sip->sip_cseq), - TAG_END()); - if (!ds->ds_leg) - goto error; - - leg = ds->ds_leg; - - if (!sip->sip_from->a_tag && - sip_from_tag(msg_home(msg), sip->sip_from, - nta_leg_tag(ds->ds_leg, NULL)) < 0) - goto error; - } - - if (nta_msg_request_complete(msg, leg, method, name, url) < 0) - goto error; - - add_service_route = !restart; - } - else { - /** - * For in-dialog requests, the request URI is taken from the @Contact - * header received from the remote party during dialog establishment, - * and the NUTAG_URL() is ignored. - */ - if (ds->ds_route) - url = NULL; - - /**Also, the @CallID and @CSeq headers and @From and @To tags are - * generated based on the dialog information and added to the request. - * If the dialog has a route, it is added to the request, too. - */ - if (nta_msg_request_complete(msg, ds->ds_leg, method, name, url) < 0) - goto error; - add_service_route = 0; - } - /*** - * @MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is - * also added now, if it does not exist. - */ - - /** - * Next, the stack generates a @Contact header for the request (unless - * the application already gave a @Contact header or it does not want to - * use @Contact and indicates that by including SIPTAG_CONTACT(NULL) or - * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the - * application has registered the URI in @From header, the @Contact - * header used with registration is used. Otherwise, the @Contact header - * is generated from the local IP address and port number. - */ - if (!add_contact || - sip->sip_contact || - nua_tagis_have_contact_tag(nh->nh_tags) || - nua_tagis_have_contact_tag(ta_args(ta))) - add_contact = 0; - - /**For the initial requests, @ServiceRoute set received from the registrar - * is also added to the request message. - */ - if (add_contact || add_service_route) { - if (nua_registration_add_contact_to_request(nh, msg, sip, - add_contact, - add_service_route) < 0) - goto error; - } - - if (method != sip_method_ack) { - if (nh->nh_auth) { - nh_authorize(nh, ta_tags(ta)); - - if (method != sip_method_invite && - method != sip_method_update && - method != sip_method_prack && - /* auc_authorize() removes existing authentication headers */ - auc_authorize(&nh->nh_auth, msg, sip) < 0) - goto error; - } - } - else /* ACK */ { - while (sip->sip_allow) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_allow); - while (sip->sip_priority) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_priority); - while (sip->sip_proxy_require) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_proxy_require); - while (sip->sip_require) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_require); - while (sip->sip_subject) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_subject); - while (sip->sip_supported) - sip_header_remove(msg, sip, (sip_header_t*)sip->sip_supported); - } - - ta_end(ta); - - if (!ds->ds_remote) - ds->ds_remote = sip_to_dup(nh->nh_home, sip->sip_to); - if (!ds->ds_local) - ds->ds_local = sip_from_dup(nh->nh_home, sip->sip_from); - - if (copy) { - cr->cr_msg = msg; - msg = msg_copy(msg); - } - } - - return msg; - - error: - ta_end(ta); - msg_destroy(msg); - return NULL; -} - -/* ---------------------------------------------------------------------- */ -nua_client_request_t * -nua_client_request_pending(nua_client_request_t const *cr) -{ - for (;cr;cr = cr->cr_next) - if (cr->cr_orq) - return (nua_client_request_t *)cr; - - return NULL; -} - -nua_client_request_t * -nua_client_request_restarting(nua_client_request_t const *cr) -{ - for (;cr;cr = cr->cr_next) - if (cr->cr_restart) - return (nua_client_request_t *)cr; - - return NULL; -} - -nua_client_request_t * -nua_client_request_by_orq(nua_client_request_t const *cr, - nta_outgoing_t const *orq) -{ - for (;cr;cr = cr->cr_next) - if (cr->cr_orq == orq) - return (nua_client_request_t *)cr; - - return NULL; -} - -void nua_creq_deinit(nua_client_request_t *cr, nta_outgoing_t *orq) -{ - if (orq == NULL || orq == cr->cr_orq) { - cr->cr_retry_count = 0; - cr->cr_offer_sent = cr->cr_answer_recv = 0; - - if (cr->cr_msg) - msg_destroy(cr->cr_msg); - cr->cr_msg = NULL; - - if (cr->cr_orq) - nta_outgoing_destroy(cr->cr_orq); - cr->cr_orq = NULL; - } - else { - nta_outgoing_destroy(orq); - } -} - - -/**@internal - * Get remote contact header for @a irq */ -static inline -sip_contact_t const *incoming_contact(nta_incoming_t *irq) -{ - sip_contact_t const *retval = NULL; - msg_t *request; - sip_t *sip; - - request = nta_incoming_getrequest(irq); - sip = sip_object(request); - if (sip) - retval = sip->sip_contact; - msg_destroy(request); - - return retval; -} - -/**@internal - * Create a response message. - */ -msg_t *nh_make_response(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...) -{ - ta_list ta; - msg_t *msg = nta_msg_create(nua->nua_nta, 0); - sip_t *sip = sip_object(msg); - msg_t *retval = NULL; - tagi_t const *t; - - ta_start(ta, tag, value); - - if (!msg) - /* retval is NULL */; - else if (nta_msg_response_complete(msg, irq, status, phrase) < 0) - msg_destroy(msg); - else if (sip_add_tl(msg, sip, ta_tags(ta)) < 0) - msg_destroy(msg); - else if (sip_complete_message(msg) < 0) - msg_destroy(msg); - else if (!sip->sip_supported && NH_PGET(nh, supported) && - sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)) < 0) - msg_destroy(msg); - else if (!sip->sip_user_agent && NH_PGET(nh, user_agent) && - sip_add_make(msg, sip, sip_user_agent_class, - NH_PGET(nh, user_agent)) < 0) - msg_destroy(msg); - else if (!sip->sip_organization && NH_PGET(nh, organization) && - sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, organization)) < 0) - msg_destroy(msg); - else if (!sip->sip_allow && NH_PGET(nh, allow) && - sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow)) < 0) - msg_destroy(msg); - else if (!sip->sip_allow_events && - (sip->sip_cseq && - (sip->sip_cseq->cs_method == sip_method_publish || - sip->sip_cseq->cs_method == sip_method_subscribe)) && - NH_PGET(nh, allow_events) && - sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow_events)) < 0) - msg_destroy(msg); - else if (!sip->sip_contact && - (t = tl_find(ta_args(ta), _nutag_add_contact)) && - t->t_value && - nua_registration_add_contact_to_response(nh, msg, sip, NULL, - incoming_contact(irq)) < 0) - msg_destroy(msg); - else - retval = msg; - - ta_end(ta); - - return retval; -} - - -/* ======================================================================== */ -/* Generic processing */ - -int nua_stack_process_unknown(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) -{ - return 501; -} - -/**@internal - * Relay response message to the application. - * - * If handle has already been marked as destroyed by nua_handle_destroy(), - * release the handle with nh_destroy(). - */ -int nua_stack_process_response(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - tag_type_t tag, tag_value_t value, ...) -{ - msg_t *msg = nta_outgoing_getresponse(orq); - int status = sip->sip_status->st_status; - char const *phrase = sip->sip_status->st_phrase; - ta_list ta; - int final; - - if (status >= 200 && status < 300) - nh_challenge(nh, sip); /* Collect nextnonce */ - - if (nta_outgoing_method(orq) == sip_method_invite) - final = status >= 300; - else - final = status >= 200; - - if (final && cr) { - nua_creq_deinit(cr, orq); - - if (cr->cr_usage && nh->nh_ds->ds_cr == cr) { - if ((status >= 300 && !cr->cr_usage->du_ready) || - cr->cr_usage->du_terminating) - nua_dialog_usage_remove(nh, nh->nh_ds, cr->cr_usage); - } - - cr->cr_usage = NULL; - } - - ta_start(ta, tag, value); - - nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, status, phrase, - ta_tags(ta)); - - if (final) - cr->cr_event = nua_i_error; - - ta_end(ta); - - return 0; -} - static inline int can_redirect(sip_contact_t const *m, sip_method_t method) { @@ -1457,184 +988,6 @@ int can_redirect(sip_contact_t const *m, sip_method_t method) return 0; } -int nua_creq_restart_with(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - int status, char const *phrase, - nua_creq_restart_f *f, - TAG_LIST) -{ - ta_list ta; - msg_t *msg = nta_outgoing_getresponse(orq); - - nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, status, phrase, - TAG_END()); - - nta_outgoing_destroy(orq); - - if (f) { - ta_start(ta, tag, value); - f(nh, ta_args(ta)); - ta_end(ta); - } - - return 1; -} - - -/** @internal Save operation until it can be restarted */ -int nua_creq_save_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - int status, char const *phrase, - nua_creq_restart_f *restart_function) -{ - nua_dialog_usage_t *du = cr->cr_usage; - msg_t *msg = nta_outgoing_getresponse(orq); - - nua_stack_event(nh->nh_nua, nh, msg, cr->cr_event, - status, phrase, - TAG_END()); - nta_outgoing_destroy(orq); - - if (du) - du->du_refresh = 0; - - cr->cr_restart = restart_function; - return 1; -} - - -/**@internal - * Check response, return true if we can restart the request. - * - */ -int nua_creq_check_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - nua_creq_restart_f *restart_function) -{ - int status = sip->sip_status->st_status; - sip_method_t method = nta_outgoing_method(orq); - - nua_dialog_usage_t *du = cr->cr_usage; - - assert(restart_function); - - if (orq != cr->cr_orq) - return 0; - - cr->cr_orq = NULL; - cr->cr_restart = NULL; - - if (cr->cr_msg == NULL || status < 200) - ; - else if (++cr->cr_retry_count > NH_PGET(nh, retry_count)) - ; - else if (status == 302) { - if (can_redirect(sip->sip_contact, method)) { - return - nua_creq_restart_with(nh, cr, orq, 100, "Redirected", - restart_function, - NUTAG_URL(sip->sip_contact->m_url), - TAG_END()); - } - } - else if (status == 423) { - sip_t *req = sip_object(cr->cr_msg); - unsigned my_expires = 0; - - if (req->sip_expires) - my_expires = req->sip_expires->ex_delta; - - if (sip->sip_min_expires && - sip->sip_min_expires->me_delta > my_expires) { - sip_expires_t ex[1]; - sip_expires_init(ex); - ex->ex_delta = sip->sip_min_expires->me_delta; - - return - nua_creq_restart_with(nh, cr, orq, - 100, "Re-Negotiating Expiration", - restart_function, - SIPTAG_EXPIRES(ex), - TAG_END()); - } - } - else if (method != sip_method_ack && method != sip_method_cancel && - ((status == 401 && sip->sip_www_authenticate) || - (status == 407 && sip->sip_proxy_authenticate)) && - nh_challenge(nh, sip) > 0) { - msg_t *request = nta_outgoing_getrequest(orq); - sip_t *rsip = sip_object(request); - int done; - - /* XXX - check for instant restart */ - done = auc_authorization(&nh->nh_auth, cr->cr_msg, (msg_pub_t*)NULL, - rsip->sip_request->rq_method_name, - rsip->sip_request->rq_url, - rsip->sip_payload); - - msg_destroy(request); - - if (done > 0) { - return - nua_creq_restart_with(nh, cr, orq, - 100, "Request Authorized by Cache", - restart_function, TAG_END()); - } - else if (done == 0) { - /* Operation waits for application to call nua_authenticate() */ - return nua_creq_save_restart(nh, cr, orq, - status, sip->sip_status->st_phrase, - restart_function); - } - else { - SU_DEBUG_5(("nua(%p): auc_authorization failed\n", nh)); - } - } - - /* This was final response that cannot be restarted. */ - cr->cr_orq = orq; - - if (du) - du->du_refresh = 0; - cr->cr_retry_count = 0; - - if (cr->cr_msg) - msg_destroy(cr->cr_msg), cr->cr_msg = NULL; - - return 0; -} - -/** @internal Restart a request */ -int nua_creq_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_response_f *cb, - tagi_t *tags) -{ - msg_t *msg; - - cr->cr_restart = NULL; - - if (!cr->cr_msg) - return 0; - - msg = nua_creq_msg(nh->nh_nua, nh, cr, 1, SIP_METHOD_UNKNOWN, - TAG_NEXT(tags)); - - cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta, cb, nh, NULL, msg, - SIPTAG_END(), TAG_NEXT(tags)); - - if (!cr->cr_orq) { - msg_destroy(msg); - return 0; - } - - return 1; -} - /* ======================================================================== */ /* Authentication */ @@ -1674,37 +1027,52 @@ nua_stack_authenticate(nua_t *nua, nua_handle_t *nh, nua_event_t e, int status = nh_authorize(nh, TAG_NEXT(tags)); if (status > 0) { - nua_client_request_t *cr; - nua_creq_restart_f *restart = NULL; + nua_client_request_t *cr = nh->nh_ds->ds_cr; - cr = nua_client_request_restarting(nh->nh_ds->ds_cr); - - if (cr) - restart = cr->cr_restart, cr->cr_restart = NULL; - - if (restart) { - /* nua_stack_event(nua, nh, NULL, e, SIP_200_OK, TAG_END()); */ - restart(nh, (tagi_t *)tags); /* Restart operation */ + if (cr && cr->cr_challenged) { + nua_client_resend_request(cr, cr->cr_terminating, tags); } else { nua_stack_event(nua, nh, NULL, e, 202, "No operation to restart", - TAG_END()); + NULL); } } else if (status < 0) { - nua_stack_event(nua, nh, NULL, e, 900, "Cannot add credentials", TAG_END()); + nua_stack_event(nua, nh, NULL, e, 900, "Cannot add credentials", NULL); } else { - nua_stack_event(nua, nh, NULL, e, 904, "No matching challenge", TAG_END()); + nua_stack_event(nua, nh, NULL, e, 904, "No matching challenge", NULL); } } + /* ======================================================================== */ /* * Process incoming requests */ +nua_server_methods_t const *nua_server_methods[] = { + /* These must be in same order as in sip_method_t */ + &nua_extension_server_methods, + &nua_invite_server_methods, /**< INVITE */ + NULL, /**< ACK */ + NULL, /**< CANCEL */ + &nua_bye_server_methods, /**< BYE */ + &nua_options_server_methods, /**< OPTIONS */ + &nua_register_server_methods, /**< REGISTER */ + &nua_info_server_methods, /**< INFO */ + &nua_prack_server_methods, /**< PRACK */ + &nua_update_server_methods, /**< UPDATE */ + &nua_message_server_methods, /**< MESSAGE */ + &nua_subscribe_server_methods,/**< SUBSCRIBE */ + &nua_notify_server_methods, /**< NOTIFY */ + &nua_refer_server_methods, /**< REFER */ + &nua_publish_server_methods, /**< PUBLISH */ + NULL +}; + + int nua_stack_process_request(nua_handle_t *nh, nta_leg_t *leg, nta_incoming_t *irq, @@ -1712,13 +1080,27 @@ int nua_stack_process_request(nua_handle_t *nh, { nua_t *nua = nh->nh_nua; sip_method_t method = sip->sip_request->rq_method; + char const *name = sip->sip_request->rq_method_name; + nua_server_methods_t const *sm; + nua_server_request_t *sr, sr0[1]; + int status, initial = 1; + char const *user_agent = NH_PGET(nh, user_agent); sip_supported_t const *supported = NH_PGET(nh, supported); sip_allow_t const *allow = NH_PGET(nh, allow); + enter; nta_incoming_tag(irq, NULL); + /* Hook to outbound */ + if (method == sip_method_options) { + status = nua_registration_process_request(nua->nua_registrations, + irq, sip); + if (status) + return status; + } + if (nta_check_method(irq, sip, allow, SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), @@ -1733,11 +1115,12 @@ int nua_stack_process_request(nua_handle_t *nh, case url_tel: break; default: - nta_incoming_treply(irq, SIP_416_UNSUPPORTED_URI, + nta_incoming_treply(irq, status = SIP_416_UNSUPPORTED_URI, SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), TAG_END()); + return status; } if (nta_check_required(irq, sip, supported, @@ -1746,131 +1129,110 @@ int nua_stack_process_request(nua_handle_t *nh, TAG_END())) return 420; - if (nh == nua->nua_dhandle) { - if (!sip->sip_to->a_tag) - ; - else if (method == sip_method_message && NH_PGET(nh, win_messenger_enable)) - ; - else { - nta_incoming_treply(irq, 481, "Initial transaction with a To tag", - TAG_END()); - return 481; - } - nh = NULL; + if (method > sip_method_unknown && method <= sip_method_publish) + sm = nua_server_methods[method]; + else + sm = nua_server_methods[0]; + + initial = nh == nua->nua_dhandle; + + if (sm == NULL) { + SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n", + (void *)nh, sip->sip_request->rq_method_name, + URL_PRINT_ARGS(sip->sip_from->a_url))); + } + else if (initial && sm->sm_flags.in_dialog) { + /* These must be in-dialog */ + sm = NULL; + } + else if (initial && sip->sip_to->a_tag) { + /* RFC 3261 section 12.2.2: + + If the UAS wishes to reject the request because it does not wish to + recreate the dialog, it MUST respond to the request with a 481 + (Call/Transaction Does Not Exist) status code and pass that to the + server transaction. + */ + if (method != sip_method_message || !NH_PGET(nh, win_messenger_enable)) + sm = NULL; } - if (sip->sip_timestamp) - nta_incoming_treply(irq, SIP_100_TRYING, TAG_END()); - - switch (method) { - case sip_method_invite: - return nua_stack_process_invite(nua, nh, irq, sip); - - case sip_method_info: - if (nh) return nua_stack_process_info(nua, nh, irq, sip); - /*FALLTHROUGH*/ - - case sip_method_update: - if (nh) return nua_stack_process_update(nua, nh, irq, sip); - /*FALLTHROUGH*/ - - case sip_method_bye: - if (nh) return nua_stack_process_bye(nua, nh, irq, sip); - + if (!sm) { nta_incoming_treply(irq, - 481, "Call Does Not Exist", + status = 481, "Call Does Not Exist", SIPTAG_ALLOW(allow), SIPTAG_SUPPORTED(supported), SIPTAG_USER_AGENT_STR(user_agent), TAG_END()); return 481; - - case sip_method_message: - return nua_stack_process_message(nua, nh, irq, sip); - - case sip_method_notify: - return nua_stack_process_notify(nua, nh, irq, sip); - - case sip_method_subscribe: - return nua_stack_process_subscribe(nua, nh, irq, sip); - - case sip_method_register: - return nua_stack_process_register(nua, nh, irq, sip); - - case sip_method_options: - return nua_stack_process_options(nua, nh, irq, sip); - - case sip_method_refer: - return nua_stack_process_refer(nua, nh, irq, sip); - - case sip_method_publish: - return nua_stack_process_publish(nua, nh, irq, sip); - - case sip_method_ack: - case sip_method_cancel: - SU_DEBUG_1(("nua(%p): strange %s from <" URL_PRINT_FORMAT ">\n", nh, - sip->sip_request->rq_method_name, - URL_PRINT_ARGS(sip->sip_from->a_url))); - /* Send nua_i_error ? */ - return 481; - - case sip_method_unknown: - return nua_stack_process_method(nua, nh, irq, sip); - - default: - return nua_stack_process_unknown(nua, nh, irq, sip); } -} -nua_server_request_t *nua_server_request(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip, - nua_server_request_t *sr, - size_t size, - nua_server_respond_f *respond, - int create_dialog) -{ - int initial = 1, final = 200; + sr = memset(sr0, 0, (sizeof sr0)); - assert(nua && irq && sip && sr); + sr->sr_methods = sm; + sr->sr_method = method = sip->sip_request->rq_method; + sr->sr_add_contact = sm->sm_flags.add_contact; - initial = nh == NULL || nh == nua->nua_dhandle; + sr->sr_owner = nh; + sr->sr_initial = initial; - /* INVITE server request is not finalized after 2XX response */ - if (sip->sip_request->rq_method == sip_method_invite) - final = 300; + sr->sr_irq = irq; - /* Create handle if request does not fail */ - if (sr->sr_status >= 300) - ; - else if (initial) { - if (!(nh = nua_stack_incoming_handle(nua, irq, sip, create_dialog))) + SR_STATUS1(sr, SIP_100_TRYING); + + sr->sr_request.msg = nta_incoming_getrequest(irq); + sr->sr_request.sip = sip; + assert(sr->sr_request.msg); + + sr->sr_response.msg = nta_incoming_create_response(irq, 0, NULL); + sr->sr_response.sip = sip_object(sr->sr_response.msg); + + if (sr->sr_response.msg == NULL) { + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + } + else if (sm->sm_init && sm->sm_init(sr)) { + if (sr->sr_status < 200) /* Init may have set response status */ SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } - else if (create_dialog) { - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); + /* Create handle if request does not fail */ + else if (initial && sr->sr_status < 300) { + if ((nh = nua_stack_incoming_handle(nua, irq, sip, create_dialog))) + sr->sr_owner = nh; + else + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } - if (nh == NULL) - nh = nua->nua_dhandle; + if (sr->sr_status < 300 && sm->sm_preprocess && sm->sm_preprocess(sr)) { + if (sr->sr_status < 200) /* Preprocess may have set response status */ + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + } - if (sr->sr_status < final) { - nua_server_request_t *sr0 = sr; + if (sr->sr_status < 300) { + if (sm->sm_flags.target_refresh) + nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); /* Set route and tags */ + nua_dialog_store_peer_info(nh, nh->nh_ds, sip); + } - if (size < (sizeof *sr)) - size = sizeof *sr; + if (sr->sr_status == 100 && method != sip_method_unknown && + !sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), method, name)) { + if (method == sip_method_refer || method == sip_method_subscribe) + SR_STATUS1(sr, SIP_202_ACCEPTED); + else + SR_STATUS1(sr, SIP_200_OK); + } - sr = su_zalloc(nh->nh_home, size); + /* INVITE server request is not finalized after 2XX response */ + if (sr->sr_status < (method == sip_method_invite ? 300 : 200)) { + sr = su_alloc(nh->nh_home, (sizeof *sr)); if (sr) { + *sr = *sr0; + if ((sr->sr_next = nh->nh_ds->ds_sr)) *(sr->sr_prev = sr->sr_next->sr_prev) = sr, sr->sr_next->sr_prev = &sr->sr_next; else *(sr->sr_prev = &nh->nh_ds->ds_sr) = sr; - SR_STATUS(sr, sr0->sr_status, sr0->sr_phrase); } else { sr = sr0; @@ -1878,148 +1240,61 @@ nua_server_request_t *nua_server_request(nua_t *nua, } } - sr->sr_owner = nh; - sr->sr_method = sip->sip_request->rq_method; - sr->sr_respond = respond; - sr->sr_irq = irq; - sr->sr_initial = initial; + if (sr->sr_status <= 100) { + SR_STATUS1(sr, SIP_100_TRYING); + if (method == sip_method_invite || sip->sip_timestamp) { + nta_incoming_treply(irq, SIP_100_TRYING, + SIPTAG_USER_AGENT_STR(user_agent), + TAG_END()); + } + } + else { + /* Note that this may change the sr->sr_status */ + nua_server_respond(sr, NULL); + } - return sr; + if (nua_server_report(sr) == 0) + return 0; + + return 501; } +#undef nua_base_server_init +#undef nua_base_server_preprocess + +int nua_base_server_init(nua_server_request_t *sr) +{ + return 0; +} + +int nua_base_server_preprocess(nua_server_request_t *sr) +{ + return 0; +} + void nua_server_request_destroy(nua_server_request_t *sr) { + if (sr == NULL) + return; + if (sr->sr_irq) nta_incoming_destroy(sr->sr_irq), sr->sr_irq = NULL; - sr->sr_msg = NULL; + if (sr->sr_request.msg) + msg_destroy(sr->sr_request.msg), sr->sr_request.msg = NULL; + + if (sr->sr_response.msg) + msg_destroy(sr->sr_response.msg), sr->sr_response.msg = NULL; if (sr->sr_prev) { + /* Allocated from heap */ if ((*sr->sr_prev = sr->sr_next)) sr->sr_next->sr_prev = sr->sr_prev; - - if (sr->sr_owner) - su_free(sr->sr_owner->nh_home, sr); + su_free(sr->sr_owner->nh_home, sr); } } -/** Send server event (nua_i_*) to the application. */ -int nua_stack_server_event(nua_t *nua, - nua_server_request_t *sr, - nua_event_t event, - tag_type_t tag, tag_value_t value, ...) -{ - nua_handle_t *nh = sr->sr_owner; - int status, final = 0; - - if (nh == NULL) nh = nua->nua_dhandle; - - if (sr->sr_status > 100) - /* Note that this may change the sr->sr_status */ - final = sr->sr_respond(sr, NULL); - - status = sr->sr_status; - - if (status >= 200) - sr->sr_respond = NULL; - - if (status < 300 || !sr->sr_initial) { - ta_list ta; - msg_t *request; - - ta_start(ta, tag, value); - - assert(sr->sr_owner); - request = nta_incoming_getrequest(sr->sr_irq); - nua_stack_event(nua, sr->sr_owner, request, event, - sr->sr_status, sr->sr_phrase, - ta_tags(ta)); - ta_end(ta); - - if (final) - nua_server_request_destroy(sr); - else if (sr->sr_status < 200) - sr->sr_msg = request; - } - else { - nh = sr->sr_owner; - - nua_server_request_destroy(sr); - - if (nh && nh != nua->nua_dhandle) - nh_destroy(nua, nh); - } - - return 0; -} - -/** Respond to a request. */ -int nua_server_respond(nua_server_request_t *sr, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...) -{ - ta_list ta; - int final; - - assert(sr && sr->sr_respond); - SR_STATUS(sr, status, phrase); - - ta_start(ta, tag, value); - final = sr->sr_respond(sr, ta_args(ta)); - ta_end(ta); - - if (final) { - nua_server_request_destroy(sr); - return final; - } - - if (sr->sr_status >= 200) - sr->sr_respond = NULL; - - return 0; -} - -msg_t *nua_server_response(nua_server_request_t *sr, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...) -{ - msg_t *msg; - ta_list(ta); - - assert(sr && sr->sr_owner && sr->sr_owner->nh_nua); - - ta_start(ta, tag, value); - - msg = nh_make_response(sr->sr_owner->nh_nua, sr->sr_owner, sr->sr_irq, - sr->sr_status, sr->sr_phrase, - ta_tags(ta)); - - ta_end(ta); - - return msg; -} - -int nua_default_respond(nua_server_request_t *sr, - tagi_t const *tags) -{ - msg_t *m; - - assert(sr && sr->sr_owner && sr->sr_owner->nh_nua); - - m = nh_make_response(sr->sr_owner->nh_nua, sr->sr_owner, - sr->sr_irq, - sr->sr_status, sr->sr_phrase, - TAG_NEXT(tags)); - - if (m) { - if (nta_incoming_mreply(sr->sr_irq, m) < 0) - SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); - } - - return sr->sr_status >= 200 ? sr->sr_status : 0; -} - -/** Respond to an request with given status. +/** Respond to a request with given status. * * When nua protocol engine receives an incoming SIP request, it can either * respond to the request automatically or let it up to application to @@ -2085,29 +1360,1294 @@ nua_stack_respond(nua_t *nua, nua_handle_t *nh, request = (msg_t const *)t->t_value; for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next) { - if (request && sr->sr_msg == request) + if (request && sr->sr_request.msg == request) break; /* nua_respond() to INVITE can be used without NUTAG_WITH() */ - if (!t && sr->sr_method == sip_method_invite && sr->sr_respond) + if (!t && sr->sr_method == sip_method_invite) break; } - - if (sr && sr->sr_respond) { - int final; - SR_STATUS(sr, status, phrase); - final = sr->sr_respond(sr, tags); - if (final) - nua_server_request_destroy(sr); - else if (sr->sr_status >= 200) - sr->sr_respond = NULL; - return; - } - else if (sr) { + + if (sr == NULL) { nua_stack_event(nua, nh, NULL, nua_i_error, - 500, "Already Sent Final Response", TAG_END()); - return; + 500, "Responding to a Non-Existing Request", NULL); + } + else if (!nua_server_request_is_pending(sr)) { + nua_stack_event(nua, nh, NULL, nua_i_error, + 500, "Already Sent Final Response", NULL); + } + else { + sr->sr_application = status; + + if (tags && nua_stack_set_params(nua, nh, nua_i_none, tags) < 0) + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + else + sr->sr_status = status, sr->sr_phrase = phrase; + + nua_server_params(sr, tags); + nua_server_respond(sr, tags); + nua_server_report(sr); + } +} + +int nua_server_params(nua_server_request_t *sr, tagi_t const *tags) +{ + if (sr->sr_methods->sm_params) + return sr->sr_methods->sm_params(sr, tags); + return 0; +} + +#undef nua_base_server_params + +int nua_base_server_params(nua_server_request_t *sr, tagi_t const *tags) +{ + return 0; +} + +/** Return the response to the client. + * + * @retval 0 when successfully sent + * @retval -1 upon an error + */ +int nua_server_trespond(nua_server_request_t *sr, + tag_type_t tag, tag_value_t value, ...) +{ + int retval; + ta_list ta; + ta_start(ta, tag, value); + retval = nua_server_respond(sr, ta_args(ta)); + ta_end(ta); + return retval; +} + +/** Return the response to the client. + * + * @retval 0 when successfully sent + * @retval -1 upon an error + */ +int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + sip_method_t method = sr->sr_method; + struct { msg_t *msg; sip_t *sip; } next = { NULL, NULL }; + tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }}; + int retval; + + msg_t *msg = sr->sr_response.msg; + sip_t *sip = sr->sr_response.sip; + sip_contact_t *m = sr->sr_request.sip->sip_contact; + + if (sr->sr_response.msg == NULL) { + assert(sr->sr_status == 500); + goto internal_error; } - nua_stack_event(nua, nh, NULL, nua_i_error, - 500, "Responding to a Non-Existing Request", TAG_END()); + if (sr->sr_status < 200) { + next.msg = nta_incoming_create_response(sr->sr_irq, 0, NULL); + next.sip = sip_object(next.msg); + if (next.sip == NULL) + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + } + + if (nta_incoming_complete_response(sr->sr_irq, msg, + sr->sr_status, + sr->sr_phrase, + TAG_NEXT(tags)) < 0) + ; + else if (!sip->sip_supported && NH_PGET(nh, supported) && + sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)) < 0) + ; + else if (!sip->sip_user_agent && NH_PGET(nh, user_agent) && + sip_add_make(msg, sip, sip_user_agent_class, + NH_PGET(nh, user_agent)) < 0) + ; + else if (!sip->sip_organization && NH_PGET(nh, organization) && + sip_add_dup(msg, sip, (void *)NH_PGET(nh, organization)) < 0) + ; + else if (!sip->sip_allow && NH_PGET(nh, allow) && + sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow)) < 0) + ; + else if (!sip->sip_allow_events && + (method == sip_method_publish || method == sip_method_subscribe) && + NH_PGET(nh, allow_events) && + sip_add_dup(msg, sip, (void *)NH_PGET(nh, allow_events)) < 0) + ; + else if (!sip->sip_contact && sr->sr_status < 300 && sr->sr_add_contact && + nua_registration_add_contact_to_response(nh, msg, sip, NULL, m) < 0) + ; + else { + int term; + + term = sip_response_terminates_dialog(sr->sr_status, sr->sr_method, NULL); + + sr->sr_terminating = (term < 0) ? -1 : (term > 0 || sr->sr_terminating); + + retval = sr->sr_methods->sm_respond(sr, next_tags); + + if (sr->sr_status < 200) + sr->sr_response.msg = next.msg, sr->sr_response.sip = next.sip; + else if (next.msg) + msg_destroy(next.msg); + + return retval; + } + + if (next.msg) + msg_destroy(next.msg); + + SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); + + msg_destroy(msg); + + internal_error: + sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; + nta_incoming_treply(sr->sr_irq, sr->sr_status, sr->sr_phrase, TAG_END()); + + return 0; +} + +/** Return the response to the client. + * + * @retval 0 when successfully sent + * @retval -1 upon an error + */ +int nua_base_server_respond(nua_server_request_t *sr, tagi_t const *tags) +{ + msg_t *response = sr->sr_response.msg; + + sr->sr_response.msg = NULL, sr->sr_response.sip = NULL; + + return nta_incoming_mreply(sr->sr_irq, response); +} + +int nua_server_report(nua_server_request_t *sr) +{ + if (sr) + return sr->sr_methods->sm_report(sr, NULL); + else + return 2; +} + +int nua_base_server_treport(nua_server_request_t *sr, + tag_type_t tag, tag_value_t value, + ...) +{ + int retval; + ta_list ta; + ta_start(ta, tag, value); + retval = nua_base_server_report(sr, ta_args(ta)); + ta_end(ta); + return retval; +} + +/**Report request event to the application. + * + * @retval 0 request lives + * @retval 1 request was destroyed + * @retval 2 request and its usage was destroyed + * @retval 3 request, all usages and dialog was destroyed + * @retval 4 request, all usages, dialog, and handle was destroyed + */ +int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_t *nua = nh->nh_nua; + nua_dialog_usage_t *usage = sr->sr_usage; + int initial = sr->sr_initial; + int status = sr->sr_status; + char const *phrase = sr->sr_phrase; + + int terminated; + int handle_can_be_terminated = initial && !sr->sr_event; + + assert(nh); + + if (sr->sr_application) { + /* There was an error sending response */ + if (sr->sr_application != sr->sr_status) + nua_stack_event(nua, nh, NULL, nua_i_error, status, phrase, tags); + sr->sr_application = 0; + } + else if (status < 300 && !sr->sr_event) { + msg_t *msg = msg_ref_create(sr->sr_request.msg); + nua_event_t e = sr->sr_methods->sm_event; + sr->sr_event = 1; + nua_stack_event(nua, nh, msg, e, status, phrase, tags); + } + + if (status < 200) + return 0; /* sr lives on until final response is sent */ + + if (sr->sr_method == sip_method_invite && status < 300) + return 0; /* INVITE lives on until ACK is received */ + + if (initial && 300 <= status) + terminated = 1; + else if (sr->sr_terminating && status < 300) + terminated = 1; + else + terminated = sip_response_terminates_dialog(status, sr->sr_method, NULL); + + nua_server_request_destroy(sr); + + if (!terminated) + return 1; + + if (usage) + nua_dialog_usage_remove(nh, nh->nh_ds, usage); + + if (!initial) { + if (terminated > 0) + return 2; + + /* Remove all usages of the dialog */ + nua_dialog_remove_usages(nh, nh->nh_ds, status, phrase); + + return 3; + } + else if (!handle_can_be_terminated) { + return 3; + } + else { + if (nh != nh->nh_nua->nua_dhandle) + nh_destroy(nh->nh_nua, nh); + + return 4; + } +} + +/* ---------------------------------------------------------------------- */ + +/** @class nua_client_request + * + * Each handle has a queue of client-side requests; if a request is pending, + * a new request from API is added to the queue. After the request is + * complete, it is removed from the queue and destroyed by the default. The + * exception is the client requests bound to a dialog usage: they are saved + * and re-used when the dialog usage is refreshed (and sometimes when the + * usage is terminated). + * + * The client request is subclassed and its behaviour modified using virtual + * function table in #nua_client_methods_t. + * + * The first three methods (crm_template(), crm_init(), crm_send()) are + * called when the request is sent first time. + * + * The crm_template() is called if a template request message is needed (for + * example, in case of unregister, unsubscribe and unpublish, the template + * message is taken from the request establishing the usage). + * + * The crm_init() is called when the template message and dialog leg has + * been created and populated by the tags procided by the application. Its + * parameters msg and sip are pointer to the template request message that + * is saved in the @ref "cr_msg" nua_client_request::cr_msg field. + * + * The crm_send() is called with a copy of the template message that has + * been populated with all the fields included in the request, including + * @CSeq and @MaxForwards. The crm_send() function, such as + * nua_publish_client_request(), usually calls nua_base_client_trequest() that + * then creates the nta-level transaction. + * + * The response to the request is processed by crm_check_restart(), which + * modifies and restarts the request when needed (e.g., when negotiating + * expiration time). After the request has been suitably modified, e.g., the + * expiration time has been increased, the restart function calls + * nua_client_restart(), which restarts the request and relays the + * intermediate response to the application with nua_client_restart() and + * crm_report(). + * + * The final responses are processed by crm_recv() and and preliminary ones + * by crm_preliminary(). Both functions call nua_base_client_response() after + * method-specific processing. + * + * The nua_base_client_response() relays the response to the application with + * nua_client_restart() and crm_report(). + * + * @par Terminating Dialog Usages and Dialogs + * + * The response can be marked as terminating with nua_client_terminating(). + * When a terminating request completes the dialog usage is removed and the + * dialog is destroyed (unless there is an another active usage). + */ +static int nua_client_request_try(nua_client_request_t *cr); +static int nua_client_request_sendmsg(nua_client_request_t *cr, + msg_t *msg, sip_t *sip); + +/**Create a client request. + * + * @retval 0 if request is pending + * @retval > 0 if error event has been sent + * @retval < 0 upon an error + */ +int nua_client_create(nua_handle_t *nh, + int event, + nua_client_methods_t const *methods, + tagi_t const * const tags) +{ + su_home_t *home = nh->nh_home; + nua_client_request_t *cr; + sip_method_t method; + char const *name; + + method = methods->crm_method, name = methods->crm_method_name; + if (!name) { + tagi_t const *t = tl_find_last(tags, nutag_method); + if (t) + name = (char const *)t->t_value; + } + + cr = su_zalloc(home, sizeof *cr + methods->crm_extra); + if (!cr) { + return nua_stack_event(nh->nh_nua, nh, + NULL, + event, + NUA_INTERNAL_ERROR, + NULL); + } + + cr->cr_owner = nh; + cr->cr_methods = methods; + cr->cr_event = event; + cr->cr_method = method; + cr->cr_method_name = name; + cr->cr_contactize = methods->crm_flags.target_refresh; + cr->cr_auto = 1; + + if (su_msg_is_non_null(nh->nh_nua->nua_signal)) { + nua_event_data_t const *e = su_msg_data(cr->cr_signal); + + if (tags == e->e_tags && event == e->e_event) { + cr->cr_auto = 0; + if (tags) { + su_msg_save(cr->cr_signal, nh->nh_nua->nua_signal); + cr->cr_tags = tags; + } + } + } + + if (tags && cr->cr_tags == NULL) + cr->cr_tags = tl_tlist(nh->nh_home, TAG_NEXT(tags)); + + if (nua_client_request_queue(cr)) + return 0; + + return nua_client_init_request(cr); +} + +int nua_client_tcreate(nua_handle_t *nh, + int event, + nua_client_methods_t const *methods, + tag_type_t tag, tag_value_t value, ...) +{ + int retval; + ta_list ta; + ta_start(ta, tag, value); + retval = nua_client_create(nh, event, methods, ta_args(ta)); + ta_end(ta); + return retval; +} + +inline int nua_client_request_queue(nua_client_request_t *cr) +{ + int queued = 0; + nua_client_request_t **queue = &cr->cr_owner->nh_ds->ds_cr; + + assert(cr->cr_prev == NULL && cr->cr_next == NULL); + + cr->cr_status = 0; + + if (cr->cr_method != sip_method_invite && + cr->cr_method != sip_method_cancel) { + while (*queue) { + if ((*queue)->cr_method == sip_method_invite || + (*queue)->cr_method == sip_method_cancel) + break; + queue = &(*queue)->cr_next; + queued = 1; + } + } + else { + while (*queue) + queue = &(*queue)->cr_next; + } + + if ((cr->cr_next = *queue)) + cr->cr_next->cr_prev = &cr->cr_next; + + cr->cr_prev = queue, *queue = cr; + + return queued; +} + +inline nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr) +{ + if (cr->cr_prev) + if ((*cr->cr_prev = cr->cr_next)) + cr->cr_next->cr_prev = cr->cr_prev; + cr->cr_prev = NULL, cr->cr_next = NULL; + return cr; +} + +void nua_client_request_destroy(nua_client_request_t *cr) +{ + nua_handle_t *nh; + + if (cr == NULL) + return; + + if (cr->cr_methods->crm_deinit) + cr->cr_methods->crm_deinit(cr); + + nh = cr->cr_owner; + + su_msg_destroy(cr->cr_signal); + + nua_client_request_remove(cr); + nua_client_bind(cr, NULL); + + if (cr->cr_msg) + msg_destroy(cr->cr_msg); + cr->cr_msg = NULL, cr->cr_sip = NULL; + + if (cr->cr_orq) + nta_outgoing_destroy(cr->cr_orq); + + cr->cr_orq = NULL; + + if (cr->cr_target) + su_free(nh->nh_home, cr->cr_target); + + su_free(nh->nh_home, cr); +} + +/** Bind client request to a dialog usage */ +int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du) +{ + assert(cr); + if (cr == NULL) + return -1; + + if (du == NULL) { + if (cr->cr_usage && cr->cr_usage->du_cr == cr) + cr->cr_usage->du_cr = NULL; + cr->cr_usage = NULL; + return 0; + } + + if (du->du_cr && cr != du->du_cr) { + assert(!nua_client_is_queued(du->du_cr)); + if (nua_client_is_queued(du->du_cr)) + return -1; + if (nua_client_is_reporting(du->du_cr)) { + du->du_cr->cr_usage = NULL; + du->du_cr = NULL; + } + else + nua_client_request_destroy(du->du_cr); + } + + du->du_cr = cr, cr->cr_usage = du; + + return 0; +} + +/**Initialize client request for sending. + * + * This function is called only first time the request is sent. + * + * @retval 0 if request is pending + * @retval >=1 if error event has been sent + */ +int nua_client_init_request(nua_client_request_t *cr) +{ + nua_handle_t *nh = cr->cr_owner; + nua_t *nua = nh->nh_nua; + nua_dialog_state_t *ds = nh->nh_ds; + msg_t *msg = NULL; + sip_t *sip; + url_string_t const *url = NULL; + tagi_t const *t; + int has_contact = 0; + int error = 0; + + if (!cr->cr_method_name) + return nua_client_return(cr, NUA_INTERNAL_ERROR, NULL); + + if (cr->cr_msg) + return nua_client_request_try(cr); + + cr->cr_answer_recv = 0, cr->cr_offer_sent = 0; + cr->cr_offer_recv = 0, cr->cr_answer_sent = 0; + cr->cr_terminated = 0, cr->cr_graceful = 0; + + nua_stack_init_handle(nua, nh, TAG_NEXT(cr->cr_tags)); + + if (cr->cr_method == sip_method_cancel) { + if (cr->cr_methods->crm_init) { + error = cr->cr_methods->crm_init(cr, NULL, NULL, cr->cr_tags); + if (error) + return error; + } + + if (cr->cr_methods->crm_send) + return cr->cr_methods->crm_send(cr, NULL, NULL, cr->cr_tags); + else + return nua_base_client_request(cr, NULL, NULL, cr->cr_tags); + } + + if (!cr->cr_methods->crm_template || + !cr->cr_methods->crm_template(cr, &msg, cr->cr_tags)) + msg = nta_msg_create(nua->nua_nta, 0); + + sip = sip_object(msg); + if (!sip) + return nua_client_return(cr, NUA_INTERNAL_ERROR, msg); + + /**@par Populating SIP Request Message with Tagged Arguments + * + * The tagged arguments can be used to pass values for any SIP headers + * to the stack. When the INVITE message (or any other SIP message) is + * created, the tagged values saved with nua_handle() are used first, + * next the tagged values given with the operation (nua_invite()) are + * added. + * + * When multiple tags for the same header are specified, the behaviour + * depends on the header type. If only a single header field can be + * included in a SIP message, the latest non-NULL value is used, e.g., + * @Subject. However, if the SIP header can consist of multiple lines or + * header fields separated by comma, e.g., @Accept, all the tagged + * values are concatenated. + * + * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), + * the values from previous tags are ignored. + */ + if (nh->nh_tags) { + for (t = nh->nh_tags; t; t = t_next(t)) { + if (t->t_tag == siptag_contact || + t->t_tag == siptag_contact_str) + has_contact = 1; + else if (t->t_tag == nutag_url) + url = (url_string_t const *)t->t_value; + } + + t = nh->nh_tags, sip_add_tagis(msg, sip, &t); + } + + for (t = cr->cr_tags; t; t = t_next(t)) { + if (t->t_tag == siptag_contact || + t->t_tag == siptag_contact_str) + has_contact = 1; + else if (t->t_tag == nutag_url) + url = (url_string_t const *)t->t_value; + else if (t->t_tag == nutag_auth && t->t_value) { + /* XXX ignoring errors */ + if (nh->nh_auth) + auc_credentials(&nh->nh_auth, nh->nh_home, (char *)t->t_value); + } + } + + if (cr->cr_method == sip_method_register && url == NULL) + url = (url_string_t const *)NH_PGET(nh, registrar); + + if ((t = cr->cr_tags)) { + if (sip_add_tagis(msg, sip, &t) < 0) + goto error; + } + + /** + * Now, the target URI for the request needs to be determined. + * + * For initial requests, values from tags are used. If NUTAG_URL() is + * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, + * it is used as target URI. If neither is given, the complete request + * line already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() + * is used. At this point, the target URI is stored in the request line, + * together with method name and protocol version ("SIP/2.0"). The + * initial dialog information is also created: @CallID, @CSeq headers + * are generated, if they do not exist, and a tag is added to the @From + * header. + */ + + if (!ds->ds_leg) { + if (ds->ds_remote_tag && ds->ds_remote_tag[0] && + sip_to_tag(nh->nh_home, sip->sip_to, ds->ds_remote_tag) < 0) + goto error; + + if (sip->sip_from == NULL && + sip_add_dup(msg, sip, (sip_header_t *)nua->nua_from) < 0) + goto error; + + if (cr->cr_methods->crm_flags.create_dialog) { + ds->ds_leg = nta_leg_tcreate(nua->nua_nta, + nua_stack_process_request, nh, + SIPTAG_CALL_ID(sip->sip_call_id), + SIPTAG_FROM(sip->sip_from), + SIPTAG_TO(sip->sip_to), + SIPTAG_CSEQ(sip->sip_cseq), + TAG_END()); + if (!ds->ds_leg) + goto error; + + if (!sip->sip_from->a_tag && + sip_from_tag(msg_home(msg), sip->sip_from, + nta_leg_tag(ds->ds_leg, NULL)) < 0) + goto error; + } + } + else { + if (ds->ds_route) + url = NULL; + } + + if (url && nua_client_set_target(cr, (url_t *)url) < 0) + goto error; + + cr->cr_has_contact = has_contact; + + if (cr->cr_methods->crm_init) { + error = cr->cr_methods->crm_init(cr, msg, sip, cr->cr_tags); + if (error < -1) + msg = NULL; + if (error < 0) + goto error; + if (error != 0) + return error; + } + + cr->cr_msg = msg; + cr->cr_sip = sip; + + return nua_client_request_try(cr); + + error: + return nua_client_return(cr, NUA_INTERNAL_ERROR, msg); +} + + +/** Resend the request message. + * + * @retval 0 if request is pending + * @retval >=1 if error event has been sent + */ +int nua_client_resend_request(nua_client_request_t *cr, + int terminating, + tagi_t const *tags) +{ + if (cr) { + if (tags && cr->cr_msg) + if (sip_add_tagis(cr->cr_msg, NULL, &tags) < 0) + /* XXX */; + + cr->cr_retry_count = 0; + cr->cr_terminating = terminating; + + if (!nua_client_is_queued(cr)) { + if (nua_client_request_queue(cr)) + return 0; + if (nua_client_is_reporting(cr)) + return 0; + } + + return nua_client_request_try(cr); + } + return 0; +} + + +/** Create a request message and send it. + * + * If an error occurs, send error event to the application. + * + * @retval 0 if request is pending + * @retval >=1 if error event has been sent + */ +static +int nua_client_request_try(nua_client_request_t *cr) +{ + int error = -1; + msg_t *msg = msg_copy(cr->cr_msg); + sip_t *sip = sip_object(msg); + + cr->cr_answer_recv = 0, cr->cr_offer_sent = 0; + cr->cr_offer_recv = 0, cr->cr_answer_sent = 0; + cr->cr_terminated = 0, cr->cr_graceful = 0; + + if (msg && sip) { + error = nua_client_request_sendmsg(cr, msg, sip); + if (!error) + return 0; + + if (error == -1) + msg_destroy(msg); + } + + if (error < 0) + error = nua_client_response(cr, NUA_INTERNAL_ERROR, NULL); + + assert(error > 0); + return error; +} + +/**Send a request message. + * + * @retval 0 if request is pending + * @retval >=1 if error event has been sent + * @retval -1 if error occurred but event has not been sent, + and @a msg has not been destroyed + * @retval -2 if error occurred, event has not been sent, + * but @a msg has been destroyed + */ +static +int nua_client_request_sendmsg(nua_client_request_t *cr, msg_t *msg, sip_t *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_state_t *ds = nh->nh_ds; + sip_method_t method = cr->cr_method; + char const *name = cr->cr_method_name; + url_string_t const *url = (url_string_t *)cr->cr_target; + nta_leg_t *leg; + + assert(cr->cr_orq == NULL); + + if (ds->ds_leg) + leg = ds->ds_leg; + else + leg = nh->nh_nua->nua_dhandle->nh_ds->ds_leg; /* Default leg */ + + if (nua_dialog_is_established(ds)) { + while (sip->sip_route) + sip_route_remove(msg, sip); + } + + /** + * For in-dialog requests, the request URI is taken from the @Contact + * header received from the remote party during dialog establishment, + * and the NUTAG_URL() is ignored. + * + * Also, the @CallID and @CSeq headers and @From and @To tags are + * generated based on the dialog information and added to the request. + * If the dialog has a route, it is added to the request, too. + */ + if (nta_msg_request_complete(msg, leg, method, name, url) < 0) + return -1; + + /**@MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is + * also added now, if it does not exist. + */ + + if (!ds->ds_remote) + ds->ds_remote = sip_to_dup(nh->nh_home, sip->sip_to); + if (!ds->ds_local) + ds->ds_local = sip_from_dup(nh->nh_home, sip->sip_from); + + /** + * Next, values previously set with nua_set_params() or nua_set_hparams() + * are used: @Allow, @Supported, @Organization, and @UserAgent headers are + * added to the request if they are not already set. + */ + if (!sip->sip_allow && !ds->ds_route) + sip_add_dup(msg, sip, (sip_header_t*)NH_PGET(nh, allow)); + + if (!sip->sip_supported && NH_PGET(nh, supported)) + sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, supported)); + + if (method == sip_method_register && NH_PGET(nh, path_enable) && + !sip_has_feature(sip->sip_supported, "path") && + !sip_has_feature(sip->sip_require, "path")) + sip_add_make(msg, sip, sip_supported_class, "path"); + + if (!sip->sip_organization && NH_PGET(nh, organization)) + sip_add_dup(msg, sip, (sip_header_t *)NH_PGET(nh, organization)); + + if (!sip->sip_user_agent && NH_PGET(nh, user_agent)) + sip_add_make(msg, sip, sip_user_agent_class, NH_PGET(nh, user_agent)); + + /** + * Next, the stack generates a @Contact header for the request (unless + * the application already gave a @Contact header or it does not want to + * use @Contact and indicates that by including SIPTAG_CONTACT(NULL) or + * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the + * application has registered the URI in @From header, the @Contact + * header used with registration is used. Otherwise, the @Contact header + * is generated from the local IP address and port number. + */ + + /**For the initial requests, @ServiceRoute set that was received from the + * registrar is also added to the request message. + */ + if (cr->cr_method != sip_method_register) { + if (nua_registration_add_contact_to_request(nh, msg, sip, + cr->cr_contactize && + !cr->cr_has_contact, + !ds->ds_route) < 0) + return -1; + } + + cr->cr_challenged = 0; + + if (cr->cr_methods->crm_send) + return cr->cr_methods->crm_send(cr, msg, sip, NULL); + + return nua_base_client_request(cr, msg, sip, NULL); +} + +/**Add tags to request message and send it, + * + * @retval 0 success + * @retval -1 if error occurred, but event has not been sent + * @retval -2 if error occurred, event has not been sent, + * and @a msg has been destroyed + * @retval >=1 if error event has been sent + */ +int nua_base_client_trequest(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tag_type_t tag, tag_value_t value, ...) +{ + int retval; + ta_list ta; + ta_start(ta, tag, value); + retval = nua_base_client_request(cr, msg, sip, ta_args(ta)); + ta_end(ta); + return retval; +} + +/** Send request. + * + * @retval 0 success + * @retval -1 if error occurred, but event has not been sent + * @retval -2 if error occurred, event has not been sent, + * and @a msg has been destroyed + * @retval >=1 if error event has been sent + */ +int nua_base_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + + if (nh->nh_auth && auc_authorize(&nh->nh_auth, msg, sip) < 0) + return nua_client_return(cr, 900, "Cannot add credentials", msg); + + cr->cr_seq = sip->sip_cseq->cs_seq; /* Save last sequence number */ + + cr->cr_orq = nta_outgoing_mcreate(nh->nh_nua->nua_nta, + nua_client_orq_response, cr, + NULL, + msg, + TAG_NEXT(tags)); + + return cr->cr_orq ? 0 : -1; +} + +/** Callback for nta client transaction */ +int nua_client_orq_response(nua_client_request_t *cr, + nta_outgoing_t *orq, + sip_t const *sip) +{ + int status; + char const *phrase; + + if (sip && sip->sip_status) { + status = sip->sip_status->st_status; + phrase = sip->sip_status->st_phrase; + } + else { + status = nta_outgoing_status(orq); + phrase = ""; + } + + nua_client_response(cr, status, phrase, sip); + + return 0; +} + +/**Return response to the client request. + * + * Return a response generated by the stack. This function is used to return + * a error response within @a nua_client_methods_t#crm_init or @a + * nua_client_methods_t#crm_send functions. It takes care of disposing the @a + * to_be_destroyed that cannot be sent. + * + * @retval 0 if response event was preliminary + * @retval 1 if response event was final + * @retval 2 if response event destroyed the handle, too. + */ +int nua_client_return(nua_client_request_t *cr, + int status, + char const *phrase, + msg_t *to_be_destroyed) +{ + if (to_be_destroyed) + msg_destroy(to_be_destroyed); + nua_client_response(cr, status, phrase, NULL); + return 1; +} + +/** Process response to the client request. + * + * The response can be generated by the stack (@a sip is NULL) or + * returned by the remote server. + * + * @retval 0 if response event was preliminary + * @retval 1 if response event was final + * @retval 2 if response event destroyed the handle, too. + */ +int nua_client_response(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + + if (cr->cr_restarting) + return 0; + + cr->cr_status = status; + + if (status < 200) { + /* Xyzzy */ + } + else if (sip && nua_client_check_restart(cr, status, phrase, sip)) { + return 0; + } + else if (status < 300) { + if (cr->cr_terminating) { + cr->cr_terminated = 1; + } + else { + if (sip) { + if (cr->cr_methods->crm_flags.target_refresh) + nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); + nua_dialog_store_peer_info(nh, nh->nh_ds, sip); + } + + if (du && du->du_cr == cr) + du->du_ready = 1; + } + } + else { + sip_method_t method = cr->cr_method; + int terminated, graceful = 1; + + if (status < 700) + terminated = sip_response_terminates_dialog(status, method, &graceful); + else + /* XXX - terminate usage by all internal error responses */ + terminated = 0, graceful = 1; + + if (terminated < 0) + cr->cr_terminated = terminated; + else if (cr->cr_terminating) + cr->cr_terminated = 1; + else if (terminated && graceful) + cr->cr_graceful = graceful; + else if (terminated) + cr->cr_terminated = 1; + } + + if (status < 200) { + if (cr->cr_methods->crm_preliminary) + cr->cr_methods->crm_preliminary(cr, status, phrase, sip); + else + nua_base_client_response(cr, status, phrase, sip, NULL); + return 0; + } + + if (cr->cr_methods->crm_recv) + return cr->cr_methods->crm_recv(cr, status, phrase, sip); + else + return nua_base_client_response(cr, status, phrase, sip, NULL); +} + +/** Check if request should be restarted. + * + * @retval 1 if restarted or waring for restart + * @retval 0 otherwise + */ +int nua_client_check_restart(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + + assert(cr && status >= 200 && phrase && sip); + + if (cr->cr_retry_count >= NH_PGET(nh, retry_count)) + return 0; + + if (cr->cr_methods->crm_check_restart) + return cr->cr_methods->crm_check_restart(cr, status, phrase, sip); + else + return nua_base_client_check_restart(cr, status, phrase, sip); +} + +int nua_base_client_check_restart(nua_client_request_t *cr, + int status, + char const *phrase, + sip_t const *sip) +{ + nua_handle_t *nh = cr->cr_owner; + + /* XXX - handle Retry-After */ + + if (status == 302) { + if (!can_redirect(sip->sip_contact, cr->cr_method)) + return 0; + + if (nua_client_set_target(cr, sip->sip_contact->m_url) >= 0) + return nua_client_restart(cr, 100, "Redirected"); + } + + if (status == 423) { + unsigned my_expires = 0; + + if (cr->cr_sip->sip_expires) + my_expires = cr->cr_sip->sip_expires->ex_delta; + + if (sip->sip_min_expires && + sip->sip_min_expires->me_delta > my_expires) { + sip_expires_t ex[1]; + sip_expires_init(ex); + ex->ex_delta = sip->sip_min_expires->me_delta; + + if (sip_add_dup(cr->cr_msg, NULL, (sip_header_t *)ex) < 0) + return 0; + + return nua_client_restart(cr, 100, "Re-Negotiating Expiration"); + } + } + + if (((status == 401 && sip->sip_www_authenticate) || + (status == 407 && sip->sip_proxy_authenticate)) && + nh_challenge(nh, sip) > 0) { + nta_outgoing_t *orq; + if (auc_has_authorization(&nh->nh_auth)) + return nua_client_restart(cr, 100, "Request Authorized by Cache"); + + orq = cr->cr_orq, cr->cr_orq = NULL; + cr->cr_challenged = 1; + cr->cr_retry_count++; + nua_client_report(cr, status, phrase, NULL, orq, NULL); + nta_outgoing_destroy(orq); + + return 1; + } + + return 0; /* This was a final response that cannot be restarted. */ +} + +/** Restart request. + * + * @retval 1 if restarted + * @retval 0 otherwise + */ +int nua_client_restart(nua_client_request_t *cr, + int status, char const *phrase) +{ + nua_handle_t *nh = cr->cr_owner; + nta_outgoing_t *orq; + int error = -1, terminated, graceful; + msg_t *msg; + sip_t *sip; + + if (++cr->cr_retry_count > NH_PGET(nh, retry_count)) + return 0; + + orq = cr->cr_orq, cr->cr_orq = NULL; assert(orq); + terminated = cr->cr_terminated, cr->cr_terminated = 0; + graceful = cr->cr_graceful, cr->cr_graceful = 0; + + msg = msg_copy(cr->cr_msg); + sip = sip_object(msg); + + if (msg && sip) { + cr->cr_restarting = 1; + error = nua_client_request_sendmsg(cr, msg, sip); + cr->cr_restarting = 0; + if (error !=0 && error != -2) + msg_destroy(msg); + } + + + if (error) { + cr->cr_graceful = graceful; + cr->cr_terminated = terminated; + assert(cr->cr_orq == NULL); + cr->cr_orq = orq; + return 0; + } + + nua_client_report(cr, status, phrase, NULL, orq, NULL); + + nta_outgoing_destroy(orq); + + return 1; +} + +int nua_client_set_target(nua_client_request_t *cr, url_t const *target) +{ + url_t *new_target, *old_target = cr->cr_target; + + if (!target || target == old_target) + return 0; + + new_target = url_hdup(cr->cr_owner->nh_home, (url_t *)target); + if (!new_target) + return -1; + cr->cr_target = new_target; + if (old_target) + su_free(cr->cr_owner->nh_home, old_target); + + return 0; +} + +/**@internal + * Relay response event to the application. + * + * @todo + * If handle has already been marked as destroyed by nua_handle_destroy(), + * release the handle with nh_destroy(). + * + * @retval 0 if event was preliminary + * @retval 1 if event was final + * @retval 2 if event destroyed the handle, too. + */ +int nua_base_client_tresponse(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + tag_type_t tag, tag_value_t value, ...) +{ + ta_list ta; + int retval; + + if (cr->cr_event == nua_r_destroy) + return nua_base_client_response(cr, status, phrase, sip, NULL); + + ta_start(ta, tag, value); + retval = nua_base_client_response(cr, status, phrase, sip, ta_args(ta)); + ta_end(ta); + + return retval; +} + +/**@internal + * Relay response event to the application. + * + * @todo + * If handle has already been marked as destroyed by nua_handle_destroy(), + * release the handle with nh_destroy(). + * + * @retval 0 if event was preliminary + * @retval 1 if event was final + * @retval 2 if event destroyed the handle, too. + */ +int nua_base_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + int next; + + cr->cr_reporting = 1; + + if (status >= 200 && status < 300) + nh_challenge(nh, sip); /* Collect nextnonce */ + + nua_client_report(cr, status, phrase, sip, cr->cr_orq, tags); + + if (status >= 200) + nua_client_request_remove(cr); + + if (cr->cr_method == sip_method_invite ? status < 300 : status < 200) { + cr->cr_reporting = 0; + return 1; + } + + if (cr->cr_orq) + nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; + + if (cr->cr_usage) { + nua_dialog_usage_t *du = cr->cr_usage; + + if (cr->cr_terminated < 0) + /* XXX - dialog has been terminated */; + + if (cr->cr_terminated || + (!du->du_ready && status >= 300 && nua_client_is_bound(cr))) { + /* Usage has been destroyed */ + nua_dialog_usage_remove(nh, nh->nh_ds, du); + } + else if (cr->cr_graceful) { + /* Terminate usage gracefully */ + nua_dialog_usage_shutdown(nh, nh->nh_ds, du); + } + } + + cr->cr_reporting = 0; + + if (nua_client_is_queued(cr)) + return 1; + + next = cr->cr_method != sip_method_invite && cr->cr_method != sip_method_cancel; + + if (!nua_client_is_bound(cr)) + nua_client_request_destroy(cr); + + if (next && nh->nh_ds->ds_cr != NULL && nh->nh_ds->ds_cr != cr) { + cr = nh->nh_ds->ds_cr; + if (cr->cr_method != sip_method_invite && cr->cr_method != sip_method_cancel) + nua_client_init_request(cr); + } + + return 1; +} + +/** Send event, zap transaction but leave cr in list */ +int nua_client_report(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tagi_t const *tags) +{ + nua_handle_t *nh; + + if (cr->cr_event == nua_r_destroy) + return 1; + + if (cr->cr_methods->crm_report) + return cr->cr_methods->crm_report(cr, status, phrase, sip, orq, tags); + + nh = cr->cr_owner; + + nua_stack_event(nh->nh_nua, nh, + nta_outgoing_getresponse(orq), + cr->cr_event, + status, phrase, + tags); + return 1; +} + +int nua_client_treport(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip, + nta_outgoing_t *orq, + tag_type_t tag, tag_value_t value, ...) +{ + int retval; + ta_list ta; + ta_start(ta, tag, value); + retval = nua_client_report(cr, status, phrase, sip, orq, ta_args(ta)); + ta_end(ta); + return retval; +} + +nua_client_request_t * +nua_client_request_pending(nua_client_request_t const *cr) +{ + for (;cr;cr = cr->cr_next) + if (cr->cr_orq) + return (nua_client_request_t *)cr; + + return NULL; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h index e9c0afcdc7..48c5d136e5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h @@ -103,6 +103,32 @@ typedef struct register_usage nua_registration_t; TAG_IF((include) && (soa) && soa_is_remote_chat_active(soa) >= 0, \ SOATAG_ACTIVE_CHAT(soa_is_remote_chat_active(soa))) +#if HAVE_NUA_HANDLE_DEBUG + +#define nua_handle_ref(nh) nua_handle_ref_by((nh), __func__) +#define nua_handle_unref(nh) nua_handle_unref_by((nh), __func__) + +static inline nua_handle_t *nua_handle_ref_by(nua_handle_t *nh, + char const *by) +{ + if (nh) + SU_DEBUG_0(("nua_handle_ref(%p) => "MOD_ZU" by %s\n", nh, + su_home_refcount((su_home_t *)nh) + 1, + by)); + return (nua_handle_t *)su_home_ref((su_home_t *)nh); +} + +static inline int nua_handle_unref_by(nua_handle_t *nh, char const *by) +{ + if (nh) + SU_DEBUG_0(("nua_handle_unref(%p) => "MOD_ZU" by %s\n", nh, + su_home_refcount((su_home_t *)nh) - 1, + by)); + return su_home_unref((su_home_t *)nh); +} + +#endif + /** NUA handle. * */ @@ -113,7 +139,8 @@ struct nua_handle_s nua_handle_t **nh_prev; nua_t *nh_nua; /**< Pointer to NUA object */ - void *nh_valid; + void *nh_valid; /**< Cookie */ +#define nua_valid_handle_cookie ((void *)(intptr_t)nua_handle) nua_hmagic_t *nh_magic; /**< Application context */ tagi_t *nh_tags; /**< Initial tags */ @@ -154,7 +181,8 @@ struct nua_handle_s nea_server_t *nh_notifier; /**< SIP notifier */ }; -#define NH_IS_VALID(nh) ((nh) && (nh)->nh_valid) +#define NH_IS_VALID(nh) \ + ((nh) && (nh)->nh_valid == nua_valid_handle_cookie) #define NH_STATUS(nh) \ (nh)->nh_status, \ @@ -285,20 +313,23 @@ nua_stack_signal_handler nua_stack_method; #define UA_EVENT1(e, statusphrase) \ - nua_stack_event(nua, nh, NULL, e, statusphrase, TAG_END()) + nua_stack_event(nua, nh, NULL, e, statusphrase, NULL) #define UA_EVENT2(e, status, phrase) \ - nua_stack_event(nua, nh, NULL, e, status, phrase, TAG_END()) + nua_stack_event(nua, nh, NULL, e, status, phrase, NULL) #define UA_EVENT3(e, status, phrase, tag) \ - nua_stack_event(nua, nh, NULL, e, status, phrase, tag, TAG_END()) + nua_stack_event(nua, nh, NULL, e, status, phrase, tag, NULL) + +int nua_stack_tevent(nua_t *nua, nua_handle_t *nh, msg_t *msg, + nua_event_t event, int status, char const *phrase, + tag_type_t tag, tag_value_t value, ...); int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg, nua_event_t event, int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...); + tagi_t const *tags); -nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, - tagi_t *tags); +nua_handle_t *nh_create_handle(nua_t *nua, nua_hmagic_t *hmagic, tagi_t *tags); nua_handle_t *nua_stack_incoming_handle(nua_t *nua, nta_incoming_t *irq, @@ -349,48 +380,8 @@ int nua_stack_process_request(nua_handle_t *nh, nta_incoming_t *irq, sip_t const *sip); -int nua_stack_process_response(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - tag_type_t tag, tag_value_t value, ...); - int nua_stack_launch_network_change_detector(nua_t *nua); -msg_t *nua_creq_msg(nua_t *nua, nua_handle_t *nh, - nua_client_request_t *cr, - int restart, - sip_method_t method, char const *name, - tag_type_t tag, tag_value_t value, ...); - -int nua_tagis_have_contact_tag(tagi_t const *t); - -int nua_creq_check_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - sip_t const *sip, - nua_creq_restart_f *f); - -int nua_creq_restart_with(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - int status, char const *phrase, - nua_creq_restart_f *f, - tag_type_t tag, tag_value_t value, ...); - -int nua_creq_save_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_outgoing_t *orq, - int status, char const *phrase, - nua_creq_restart_f *f); - -int nua_creq_restart(nua_handle_t *nh, - nua_client_request_t *cr, - nta_response_f *cb, - tagi_t *tags); - -void nua_creq_deinit(nua_client_request_t *cr, nta_outgoing_t *orq); - sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr); int nua_registration_add_contact_to_request(nua_handle_t *nh, @@ -405,51 +396,6 @@ int nua_registration_add_contact_to_response(nua_handle_t *nh, sip_record_route_t const *, sip_contact_t const *remote); -msg_t *nh_make_response(nua_t *nua, nua_handle_t *nh, - nta_incoming_t *irq, - int status, char const *phrase, - tag_type_t tag, tag_value_t value, ...); - - -typedef int nua_stack_process_request_t(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip); - -nua_stack_process_request_t nua_stack_process_invite; -nua_stack_process_request_t nua_stack_process_info; -nua_stack_process_request_t nua_stack_process_update; -nua_stack_process_request_t nua_stack_process_bye; -nua_stack_process_request_t nua_stack_process_message; -nua_stack_process_request_t nua_stack_process_options; -nua_stack_process_request_t nua_stack_process_publish; -nua_stack_process_request_t nua_stack_process_subscribe; -nua_stack_process_request_t nua_stack_process_notify; -nua_stack_process_request_t nua_stack_process_refer; -nua_stack_process_request_t nua_stack_process_unknown; -nua_stack_process_request_t nua_stack_process_register; -nua_stack_process_request_t nua_stack_process_method; - -nua_client_request_t - *nua_client_request_pending(nua_client_request_t const *), - *nua_client_request_restarting(nua_client_request_t const *), - *nua_client_request_by_orq(nua_client_request_t const *cr, - nta_outgoing_t const *orq); - -nua_server_request_t *nua_server_request(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip, - nua_server_request_t *sr, - size_t size, - nua_server_respond_f *respond, - int create_dialog); - -int nua_stack_server_event(nua_t *nua, - nua_server_request_t *sr, - nua_event_t event, - tag_type_t tag, tag_value_t value, ...); - /* ---------------------------------------------------------------------- */ #ifndef SDP_MIME_TYPE @@ -466,15 +412,6 @@ extern char const nua_application_sdp[]; #define NUTAG_ADD_CONTACT(v) _nutag_add_contact, tag_bool_v(v) extern tag_typedef_t _nutag_add_contact; -#define NUTAG_ADD_CONTACT_REF(v) _nutag_add_contact_ref, tag_bool_vr(&v) -extern tag_typedef_t _nutag_add_contact_ref; - -#define NUTAG_COPY(v) _nutag_copy, tag_bool_v(v) -extern tag_typedef_t _nutag_copy; - -#define NUTAG_COPY_REF(v) _nutag_copy_ref, tag_bool_vr(&v) -extern tag_typedef_t _nutag_copy_ref; - /* ---------------------------------------------------------------------- */ typedef unsigned longlong ull; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c index cb26ff966e..e06e7bd065 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c @@ -47,12 +47,10 @@ #include #include #include +#include #include #include -#define NTA_LEG_MAGIC_T struct nua_handle_s -#define NTA_OUTGOING_MAGIC_T struct nua_handle_s - #include "nua_stack.h" /* ---------------------------------------------------------------------- */ @@ -60,9 +58,10 @@ struct event_usage { - enum nua_substate eu_substate; /**< Subscription state */ + enum nua_substate eu_substate; /**< Subscription state */ sip_time_t eu_expires; /**< Proposed expiration time */ unsigned eu_notified; /**< Number of NOTIFYs received */ + unsigned eu_refer:1; /**< Implied subscription by refer */ unsigned eu_final_wait:1; /**< Waiting for final NOTIFY */ unsigned eu_no_id:1; /**< Do not use "id" (even if we have one) */ }; @@ -105,6 +104,7 @@ int nua_subscribe_usage_add(nua_handle_t *nh, { ds->ds_has_events++; ds->ds_has_subscribes++; + return 0; } @@ -167,134 +167,128 @@ void nua_subscribe_usage_remove(nua_handle_t *nh, * @sa NUTAG_SUBSTATE(), @RFC3265 */ -static int process_response_to_subscribe(nua_handle_t *nh, - nta_outgoing_t *orq, +static int nua_subscribe_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_subscribe_client_request(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_subscribe_client_response(nua_client_request_t *cr, + int status, char const *phrase, sip_t const *sip); +static nua_client_methods_t const nua_subscribe_client_methods = { + SIP_METHOD_SUBSCRIBE, + 0, + { + /* create_dialog */ 1, + /* in_dialog */ 1, + /* target refresh */ 1 + }, + NULL, + nua_subscribe_client_init, + nua_subscribe_client_request, + /* nua_subscribe_client_check_restart */ NULL, + nua_subscribe_client_response +}; int nua_stack_subscribe(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - nua_dialog_usage_t *du = NULL; - struct event_usage *eu; - msg_t *msg; - sip_t *sip; + return nua_client_create(nh, e, &nua_subscribe_client_methods, tags); +} - if (nua_stack_set_handle_special(nh, nh_has_subscribe, nua_r_subscribe) < 0) - return UA_EVENT3(e, 500, "Invalid handle for SUBSCRIBE", - NUTAG_SUBSTATE(nua_substate_terminated)); - else if (cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); +static int nua_subscribe_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du; + sip_event_t *o = sip->sip_event; - /* Initialize allow and auth */ - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); + du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, o); - msg = nua_creq_msg(nua, nh, cr, 0, - SIP_METHOD_SUBSCRIBE, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - sip = sip_object(msg); + if (du == NULL && o == NULL) + du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, NONE); - if (sip) { + if (du) { + if (du->du_event && o == NULL) + /* Add Event header */ + sip_add_dup(msg, sip, (sip_header_t *)du->du_event); + } + else if (cr->cr_event == nua_r_subscribe) { + /* Create dialog usage */ + du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, o); + /* Note that we allow SUBSCRIBE without event */ + } + + cr->cr_usage = du; + + return 0; +} + +static int nua_subscribe_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_dialog_usage_t *du = cr->cr_usage; + sip_time_t expires = 0; + + if (cr->cr_event != nua_r_subscribe || + (du && du->du_shutdown) || + (sip->sip_expires && sip->sip_expires->ex_delta == 0)) + cr->cr_terminating = 1; + + if (du) { + struct event_usage *eu = nua_dialog_usage_private(du); sip_event_t *o = sip->sip_event; - du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, o); + if (nua_client_bind(cr, du) < 0) + return -1; - if (du == NULL && o == NULL) - du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, NONE); - - eu = nua_dialog_usage_private(du); - - if (du && du->du_event && (o == NULL || (o->o_id && eu->eu_no_id))) { - if (eu->eu_no_id) /* No id (XXX - nor other parameters) */ - sip_add_make(msg, sip, sip_event_class, du->du_event->o_type); - else - sip_add_dup(msg, sip, (sip_header_t *)du->du_event); + if (eu->eu_no_id && o && o->o_id) { + /* Notifier does not handle id properly, remove it */ + msg_header_remove_param(o->o_common, "id"); } - if (e == nua_r_subscribe) { - if (du == NULL) /* Create dialog usage */ - /* We allow here SUBSCRIBE without event */ - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, o); - } - else if (du) { /* Unsubscribe */ - /* Embryonic subscription is just a placeholder */ +#if 0 + if (cr->cr_terminating) { + /* Already terminated subscription? */ if (eu->eu_substate == nua_substate_terminated || eu->eu_substate == nua_substate_embryonic) { - nua_dialog_usage_remove(nh, nh->nh_ds, du); - msg_destroy(msg); - return UA_EVENT3(e, SIP_200_OK, - NUTAG_SUBSTATE(nua_substate_terminated), - TAG_END()); + return nua_client_return(cr, SIP_200_OK, msg); } } - } +#endif - /* Store message template with supported features (eventlist) */ - if (du && sip) { - if (du->du_msg) - msg_destroy(du->du_msg); - du->du_msg = msg_ref_create(cr->cr_msg); - } - - if (du) - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_subscribe, nh, NULL, - msg, - TAG_IF(e != nua_r_subscribe, - SIPTAG_EXPIRES_STR("0")), - SIPTAG_END(), TAG_NEXT(tags)); - - eu = nua_dialog_usage_private(du); - - if (!cr->cr_orq) { - int substate = nua_substate_terminated; - - if (du == NULL) - ; - else if (du->du_ready) - substate = eu->eu_substate; /* No change in subscription state */ + nua_dialog_usage_reset_refresh(du); /* during SUBSCRIBE transaction */ + + if (cr->cr_terminating) + expires = eu->eu_expires = 0; + else if (sip->sip_expires) + /* Use value specified by application or negotiated with Min-Expires */ + expires = eu->eu_expires = sip->sip_expires->ex_delta; else - nua_dialog_usage_remove(nh, nh->nh_ds, du); - - msg_destroy(msg); - - return UA_EVENT3(e, NUA_INTERNAL_ERROR, - NUTAG_SUBSTATE(substate), TAG_END()); - } - - nua_dialog_usage_reset_refresh(du); /* during SUBSCRIBE transaction */ - du->du_terminating = e != nua_r_subscribe; /* Unsubscribe or destroy */ - - if (du->du_terminating) - eu->eu_expires = 0; - else if (sip->sip_expires) - eu->eu_expires = sip->sip_expires->ex_delta; - else /* We just use common default value, but the default is actually package-specific according to the RFC 3265 section 4.4.4: [Event] packages MUST also define a default "Expires" value to be used if none is specified. */ - eu->eu_expires = 3600; + expires = eu->eu_expires = 3600; - eu->eu_final_wait = 0; - - if (sip->sip_expires && sip->sip_expires->ex_delta == 0) - du->du_terminating = 1; + eu->eu_final_wait = 0; - if (eu->eu_substate == nua_substate_terminated) - eu->eu_substate = nua_substate_embryonic; + if (eu->eu_substate == nua_substate_terminated) + eu->eu_substate = nua_substate_embryonic; + } - cr->cr_usage = du; - return cr->cr_event = e; -} + if (!sip->sip_expires || sip->sip_expires->ex_delta != expires) { + sip_expires_t ex[1]; + sip_expires_init(ex)->ex_delta = expires; + sip_add_dup(msg, sip, (sip_header_t *)ex); + } -static void restart_subscribe(nua_handle_t *nh, tagi_t *tags) -{ - nua_creq_restart(nh, nh->nh_ds->ds_cr, process_response_to_subscribe, tags); + return nua_base_client_request(cr, msg, sip, tags); } /** @NUA_EVENT nua_r_subscribe @@ -342,51 +336,41 @@ static void restart_subscribe(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_subscribe(nua_handle_t *nh, - nta_outgoing_t *orq, +static int nua_subscribe_client_response(nua_client_request_t *cr, + int status, char const *phrase, sip_t const *sip) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; + nua_handle_t *nh = cr->cr_owner; nua_dialog_usage_t *du = cr->cr_usage; struct event_usage *eu = nua_dialog_usage_private(du); - int status = sip ? sip->sip_status->st_status : 408; - int gracefully = 0; - int substate = nua_substate_embryonic; + enum nua_substate substate; - assert(du); assert(du->du_class == nua_subscribe_usage); - - if (status < 200) - ; - else if (du == NULL) { - /* NOTIFY already removed du */ - } - /* We have not received NOTIFY. */ - else if (status < 300) { + if (eu == NULL || cr->cr_terminated) + substate = nua_substate_terminated; + else if (status >= 300) + substate = eu->eu_substate; + else { int win_messenger_enable = NH_PGET(nh, win_messenger_enable); sip_time_t delta, now = sip_now(); du->du_ready = 1; - substate = eu->eu_substate; - - if (du->du_terminating) - delta = 0; - else - /* If there is no expires header, + + if (eu->eu_substate != nua_substate_terminated) + /* If there is no @Expires header, use default value stored in eu_expires */ delta = sip_contact_expires(NULL, sip->sip_expires, sip->sip_date, eu->eu_expires, now); + else + delta = 0; if (win_messenger_enable && !nua_dialog_is_established(nh->nh_ds)) { /* Notify from messanger does not match with dialog tag */ nh->nh_ds->ds_remote_tag = su_strdup(nh->nh_home, ""); } - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - if (delta > 0) { nua_dialog_usage_set_refresh(du, delta); - } + } else if (!eu->eu_notified) { /* This is a fetch: subscription was really terminated but we wait 32 seconds for NOTIFY. */ @@ -396,51 +380,26 @@ static int process_response_to_subscribe(nua_handle_t *nh, delta = 4 * 60; /* Wait 4 minutes for NOTIFY from Messenger */ eu->eu_final_wait = 1; - - /* Do not remove usage in nua_stack_process_response */ - cr->cr_usage = NULL; + + if (eu->eu_substate == nua_substate_terminated) + eu->eu_substate = nua_substate_embryonic; nua_dialog_usage_refresh_range(du, delta, delta); } else { - eu->eu_substate = substate = nua_substate_terminated; + eu->eu_substate = nua_substate_terminated; } - } - else /* if (status >= 300) */ { - int terminated; - - if (nua_creq_check_restart(nh, cr, orq, sip, restart_subscribe)) - return 0; - - cr->cr_usage = NULL; /* We take care of removing/not removing usage */ substate = eu->eu_substate; - if (!sip || !sip->sip_retry_after) - gracefully = 1; - - terminated = - sip_response_terminates_dialog(status, sip_method_subscribe, - &gracefully); - - /* XXX - zap dialog if terminated < 0 ? */ - - if (terminated || !du->du_ready || du->du_terminating) { - substate = nua_substate_terminated; - nua_dialog_usage_remove(nh, nh->nh_ds, du); - } - else if (gracefully && substate != nua_substate_terminated) - /* Post un-subscribe event */ - nua_stack_post_signal(nh, nua_r_unsubscribe, - SIPTAG_EVENT(du->du_event), - SIPTAG_EXPIRES_STR("0"), - TAG_END()); + if (substate == nua_substate_terminated) + /* let nua_base_client_tresponse to remove usage */ + cr->cr_terminated = 1; } - - nua_stack_process_response(nh, cr, orq, sip, - TAG_IF(substate >= 0, NUTAG_SUBSTATE(substate)), - TAG_END()); - return 0; + + return nua_base_client_tresponse(cr, status, phrase, sip, + NUTAG_SUBSTATE(substate), + TAG_END()); } /** Refresh subscription */ @@ -449,120 +408,75 @@ static void nua_subscribe_usage_refresh(nua_handle_t *nh, nua_dialog_usage_t *du, sip_time_t now) { - nua_t *nua = nh->nh_nua; - nua_client_request_t *cr = ds->ds_cr; + nua_client_request_t *cr = du->du_cr; struct event_usage *eu = nua_dialog_usage_private(du); - msg_t *msg; - + assert(eu); if (eu->eu_final_wait) { - /* Did not receive NOTIFY for fetch... */ + /* Did not receive NOTIFY for fetch */ sip_event_t const *o = du->du_event; char const *id = o ? o->o_id : NULL; - SU_DEBUG_3(("nua(%p): fetch event %s%s%s timeouts\n", - nh, o ? o->o_type : "(empty)", + SU_DEBUG_3(("nua(%p): event %s%s%s fetch timeouts\n", + (void *)nh, o ? o->o_type : "(empty)", id ? "; id=" : "", id ? id : "")); - nua_stack_event(nh->nh_nua, nh, NULL, - nua_i_notify, 408, "Fetch Timeouts without NOTIFY", - NUTAG_SUBSTATE(nua_substate_terminated), - SIPTAG_EVENT(o), - TAG_END()); - + nua_stack_tevent(nh->nh_nua, nh, NULL, + nua_i_notify, 408, "Fetch Timeouts without NOTIFY", + NUTAG_SUBSTATE(nua_substate_terminated), + SIPTAG_EVENT(du->du_event), + TAG_END()); nua_dialog_usage_remove(nh, ds, du); return; } - if (du->du_terminating) /* No need to refresh. */ - return; - - if (cr->cr_msg) { - /* Already doing something, delay 5..15 seconds? */ - if (cr->cr_usage != du) - nua_dialog_usage_refresh_range(du, 5, 15); - return; + if (cr) { + if (nua_client_is_queued(cr) || /* Already refreshing */ + nua_client_resend_request(cr, 0, NULL) >= 0) + return; + } + else if (eu->eu_refer) { + /* + * XXX - If we have received a NOTIFY, we should try to terminate + * subscription + */ } - cr->cr_msg = msg_copy(du->du_msg); + nua_stack_tevent(nh->nh_nua, nh, NULL, + nua_i_notify, NUA_INTERNAL_ERROR, + NUTAG_SUBSTATE(nua_substate_terminated), + SIPTAG_EVENT(du->du_event), + TAG_END()); - msg = nua_creq_msg(nua, nh, cr, 1, - SIP_METHOD_SUBSCRIBE, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - /* If dialog is established, remove initial route */ - TAG_IF(nua_dialog_is_established(nh->nh_ds), - SIPTAG_ROUTE(NONE)), - TAG_END()); - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_subscribe, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(NULL)); - if (cr->cr_orq) { - cr->cr_usage = du; - cr->cr_event = nua_r_subscribe; - return; - } - - if (du->du_terminating) - nua_dialog_usage_remove(nh, nh->nh_ds, du); - else /* Try again later? */ - nua_dialog_usage_refresh_range(du, 5, 15); - - msg_destroy(msg); - UA_EVENT3(nua_r_subscribe, NUA_INTERNAL_ERROR, - NUTAG_SUBSTATE(eu->eu_substate), - TAG_END()); + nua_dialog_usage_remove(nh, ds, du); } - -/** Terminate subscription */ +/** Terminate subscription. + * + * @retval >0 shutdown done + * @retval 0 shutdown in progress + * @retval <0 try again later + */ static int nua_subscribe_usage_shutdown(nua_handle_t *nh, nua_dialog_state_t *ds, nua_dialog_usage_t *du) { - nua_t *nua = nh->nh_nua; - nua_client_request_t *cr = ds->ds_cr; struct event_usage *eu = nua_dialog_usage_private(du); - msg_t *msg; + nua_client_request_t *cr = du->du_cr; assert(eu); (void)eu; - if (du->du_terminating) - return 100; /* ...in progress */ - - if (cr->cr_msg) - /* XXX - already doing something else? */ - return 100; + if (cr) { + if (nua_client_is_queued(cr)) /* Subscribing. */ + return -1; /* Request in progress */ - cr->cr_msg = msg_copy(du->du_msg); - - msg = nua_creq_msg(nua, nh, cr, 1, - SIP_METHOD_SUBSCRIBE, - NUTAG_USE_DIALOG(1), - NUTAG_ADD_CONTACT(1), - SIPTAG_EXPIRES_STR("0"), - /* If dialog is established, remove initial route */ - TAG_IF(nua_dialog_is_established(nh->nh_ds), - SIPTAG_ROUTE(NONE)), - TAG_END()); - - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_subscribe, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(NULL)); - if (cr->cr_orq) { - cr->cr_usage = du; - cr->cr_event = nua_r_destroy; - return 100; + if (nua_client_resend_request(cr, 1, NULL) >= 0) + return 0; } - - /* Too bad. */ + nua_dialog_usage_remove(nh, ds, du); - msg_destroy(msg); return 200; } @@ -585,178 +499,183 @@ static int nua_subscribe_usage_shutdown(nua_handle_t *nh, * @END_NUA_EVENT */ -/** @internal Process incoming NOTIFY. */ -int nua_stack_process_notify(nua_t *nua, - nua_handle_t *nh, - nta_incoming_t *irq, - sip_t const *sip) +int nua_notify_server_init(nua_server_request_t *sr); +int nua_notify_server_preprocess(nua_server_request_t *sr); +int nua_notify_server_report(nua_server_request_t *, tagi_t const *); + +nua_server_methods_t const nua_notify_server_methods = + { + SIP_METHOD_NOTIFY, + nua_i_notify, /* Event */ + { + 1, /* Do create dialog */ + 0, /* Not always in-dialog request */ + 1, /* Target refresh request */ + 1, /* Add Contact to response */ + }, + nua_notify_server_init, + nua_notify_server_preprocess, + nua_base_server_params, + nua_base_server_respond, + nua_notify_server_report, + }; + + +int nua_notify_server_init(nua_server_request_t *sr) { - nua_dialog_state_t *ds = nh->nh_ds; - nua_dialog_usage_t *du; - struct event_usage *eu; - sip_subscription_state_t *subs = sip ? sip->sip_subscription_state : NULL; - sip_subscription_state_t ss0[1]; - msg_t *response; - char expires[32]; - int retry = -1; - char const *what = NULL, *why = NULL; + if (!sr->sr_initial) { + nua_dialog_state_t *ds = sr->sr_owner->nh_ds; - enter; + /* Check for forked subscription. */ + if (ds->ds_remote_tag && ds->ds_remote_tag[0] && + str0cmp(ds->ds_remote_tag, sr->sr_request.sip->sip_from->a_tag)) { + sip_contact_t const *m = NULL; - if (nh == NULL) { - nta_incoming_treply(irq, 481, "Subscription Does Not Exist", - TAG_END()); - return 481; - } - assert(nh); + m = nua_stack_get_contact(sr->sr_owner->nh_nua->nua_registrations); + + if (m) { + sip_warning_t w[1]; + + sip_warning_init(w)->w_code = 399; + w->w_host = m->m_url->url_host; + w->w_port = m->m_url->url_port; + w->w_text = "Forking SUBSCRIBEs are not supported"; - if (/* XXX - support forking of subscriptions?... */ - ds->ds_remote_tag && ds->ds_remote_tag[0] && - sip && sip->sip_from->a_tag && - strcmp(ds->ds_remote_tag, sip->sip_from->a_tag)) { - sip_contact_t const *m = NULL; - sip_warning_t *w = NULL, w0[1]; + sip_add_dup(sr->sr_response.msg, NULL, (sip_header_t*)w); + } - m = nua_stack_get_contact(nua->nua_registrations); - if (m) { - w = sip_warning_init(w0); - w->w_code = 399; - w->w_host = m->m_url->url_host; - w->w_port = m->m_url->url_port; - w->w_text = "Forking SUBSCRIBEs are not supported"; + return SR_STATUS(sr, 481, "Subscription Does Not Exist"); } - - nta_incoming_treply(irq, 481, "Subscription Does Not Exist", - SIPTAG_WARNING(w), - TAG_END()); - return 481; - } - - du = nua_dialog_usage_get(nh->nh_ds, nua_subscribe_usage, sip->sip_event); - - if (du == NULL) { - nta_incoming_treply(irq, 481, "Subscription Does Not Exist", TAG_END()); - return 481; - } - - eu = nua_dialog_usage_private(du); assert(eu); - eu->eu_notified++; - - if (!sip->sip_event->o_id) { - eu->eu_no_id = 1; - } - - if (subs == NULL) { - /* Do some compatibility stuff here */ - unsigned long delta; - - sip_subscription_state_init(subs = ss0); - - delta = sip->sip_expires ? sip->sip_expires->ex_delta : eu->eu_expires; - - if (delta == 0) - subs->ss_substate = "terminated"; - else - subs->ss_substate = "active"; - - if (delta > 0 && sip->sip_expires) { - snprintf(expires, sizeof expires, "%lu", delta); - subs->ss_expires = expires; - } - } - - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - nua_dialog_uas_route(nh, nh->nh_ds, sip, 1); - - if (strcasecmp(subs->ss_substate, what = "terminated") == 0) { - eu->eu_substate = nua_substate_terminated; - - if (str0casecmp(subs->ss_reason, why = "deactivated") == 0) { - eu->eu_substate = nua_substate_embryonic; - retry = 0; /* retry immediately */ - } - else if (str0casecmp(subs->ss_reason, why = "probation") == 0) { - eu->eu_substate = nua_substate_embryonic; - retry = 30; - if (subs->ss_retry_after) - retry = strtoul(subs->ss_retry_after, NULL, 10); - if (retry > 3600) - retry = 3600; - } - else - why = subs->ss_reason; - } - else if (strcasecmp(subs->ss_substate, what = "pending") == 0) - eu->eu_substate = nua_substate_pending; - else /* if (strcasecmp(subs->ss_substate, "active") == 0) */ { - /* Any extended state is considered as active */ - what = subs->ss_substate ? subs->ss_substate : "active"; - eu->eu_substate = nua_substate_active; - } - - if (du->du_terminating) - retry = -1; - - response = nh_make_response(nua, nh, irq, SIP_200_OK, - SIPTAG_ALLOW(NH_PGET(nh, allow)), - SIPTAG_SUPPORTED(NH_PGET(nh, supported)), - TAG_END()); - - if (response && - nua_registration_add_contact_to_response(nh, response, NULL, - sip->sip_record_route, - sip->sip_contact) >= 0) - nta_incoming_mreply(irq, response); - else - nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR, TAG_END()); - - if (eu->eu_substate == nua_substate_terminated && retry > 0) - eu->eu_substate = nua_substate_embryonic; - - nua_stack_event(nh->nh_nua, nh, nta_incoming_getrequest(irq), - nua_i_notify, SIP_200_OK, - NUTAG_SUBSTATE(eu->eu_substate), - TAG_END()); - - nta_incoming_destroy(irq), irq = NULL; - - SU_DEBUG_5(("nua(%p): nua_stack_process_notify: %s (%s)\n", - nh, what, why ? why : "")); - - if (eu->eu_substate == nua_substate_terminated) { - if (du != nh->nh_ds->ds_cr->cr_usage) - nua_dialog_usage_remove(nh, nh->nh_ds, du); - else - nua_dialog_usage_reset_refresh(du); - } - else if (eu->eu_substate == nua_substate_embryonic) { - if (retry >= 0) { - /* Try to subscribe again */ - nua_dialog_remove(nh, nh->nh_ds, du); /* tear down */ - nua_dialog_usage_refresh_range(du, retry, retry + 5); - } - else if (du != nh->nh_ds->ds_cr->cr_usage) - nua_dialog_usage_remove(nh, nh->nh_ds, du); - else - nua_dialog_usage_reset_refresh(du); - } - else if (du->du_terminating) { - nua_dialog_usage_reset_refresh(du); - } - else { - sip_time_t delta; - - if (subs->ss_expires) - delta = strtoul(subs->ss_expires, NULL, 10); - else - delta = eu->eu_expires; - - nua_dialog_usage_set_refresh(du, delta); } return 0; } +int nua_notify_server_preprocess(nua_server_request_t *sr) +{ + nua_dialog_state_t *ds = sr->sr_owner->nh_ds; + nua_dialog_usage_t *du; + struct event_usage *eu; + sip_t const *sip = sr->sr_request.sip; + sip_event_t *o = sip->sip_event; + enum nua_substate substate = nua_substate_terminated; + sip_subscription_state_t *subs = sip->sip_subscription_state; + char const *what = "", *reason = NULL; + + du = nua_dialog_usage_get(ds, nua_subscribe_usage, o); + sr->sr_usage = du; + + if (du == NULL) { + if (!sip_is_allowed(NH_PGET(sr->sr_owner, appl_method), SIP_METHOD_NOTIFY)) + return SR_STATUS(sr, 481, "Subscription Does Not Exist"); + /* Let application to handle unsolicited NOTIFY */ + return 0; + } + + eu = nua_dialog_usage_private(du); assert(eu); + eu->eu_notified++; + if (!o->o_id) + eu->eu_no_id = 1; + + if (subs == NULL) { + /* Compatibility */ + unsigned long delta = eu->eu_expires; + if (sip->sip_expires) + delta = sip->sip_expires->ex_delta; + + if (delta == 0) + substate = nua_substate_terminated, what = "terminated"; + else + substate = nua_substate_active, what = "active"; + } + else if (strcasecmp(subs->ss_substate, what = "terminated") == 0) { + substate = nua_substate_terminated; + reason = subs->ss_reason; + + if (str0casecmp(reason, "deactivated") == 0 || + str0casecmp(reason, "probation") == 0) + substate = nua_substate_embryonic; + } + else if (strcasecmp(subs->ss_substate, what = "pending") == 0) { + substate = nua_substate_pending; + } + else /* if (strcasecmp(subs->ss_substate, what = "active") == 0) */ { + /* Any extended state is considered as active */ + what = subs->ss_substate; + substate = nua_substate_active; + } + + eu->eu_substate = substate; + + SU_DEBUG_5(("nua(%p): %s: %s (%s)\n", + (void *)sr->sr_owner, "nua_notify_server_preprocess", + what, reason ? reason : "")); + + return SR_STATUS1(sr, SIP_200_OK); +} + + +int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags) +{ + nua_handle_t *nh = sr->sr_owner; + nua_dialog_usage_t *du = sr->sr_usage; + struct event_usage *eu = nua_dialog_usage_private(du); + sip_t const *sip = sr->sr_request.sip; + enum nua_substate substate = nua_substate_terminated; + sip_time_t delta = SIP_TIME_MAX; + int retry = -1; + int retval; + + if (eu) { + sip_subscription_state_t *subs = sip->sip_subscription_state; + + substate = eu->eu_substate; + + if (substate == nua_substate_active || substate == nua_substate_pending) { + if (subs && subs->ss_expires) + delta = strtoul(subs->ss_expires, NULL, 10); + else + delta = eu->eu_expires; + } + else if (substate == nua_substate_embryonic) { + if (subs && subs->ss_reason) { + if (str0casecmp(subs->ss_reason, "deactivated") == 0) { + retry = 0; /* retry immediately */ + } + else if (str0casecmp(subs->ss_reason, "probation") == 0) { + retry = 30; + if (subs->ss_retry_after) + retry = strtoul(subs->ss_retry_after, NULL, 10); + if (retry > 3600) + retry = 3600; + } + } + } + else if (substate == nua_substate_terminated) { + sr->sr_terminating = 1; + } + } + + retval = nua_base_server_treport(sr, /* can destroy sr */ + NUTAG_SUBSTATE(substate), + TAG_NEXT(tags)); + + if (retval >= 2 || du == NULL) + return retval; + + if (retry >= 0) { /* Try to subscribe again */ + /* XXX - this needs through testing */ + nua_dialog_remove(nh, nh->nh_ds, du); /* tear down */ + nua_dialog_usage_refresh_range(du, retry, retry + 5); + } + else { + nua_dialog_usage_set_refresh(du, delta); + } + + return retval; +} + + /* ======================================================================== */ /* REFER */ @@ -802,81 +721,6 @@ int nua_stack_process_notify(nua_t *nua, * @RFC3515, @ReferTo, @RFC3892, @ReferredBy */ -static int process_response_to_refer(nua_handle_t *nh, - nta_outgoing_t *orq, - sip_t const *sip); - -int -nua_stack_refer(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *tags) -{ - nua_dialog_usage_t *du = NULL; - nua_client_request_t *cr = nh->nh_ds->ds_cr; - msg_t *msg; - sip_t *sip; - sip_referred_by_t by[1]; - sip_event_t *event = NULL; - - if (nua_stack_set_handle_special(nh, nh_has_subscribe, nua_r_subscribe) < 0) - return UA_EVENT2(e, 900, "Invalid handle for REFER"); - else if (cr->cr_orq) - return UA_EVENT2(e, 900, "Request already in progress"); - - nua_stack_init_handle(nua, nh, TAG_NEXT(tags)); - - sip_referred_by_init(by); - by->b_display = nua->nua_from->a_display; - *by->b_url = *nua->nua_from->a_url; - - /* Now we create a REFER request message */ - msg = nua_creq_msg(nua, nh, cr, cr->cr_retry_count, - SIP_METHOD_REFER, - NUTAG_USE_DIALOG(1), - SIPTAG_EVENT(SIP_NONE), /* remove event */ - SIPTAG_REFERRED_BY(by), /* Overriden by user tags */ - NUTAG_ADD_CONTACT(1), - TAG_NEXT(tags)); - sip = sip_object(msg); - - if (sip && sip->sip_cseq) - event = sip_event_format(nh->nh_home, "refer;id=%u", - sip->sip_cseq->cs_seq); - - if (event) - du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, event); - - if (du) - cr->cr_orq = nta_outgoing_mcreate(nua->nua_nta, - process_response_to_refer, nh, NULL, - msg, - SIPTAG_END(), TAG_NEXT(tags)); - - if (!cr->cr_orq) { - if (du) - nua_dialog_usage_remove(nh, nh->nh_ds, du); - su_free(nh->nh_home, event); - msg_destroy(msg); - return UA_EVENT1(e, NUA_INTERNAL_ERROR); - } - - /* - * We send a 100 trying event so that application gets a event - * it can use to match NOTIFYs with its REFER - */ - nua_stack_event(nua, nh, NULL, e, SIP_100_TRYING, - NUTAG_REFER_EVENT(event), - TAG_END()); - su_free(nh->nh_home, event); - - cr->cr_usage = du; - - return cr->cr_event = e; -} - -void restart_refer(nua_handle_t *nh, tagi_t *tags) -{ - nua_stack_refer(nh->nh_nua, nh, nh->nh_ds->ds_cr->cr_event, tags); -} - /**@NUA_EVENT nua_r_refer * * @brief Response to outgoing REFER. @@ -900,27 +744,130 @@ void restart_refer(nua_handle_t *nh, tagi_t *tags) * @END_NUA_EVENT */ -static int process_response_to_refer(nua_handle_t *nh, - nta_outgoing_t *orq, +static int nua_refer_client_init(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_refer_client_request(nua_client_request_t *cr, + msg_t *, sip_t *, + tagi_t const *tags); +static int nua_refer_client_response(nua_client_request_t *cr, + int status, char const *phrase, + sip_t const *sip); + +static nua_client_methods_t const nua_refer_client_methods = { + SIP_METHOD_REFER, + 0, + { + /* create_dialog */ 1, + /* in_dialog */ 1, + /* target refresh */ 1 + }, + /*nua_refer_client_template*/ NULL, + nua_refer_client_init, + nua_refer_client_request, + /* nua_refer_client_check_restart */ NULL, + nua_refer_client_response, + nua_refer_client_response, /* Preliminary */ + NULL +}; + +int +nua_stack_refer(nua_t *nua, nua_handle_t *nh, nua_event_t e, + tagi_t const *tags) +{ + return nua_client_create(nh, e, &nua_refer_client_methods, tags); +} + +static int nua_refer_client_init(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + + if (sip->sip_referred_by == NULL) { + sip_from_t *a = sip->sip_from; + sip_referred_by_t by[1]; + + sip_referred_by_init(by); + + if (a == NULL) + a = nh->nh_nua->nua_from; + by->b_display = a->a_display; + *by->b_url = *a->a_url; + + sip_add_dup(msg, sip, (sip_header_t *)by); + } + + if (sip->sip_event) + sip_header_remove(msg, sip, (sip_header_t *)sip->sip_event); + + return 0; +} + +static int nua_refer_client_request(nua_client_request_t *cr, + msg_t *msg, sip_t *sip, + tagi_t const *tags) +{ + nua_handle_t *nh = cr->cr_owner; + nua_dialog_usage_t *du = cr->cr_usage; + struct event_usage *eu; + sip_event_t *event; + int error; + + cr->cr_usage = NULL; + + if (du) + nua_dialog_usage_remove(nh, nh->nh_ds, du); + + event = sip_event_format(nh->nh_home, "refer;id=%u", sip->sip_cseq->cs_seq); + if (!event) + return -1; + du = nua_dialog_usage_add(nh, nh->nh_ds, nua_subscribe_usage, event); + if (!du) + return -1; + + eu = nua_dialog_usage_private(cr->cr_usage = du); + eu ->eu_refer = 1; + + error = nua_base_client_request(cr, msg, sip, tags); + + if (!error) { + /* Give application an Event header for matching NOTIFYs with REFER */ + nua_stack_tevent(nh->nh_nua, nh, NULL, + cr->cr_event, SIP_100_TRYING, + NUTAG_REFER_EVENT(event), + TAG_END()); + su_free(nh->nh_home, event); + } + + return error; +} + +static int nua_refer_client_response(nua_client_request_t *cr, + int status, char const *phrase, sip_t const *sip) { - nua_client_request_t *cr = nh->nh_ds->ds_cr; - int status = sip ? sip->sip_status->st_status : 408; + nua_dialog_usage_t *du = cr->cr_usage; + enum nua_substate substate = nua_substate_terminated; - if (status < 200) - ; - else if (status < 300) { - if (cr->cr_usage) - cr->cr_usage->du_ready = 1; - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); - nua_dialog_store_peer_info(nh, nh->nh_ds, sip); - } - else /* if (status >= 300) */ { - if (cr->cr_usage) - nua_dialog_usage_remove(nh, nh->nh_ds, cr->cr_usage), cr->cr_usage = NULL; - if (nua_creq_check_restart(nh, cr, orq, sip, restart_refer)) - return 0; - } + if (du) { + struct event_usage *eu = nua_dialog_usage_private(du); - return nua_stack_process_response(nh, cr, orq, sip, TAG_END()); + if (status < 200) { + substate = eu->eu_substate; + } + else if (status < 300) { + sip_refer_sub_t const *rs = sip_refer_sub(sip); + + if (rs && strcasecmp("false", rs->rs_value) == 0) + cr->cr_terminated = 1; + + if (!cr->cr_terminated) + substate = eu->eu_substate; + } + } + + return nua_base_client_tresponse(cr, status, phrase, sip, + NUTAG_SUBSTATE(substate), + TAG_END()); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c index b900f666e0..14979b8463 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_tag.c @@ -68,6 +68,7 @@ tag_typedef_t nutag_answer_recv = BOOLTAG_TYPEDEF(answer_recv); tag_typedef_t nutag_offer_sent = BOOLTAG_TYPEDEF(offer_sent); tag_typedef_t nutag_answer_sent = BOOLTAG_TYPEDEF(answer_sent); tag_typedef_t nutag_substate = INTTAG_TYPEDEF(substate); +tag_typedef_t nutag_newsub = BOOLTAG_TYPEDEF(newsub); tag_typedef_t nutag_invite_timer = UINTTAG_TYPEDEF(invite_timer); tag_typedef_t nutag_session_timer = UINTTAG_TYPEDEF(session_timer); tag_typedef_t nutag_min_se = UINTTAG_TYPEDEF(min_se); @@ -147,6 +148,3 @@ tag_typedef_t nutag_service_route_enable = tag_typedef_t nutag_detect_network_updates = UINTTAG_TYPEDEF(detect_network_updates); tag_typedef_t nutag_with = PTRTAG_TYPEDEF(with); - -tag_typedef_t _nutag_add_contact = BOOLTAG_TYPEDEF(add_contact); -tag_typedef_t _nutag_copy = BOOLTAG_TYPEDEF(copy); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c index eb86716cbe..2713cfb41d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c @@ -294,7 +294,8 @@ int outbound_set_options(outbound_t *ob, else if (MATCH(use-upnp) || MATCH(use_upnp)) prefs->use_upnp = value; else if (MATCH(use-stun) || MATCH(use_stun)) prefs->use_stun = value; else - SU_DEBUG_1(("outbound_t: unknown option \"%.*s\"\n", (int)len, s)); + SU_DEBUG_1(("outbound(%p): unknown option \"%.*s\"\n", + (void *)ob->ob_owner, (int)len, s)); s += len; len = strspn(s, " \t\n\r,;"); @@ -304,7 +305,8 @@ int outbound_set_options(outbound_t *ob, } if (s && s[0]) { - SU_DEBUG_1(("outbound_t: invalid options \"%s\"\n", options)); + SU_DEBUG_1(("outbound(%p): invalid options \"%s\"\n", + (void *)ob->ob_owner, options)); return -1; } @@ -315,7 +317,8 @@ int outbound_set_options(outbound_t *ob, prefs->use_socks || prefs->use_upnp || prefs->use_stun)) { - SU_DEBUG_1(("outbound(%p): no nat traversal method given\n", ob->ob_owner)); + SU_DEBUG_1(("outbound(%p): no nat traversal method given\n", + (void *)ob->ob_owner)); } ob->ob_prefs = *prefs; @@ -340,44 +343,25 @@ int outbound_set_features(outbound_t *ob, char *features) /* ---------------------------------------------------------------------- */ -/** Hook for sending register request with extra outbound-ish headers. */ -nta_outgoing_t *outbound_register_request(outbound_t *ob, int terminating, - sip_contact_t *stack_contact, - nta_agent_t *nta, - nta_response_f *callback, - nta_outgoing_magic_t *magic, - url_string_t *next_hop, - msg_t *msg, - tag_type_t tag, tag_value_t value, - ...) +/** Obtain contacts for REGISTER */ +int outbound_get_contacts(outbound_t *ob, + sip_contact_t **return_current_contact, + sip_contact_t **return_previous_contact) { - sip_contact_t *previous_contact = NULL; - ta_list ta; - nta_outgoing_t *orq; - - if (stack_contact) { - if (ob) { - if (ob->ob_contacts) - stack_contact = ob->ob_rcontact; - previous_contact = ob->ob_previous; - } + if (ob) { + if (ob->ob_contacts) + *return_current_contact = ob->ob_rcontact; + *return_previous_contact = ob->ob_previous; } + return 0; +} - ta_start(ta, tag, value); - - orq = nta_outgoing_mcreate(nta, callback, magic, next_hop, msg, - TAG_IF(previous_contact, - SIPTAG_CONTACT(previous_contact)), - TAG_IF(stack_contact, - SIPTAG_CONTACT(stack_contact)), - ta_tags(ta)); - - ta_end(ta); - - if (orq && ob) +/** REGISTER request has been sent */ +int outbound_start_registering(outbound_t *ob) +{ + if (ob) ob->ob_registering = 1; - - return orq; + return 0; } /** Process response to REGISTER request */ @@ -391,17 +375,16 @@ int outbound_register_response(outbound_t *ob, if (!ob) return 0; - assert(!request || request->sip_request); - assert(!response || response->sip_status); - - if (!response || !request) - return 0; - if (terminating) { - ob->ob_registered = ob->ob_registering = 0; + ob->ob_registering = ob->ob_registered = 0; return 0; /* Cleanup is done separately */ } + if (!response || !request) + return 0; + + assert(request->sip_request); assert(response->sip_status); + reregister = outbound_check_for_nat(ob, request, response); if (reregister) return reregister; @@ -423,7 +406,13 @@ int outbound_register_response(outbound_t *ob, } -/** @internal Check if there is a NAT between us and registrar */ +/** @internal Check if there is a NAT between us and registrar. + * + * @retval -1 upon an error + * @retval #ob_register_ok (0) if the registration was OK + * @retval #ob_reregister (1) if client needs to re-register + * @retval #ob_reregister_now (2) if client needs to re-register immediately + */ static int outbound_check_for_nat(outbound_t *ob, sip_t const *request, @@ -457,11 +446,11 @@ int outbound_check_for_nat(outbound_t *ob, if (!m || binding_changed >= ob_nat_changed) { if (ob->ob_stun) { /* Use STUN? */ - return 1; + return ob_reregister; } else if (ob->ob_upnp) { /* Use UPnP */ - return 1; + return ob_reregister; } else { if (outbound_contacts_from_via(ob, response->sip_via) < 0) @@ -512,7 +501,7 @@ int outbound_nat_detect(outbound_t *ob, if (!host_is_ip_address(received)) { if (received[0]) SU_DEBUG_3(("outbound(%p): Via with invalid received=%s\n", - ob->ob_owner, received)); + (void *)ob->ob_owner, received)); return 0; } @@ -530,14 +519,14 @@ int outbound_nat_detect(outbound_t *ob, if (!nat_detected) { SU_DEBUG_1(("outbound(%p): detected NAT: %s != %s\n", - ob->ob_owner, v->v_host, received)); + (void *)ob->ob_owner, v->v_host, received)); if (ob->ob_oo && ob->ob_oo->oo_status) ob->ob_oo->oo_status(ob->ob_owner, ob, 101, "NAT detected", TAG_END()); } else { SU_DEBUG_1(("outbound(%p): NAT binding changed: " "[%s]:%s != [%s]:%s\n", - ob->ob_owner, nat_detected, nat_port, received, rport)); + (void *)ob->ob_owner, nat_detected, nat_port, received, rport)); if (ob->ob_oo && ob->ob_oo->oo_status) ob->ob_oo->oo_status(ob->ob_owner, ob, 102, "NAT binding changed", TAG_END()); } @@ -877,18 +866,19 @@ static int response_to_keepalive_options(outbound_t *ob, if (loglevel >= SU_LOG->log_level) { su_llog(SU_LOG, loglevel, "outbound(%p): %s <" URL_PRINT_FORMAT ">\n", - ob->ob_owner, failed ? "FAILED to validate" : "validated", + (void *)ob->ob_owner, + failed ? "FAILED to validate" : "validated", URL_PRINT_ARGS(ob->ob_rcontact->m_url)); if (failed) su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n", - ob->ob_owner, status, phrase); + (void *)ob->ob_owner, status, phrase); } if (failed) ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END()); } else if (status == 408) { - SU_DEBUG_1(("outbound(%p): keepalive timeout\n", ob->ob_owner)); + SU_DEBUG_1(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner)); ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END()); return 0; } @@ -982,7 +972,7 @@ int outbound_process_request(outbound_t *ob, if (ob->ob_keepalive.validating) { SU_DEBUG_1(("outbound(%p): registration check OPTIONS received\n", - ob->ob_owner)); + (void *)ob->ob_owner)); ob->ob_keepalive.validated = 1; } @@ -1037,8 +1027,6 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via) dcontact = sip_contact_make(home, uri); - - if (ob->ob_instance) { char reg_id[20]; @@ -1172,9 +1160,11 @@ int outbound_set_contact(outbound_t *ob, previous = ob->ob_contacts ? ob->ob_rcontact : NULL; } } - + ob->ob_by_stack = application_contact == NULL; + ob->ob_contacts = rcontact != NULL; + ob->ob_rcontact = rcontact; ob->ob_dcontact = dcontact; ob->ob_previous = previous; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h index b6561fedbf..b86994686d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/outbound.h @@ -72,15 +72,11 @@ int outbound_set_options(outbound_t *ob, int outbound_set_features(outbound_t *ob, char *features); -nta_outgoing_t *outbound_register_request(outbound_t *ob, int terminating, - sip_contact_t *stack_contact, - nta_agent_t *nta, - nta_response_f *callback, - nta_outgoing_magic_t *magic, - url_string_t *next_hop, - msg_t *msg, - tag_type_t tag, tag_value_t value, - ...); +int outbound_get_contacts(outbound_t *ob, + sip_contact_t **return_current_contact, + sip_contact_t **return_previous_contact); + +int outbound_start_registering(outbound_t *ob); int outbound_register_response(outbound_t *ob, int terminating, diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h b/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h index 277e606c32..d292e08f53 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h @@ -262,6 +262,12 @@ SOFIAPUBFUN char const *nua_event_name(nua_event_t event); /** Get name for NUA callstate. */ SOFIAPUBFUN char const *nua_callstate_name(enum nua_callstate state); +/** Return name of subscription state. @NEW_1_12_5. */ +SOFIAPUBFUN char const *nua_substate_name(enum nua_substate substate); + +/** Convert string to enum nua_substate. @NEW_1_12_5. */ +SOFIAPUBFUN enum nua_substate nua_substate_make(char const *sip_substate); + /** Send SIP REGISTER request to the registrar. */ SOFIAPUBFUN void nua_register(nua_handle_t *nh, tag_type_t, tag_value_t, ...); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h b/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h index 059cc92c5c..39b17a4e57 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h @@ -1327,6 +1327,7 @@ SOFIAPUBVAR tag_typedef_t nutag_authtime_ref; * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params(). + * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) @@ -1358,6 +1359,7 @@ SOFIAPUBVAR tag_typedef_t nutag_m_display_ref; * * @par Used with * nua_register(), nua_set_hparams(), nua_set_params(). + * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) @@ -1388,7 +1390,8 @@ SOFIAPUBVAR tag_typedef_t nutag_m_username_ref; * user-agent. * * @par Used with - * nua_register(), nua_set_hparams(), nua_set_params(). + * nua_register(), nua_set_hparams(), nua_set_params(), + * nua_invite(), nua_respond(), nua_subscribe(), nua_notify() * * @par Parameter type * string (char *) @@ -1859,26 +1862,39 @@ enum nua_callstate { /** Get name for NUA call state */ SOFIAPUBFUN char const *nua_callstate_name(enum nua_callstate state); -/** Subscription state +/**Subscription state. * * @par Used with + * #nua_notify() \n * #nua_r_subscribe \n - * #nua_i_notify + * #nua_i_notify \n + * #nua_i_subscribe \n + * #nua_r_notify \n + * nua_notify() \n + * nua_respond() to SUBSCRIBE * * @par Parameter type * int * * @par Values - * @c nua_substate_embryonic (0) \n - * @c nua_substate_pending (1) \n - * @c nua_substate_active (2) \n - * @c nua_substate_terminated (3) \n + * - #nua_substate_embryonic (0) + * - #nua_substate_pending (1) + * - #nua_substate_active (2) + * - #nua_substate_terminated (3) * - * see - * RFC 3265 + * Note that the @SubscriptionState or @Expires headers specified by + * application overrides the subscription state specified by + * NUTAG_SUBSTATE(). Application can terminate subscription by including + * NUTAG_SUBSTATE(nua_substate_terminated), @SubscriptionState with value + * "terminated" or @Expires header with value 0 in the NOTIFY request sent + * by nua_notify(). + * + * @sa @RFC3265, @SubscriptionState, SIPTAG_SUBSCRIPTION_STATE(), + * SIPTAG_SUBSCRIPTION_STATE_STR(), #nua_r_subscribe, #nua_i_subscribe, + * #nua_i_refer, #nua_r_notify, #nua_i_notify. * * Corresponding tag taking reference parameter is NUTAG_SUBSTATE_REF() -*/ + */ #define NUTAG_SUBSTATE(x) nutag_substate, tag_int_v(x) SOFIAPUBVAR tag_typedef_t nutag_substate; @@ -1896,6 +1912,46 @@ enum nua_substate { nua_substate_terminated = nea_terminated /**< Terminated subscription */ }; +/** Return name of subscription state. @NEW_1_12_5. */ +SOFIAPUBFUN char const *nua_substate_name(enum nua_substate substate); + +/** Convert string to enum nua_substate. @NEW_1_12_5. */ +SOFIAPUBFUN enum nua_substate nua_substate_make(char const *sip_substate); + +/**Send unsolicited NOTIFY request. + * + * Some applications may require sending unsolicited NOTIFY requests, that + * is, NOTIFY without SUBSCRIBE or REFER request sent by event watcher. + * However, sending NOTIFY request requires an existing dialog usage by + * default. If NUTAG_NEWSUB(1) is included in the nua_notify() the usage + * is create the usage by itself. + * + * If you want to create a subscription that does not terminate immediately + * include SIPTAG_SUBSCRIPTION_STATE_STR() with an "expires" parameter in + * the argument list, too. + * + * @par Used with + * nua_notify() + * + * @par Parameter type + * int (boolean) + * + * @par Values + * - 0 - false (default) - do not create new subscription + * but reject NOTIFY with 481 locally \n + * - 1 - true - create a subscription if it does not exist \n + * + * Corresponding tag taking reference parameter is NUTAG_NEWSUB(). + * + * @since @NEW_1_12_5. + */ +#define NUTAG_NEWSUB(x) nutag_newsub, tag_bool_v(x) +SOFIAPUBVAR tag_typedef_t nutag_newsub; + +#define NUTAG_NEWSUB_REF(x) nutag_newsub_ref, tag_bool_vr(&(x)) +SOFIAPUBVAR tag_typedef_t nutag_newsub_ref; + + /**Default lifetime for implicit subscriptions created by REFER. * * Default expiration time in seconds for implicit subscriptions created by diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c index 420031ce28..2c18dfd85d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_100rel.c @@ -1590,5 +1590,25 @@ int test_100rel(struct context *ctx) retval = test_preconditions2(ctx); RETURN_ON_SINGLE_FAILURE(retval); retval = test_update_by_uas(ctx); RETURN_ON_SINGLE_FAILURE(retval); + nua_set_params(ctx->a.nua, + NUTAG_EARLY_MEDIA(0), + SIPTAG_SUPPORTED(ctx->a.supported), + TAG_END()); + run_a_until(ctx, nua_r_set_params, until_final_response); + + nua_set_params(ctx->b.nua, + NUTAG_EARLY_MEDIA(0), + NUTAG_ONLY183_100REL(0), + SIPTAG_SUPPORTED(ctx->b.supported), + TAG_END()); + run_b_until(ctx, nua_r_set_params, until_final_response); + + nua_set_params(ctx->c.nua, + NUTAG_EARLY_MEDIA(0), + NUTAG_ONLY183_100REL(0), + SIPTAG_SUPPORTED(ctx->c.supported), + TAG_END()); + run_c_until(ctx, nua_r_set_params, until_final_response); + return retval; } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c index d48d11732a..35c1c159f7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c @@ -117,6 +117,8 @@ int accept_call_with_early_sdp(CONDITION_PARAMS) case nua_callstate_received: RESPOND(ep, call, nh, SIP_180_RINGING, TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)), + NUTAG_M_DISPLAY("Bob"), + NUTAG_M_USERNAME("b+b"), TAG_END()); return 0; case nua_callstate_early: @@ -217,6 +219,8 @@ int test_basic_call_1(struct context *ctx) INVITE(a, a_call, a_call->nh, TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), SOATAG_USER_SDP_STR(a_call->sdp), + NUTAG_M_USERNAME("a+a"), + NUTAG_M_DISPLAY("Alice"), TAG_END()); run_ab_until(ctx, -1, until_ready, -1, accept_call_with_early_sdp); @@ -263,8 +267,11 @@ int test_basic_call_1(struct context *ctx) TEST_1(is_answer_recv(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 200); - TEST_1(sip->sip_payload); TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_payload); + TEST_1(sip->sip_contact); + TEST_S(sip->sip_contact->m_display, "Bob"); + TEST_S(sip->sip_contact->m_url->url_user, "b+b"); /* Test that B uses application-specific contact */ if (ctx->proxy_tests) TEST_1(sip->sip_contact->m_url->url_user); @@ -282,6 +289,10 @@ int test_basic_call_1(struct context *ctx) */ TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); TEST(e->data->e_status, 100); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_contact); + TEST_S(sip->sip_contact->m_display, "Alice"); + TEST_S(sip->sip_contact->m_url->url_user, "a+a"); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ TEST_1(is_offer_recv(e->data->e_tags)); @@ -404,6 +415,7 @@ int test_basic_call_2(struct context *ctx) INVITE(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), SOATAG_USER_SDP_STR(a_call->sdp), + NUTAG_ALLOW("INFO"), TAG_END()); run_ab_until(ctx, -1, until_ready, -1, accept_early_answer); @@ -466,32 +478,55 @@ int test_basic_call_2(struct context *ctx) TEST_1(nua_handle_has_active_call(b_call->nh)); TEST_1(!nua_handle_has_call_on_hold(b_call->nh)); + INFO(b, b_call, b_call->nh, TAG_END()); BYE(b, b_call, b_call->nh, TAG_END()); + INFO(b, b_call, b_call->nh, TAG_END()); + run_ab_until(ctx, -1, until_terminated, -1, until_terminated); + while (!b->events->head || /* r_info */ + !b->events->head->next || /* r_bye */ + !b->events->head->next->next || /* i_state */ + !b->events->head->next->next->next) /* r_info */ + run_ab_until(ctx, -1, save_events, -1, save_until_final_response); + /* B transitions: + nua_info() READY --(T2)--> TERMINATING: nua_bye() + nua_r_info with 200 TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state + nua_r_info with 481/900 */ - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_bye); + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_info); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_info); + TEST_1(e->data->e_status >= 900 || e->data->e_status == 481); TEST_1(!e->next); free_events_in_list(ctx, b->events); TEST_1(!nua_handle_has_active_call(b_call->nh)); /* A transitions: + nua_i_info READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state */ - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_bye); + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_info); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye); TEST(e->data->e_status, 200); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ TEST_1(!e->next); free_events_in_list(ctx, a->events); - TEST_1(!nua_handle_has_active_call(a_call->nh)); + BYE(a, a_call, a_call->nh, TAG_END()); + run_a_until(ctx, -1, save_until_final_response); + + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_bye); + TEST_1(e->data->e_status >= 900); + TEST_1(!e->next); + free_events_in_list(ctx, a->events); nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c index a3f18ff9e1..075b72793f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_call_reject.c @@ -638,11 +638,12 @@ int test_reject_401(struct context *ctx) TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_invite); + TEST(e->data->e_status, 100); TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_proxy_authorization); + /* Ensure that nua_authenticate() tags get added to the request */ TEST_1(sip->sip_subject); TEST_S(sip->sip_subject->g_value, "Got 407"); - TEST_1(sip->sip_proxy_authorization); - TEST(e->data->e_status, 100); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ TEST_1(is_offer_recv(e->data->e_tags)); @@ -911,7 +912,7 @@ int test_mime_negotiation(struct context *ctx) /* Client transitions in reject-3: - INIT -(C1)-> PROCEEDING -(C6a)-> TERMINATED + INIT -(C1)-> CALLING -(C6a)-> TERMINATED */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state); @@ -927,7 +928,7 @@ int test_mime_negotiation(struct context *ctx) /* No content-encoding is supported */ TEST_S(sip->sip_accept_encoding->aa_value, ""); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* CALLING */ + TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ TEST_1(!e->next); free_events_in_list(ctx, a->events); @@ -944,3 +945,316 @@ int test_mime_negotiation(struct context *ctx) END(); } + +/* ---------------------------------------------------------------------- */ + +size_t filter_200_OK(void *message, size_t len) +{ + if (len >= 11 && strncasecmp(message, "SIP/2.0 200", 11) == 0) + return 0; + return len; +} + +size_t filter_ACK(void *message, size_t len) +{ + if (len >= 7 && strncasecmp(message, "ACK sip", 7) == 0) + return 0; + return len; +} + +int call_with_bad_ack(CONDITION_PARAMS); +int accept_call_with_bad_contact(CONDITION_PARAMS); + +int test_call_timeouts(struct context *ctx) +{ + BEGIN(); + + struct endpoint *a = &ctx->a, *b = &ctx->b; + struct call *a_call = a->call, *b_call = b->call; + struct event *e; + struct nat_filter *f; + + if (print_headings) + printf("TEST NUA-4.7: check for error and timeout handling\n"); + + a_call->sdp = "m=audio 5008 RTP/AVP 8"; + b_call->sdp = "m=audio 5010 RTP/AVP 0 8"; + + if (!ctx->nat) + goto completed_4_7_1; + + if (print_headings) + printf("TEST NUA-4.7.1: ACK timeout (200 OK filtered)\n"); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + TEST_1(f = test_nat_add_filter(ctx->nat, filter_200_OK, nat_inbound)); + + INVITE(a, a_call, a_call->nh, + TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), + SIPTAG_SUBJECT_STR("NUA-4.7.1"), + SOATAG_USER_SDP_STR(a_call->sdp), + TAG_END()); + run_ab_until(ctx, -1, until_terminated, -1, accept_call); + + /* + A accept_call B + | | + |-------INVITE------>| + |<----100 Trying-----| + | | + |<----180 Ringing----| + | | + | X-----200--------| + | X-----200--------| + | X-----200--------| + | | + |<--------BYE--------| + |--------200 OK----->| + + */ + + /* + Client transitions: + */ + + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 180); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ + TEST_1(!e->next); + + /* + Server transitions: + -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING + -(S10)-> TERMINATED -X + */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); + TEST(e->data->e_status, 100); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ + TEST_1(is_offer_recv(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ + TEST_1(is_answer_sent(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_error); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminating); /* TERMINATING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + free_events_in_list(ctx, b->events); + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + TEST_1(test_nat_remove_filter(ctx->nat, f) == 0); + + if (print_headings) + printf("TEST NUA-4.7.1: PASSED\n"); + + completed_4_7_1: + + if (!ctx->nat) + goto completed_4_7_2; + + if (print_headings) + printf("TEST NUA-4.7.2: ACK timeout (ACK filtered)\n"); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + TEST_1(f = test_nat_add_filter(ctx->nat, filter_ACK, nat_outbound)); + + INVITE(a, a_call, a_call->nh, + TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), + SIPTAG_SUBJECT_STR("NUA-4.7.2"), + SOATAG_USER_SDP_STR(a_call->sdp), + TAG_END()); + run_ab_until(ctx, -1, until_terminated, -1, accept_call); + + /* + A accept_call B + | | + |-------INVITE------>| + |<----100 Trying-----| + | | + |<----180 Ringing----| + | | + |<--------200--------| + |--------ACK-----X | + | | + |<--------200--------| + |--------ACK-----X | + | | + |<--------200--------| + |--------ACK-----X | + | | + |<--------BYE--------| + |--------200 OK----->| + + */ + + /* + */ + + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 180); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_proceeding); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 200); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); + TEST_1(!e->next); + + /* + Server transitions: + -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING + -(S10)-> TERMINATED -X + */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); + TEST(e->data->e_status, 100); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ + TEST_1(is_offer_recv(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ + TEST_1(is_answer_sent(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_error); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminating); /* TERMINATING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + free_events_in_list(ctx, b->events); + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + TEST_1(test_nat_remove_filter(ctx->nat, f) == 0); + + if (print_headings) + printf("TEST NUA-4.7.2: PASSED\n"); + + completed_4_7_2: + + if (print_headings) + printf("TEST NUA-4.7.3: sending ACK fails\n"); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + INVITE(a, a_call, a_call->nh, + TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), + SIPTAG_SUBJECT_STR("NUA-4.7.3"), + SOATAG_USER_SDP_STR(a_call->sdp), + NUTAG_AUTOACK(0), + TAG_END()); + run_ab_until(ctx, -1, call_with_bad_ack, -1, accept_call); + + /* + A accept_call B + | | + |-------INVITE------>| + |<----100 Trying-----| + | | + |<----180 Ringing----| + | | + |<--------200--------| + |--ACK-X | + | | + |---------BYE------->| + |<-------200 OK------| + + */ + + /* + */ + + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 180); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_proceeding); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 200); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_completing); /* COMPLETING */ + /* try to send ACK */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminating); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); + TEST_1(!e->next); + + /* + Server transitions: + -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S5)-> TERMINATING + -(S10)-> TERMINATED -X + */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); + TEST(e->data->e_status, 100); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ + TEST_1(is_offer_recv(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ + TEST_1(is_answer_sent(e->data->e_tags)); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + free_events_in_list(ctx, b->events); + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + if (print_headings) + printf("TEST NUA-4.7.3: PASSED\n"); + + /* XXX - PRACK timeout, PRACK failing, media failing, re-INVITEs */ + + if (print_headings) + printf("TEST NUA-4.7: PASSED\n"); + + END(); +} + +int call_with_bad_ack(CONDITION_PARAMS) +{ + if (!check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)) + return 0; + + save_event_in_list(ctx, event, ep, call); + + if (event == nua_r_invite && 200 <= status && status < 300) { + ACK(ep, call, nh, + /* Syntax error - sending ACK fails, we send BYE */ + SIPTAG_MAX_FORWARDS_STR("blue"), + TAG_END()); + } + + return event == nua_i_state && callstate(tags) == nua_callstate_terminated; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c index 76f9a9575f..71577509a2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c @@ -496,13 +496,13 @@ int destroy_when_early(CONDITION_PARAMS) return 0; case nua_callstate_early: if (call) - nua_handle_destroy(call->nh), call->nh = NULL; + DESTROY(ep, call, nh), call->nh = NULL; return 1; case nua_callstate_completed: case nua_callstate_ready: case nua_callstate_terminated: if (call) - nua_handle_destroy(call->nh), call->nh = NULL; + DESTROY(ep, call, nh), call->nh = NULL; return 1; default: return 0; @@ -594,7 +594,7 @@ int destroy_when_completed(CONDITION_PARAMS) case nua_callstate_ready: case nua_callstate_terminated: if (call) - nua_handle_destroy(call->nh), call->nh = NULL; + DESTROY(ep, call, nh), call->nh = NULL; return 1; default: return 0; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_extension.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_extension.c index e1460e1460..79aac676cb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_extension.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_extension.c @@ -167,6 +167,13 @@ int test_extension(struct context *ctx) free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; + nua_set_params(b->nua, + SIPTAG_ALLOW(b->allow), + NUTAG_APPL_METHOD(NULL), + NUTAG_APPL_METHOD(b->appl_method), + TAG_END()); + run_b_until(ctx, nua_r_set_params, until_final_response); + if (print_headings) printf("TEST NUA-13.1: PASSED\n"); END(); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c index 2b960d1a7b..ffab6585a2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_init.c @@ -35,6 +35,8 @@ #include "test_nua.h" +#include + #if HAVE_FUNC #elif HAVE_FUNCTION #define __func__ __FUNCTION__ @@ -65,6 +67,9 @@ int test_nua_init(struct context *ctx, struct event *e; sip_contact_t const *m = NULL; sip_from_t const *sipaddress = NULL; + sip_allow_t const *allow = NULL; + sip_supported_t const *supported = NULL; + char const *appl_method = NULL; url_t const *p_uri, *a_uri; /* Proxy URI */ char const *a_bind, *a_bind2; @@ -106,6 +111,7 @@ int test_nua_init(struct context *ctx, AUTHTAG_DB(passwd_name), AUTHTAG_QOP("auth-int"), AUTHTAG_ALGORITHM("md5-sess"), + TAG_IF(ctx->proxy_logging, TPTAG_LOG(1)), TAG_END()); ctx->proxy_tests = ctx->p != NULL; @@ -218,22 +224,29 @@ int test_nua_init(struct context *ctx, NUTAG_URL(a_bind), TAG_IF(a_bind != a_bind2, NUTAG_SIPS_URL(a_bind2)), SOATAG_USER_SDP_STR("m=audio 5004 RTP/AVP 0 8"), - NTATAG_SIP_T1X64(4000), + NTATAG_SIP_T1X64(2000), NUTAG_INSTANCE(ctx->a.instance), + TAG_IF(ctx->a.logging, TPTAG_LOG(1)), TAG_END()); TEST_1(ctx->a.nua); nua_get_params(ctx->a.nua, TAG_ANY(), TAG_END()); run_a_until(ctx, nua_r_get_params, save_until_final_response); - TEST_1(e = ctx->a.events->head); + TEST_1(e = ctx->a.specials->head); TEST(tl_gets(e->data->e_tags, NTATAG_CONTACT_REF(m), SIPTAG_FROM_REF(sipaddress), - TAG_END()), 2); TEST_1(m); + SIPTAG_ALLOW_REF(allow), + NUTAG_APPL_METHOD_REF(appl_method), + SIPTAG_SUPPORTED_REF(supported), + TAG_END()), 5); TEST_1(m); TEST_1(ctx->a.contact = sip_contact_dup(ctx->home, m)); TEST_1(ctx->a.to = sip_to_dup(ctx->home, sipaddress)); + TEST_1(ctx->a.allow = sip_allow_dup(ctx->home, allow)); + TEST_1(ctx->a.appl_method = su_strdup(ctx->home, appl_method)); + TEST_1(ctx->a.supported = sip_supported_dup(ctx->home, supported)); - free_events_in_list(ctx, ctx->a.events); + free_events_in_list(ctx, ctx->a.specials); if (print_headings) printf("TEST NUA-2.2.1: PASSED\n"); @@ -249,19 +262,30 @@ int test_nua_init(struct context *ctx, NUTAG_URL("sip:0.0.0.0:*"), SOATAG_USER_SDP_STR("m=audio 5006 RTP/AVP 8 0"), NUTAG_INSTANCE(ctx->b.instance), + /* Quicker timeout */ + NTATAG_SIP_T1X64(2000), + TAG_IF(ctx->b.logging, TPTAG_LOG(1)), TAG_END()); TEST_1(ctx->b.nua); nua_get_params(ctx->b.nua, TAG_ANY(), TAG_END()); run_b_until(ctx, nua_r_get_params, save_until_final_response); - TEST_1(e = ctx->b.events->head); + TEST_1(e = ctx->b.specials->head); TEST(tl_gets(e->data->e_tags, NTATAG_CONTACT_REF(m), SIPTAG_FROM_REF(sipaddress), - TAG_END()), 2); TEST_1(m); + SIPTAG_ALLOW_REF(allow), + NUTAG_APPL_METHOD_REF(appl_method), + SIPTAG_SUPPORTED_REF(supported), + TAG_END()), 5); TEST_1(m); + TEST_1(ctx->b.contact = sip_contact_dup(ctx->home, m)); TEST_1(ctx->b.to = sip_to_dup(ctx->home, sipaddress)); - free_events_in_list(ctx, ctx->b.events); + TEST_1(ctx->b.allow = sip_allow_dup(ctx->home, allow)); + TEST_1(ctx->b.appl_method = su_strdup(ctx->home, appl_method)); + TEST_1(ctx->b.supported = sip_supported_dup(ctx->home, supported)); + + free_events_in_list(ctx, ctx->b.specials); if (print_headings) printf("TEST NUA-2.2.2: PASSED\n"); @@ -277,19 +301,26 @@ int test_nua_init(struct context *ctx, NUTAG_URL("sip:0.0.0.0:*"), SOATAG_USER_SDP_STR("m=audio 5400 RTP/AVP 8 0"), NUTAG_INSTANCE(ctx->c.instance), + TAG_IF(ctx->c.logging, TPTAG_LOG(1)), TAG_END()); TEST_1(ctx->c.nua); nua_get_params(ctx->c.nua, TAG_ANY(), TAG_END()); run_c_until(ctx, nua_r_get_params, save_until_final_response); - TEST_1(e = ctx->c.events->head); + TEST_1(e = ctx->c.specials->head); TEST(tl_gets(e->data->e_tags, NTATAG_CONTACT_REF(m), SIPTAG_FROM_REF(sipaddress), - TAG_END()), 2); TEST_1(m); + SIPTAG_ALLOW_REF(allow), + NUTAG_APPL_METHOD_REF(appl_method), + SIPTAG_SUPPORTED_REF(supported), + TAG_END()), 5); TEST_1(m); TEST_1(ctx->c.contact = sip_contact_dup(ctx->home, m)); TEST_1(ctx->c.to = sip_to_dup(ctx->home, sipaddress)); - free_events_in_list(ctx, ctx->c.events); + TEST_1(ctx->c.allow = sip_allow_dup(ctx->home, allow)); + TEST_1(ctx->c.appl_method = su_strdup(ctx->home, appl_method)); + TEST_1(ctx->c.supported = sip_supported_dup(ctx->home, supported)); + free_events_in_list(ctx, ctx->c.specials); if (print_headings) printf("TEST NUA-2.2.3: PASSED\n"); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.c index 936810132d..f5fb91863b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.c @@ -91,6 +91,8 @@ struct nat { struct binding *bindings; + struct nat_filter *in_filters, *out_filters; + /* True if we act in symmetric way */ int symmetric; /* True if we do logging */ @@ -153,6 +155,14 @@ static int tcp_out_to_in(struct nat *, su_wait_t *wait, struct binding *); static int invalidate_binding(struct binding *b); +LIST_PROTOS(static, nat_filter, struct nat_filter); + +struct nat_filter +{ + struct nat_filter *next, **prev; + size_t (*condition)(void *message, size_t len); +}; + /* nat entry point */ static int test_nat_init(su_root_t *root, struct nat *nat) @@ -670,19 +680,35 @@ static int udp_in_to_out(struct nat *nat, su_wait_t *wait, struct binding *b) { int events; ssize_t n, m; + size_t len, filtered; + struct nat_filter *f; events = su_wait_events(wait, b->in_socket); n = su_recv(b->in_socket, nat->buffer, sizeof nat->buffer, 0); - if (n < 0) { + if (n == -1) { su_perror("udp_in_to_out: recv"); return 0; } + len = (size_t)n; + + for (f = nat->out_filters; f; f = f->next) { + filtered = f->condition(nat->buffer, len); + if (filtered != len) { + if (nat->logging) + printf("nat: udp filtered "MOD_ZU" from %s => "MOD_ZU" to %s\n", + len, b->in_name, filtered, b->out_name); + if (filtered == 0) + return 0; + len = filtered; + } + } + if (nat->symmetric) - m = su_send(b->out_socket, nat->buffer, n, 0); + m = su_send(b->out_socket, nat->buffer, len, 0); else - m = su_sendto(b->out_socket, nat->buffer, n, 0, + m = su_sendto(b->out_socket, nat->buffer, len, 0, nat->out_address, nat->out_addrlen); if (nat->logging) @@ -696,6 +722,8 @@ static int udp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b) { int events; ssize_t n, m; + size_t len, filtered; + struct nat_filter *f; events = su_wait_events(wait, b->out_socket); @@ -705,6 +733,20 @@ static int udp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b) return 0; } + len = (size_t)n; + + for (f = nat->in_filters; f; f = f->next) { + filtered = f->condition(nat->buffer, len); + if (filtered != len) { + if (nat->logging) + printf("nat: udp filtered "MOD_ZU" from %s => "MOD_ZU" to %s\n", + len, b->out_name, filtered, b->in_name); + if (filtered == 0) + return 0; + len = filtered; + } + } + m = su_send(b->in_socket, nat->buffer, n, 0); if (nat->logging) @@ -882,3 +924,72 @@ static int invalidate_binding(struct binding *b) return 0; } + +LIST_BODIES(static, nat_filter, struct nat_filter, next, prev); + +struct args { + struct nat *nat; + struct nat_filter *f; + int outbound; +}; + +int execute_nat_filter_insert(void *_args) +{ + struct args *a = (struct args *)_args; + if (a->outbound) + nat_filter_insert(&a->nat->out_filters, a->f); + else + nat_filter_insert(&a->nat->in_filters, a->f); + return 0; +} + +int execute_nat_filter_remove(void *_args) +{ + struct args *a = (struct args *)_args; + nat_filter_remove(a->f); + return 0; +} + +struct nat_filter *test_nat_add_filter(struct nat *nat, + size_t (*condition)(void *message, + size_t len), + int outbound) +{ + struct args a[1]; + + if (nat == NULL) + return su_seterrno(EFAULT), NULL; + + a->nat = nat; + a->f = su_zalloc(nat->home, sizeof *a->f); + a->outbound = outbound; + + if (a->f) { + a->f->condition = condition; + if (su_task_execute(su_clone_task(nat->clone), + execute_nat_filter_insert, a, NULL) < 0) + su_free(nat->home, a->f), a->f = NULL; + } + + return a->f; +} + + +int test_nat_remove_filter(struct nat *nat, + struct nat_filter *filter) +{ + struct args a[1]; + + if (nat == NULL) + return su_seterrno(EFAULT); + + a->nat = nat; + a->f = filter; + + if (su_task_execute(su_clone_task(nat->clone), + execute_nat_filter_remove, a, NULL) < 0) + return -1; + + su_free(nat->home, filter); + return 0; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.h index 08f98efa7d..b54a9ce2cc 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nat.h @@ -31,6 +31,7 @@ SOFIA_BEGIN_DECLS struct nat; +struct nat_filter; struct nat *test_nat_create(su_root_t *, int family, tag_type_t, tag_value_t, ...); @@ -42,6 +43,16 @@ int test_nat_public(struct nat *nat, void const *address, int addrlen); int test_nat_flush(struct nat *nat); +struct nat_filter *test_nat_add_filter(struct nat *nat, + size_t (*condition)(void *message, + size_t len), + int outbound); + +enum { nat_inbound, nat_outbound }; + +int test_nat_remove_filter(struct nat *nat, + struct nat_filter *filter); + /* Tags */ /** If true, act as symmetric nat. */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c index 9741da223d..d764fb77d7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c @@ -72,17 +72,23 @@ static RETSIGTYPE sig_alarm(int s) static char const options_usage[] = " -v | --verbose be verbose\n" " -q | --quiet be quiet\n" + " -a | --abort abort on error\n" " -s use only single thread\n" " -l level set logging level (0 by default)\n" " -e | --events print nua events\n" " -A print nua events for A\n" " -B print nua events for B\n" " -C print nua events for C\n" + " --log=a log messages for A\n" + " --log=b log messages for B\n" + " --log=c log messages for C\n" + " --log=proxy log messages for proxy\n" " --attach print pid, wait for a debugger to be attached\n" " --no-proxy do not use internal proxy\n" " --no-nat do not use internal \"nat\"\n" " --symmetric run internal \"nat\" in symmetric mode\n" " -N print events from internal \"nat\"\n" + " --loop loop main tests for ever\n" " --no-alarm don't ask for guard ALARM\n" " -p uri specify uri of outbound proxy (implies --no-proxy)\n" " --proxy-tests run tests involving proxy, too\n" @@ -99,7 +105,7 @@ void usage(int exitcode) int main(int argc, char *argv[]) { int retval = 0; - int i, o_quiet = 0, o_attach = 0, o_alarm = 1; + int i, o_quiet = 0, o_attach = 0, o_alarm = 1, o_loop = 0; int o_events_init = 0, o_events_a = 0, o_events_b = 0, o_events_c = 0; int o_iproxy = 1, o_inat = 1; int o_inat_symmetric = 0, o_inat_logging = 0, o_expensive = 0; @@ -199,6 +205,21 @@ int main(int argc, char *argv[]) else if (strcmp(argv[i], "--no-alarm") == 0) { o_alarm = 0; } + else if (strcmp(argv[i], "--loop") == 0) { + o_alarm = 0, o_loop = 1; + } + else if (strcmp(argv[i], "--log=a") == 0) { + ctx->a.logging = 1; + } + else if (strcmp(argv[i], "--log=b") == 0) { + ctx->b.logging = 1; + } + else if (strcmp(argv[i], "--log=c") == 0) { + ctx->c.logging = 1; + } + else if (strcmp(argv[i], "--log=proxy") == 0) { + ctx->proxy_logging = 1; + } #if SU_HAVE_OSX_CF_API /* If compiled with CoreFoundation events */ else if (strcmp(argv[i], "--osx-runloop") == 0) { ctx->osx_runloop = 1; @@ -210,8 +231,10 @@ int main(int argc, char *argv[]) else if (argv[i][0] != '-') { break; } - else + else { + fprintf(stderr, "test_nua: unknown argument \"%s\"\n\n", argv[i]); usage(1); + } } if (o_attach) { @@ -279,14 +302,14 @@ int main(int argc, char *argv[]) if (retval == 0 && o_inat) retval |= test_nat_timeout(ctx); - if (retval == 0) { - retval |= test_extension(ctx); SINGLE_FAILURE_CHECK(); + while (retval == 0) { retval |= test_basic_call(ctx); SINGLE_FAILURE_CHECK(); retval |= test_reject_a(ctx); SINGLE_FAILURE_CHECK(); retval |= test_reject_b(ctx); SINGLE_FAILURE_CHECK(); retval |= test_reject_302(ctx); SINGLE_FAILURE_CHECK(); retval |= test_reject_401(ctx); SINGLE_FAILURE_CHECK(); retval |= test_mime_negotiation(ctx); SINGLE_FAILURE_CHECK(); + retval |= test_call_timeouts(ctx); SINGLE_FAILURE_CHECK(); retval |= test_reject_401_aka(ctx); SINGLE_FAILURE_CHECK(); retval |= test_call_cancel(ctx); SINGLE_FAILURE_CHECK(); retval |= test_call_destroy(ctx); SINGLE_FAILURE_CHECK(); @@ -295,8 +318,11 @@ int main(int argc, char *argv[]) retval |= test_session_timer(ctx); SINGLE_FAILURE_CHECK(); retval |= test_refer(ctx); SINGLE_FAILURE_CHECK(); retval |= test_100rel(ctx); SINGLE_FAILURE_CHECK(); - retval |= test_simple(ctx); SINGLE_FAILURE_CHECK(); retval |= test_events(ctx); SINGLE_FAILURE_CHECK(); + retval |= test_simple(ctx); SINGLE_FAILURE_CHECK(); + retval |= test_extension(ctx); SINGLE_FAILURE_CHECK(); + if (!o_loop) + break; } if (ctx->proxy_tests && (retval == 0 || !ctx->p)) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h index b90464902c..305611a133 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h @@ -126,10 +126,14 @@ struct context int threading, proxy_tests, expensive, quit_on_single_failure, osx_runloop; char const *external_proxy; + int proxy_logging; + struct endpoint { char name[4]; struct context *ctx; /* Backpointer */ + int logging; + int running; condition_function *next_condition; @@ -138,6 +142,10 @@ struct context sip_contact_t *contact; sip_from_t *to; + sip_allow_t *allow; + char const *appl_method; + sip_supported_t *supported; + printer_function *printer; char const *instance; @@ -185,6 +193,9 @@ int save_event_in_list(struct context *, struct call *); void free_events_in_list(struct context *, struct eventlist *); +void free_event_in_list(struct context *ctx, + struct eventlist *list, + struct event *e); #define CONDITION_PARAMS \ nua_event_t event, \ @@ -321,6 +332,7 @@ int test_reject_b(struct context *ctx); int test_reject_302(struct context *ctx); int test_reject_401(struct context *ctx); int test_mime_negotiation(struct context *ctx); +int test_call_timeouts(struct context *ctx); int test_reject_401_aka(struct context *ctx); int test_call_cancel(struct context *ctx); int test_call_destroy(struct context *ctx); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua_params.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua_params.c index 5483fc28a3..780fce3588 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_nua_params.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_nua_params.c @@ -117,12 +117,12 @@ int test_nua_params(struct context *ctx) nua_get_params(ctx->a.nua, TAG_ANY(), TAG_END()); run_a_until(ctx, nua_r_get_params, save_until_final_response); - TEST_1(e = ctx->a.events->head); + TEST_1(e = ctx->a.specials->head); TEST_E(e->data->e_event, nua_r_get_params); for (n = 0, t = e->data->e_tags; t; n++, t = tl_next(t)) ; TEST_1(n > 32); - free_events_in_list(ctx, ctx->a.events); + free_events_in_list(ctx, ctx->a.specials); nh = nua_handle(ctx->a.nua, NULL, TAG_END()); TEST_1(nh); nua_handle_unref(nh); @@ -148,9 +148,12 @@ int test_nua_params(struct context *ctx) SIPTAG_SUPPORTED_STR("test"), SIPTAG_ALLOW_STR("DWIM, OPTIONS, INFO"), + NUTAG_APPL_METHOD(NULL), + NUTAG_APPL_METHOD("INVITE, REGISTER, PUBLISH, SUBSCRIBE"), SIPTAG_ALLOW_EVENTS_STR("reg"), SIPTAG_USER_AGENT_STR("test_nua/1.0"), + SIPTAG_ORGANIZATION_STR("Open Laboratory"), NUTAG_M_DISPLAY("XXX"), @@ -211,10 +214,13 @@ int test_nua_params(struct context *ctx) SIPTAG_ALLOW(sip_allow_make(tmphome, "INFO")), NUTAG_ALLOW("ACK, INFO"), + NUTAG_APPL_METHOD("NOTIFY"), + SIPTAG_ALLOW_EVENTS_STR("reg"), SIPTAG_ALLOW_EVENTS(sip_allow_events_make(tmphome, "presence")), NUTAG_ALLOW_EVENTS("presence.winfo"), + SIPTAG_USER_AGENT(sip_user_agent_make(tmphome, "test_nua")), SIPTAG_ORGANIZATION(sip_organization_make(tmphome, "Pussy Galore's Flying Circus")), @@ -268,6 +274,7 @@ int test_nua_params(struct context *ctx) sip_allow_t const *allow = NONE; char const *allow_str = "NONE"; + char const *appl_method = "NONE"; sip_allow_events_t const *allow_events = NONE; char const *allow_events_str = "NONE"; sip_supported_t const *supported = NONE; @@ -291,7 +298,7 @@ int test_nua_params(struct context *ctx) nua_get_params(ctx->a.nua, TAG_ANY(), TAG_END()); run_a_until(ctx, nua_r_get_params, save_until_final_response); - TEST_1(e = ctx->a.events->head); + TEST_1(e = ctx->a.specials->head); TEST_E(e->data->e_event, nua_r_get_params); n = tl_gets(e->data->e_tags, @@ -332,6 +339,7 @@ int test_nua_params(struct context *ctx) SIPTAG_SUPPORTED_STR_REF(supported_str), SIPTAG_ALLOW_REF(allow), SIPTAG_ALLOW_STR_REF(allow_str), + NUTAG_APPL_METHOD_REF(appl_method), SIPTAG_ALLOW_EVENTS_REF(allow_events), SIPTAG_ALLOW_EVENTS_STR_REF(allow_events_str), SIPTAG_USER_AGENT_REF(user_agent), @@ -353,7 +361,7 @@ int test_nua_params(struct context *ctx) NUTAG_INSTANCE_REF(instance), TAG_END()); - TEST(n, 46); + TEST(n, 47); TEST_S(sip_header_as_string(tmphome, (void *)from), Alice); TEST_S(from_str, Alice); @@ -389,6 +397,7 @@ int test_nua_params(struct context *ctx) TEST_S(sip_header_as_string(tmphome, (void *)allow), "OPTIONS, INFO, ACK"); TEST_S(allow_str, "OPTIONS, INFO, ACK"); + TEST_S(appl_method, "INVITE, REGISTER, PUBLISH, SUBSCRIBE, NOTIFY"); TEST_S(sip_header_as_string(tmphome, (void *)allow_events), "reg, presence, presence.winfo"); TEST_S(allow_events_str, "reg, presence, presence.winfo"); @@ -414,7 +423,7 @@ int test_nua_params(struct context *ctx) TEST_S(m_features, expect_m_features); } TEST_S(outbound, "foo"); - free_events_in_list(ctx, ctx->a.events); + free_events_in_list(ctx, ctx->a.specials); } /* Test that only those tags that have been set per handle are returned by nua_get_hparams() */ diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_ops.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_ops.c index ecf9fd2185..1b82885d81 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_ops.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_ops.c @@ -44,7 +44,7 @@ int save_events(CONDITION_PARAMS) { - return save_event_in_list(ctx, event, ep, ep->call) == event_is_normal; + return save_event_in_list(ctx, event, ep, call) == event_is_normal; } int until_final_response(CONDITION_PARAMS) @@ -54,7 +54,7 @@ int until_final_response(CONDITION_PARAMS) int save_until_final_response(CONDITION_PARAMS) { - save_event_in_list(ctx, event, ep, ep->call); + save_event_in_list(ctx, event, ep, call); return event >= nua_r_set_params && status >= 200; } @@ -64,13 +64,13 @@ int save_until_final_response(CONDITION_PARAMS) */ int save_until_received(CONDITION_PARAMS) { - return save_event_in_list(ctx, event, ep, ep->call) == event_is_normal; + return save_event_in_list(ctx, event, ep, call) == event_is_normal; } /** Save events until nua_i_outbound is received. */ int save_until_special(CONDITION_PARAMS) { - return save_event_in_list(ctx, event, ep, ep->call) == event_is_special; + return save_event_in_list(ctx, event, ep, call) == event_is_special; } /* Return call state from event tag list */ @@ -143,34 +143,49 @@ void print_event(nua_event_t event, sip_t const *sip, tagi_t tags[]) { + tagi_t const *t; + if (event == nua_i_state) { fprintf(stderr, "%s.nua(%p): event %s %s\n", - ep->name, nh, nua_event_name(event), + ep->name, (void *)nh, nua_event_name(event), nua_callstate_name(callstate(tags))); } else if ((int)event >= nua_r_set_params) { - fprintf(stderr, "%s.nua(%p): event %s status %u %s\n", - ep->name, nh, nua_event_name(event), status, phrase); + t = tl_find(tags, nutag_substate); + if (t) { + fprintf(stderr, "%s.nua(%p): event %s status %u %s (%s)\n", + ep->name, (void*)nh, nua_event_name(event), status, phrase, + nua_substate_name(t->t_value)); + } + else { + fprintf(stderr, "%s.nua(%p): event %s status %u %s\n", + ep->name, (void *)nh, nua_event_name(event), status, phrase); + } + } + else if (event == nua_i_notify) { + t = tl_find(tags, nutag_substate); + fprintf(stderr, "%s.nua(%p): event %s %s (%s)\n", + ep->name, (void *)nh, nua_event_name(event), phrase, + nua_substate_name(t ? t->t_value : 0)); } else if ((int)event >= 0) { fprintf(stderr, "%s.nua(%p): event %s %s\n", - ep->name, nh, nua_event_name(event), phrase); + ep->name, (void *)nh, nua_event_name(event), phrase); } else if (status > 0) { fprintf(stderr, "%s.nua(%p): call %s() with status %u %s\n", - ep->name, nh, operation, status, phrase); + ep->name, (void *)nh, operation, status, phrase); } else { - tagi_t const *t; t = tl_find(tags, siptag_subject_str); if (t && t->t_value) { char const *subject = (char const *)t->t_value; fprintf(stderr, "%s.nua(%p): call %s() \"%s\"\n", - ep->name, nh, operation, subject); + ep->name, (void *)nh, operation, subject); } else fprintf(stderr, "%s.nua(%p): call %s()\n", - ep->name, nh, operation); + ep->name, (void *)nh, operation); } if ((tstflags & tst_verbatim) && tags) @@ -202,10 +217,11 @@ void ep_callback(nua_event_t event, } } - if ((ep->next_event == -1 || ep->next_event == event) && - (ep->next_condition == NULL || + if ((ep->next_condition == NULL || ep->next_condition(event, status, phrase, - nua, ctx, ep, nh, call, sip, tags))) + nua, ctx, ep, nh, call, sip, tags)) + && + (ep->next_event == -1 || ep->next_event == event)) ep->running = 0; ep->last_event = event; @@ -379,7 +395,7 @@ int RESPOND(struct endpoint *ep, return 0; } -/* Destroy an handle */ +/* Destroy a handle */ int DESTROY(struct endpoint *ep, struct call *call, nua_handle_t *nh) @@ -450,7 +466,7 @@ int save_event_in_list(struct context *ctx, return action; } -/* Save nua event in endpoint list */ +/* Free nua events from endpoint list */ void free_events_in_list(struct context *ctx, struct eventlist *list) { @@ -466,6 +482,21 @@ void free_events_in_list(struct context *ctx, list->tail = &list->head; } +void free_event_in_list(struct context *ctx, + struct eventlist *list, + struct event *e) +{ + if (e) { + if ((*e->prev = e->next)) + e->next->prev = e->prev; + nua_destroy_event(e->saved_event); + su_free(ctx->home, e); + + if (list->head == NULL) + list->tail = &list->head; + } +} + int is_special(nua_event_t e) { if (e == nua_i_active || e == nua_i_terminated) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c index 198f7ad914..b184f1a37b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c @@ -230,7 +230,7 @@ test_proxy_init(su_root_t *root, struct proxy *proxy) NTATAG_UA(0), NTATAG_SERVER_RPORT(1), NTATAG_CLIENT_RPORT(1), - TAG_END()); + TAG_NEXT(proxy->tags)); proxy->transport_contacts = create_transport_contacts(proxy); @@ -308,7 +308,7 @@ test_proxy_deinit(su_root_t *root, struct proxy *proxy) free(proxy->tags); } -/* Create tst proxy object */ +/* Create test proxy object */ struct proxy *test_proxy_create(su_root_t *root, tag_type_t tag, tag_value_t value, ...) { diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_refer.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_refer.c index 402d37ace2..8cc97c1d59 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_refer.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_refer.c @@ -43,21 +43,22 @@ #define __func__ "test_call_hold" #endif -int accept_call_immediately(CONDITION_PARAMS); - /* ======================================================================== */ /* NUA-9 tests: REFER */ -int test_refer0(struct context *ctx, int refer_with_id, char const *tests); -int test_refer1(struct context *ctx, int refer_with_id, char const *tests); +int test_refer0(struct context *ctx, char const *tests, + int refer_with_id, int notify_by_appl); + +int notify_until_terminated(CONDITION_PARAMS); int test_refer(struct context *ctx) { /* test twice, once without id and once with id */ return - test_refer0(ctx, 0, "NUA-9.1") || - test_refer0(ctx, 1, "NUA-9.2") || - test_refer1(ctx, 0, "NUA-9.3"); + test_refer0(ctx, "NUA-9.1", 0, 0) || + test_refer0(ctx, "NUA-9.2", 1, 0) || + test_refer0(ctx, "NUA-9.3", 0, 1) || + test_refer0(ctx, "NUA-9.4", 1, 1); } /* Referred call: @@ -103,13 +104,15 @@ int test_refer(struct context *ctx) */ -int test_refer0(struct context *ctx, int refer_with_id, char const *tests) +int test_refer0(struct context *ctx, char const *tests, + int refer_with_id, int notify_by_appl) { BEGIN(); struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; struct call *a_call = a->call, *b_call = b->call, *c_call = c->call; - struct call *a_c2; + struct call *a_refer, *a_c2, *b_refer; + struct eventlist *a_revents, *b_revents; struct event *e; sip_t const *sip; sip_event_t const *a_event, *b_event; @@ -124,7 +127,10 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) su_home_auto(tmphome, sizeof(tmphome)); if (print_headings) - printf("TEST %s: REFER: refer A to C\n", tests); + printf("TEST %s: REFER: refer A to C%s%s%s\n", tests, + refer_with_id ? " with Event id" : "", + refer_with_id && !notify_by_appl ? " and" : "", + !notify_by_appl ? " nua generating the NOTIFYs" : ""); if (print_headings) printf("TEST %s.1: REFER: make a call between A and B\n", tests); @@ -133,6 +139,28 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) nua_set_params(ctx->a.nua, NUTAG_REFER_WITH_ID(refer_with_id), TAG_END()); run_a_until(ctx, nua_r_set_params, until_final_response); + if (refer_with_id) { + TEST_1(a_refer = calloc(1, (sizeof *a_refer) + (sizeof *a_refer->events))); + call_init(a_refer); + a_refer->events = (void *)(a_refer + 1); + eventlist_init(a_refer->events); + + a_call->next = a_refer; + a_revents = a_refer->events; + + TEST_1(b_refer = calloc(1, (sizeof *b_refer) + (sizeof *b_refer->events))); + call_init(b_refer); + b_refer->events = (void *)(b_refer + 1); + eventlist_init(b_refer->events); + + b_call->next = b_refer; + b_revents = b_refer->events; + } + else { + a_refer = a_call, b_refer = b_call; + a_revents = a->events, b_revents = b->events; + } + TEST_1(a_c2 = calloc(1, (sizeof *a_c2) + (sizeof *a_c2->events))); call_init(a_c2); a_c2->events = (void *)(a_c2 + 1); @@ -198,7 +226,7 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) printf("TEST %s.1: PASSED\n", tests); /* ---------------------------------------------------------------------- */ - /* REFER (initial NOTIFY is no more sent) + /* REFER (initial NOTIFY is no more sent unless REFER creates a new dialog) A B |<------REFER--------| |-------200 OK------>| @@ -207,13 +235,20 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) */ if (print_headings) - printf("TEST %s.2: refer A to C\n", tests); + printf("TEST %s.2: B refers A to C\n", tests); + + if (b_refer != b_call) + TEST_1(b_refer->nh = + nua_handle(b->nua, b_refer, SIPTAG_TO(a->to), TAG_END())); *sip_refer_to_init(r0)->r_url = *c->contact->m_url; r0->r_url->url_headers = "subject=referred"; r0->r_display = "C"; - REFER(b, b_call, b_call->nh, SIPTAG_REFER_TO(r0), TAG_END()); + REFER(b, b_refer, b_refer->nh, SIPTAG_REFER_TO(r0), + TAG_IF(!ctx->proxy_tests && b_refer != b_call, + NUTAG_URL(a->contact->m_url)), + TAG_END()); run_ab_until(ctx, -1, save_until_received, -1, save_until_final_response); @@ -221,7 +256,7 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) Events in A: nua_i_refer */ - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_refer); + TEST_1(e = a_revents->head); TEST_E(e->data->e_event, nua_i_refer); TEST(e->data->e_status, 202); a_event = NULL; TEST(tl_gets(e->data->e_tags, @@ -233,17 +268,12 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) TEST_1(refer_to = sip_refer_to_dup(tmphome, sip->sip_refer_to)); TEST_1(sip->sip_referred_by); TEST_1(referred_by = sip_referred_by_dup(tmphome, sip->sip_referred_by)); - if (e->next) { - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify); - TEST_1(!e->next); - } - free_events_in_list(ctx, a->events); /* Events in B after nua_refer(): nua_r_refer */ - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_refer); + TEST_1(e = b_revents->head); TEST_E(e->data->e_event, nua_r_refer); TEST(e->data->e_status, 100); TEST(tl_gets(e->data->e_tags, NUTAG_REFER_EVENT_REF(b_event), @@ -254,22 +284,32 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) TEST(e->data->e_status, 202); TEST_1(sip = sip_object(e->data->e_msg)); TEST_SIZE(strtoul(b_event->o_id, NULL, 10), sip->sip_cseq->cs_seq); -#if 0 - if (!e->next) - run_b_until(ctx, -1, save_until_received); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify); - TEST(e->data->e_status, 200); - TEST_1(sip = sip_object(e->data->e_msg)); - TEST_1(sip->sip_event); - if (refer_with_id) - TEST_S(sip->sip_event->o_id, b_event->o_id); - TEST_1(sip->sip_subscription_state); - TEST_S(sip->sip_subscription_state->ss_substate, "pending"); - TEST_1(sip->sip_payload && sip->sip_payload->pl_data); - TEST_S(sip->sip_payload->pl_data, "SIP/2.0 100 Trying\r\n"); - TEST_1(!e->next); -#endif - free_events_in_list(ctx, b->events); + + if (a_refer != a_call) { + if (b_revents->head->next->next == NULL) + run_ab_until(ctx, -1, save_until_received, nua_i_notify, save_events); + else if (a_revents->head->next == NULL) + run_a_until(ctx, -1, save_until_received); + + TEST_1(e = a_revents->head->next); TEST_E(e->data->e_event, nua_r_notify); + TEST_1(!e->next); + + TEST_1(e = b_revents->head->next->next); + TEST_E(e->data->e_event, nua_i_notify); + TEST(e->data->e_status, 200); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_event); + if (refer_with_id) + TEST_S(sip->sip_event->o_id, b_event->o_id); + TEST_1(sip->sip_subscription_state); + TEST_S(sip->sip_subscription_state->ss_substate, "pending"); + TEST_1(sip->sip_payload && sip->sip_payload->pl_data); + TEST_S(sip->sip_payload->pl_data, "SIP/2.0 100 Trying\r\n"); + TEST_1(!e->next); + } + + free_events_in_list(ctx, a_revents); + free_events_in_list(ctx, b_revents); if (print_headings) printf("TEST %s.2: PASSED\n", tests); @@ -371,42 +411,43 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) *sip_to_init(to)->a_url = *refer_to->r_url; to->a_display = refer_to->r_display; - a->call->next = a_c2; + a_refer->next = a_c2; TEST_1(a_c2->nh = nua_handle(a->nua, a_c2, SIPTAG_TO(to), TAG_END())); INVITE(a, a_c2, a_c2->nh, /* NUTAG_URL(refer_to->r_url), */ - NUTAG_REFER_EVENT(a_event), - NUTAG_NOTIFY_REFER(a_call->nh), + TAG_IF(!notify_by_appl, NUTAG_REFER_EVENT(a_event)), + TAG_IF(!notify_by_appl, NUTAG_NOTIFY_REFER(a_refer->nh)), SOATAG_USER_SDP_STR(a_c2->sdp), SIPTAG_REFERRED_BY(referred_by), TAG_END()); run_abc_until(ctx, - -1, until_ready, + -1, notify_by_appl ? notify_until_terminated : until_ready, -1, save_until_received, - -1, accept_call_immediately); - /* XXX - we should use accept_call instead of accept_call_immediately but - nua has a problem with automatically generated NOTIFYs: - 3rd NOTIFY is not sent because 2nd is still in progress - */ + -1, accept_call); + + /* Wait until both NOTIFY has been responded */ + while (a_revents->head == NULL || a_revents->head->next == NULL) + run_ab_until(ctx, -1, save_until_received, -1, save_events); + while (b_revents->head == NULL || b_revents->head->next == NULL) + run_ab_until(ctx, -1, save_events, -1, save_until_received); /* Client A transitions: INIT -(C1)-> CALLING: nua_invite(), nua_i_state - CALLING -(C2a+C4)-> READY: nua_r_invite, nua_i_state - nua_i_notify - - XXX should be: CALLING -(C2+C4)-> PROCEEDING: nua_r_invite, nua_i_state - optional: nua_i_notify + nua_r_notify PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state - nua_i_notify - optional: nua_i_notify + nua_r_notify */ TEST_1(e = a_c2->events->head); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ TEST_1(is_offer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); + TEST(e->data->e_status, 180); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); TEST(e->data->e_status, 200); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ @@ -414,19 +455,32 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) TEST_1(!e->next); free_events_in_list(ctx, a_c2->events); - if (a->events->head == NULL) - run_a_until(ctx, -1, save_until_received); - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify); - TEST_1(!e->next); - free_events_in_list(ctx, a->events); + TEST_1(e = a_revents->head); TEST_E(e->data->e_event, nua_r_notify); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify); + if (a_refer == a_call && notify_by_appl) { + free_event_in_list(ctx, a_revents, a_revents->head); + free_event_in_list(ctx, a_revents, a_revents->head); + } + else { + TEST_1(!e->next); + free_events_in_list(ctx, a_revents); + } /* Events in B after nua_refer(): nua_i_notify */ - if (b->events->head == NULL) - run_b_until(ctx, -1, save_until_received); - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify); + TEST_1(e = b_revents->head); TEST_E(e->data->e_event, nua_i_notify); + TEST(e->data->e_status, 200); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_subscription_state); + TEST_S(sip->sip_subscription_state->ss_substate, "active"); + TEST_1(sip->sip_payload && sip->sip_payload->pl_data); + TEST_S(sip->sip_payload->pl_data, "SIP/2.0 180 Ringing\r\n"); + TEST_1(sip->sip_event); + if (refer_with_id) + TEST_S(sip->sip_event->o_id, b_event->o_id); + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_subscription_state); @@ -436,13 +490,20 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) TEST_1(sip->sip_event); if (refer_with_id) TEST_S(sip->sip_event->o_id, b_event->o_id); - TEST_1(!e->next); - free_events_in_list(ctx, b->events); + if (b_refer == b_call && notify_by_appl) { + free_event_in_list(ctx, b_revents, b_revents->head); + free_event_in_list(ctx, b_revents, b_revents->head); + } + else { + TEST_1(!e->next); + free_events_in_list(ctx, b_revents); + } /* C transitions: INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state - RECEIVED -(S3b)-> COMPLETED: nua_respond(), nua_i_state + RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state + EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state */ TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_i_invite); @@ -451,6 +512,8 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ TEST_1(is_offer_recv(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); + TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */ + TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ TEST_1(is_answer_sent(e->data->e_tags)); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack); @@ -472,20 +535,28 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) if (print_headings) printf("TEST %s.5.1: terminate call between A and B\n", tests); - BYE(a, a_call, a_call->nh, TAG_END()); - run_ab_until(ctx, -1, until_terminated, -1, until_terminated); + if (notify_by_appl) { + if (!a->events->head || !a->events->head->next) + run_ab_until(ctx, -1, until_terminated, -1, save_events); + if (!b->events->head || !b->events->head->next) + run_ab_until(ctx, -1, save_events, -1, until_terminated); + } + else { + BYE(a, a_call, a_call->nh, TAG_END()); + run_ab_until(ctx, -1, until_terminated, -1, until_terminated); + } /* - Transitions of A: - READY --(T2)--> TERMINATING: nua_bye() - TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state + Transitions of A: + READY --(T2)--> TERMINATING: nua_bye() + TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state */ TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_bye); TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ TEST_1(!e->next); free_events_in_list(ctx, a->events); - + /* Transitions of B: READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state */ @@ -540,11 +611,21 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) if (print_headings) printf("TEST %s.5.2: PASSED\n", tests); - nua_handle_destroy(a_c2->nh), a_c2->nh = NULL; - a->call->next = NULL; free(a_c2); - nua_handle_destroy(c_call->nh), c_call->nh = NULL; + nua_handle_destroy(a_c2->nh), a_c2->nh = NULL; + a_refer->next = NULL; free(a_c2); + + if (a_refer != a_call) { + nua_handle_destroy(a_refer->nh), a_refer->nh = NULL; + a_call->next = NULL; free(a_refer); + } + + if (b_refer != b_call) { + nua_handle_destroy(b_refer->nh), b_refer->nh = NULL; + b_call->next = NULL; free(b_refer); + } + if (print_headings) printf("TEST %s: PASSED\n", tests); @@ -554,40 +635,6 @@ int test_refer0(struct context *ctx, int refer_with_id, char const *tests) } -/* - accept_call_immediately - X - | | - |-------INVITE------>| - |<----100 Trying-----| - | | - |<--------200--------| - |---------ACK------->| -*/ -int accept_call_immediately(CONDITION_PARAMS) -{ - if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) - return 0; - - save_event_in_list(ctx, event, ep, call); - - switch (callstate(tags)) { - case nua_callstate_received: - RESPOND(ep, call, nh, SIP_200_OK, - TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)), - TAG_END()); - return 0; - case nua_callstate_ready: - return 1; - case nua_callstate_terminated: - if (call) - nua_handle_destroy(call->nh), call->nh = NULL; - return 1; - default: - return 0; - } -} - /* X INVITE | | @@ -610,18 +657,31 @@ int notify_until_terminated(CONDITION_PARAMS) if (event == nua_r_invite) { sip_status_t *st = sip->sip_status; sip_payload_t *pl; + struct call *r_call; + + if (!nua_handle_has_events(ep->call->nh)) + r_call = ep->call->next; + else + r_call = ep->call; + + assert(nua_handle_has_events(r_call->nh)); pl = sip_payload_format(NULL, "SIP/2.0 %u %s\r\n", st->st_status, st->st_phrase); - NOTIFY(ep, ep->call, ep->call->nh, + NOTIFY(ep, r_call, r_call->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD(pl), - TAG_IF(st->st_status >= 200, - NUTAG_SUBSTATE(nua_substate_terminated)), + NUTAG_SUBSTATE(st->st_status >= 200 + ? nua_substate_terminated + : nua_substate_active), TAG_END()); - BYE(ep, ep->call, ep->call->nh, TAG_END()); + su_free(NULL, pl); + + if (st->st_status >= 200) + BYE(ep, ep->call, ep->call->nh, TAG_END()); + return 0; } @@ -635,392 +695,3 @@ int notify_until_terminated(CONDITION_PARAMS) return 0; } } - -/* Referred call - NOTIFY and BYE are overlapped - - A B - | | - |-------INVITE------>| - |<----100 Trying-----| - | | - |<----180 Ringing----| - | | - |<------200 OK-------| - |--------ACK-------->| - | | - |<------REFER--------| - |-------200 OK------>| C - [|-------NOTIFY------>|] | - [|<------200 OK-------|] | - | | | - | | | - |<-----SUBSCRIBE-----| | - |-------200 OK------>| | - | | | - | | | - |-----------------INVITE-------------------->| - | | | - | | | - |<------------------200----------------------| - |-------NOTIFY------>| | - |--------BYE-------->| | - |-------------------ACK--------------------->| - |<------200 OK-------| | - |<------200 OK-------| | - | X | - | | - |-------------------BYE--------------------->| - |<------------------200----------------------| - | | - -*/ - -int test_refer1(struct context *ctx, int refer_with_id, char const *tests) -{ - BEGIN(); - - struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; - struct call *a_call = a->call, *b_call = b->call, *c_call = c->call; - struct call *a_c2; - struct event *e; - sip_t const *sip; - sip_event_t const *a_event, *b_event; - sip_refer_to_t const *refer_to; - sip_referred_by_t const *referred_by; - - sip_refer_to_t r0[1]; - sip_to_t to[1]; - - su_home_t tmphome[SU_HOME_AUTO_SIZE(16384)]; - - su_home_auto(tmphome, sizeof(tmphome)); - - if (print_headings) - printf("TEST %s: REFER: refer A to C\n", tests); - - if (print_headings) - printf("TEST %s.1: REFER: make a call between A and B\n", tests); - - /* Do (not) include id with first implicit Event: refer */ - nua_set_params(ctx->a.nua, NUTAG_REFER_WITH_ID(refer_with_id), TAG_END()); - run_a_until(ctx, nua_r_set_params, until_final_response); - - TEST_1(a_c2 = calloc(1, (sizeof *a_c2) + (sizeof *a_c2->events))); - call_init(a_c2); - a_c2->events = (void *)(a_c2 + 1); - eventlist_init(a_c2->events); - - a_call->sdp = "m=audio 5008 RTP/AVP 8"; - b_call->sdp = "m=audio 5010 RTP/AVP 0 8"; - a_c2->sdp = "m=audio 5012 RTP/AVP 8"; - c_call->sdp = "m=audio 5014 RTP/AVP 0 8"; - - TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); - - INVITE(a, a_call, a_call->nh, - TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), - SOATAG_USER_SDP_STR(a_call->sdp), - TAG_END()); - - run_ab_until(ctx, -1, until_ready, -1, accept_call); - - /* Client transitions: - INIT -(C1)-> CALLING: nua_invite(), nua_i_state - CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state - PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state - */ - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ - TEST_1(is_offer_sent(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); - TEST(e->data->e_status, 180); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */ - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ - TEST_1(is_answer_recv(e->data->e_tags)); - TEST_1(!e->next); - free_events_in_list(ctx, a->events); - - /* - Server transitions: - INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state - RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state - EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state - COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state - */ - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite); - TEST(e->data->e_status, 100); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ - TEST_1(is_offer_recv(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */ - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ - TEST_1(is_answer_sent(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ - TEST_1(!e->next); - free_events_in_list(ctx, b->events); - - if (print_headings) - printf("TEST %s.1: PASSED\n", tests); - - /* ---------------------------------------------------------------------- */ - /* REFER (initial NOTIFY is no more sent) - A B - |<------REFER--------| - |-------200 OK------>| - [|-------NOTIFY------>|] | - [|<------200 OK-------|] | - */ - - if (print_headings) - printf("TEST %s.2: refer A to C\n", tests); - - *sip_refer_to_init(r0)->r_url = *c->contact->m_url; - r0->r_url->url_headers = "subject=referred"; - r0->r_display = "C"; - - REFER(b, b_call, b_call->nh, SIPTAG_REFER_TO(r0), TAG_END()); - run_ab_until(ctx, -1, save_until_received, - -1, save_until_final_response); - - /* - Events in A: - nua_i_refer - */ - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_refer); - TEST(e->data->e_status, 202); - a_event = NULL; - TEST(tl_gets(e->data->e_tags, - NUTAG_REFER_EVENT_REF(a_event), - TAG_END()), 1); - TEST_1(a_event); TEST_1(a_event = sip_event_dup(tmphome, a_event)); - TEST_1(sip = sip_object(e->data->e_msg)); - TEST_1(sip->sip_refer_to); - TEST_1(refer_to = sip_refer_to_dup(tmphome, sip->sip_refer_to)); - TEST_1(sip->sip_referred_by); - TEST_1(referred_by = sip_referred_by_dup(tmphome, sip->sip_referred_by)); - if (e->next) { - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_notify); - TEST_1(!e->next); - } - free_events_in_list(ctx, a->events); - - /* - Events in B after nua_refer(): - nua_r_refer - */ - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_refer); - TEST(e->data->e_status, 100); - TEST(tl_gets(e->data->e_tags, - NUTAG_REFER_EVENT_REF(b_event), - TAG_END()), 1); - TEST_1(b_event); TEST_1(b_event->o_id); - TEST_1(b_event = sip_event_dup(tmphome, b_event)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_refer); - TEST(e->data->e_status, 202); - TEST_1(sip = sip_object(e->data->e_msg)); - TEST_SIZE(strtoul(b_event->o_id, NULL, 10), sip->sip_cseq->cs_seq); -#if 0 - if (!e->next) - run_b_until(ctx, -1, save_until_received); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_notify); - TEST(e->data->e_status, 200); - TEST_1(sip = sip_object(e->data->e_msg)); - TEST_1(sip->sip_event); - if (refer_with_id) - TEST_S(sip->sip_event->o_id, b_event->o_id); - TEST_1(sip->sip_subscription_state); - TEST_S(sip->sip_subscription_state->ss_substate, "pending"); - TEST_1(sip->sip_payload && sip->sip_payload->pl_data); - TEST_S(sip->sip_payload->pl_data, "SIP/2.0 100 Trying\r\n"); - TEST_1(!e->next); -#endif - free_events_in_list(ctx, b->events); - - if (print_headings) - printf("TEST %s.2: PASSED\n", tests); - - - /* ---------------------------------------------------------------------- */ - /* - A B C - | | | - |-----------------INVITE-------------------->| - | | | - XXX | | - | | | - |<------------------200----------------------| - |-------NOTIFY------>| | - |---------BYE------->| | - |-------------------ACK--------------------->| - |<--------200--------| | - |<------200 OK-------| | - | X - */ - - if (print_headings) - printf("TEST %s.4: A invites C\n", tests); - - *sip_to_init(to)->a_url = *refer_to->r_url; - to->a_display = refer_to->r_display; - - a->call->next = a_c2; - - TEST_1(a_c2->nh = nua_handle(a->nua, a_c2, SIPTAG_TO(to), TAG_END())); - - INVITE(a, a_c2, a_c2->nh, /* NUTAG_URL(refer_to->r_url), */ - NUTAG_REFER_EVENT(a_event), - /* NUTAG_NOTIFY_REFER(a_call->nh), */ - SOATAG_USER_SDP_STR(a_c2->sdp), - SIPTAG_REFERRED_BY(referred_by), - TAG_END()); - - run_abc_until(ctx, - -1, notify_until_terminated, - -1, until_terminated, - -1, accept_call_immediately); - - /* XXX - we should use accept_call instead of accept_call_immediately but - nua has a problem with automatically generated NOTIFYs: - 3rd NOTIFY is not sent because 2nd is still in progress - */ - - /* Client A transitions: - INIT -(C1)-> CALLING: nua_invite(), nua_i_state - CALLING -(C2a+C4)-> READY: nua_r_invite, nua_i_state - nua_r_notify - - Transitions of first call: - READY --(T2)--> TERMINATING: nua_bye() - TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state - - XXX should be: - CALLING -(C2+C4)-> PROCEEDING: nua_r_invite, nua_i_state - optional: nua_i_notify - PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state - nua_i_notify - optional: nua_i_notify - */ - TEST_1(e = a_c2->events->head); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */ - TEST_1(is_offer_sent(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite); - TEST(e->data->e_status, 200); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ - TEST_1(is_answer_recv(e->data->e_tags)); - TEST_1(!e->next); - free_events_in_list(ctx, a_c2->events); - - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_bye); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ - free_events_in_list(ctx, a->events); - - nua_handle_destroy(a_call->nh), a_call->nh = NULL; - - /* - Events in B after nua_refer(): - nua_i_notify - READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state - */ - if (b->events->head == NULL) - run_b_until(ctx, -1, save_until_received); - TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify); - TEST(e->data->e_status, 200); - TEST_1(sip = sip_object(e->data->e_msg)); - TEST_1(sip->sip_subscription_state); - TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); - TEST_1(sip->sip_payload && sip->sip_payload->pl_data); - TEST_S(sip->sip_payload->pl_data, "SIP/2.0 200 OK\r\n"); - TEST_1(sip->sip_event); - if (refer_with_id) - TEST_S(sip->sip_event->o_id, b_event->o_id); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_bye); - TEST(e->data->e_status, 200); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ - TEST_1(!e->next); - free_events_in_list(ctx, b->events); - - nua_handle_destroy(b_call->nh), b_call->nh = NULL; - - /* - C transitions: - INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state - RECEIVED -(S3b)-> COMPLETED: nua_respond(), nua_i_state - COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state - */ - TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_i_invite); - TEST(e->data->e_status, 100); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */ - TEST_1(is_offer_recv(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */ - TEST_1(is_answer_sent(e->data->e_tags)); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */ - TEST_1(!e->next); - free_events_in_list(ctx, c->events); - - if (print_headings) - printf("TEST %s.4: PASSED\n", tests); - - /* ---------------------------------------------------------------------- */ - /* - A C - |-------------------BYE--------------------->| - |<------------------200----------------------| - */ - - if (print_headings) - printf("TEST %s.5.2: terminate call between A and C\n", tests); - - BYE(a, a_c2, a_c2->nh, TAG_END()); - run_abc_until(ctx, -1, until_terminated, -1, NULL, -1, until_terminated); - - /* - Transitions of A: - READY --(T2)--> TERMINATING: nua_bye() - TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state - */ - TEST_1(e = a_c2->events->head); TEST_E(e->data->e_event, nua_r_bye); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ - TEST_1(!e->next); - free_events_in_list(ctx, a_c2->events); - - /* Transitions of B: - READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state - */ - TEST_1(e = c->events->head); TEST_E(e->data->e_event, nua_i_bye); - TEST(e->data->e_status, 200); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state); - TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */ - TEST_1(!e->next); - free_events_in_list(ctx, c->events); - - if (print_headings) - printf("TEST %s.5.2: PASSED\n", tests); - - nua_handle_destroy(a_c2->nh), a_c2->nh = NULL; - a->call->next = NULL; free(a_c2); - - nua_handle_destroy(c_call->nh), c_call->nh = NULL; - - if (print_headings) - printf("TEST %s: PASSED\n", tests); - - su_home_deinit(tmphome); - - END(); -} diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c index fd5757cdb7..fb41bdd2a8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_register.c @@ -142,6 +142,7 @@ int test_register_to_proxy(struct context *ctx) TEST_1(sip = sip_object(e->data->e_msg)); TEST(e->data->e_status, 401); TEST(sip->sip_status->st_status, 401); + /* Check that CSeq included in tags is actually used in the request */ TEST(sip->sip_cseq->cs_seq, 13); TEST_1(!sip->sip_contact); TEST_1(!e->next); @@ -349,7 +350,7 @@ int test_register_to_c(struct context *ctx) sip_t const *sip; if (print_headings) - printf("TEST NUA-2.3.2: REGISTER b to c\n"); + printf("TEST NUA-2.6.1: REGISTER b to c\n"); nua_set_params(ctx->c.nua, NUTAG_ALLOW("REGISTER"), @@ -372,9 +373,6 @@ int test_register_to_c(struct context *ctx) TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(!sip->sip_contact); - if (print_headings) - printf("TEST NUA-2.6.1: PASSED\n"); - free_events_in_list(ctx, b->events); nua_handle_destroy(b_call->nh), b_call->nh = NULL; @@ -388,7 +386,7 @@ int test_register_to_c(struct context *ctx) nua_handle_destroy(c_call->nh), c_call->nh = NULL; if (print_headings) - printf("TEST NUA-2.3.4: PASSED\n"); + printf("TEST NUA-2.6.1: PASSED\n"); END(); } @@ -552,7 +550,8 @@ int test_nat_timeout(struct context *ctx) BEGIN(); - struct endpoint *a = &ctx->a, *b = &ctx->b, *c = &ctx->c; + struct endpoint *a = &ctx->a, *b = &ctx->b; + struct call *a_call = a->call, *b_call = b->call; struct event *e; sip_t const *sip; @@ -586,7 +585,38 @@ int test_nat_timeout(struct context *ctx) if (print_headings) printf("TEST NUA-2.5.1: PASSED\n"); - (void)b; (void)c; (void)sip; + if (print_headings) + printf("TEST NUA-2.5.2: OPTIONS from B to A\n"); + + TEST_1(b_call->nh = nua_handle(b->nua, b_call, SIPTAG_TO(a->to), TAG_END())); + + OPTIONS(b, b_call, b_call->nh, TAG_END()); + + run_ab_until(ctx, -1, save_until_received, + -1, save_until_final_response); + + /* Client events: nua_options(), nua_r_options */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_options); + TEST(e->data->e_status, 200); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_allow); TEST_1(sip->sip_accept); TEST_1(sip->sip_supported); + /* TEST_1(sip->sip_content_type); */ + /* TEST_1(sip->sip_payload); */ + TEST_1(!e->next); + + free_events_in_list(ctx, b->events); + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + /* Server events: nua_i_options */ + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_options); + TEST(e->data->e_status, 200); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + + if (print_headings) + printf("TEST NUA-2.5.2: PASSED\n"); END(); } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c b/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c index d8377313d7..696a4c9218 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/test_simple.c @@ -43,6 +43,8 @@ #define __func__ "test_simple" #endif +extern int accept_request(CONDITION_PARAMS); + int test_message(struct context *ctx) { BEGIN(); @@ -62,7 +64,7 @@ int test_message(struct context *ctx) */ if (print_headings) - printf("TEST NUA-11.1: MESSAGE\n"); + printf("TEST NUA-11.1.1: MESSAGE\n"); if (ctx->proxy_tests) *url = *b->to->a_url; @@ -76,7 +78,7 @@ int test_message(struct context *ctx) MESSAGE(a, a_call, a_call->nh, NUTAG_URL(url), - SIPTAG_SUBJECT_STR("NUA-11.1"), + SIPTAG_SUBJECT_STR("NUA-11.1.1"), SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("Hello hellO!\n"), TAG_END()); @@ -98,7 +100,7 @@ int test_message(struct context *ctx) TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_subject && sip->sip_subject->g_string); - TEST_S(sip->sip_subject->g_string, "NUA-11.1"); + TEST_S(sip->sip_subject->g_string, "NUA-11.1.1"); TEST_1(sip->sip_organization); TEST_S(sip->sip_organization->g_string, "United Testers"); TEST_1(!e->next); @@ -110,7 +112,64 @@ int test_message(struct context *ctx) nua_handle_destroy(b_call->nh), b_call->nh = NULL; if (print_headings) - printf("TEST NUA-11.1: PASSED\n"); + printf("TEST NUA-11.1.1: PASSED\n"); + +/* MESSAGE as application method + + A B + |-------MESSAGE----->| + |<-------202---------| + | | +*/ + + if (print_headings) + printf("TEST NUA-11.1.2: MESSAGE\n"); + + nua_set_params(b->nua, NUTAG_APPL_METHOD("MESSAGE"), TAG_END()); + run_b_until(ctx, nua_r_set_params, until_final_response); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, TAG_END())); + + MESSAGE(a, a_call, a_call->nh, + NUTAG_URL(url), + SIPTAG_SUBJECT_STR("NUA-11.1.2"), + SIPTAG_CONTENT_TYPE_STR("text/plain"), + SIPTAG_PAYLOAD_STR("Hello hellO!\n"), + TAG_END()); + + run_ab_until(ctx, -1, save_until_final_response, -1, accept_request); + + /* Client events: + nua_message(), nua_r_message + */ + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_message); + TEST(e->data->e_status, 202); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip_user_agent(sip)); + TEST_S(sip_user_agent(sip)->g_value, "007"); + TEST_1(!e->next); + + /* + Server events: + nua_i_message + */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_message); + TEST(e->data->e_status, 100); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_subject && sip->sip_subject->g_string); + TEST_S(sip->sip_subject->g_string, "NUA-11.1.2"); + TEST_1(sip->sip_organization); + TEST_S(sip->sip_organization->g_string, "United Testers"); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + + free_events_in_list(ctx, b->events); + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + if (print_headings) + printf("TEST NUA-11.1.2: PASSED\n"); /* Message test @@ -131,7 +190,7 @@ int test_message(struct context *ctx) MESSAGE(a, a_call, a_call->nh, /* We cannot reach us by using our contact! */ NUTAG_URL(!ctx->p && !ctx->proxy_tests ? a->contact->m_url : NULL), - SIPTAG_SUBJECT_STR("NUA-11.1b"), + SIPTAG_SUBJECT_STR("NUA-11.2"), SIPTAG_CONTENT_TYPE_STR("text/plain"), SIPTAG_PAYLOAD_STR("Hello hellO!\n"), TAG_END()); @@ -141,16 +200,18 @@ int test_message(struct context *ctx) /* Events: nua_message(), nua_i_message, nua_r_message */ - TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_message); + TEST_1(e = a->specials->head); TEST_E(e->data->e_event, nua_i_message); TEST(e->data->e_status, 200); TEST_1(sip = sip_object(e->data->e_msg)); TEST_1(sip->sip_subject && sip->sip_subject->g_string); - TEST_S(sip->sip_subject->g_string, "NUA-11.1b"); - TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_message); + TEST_S(sip->sip_subject->g_string, "NUA-11.2"); + TEST_1(!e->next); + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_message); TEST(e->data->e_status, 200); TEST_1(!e->next); free_events_in_list(ctx, a->events); + free_events_in_list(ctx, a->specials); nua_handle_destroy(a_call->nh), a_call->nh = NULL; if (print_headings) @@ -159,12 +220,32 @@ int test_message(struct context *ctx) END(); } +int accept_request(CONDITION_PARAMS) +{ + msg_t *with = nua_current_request(nua); + + if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) + return 0; + + save_event_in_list(ctx, event, ep, call); + + if (status < 200) { + RESPOND(ep, call, nh, SIP_202_ACCEPTED, + NUTAG_WITH(with), + SIPTAG_USER_AGENT_STR("007"), + TAG_END()); + return 1; + } + + return 0; +} + int respond_with_etag(CONDITION_PARAMS) { msg_t *with = nua_current_request(nua); if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR))) - return 0; + return 1; save_event_in_list(ctx, event, ep, call); @@ -191,6 +272,14 @@ int respond_with_etag(CONDITION_PARAMS) } } +static int close_handle(CONDITION_PARAMS) +{ + if (call->nh == nh) + call->nh = NULL; + nua_handle_destroy(nh); + return 1; +} + int test_publish(struct context *ctx) { BEGIN(); @@ -357,8 +446,60 @@ int test_publish(struct context *ctx) nua_handle_destroy(a_call->nh), a_call->nh = NULL; nua_handle_destroy(b_call->nh), b_call->nh = NULL; + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + /* Let server close handle without responding to PUBLISH */ + PUBLISH(a, a_call, a_call->nh, + TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), + SIPTAG_EVENT_STR("presence"), + SIPTAG_CONTENT_TYPE_STR("text/urllist"), + SIPTAG_PAYLOAD_STR("sip:example.com\n"), + TAG_END()); + + run_ab_until(ctx, -1, save_until_final_response, -1, close_handle); + + /* Client events: + nua_publish(), nua_r_publish + */ + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish); + TEST(e->data->e_status, 500); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + + /* No Event header */ + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + PUBLISH(a, a_call, a_call->nh, + TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)), + SIPTAG_CONTENT_TYPE_STR("text/urllist"), + SIPTAG_PAYLOAD_STR("sip:example.com\n"), + TAG_END()); + + run_ab_until(ctx, -1, save_until_final_response, -1, save_events); + + /* Client events: + nua_publish(), nua_r_publish + */ + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_publish); + TEST(e->data->e_status, 489); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + + /* + Server events: nothing + */ + TEST_1(!b->events->head); + + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + if (print_headings) printf("TEST NUA-11.3: PASSED\n"); + END(); } @@ -619,14 +760,155 @@ int test_subscribe_notify(struct context *ctx) END(); } +/* ---------------------------------------------------------------------- */ +/* Unsolicited NOTIFY */ + +int accept_notify(CONDITION_PARAMS); + +int test_newsub_notify(struct context *ctx) +{ + BEGIN(); + + struct endpoint *a = &ctx->a, *b = &ctx->b; + struct call *a_call = a->call, *b_call = b->call; + struct event *e; + sip_t const *sip; + tagi_t const *n_tags, *r_tags; + + if (print_headings) + printf("TEST NUA-11.7.1: rejecting NOTIFY without subscription locally\n"); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + NOTIFY(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), + SIPTAG_SUBJECT_STR("NUA-11.7.1"), + SIPTAG_EVENT_STR("message-summary"), + SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), + SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"), + TAG_END()); + + run_a_until(ctx, -1, save_until_final_response); + + /* Client events: + nua_notify(), nua_r_notify + */ + TEST_1(e = a->events->head); + TEST_E(e->data->e_event, nua_r_notify); + TEST(e->data->e_status, 481); + TEST_1(!e->data->e_msg); + TEST_1(!e->next); + free_events_in_list(ctx, a->events); + + if (print_headings) + printf("TEST NUA-11.7.1: PASSED\n"); + + if (print_headings) + printf("TEST NUA-11.7.2: rejecting NOTIFY without subscription\n"); + + TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END())); + + NOTIFY(a, a_call, a_call->nh, NUTAG_URL(b->contact->m_url), + NUTAG_NEWSUB(1), + SIPTAG_SUBJECT_STR("NUA-11.7.2"), + SIPTAG_EVENT_STR("message-summary"), + SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), + SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"), + TAG_END()); + + run_a_until(ctx, -1, save_until_final_response); + + /* Client events: + nua_notify(), nua_r_notify + */ + TEST_1(e = a->events->head); + TEST_E(e->data->e_event, nua_r_notify); + TEST(e->data->e_status, 481); + TEST_1(e->data->e_msg); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + + if (print_headings) + printf("TEST NUA-11.7.2: PASSED\n"); + + /* ---------------------------------------------------------------------- */ + + if (print_headings) + printf("TEST NUA-11.7.3: accept NOTIFY\n"); + + nua_set_params(b->nua, NUTAG_APPL_METHOD("NOTIFY"), TAG_END()); + run_b_until(ctx, nua_r_set_params, until_final_response); + + NOTIFY(a, a_call, a_call->nh, + NUTAG_URL(b->contact->m_url), + NUTAG_NEWSUB(1), + SIPTAG_SUBJECT_STR("NUA-11.7.3"), + SIPTAG_EVENT_STR("message-summary"), + SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"), + SIPTAG_PAYLOAD_STR("Messages-Waiting: yes"), + TAG_END()); + + run_ab_until(ctx, -1, save_until_final_response, -1, accept_notify); + + /* Notifier events: nua_r_notify */ + TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_r_notify); + TEST(e->data->e_status, 200); + r_tags = e->data->e_tags; + TEST_1(tl_find(r_tags, nutag_substate)); + TEST(tl_find(r_tags, nutag_substate)->t_value, nua_substate_terminated); + + /* subscriber events: + nua_i_notify + */ + TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_notify); + TEST_1(sip = sip_object(e->data->e_msg)); + TEST_1(sip->sip_subscription_state); + TEST_S(sip->sip_subscription_state->ss_substate, "terminated"); + n_tags = e->data->e_tags; + TEST_1(tl_find(n_tags, nutag_substate)); + TEST(tl_find(n_tags, nutag_substate)->t_value, nua_substate_terminated); + TEST_1(!e->next); + + free_events_in_list(ctx, a->events); + free_events_in_list(ctx, b->events); + + if (print_headings) + printf("TEST NUA-11.7.3: PASSED\n"); + + nua_handle_destroy(a_call->nh), a_call->nh = NULL; + nua_handle_destroy(b_call->nh), b_call->nh = NULL; + + if (print_headings) + printf("TEST NUA-11.6: PASSED\n"); + + END(); +} + +/**Terminate when received notify. + * Respond to NOTIFY with 200 OK if it has not been responded. + * Save events (except nua_i_active or terminated). + */ +int accept_notify(CONDITION_PARAMS) +{ + if (event == nua_i_notify && status < 200) + RESPOND(ep, call, nh, SIP_200_OK, + NUTAG_WITH_THIS(ep->nua), + TAG_END()); + + save_event_in_list(ctx, event, ep, call); + + return event == nua_i_notify; +} + /* ======================================================================== */ /* Test simple methods: MESSAGE, PUBLISH, SUBSCRIBE/NOTIFY */ int test_simple(struct context *ctx) { return - test_message(ctx) - || test_publish(ctx) + /* test_message(ctx) + || */ test_publish(ctx) || test_subscribe_notify(ctx) + || test_newsub_notify(ctx) ; } diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.am index e39a2941cd..cf14047741 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.am @@ -58,4 +58,5 @@ EXTRA_DIST = Doxyfile sdp.docs $(BUILT_SOURCES) \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.in index 6d47abbe2f..52715f3637 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/sdp/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -56,8 +81,12 @@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = torture_sdp$(EXEEXT) test_sdp$(EXEEXT) DIST_COMMON = README $(dist_noinst_SCRIPTS) \ - $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog + $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/sdp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -110,6 +139,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -156,8 +186,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -201,6 +235,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -293,7 +328,7 @@ EXTRA_DIST = Doxyfile sdp.docs $(BUILT_SOURCES) \ tests/message-9.sdp \ tests/message-10.sdp -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -319,12 +354,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -564,7 +601,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip $(distdir)/tests + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip $(distdir)/tests @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -715,6 +752,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.am index 7ff975e0b5..ab0b808ab6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.am @@ -100,7 +100,7 @@ EXTRA_DIST = Doxyfile sip.docs sip_parser.docs sip.doxyaliases \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am MSG_PARSER_AWK = $(srcdir)/../msg/msg_parser.awk diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.in index 523c356ad6..29d3366c5b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/sip/Makefile.in @@ -21,11 +21,36 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. -SOURCES = $(libsip_la_SOURCES) date_test.c test_sip_msg.c torture_sip.c validator.c +SOURCES = $(libsip_la_SOURCES) test_date.c test_sip_msg.c torture_sip.c validator.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -51,9 +76,13 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = torture_sip$(EXEEXT) test_sip_msg$(EXEEXT) \ - validator$(EXEEXT) date_test$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog + validator$(EXEEXT) test_date$(EXEEXT) +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/sip ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -75,10 +104,10 @@ am_libsip_la_OBJECTS = sip_parser.lo sip_header.lo sip_util.lo \ sip_refer.lo sip_session.lo sip_caller_prefs.lo sip_reason.lo \ sip_status.lo sip_time.lo sip_tag_class.lo $(am__objects_1) libsip_la_OBJECTS = $(am_libsip_la_OBJECTS) -date_test_SOURCES = date_test.c -date_test_OBJECTS = date_test.$(OBJEXT) -date_test_LDADD = $(LDADD) -date_test_DEPENDENCIES = libsip.la ../msg/libmsg.la ../bnf/libbnf.la \ +test_date_SOURCES = test_date.c +test_date_OBJECTS = test_date.$(OBJEXT) +test_date_LDADD = $(LDADD) +test_date_DEPENDENCIES = libsip.la ../msg/libmsg.la ../bnf/libbnf.la \ ../url/liburl.la ../su/libsu.la test_sip_msg_SOURCES = test_sip_msg.c test_sip_msg_OBJECTS = test_sip_msg.$(OBJEXT) @@ -106,9 +135,9 @@ LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --mode=link --tag=CC $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libsip_la_SOURCES) date_test.c test_sip_msg.c \ +SOURCES = $(libsip_la_SOURCES) test_date.c test_sip_msg.c \ torture_sip.c validator.c -DIST_SOURCES = $(libsip_la_SOURCES) date_test.c test_sip_msg.c \ +DIST_SOURCES = $(libsip_la_SOURCES) test_date.c test_sip_msg.c \ torture_sip.c validator.c am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ @@ -123,6 +152,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -169,8 +199,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -214,6 +248,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -315,7 +350,7 @@ LDADD = libsip.la \ torture_sip_LDFLAGS = -static test_sip_msg_LDFLAGS = -static -date_test_LDFLAGS = -static +test_date_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules @@ -345,7 +380,7 @@ EXTRA_DIST = Doxyfile sip.docs sip_parser.docs sip.doxyaliases \ tests/test35.txt tests/test36.txt tests/test37.txt tests/test38.txt \ tests/test39.txt tests/test40.txt tests/test41.txt tests/test42.txt -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -371,13 +406,15 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Tests -#TESTS = torture_sip run_test_sip_msg run_date_test +#TESTS = torture_sip run_test_sip_msg run_test_date -#dist_noinst_SCRIPTS = run_test_sip_msg run_date_test +#dist_noinst_SCRIPTS = run_test_sip_msg run_test_date # ---------------------------------------------------------------------- # Sofia specific rules @@ -389,7 +426,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -436,9 +473,9 @@ clean-checkPROGRAMS: echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done -date_test$(EXEEXT): $(date_test_OBJECTS) $(date_test_DEPENDENCIES) - @rm -f date_test$(EXEEXT) - $(LINK) $(date_test_LDFLAGS) $(date_test_OBJECTS) $(date_test_LDADD) $(LIBS) +test_date$(EXEEXT): $(test_date_OBJECTS) $(test_date_DEPENDENCIES) + @rm -f test_date$(EXEEXT) + $(LINK) $(test_date_LDFLAGS) $(test_date_OBJECTS) $(test_date_LDADD) $(LIBS) test_sip_msg$(EXEEXT): $(test_sip_msg_OBJECTS) $(test_sip_msg_DEPENDENCIES) @rm -f test_sip_msg$(EXEEXT) $(LINK) $(test_sip_msg_LDFLAGS) $(test_sip_msg_OBJECTS) $(test_sip_msg_LDADD) $(LIBS) @@ -455,7 +492,6 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/date_test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_basic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_caller_prefs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_event.Plo@am__quote@ @@ -477,6 +513,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_tag_ref.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sip_util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_date.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_sip_msg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torture_sip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/validator.Po@am__quote@ @@ -580,7 +617,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/images $(distdir)/sofia-sip $(distdir)/tests + $(mkdir_p) $(distdir)/../../rules $(distdir)/images $(distdir)/sofia-sip $(distdir)/tests @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -730,6 +767,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # # Note: sip_bad_mask is used by nta to weed out bad messages # diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c index 2b08adf31f..39c376cda7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c @@ -757,6 +757,8 @@ char *sip_info_dup_one(sip_header_t *dst, /* ====================================================================== */ +#if SU_HAVE_EXPERIMENTAL + /**@SIP_HEADER sip_suppress_body_if_match Suppress-Body-If-Match Header * * The @b Suppress-Body-If-Match header field identifies a SIP event content @@ -773,7 +775,7 @@ char *sip_info_dup_one(sip_header_t *dst, * * @sa @RFC3265, draft-niemi-sip-subnot-etags-01.txt * - * @NEW_1_12_5. Note that #sip_t does not contain @a + * @EXP_1_12_5. Note that #sip_t does not contain @a * sip_suppress_body_if_match field, but sip_suppress_body_if_match() * function should be used for accessing the @b Suppress-Body-If-Match * header structure. @@ -839,7 +841,7 @@ issize_t sip_suppress_body_if_match_e(char b[], isize_t bsiz, * * @sa @RFC3265, draft-niemi-sip-subnot-etag-01 * - * @NEW_1_12_5. Note that #sip_t does not contain @a + * @EXP_1_12_5. Note that #sip_t does not contain @a * sip_suppress_notify_if_match field, but sip_suppress_notify_if_match() * function should be used for accessing the @b Suppress-Notify-If-Match * header structure. @@ -887,4 +889,4 @@ issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz, return msg_generic_e(b, bsiz, h, f); } - +#endif diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra_headers.txt b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra_headers.txt index 163a92f7f1..7c49732d16 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra_headers.txt +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra_headers.txt @@ -4,10 +4,15 @@ # The line format is: # C-name @SINCE sip_t-like-comment # +# Put all experimental things after EXPERIMENTAL HEADER LIST STARTS HERE... +# #### EXTRA HEADER LIST STARTS HERE #### -refer_sub @VERSION_1_12_5 /**< Refer-Sub header */ -suppress_body_if_match @VERSION_1_12_5 /**< Suppress-Body-If-Match header */ -suppress_notify_if_match @VERSION_1_12_5 /**< Suppress-Notify-If-Match header*/ +refer_sub @NEW_1_12_5 /**< Refer-Sub header */ + +#### EXPERIMENTAL HEADER LIST STARTS HERE #### + +suppress_body_if_match @EXP_1_12_5 /**< Suppress-Body-If-Match header */ +suppress_notify_if_match @EXP_1_12_5 /**< Suppress-Notify-If-Match header */ #### EXTRA HEADER LIST ENDS HERE #### diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/test_date.c b/libs/sofia-sip/libsofia-sip-ua/sip/test_date.c index 3d840e1021..f6107922ba 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/test_date.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/test_date.c @@ -33,6 +33,8 @@ * @date Wed Mar 21 19:12:13 2001 ppessi */ +#include "config.h" + #include #include #include diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c b/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c index cd9d5ceee8..58fe6d2e45 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c @@ -1653,7 +1653,11 @@ static int sip_header_test(void) TEST(count(sip->sip_content_type->c_common), 1); TEST(count(sip->sip_route->r_common), 0); TEST(count(sip->sip_record_route->r_common), 4); +#if SU_HAVE_EXPERIMENTAL TEST(count(sip->sip_unknown->un_common), 2); +#else + TEST(count(sip->sip_unknown->un_common), 4); +#endif TEST(count(sip->sip_error->er_common), 1); TEST(count(sip->sip_max_forwards->mf_common), 1); TEST(count(sip->sip_min_expires->me_common), 1); @@ -1667,6 +1671,7 @@ static int sip_header_test(void) TEST(sip->sip_max_forwards->mf_count, 12); TEST(sip->sip_min_expires->me_delta, 150); +#if SU_HAVE_EXPERIMENTAL { sip_suppress_body_if_match_t *sbim; sip_suppress_notify_if_match_t *snim; @@ -1683,6 +1688,7 @@ static int sip_header_test(void) TEST_SIZE(offsetof(msg_generic_t, g_value), offsetof(sip_suppress_notify_if_match_t, snim_tag)); } +#endif TEST_1(sip->sip_from->a_display); TEST_S(sip->sip_from->a_display, "h"); diff --git a/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.am index 5694677200..17925afe9a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.am @@ -58,6 +58,6 @@ EXTRA_DIST = Doxyfile soa.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = LIST=soa_tag_list \ No newline at end of file diff --git a/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.in index 986a81127a..3aa8e7b026 100644 --- a/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/soa/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(libsoa_la_SOURCES) test_soa.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_soa$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/soa ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -104,6 +133,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -150,8 +180,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -195,6 +229,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -288,7 +323,7 @@ test_soa_LDFLAGS = -static # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile soa.docs $(BUILT_SOURCES) -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -314,6 +349,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -323,7 +360,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -558,7 +595,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -708,6 +745,92 @@ clean-built-sources: ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libs/sofia-sip/libsofia-sip-ua/soa/soa.c b/libs/sofia-sip/libsofia-sip-ua/soa/soa.c index 4a5b66a439..7dc74a5edb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/soa/soa.c +++ b/libs/sofia-sip/libsofia-sip-ua/soa/soa.c @@ -167,7 +167,7 @@ int soa_add(char const *name, struct soa_namenode const *n; struct soa_namenode *e; - SU_DEBUG_9(("soa_add(%s%s%s, %p) called\n", NICE(name), actions)); + SU_DEBUG_9(("soa_add(%s%s%s, %p) called\n", NICE(name), (void *)actions)); if (name == NULL || actions == NULL) return su_seterrno(EFAULT); @@ -227,7 +227,7 @@ soa_session_t *soa_create(char const *name, size_t namelen; SU_DEBUG_9(("soa_create(\"%s\", %p, %p) called\n", - name ? name : "default", root, magic)); + name ? name : "default", (void *)root, (void *)magic)); if (name && name[0]) { struct soa_namenode const *n; @@ -276,7 +276,7 @@ soa_session_t *soa_clone(soa_session_t *parent_ss, SU_DEBUG_9(("soa_clone(%s::%p, %p, %p) called\n", parent_ss ? parent_ss->ss_actions->soa_name : "", - parent_ss, root, magic)); + (void *)parent_ss, (void *)root, (void *)magic)); if (parent_ss == NULL || root == NULL) return (void)su_seterrno(EFAULT), NULL; @@ -302,7 +302,7 @@ soa_session_t *soa_clone(soa_session_t *parent_ss, soa_session_t *soa_session_ref(soa_session_t *ss) { SU_DEBUG_9(("soa_session_ref(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); return su_home_ref(ss->ss_home); } @@ -310,7 +310,7 @@ soa_session_t *soa_session_ref(soa_session_t *ss) void soa_session_unref(soa_session_t *ss) { SU_DEBUG_9(("soa_session_unref(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); su_home_unref(ss->ss_home); } @@ -350,7 +350,7 @@ int soa_base_init(char const *name, void soa_destroy(soa_session_t *ss) { SU_DEBUG_9(("soa_destroy(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss) { ss->ss_active = 0; @@ -396,7 +396,7 @@ int soa_set_params(soa_session_t *ss, tag_type_t tag, tag_value_t value, ...) int n; SU_DEBUG_9(("soa_set_params(%s::%p, ...) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss == NULL) return su_seterrno(EFAULT), -1; @@ -606,7 +606,7 @@ int soa_get_params(soa_session_t const *ss, int n; SU_DEBUG_9(("soa_get_params(%s::%p, ...) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss == NULL) return su_seterrno(EFAULT), -1; @@ -688,7 +688,7 @@ tagi_t *soa_get_paramlist(soa_session_t const *ss, tagi_t *params = NULL; SU_DEBUG_9(("soa_get_paramlist(%s::%p, ...) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss) { ta_start(ta, tag, value); @@ -756,7 +756,7 @@ int soa_error_as_sip_response(soa_session_t *ss, char const **return_phrase) { SU_DEBUG_9(("soa_error_as_sip_response(%s::%p, ...) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss == NULL || ss->ss_status < 400 || ss->ss_status >= 700) { if (return_phrase) @@ -777,7 +777,7 @@ char const *soa_error_as_sip_reason(soa_session_t *ss) char *reason; SU_DEBUG_9(("soa_error_as_sip_reason(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss == NULL) return "SIP;cause=500;text=\"Internal Server Error\""; @@ -832,8 +832,8 @@ int soa_get_capability_sdp(soa_session_t const *ss, char const *sdp_str; SU_DEBUG_9(("soa_get_capability_sdp(%s::%p, [%p], [%p], [%p]) called\n", - ss ? ss->ss_actions->soa_name : "", ss, - return_sdp, return_sdp_str, return_len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, + (void *)return_sdp, (void *)return_sdp_str, (void *)return_len)); if (ss == NULL) return (void)su_seterrno(EFAULT), -1; @@ -878,7 +878,7 @@ int soa_set_capability_sdp(soa_session_t *ss, char const *str, issize_t len) { SU_DEBUG_9(("soa_set_capability_sdp(%s::%p, %p, %p, "MOD_ZD") called\n", - ss ? ss->ss_actions->soa_name : "", ss, sdp, str, (ssize_t)len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, (void *)sdp, (void *)str, (ssize_t)len)); return soa_set_sdp(ss, soa_capability_sdp_kind, sdp, str, len); } @@ -964,8 +964,8 @@ int soa_get_user_sdp(soa_session_t const *ss, char const *sdp_str; SU_DEBUG_9(("soa_get_user_sdp(%s::%p, [%p], [%p], [%p]) called\n", - ss ? ss->ss_actions->soa_name : "", ss, - return_sdp, return_sdp_str, return_len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, + (void *)return_sdp, (void *)return_sdp_str, (void *)return_len)); if (ss == NULL) return (void)su_seterrno(EFAULT), -1; @@ -1036,7 +1036,7 @@ int soa_set_user_sdp(soa_session_t *ss, char const *str, issize_t len) { SU_DEBUG_9(("soa_set_user_sdp(%s::%p, %p, %p, "MOD_ZD") called\n", - ss ? ss->ss_actions->soa_name : "", ss, sdp, str, (ssize_t)len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, (void *)sdp, (void *)str, (ssize_t)len)); return soa_set_sdp(ss, soa_user_sdp_kind, sdp, str, len); } @@ -1081,8 +1081,8 @@ int soa_get_remote_sdp(soa_session_t const *ss, char const *sdp_str; SU_DEBUG_9(("soa_get_remote_sdp(%s::%p, [%p], [%p], [%p]) called\n", - ss ? ss->ss_actions->soa_name : "", ss, - return_sdp, return_sdp_str, return_len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, + (void *)return_sdp, (void *)return_sdp_str, (void *)return_len)); if (ss == NULL) return (void)su_seterrno(EFAULT), -1; @@ -1155,7 +1155,7 @@ int soa_set_remote_sdp(soa_session_t *ss, char const *str, issize_t len) { SU_DEBUG_9(("soa_set_remote_sdp(%s::%p, %p, %p, "MOD_ZD") called\n", - ss ? ss->ss_actions->soa_name : "", ss, sdp, str, (ssize_t)len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, (void *)sdp, (void *)str, (ssize_t)len)); return soa_set_sdp(ss, soa_remote_sdp_kind, sdp, str, len); } @@ -1198,7 +1198,7 @@ int soa_base_set_remote_sdp(soa_session_t *ss, int soa_clear_remote_sdp(soa_session_t *ss) { SU_DEBUG_9(("soa_clear_remote_sdp(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (!ss) return (void)su_seterrno(EFAULT), -1; @@ -1253,8 +1253,8 @@ int soa_get_local_sdp(soa_session_t const *ss, char const *sdp_str; SU_DEBUG_9(("soa_get_local_sdp(%s::%p, [%p], [%p], [%p]) called\n", - ss ? ss->ss_actions->soa_name : "", ss, - return_sdp, return_sdp_str, return_len)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, + (void *)return_sdp, (void *)return_sdp_str, (void *)return_len)); if (ss == NULL) return (void)su_seterrno(EFAULT), -1; @@ -1286,7 +1286,7 @@ int soa_init_offer_answer(soa_session_t *ss) int complete; SU_DEBUG_9(("soa_init_offer_answer(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (!ss) return 0; @@ -1308,7 +1308,7 @@ int soa_init_offer_answer(soa_session_t *ss) char **soa_media_features(soa_session_t *ss, int live, su_home_t *home) { SU_DEBUG_9(("soa_media_features(%s::%p, %u, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, live, home)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, live, (void *)home)); if (ss) return ss->ss_actions->soa_media_features(ss, live, home); @@ -1324,7 +1324,7 @@ char **soa_base_media_features(soa_session_t *ss, int live, su_home_t *home) char const * const * soa_sip_require(soa_session_t const *ss) { SU_DEBUG_9(("soa_sip_require(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss) return ss->ss_actions->soa_sip_require(ss); @@ -1341,7 +1341,7 @@ char const * const * soa_base_sip_require(soa_session_t const *ss) char const * const * soa_sip_supported(soa_session_t const *ss) { SU_DEBUG_9(("soa_sip_supported(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); if (ss) return ss->ss_actions->soa_sip_supported(ss); @@ -1360,7 +1360,7 @@ int soa_remote_sip_features(soa_session_t *ss, char const * const * require) { SU_DEBUG_9(("soa_remote_sip_features(%s::%p, %p, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, supported, require)); + ss ? ss->ss_actions->soa_name : "", (void *)ss, (void *)supported, (void *)require)); if (ss) return ss->ss_actions->soa_remote_sip_features(ss, supported, require); @@ -1405,8 +1405,8 @@ int soa_generate_offer(soa_session_t *ss, int always, soa_callback_f *completed) { - SU_DEBUG_9(("soa_generate_offer(%s::%p, %u, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, always, completed)); + SU_DEBUG_9(("soa_generate_offer(%s::%p, %u) called\n", + ss ? ss->ss_actions->soa_name : "", (void *)ss, always)); /** @ERROR EFAULT Bad address. */ if (ss == NULL) @@ -1493,8 +1493,8 @@ int soa_base_generate_offer(soa_session_t *ss, int soa_generate_answer(soa_session_t *ss, soa_callback_f *completed) { - SU_DEBUG_9(("soa_generate_answer(%s::%p, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, completed)); + SU_DEBUG_9(("soa_generate_answer(%s::%p) called\n", + ss ? ss->ss_actions->soa_name : "", (void *)ss)); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) @@ -1573,8 +1573,8 @@ int soa_base_generate_answer(soa_session_t *ss, int soa_process_answer(soa_session_t *ss, soa_callback_f *completed) { - SU_DEBUG_9(("soa_process_answer(%s::%p, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, completed)); + SU_DEBUG_9(("soa_process_answer(%s::%p) called\n", + ss ? ss->ss_actions->soa_name : "", (void *)ss)); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) @@ -1654,8 +1654,8 @@ int soa_base_process_answer(soa_session_t *ss, int soa_process_reject(soa_session_t *ss, soa_callback_f *completed) { - SU_DEBUG_9(("soa_process_reject(%s::%p, %p) called\n", - ss ? ss->ss_actions->soa_name : "", ss, completed)); + SU_DEBUG_9(("soa_process_reject(%s::%p) called\n", + ss ? ss->ss_actions->soa_name : "", (void *)ss)); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) @@ -1711,7 +1711,7 @@ int soa_base_process_reject(soa_session_t *ss, int soa_activate(soa_session_t *ss, char const *option) { SU_DEBUG_9(("soa_activate(%s::%p, %s%s%s) called\n", - ss ? ss->ss_actions->soa_name : "", ss, NICE(option))); + ss ? ss->ss_actions->soa_name : "", (void *)ss, NICE(option))); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) @@ -1741,7 +1741,7 @@ int soa_base_activate(soa_session_t *ss, char const *option) int soa_deactivate(soa_session_t *ss, char const *option) { SU_DEBUG_9(("soa_deactivate(%s::%p, %s%s%s) called\n", - ss ? ss->ss_actions->soa_name : "", ss, NICE(option))); + ss ? ss->ss_actions->soa_name : "", (void *)ss, NICE(option))); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) @@ -1763,7 +1763,7 @@ int soa_base_deactivate(soa_session_t *ss, char const *option) void soa_terminate(soa_session_t *ss, char const *option) { SU_DEBUG_9(("soa_terminate(%s::%p) called\n", - ss ? ss->ss_actions->soa_name : "", ss)); + ss ? ss->ss_actions->soa_name : "", (void *)ss)); /** @ERROR EFAULT Bad address as @a ss. */ if (ss == NULL) diff --git a/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c b/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c index 4e6b57258c..47a74fb3dd 100644 --- a/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c +++ b/libs/sofia-sip/libsofia-sip-ua/soa/soa_static.c @@ -822,7 +822,7 @@ int soa_sdp_mode_set_is_needed(sdp_session_t const *session, sdp_mode_t recv_mode; SU_DEBUG_7(("soa_sdp_mode_set_is_needed(%p, %p, \"%s\"): called\n", - session, remote, hold ? hold : "")); + (void *)session, (void *)remote, hold ? hold : "")); if (!session ) return 0; @@ -865,7 +865,7 @@ int soa_sdp_mode_set(sdp_session_t *session, sdp_mode_t send_mode, recv_mode; SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n", - session, remote, hold ? hold : "")); + (void *)session, (void *)remote, hold ? hold : "")); if (!session || !session->sdp_media) return 0; @@ -928,7 +928,8 @@ static int offer_answer_step(soa_session_t *ss, su_home_auto(tmphome, sizeof tmphome); - SU_DEBUG_7(("soa_static_offer_answer_action(%p, %s): called\n", ss, by)); + SU_DEBUG_7(("soa_static_offer_answer_action(%p, %s): called\n", + (void *)ss, by)); if (user == NULL) return soa_set_status(ss, 500, "No session set by user"); @@ -954,7 +955,8 @@ static int offer_answer_step(soa_session_t *ss, if (local == NULL) switch (action) { case generate_offer: case generate_answer: - SU_DEBUG_7(("soa_static(%p, %s): generating local description\n", ss, by)); + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, + "generating local description")); local = local0; *local = *user, local->sdp_media = NULL; @@ -987,7 +989,7 @@ static int offer_answer_step(soa_session_t *ss, break; if (local != local0) *local0 = *local, local = local0; - SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, "upgrade with local description")); soa_sdp_upgrade(ss, tmphome, local, user, user); break; @@ -999,7 +1001,7 @@ static int offer_answer_step(soa_session_t *ss, if (1) { if (local != local0) *local0 = *local, local = local0; - SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, "upgrade with remote description")); soa_sdp_upgrade(ss, tmphome, local, user, remote); } @@ -1032,7 +1034,8 @@ static int offer_answer_step(soa_session_t *ss, } while (0) DUP_LOCAL(local); } - SU_DEBUG_7(("soa_static(%p, %s): marking rejected media\n", ss, by)); + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, + "marking rejected media")); soa_sdp_reject(tmphome, local, remote); } break; @@ -1065,7 +1068,7 @@ static int offer_answer_step(soa_session_t *ss, if (ss->ss_local_remote_version == remote_version) break; if (1 /* We don't have good test for codecs */) { - SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, "upgrade codecs with remote description")); if (local != local0) { *local0 = *local, local = local0; @@ -1143,7 +1146,8 @@ static int offer_answer_step(soa_session_t *ss, ss->ss_previous_remote_version = ss->ss_local_remote_version; } - SU_DEBUG_7(("soa_static(%p, %s): storing local description\n", ss, by)); + SU_DEBUG_7(("soa_static(%p, %s): %s\n", (void *)ss, by, + "storing local description")); /* Update the unparsed and pretty-printed descriptions */ if (soa_description_set(ss, ss->ss_local, local, NULL, 0) < 0) { diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.am index 2c0f342a0a..b77a8b2493 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.am @@ -61,4 +61,5 @@ dist_noinst_DATA = run_test_sresolv \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.in index f99faf84d4..8ba584ef10 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -56,8 +81,12 @@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = test_sresolv$(EXEEXT) DIST_COMMON = $(dist_noinst_DATA) $(nobase_include_sofia_HEADERS) \ - $(srcdir)/../sofia.am $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in ChangeLog + $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am \ + ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/sresolv ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -107,6 +136,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -153,8 +183,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -198,6 +232,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = $(SHELL) @@ -292,7 +327,7 @@ dist_noinst_DATA = run_test_sresolv \ 127.zone 194.2.188 3.f.f.e.1.2.0.0.3.0.1.2.c.0.0.0 example.com \ 3.f.f.e.1.2.0.0.3.0.1.2.c.0.0.0.arpa -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -318,11 +353,13 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -557,7 +594,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-resolv $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-resolv $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -706,6 +743,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/run_test_sresolv b/libs/sofia-sip/libsofia-sip-ua/sresolv/run_test_sresolv index ca015a69a5..8798bd3916 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/run_test_sresolv +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/run_test_sresolv @@ -56,7 +56,10 @@ if netstat --ip >/dev/null 2>&1 ; then fi # No named, no fun -type -p named >/dev/null || exit 77 +type -p named >/dev/null || { +echo test_sresolv: there is no BIND named installed, skipping +exit 77 +} if eval $ipv6 then diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c index 002b0c246c..69d508c0f2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c @@ -70,6 +70,10 @@ typedef int socklen_t; #endif #endif +#if HAVE_IPHLPAPI_H +#include +#endif + #include #include "sofia-resolv/sres.h" @@ -923,8 +927,8 @@ sres_query(sres_resolver_t *res, size_t dlen; char b[8]; - SU_DEBUG_9(("sres_query(%p, %p, %p, %s, \"%s\") called\n", - res, callback, context, sres_record_type(type, b), domain)); + SU_DEBUG_9(("sres_query(%p, %p, %s, \"%s\") called\n", + (void *)res, (void *)context, sres_record_type(type, b), domain)); if (res == NULL || domain == NULL) return su_seterrno(EFAULT), (void *)NULL; @@ -990,8 +994,8 @@ sres_search(sres_resolver_t *res, unsigned dots; char const *dot; char b[8]; - SU_DEBUG_9(("sres_search(%p, %p, %p, %s, \"%s\") called\n", - res, callback, context, sres_record_type(type, b), domain)); + SU_DEBUG_9(("sres_search(%p, %p, %s, \"%s\") called\n", + (void *)res, (void *)context, sres_record_type(type, b), domain)); if (res == NULL || domain == NULL) return su_seterrno(EFAULT), (void *)NULL; @@ -1235,7 +1239,7 @@ sres_search_cached_answers(sres_resolver_t *res, int i; SU_DEBUG_9(("sres_search_cached_answers(%p, %s, \"%s\") called\n", - res, sres_record_type(type, rooted_domain), domain)); + (void *)res, sres_record_type(type, rooted_domain), domain)); if (!res || !name) return su_seterrno(EFAULT), (void *)NULL; @@ -1894,6 +1898,36 @@ int sres_update_config(sres_resolver_t *res, int always, time_t now) #define QUERY_DATALEN 1024 #define MAX_DATALEN 65535 +/** + * Uses IP Helper IP to get DNS servers list. + */ +static int sres_parse_win32_ip(sres_config_t *c) +{ + int ret = -1; + +#if HAVE_IPHLPAPI_H + DWORD dw; + su_home_t *home = c->c_home; + ULONG size = sizeof(FIXED_INFO); + + do { + FIXED_INFO *info = (FIXED_INFO *)su_alloc(home, size); + dw = GetNetworkParams(info, &size); + if (dw == ERROR_SUCCESS) { + IP_ADDR_STRING* addr = &info->DnsServerList; + for (; addr; addr = addr->Next) { + SU_DEBUG_3(("Adding nameserver: %s\n", addr->IpAddress.String)); + sres_parse_nameserver(c, addr->IpAddress.String); + } + ret = 0; + } + su_free(home, info); + } while (dw == ERROR_BUFFER_OVERFLOW); +#endif + + return ret; +} + /** * Parses name servers listed in registry key 'key+lpValueName'. The * key is expected to contain a whitespace separate list of @@ -2072,7 +2106,7 @@ sres_config_t *sres_parse_resolv_conf(sres_resolver_t *res, #if _WIN32 /* note: no 127.0.0.1 on win32 systems */ /* on win32, query the registry for nameservers */ - if (sres_parse_win32_reg(c) == 0) + if (sres_parse_win32_ip(c) == 0 || sres_parse_win32_reg(c) == 0) /* success */; else /* now what? */; @@ -2558,7 +2592,7 @@ sres_send_dns_query(sres_resolver_t *res, if (now == 0) time(&now); - SU_DEBUG_9(("sres_send_dns_query(%p, %p) called\n", res, q)); + SU_DEBUG_9(("sres_send_dns_query(%p, %p) called\n", (void *)res, (void *)q)); if (domain == NULL) return -1; @@ -2645,7 +2679,7 @@ sres_send_dns_query(sres_resolver_t *res, SU_DEBUG_5(("%s(%p, %p) id=%u %s %s (to [%s]:%u)\n", "sres_send_dns_query", - res, q, id, sres_record_type(type, b), domain, + (void *)res, (void *)q, id, sres_record_type(type, b), domain, dns->dns_name, htons(((struct sockaddr_in *)dns->dns_addr)->sin_port))); @@ -2763,7 +2797,7 @@ sres_query_report_error(sres_query_t *q, } SU_DEBUG_5(("sres(q=%p): reporting errors for %u %s\n", - q, q->q_type, q->q_name)); + (void *)q, q->q_type, q->q_name)); sres_remove_query(q->q_res, q, 1); (q->q_callback)(q->q_context, q, answers); @@ -2830,7 +2864,7 @@ sres_resend_dns_query(sres_resolver_t *res, sres_query_t *q, int timeout) sres_server_t *dns; SU_DEBUG_9(("sres_resend_dns_query(%p, %p, %u) called\n", - res, q, timeout)); + (void *)res, (void *)q, timeout)); N = res->res_n_servers; @@ -2998,7 +3032,8 @@ int sres_resolver_error(sres_resolver_t *res, int socket) int n; char info[128] = ""; - SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_error", res, socket)); + SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_error", + (void *)res, socket)); msg->msg_name = name, msg->msg_namelen = sizeof(name); msg->msg_iov = iov, msg->msg_iovlen = 1; @@ -3111,7 +3146,8 @@ int sres_resolver_error(sres_resolver_t *res, int socket) int errcode = 0; socklen_t errorlen = sizeof(errcode); - SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_error", res, socket)); + SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_error", + (void *)res, socket)); getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&errcode, &errorlen); @@ -3203,7 +3239,8 @@ sres_resolver_receive(sres_resolver_t *res, int socket) struct sockaddr_storage from[1]; socklen_t fromlen = sizeof from; - SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_receive", res, socket)); + SU_DEBUG_9(("%s(%p, %u) called\n", "sres_resolver_receive", + (void *)res, socket)); memset(m, 0, offsetof(sres_message_t, m_data)); @@ -3282,7 +3319,7 @@ void sres_log_response(sres_resolver_t const *res, #endif SU_DEBUG_5(("sres_resolver_receive(%p, %p) id=%u (from [%s]:%u)\n", - res, query, m->m_id, + (void *)res, (void *)query, m->m_id, host, ntohs(((struct sockaddr_in *)from)->sin_port))); } } diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_blocking.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_blocking.c index 8d3d82a286..58751b1323 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_blocking.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_blocking.c @@ -86,7 +86,13 @@ struct sres_blocking_s #elif HAVE_SELECT struct { sres_socket_t fd; } fds[SRES_MAX_NAMESERVERS]; #else -#error No wait mechanism! +#warning No guaranteed wait mechanism! +/* typedef struct os_specific su_wait_t; */ +struct _pollfd { + sres_socket_t fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +} fds[SRES_MAX_NAMESERVERS]; #endif sres_record_t ***return_records; }; diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c index 1b1ae11ed4..2620cc9e64 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c @@ -178,7 +178,7 @@ int sres_cache_get(sres_cache_t *cache, *return_cached = NULL; SU_DEBUG_9(("%s(%p, %s, \"%s\") called\n", "sres_cache_get", - cache, sres_record_type(type, b), domain)); + (void *)cache, sres_record_type(type, b), domain)); hash = sres_hash_key(domain); @@ -241,7 +241,7 @@ int sres_cache_get(sres_cache_t *cache, UNLOCK(cache); SU_DEBUG_9(("%s(%p, %s, \"%s\") returned %d entries\n", "sres_cache_get", - cache, sres_record_type(type, b), domain, rr_count)); + (void *)cache, sres_record_type(type, b), domain, rr_count)); *return_cached = result; diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/sresolv.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/sresolv.c index 22b55e1a61..d1385bd3a0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/sresolv.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/sresolv.c @@ -186,8 +186,8 @@ static int sres_sofia_update(sres_sofia_t *srs, int i, index = -1, error = 0; int N = SRES_MAX_NAMESERVERS; - SU_DEBUG_9(("sres_sofia_update(%p, %d, %d)\n", srs, - (int)new_socket, (int)old_socket)); + SU_DEBUG_9(("sres_sofia_update(%p, %d, %d)\n", + (void *)srs, (int)new_socket, (int)old_socket)); if (srs == NULL) return 0; @@ -297,7 +297,7 @@ su_socket_t sres_resolver_root_socket(sres_resolver_t *res) if (!srs) return su_seterrno(EINVAL); - if (sres_resolver_set_async(res, sres_sofia_update, srs, 1) < 0) + if (sres_resolver_set_async(res, sres_sofia_update, srs, 1) == NULL) return INVALID_SOCKET; if (srs->srs_socket != INVALID_SOCKET) diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c index ef05a0b78b..0c369d278c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c +++ b/libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c @@ -101,7 +101,7 @@ struct sres_context_s sres_record_t **result; int timeout; - int sink; + sres_socket_t sink; int sinkidx; char const *sinkconf; @@ -1356,14 +1356,15 @@ int sink_make(sres_context_t *ctx) { char *tmpdir = getenv("TMPDIR"); char *template; - int fd, sink; + int fd; + sres_socket_t sink; struct sockaddr_in sin[1]; socklen_t sinsize = sizeof sin; FILE *f; BEGIN(); - sink = socket(AF_INET, SOCK_DGRAM, 0); TEST_1(sink != -1); + sink = socket(AF_INET, SOCK_DGRAM, 0); TEST_1(sink != INVALID_SOCKET); TEST(getsockname(sink, (struct sockaddr *)sin, &sinsize), 0); sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); TEST(bind(sink, (struct sockaddr *)sin, sinsize), 0); @@ -1427,7 +1428,7 @@ int sink_deinit(sres_context_t *ctx) if (ctx->sinkidx) su_root_deregister(ctx->root, ctx->sinkidx); ctx->sinkidx = 0; - su_close(ctx->sink), ctx->sink = -1; + su_close(ctx->sink), ctx->sink = INVALID_SOCKET; END(); } @@ -1541,12 +1542,12 @@ int test_expiration(sres_context_t *ctx) /* Convert lowercase hex to binary */ static void *hex2bin(char const *test_name, - char const *hex1, char const *hex2, unsigned *binsize) + char const *hex1, char const *hex2, size_t *binsize) { char output[2048]; char *bin; char const *b; - int j; + size_t j; if (hex1 == NULL || binsize == NULL) return NULL; @@ -1619,18 +1620,18 @@ int test_net(sres_context_t *ctx) { sres_resolver_t *res = ctx->resolver; sres_query_t *q = NULL; - int c = ctx->sink; + sres_socket_t c = ctx->sink; struct sockaddr_storage ss[1]; struct sockaddr *sa = (void *)ss; - socklen_t salen = sizeof ss, binlen; + socklen_t salen = sizeof ss; char *bin; - int i, n; + size_t i, n, binlen; char const *domain = "example.com"; char query[512]; BEGIN(); - TEST_1(ctx->sink != -1 && ctx->sink != 0); + TEST_1(ctx->sink != INVALID_SOCKET && ctx->sink != (sres_socket_t)0); /* Prepare for test_answer() callback */ sres_free_answers(ctx->resolver, ctx->result); @@ -1641,7 +1642,7 @@ int test_net(sres_context_t *ctx) TEST_1(bin = hex2bin(__func__, hextest, NULL, &binlen)); /* Send responses with one erroneus byte */ - for (i = 1; i < (int)binlen; i++) { + for (i = 1; i < binlen; i++) { if (!q) { /* We got an error => make new query */ TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */ @@ -1653,7 +1654,7 @@ int test_net(sres_context_t *ctx) bin[i] ^= 0xff; else bin[3] ^= SRES_FORMAT_ERR; /* format error -> EDNS0 failure */ - n = sendto(c, bin, binlen, 0, sa, salen); + n = su_sendto(c, bin, binlen, 0, sa, salen); if (i != 1) bin[i] ^= 0xff; else @@ -1669,15 +1670,15 @@ int test_net(sres_context_t *ctx) } /* Send runt responses */ - for (i = 1; i <= (int)binlen; i++) { + for (i = 1; i <= binlen; i++) { if (!q) { /* We got an error => make new query */ TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */ sres_type_naptr, domain)); - TEST_1((n = recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1); + TEST_1((n = su_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1); memcpy(bin, query, 2); /* Copy ID */ } - n = sendto(c, bin, i, 0, sa, salen); + n = su_sendto(c, bin, i, 0, sa, salen); if (n == -1) perror("sendto"); while (!poll_sockets(ctx)) @@ -1938,12 +1939,12 @@ int main(int argc, char **argv) } if (o_attach) { - char buf[8]; + char buf[8], *line; fprintf(stderr, "test_sresolv: started with pid %u" " (press enter to continue)\n", getpid()); - fgets(buf, sizeof buf, stdin); + line = fgets(buf, sizeof buf, stdin); (void) line; } #if HAVE_ALARM else if (o_alarm) { diff --git a/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.am index 73ed61eb8b..84816ef259 100644 --- a/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.am @@ -58,6 +58,6 @@ EXTRA_DIST = Doxyfile stun.docs cert.pem key.pem # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = LIST=stun_tag_list diff --git a/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.in index dbb0d59665..6d30891189 100644 --- a/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/stun/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # General options -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -56,8 +81,12 @@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = stunc$(EXEEXT) check_PROGRAMS = lookup_stun_server$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/stun ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -112,6 +141,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -158,8 +188,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -203,6 +237,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -291,7 +326,7 @@ lookup_stun_server_LDADD = libstun.la ../sresolv/libsresolv.la ../su/libsu.la # ---------------------------------------------------------------------- # Install and distribution rules EXTRA_DIST = Doxyfile stun.docs cert.pem key.pem -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -317,6 +352,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -326,7 +363,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -522,7 +559,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -674,6 +711,92 @@ clean-built-sources: ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libs/sofia-sip/libsofia-sip-ua/stun/stun.c b/libs/sofia-sip/libsofia-sip-ua/stun/stun.c index 478a315bec..940f31d052 100644 --- a/libs/sofia-sip/libsofia-sip-ua/stun/stun.c +++ b/libs/sofia-sip/libsofia-sip-ua/stun/stun.c @@ -57,7 +57,7 @@ #include #endif -#if defined(HAVE_OPENSSL) +#if HAVE_OPENSSL #include #endif @@ -218,7 +218,7 @@ struct stun_handle_s stun_discovery_magic_t *sh_dns_pend_ctx; tagi_t *sh_dns_pend_tags; -#if defined(HAVE_OPENSSL) +#if HAVE_OPENSSL SSL_CTX *sh_ctx; /**< SSL context for TLS */ SSL *sh_ssl; /**< SSL handle for TLS */ #else @@ -316,7 +316,7 @@ int stun_lifetime(stun_discovery_t *sd) } -#if defined(HAVE_OPENSSL) +#if HAVE_OPENSSL char const stun_version[] = "sofia-sip-stun using " OPENSSL_VERSION_TEXT; #else @@ -325,7 +325,9 @@ char const stun_version[] = #endif static int do_action(stun_handle_t *sh, stun_msg_t *binding_response); +#if HAVE_OPENSSL static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *arg); +#endif static int process_binding_request(stun_request_t *req, stun_msg_t *binding_response); static stun_discovery_t *stun_discovery_create(stun_handle_t *sh, stun_action_t action, @@ -349,9 +351,11 @@ static int get_localinfo(int family, su_sockaddr_t *su, socklen_t *return_len); static void stun_sendto_timer_cb(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg); +#if HAVE_OPENSSL static void stun_tls_connect_timer_cb(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg); +#endif static void stun_test_lifetime_timer_cb(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg); @@ -526,7 +530,7 @@ int stun_obtain_shared_secret(stun_handle_t *sh, stun_discovery_magic_t *magic, tag_type_t tag, tag_value_t value, ...) { -#if defined(HAVE_OPENSSL) +#if HAVE_OPENSSL int events = -1; int one, err = -1; su_wait_t wait[1] = { SU_WAIT_INIT }; @@ -1280,8 +1284,9 @@ int stun_test_nattype(stun_handle_t *sh, * Internal functions *******************************************************************/ -#if defined(HAVE_OPENSSL) -static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *arg) +#if HAVE_OPENSSL +static +int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *arg) { stun_discovery_t *sd = arg; stun_handle_t *self = sd->sd_handle; @@ -1298,7 +1303,7 @@ static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t * enter; - SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, self, + SU_DEBUG_7(("%s(%p): events%s%s%s%s\n", __func__, (void *)self, events & SU_WAIT_CONNECT ? " CONNECTED" : "", events & SU_WAIT_ERR ? " ERR" : "", events & SU_WAIT_IN ? " IN" : "", @@ -1528,15 +1533,11 @@ static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t * return 0; } -#else -static int stun_tls_callback(su_root_magic_t *m, su_wait_t *w, su_wakeup_arg_t *arg) -{ - return 0; -} + #endif /* HAVE_OPENSSL */ -#if defined(HAVE_OPENSSL) +#if HAVE_OPENSSL static void stun_tls_connect_timer_cb(su_root_magic_t *magic, su_timer_t *t, su_timer_arg_t *arg) @@ -1566,12 +1567,7 @@ static void stun_tls_connect_timer_cb(su_root_magic_t *magic, return; } -#else -static void stun_tls_connect_timer_cb(su_root_magic_t *magic, - su_timer_t *t, - su_timer_arg_t *arg) -{ -} + #endif /* HAVE_OPENSSL */ /** Compose a STUN message of the format defined by stun_msg_t @@ -1664,7 +1660,7 @@ static int stun_bind_callback(stun_magic_t *m, su_wait_t *w, su_wakeup_arg_t *ar enter; - SU_DEBUG_7(("%s(%p): events%s%s%s\n", __func__, self, + SU_DEBUG_7(("%s(%p): events%s%s%s\n", __func__, (void *)self, events & SU_WAIT_IN ? " IN" : "", events & SU_WAIT_OUT ? " OUT" : "", events & SU_WAIT_ERR ? " ERR" : "")); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/su/Makefile.am index 2e5745858b..bbab6db0f9 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/su/Makefile.am @@ -77,7 +77,10 @@ libsu_la_SOURCES = \ su_alloc.c su_alloc_lock.c su_strdup.c su_sprintf.c \ su_strlst.c su_vector.c \ su_time.c su_time0.c \ - su_wait.c su_root.c su_timer.c su_port.c su_port.h \ + su_wait.c su_root.c su_timer.c \ + su_port.c su_port.h \ + su_base_port.c su_pthread_port.c \ + su_poll_port.c su_epoll_port.c su_select_port.c \ su_localinfo.c \ su_os_nw.c \ su_taglist.c su_tag.c su_tag_io.c \ @@ -88,8 +91,8 @@ libsu_la_SOURCES = \ EXTRA_libsu_la_SOURCES = \ memmem.c strtoull.c strcasestr.c \ memspn.c memcspn.c memccpy.c \ - inet_ntop.c inet_pton.c getopt.c \ - su_tag_ref.c + inet_ntop.c inet_pton.c poll.c getopt.c \ + su_tag_ref.c su_win32_port.c libsu_la_LIBADD = $(REPLACE_LIBADD) libsu_la_DEPENDENCIES = $(REPLACE_LIBADD) @@ -116,4 +119,4 @@ AUTOMAKE_OPTIONS = foreign # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am diff --git a/libs/sofia-sip/libsofia-sip-ua/su/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/su/Makefile.in index 4effcddc6e..f21a5378bc 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/su/Makefile.in @@ -28,8 +28,33 @@ # ---------------------------------------------------------------------- # Build targets -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -68,8 +93,12 @@ check_PROGRAMS = torture_su$(EXEEXT) torture_su_port$(EXEEXT) \ torture_su_timer$(EXEEXT) test_su$(EXEEXT) su_proxy$(EXEEXT) \ test_poll$(EXEEXT) $(am__EXEEXT_1) DIST_COMMON = $(am__nobase_include_sofia_HEADERS_DIST) \ - $(dist_pkgdata_SCRIPTS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog + $(dist_pkgdata_SCRIPTS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/su ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -87,18 +116,21 @@ am__DEPENDENCIES_1 = am__libsu_la_SOURCES_DIST = su.c su_errno.c su_addrinfo.c su_alloc.c \ su_alloc_lock.c su_strdup.c su_sprintf.c su_strlst.c \ su_vector.c su_time.c su_time0.c su_wait.c su_root.c \ - su_timer.c su_port.c su_port.h su_localinfo.c su_os_nw.c \ - su_taglist.c su_tag.c su_tag_io.c su_log.c su_global_log.c \ - su_default_log.c su_module_debug.h su_md5.c su_uniqueid.c \ - su_bm.c su_osx_runloop.c + su_timer.c su_port.c su_port.h su_base_port.c \ + su_pthread_port.c su_poll_port.c su_epoll_port.c \ + su_select_port.c su_localinfo.c su_os_nw.c su_taglist.c \ + su_tag.c su_tag_io.c su_log.c su_global_log.c su_default_log.c \ + su_module_debug.h su_md5.c su_uniqueid.c su_bm.c \ + su_osx_runloop.c @COREFOUNDATION_TRUE@am__objects_1 = su_osx_runloop.lo am_libsu_la_OBJECTS = su.lo su_errno.lo su_addrinfo.lo su_alloc.lo \ su_alloc_lock.lo su_strdup.lo su_sprintf.lo su_strlst.lo \ su_vector.lo su_time.lo su_time0.lo su_wait.lo su_root.lo \ - su_timer.lo su_port.lo su_localinfo.lo su_os_nw.lo \ - su_taglist.lo su_tag.lo su_tag_io.lo su_log.lo \ - su_global_log.lo su_default_log.lo su_md5.lo su_uniqueid.lo \ - su_bm.lo $(am__objects_1) + su_timer.lo su_port.lo su_base_port.lo su_pthread_port.lo \ + su_poll_port.lo su_epoll_port.lo su_select_port.lo \ + su_localinfo.lo su_os_nw.lo su_taglist.lo su_tag.lo \ + su_tag_io.lo su_log.lo su_global_log.lo su_default_log.lo \ + su_md5.lo su_uniqueid.lo su_bm.lo $(am__objects_1) libsu_la_OBJECTS = $(am_libsu_la_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)" \ "$(DESTDIR)$(include_sofiadir)" \ @@ -231,6 +263,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -277,8 +310,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -322,6 +359,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -429,7 +467,10 @@ libsu_la_SOURCES = \ su_alloc.c su_alloc_lock.c su_strdup.c su_sprintf.c \ su_strlst.c su_vector.c \ su_time.c su_time0.c \ - su_wait.c su_root.c su_timer.c su_port.c su_port.h \ + su_wait.c su_root.c su_timer.c \ + su_port.c su_port.h \ + su_base_port.c su_pthread_port.c \ + su_poll_port.c su_epoll_port.c su_select_port.c \ su_localinfo.c \ su_os_nw.c \ su_taglist.c su_tag.c su_tag_io.c \ @@ -439,8 +480,8 @@ libsu_la_SOURCES = \ EXTRA_libsu_la_SOURCES = \ memmem.c strtoull.c strcasestr.c \ memspn.c memcspn.c memccpy.c \ - inet_ntop.c inet_pton.c getopt.c \ - su_tag_ref.c + inet_ntop.c inet_pton.c poll.c getopt.c \ + su_tag_ref.c su_win32_port.c libsu_la_LIBADD = $(REPLACE_LIBADD) libsu_la_DEPENDENCIES = $(REPLACE_LIBADD) @@ -457,7 +498,7 @@ dist_pkgdata_SCRIPTS = tag_dll.awk # ---------------------------------------------------------------------- # Automake options AUTOMAKE_OPTIONS = foreign -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -483,12 +524,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -652,14 +695,17 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcspn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memmem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memspn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/poll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strcasestr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strtoull.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_addrinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_alloc_lock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_base_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_bm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_default_log.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_epoll_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_errno.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_global_log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_localinfo.Plo@am__quote@ @@ -667,9 +713,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_md5.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_os_nw.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_osx_runloop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_poll_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_proxy.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_pthread_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_root.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_select_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_sprintf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_strdup.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_strlst.Plo@am__quote@ @@ -683,6 +732,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_uniqueid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_wait.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/su_win32_port.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_htable.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_memmem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_poll.Po@am__quote@ @@ -890,7 +940,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -1051,6 +1101,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/su/addrinfo.c b/libs/sofia-sip/libsofia-sip-ua/su/addrinfo.c index b9e73ab950..3b92077d84 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/addrinfo.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/addrinfo.c @@ -1,7 +1,7 @@ /* * This file is part of the Sofia-SIP package * - * Copyright (C) 2005 Nokia Corporation. + * Copyright (C) 2005,2007 Nokia Corporation. * * Contact: Pekka Pessi * @@ -26,12 +26,13 @@ * * @section synopsis Synopsis * - * addrinfo [-pcn46] host service + * addrinfo [-pcn46] service-name host * * @section description Description * * The @em addrinfo utility will use su_getaddrinfo() to resolve the network - * services and print resolved names. + * services and print resolved names. See sect 6.1 of RFC3493 and the getaddrinfo(3) + * manual page of POSIX 1003.1g, for more information. * * @section options Options * @@ -56,7 +57,7 @@ * Written by Pekka Pessi * * @section copyright Copyright - * Copyright (C) 2005 Nokia Corporation. + * Copyright (C) 2005,2007 Nokia Corporation. * * This program is free software; see the source for copying conditions. * There is @b NO warranty; not even for @b MERCHANTABILITY or FITNESS @@ -72,7 +73,7 @@ #include "sofia-sip/su.h" char const help[] = -"usage: addrinfo [-pnc46] [domainname]\n" +"usage: addrinfo [-pnc46] \n" "\t-p query for passive open\n" "\t-n use numeric host names\n" "\t-c ask for canonic names\n" diff --git a/libs/sofia-sip/libsofia-sip-ua/su/poll.c b/libs/sofia-sip/libsofia-sip-ua/su/poll.c new file mode 100644 index 0000000000..35159ad1b2 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/poll.c @@ -0,0 +1,255 @@ +/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "config.h" + +#if !HAVE_POLL && HAVE_SELECT && HAVE_POLL_PORT + +#include "sofia-sip/su.h" + + +//extern __typeof(poll) __libc_poll; + +#if 1 + +#include +#include + +#include "sofia-sip/su_wait.h" + +#ifndef __NFDBITS +#define NBBY 8 /* bits in a byte */ +#define __NFDBITS (sizeof(__int32_t) * NBBY) /* bits per mask */ +#endif + + +#undef howmany + +#ifndef howmany +#define howmany(x, y) (((x)+((y)-1))/(y)) * sizeof(uint32_t) +#endif + +//libc_hidden_proto(memcpy) +//libc_hidden_proto(memset) +//libc_hidden_proto(getdtablesize) +//libc_hidden_proto(select) + +/* uClinux 2.0 doesn't have poll, emulate it using select */ + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + struct timeval tv; +#if HAVE_ALLOCA_H + static int max_fd_size; + int bytes; + fd_set *rset, *wset, *xset; +#else + fd_set rset[1], wset[1], xset[1]; +#endif + struct pollfd *f; + int ready; + int maxfd = 0; + +#if HAVE_ALLOCA_H + if (!max_fd_size) + max_fd_size = getdtablesize (); + + bytes = howmany (max_fd_size, __NFDBITS); + + rset = alloca (bytes); + wset = alloca (bytes); + xset = alloca (bytes); + + /* We can't call FD_ZERO, since FD_ZERO only works with sets + of exactly __FD_SETSIZE size. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); +#else + FD_ZERO(rset); + FD_ZERO(wset); + FD_ZERO(xset); +#endif + + + for (f = fds; f < &fds[nfds]; ++f) + { + f->revents = 0; + if (f->fd >= 0) + { +#if HAVE_ALLOCA_H + if (f->fd >= max_fd_size) + { + /* The user provides a file descriptor number which is higher + than the maximum we got from the `getdtablesize' call. + Maybe this is ok so enlarge the arrays. */ + fd_set *nrset, *nwset, *nxset; + int nbytes; + + max_fd_size = roundup (f->fd, __NFDBITS); + nbytes = howmany (max_fd_size, __NFDBITS); + + nrset = alloca (nbytes); + nwset = alloca (nbytes); + nxset = alloca (nbytes); + + memset ((char *) nrset + bytes, 0, nbytes - bytes); + memset ((char *) nwset + bytes, 0, nbytes - bytes); + memset ((char *) nxset + bytes, 0, nbytes - bytes); + + rset = memcpy (nrset, rset, bytes); + wset = memcpy (nwset, wset, bytes); + xset = memcpy (nxset, xset, bytes); + + bytes = nbytes; + } +#else + if (f->fd >= FD_SETSIZE) { + errno = EBADF; + return -1; + } +#endif /* HAVE_ALLOCA_H */ + + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + } + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + while (1) + { + ready = select (maxfd + 1, rset, wset, xset, + timeout == -1 ? NULL : &tv); + + /* It might be that one or more of the file descriptors is invalid. + We now try to find and mark them and then try again. */ + if (ready == -1 && errno == EBADF) + { + struct timeval sngl_tv; +#if HAVE_ALLOCA_H + fd_set *sngl_rset = alloca (bytes); + fd_set *sngl_wset = alloca (bytes); + fd_set *sngl_xset = alloca (bytes); + + /* Clear the original set. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); +#else + fd_set sngl_rset[1]; + fd_set sngl_wset[1]; + fd_set sngl_xset[1]; + + FD_ZERO(rset); + FD_ZERO(wset); + FD_ZERO(xset); +#endif + + /* This means we don't wait for input. */ + sngl_tv.tv_sec = 0; + sngl_tv.tv_usec = 0; + + maxfd = -1; + + /* Reset the return value. */ + ready = 0; + + for (f = fds; f < &fds[nfds]; ++f) + if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) + && (f->revents & POLLNVAL) == 0) + { + int n; + +#if HAVE_ALLOCA_H + memset (sngl_rset, 0, bytes); + memset (sngl_wset, 0, bytes); + memset (sngl_xset, 0, bytes); +#else + FD_ZERO(rset); + FD_ZERO(wset); + FD_ZERO(xset); +#endif + + if (f->events & POLLIN) + FD_SET (f->fd, sngl_rset); + if (f->events & POLLOUT) + FD_SET (f->fd, sngl_wset); + if (f->events & POLLPRI) + FD_SET (f->fd, sngl_xset); + + n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, + &sngl_tv); + if (n != -1) + { + /* This descriptor is ok. */ + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd) + maxfd = f->fd; + if (n > 0) + /* Count it as being available. */ + ++ready; + } + else if (errno == EBADF) + f->revents |= POLLNVAL; + } + /* Try again. */ + continue; + } + + break; + } + + if (ready > 0) + for (f = fds; f < &fds[nfds]; ++f) + { + if (f->fd >= 0) + { + if (FD_ISSET (f->fd, rset)) + f->revents |= POLLIN; + if (FD_ISSET (f->fd, wset)) + f->revents |= POLLOUT; + if (FD_ISSET (f->fd, xset)) + f->revents |= POLLPRI; + } + } + + return ready; +} + +#endif +#endif diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_bm.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_bm.h index 0e7915ba3e..a9ee6ba991 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_bm.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_bm.h @@ -45,15 +45,15 @@ typedef struct bw_fwd_table bm_fwd_table_t; SOFIAPUBFUN bm_fwd_table_t *bm_memmem_study(char const *needle, size_t nlen); -SOFIAPUBFUN char const* bm_memmem(char const *haystack, size_t hlen, - char const *needle, size_t nlen, - bm_fwd_table_t *fwd); +SOFIAPUBFUN char *bm_memmem(char const *haystack, size_t hlen, + char const *needle, size_t nlen, + bm_fwd_table_t *fwd); SOFIAPUBFUN bm_fwd_table_t *bm_memcasemem_study(char const *needle, size_t); -SOFIAPUBFUN char const* bm_memcasemem(char const *haystack, size_t hlen, - char const *needle, size_t nlen, - bm_fwd_table_t *fwd); +SOFIAPUBFUN char *bm_memcasemem(char const *haystack, size_t hlen, + char const *needle, size_t nlen, + bm_fwd_table_t *fwd); SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h.in b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h.in index 814fea2a43..687463a883 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h.in +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h.in @@ -75,6 +75,12 @@ /** Define as 1 if you have OSX CoreFoundation interface */ #undef SU_HAVE_OSX_CF_API +/** Define as 1 if you want to enable experimental features. + * + * Use --enable-experimental with ./configure + */ +#undef SU_HAVE_EXPERIMENTAL + /** Define as 1 if you have inline functions */ #undef SU_HAVE_INLINE /** Define as suitable declarator inline functions */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h index 73d37adefa..33674605f8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_tag.h @@ -174,7 +174,7 @@ SOFIAPUBFUN void tl_vfree(tagi_t *t); #if SU_HAVE_INLINE su_inline tag_value_t tag_int_v(int v) { return (tag_value_t)v; } su_inline tag_value_t tag_int_vr(int *vp) { return (tag_value_t)vp; } -su_inline tag_value_t tag_uint_v(size_t v) { return (tag_value_t)v; } +su_inline tag_value_t tag_uint_v(unsigned v) { return (tag_value_t)v; } su_inline tag_value_t tag_uint_vr(unsigned *vp) { return (tag_value_t)vp; } su_inline tag_value_t tag_usize_v(usize_t v) { return (tag_value_t)v; } su_inline tag_value_t tag_usize_vr(usize_t *vp) { return (tag_value_t)vp; } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h index 1b22eb0d8c..ad2ad69e88 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h @@ -101,35 +101,71 @@ SOFIA_BEGIN_DECLS #define SU_WAIT_MAX (64) #else -#define SU_WAIT_CMP(x, y) -#define SU_WAIT_IN -#define SU_WAIT_OUT -#define SU_WAIT_ERR -#define SU_WAIT_HUP -#define SU_WAIT_ACCEPT -#define SU_WAIT_FOREVER -#define SU_WAIT_TIMEOUT +/* If nothing works, try these */ -#define SU_WAIT_INIT +#define POLLIN 0x001 +#define POLLPRI 0x002 +#define POLLOUT 0x004 + +#ifdef __USE_XOPEN +#define POLLRDNORM 0x040 +#define POLLRDBAND 0x080 +#define POLLWRNORM 0x100 +#define POLLWRBAND 0x200 +#endif + +/* These for pollfd.revents */ +#define POLLERR 0x008 +#define POLLHUP 0x010 +#define POLLNVAL 0x020 + +#define SU_WAIT_CMP(x, y) \ + (((x).fd - (y).fd) ? ((x).fd - (y).fd) : ((x).events - (y).events)) + +#define SU_WAIT_IN POLLIN +#define SU_WAIT_OUT POLLOUT +#define SU_WAIT_CONNECT POLLOUT +#define SU_WAIT_ERR POLLERR +#define SU_WAIT_HUP POLLHUP +#define SU_WAIT_ACCEPT POLLIN +#define SU_WAIT_FOREVER (-1) +#define SU_WAIT_TIMEOUT (-2) + +#define SU_WAIT_INIT { INVALID_SOCKET, 0, 0 } + +/** Maximum number of sources supported by su_wait() */ +#define SU_WAIT_MAX (0x7fffffff) #endif /* ---------------------------------------------------------------------- */ /* Types */ -#if 0 -typedef struct _pollfd { - su_socket_t fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -} su_wait_t; -#elif SU_HAVE_POLL +/** Wait object. */ +#if SU_HAVE_POLL typedef struct pollfd su_wait_t; #elif SU_HAVE_WINSOCK typedef HANDLE su_wait_t; #else -/** Wait object. */ -typedef struct os_specific su_wait_t; +/* typedef struct os_specific su_wait_t; */ +typedef struct pollfd su_wait_t; +struct pollfd { + su_socket_t fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; + + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ +int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); + #endif /* Used by AD */ @@ -191,7 +227,7 @@ typedef SU_ROOT_MAGIC_T su_root_magic_t; */ typedef SU_WAKEUP_ARG_T su_wakeup_arg_t; -/** Wakeup callback function prototype. +/** Wakeup callback function pointer type. * * Whenever a registered wait object receives an event, the @link * ::su_wakeup_f callback function @endlink is invoked. @@ -316,9 +352,13 @@ typedef su_msg_t * const su_msg_cr[1]; #define SU_MSG_R_INIT { NULL } /** Message delivery function type. */ -typedef void (*su_msg_f)(su_root_magic_t *magic, - su_msg_r msg, - su_msg_arg_t *arg); +typedef void su_msg_function(su_root_magic_t *magic, + su_msg_r msg, + su_msg_arg_t *arg); + +/** Message delivery function pointer type. */ +typedef su_msg_function *su_msg_f; + /* ---------------------------------------------------------------------- */ @@ -350,7 +390,7 @@ SOFIAPUBFUN int su_wait(su_wait_t waits[], unsigned n, su_duration_t timeout); SOFIAPUBFUN int su_wait_events(su_wait_t *wait, su_socket_t s); SOFIAPUBFUN int su_wait_mask(su_wait_t *dst, su_socket_t s, int events); -#if SU_HAVE_POLL +#if !HAVE_WIN32 && (SU_HAVE_POLL || HAVE_SELECT) static inline su_socket_t su_wait_socket(su_wait_t *wait) { diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su.c b/libs/sofia-sip/libsofia-sip-ua/su/su.c index 9dd78f023b..1b97828341 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su.c @@ -32,14 +32,16 @@ #include "config.h" -#include -#include -#include - #include "sofia-sip/su.h" #include "sofia-sip/su_log.h" #include "sofia-sip/su_alloc.h" +#include +#include +#if HAVE_SIGNAL +#include +#endif + #if !SU_HAVE_BSDSOCK && !SU_HAVE_WINSOCK #error Bad configuration #endif @@ -67,7 +69,9 @@ int su_init(void) { su_home_threadsafe(NULL); +#if HAVE_SIGPIPE signal(SIGPIPE, SIG_IGN); /* we want to get EPIPE instead */ +#endif su_log_init(su_log_default); su_log_init(su_log_global); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c index 9b02edb237..0a679cc5bb 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc.c @@ -87,8 +87,8 @@ * * As you might have guessed, it is also possible to use reference counting * with home objects. The function su_home_ref() increases the reference - * count, su_home_unref() decreases. A newly allocated home object has - * reference count of 1. + * count, su_home_unref() decreases it. A newly allocated or initialized + * home object has reference count of 1. * * @note Please note that while it is possible to create new references to * secondary home objects which have a parent home, the secondary home @@ -104,10 +104,13 @@ * @note * * The su_home_destroy() function is deprecated as it does not free the home - * object itself. + * object itself. Like su_home_deinit(), it should be called only on home + * objects with reference count of 1. * - * The function su_home_init() initializes a home object with infinite - * reference count. It must be deinitialized with su_home_deinit(). + * The function su_home_init() initializes a home object structure. When the + * initialized home object is destroyed or deinitialized or its reference + * count reaches zero, the memory allocate thorugh it reclaimed but the home + * object structure itself is not freed. * * @section su_home_destructor_usage Destructors * @@ -148,19 +151,20 @@ * @section su_alloc_threadsafe Threadsafe Operation * * If multiple threads need to access same home object, it must be marked as - * @c threadsafe by calling su_home_threadsafe() with the home pointer as + * @e threadsafe by calling su_home_threadsafe() with the home pointer as * argument. The threadsafeness is not inherited by clones. * * The threadsafe home objects can be locked and unlocked with - * su_home_mutex_lock() and su_home_mutex_unlock(). + * su_home_mutex_lock() and su_home_mutex_unlock(). These operations are + * no-op on home object that is not threadsafe. * * @section su_alloc_preloading Preloading a Memory Home * - * In some situations there is quite heavy overhead when using the global - * heap allocator. The overhead caused by the large number of small + * In some situations there is quite heavy overhead if the global heap + * allocator is used. The overhead caused by the large number of small * allocations can be reduced by using su_home_preload(): it allocates or * preloads some a memory to home to be used as a kind of private heap. The - * preloaded memory area is then used to satisfy small enough allocations. + * preloaded memory area is then used to satisfy small enough allocations. * For instance, the SIP parser typically preloads some 2K of memory when it * starts to parse the message. * @@ -172,10 +176,9 @@ * far as possible; if it is not enough, allocation is made from heap. * * The word @e auto refers to the automatic scope; however, the home object - * initialized with su_home_auto() must be explicitly deinitialized with - * su_home_deinit() when the program exits the scope where the stack frame - * used in su_home_auto() was allocate. - * + * that was initialized with su_home_auto() must be explicitly deinitialized + * with su_home_deinit() or su_home_unref() when the program exits the scope + * where the stack frame used in su_home_auto() was allocated. */ #include @@ -196,6 +199,8 @@ void (*su_home_unlocker)(void *mutex); void (*su_home_mutex_locker)(void *mutex); void (*su_home_mutex_unlocker)(void *mutex); +void (*su_home_destroy_mutexes)(void *mutex); + #define MEMLOCK(h) \ (((h) && (h)->suh_lock ? su_home_locker((h)->suh_lock) : (void)0), (h)->suh_blocks) #define UNLOCK(h) (((h) && (h)->suh_lock ? su_home_unlocker((h)->suh_lock) : (void)0), NULL) @@ -221,10 +226,10 @@ enum { #define ALIGNMENT (8) #define ALIGN(n) (size_t)(((n) + (ALIGNMENT - 1)) & (size_t)~(ALIGNMENT - 1)) -#define SIZEBITS (sizeof (size_t) * 8 - 1) +#define SIZEBITS (sizeof (unsigned) * 8 - 1) typedef struct { - size_t sua_size:SIZEBITS; /**< Size of the block */ + unsigned sua_size:SIZEBITS; /**< Size of the block */ unsigned sua_home:1; /**< Is this another home? */ unsigned :0; void *sua_data; /**< Data pointer */ @@ -242,8 +247,9 @@ struct su_block_s { unsigned sub_prsize:16; /**< Preload size */ unsigned sub_prused:16; /**< Used from preload */ - unsigned sub_auto:1; /**< struct su_block_s is from stack! */ - unsigned sub_preauto:1; /**< Preload is from stack! */ + unsigned sub_hauto:1; /**< "Home" is not from malloc */ + unsigned sub_auto:1; /**< struct su_block_s is not from malloc */ + unsigned sub_preauto:1; /**< Preload is not from malloc */ unsigned sub_auto_all:1; /**< Everything is from stack! */ unsigned :0; @@ -255,7 +261,7 @@ static void su_home_check_blocks(su_block_t const *b); static void su_home_stats_alloc(su_block_t *, void *p, void *preload, size_t size, int zero); static void su_home_stats_free(su_block_t *sub, void *p, void *preload, - size_t size); + unsigned size); static void _su_home_deinit(su_home_t *home); @@ -345,7 +351,7 @@ static inline int su_alloc_check(su_block_t const *sub, su_alloc_t const *sua) size_t size, term; assert(sua); if (sua) { - size = sua->sua_size; + size = (size_t)sua->sua_size; memcpy(&term, (char *)sua->sua_data + size, sizeof (term)); assert(size - term == 0); return size - term == 0; @@ -358,8 +364,9 @@ static inline int su_alloc_check(su_block_t const *sub, su_alloc_t const *sua) /** Allocate the block hash table. * - * The function su_hash_alloc() allocates a block hash table of @a n - * elements. + * @internal + * + * Allocate a block hash table of @a n elements. * * @param home pointer to home object * @param n number of buckets in hash table @@ -372,8 +379,12 @@ static inline su_block_t *su_hash_alloc(size_t n) { su_block_t *b = calloc(1, offsetof(su_block_t, sub_nodes[n])); - if (b) + if (b) { + /* Implicit su_home_init(); */ + b->sub_ref = 1; + b->sub_hauto = 1; b->sub_n = n; + } return b; } @@ -381,6 +392,8 @@ static inline su_block_t *su_hash_alloc(size_t n) enum sub_zero { do_malloc, do_calloc, do_clone }; /** Allocate a memory block. + * + * @internal * * Precondition: locked home * @@ -399,7 +412,10 @@ void *sub_alloc(su_home_t *home, { void *data, *preload = NULL; - assert (size < (1UL << SIZEBITS)); + assert (size < (((size_t)1) << SIZEBITS)); + + if (size >= ((size_t)1) << SIZEBITS) + return (void)(errno = ENOMEM), NULL; if (sub == NULL || 3 * sub->sub_used > 2 * sub->sub_n) { /* Resize the hash table */ @@ -429,6 +445,7 @@ void *sub_alloc(su_home_t *home, b2->sub_preload = sub->sub_preload; b2->sub_prsize = sub->sub_prsize; b2->sub_prused = sub->sub_prused; + b2->sub_hauto = sub->sub_hauto; b2->sub_preauto = sub->sub_preauto; b2->sub_destructor = sub->sub_destructor; /* auto_all is not copied! */ @@ -473,7 +490,7 @@ void *sub_alloc(su_home_t *home, if (!preload) sub->sub_auto_all = 0; - if (zero == do_clone) { + if (zero >= do_clone) { /* Prepare cloned home */ su_home_t *subhome = data; @@ -485,13 +502,13 @@ void *sub_alloc(su_home_t *home, subhome->suh_size = (unsigned)size; subhome->suh_blocks->sub_parent = home; - subhome->suh_blocks->sub_ref = 1; + subhome->suh_blocks->sub_hauto = 0; } /* OK, add the block to the hash table. */ sua = su_block_add(sub, data); assert(sua); - sua->sua_size = size; + sua->sua_size = (unsigned)size; sua->sua_home = zero > 1; if (sub->sub_stats) @@ -525,16 +542,16 @@ void *su_home_new(isize_t size) assert(size >= sizeof (*home)); if (size < sizeof (*home)) - return (errno = EINVAL), NULL; + return (void)(errno = EINVAL), NULL; else if (size > INT_MAX) - return (errno = ENOMEM), NULL; + return (void)(errno = ENOMEM), NULL; home = calloc(1, size); if (home) { home->suh_size = (int)size; home->suh_blocks = su_hash_alloc(SUB_N); if (home->suh_blocks) - home->suh_blocks->sub_ref = 1; + home->suh_blocks->sub_hauto = 0; else free(home), home = NULL; } @@ -612,12 +629,10 @@ int su_home_desctructor(su_home_t *home, void (*destructor)(void *)) /**Unreference a su_home_t object. * - * The function su_home_unref() decrements the reference count on a home - * object and destroys and frees it and the memory allocations using it. + * Decrements the reference count on home object and destroys and frees it + * and the memory allocations using it if the reference count reaches 0. * - * @param home memory pool object to be unreferences - * - * The function return values is + * @param home memory pool object to be unreferenced * * @retval 1 if object was freed * @retval 0 if object is still alive @@ -650,8 +665,10 @@ int su_home_unref(su_home_t *home) return 1; } else { + int hauto = sub->sub_hauto; _su_home_deinit(home); - free(home); + if (!hauto) + free(home); /* UNLOCK(home); */ return 1; } @@ -725,7 +742,7 @@ int su_home_has_parent(su_home_t const *home) /** Allocate a memory block. * - * The function su_alloc() allocates a memory block of a given @a size. + * Allocates a memory block of a given @a size. * * If @a home is NULL, this function behaves exactly like malloc(). * @@ -752,9 +769,9 @@ void *su_alloc(su_home_t *home, isize_t size) /**Free a memory block. * - * The function su_free() frees a single memory block. The @a home must be - * the owner of the memory block (usually the memory home used to allocate - * the memory block, or NULL if no home was used). + * Frees a single memory block. The @a home must be the owner of the memory + * block (usually the memory home used to allocate the memory block, or NULL + * if no home was used). * * @param home pointer to home object * @param data pointer to the memory block to be freed @@ -792,7 +809,7 @@ void su_free(su_home_t *home, void *data) } #if MEMCHECK != 0 - memset(data, 0xaa, allocation->sua_size); + memset(data, 0xaa, (size_t)allocation->sua_size); #endif memset(allocation, 0, sizeof (*allocation)); @@ -810,9 +827,9 @@ void su_free(su_home_t *home, void *data) /** Check home consistency. * - * The function su_home_check() ensures that the home structure and all - * memory blocks allocated through it are consistent. It can be used to - * catch memory allocation and usage errors. + * Ensures that the home structure and all memory blocks allocated through + * it are consistent. It can be used to catch memory allocation and usage + * errors. * * @param home Pointer to a memory home. */ @@ -851,11 +868,10 @@ void su_home_check_blocks(su_block_t const *b) /** * Create an su_home_t object. * - * The function su_home_create() creates a home object. A home object is - * used to collect multiple memory allocations, so that they all can be - * freed by calling su_home_unref(). + * Creates a home object. A home object is used to collect multiple memory + * allocations, so that they all can be freed by calling su_home_unref(). * - * @return This function returns a pointer to an @c su_home_t object, or @c + * @return This function returns a pointer to an #su_home_t object, or * NULL upon an error. */ su_home_t *su_home_create(void) @@ -863,10 +879,10 @@ su_home_t *su_home_create(void) return su_home_new(sizeof(su_home_t)); } -/** Deinitialize a home object +/** Destroy a home object * - * The function su_home_destroy() frees all memory blocks associated with a - * home object. Note that the home object is not freed. + * Frees all memory blocks associated with a home object. Note that the home + * object structure is not freed. * * @param home pointer to a home object * @@ -876,14 +892,22 @@ su_home_t *su_home_create(void) */ void su_home_destroy(su_home_t *home) { - su_home_deinit(home); - /* XXX - home itself is not destroyed */ + if (MEMLOCK(home)) { + assert(home->suh_blocks); + assert(home->suh_blocks->sub_ref == 1); + if (!home->suh_blocks->sub_hauto) + /* should warn user */; + home->suh_blocks->sub_hauto = 1; + _su_home_deinit(home); + /* UNLOCK(home); */ + } } /** Initialize an su_home_t struct. * - * The function su_home_init() initializes an su_home_t structure. It can be - * used when the home structure is allocated from stack. + * Initializes an su_home_t structure. It can be used when the home + * structure is allocated from stack or when the home structure is part of + * an another object. * * @param home pointer to home object * @@ -894,10 +918,14 @@ void su_home_destroy(su_home_t *home) */ int su_home_init(su_home_t *home) { + su_block_t *sub; + if (home == NULL) return -1; - home->suh_blocks = su_hash_alloc(SUB_N); + home->suh_blocks = sub = su_hash_alloc(SUB_N); + if (!sub) + return -1; return 0; } @@ -949,6 +977,9 @@ void _su_home_deinit(su_home_t *home) free(b); home->suh_blocks = NULL; + + if (home->suh_lock) + su_home_destroy_mutexes(home->suh_lock); } home->suh_lock = NULL; @@ -956,9 +987,9 @@ void _su_home_deinit(su_home_t *home) /** Free memory blocks allocated through home. * - * The function @c su_home_deinit() frees the memory blocks associated with - * the home object allocated otherwise. It does not free the home object - * itself. Use su_home_unref() to free the home object. + * Frees the memory blocks associated with the home object allocated. It + * does not free the home object itself. Use su_home_unref() to free the + * home object. * * @param home pointer to home object * @@ -967,7 +998,9 @@ void _su_home_deinit(su_home_t *home) void su_home_deinit(su_home_t *home) { if (MEMLOCK(home)) { - assert(home->suh_blocks && home->suh_blocks->sub_ref == 0); + assert(home->suh_blocks); + assert(home->suh_blocks->sub_ref == 1); + assert(home->suh_blocks->sub_hauto); _su_home_deinit(home); /* UNLOCK(home); */ } @@ -975,11 +1008,11 @@ void su_home_deinit(su_home_t *home) /**Move allocations from a su_home_t object to another. * - * The function su_home_move() moves allocations made through the @a src - * home object under the @a dst home object. It is handy, for example, if an - * operation allocates some number of blocks that should be freed upon an - * error. It uses a temporary home and moves the blocks from temporary to a - * proper home when successful, but frees the temporary home upon an error. + * Moves allocations made through the @a src home object under the @a dst + * home object. It is handy, for example, if an operation allocates some + * number of blocks that should be freed upon an error. It uses a temporary + * home and moves the blocks from temporary to a proper home when + * successful, but frees the temporary home upon an error. * * If @a src has destructor, it is called before starting to move. * @@ -1111,8 +1144,8 @@ void su_home_preload(su_home_t *home, isize_t n, isize_t isize) /** Preload a memory home from stack. * - * The function su_home_auto() initalizes a memory home using an area - * allocated from stack. Poor mans alloca(). + * Initializes a memory home using an area allocated from stack. Poor man's + * alloca(). */ su_home_t *su_home_auto(void *area, isize_t size) { @@ -1142,10 +1175,12 @@ su_home_t *su_home_auto(void *area, isize_t size) size = prepsize + 65535; sub->sub_n = SUB_N_AUTO; + sub->sub_ref = 1; sub->sub_preload = p + prepsize; sub->sub_prsize = (unsigned)(size - prepsize); - sub->sub_preauto = 1; + sub->sub_hauto = 1; sub->sub_auto = 1; + sub->sub_preauto = 1; sub->sub_auto_all = 1; return home; @@ -1154,7 +1189,7 @@ su_home_t *su_home_auto(void *area, isize_t size) /** Reallocate a memory block. * - * The function su_realloc() allocates a memory block of @a size bytes. + * Allocates a memory block of @a size bytes. * It copies the old block contents to the new block and frees the old * block. * @@ -1165,7 +1200,7 @@ su_home_t *su_home_auto(void *area, isize_t size) * @param size size of the memory block to be allocated * * @return - * This function returns a pointer to the allocated memory block or + * A pointer to the allocated memory block or * NULL if an error occurred. */ void *su_realloc(su_home_t *home, void *data, isize_t size) @@ -1216,7 +1251,7 @@ void *su_realloc(su_home_t *home, void *data, isize_t size) #endif memset(sua, 0, sizeof *sua); sub->sub_used--; - su_block_add(sub, ndata)->sua_size = size; + su_block_add(sub, ndata)->sua_size = (unsigned)size; } UNLOCK(home); @@ -1247,7 +1282,7 @@ void *su_realloc(su_home_t *home, void *data, isize_t size) return data; } } - else if (size < sua->sua_size) { + else if (size < (size_t)sua->sua_size) { /* Reduce existing preload */ if (sub->sub_stats) { su_home_stats_free(sub, data, data, sua->sua_size); @@ -1256,7 +1291,7 @@ void *su_realloc(su_home_t *home, void *data, isize_t size) #if MEMCHECK_EXTRA memcpy((char *)data + size, &term, sizeof (term)); #endif - sua->sua_size = size; + sua->sua_size = (unsigned)size; UNLOCK(home); return data; } @@ -1271,7 +1306,10 @@ void *su_realloc(su_home_t *home, void *data, isize_t size) su_home_stats_free(sub, data, data, sua->sua_size); } - memcpy(ndata, data, sua->sua_size < size ? sua->sua_size : size); + memcpy(ndata, data, + (size_t)sua->sua_size < size + ? (size_t)sua->sua_size + : size); #if MEMCHECK_EXTRA memcpy((char *)ndata + size, &term, sizeof (term)); #endif @@ -1281,7 +1319,7 @@ void *su_realloc(su_home_t *home, void *data, isize_t size) memset(sua, 0, sizeof *sua); sub->sub_used--; - su_block_add(sub, ndata)->sua_size = size; + su_block_add(sub, ndata)->sua_size = (unsigned)size; } UNLOCK(home); @@ -1327,7 +1365,7 @@ int su_in_home(su_home_t *home, void const *memory) /**Allocate and zero a memory block. * - * The function su_zalloc() allocates a memory block with a given size from + * Allocates a memory block with a given size from * given memory home @a home and zeroes the allocated block. * * @param home pointer to memory pool object @@ -1359,9 +1397,9 @@ void *su_zalloc(su_home_t *home, isize_t size) /** Allocate a structure * - * The function su_salloc() allocates a structure with a given size, zeros + * Allocates a structure with a given size, zeros * it, and initializes the size field to the given size. The size field - * is the first in the structure. It has type of int. + * is an int at the beginning of the structure. Note that it has type of int. * * @param home pointer to memory pool object * @param size size of the structure @@ -1540,7 +1578,8 @@ void su_home_stats_alloc(su_block_t *sub, void *p, void *preload, } static -void su_home_stats_free(su_block_t *sub, void *p, void *preload, size_t size) +void su_home_stats_free(su_block_t *sub, void *p, void *preload, + unsigned size) { su_home_stat_t *hs = sub->sub_stats; diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc_lock.c b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc_lock.c index f9fb0ab5f6..d9f4a94724 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_alloc_lock.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_alloc_lock.c @@ -39,6 +39,7 @@ #if SU_HAVE_PTHREADS #include #include +#include extern void (*su_home_locker)(void *mutex); extern void (*su_home_unlocker)(void *mutex); @@ -46,6 +47,8 @@ extern void (*su_home_unlocker)(void *mutex); extern void (*su_home_mutex_locker)(void *mutex); extern void (*su_home_mutex_unlocker)(void *mutex); +extern void (*su_home_destroy_mutexes)(void *mutex); + /** Mutex */ static void mutex_locker(void *_mutex) { @@ -58,6 +61,15 @@ static void mutex_unlocker(void *_mutex) pthread_mutex_t *mutex = _mutex; pthread_mutex_unlock(mutex + 1); } + +static void mutex_destroy(void *_mutex) +{ + pthread_mutex_t *mutex = _mutex; + pthread_mutex_destroy(mutex + 0); + pthread_mutex_destroy(mutex + 1); + free(_mutex); +} + #endif @@ -65,7 +77,7 @@ static void mutex_unlocker(void *_mutex) * * Convert a memory home object as thread-safe by allocating mutexes and * modifying function pointers in su_alloc.c module. - + * * @param home memory home object to be converted thread-safe. * * @retval 0 when successful, @@ -94,9 +106,10 @@ int su_home_threadsafe(su_home_t *home) su_home_mutex_unlocker = mutex_unlocker; su_home_locker = (void (*)(void *))pthread_mutex_lock; su_home_unlocker = (void (*)(void *))pthread_mutex_unlock; + su_home_destroy_mutexes = mutex_destroy; } - mutex = su_alloc(home, 2 * sizeof (pthread_mutex_t)); + mutex = calloc(1, 2 * (sizeof *mutex)); assert(mutex); if (mutex) { /* Mutex for memory operations */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c new file mode 100644 index 0000000000..e37761922e --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c @@ -0,0 +1,577 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_port.c + * + * OS-Independent Socket Syncronization Interface. + * + * This looks like nth reincarnation of "reactor". It implements the + * poll/select/WaitForMultipleObjects and message passing functionality. + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#define su_base_port_s su_port_s +#define SU_CLONE_T su_msg_t + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +#include +#include +#include +#include +#include +#include +#include + +#if 1 +#define PORT_REFCOUNT_DEBUG(x) ((void)0) +#else +#define PORT_REFCOUNT_DEBUG(x) printf x +#endif + +static int su_base_port_execute_msgs(su_msg_t *queue); + +/**@internal + * + * Initialize a message port. + * + * @retval 0 when successful + * @retval -1 upon an error + */ +int su_base_port_init(su_port_t *self, su_port_vtable_t const *vtable) +{ + if (self) { + self->sup_vtable = vtable; + self->sup_tail = &self->sup_head; + + return 0; + } + + return -1; +} + +/** @internal Deinit a base implementation of port. */ +void su_base_port_deinit(su_port_t *self) +{ +} + +void su_base_port_lock(su_port_t *self, char const *who) +{ +} + +void su_base_port_unlock(su_port_t *self, char const *who) +{ +} + +int su_base_port_own_thread(su_port_t const *self) +{ + return 1; +} + +void su_base_port_incref(su_port_t *self, char const *who) +{ + su_home_ref(self->sup_home); + PORT_REFCOUNT_DEBUG(("incref(%p) to %u by %s\n", self, + su_home_refcount(self->sup_home), who)); +} + +int su_base_port_decref(su_port_t *self, int blocking, char const *who) +{ + int zapped = su_home_unref(self->sup_home); + + PORT_REFCOUNT_DEBUG(("%s(%p) to %u%s by %s\n", + blocking ? "zapref" : "decref", + self, zapped ? 0 : su_home_refcount(self->sup_home), + blocking && !zapped ? " FAILED" :"", + who)); + + /* We should block until all references are destroyed */ + if (blocking) + /* ...but we just abort() */ + assert(zapped); + + return zapped; +} + +struct _GSource *su_base_port_gsource(su_port_t *self) +{ + return NULL; +} + +/** @internal Send a message to the port. + * + * @retval 1 if port thread needs to be woken + * @retval 0 if there are other messages in queue, too + * @retval -1 upon an error + */ +int su_base_port_send(su_port_t *self, su_msg_r rmsg) +{ + if (self) { + int wakeup; + + su_port_lock(self, "su_port_send"); + + wakeup = self->sup_head == NULL; + + *self->sup_tail = rmsg[0]; rmsg[0] = NULL; + self->sup_tail = &(*self->sup_tail)->sum_next; + + su_port_unlock(self, "su_port_send"); + + return wakeup; + } + else { + su_msg_destroy(rmsg); + return -1; + } +} + +/** @internal + * Execute the messages in the incoming queue. + * + * @param self - pointer to a port object + * + * @retval Number of messages executed + */ +int su_base_port_getmsgs(su_port_t *self) +{ + if (self->sup_head) { + su_msg_t *queue; + + su_port_lock(self, "su_base_port_getmsgs"); + + queue = self->sup_head; + self->sup_tail = &self->sup_head; + self->sup_head = NULL; + + su_port_unlock(self, "su_base_port_getmsgs"); + + return su_base_port_execute_msgs(queue); + } + + return 0; +} + + +int su_base_port_getmsgs_from(su_port_t *self, su_port_t *from) +{ + su_msg_t *msg, *selected; + su_msg_t **next = &self->sup_head, **tail= &selected; + + if (!*next) + return 0; + + su_port_lock(self, "su_base_port_getmsgs_from_port"); + + while (*next) { + msg = *next; + + if (msg->sum_from->sut_port == from) { + *tail = msg, *next = msg->sum_next, tail = &msg->sum_next; + } + else + next = &msg->sum_next; + } + + *tail = NULL, self->sup_tail = next; + + su_port_unlock(self, "su_base_port_getmsgs_from_port"); + + return su_base_port_execute_msgs(selected); +} + +static +int su_base_port_getmsgs_of_root(su_port_t *self, su_root_t *root) +{ + su_msg_t *msg, *selected; + su_msg_t **next = &self->sup_head, **tail= &selected; + + if (!*next) + return 0; + + su_port_lock(self, "su_base_port_getmsgs_of_root"); + + while (*next) { + msg = *next; + + if (msg->sum_from->sut_root == root || + msg->sum_to->sut_root == root) { + *tail = msg, *next = msg->sum_next, tail = &msg->sum_next; + } + else + next = &msg->sum_next; + } + + *tail = NULL, self->sup_tail = next; + + su_port_unlock(self, "su_base_port_getmsgs_of_root"); + + return su_base_port_execute_msgs(selected); +} + +static int su_base_port_execute_msgs(su_msg_t *queue) +{ + su_msg_t *msg; + int n = 0; + + for (msg = queue; msg; msg = queue) { + su_msg_f f = msg->sum_func; + + queue = msg->sum_next, msg->sum_next = NULL; + + if (f) + f(SU_ROOT_MAGIC(msg->sum_to->sut_root), &msg, msg->sum_data); + su_msg_delivery_report(&msg); + n++; + } + + return n; +} + +/** @internal Enable multishot mode. + * + * The function su_port_multishot() enables, disables or queries the + * multishot mode for the port. The multishot mode determines how the events + * are scheduled by port. If multishot mode is enabled, port serves all the + * sockets that have received network events. If it is disabled, the + * socket events are server one at a time. + * + * @param self pointer to port object + * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) + * + * @retval 0 multishot mode is disabled + * @retval 1 multishot mode is enabled + * @retval -1 an error occurred + */ +int su_base_port_multishot(su_port_t *self, int multishot) +{ + return 0; +} + +/** @internal Enable threadsafe operation. */ +int su_base_port_threadsafe(su_port_t *self) +{ + return su_home_threadsafe(self->sup_home); +} + +/** @internal Main loop. + * + * The function @c su_port_run() waits for wait objects and the timers + * associated with the port object. When any wait object is signaled or + * timer is expired, it invokes the callbacks, and returns waiting. + * + * The function @c su_port_run() runs until @c su_port_break() is called + * from a callback. + * + * @param self pointer to port object + * + */ +void su_base_port_run(su_port_t *self) +{ + su_duration_t tout = 0; + + assert(su_port_own_thread(self)); + + for (self->sup_running = 1; self->sup_running;) { + tout = 2000; + + if (self->sup_prepoll) + self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); + + if (self->sup_head) + self->sup_vtable->su_port_getmsgs(self); + + if (self->sup_timers) + su_timer_expire(&self->sup_timers, &tout, su_now()); + + if (!self->sup_running) + break; + + if (self->sup_head) /* if there are messages do a quick wait */ + tout = 0; + + self->sup_vtable->su_port_wait_events(self, tout); + } +} + +#if tuning +/* This version can help tuning... */ +void su_base_port_run_tune(su_port_t *self) +{ + int i; + int timers = 0, messages = 0, events = 0; + su_duration_t tout = 0, tout0; + su_time_t started = su_now(), woken = started, bedtime = woken; + + assert(su_port_own_thread(self)); + + for (self->sup_running = 1; self->sup_running;) { + tout = 2000; + + timers = 0, messages = 0; + + if (self->sup_prepoll) + self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); + + if (self->sup_head) + messages = self->sup_vtable->su_port_getmsgs(self); + + if (self->sup_timers) + timers = su_timer_expire(&self->sup_timers, &tout, su_now()); + + if (!self->sup_running) + break; + + if (self->sup_head) /* if there are messages do a quick wait */ + tout = 0; + + bedtime = su_now(); + + events = self->sup_vtable->su_port_wait_events(self, tout); + + woken = su_now(); + + if (messages || timers || events) + SU_DEBUG_1(("su_port_run(%p): %.6f: %u messages %u timers %u " + "events slept %.6f/%.3f\n", + self, su_time_diff(woken, started), messages, timers, events, + su_time_diff(woken, bedtime), tout * 1e-3)); + + if (!self->sup_running) + break; + } +} +#endif + +/** @internal + * The function @c su_port_break() is used to terminate execution of @c + * su_port_run(). It can be called from a callback function. + * + * @param self pointer to port + * + */ +void su_base_port_break(su_port_t *self) +{ + self->sup_running = 0; +} + +/** @internal Block until wait object is signaled or timeout. + * + * This function waits for wait objects and the timers associated with + * the root object. When any wait object is signaled or timer is + * expired, it invokes the callbacks. + * + * This function returns when a callback has been invoked or @c tout + * milliseconds is elapsed. + * + * @param self pointer to port + * @param tout timeout in milliseconds + * + * @return + * Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if + * there are no active timers. + */ +su_duration_t su_base_port_step(su_port_t *self, su_duration_t tout) +{ + su_time_t now = su_now(); + + assert(su_port_own_thread(self)); + + if (self->sup_prepoll) + self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); + + if (self->sup_head) + self->sup_vtable->su_port_getmsgs(self); + + if (self->sup_timers) + su_timer_expire(&self->sup_timers, &tout, now); + + /* if there are messages do a quick wait */ + if (self->sup_head) + tout = 0; + + if (self->sup_vtable->su_port_wait_events(self, tout)) + tout = 0; + else + tout = SU_WAIT_FOREVER; + + if (self->sup_head) + if (self->sup_vtable->su_port_getmsgs(self)) { + /* Check for wait events that may have been generated by messages */ + if (self->sup_vtable->su_port_wait_events(self, 0)) + tout = 0; + } + + if (self->sup_timers) + su_timer_expire(&self->sup_timers, &tout, su_now()); + + if (self->sup_head) + tout = 0; + + return tout; +} + +/* ========================================================================= + * Pre-poll() callback + */ + +int su_base_port_add_prepoll(su_port_t *self, + su_root_t *root, + su_prepoll_f *callback, + su_prepoll_magic_t *magic) +{ + if (self->sup_prepoll) + return -1; + + self->sup_prepoll = callback; + self->sup_pp_magic = magic; + self->sup_pp_root = root; + + return 0; +} + +int su_base_port_remove_prepoll(su_port_t *self, + su_root_t *root) +{ + if (self->sup_pp_root != root) + return -1; + + self->sup_prepoll = NULL; + self->sup_pp_magic = NULL; + self->sup_pp_root = NULL; + + return 0; +} + +/* ========================================================================= + * Timers + */ + +su_timer_t **su_base_port_timers(su_port_t *self) +{ + return &self->sup_timers; +} + +/* ====================================================================== */ + +/** @internal + * Used to check wait events in callbacks that take lots of time + * + * This function does a timeout 0 poll() and runs wait objects. + * + * @param port pointer to port + * + * @return number of events handled + */ +int su_base_port_yield(su_port_t *self) +{ + return self->sup_vtable->su_port_wait_events(self, 0); +} + +/* ====================================================================== + * Clones + */ + +#define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \ + (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0) + +static void su_base_port_clone_break(su_root_magic_t *m, + su_msg_r msg, + su_msg_arg_t *arg); + +int su_base_port_start_shared(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + su_port_t *self = parent->sur_task->sut_port; + su_root_t *child; + + child = su_salloc(su_port_home(self), sizeof *child); + if (!child) + return -1; + + child->sur_magic = magic; + child->sur_deinit = deinit; + child->sur_threading = parent->sur_threading; + + SU_TASK_COPY(child->sur_parent, su_root_task(parent), + su_base_port_clone_start); + SU_TASK_COPY(child->sur_task, child->sur_parent, + su_base_port_clone_start); + + child->sur_task->sut_root = child; + + if (su_msg_create(return_clone, + child->sur_task, su_root_task(parent), + su_base_port_clone_break, + 0) == 0 && + init(child, magic) == 0) + return 0; + + deinit(child, magic); + su_msg_destroy(return_clone); + su_root_destroy(child); + return -1; +} + +static void su_base_port_clone_break(su_root_magic_t *m, + su_msg_r msg, + su_msg_arg_t *arg) +{ + _su_task_t const *task = su_msg_to(msg); + + while (su_base_port_getmsgs_of_root(task->sut_port, task->sut_root)) + ; + + su_root_destroy(task->sut_root); +} + +void su_base_port_wait(su_clone_r rclone) +{ + su_port_t *self; + su_root_t *root_to_wait; + + self = su_msg_from(rclone)->sut_port; + assert(self == su_msg_to(rclone)->sut_port); + root_to_wait = su_msg_to(rclone)->sut_root; + + assert(rclone[0]->sum_func == su_base_port_clone_break); + + while (su_base_port_getmsgs_of_root(self, root_to_wait)) + ; + su_root_destroy(root_to_wait); + su_msg_destroy(rclone); +} + diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_bm.c b/libs/sofia-sip/libsofia-sip-ua/su/su_bm.c index 5be78a7199..77dd61f906 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_bm.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_bm.c @@ -108,7 +108,7 @@ bm_memmem_study(char const *needle, size_t nlen) /** Search for a substring using Boyer-Moore algorithm. * @ingroup su_bm */ -char const* +char * bm_memmem(char const *haystack, size_t hlen, char const *needle, size_t nlen, bm_fwd_table_t *fwd) @@ -117,14 +117,14 @@ bm_memmem(char const *haystack, size_t hlen, bm_fwd_table_t fwd0[1]; if (nlen == 0) - return haystack; + return (char *)haystack; if (needle == NULL || haystack == NULL || nlen > hlen) return NULL; if (nlen == 1) { for (i = 0; i < hlen; i++) if (haystack[i] == needle[0]) - return haystack + i; + return (char *)haystack + i; return NULL; } @@ -139,7 +139,7 @@ bm_memmem(char const *haystack, size_t hlen, (int)(i - j), "", (int)j, needle, needle + j + 1, j == 0 ? "match!" : "back by 1")); if (j == 0) - return haystack + i; + return (char *)haystack + i; i--, j--; } else { @@ -207,7 +207,7 @@ bm_memcasemem_study(char const *needle, size_t nlen) /** Search for substring using Boyer-Moore algorithm. * @ingroup su_bm */ -char const* +char * bm_memcasemem(char const *haystack, size_t hlen, char const *needle, size_t nlen, bm_fwd_table_t *fwd) @@ -216,14 +216,14 @@ bm_memcasemem(char const *haystack, size_t hlen, bm_fwd_table_t fwd0[1]; if (nlen == 0) - return haystack; + return (char *)haystack; if (needle == 0 || haystack == 0 || nlen > hlen) return NULL; if (nlen == 1) { for (i = 0; i < hlen; i++) if (haystack[i] == needle[0]) - return haystack + i; + return (char *)haystack + i; return NULL; } @@ -245,7 +245,7 @@ bm_memcasemem(char const *haystack, size_t hlen, (int)(i - j), "", (int)j, needle, needle + j + 1, j == 0 ? "match!" : "back by 1")); if (j == 0) - return haystack + i; + return (char *)haystack + i; i--, j--; } else { diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c new file mode 100644 index 0000000000..a3a128b4e1 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c @@ -0,0 +1,583 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_poll_port.c + * + * Port implementation using poll() + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#define su_port_s su_poll_port_s + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +#if HAVE_EPOLL + +#include + +#define POLL2EPOLL_NEEDED \ + (POLLIN != EPOLLIN || POLLOUT != EPOLLOUT || POLLPRI != EPOLLPRI || \ + POLLERR != EPOLLERR || POLLHUP != EPOLLHUP) + +#define POLL2EPOLL(e) (e & (POLLIN|POLLOUT|POLLPRI|POLLERR|POLLHUP)) +#define EPOLL2POLL(e) (e & (POLLIN|POLLOUT|POLLPRI|POLLERR|POLLHUP)) + +/** Port based on epoll(). */ + +struct su_poll_port_s { + su_pthread_port_t sup_base[1]; + + /** epoll fd */ + int sup_epoll; + unsigned sup_multishot; /**< Multishot operation? */ + + unsigned sup_registers; /** Counter incremented by + su_port_register() or + su_port_unregister() + */ + int sup_n_registrations; + int sup_max_index; /**< Indexes are equal or smaller than this */ + int sup_size_indices; /**< Size of allocated index table */ + + /** Structure containing registration data */ + struct su_epoll_register { + struct su_epoll_register *ser_next; /* Next in free list */ + su_wakeup_f ser_cb; + su_wakeup_arg_t*ser_arg; + su_root_t *ser_root; + int ser_id; /** registration identifier */ + su_wait_t ser_wait[1]; + } **sup_indices; +}; + +static void su_epoll_port_decref(su_port_t *self, int blocking, char const *who); +static int su_epoll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority); +static int su_epoll_port_unregister(su_port_t *port, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg); +static int su_epoll_port_deregister(su_port_t *self, int i); +static int su_epoll_port_unregister_all(su_port_t *self, su_root_t *root); +static int su_epoll_port_eventmask(su_port_t *self, + int index, + int socket, + int events); +static int su_epoll_port_multishot(su_port_t *self, int multishot); +static int su_epoll_port_wait_events(su_port_t *self, su_duration_t tout); +static char const *su_epoll_port_name(su_port_t const *self); + +su_port_vtable_t const su_epoll_port_vtable[1] = + {{ + /* su_vtable_size: */ sizeof su_epoll_port_vtable, + su_pthread_port_lock, + su_pthread_port_unlock, + su_base_port_incref, + su_epoll_port_decref, + su_base_port_gsource, + su_pthread_port_send, + su_epoll_port_register, + su_epoll_port_unregister, + su_epoll_port_deregister, + su_epoll_port_unregister_all, + su_epoll_port_eventmask, + su_base_port_run, + su_base_port_break, + su_base_port_step, + su_pthread_port_own_thread, + su_base_port_add_prepoll, + su_base_port_remove_prepoll, + su_base_port_timers, + su_epoll_port_multishot, + su_base_port_threadsafe, + su_base_port_yield, + su_epoll_port_wait_events, + su_base_port_getmsgs, + su_base_port_getmsgs_from, + su_epoll_port_name, + su_base_port_start_shared, + su_pthread_port_wait, + su_pthread_port_execute, + }}; + +static char const *su_epoll_port_name(su_port_t const *self) +{ + return "epoll"; +} + +static void su_epoll_port_decref(su_port_t *self, int blocking, char const *who) +{ + (void)su_base_port_decref(self, blocking, who); +} + +static void su_epoll_port_deinit(void *arg) +{ + su_port_t *self = arg; + + SU_DEBUG_9(("%s(%p) called\n", "su_epoll_port_deinit", (void* )self)); + + su_pthread_port_deinit(self); + + close(self->sup_epoll), self->sup_epoll = -1; +} + +/** @internal + * + * Register a #su_wait_t object. The wait object, a callback function and + * an argument pointer is stored in the port object. The callback function + * will be called when the wait object is signaled. + * + * Please note if identical wait objects are inserted, only first one is + * ever signalled. + * + * @param self pointer to port + * @param root pointer to root object + * @param waits pointer to wait object + * @param callback callback function pointer + * @param arg argument given to callback function when it is invoked + * @param priority relative priority of the wait object + * (0 is normal, 1 important, 2 realtime) + * + * @return + * Positive index of the wait object, + * or -1 upon an error. + */ +int su_epoll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority) +{ + int i, j, n; + struct epoll_event ev; + struct su_epoll_register *ser; + struct su_epoll_register **indices = self->sup_indices; + + assert(su_port_own_thread(self)); + + n = self->sup_size_indices; + + if (n >= SU_WAIT_MAX) + return su_seterrno(ENOMEM); + + ser = indices[0]; + + if (!ser) { + su_home_t *h = su_port_home(self); + + i = self->sup_max_index, j = i == 0 ? 15 : i + 16; + + if (j >= self->sup_size_indices) { + /* Reallocate index table */ + n = n < 1024 ? 2 * n : n + 1024; + indices = su_realloc(h, indices, n * sizeof(indices[0])); + if (!indices) + return -1; + self->sup_indices = indices; + self->sup_size_indices = n; + } + + /* Allocate registrations */ + ser = su_zalloc(h, (j - i) * (sizeof *ser)); + if (!ser) + return -1; + + indices[0] = ser; + + for (i++; i <= j; i++) { + ser->ser_id = i; + ser->ser_next = i < j ? ser + 1 : NULL; + indices[i] = ser++; + } + + self->sup_max_index = j; + + ser = indices[0]; + } + + i = ser->ser_id; + + ev.events = POLL2EPOLL(wait->events); + ev.data.u64 = 0; + ev.data.u32 = (uint32_t)i; + + if (epoll_ctl(self->sup_epoll, EPOLL_CTL_ADD, wait->fd, &ev) == -1) { + SU_DEBUG_0(("EPOLL_CTL_ADD(%u, %u) failed: %s\n", + wait->fd, ev.events, strerror(errno))); + return -1; + } + + indices[0] = ser->ser_next; + + ser->ser_next = NULL; + *ser->ser_wait = *wait; + ser->ser_cb = callback; + ser->ser_arg = arg; + ser->ser_root = root; + + self->sup_registers++; + self->sup_n_registrations++; + + return i; /* return index */ +} + +/** Deregister a su_wait_t object. */ +static int su_epoll_port_deregister0(su_port_t *self, int i, int destroy_wait) +{ + struct su_epoll_register **indices = self->sup_indices; + struct su_epoll_register *ser; + + ser = self->sup_indices[i]; + if (ser == NULL || ser->ser_cb == NULL) { + su_seterrno(ENOENT); + return -1; + } + + assert(ser->ser_id == i); + + if (epoll_ctl(self->sup_epoll, EPOLL_CTL_DEL, ser->ser_wait->fd, NULL) == -1) { + SU_DEBUG_1(("su_port(%p): EPOLL_CTL_DEL(%u): %s\n", (void *)self, + ser->ser_wait->fd, su_strerror(su_errno()))); + } + + if (destroy_wait) + su_wait_destroy(ser->ser_wait); + + memset(ser, 0, sizeof *ser); + ser->ser_id = i; + ser->ser_next = indices[0], indices[0] = ser; + + self->sup_n_registrations--; + self->sup_registers++; + + return i; +} + + +/** Unregister a su_wait_t object. + * + * The function su_epoll_port_unregister() unregisters a su_wait_t object. The + * wait object, a callback function and a argument are removed from the + * port object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * @param wait - pointer to wait object + * @param callback - callback function pointer (may be NULL) + * @param arg - argument given to callback function when it is invoked + * (may be NULL) + * + * @deprecated Use su_epoll_port_deregister() instead. + * + * @return Nonzero index of the wait object, or -1 upon an error. + */ +int su_epoll_port_unregister(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, /* XXX - ignored */ + su_wakeup_arg_t *arg) +{ + int i, I; + + struct su_epoll_register *ser; + + assert(self); + assert(su_port_own_thread(self)); + + I = self->sup_max_index; + + for (i = 1; i <= I; i++) { + ser = self->sup_indices[i]; + + if (ser->ser_cb && + arg == ser->ser_arg && + SU_WAIT_CMP(wait[0], ser->ser_wait[0]) == 0) + return su_epoll_port_deregister0(self, ser->ser_id, 0); + } + + su_seterrno(ENOENT); + + return -1; +} + +/** Deregister a su_wait_t object. + * + * Deregisters a registration by index. The wait object, a callback + * function and a argument are removed from the port object. The wait + * object is destroyed. + * + * @param self - pointer to port object + * @param i - registration index + * + * @return Index of the wait object, or -1 upon an error. + */ +int su_epoll_port_deregister(su_port_t *self, int i) +{ + struct su_epoll_register *ser; + + if (i <= 0 || i > self->sup_max_index) + return su_seterrno(EBADF); + + ser = self->sup_indices[i]; + if (!ser->ser_cb) + return su_seterrno(EBADF); + + return su_epoll_port_deregister0(self, i, 1); +} + + +/** @internal + * Unregister all su_wait_t objects of given su_root_t instance. + * + * The function su_epoll_port_unregister_all() unregisters all su_wait_t + * objects associated with given root object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * + * @return Number of wait objects removed. + */ +int su_epoll_port_unregister_all(su_port_t *self, su_root_t *root) +{ + int i, I, n; + + struct su_epoll_register *ser; + + assert(self); assert(root); + assert(su_port_own_thread(self)); + + I = self->sup_max_index; + + for (i = 1, n = 0; i <= I; i++) { + ser = self->sup_indices[i]; + if (ser->ser_root != root) + continue; + su_epoll_port_deregister0(self, ser->ser_id, 0); + n++; + } + + return n; +} + +/**Set mask for a registered event. @internal + * + * The function su_epoll_port_eventmask() sets the mask describing events that can + * signal the registered callback. + * + * @param port pointer to port object + * @param index registration index + * @param socket socket + * @param events new event mask + * + * @retval 0 when successful, + * @retval -1 upon an error. + */ +int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events) +{ + struct su_epoll_register *ser; + struct epoll_event ev; + + if (index <= 0 || index > self->sup_max_index) + return su_seterrno(EBADF); + + ser = self->sup_indices[index]; + if (!ser->ser_cb) + return su_seterrno(EBADF); + + ser->ser_wait->events = events; + + ev.events = POLL2EPOLL(events); + ev.data.u64 = (uint64_t)0; + ev.data.u32 = (uint32_t)index; + + if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, ser->ser_wait->fd, &ev) == -1) { + SU_DEBUG_1(("su_port(%p): EPOLL_CTL_MOD(%u): %s\n", (void *)self, + ser->ser_wait->fd, su_strerror(su_errno()))); + return -1; + } + + return 0; +} + +/** @internal Enable multishot mode. + * + * Enables, disables or queries the multishot mode for the port. The + * multishot mode determines how the events are scheduled by port. If + * multishot mode is enabled, port serves all the sockets that have received + * network events. If it is disabled, only first socket event is served. +p * + * @param self pointer to port object + * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) + * + * @retval 0 multishot mode is disabled + * @retval 1 multishot mode is enabled + * @retval -1 an error occurred + */ +static +int su_epoll_port_multishot(su_port_t *self, int multishot) +{ + if (multishot < 0) + return self->sup_multishot; + else if (multishot == 0 || multishot == 1) + return self->sup_multishot = multishot; + else + return (errno = EINVAL), -1; +} + + +/** @internal + * Wait (poll()) for wait objects in port. + * + * @param self pointer to port + * @param tout timeout in milliseconds + * + * @return number of events handled + */ +static +int su_epoll_port_wait_events(su_port_t *self, su_duration_t tout) +{ + int j, n, events = 0, index; + unsigned version = self->sup_registers; + + int const M = 4; + struct epoll_event ev[M]; + + n = epoll_wait(self->sup_epoll, ev, self->sup_multishot ? M : 1, tout); + + assert(n <= M); + + for (j = 0; j < n; j++) { + struct su_epoll_register *ser; + su_root_magic_t *magic; + + index = (int)ev[j].data.u32; + if (!ev[j].events || index <= 0 || self->sup_max_index < index) + continue; + ser = self->sup_indices[index]; + + magic = ser->ser_root ? su_root_magic(ser->ser_root) : NULL; + ser->ser_wait->revents = ev[j].events; + ser->ser_cb(magic, ser->ser_wait, ser->ser_arg); + events++; + if (version != self->sup_registers) + /* Callback function used su_register()/su_deregister() */ + return events; + } + + return n; +} + +/** Create a port using epoll() or poll(). + */ +su_port_t *su_epoll_port_create(void) +{ + su_port_t *self; + int epoll = epoll_create(su_root_size_hint); + + if (epoll == -1) { + /* Fallback to poll() */ + SU_DEBUG_3(("%s(): epoll_create() => %u: %s\n", + "su_port_create", epoll, strerror(errno))); + return su_poll_port_create(); + } + + self = su_home_new(sizeof *self); + if (!self) { + close(epoll); + return self; + } + + SU_DEBUG_9(("%s(%p): epoll_create() => %u: %s\n", + "su_port_create", (void *)self, self->sup_epoll, "OK")); + + if (su_home_destructor(su_port_home(self), su_epoll_port_deinit) < 0 || + !(self->sup_indices = + su_zalloc(su_port_home(self), + (sizeof self->sup_indices[0]) * + (self->sup_size_indices = 64)))) { + su_home_unref(su_port_home(self)); + close(epoll); + return NULL; + } + + self->sup_epoll = epoll; + self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; + + if (su_pthread_port_init(self, su_epoll_port_vtable) < 0) + return su_home_unref(su_port_home(self)), NULL; + + return self; +} + +int su_epoll_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + return su_pthreaded_port_start(su_epoll_port_create, + parent, return_clone, magic, init, deinit); +} +#else + +su_port_t *su_epoll_port_create(void) +{ + return su_poll_port_create(); +} + +int su_epoll_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + return su_pthreaded_port_start(su_poll_port_create, + parent, return_clone, magic, init, deinit); +} + +#endif /* HAVE_EPOLL */ + diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c b/libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c index 7434598db4..19bdfc2eb3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c @@ -1045,7 +1045,9 @@ int bsd_localinfo(su_localinfo_t const hints[1], { struct ifaddrs *ifa, *results; int error = 0; +#if SU_HAVE_IN6 int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0; +#endif char *canonname = NULL; if (getifaddrs(&results) < 0) { @@ -1057,7 +1059,10 @@ int bsd_localinfo(su_localinfo_t const hints[1], for (ifa = results; ifa; ifa = ifa->ifa_next) { su_localinfo_t *li; - su_sockaddr_t *su, su2[1]; + su_sockaddr_t *su; +#if SU_HAVE_IN6 + su_sockaddr_t su2[1]; +#endif socklen_t sulen; int scope, flags = 0, gni_flags = 0, if_index = 0; char const *ifname = 0; @@ -1075,15 +1080,19 @@ int bsd_localinfo(su_localinfo_t const hints[1], if (su->su_family == AF_INET) { sulen = sizeof(su->su_sin); scope = li_scope4(su->su_sin.sin_addr.s_addr); +#if SU_HAVE_IN6 if (v4_mapped) sulen = sizeof(su->su_sin6); +#endif } +#if SU_HAVE_IN6 else if (su->su_family == AF_INET6) { if (IN6_IS_ADDR_MULTICAST(&su->su_sin6.sin6_addr)) continue; sulen = sizeof(su->su_sin6); scope = li_scope6(&su->su_sin6.sin6_addr); } +#endif else continue; @@ -1102,6 +1111,7 @@ int bsd_localinfo(su_localinfo_t const hints[1], if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK) gni_flags = NI_NUMERICHOST; +#if SU_HAVE_IN6 if (v4_mapped && su->su_family == AF_INET) { /* Map IPv4 address to IPv6 address */ memset(su2, 0, sizeof(*su2)); @@ -1110,6 +1120,7 @@ int bsd_localinfo(su_localinfo_t const hints[1], ((int32_t*)&su2->su_sin6.sin6_addr)[3] = su->su_sin.sin_addr.s_addr; su = su2; } +#endif if ((error = li_name(hints, gni_flags, su, &canonname)) < 0) break; diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_os_nw.c b/libs/sofia-sip/libsofia-sip-ua/su/su_os_nw.c index e48b7c5c8e..8bb973f799 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_os_nw.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_os_nw.c @@ -46,10 +46,14 @@ #include "sofia-sip/su_os_nw.h" #include "sofia-sip/su_debug.h" -/* Works only with pthreads */ -#if SU_HAVE_PTHREADS +#if defined(__APPLE_CC__) +# define SU_NW_CHANGE_PTHREAD 1 +#endif -#include +#if defined (SU_NW_CHANGE_PTHREAD) +# define SU_HAVE_NW_CHANGE 1 +# include +#endif #if defined(__APPLE_CC__) #include @@ -68,8 +72,9 @@ struct su_network_changed_s { SCDynamicStoreRef su_storeRef[1]; CFRunLoopSourceRef su_sourceRef[1]; #endif - +#if defined (SU_NW_CHANGE_PTHREAD) pthread_t su_os_thread; +#endif su_network_changed_f *su_network_changed_cb; su_network_changed_magic_t *su_network_changed_magic; @@ -109,7 +114,7 @@ void nw_changed_cb(SCDynamicStoreRef store, sizeof *snc) == SU_FAILURE) { return; - } + } snc2 = su_msg_data(rmsg); assert(snc2); snc2->su_root = snc->su_root; @@ -119,7 +124,7 @@ void nw_changed_cb(SCDynamicStoreRef store, snc2->su_os_thread = snc->su_os_thread; snc2->su_network_changed_cb = snc->su_network_changed_cb; snc2->su_network_changed_magic = snc->su_network_changed_magic; - + if (su_msg_send(rmsg) == SU_FAILURE) { su_msg_destroy(rmsg); return; @@ -219,10 +224,7 @@ CreateIPAddressListChangeCallbackSCF(SCDynamicStoreCallBack callback, return err; } -#endif /* __APPLE_CC__ */ - -#if defined(__APPLE_CC__) static void *su_start_nw_os_thread(void *ptr) { su_network_changed_t *snc = (su_network_changed_t *) ptr; @@ -249,19 +251,13 @@ su_network_changed_t su_network_changed_f *network_changed_cb, su_network_changed_magic_t *magic) { -#if defined (__APPLE_CC__) su_network_changed_t *snc = NULL; -#endif assert(home && root && network_changed_cb && magic); - /* Not implemented for others than OSX */ -#if !defined (__APPLE_CC__) - return NULL; -#else - +#if defined (SU_HAVE_NW_CHANGE) snc = su_zalloc(home, sizeof *snc); - + if (!snc) return NULL; @@ -269,15 +265,16 @@ su_network_changed_t snc->su_root = root; snc->su_network_changed_cb = network_changed_cb; snc->su_network_changed_magic = magic; - + +# if defined (SU_NW_CHANGE_PTHREAD) if ((pthread_create(&(snc->su_os_thread), NULL, su_start_nw_os_thread, (void *) snc)) != 0) { return NULL; } - - return snc; +# endif #endif + return snc; } /** Remove a callback registered for the network change event. @@ -288,20 +285,3 @@ int su_root_remove_network_changed(su_network_changed_t *snc) { return -1; } - -#else - -su_network_changed_t -*su_root_add_network_changed(su_home_t *home, su_root_t *root, - su_network_changed_f *network_changed_cb, - su_network_changed_magic_t *magic) -{ - return NULL; -} - -int su_root_remove_network_changed(su_network_changed_t *snc) -{ - return -1; -} - -#endif /* SU_HAVE_PTHREADS */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c b/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c index 9735c67b71..20e578527d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c @@ -38,15 +38,6 @@ #include "config.h" -/* React to multiple events per one poll() to make sure - * that high-priority events can never completely mask other events. - * Enabled by default on all platforms except WIN32 */ -#ifndef WIN32 -#define SU_ENABLE_MULTISHOT_POLL 1 -#else -#define SU_ENABLE_MULTISHOT_POLL 0 -#endif - #include #include #include diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c new file mode 100644 index 0000000000..cc873f28d6 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c @@ -0,0 +1,682 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_poll_port.c + * + * Port implementation using poll() + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#if HAVE_POLL || HAVE_SELECT + +#include +#include +#include +#include +#include +#include +#include + +#define su_port_s su_poll_port_s + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +/** Port based on poll(). */ + +struct su_poll_port_s { + su_pthread_port_t sup_base[1]; + +#define sup_home sup_base->sup_base->sup_home + + unsigned sup_multishot; /**< Multishot operation? */ + + unsigned sup_registers; /** Counter incremented by + su_port_register() or + su_port_unregister() + */ + + int sup_n_waits; /**< Active su_wait_t in su_waits */ + int sup_size_waits; /**< Size of allocated su_waits */ + int sup_pri_offset; /**< Offset to prioritized waits */ + +#if !SU_HAVE_WINSOCK +#define INDEX_MAX (0x7fffffff) +#else + /* We use WSAWaitForMultipleEvents() */ +#define INDEX_MAX (64) +#endif + + /** Indices from index returned by su_root_register() to tables below. + * + * Free elements are negative. Free elements form a list, value of free + * element is (0 - index of next free element). + * + * First element sup_indices[0] points to first free element. + */ + int *sup_indices; + + int *sup_reverses; /** Reverse index */ + su_wakeup_f *sup_wait_cbs; + su_wakeup_arg_t**sup_wait_args; + su_root_t **sup_wait_roots; + su_wait_t *sup_waits; + +}; + +static void su_poll_port_decref(su_port_t *, int blocking, char const *who); + +static int su_poll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority); +static int su_poll_port_unregister(su_port_t *port, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg); +static int su_poll_port_deregister(su_port_t *self, int i); +static int su_poll_port_unregister_all(su_port_t *self, su_root_t *root); +static int su_poll_port_eventmask(su_port_t *self, + int index, + int socket, + int events); +static int su_poll_port_multishot(su_port_t *self, int multishot); +static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout); +static char const *su_poll_port_name(su_port_t const *self); + +su_port_vtable_t const su_poll_port_vtable[1] = + {{ + /* su_vtable_size: */ sizeof su_poll_port_vtable, + su_pthread_port_lock, + su_pthread_port_unlock, + su_base_port_incref, + su_poll_port_decref, + su_base_port_gsource, + su_pthread_port_send, + su_poll_port_register, + su_poll_port_unregister, + su_poll_port_deregister, + su_poll_port_unregister_all, + su_poll_port_eventmask, + su_base_port_run, + su_base_port_break, + su_base_port_step, + su_pthread_port_own_thread, + su_base_port_add_prepoll, + su_base_port_remove_prepoll, + su_base_port_timers, + su_poll_port_multishot, + su_base_port_threadsafe, + su_base_port_yield, + su_poll_port_wait_events, + su_base_port_getmsgs, + su_base_port_getmsgs_from, + su_poll_port_name, + su_base_port_start_shared, + su_pthread_port_wait, + su_pthread_port_execute, + }}; + +static char const *su_poll_port_name(su_port_t const *self) +{ + return "poll"; +} + +static void su_poll_port_deinit(void *arg) +{ + su_port_t *self = arg; + + SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", (void *)self)); + + su_pthread_port_deinit(self); +} + +static void su_poll_port_decref(su_port_t *self, int blocking, char const *who) +{ + su_base_port_decref(self, blocking, who); +} + +/** @internal + * + * Register a @c su_wait_t object. The wait object, a callback function and + * an argument pointer is stored in the port object. The callback function + * will be called when the wait object is signaled. + * + * Please note if identical wait objects are inserted, only first one is + * ever signalled. + * + * @param self pointer to port + * @param root pointer to root object + * @param waits pointer to wait object + * @param callback callback function pointer + * @param arg argument given to callback function when it is invoked + * @param priority relative priority of the wait object + * (0 is normal, 1 important, 2 realtime) + * + * @return + * Positive index of the wait object, + * or -1 upon an error. + */ +int su_poll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority) +{ + int i, j, n; + + assert(su_port_own_thread(self)); + + n = self->sup_n_waits; + + if (n >= SU_WAIT_MAX) + return su_seterrno(ENOMEM); + + if (n >= self->sup_size_waits) { + su_home_t *h = self->sup_home; + /* Reallocate size arrays */ + int size; + int *indices; + int *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t **wait_args; + su_root_t **wait_tasks; + + if (self->sup_size_waits == 0) + size = su_root_size_hint; + else + size = 2 * self->sup_size_waits; + + if (size < SU_WAIT_MIN) + size = SU_WAIT_MIN; + + /* Too large */ + if (-3 - size > 0) + return (errno = ENOMEM), -1; + + indices = su_realloc(h, self->sup_indices, (size + 1) * sizeof(*indices)); + if (indices) { + self->sup_indices = indices; + + if (self->sup_size_waits == 0) + indices[0] = -1; + + for (i = self->sup_size_waits + 1; i <= size; i++) + indices[i] = -1 - i; + } + + reverses = su_realloc(h, self->sup_reverses, size * sizeof(*waits)); + if (reverses) { + for (i = self->sup_size_waits; i < size; i++) + reverses[i] = -1; + self->sup_reverses = reverses; + } + + waits = su_realloc(h, self->sup_waits, size * sizeof(*waits)); + if (waits) + self->sup_waits = waits; + + wait_cbs = su_realloc(h, self->sup_wait_cbs, size * sizeof(*wait_cbs)); + if (wait_cbs) + self->sup_wait_cbs = wait_cbs; + + wait_args = su_realloc(h, self->sup_wait_args, size * sizeof(*wait_args)); + if (wait_args) + self->sup_wait_args = wait_args; + + /* Add sup_wait_roots array, if needed */ + wait_tasks = su_realloc(h, self->sup_wait_roots, size * sizeof(*wait_tasks)); + if (wait_tasks) + self->sup_wait_roots = wait_tasks; + + if (!(indices && + reverses && waits && wait_cbs && wait_args && wait_tasks)) { + return -1; + } + + self->sup_size_waits = size; + } + + i = -self->sup_indices[0]; assert(i <= self->sup_size_waits); + + if (priority > 0) { + /* Insert */ + for (n = self->sup_n_waits; n > 0; n--) { + j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1); + self->sup_indices[j] = n; + self->sup_reverses[n] = j; + self->sup_waits[n] = self->sup_waits[n-1]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; + self->sup_wait_args[n] = self->sup_wait_args[n-1]; + self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; + } + + self->sup_pri_offset++; + } + else { + /* Append - no need to move anything */ + n = self->sup_n_waits; + } + + self->sup_n_waits++; + + self->sup_indices[0] = self->sup_indices[i]; /* Free index */ + self->sup_indices[i] = n; + + self->sup_reverses[n] = i; + self->sup_waits[n] = *wait; + self->sup_wait_cbs[n] = callback; + self->sup_wait_args[n] = arg; + self->sup_wait_roots[n] = root; + + self->sup_registers++; + + /* Just like epoll, we return -1 or positive integer */ + + return i; +} + +/** Deregister a su_wait_t object. */ +static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait) +{ + int n, N, *indices, *reverses; + + indices = self->sup_indices; + reverses = self->sup_reverses; + + n = indices[i]; assert(n >= 0); + + if (destroy_wait) + su_wait_destroy(&self->sup_waits[n]); + + N = --self->sup_n_waits; + + if (n < self->sup_pri_offset) { + int j = --self->sup_pri_offset; + if (n != j) { + assert(reverses[j] > 0); + assert(indices[reverses[j]] == j); + indices[reverses[j]] = n; + reverses[n] = reverses[j]; + + self->sup_waits[n] = self->sup_waits[j]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[j]; + self->sup_wait_args[n] = self->sup_wait_args[j]; + self->sup_wait_roots[n] = self->sup_wait_roots[j]; + n = j; + } + } + + if (n < N) { + assert(reverses[N] > 0); + assert(indices[reverses[N]] == N); + + indices[reverses[N]] = n; + reverses[n] = reverses[N]; + + self->sup_waits[n] = self->sup_waits[N]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[N]; + self->sup_wait_args[n] = self->sup_wait_args[N]; + self->sup_wait_roots[n] = self->sup_wait_roots[N]; + n = N; + } + + reverses[n] = -1; + memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]); + self->sup_wait_cbs[n] = NULL; + self->sup_wait_args[n] = NULL; + self->sup_wait_roots[n] = NULL; + + indices[i] = indices[0]; + indices[0] = -i; + + self->sup_registers++; + + return i; +} + + +/** Unregister a su_wait_t object. + * + * The function su_poll_port_unregister() unregisters a su_wait_t object. The + * wait object, a callback function and a argument are removed from the + * port object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * @param wait - pointer to wait object + * @param callback - callback function pointer (may be NULL) + * @param arg - argument given to callback function when it is invoked + * (may be NULL) + * + * @deprecated Use su_poll_port_deregister() instead. + * + * @return Nonzero index of the wait object, or -1 upon an error. + */ +int su_poll_port_unregister(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, /* XXX - ignored */ + su_wakeup_arg_t *arg) +{ + int n, N; + + assert(self); + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + + for (n = 0; n < N; n++) { + if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { + return su_poll_port_deregister0(self, self->sup_reverses[n], 0); + } + } + + su_seterrno(ENOENT); + + return -1; +} + +/** Deregister a su_wait_t object. + * + * Deregisters a registration by index. The wait object, a callback + * function and a argument are removed from the port object. The wait + * object is destroyed. + * + * @param self - pointer to port object + * @param i - registration index + * + * @return Index of the wait object, or -1 upon an error. + */ +int su_poll_port_deregister(su_port_t *self, int i) +{ + su_wait_t wait[1] = { SU_WAIT_INIT }; + int retval; + + assert(self); + assert(su_port_own_thread(self)); + + if (i <= 0 || i > self->sup_size_waits) + return su_seterrno(EBADF); + + if (self->sup_indices[i] < 0) + return su_seterrno(EBADF); + + retval = su_poll_port_deregister0(self, i, 1); + + su_wait_destroy(wait); + + return retval; +} + + +/** @internal + * Unregister all su_wait_t objects. + * + * The function su_poll_port_unregister_all() unregisters all su_wait_t objects + * and destroys all queued timers associated with given root object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * + * @return Number of wait objects removed. + */ +int su_poll_port_unregister_all(su_port_t *self, + su_root_t *root) +{ + int i, j, index, N; + int *indices, *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t**wait_args; + su_root_t **wait_roots; + + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + indices = self->sup_indices; + reverses = self->sup_reverses; + waits = self->sup_waits; + wait_cbs = self->sup_wait_cbs; + wait_args = self->sup_wait_args; + wait_roots = self->sup_wait_roots; + + for (i = j = 0; i < N; i++) { + index = reverses[i]; assert(index > 0 && indices[index] == i); + + if (wait_roots[i] == root) { + /* XXX - we should free all resources associated with this, too */ + if (i < self->sup_pri_offset) + self->sup_pri_offset--; + + indices[index] = indices[0]; + indices[0] = -index; + continue; + } + + if (i != j) { + indices[index] = j; + reverses[j] = reverses[i]; + waits[j] = waits[i]; + wait_cbs[j] = wait_cbs[i]; + wait_args[j] = wait_args[i]; + wait_roots[j] = wait_roots[i]; + } + + j++; + } + + for (i = j; i < N; i++) { + reverses[i] = -1; + wait_cbs[i] = NULL; + wait_args[i] = NULL; + wait_roots[i] = NULL; + } + memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]); + + self->sup_n_waits = j; + self->sup_registers++; + + return N - j; +} + +/**Set mask for a registered event. @internal + * + * The function su_poll_port_eventmask() sets the mask describing events that can + * signal the registered callback. + * + * @param port pointer to port object + * @param index registration index + * @param socket socket + * @param events new event mask + * + * @retval 0 when successful, + * @retval -1 upon an error. + */ +int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events) +{ + int n; + assert(self); + assert(su_port_own_thread(self)); + + if (index <= 0 || index > self->sup_size_waits) + return su_seterrno(EBADF); + n = self->sup_indices[index]; + if (n < 0) + return su_seterrno(EBADF); + + return su_wait_mask(&self->sup_waits[n], socket, events); +} + +/** @internal Enable multishot mode. + * + * Enables, disables or queries the multishot mode for the port. The + * multishot mode determines how the events are scheduled by port. If + * multishot mode is enabled, port serves all the sockets that have received + * network events. If it is disabled, only first socket event is served. + * + * @param self pointer to port object + * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) + * + * @retval 0 multishot mode is disabled + * @retval 1 multishot mode is enabled + * @retval -1 an error occurred + */ +static +int su_poll_port_multishot(su_port_t *self, int multishot) +{ + if (multishot < 0) + return self->sup_multishot; + else if (multishot == 0 || multishot == 1) + return self->sup_multishot = multishot; + else + return (errno = EINVAL), -1; +} + + +/** @internal + * Wait (poll()) for wait objects in port. + * + * @param self pointer to port + * @param tout timeout in milliseconds + * + * @return number of events handled + */ +static +int su_poll_port_wait_events(su_port_t *self, su_duration_t tout) +{ + int i, events = 0; + su_wait_t *waits = self->sup_waits; + int n = self->sup_n_waits; + su_root_t *root; + unsigned version = self->sup_registers; + + i = su_wait(waits, (unsigned)n, tout); + + if (i >= 0 && i < n) { + /* poll() can return events for multiple wait objects */ + if (self->sup_multishot) { + for (; i < n; i++) { + if (waits[i].revents) { + root = self->sup_wait_roots[i]; + self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, + &waits[i], + self->sup_wait_args[i]); + events++; + /* Callback function used su_register()/su_deregister() */ + if (version != self->sup_registers) + break; + } + } + } + else { + root = self->sup_wait_roots[i]; + self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, + &self->sup_waits[i], + self->sup_wait_args[i]); + events++; + } + } + + return events; +} + +#if 0 +/** @internal + * Prints out the contents of the port. + * + * @param self pointer to a port + * @param f pointer to a file (if @c NULL, uses @c stdout). + */ +void su_port_dump(su_port_t const *self, FILE *f) +{ + int i; +#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "") +#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "") +#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "") + + if (f == NULL) + f = stdout; + + fprintf(f, "su_port_t at %p:\n", self); + fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); +#if SU_HAVE_PTHREADS + fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); + fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0], + IS_WAIT_IN(&self->sup_mbox_wait), + IS_WAIT_OUT(&self->sup_mbox_wait), + IS_WAIT_ACCEPT(&self->sup_mbox_wait)); +#endif + fprintf(f, "\t%d wait objects\n", self->sup_n_waits); + for (i = 0; i < self->sup_n_waits; i++) { + + } +} + +#endif + +/** Create a port using epoll() or poll(). + */ +su_port_t *su_poll_port_create(void) +{ + su_port_t *self = su_home_new(sizeof *self); + + if (!self) + return self; + + if (su_home_destructor(su_port_home(self), su_poll_port_deinit) < 0) + return su_home_unref(su_port_home(self)), NULL; + + self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; + + if (su_pthread_port_init(self, su_poll_port_vtable) < 0) + return su_home_unref(su_port_home(self)), NULL; + + return self; +} + +int su_poll_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + return su_pthreaded_port_start(su_poll_port_create, + parent, return_clone, magic, init, deinit); +} + +#endif /* HAVE_POLL || HAVE_SELECT */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_port.c index bc0a8e31f6..a20891f1b7 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_port.c @@ -27,8 +27,9 @@ * * OS-Independent Socket Syncronization Interface. * - * This looks like nth reincarnation of "reactor". It implements the - * poll/select/WaitForMultipleObjects and message passing functionality. + * This looks like nth reincarnation of "reactor". It implements the + * poll/select/WaitForMultipleObjects and message passing functionality. + * This is virtual implementation: * * @author Pekka Pessi * @author Kai Vehmanen @@ -38,1443 +39,368 @@ #include "config.h" -/* React to multiple events per one poll() to make sure - * that high-priority events can never completely mask other events. - * Enabled by default on all platforms except WIN32 */ -#ifndef WIN32 -#define SU_ENABLE_MULTISHOT_POLL 1 -#else -#define SU_ENABLE_MULTISHOT_POLL 0 -#endif +#define SU_CLONE_T su_msg_t -#include -#include -#include -#include -#include -#include -#include +#define su_port_s su_virtual_port_s -#define SU_PORT_IMPLEMENTATION 1 - -#include "sofia-sip/su.h" #include "su_port.h" -#include "sofia-sip/su_alloc.h" -#if SU_HAVE_PTHREADS -/* Pthread implementation */ -#include -#define SU_HAVE_MBOX 1 -#else -#define SU_HAVE_MBOX 0 -#endif +#include +#include -#if HAVE_SOCKETPAIR -#define MBOX_SEND 1 -#else -#define MBOX_SEND 0 -#endif +static su_port_create_f *preferred_su_port_create; +static su_clone_start_f *preferred_su_clone_start; -#if HAVE_EPOLL -#include - -#define POLL2EPOLL_NEEDED \ - (POLLIN != EPOLLIN || POLLOUT != EPOLLOUT || POLLPRI != EPOLLPRI || \ - POLLERR != EPOLLERR || POLLHUP != EPOLLHUP) - -#define POLL2EPOLL(e) (e & (POLLIN|POLLOUT|POLLPRI|POLLERR|POLLHUP)) -#define EPOLL2POLL(e) (e & (POLLIN|POLLOUT|POLLPRI|POLLERR|POLLHUP)) - -#endif - -static void su_port_lock(su_port_t *self, char const *who); -static void su_port_unlock(su_port_t *self, char const *who); -static void su_port_incref(su_port_t *self, char const *who); -static void su_port_decref(su_port_t *self, int blocking, char const *who); - -static struct _GSource *su_port_gsource(su_port_t *port); - -static int su_port_send(su_port_t *self, su_msg_r rmsg); - -static int su_port_register(su_port_t *self, - su_root_t *root, - su_wait_t *wait, - su_wakeup_f callback, - su_wakeup_arg_t *arg, - int priority); -static int su_port_unregister(su_port_t *port, - su_root_t *root, - su_wait_t *wait, - su_wakeup_f callback, - su_wakeup_arg_t *arg); - -static int su_port_deregister(su_port_t *self, int i); - -static int su_port_unregister_all(su_port_t *self, - su_root_t *root); -static -int su_port_eventmask(su_port_t *self, int index, int socket, int events); -static -void su_port_run(su_port_t *self); -static -void su_port_break(su_port_t *self); -static -su_duration_t su_port_step(su_port_t *self, su_duration_t tout); - -static -int su_port_own_thread(su_port_t const *port); - -static -int su_port_add_prepoll(su_port_t *port, - su_root_t *root, - su_prepoll_f *, - su_prepoll_magic_t *); - -static -int su_port_remove_prepoll(su_port_t *port, - su_root_t *root); - -static -su_timer_t **su_port_timers(su_port_t *port); - -static -int su_port_multishot(su_port_t *port, int multishot); - -static -int su_port_threadsafe(su_port_t *port); - -static -int su_port_yield(su_port_t *port); - -su_port_vtable_t const su_port_vtable[1] = - {{ - /* su_vtable_size: */ sizeof su_port_vtable, - su_port_lock, - su_port_unlock, - su_port_incref, - su_port_decref, - su_port_gsource, - su_port_send, - su_port_register, - su_port_unregister, - su_port_deregister, - su_port_unregister_all, - su_port_eventmask, - su_port_run, - su_port_break, - su_port_step, - su_port_own_thread, - su_port_add_prepoll, - su_port_remove_prepoll, - su_port_timers, - su_port_multishot, - su_port_threadsafe, - su_port_yield - }}; - -static int su_port_wait_events(su_port_t *self, su_duration_t tout); - - -/** - * Port is a per-thread reactor. +/** Explicitly set the preferred su_port_t implementation. * - * Multiple root objects executed by single thread share a su_port_t object. + * @sa su_epoll_port_create(), su_poll_port_create(), su_select_port_create() */ -struct su_port_s { - su_home_t sup_home[1]; +void su_port_prefer(su_port_create_f *create, + su_clone_start_f *start) +{ + if (create) preferred_su_port_create = create; + if (start) preferred_su_clone_start = start; +} - su_port_vtable_t const *sup_vtable; - - unsigned sup_running; - -#if SU_HAVE_PTHREADS - pthread_t sup_tid; - pthread_mutex_t sup_mutex[1]; -#if __CYGWIN__ - pthread_mutex_t sup_reflock[1]; - int sup_ref; -#else - pthread_rwlock_t sup_ref[1]; -#endif -#else - int sup_ref; -#endif - -#if SU_HAVE_MBOX - su_socket_t sup_mbox[MBOX_SEND + 1]; - su_wait_t sup_mbox_wait; -#endif +void su_port_set_system_preferences(char const *name) +{ + su_port_create_f *create = preferred_su_port_create; + su_clone_start_f *start = preferred_su_clone_start; + if (name == NULL) + ; +#if HAVE_POLL_PORT #if HAVE_EPOLL - /** epoll() fd */ - int sup_epoll; + else if (strcmp(name, "epoll") == 0) { + create = su_epoll_port_create; + start = su_epoll_clone_start; + } #endif - - unsigned sup_multishot; /**< Multishot operation? */ - - unsigned sup_registers; /** Counter incremented by - su_port_register() or - su_port_unregister() - */ - int sup_n_waits; /**< Active su_wait_t in su_waits */ - int sup_size_waits; /**< Size of allocate su_waits */ - - int sup_pri_offset; /**< Offset to prioritized waits */ - -#if !SU_HAVE_WINSOCK -#define INDEX_MAX (0x7fffffff) -#else - /* We use WSAWaitForMultipleEvents() */ -#define INDEX_MAX (64) -#endif - - /** Indices from index returned by su_root_register() to tables below. - * - * Free elements are negative. Free elements form a list, value of free - * element is (0 - index of next free element). - * - * First element sup_indices[0] points to first free element. - */ - int *sup_indices; - - int *sup_reverses; /** Reverse index */ - su_wakeup_f *sup_wait_cbs; - su_wakeup_arg_t**sup_wait_args; - su_root_t **sup_wait_roots; - - su_wait_t *sup_waits; - - /* Pre-poll callback */ - su_prepoll_f *sup_prepoll; - su_prepoll_magic_t *sup_pp_magic; - su_root_t *sup_pp_root; - - /* Timer list */ - su_timer_t *sup_timers; - - /* Message list - this is protected by lock */ - su_msg_t *sup_head; - su_msg_t **sup_tail; -}; - -#if SU_HAVE_PTHREADS -#define SU_PORT_OWN_THREAD(p) (pthread_equal((p)->sup_tid, pthread_self())) - -#if __CYGWIN__ - -/* Debugging versions */ -#define SU_PORT_INITREF(p) (pthread_mutex_init((p)->sup_reflock, NULL), printf("initref(%p)\n", (p))) -#define SU_PORT_INCREF(p, f) (pthread_mutex_lock(p->sup_reflock), p->sup_ref++, pthread_mutex_unlock(p->sup_reflock), printf("incref(%p) by %s\n", (p), f)) -#define SU_PORT_DECREF(p, f) do { \ - pthread_mutex_lock(p->sup_reflock); p->sup_ref--; pthread_mutex_unlock(p->sup_reflock); \ - if ((p->sup_ref) == 0) { \ - printf("decref(%p) to 0 by %s\n", (p), f); su_port_destroy(p); } \ - else { printf("decref(%p) to %u by %s\n", (p), p->sup_ref, f); } } while(0) - -#define SU_PORT_ZAPREF(p, f) do { printf("zapref(%p) by %s\n", (p), f), \ - pthread_mutex_lock(p->sup_reflock); p->sup_ref--; pthread_mutex_unlock(p->sup_reflock); \ - if ((p->sup_ref) != 0) { \ - assert(!"SU_PORT_ZAPREF"); } \ - su_port_destroy(p); } while(0) - -#define SU_PORT_INITLOCK(p) \ - (pthread_mutex_init((p)->sup_mutex, NULL), printf("init_lock(%p)\n", p)) - -#define SU_PORT_LOCK(p, f) \ - (printf("%ld at %s locking(%p)...", pthread_self(), f, p), pthread_mutex_lock((p)->sup_mutex), printf(" ...%ld at %s locked(%p)...", pthread_self(), f, p)) - -#define SU_PORT_UNLOCK(p, f) \ - (pthread_mutex_unlock((p)->sup_mutex), printf(" ...%ld at %s unlocked(%p)\n", pthread_self(), f, p)) - -#elif 1 -#define SU_PORT_INITREF(p) (pthread_rwlock_init(p->sup_ref, NULL)) -#define SU_PORT_INCREF(p, f) (pthread_rwlock_rdlock(p->sup_ref)) -#define SU_PORT_DECREF(p, f) do { pthread_rwlock_unlock(p->sup_ref); \ - if (pthread_rwlock_trywrlock(p->sup_ref) == 0) su_port_destroy(p); } while(0) - -#define SU_PORT_ZAPREF(p, f) do { pthread_rwlock_unlock(p->sup_ref); \ - if (pthread_rwlock_trywrlock(p->sup_ref) != 0) { \ - assert(!"SU_PORT_ZAPREF"); pthread_rwlock_wrlock(p->sup_ref); } \ - su_port_destroy(p); } while(0) - -#define SU_PORT_INITLOCK(p) (pthread_mutex_init((p)->sup_mutex, NULL)) -#define SU_PORT_LOCK(p, f) (pthread_mutex_lock((p)->sup_mutex)) -#define SU_PORT_UNLOCK(p, f) (pthread_mutex_unlock((p)->sup_mutex)) - + else if (strcmp(name, "poll") == 0) { + create = su_poll_port_create; + start = su_poll_clone_start; + } #else - -/* Debugging versions */ -#define SU_PORT_INITREF(p) (pthread_rwlock_init((p)->sup_ref, NULL), printf("initref(%p)\n", (p))) -#define SU_PORT_INCREF(p, f) (pthread_rwlock_rdlock(p->sup_ref), printf("incref(%p) by %s\n", (p), f)) -#define SU_PORT_DECREF(p, f) do { \ - pthread_rwlock_unlock(p->sup_ref); \ - if (pthread_rwlock_trywrlock(p->sup_ref) == 0) { \ - printf("decref(%p) to 0 by %s\n", (p), f); su_port_destroy(p); } \ - else { printf("decref(%p) by %s\n", (p), f); } } while(0) - -#define SU_PORT_ZAPREF(p, f) do { printf("zapref(%p) by %s\n", (p), f), \ - pthread_rwlock_unlock(p->sup_ref); \ - if (pthread_rwlock_trywrlock(p->sup_ref) != 0) { \ - assert(!"SU_PORT_ZAPREF"); pthread_rwlock_wrlock(p->sup_ref); } \ - su_port_destroy(p); } while(0) - -#define SU_PORT_INITLOCK(p) \ - (pthread_mutex_init((p)->sup_mutex, NULL), printf("init_lock(%p)\n", p)) - -#define SU_PORT_LOCK(p, f) \ - (printf("%ld at %s locking(%p)...", pthread_self(), f, p), pthread_mutex_lock((p)->sup_mutex), printf(" ...%ld at %s locked(%p)...", pthread_self(), f, p)) - -#define SU_PORT_UNLOCK(p, f) \ - (pthread_mutex_unlock((p)->sup_mutex), printf(" ...%ld at %s unlocked(%p)\n", pthread_self(), f, p)) - + /* select port does not work yet */ +#error no poll! +#endif +#if HAVE_SELECT + else if (strcmp(name, "select") == 0) { + create = su_select_port_create; + start = su_select_clone_start; + } #endif -#else /* !SU_HAVE_PTHREADS */ - -#define SU_PORT_OWN_THREAD(p) 1 -#define SU_PORT_INITLOCK(p) (void)(p) -#define SU_PORT_LOCK(p, f) (void)(p) -#define SU_PORT_UNLOCK(p, f) (void)(p) -#define SU_PORT_ZAPREF(p, f) ((p)->sup_ref--) - -#define SU_PORT_INITREF(p) ((p)->sup_ref = 1) -#define SU_PORT_INCREF(p, f) ((p)->sup_ref++) -#define SU_PORT_DECREF(p, f) \ -do { if (--((p)->sup_ref) == 0) su_port_destroy(p); } while (0); - +#if HAVE_POLL_PORT +#if HAVE_EPOLL + if (create == NULL) create = su_epoll_port_create; + if (start == NULL) start = su_epoll_clone_start; +#else + if (create == NULL) create = su_poll_port_create; + if (start == NULL) start = su_poll_clone_start; +#endif +#else +#if HAVE_SELECT + if (create == NULL) create = su_select_port_create; + if (start == NULL) start = su_select_clone_start; +#endif #endif -#if SU_HAVE_MBOX -static int su_port_wakeup(su_root_magic_t *magic, - su_wait_t *w, - su_wakeup_arg_t *arg); -#endif + if (preferred_su_port_create == NULL) preferred_su_port_create = create; + if (preferred_su_clone_start == NULL) preferred_su_clone_start = start; +} -static void su_port_destroy(su_port_t *self); - -/**@internal - * - * Allocates and initializes a message port. It creates a mailbox used to. - * wake up the tasks waiting on the port if needed. Currently, the - * mailbox is simply an UDP socket connected to itself. - * - * @return - * If successful a pointer to the new message port is returned, otherwise - * NULL is returned. - */ +/** Create the preferred su_port_t implementation. */ su_port_t *su_port_create(void) { - su_port_t *self; + if (preferred_su_port_create == NULL) + su_port_set_system_preferences(getenv("SU_PORT")); - SU_DEBUG_9(("su_port_create() called\n")); + if (preferred_su_port_create) + return preferred_su_port_create(); - self = su_home_clone(NULL, sizeof(*self)); - - if (self) { -#if SU_HAVE_MBOX - int af; - su_socket_t mb = INVALID_SOCKET; - char const *why; -#endif - - self->sup_vtable = su_port_vtable; - - SU_PORT_INITREF(self); - SU_PORT_INITLOCK(self); - self->sup_tail = &self->sup_head; - - self->sup_multishot = (SU_ENABLE_MULTISHOT_POLL) != 0; - -#if SU_HAVE_PTHREADS - self->sup_tid = pthread_self(); -#endif - -#if HAVE_EPOLL - self->sup_epoll = epoll_create(su_root_size_hint); - if (self->sup_epoll == -1) - SU_DEBUG_3(("su_port(%p): epoll_create(): %s\n", self, strerror(errno))); - else - SU_DEBUG_9(("su_port(%p): epoll_create() => %u: OK\n", - self, self->sup_epoll)); -#endif - -#if SU_HAVE_MBOX -#if HAVE_SOCKETPAIR -#if defined(AF_LOCAL) - af = AF_LOCAL; -#else - af = AF_UNIX; -#endif - if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) { - why = "su_port_init: socketpair"; goto error; - } - - mb = self->sup_mbox[0]; - su_setblocking(self->sup_mbox[0], 0); - su_setblocking(self->sup_mbox[1], 0); -#else - { - struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 }; - socklen_t sinsize = sizeof sin; - struct sockaddr *sa = (struct sockaddr *)&sin; - - af = PF_INET; - - self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP); - if (mb == INVALID_SOCKET) { - why = "su_port_init: socket"; goto error; - } - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */ - - /* Get a port for us */ - if (bind(mb, sa, sizeof sin) == -1) { - why = "su_port_init: bind"; goto error; - } - - if (getsockname(mb, sa, &sinsize) == -1) { - why = "su_port_init: getsockname"; goto error; - } - - if (connect(mb, sa, sinsize) == -1) { - why = "su_port_init: connect"; goto error; - } - } -#endif - - if (su_wait_create(&self->sup_mbox_wait, mb, SU_WAIT_IN) == -1) { - why = "su_port_init: su_wait_create"; goto error; - } - - if (su_port_register(self, NULL, &self->sup_mbox_wait, su_port_wakeup, - (su_wakeup_arg_t *)self->sup_mbox, 0) - == -1) { - why = "su_port_create: su_port_register"; goto error; - } - - SU_DEBUG_9(("su_port_create() returns %p\n", self)); - - return self; - - error: - su_perror(why); - su_port_destroy(self), self = NULL; -#endif - } - - SU_DEBUG_9(("su_port_create() returns %p\n", self)); - - return self; -} - -/** @internal Destroy a port. */ -void su_port_destroy(su_port_t *self) -{ - assert(self); - - SU_DEBUG_9(("su_port_destroy() called\n")); - -#if SU_HAVE_MBOX - if (self->sup_mbox[0] != INVALID_SOCKET) { - su_port_unregister(self, NULL, &self->sup_mbox_wait, NULL, - (su_wakeup_arg_t *)self->sup_mbox); - su_wait_destroy(&self->sup_mbox_wait); - su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET; -#if HAVE_SOCKETPAIR - su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET; -#endif - SU_DEBUG_9(("su_port_destroy() close mailbox\n")); - } -#endif - if (self->sup_waits) - free(self->sup_waits), self->sup_waits = NULL; - if (self->sup_wait_cbs) - free(self->sup_wait_cbs), self->sup_wait_cbs = NULL; - if (self->sup_wait_args) - free(self->sup_wait_args), self->sup_wait_args = NULL; - if (self->sup_wait_roots) - free(self->sup_wait_roots), self->sup_wait_roots = NULL; - if (self->sup_reverses) - free(self->sup_reverses), self->sup_reverses = NULL; - if (self->sup_indices) - free(self->sup_indices), self->sup_indices = NULL; - - SU_DEBUG_9(("su_port_destroy() freed registrations\n")); - - su_home_zap(self->sup_home); - - SU_DEBUG_9(("su_port_destroy() returns\n")); - -} - -static void su_port_lock(su_port_t *self, char const *who) -{ - SU_PORT_LOCK(self, who); -} - -static void su_port_unlock(su_port_t *self, char const *who) -{ - SU_PORT_UNLOCK(self, who); -} - -static void su_port_incref(su_port_t *self, char const *who) -{ - SU_PORT_INCREF(self, who); -} - -static void su_port_decref(su_port_t *self, int blocking, char const *who) -{ - if (blocking) - SU_PORT_ZAPREF(self, who); - else - SU_PORT_DECREF(self, who); -} - -static struct _GSource *su_port_gsource(su_port_t *self) -{ return NULL; } -#if SU_HAVE_MBOX -/** @internal Message box wakeup function. */ -static int su_port_wakeup(su_root_magic_t *magic, /* NULL */ - su_wait_t *w, - su_wakeup_arg_t *arg) +/* ======================================================================== + * su_clone_t + */ + +/**@ingroup su_wait + * + * @page su_clone_t Clone Objects + * + * The process may be divided into many tasks via cloning. Several tasks may + * run in context of one thread, or each task may be run by its own thread. + * However, only a single thread can execute code within a task. There can + * be a 1-to-N mapping from thread to tasks. Thus, software using tasks can + * be executed by multiple threads in a multithreaded environment and by a + * single thread in a singlethreaded environment. + * + * The clones are useful for handling tasks that can be executed by a + * separate threads, but which do not block excessively. When threads are + * not available or they are not needed, clones can also be run in a + * single-threaded mode. Running in single-threaded mode is especially + * useful while debugging. + * + * A clone task is created with function su_clone_start(). Each clone has + * its own root object (su_root_t), which holds a context pointer + * (su_root_magic_t *). The context object can be different from that of + * parent task. + * + * When a clone is started, the clone initialization function is called. The + * initialization function should do whatever initialization there is to be + * performed, register I/O events and timers, and then return. If the + * initialization is successful, the clone task reverts to run the event + * loop and invoking the event callbacks until its parent stops it by + * calling su_clone_wait() which invokes the deinit function. The clone task + * is destroyed when the deinit function returns. + * + * The public API consists of following functions: + * - su_clone_start() + * - su_clone_task() + * - su_clone_wait() + * - su_clone_forget() + * + * @note + * There is only one event loop for each thread which can be shared by + * multiple clone tasks. Therefore, the clone tasks can not explicitly run + * or step the event loop, but they are limited to event callbacks. A clone + * task may not call su_root_break(), su_root_run() or su_root_step(). + */ + +static int su_root_init_nothing(su_root_t *root, su_root_magic_t *magic) { - char buf[32]; - su_socket_t s = *(su_socket_t *)arg; - su_wait_events(w, s); - recv(s, buf, sizeof(buf), 0); return 0; } -#endif -/** @internal Send a message to the port. */ -int su_port_send(su_port_t *self, su_msg_r rmsg) +static void su_root_deinit_nothing(su_root_t *root, su_root_magic_t *magic) { - if (self) { - int wakeup; +} + +/** Start a clone task. + * + * Allocate and initialize a sub-task. Depending on the su_root_threading() + * settings, a separate thread may be created to execute the sub-task. The + * sub-task is represented by clone handle to the rest of the application. + * The function su_clone_start() returns the clone handle in @a + * return_clone. The clone handle is used to communicate with the newly + * created clone task using messages. + * + * A new #su_root_t object is created for the sub-task with the @a magic as + * the root context pointer. Because the sub-task may or may not have its + * own thread, all its activity must be scheduled via this root object. In + * other words, the sub-task can be schedule + * -# I/O events with su_root_register() + * -# timers with su_timer_set(), su_timer_set_at() or su_timer_run() + * -# messages with su_msg_send(). + * + * Messages can also be used to pass information between tasks or threads. + * + * In multi-threaded implementation, su_clone_start() launches a new thread, + * and the initialization routine is executed by this newly created thread. + * The calling thread blocks until the initialization routine completes. If + * the initialization routine returns #su_success (0), the sub-task is + * considered to be created successfully. After the successful + * initialization, the sub-task continues to execeute the function + * su_root_run(). + * + * In single-threaded implementations, just a new root object is created. + * The initialization routine is called directly from su_clone_start(). + * + * If the initalization function @a init fails, the sub-task (either the + * newly created thread or the current thread executing the su_clone_start() + * function) calls the deinitialization function, and su_clone_start() + * returns NULL. + * + * @param parent root to be cloned + * @param return_clone reference to a clone [OUT] + * @param magic pointer to user data + * @param init initialization function + * @param deinit deinitialization function + * + * @return 0 if successfull, -1 upon an error. + * + * @note Earlier documentation mentioned that @a parent could be NULL. That + * feature has never been implemented, however. + * + * @sa su_root_threading(), su_clone_task(), su_clone_stop(), su_clone_wait(), + * su_clone_forget(). + */ +int su_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + su_port_vtable_t const *svp; + + if (init == NULL) + init = su_root_init_nothing; + if (deinit == NULL) + deinit = su_root_deinit_nothing; - SU_PORT_LOCK(self, "su_port_send"); - wakeup = self->sup_head == NULL; + if (parent == NULL || parent->sur_threading) { + if (preferred_su_clone_start == NULL) + su_port_set_system_preferences(getenv("SU_PORT")); + if (preferred_su_clone_start == NULL) + return -1; + return preferred_su_clone_start(parent, return_clone, magic, init, deinit); + } - *self->sup_tail = rmsg[0]; rmsg[0] = NULL; - self->sup_tail = &(*self->sup_tail)->sum_next; + svp = parent->sur_task->sut_port->sup_vtable; -#if SU_HAVE_MBOX - /* if (!pthread_equal(pthread_self(), self->sup_tid)) */ - if (wakeup) - { - assert(self->sup_mbox[MBOX_SEND] != INVALID_SOCKET); + if (svp->su_port_start_shared == NULL) + return su_seterrno(EINVAL); - if (send(self->sup_mbox[MBOX_SEND], "X", 1, 0) == -1) { -#if HAVE_SOCKETPAIR - if (su_errno() != EWOULDBLOCK) -#endif - su_perror("su_msg_send: send()"); - } - } -#endif + /* Return a task sharing the same port. */ + return svp->su_port_start_shared(parent, return_clone, magic, init, deinit); +} - SU_PORT_UNLOCK(self, "su_port_send"); +/** Get reference to a clone task. + * + * @param clone Clone pointer + * + * @return A reference to the task structure of the clone. + */ +_su_task_r su_clone_task(su_clone_r clone) +{ + return su_msg_to(clone); +} +/**Forget the clone. + * + * Normally, the clone task executes until it is stopped. If the parent + * task does not need to stop the task, it can "forget" the clone. The + * clone exits independently of the parent task. + * + * @param rclone Reference to the clone. + */ +void su_clone_forget(su_clone_r rclone) +{ + su_msg_destroy(rclone); +} + +/** Stop the clone. + * + * This can used only if clone task has sent no report messages (messages + * with delivery report sent back to clone). + * + * @deprecated. Use su_clone_wait(). + */ +void su_clone_stop(su_clone_r rclone) +{ + su_msg_send(rclone); +} + +/** Stop a clone and wait until it is has completed. + * + * The function su_clone_wait() is used to stop the clone task and wait + * until it has cleaned up. The clone task is destroyed asynchronously. The + * parent sends a message to clone, clone deinitializes itself and then + * replies. After the reply message is received by the parent, it will send + * a third message back to clone. + * + * The parent destroy all messages to or from clone task before calling + * su_clone_wait(). The parent task may not send any messages to the clone + * after calling su_clone_wait(). The su_clone_wait() function blocks until + * the cloned task is destroyed. During that time, the parent task must be + * prepared to process all the messages sent by clone task. This includes + * all the messages sent by clone before destroy the message reached the + * clone. + */ +void su_clone_wait(su_root_t *root, su_clone_r rclone) +{ + if (rclone[0]) { + assert(root == NULL || root == su_msg_from(rclone)->sut_root); + su_port_wait(rclone); + } +} + +/** Pause a clone. + * + * Obtain an exclusive lock on clone's private data. + * + * @retval 0 if successful (and clone is paused) + * @retval -1 upon an error + * + * @deprecated Never implemented. + */ +int su_clone_pause(su_clone_r rclone) +{ +#if 0 + su_root_t *cloneroot = su_task_root(su_msg_to(rclone)); + + if (!cloneroot) + return (errno = EFAULT), -1; + + if (SU_ROOT_OWN_THREAD(cloneroot)) + /* We own it already */ return 0; - } - else { - su_msg_destroy(rmsg); - return -1; - } -} -/** @internal - * Execute the messages in the incoming queue until the queue is empty.. - * - * @param self - pointer to a port object - * - * @retval Number of messages sent - */ -int su_port_getmsgs(su_port_t *self) -{ - int n = 0; - - if (self->sup_head) { - su_msg_f f; - su_msg_t *msg, *queue; - - SU_PORT_LOCK(self, "su_port_getmsgs"); - - queue = self->sup_head; - self->sup_tail = &self->sup_head; - self->sup_head = NULL; - - SU_PORT_UNLOCK(self, "su_port_getmsgs"); - - for (msg = queue; msg; msg = queue) { - queue = msg->sum_next; - msg->sum_next = NULL; - - f = msg->sum_func; - if (f) - f(SU_ROOT_MAGIC(msg->sum_to->sut_root), &msg, msg->sum_data); - su_msg_delivery_report(&msg); - n++; - } - - /* Check for wait events that may have been generated by messages */ - su_port_wait_events(self, 0); - } - - return n; -} - -/** @internal - * - * Register a @c su_wait_t object. The wait object, a callback function and - * a argument pointer is stored in the port object. The callback function - * will be called when the wait object is signaled. - * - * Please note if identical wait objects are inserted, only first one is - * ever signalled. - * - * @param self pointer to port - * @param root pointer to root object - * @param waits pointer to wait object - * @param callback callback function pointer - * @param arg argument given to callback function when it is invoked - * @param priority relative priority of the wait object - * (0 is normal, 1 important, 2 realtime) - * - * @return - * Positive index of the wait object, - * or -1 upon an error. - */ -int su_port_register(su_port_t *self, - su_root_t *root, - su_wait_t *wait, - su_wakeup_f callback, - su_wakeup_arg_t *arg, - int priority) -{ - int i, j, n; - - assert(SU_PORT_OWN_THREAD(self)); - - n = self->sup_n_waits; - - if (n >= SU_WAIT_MAX) - return su_seterrno(ENOMEM); - - if (n >= self->sup_size_waits) { - /* Reallocate size arrays */ - int size; - int *indices; - int *reverses; - su_wait_t *waits; - su_wakeup_f *wait_cbs; - su_wakeup_arg_t **wait_args; - su_root_t **wait_tasks; - - if (self->sup_size_waits == 0) - size = su_root_size_hint; - else - size = 2 * self->sup_size_waits; - - if (size < SU_WAIT_MIN) - size = SU_WAIT_MIN; - - /* Too large */ - if (-3 - size > 0) - return (errno = ENOMEM), -1; - - indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices)); - if (indices) { - self->sup_indices = indices; - - if (self->sup_size_waits == 0) - indices[0] = -1; - - for (i = self->sup_size_waits + 1; i <= size; i++) - indices[i] = -1 - i; - } - - reverses = realloc(self->sup_reverses, size * sizeof(*waits)); - if (reverses) { - for (i = self->sup_size_waits; i < size; i++) - reverses[i] = -1; - self->sup_reverses = reverses; - } - - waits = realloc(self->sup_waits, size * sizeof(*waits)); - if (waits) - self->sup_waits = waits; - - wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs)); - if (wait_cbs) - self->sup_wait_cbs = wait_cbs; - - wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args)); - if (wait_args) - self->sup_wait_args = wait_args; - - /* Add sup_wait_roots array, if needed */ - wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks)); - if (wait_tasks) - self->sup_wait_roots = wait_tasks; - - if (!(indices && - reverses && waits && wait_cbs && wait_args && wait_tasks)) { - return -1; - } - - self->sup_size_waits = size; - } - - i = -self->sup_indices[0]; assert(i <= self->sup_size_waits); - -#if HAVE_EPOLL - if (self->sup_epoll != -1) { - struct epoll_event ev; - - ev.events = POLL2EPOLL(wait->events); - ev.data.u64 = 0; - ev.data.u32 = (uint32_t)i; - - if (epoll_ctl(self->sup_epoll, EPOLL_CTL_ADD, wait->fd, &ev) == -1) { - SU_DEBUG_0(("EPOLL_CTL_ADD(%u, %u) failed: %s\n", - wait->fd, ev.events, strerror(errno))); - return -1; - } - } - else -#endif - if (priority > 0) { - /* Insert */ - for (n = self->sup_n_waits; n > 0; n--) { - j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1); - self->sup_indices[j] = n; - self->sup_reverses[n] = j; - self->sup_waits[n] = self->sup_waits[n-1]; - self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; - self->sup_wait_args[n] = self->sup_wait_args[n-1]; - self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; - } - - self->sup_pri_offset++; - } - else { - /* Append - no need to move anything */ - n = self->sup_n_waits; - } - - self->sup_n_waits++; - - self->sup_indices[0] = self->sup_indices[i]; /* Free index */ - self->sup_indices[i] = n; - - self->sup_reverses[n] = i; - self->sup_waits[n] = *wait; - self->sup_wait_cbs[n] = callback; - self->sup_wait_args[n] = arg; - self->sup_wait_roots[n] = root; - - self->sup_registers++; - - /* Just like epoll, we return -1 or positive integer */ - - return i; -} - -/** Deregister a su_wait_t object. */ -static -int su_port_deregister0(su_port_t *self, int i) -{ - int n, N, *indices, *reverses; - - indices = self->sup_indices; - reverses = self->sup_reverses; - - n = indices[i]; assert(n >= 0); - -#if HAVE_EPOLL - if (self->sup_epoll != -1) { - su_wait_t *wait = &self->sup_waits[n]; - struct epoll_event ev; - - ev.events = POLL2EPOLL(wait->events); - ev.data.u64 = (uint64_t)0; - ev.data.u32 = (uint32_t)i; - - if (epoll_ctl(self->sup_epoll, EPOLL_CTL_DEL, wait->fd, &ev) == -1) { - SU_DEBUG_1(("su_port(%p): EPOLL_CTL_DEL(%u): %s\n", self, - wait->fd, su_strerror(su_errno()))); - } - } + return su_port_pause(cloneroot->sur_port); +#else + return errno = ENOSYS, -1; #endif - - N = --self->sup_n_waits; - - if (n < self->sup_pri_offset) { - int j = --self->sup_pri_offset; - if (n != j) { - assert(reverses[j] > 0); - assert(indices[reverses[j]] == j); - indices[reverses[j]] = n; - reverses[n] = reverses[j]; - - self->sup_waits[n] = self->sup_waits[j]; - self->sup_wait_cbs[n] = self->sup_wait_cbs[j]; - self->sup_wait_args[n] = self->sup_wait_args[j]; - self->sup_wait_roots[n] = self->sup_wait_roots[j]; - n = j; - } - } - - if (n < N) { - assert(reverses[N] > 0); - assert(indices[reverses[N]] == N); - - indices[reverses[N]] = n; - reverses[n] = reverses[N]; - - self->sup_waits[n] = self->sup_waits[N]; - self->sup_wait_cbs[n] = self->sup_wait_cbs[N]; - self->sup_wait_args[n] = self->sup_wait_args[N]; - self->sup_wait_roots[n] = self->sup_wait_roots[N]; - n = N; - } - - reverses[n] = -1; - memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]); - self->sup_wait_cbs[n] = NULL; - self->sup_wait_args[n] = NULL; - self->sup_wait_roots[n] = NULL; - - indices[i] = indices[0]; - indices[0] = -i; - - self->sup_registers++; - - return i; } - -/** Unregister a su_wait_t object. - * - * The function su_port_unregister() unregisters a su_wait_t object. The - * wait object, a callback function and a argument are removed from the - * port object. - * - * @param self - pointer to port object - * @param root - pointer to root object - * @param wait - pointer to wait object - * @param callback - callback function pointer (may be NULL) - * @param arg - argument given to callback function when it is invoked - * (may be NULL) +/** Resume a clone. * - * @deprecated Use su_port_deregister() instead. + * Give up an exclusive lock on clone's private data. * - * @return Nonzero index of the wait object, or -1 upon an error. + * @retval 0 if successful (and clone is resumed) + * @retval -1 upon an error + * + * @deprecated Never implemented. */ -int su_port_unregister(su_port_t *self, - su_root_t *root, - su_wait_t *wait, - su_wakeup_f callback, /* XXX - ignored */ - su_wakeup_arg_t *arg) +int su_clone_resume(su_clone_r rclone) { - int n, N; - - assert(self); - assert(SU_PORT_OWN_THREAD(self)); - - N = self->sup_n_waits; - - for (n = 0; n < N; n++) { - if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { - return su_port_deregister0(self, self->sup_reverses[n]); - } - } - - su_seterrno(ENOENT); - - return -1; -} - -/** Deregister a su_wait_t object. - * - * The function su_port_deregister() deregisters a su_wait_t registrattion. - * The wait object, a callback function and a argument are removed from the - * port object. - * - * @param self - pointer to port object - * @param i - registration index - * - * @return Index of the wait object, or -1 upon an error. - */ -int su_port_deregister(su_port_t *self, int i) -{ - su_wait_t wait[1] = { SU_WAIT_INIT }; - int retval; - - assert(self); - assert(SU_PORT_OWN_THREAD(self)); - - if (i <= 0 || i > self->sup_size_waits) - return su_seterrno(EBADF); - - if (self->sup_indices[i] < 0) - return su_seterrno(EBADF); - - retval = su_port_deregister0(self, i); - - su_wait_destroy(wait); - - return retval; -} - - -/** @internal - * Unregister all su_wait_t objects. - * - * The function su_port_unregister_all() unregisters all su_wait_t objects - * and destroys all queued timers associated with given root object. - * - * @param self - pointer to port object - * @param root - pointer to root object - * - * @return Number of wait objects removed. - */ -int su_port_unregister_all(su_port_t *self, - su_root_t *root) -{ - int i, j, index, N; - int *indices, *reverses; - su_wait_t *waits; - su_wakeup_f *wait_cbs; - su_wakeup_arg_t**wait_args; - su_root_t **wait_roots; - - assert(SU_PORT_OWN_THREAD(self)); - - N = self->sup_n_waits; - indices = self->sup_indices; - reverses = self->sup_reverses; - waits = self->sup_waits; - wait_cbs = self->sup_wait_cbs; - wait_args = self->sup_wait_args; - wait_roots = self->sup_wait_roots; - - for (i = j = 0; i < N; i++) { - index = reverses[i]; assert(index > 0 && indices[index] == i); - - if (wait_roots[i] == root) { - /* XXX - we should free all resources associated with this, too */ -#if HAVE_EPOLL - if (self->sup_epoll != -1) { - int fd = waits[i].fd; - struct epoll_event ev; - - ev.events = POLL2EPOLL(waits[i].events); - ev.data.u64 = (uint64_t)0; - ev.data.u32 = (uint32_t)index; - - if (epoll_ctl(self->sup_epoll, EPOLL_CTL_DEL, fd, &ev) == -1) { - SU_DEBUG_1(("EPOLL_CTL_DEL(%u): %s\n", - waits[i].fd, su_strerror(su_errno()))); - } - } -#endif - if (i < self->sup_pri_offset) - self->sup_pri_offset--; - - indices[index] = indices[0]; - indices[0] = -index; - continue; - } - - if (i != j) { - indices[index] = j; - reverses[j] = reverses[i]; - waits[j] = waits[i]; - wait_cbs[j] = wait_cbs[i]; - wait_args[j] = wait_args[i]; - wait_roots[j] = wait_roots[i]; - } - - j++; - } - - for (i = j; i < N; i++) { - reverses[i] = -1; - wait_cbs[i] = NULL; - wait_args[i] = NULL; - wait_roots[i] = NULL; - } - memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]); - - self->sup_n_waits = j; - self->sup_registers++; - - return N - j; -} - -/**Set mask for a registered event. @internal - * - * The function su_port_eventmask() sets the mask describing events that can - * signal the registered callback. - * - * @param port pointer to port object - * @param index registration index - * @param socket socket - * @param events new event mask - * - * @retval 0 when successful, - * @retval -1 upon an error. - */ -int su_port_eventmask(su_port_t *self, int index, int socket, int events) -{ - int n; - assert(self); - assert(SU_PORT_OWN_THREAD(self)); - - if (index <= 0 || index > self->sup_size_waits) - return su_seterrno(EBADF); - n = self->sup_indices[index]; - if (n < 0) - return su_seterrno(EBADF); - -#if HAVE_EPOLL - if (self->sup_epoll != -1) { - su_wait_t *wait = &self->sup_waits[n]; - struct epoll_event ev; - - wait->events = events; - - ev.events = POLL2EPOLL(events); - ev.data.u64 = (uint64_t)0; - ev.data.u32 = (uint32_t)index; - - if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, wait->fd, &ev) == -1) { - SU_DEBUG_1(("su_port(%p): EPOLL_CTL_MOD(%u): %s\n", self, - wait->fd, su_strerror(su_errno()))); - return -1; - } - } -#endif - - return su_wait_mask(&self->sup_waits[n], socket, events); -} - #if 0 -/** @internal - * - * Copies the su_wait_t objects from the port. The number of wait objects - * can be found out by calling su_port_query() with @a n_waits as zero. - * - * @note This function is called only by friends. - * - * @param self - pointer to port object - * @param waits - pointer to array to which wait objects are copied - * @param n_waits - number of wait objects fitting in array waits - * - * @return Number of wait objects, or 0 upon an error. - */ -unsigned su_port_query(su_port_t *self, su_wait_t *waits, unsigned n_waits) + su_root_t *cloneroot = su_task_root(su_msg_to(rclone)); + + if (!cloneroot) + return (errno = EFAULT), -1; + + if (SU_ROOT_OWN_THREAD(cloneroot)) + /* We cannot give it away */ + return 0; + + return su_port_resume(cloneroot->sur_port); +#else + return errno = ENOSYS, -1; +#endif +} + +void su_port_wait(su_clone_r rclone) { - unsigned n; + su_port_t *cloneport; - assert(SU_PORT_OWN_THREAD(self)); + cloneport = su_msg_to(rclone)->sut_port; + cloneport->sup_vtable->su_port_wait(rclone); +} - n = self->sup_n_waits; +int su_port_execute(su_task_r const task, + int (*function)(void *), void *arg, + int *return_value) +{ + if (!task->sut_port->sup_vtable->su_port_execute) + return errno = ENOSYS, -1; - if (n_waits != 0) { - if (waits && n_waits >= n) - memcpy(waits, self->sup_waits, n * sizeof(*waits)); - else - n = 0; - } + return task->sut_port->sup_vtable-> + su_port_execute(task, function, arg, return_value); +} - return n; +#if notyet && nomore +int su_port_pause(su_port_t *self) +{ + assert(self->sup_vtable->su_port_pause); + return self->sup_vtable->su_port_pause(self); +} + +int su_port_resume(su_port_t *self) +{ + assert(self->sup_vtable->su_port_resume); + return self->sup_vtable->su_port_resume(self); } #endif - -/** @internal Enable multishot mode. - * - * The function su_port_multishot() enables, disables or queries the - * multishot mode for the port. The multishot mode determines how the events - * are scheduled by port. If multishot mode is enabled, port serves all the - * sockets that have received network events. If it is disables, only first - * socket event is served. - * - * @param self pointer to port object - * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) - * - * @retval 0 multishot mode is disabled - * @retval 1 multishot mode is enabled - * @retval -1 an error occurred - */ -int su_port_multishot(su_port_t *self, int multishot) -{ - if (multishot < 0) - return self->sup_multishot; - else if (multishot == 0 || multishot == 1) - return self->sup_multishot = multishot; - else - return (errno = EINVAL), -1; -} - -/** @internal Enable threadsafe operation. */ -static -int su_port_threadsafe(su_port_t *port) -{ - return su_home_threadsafe(port->sup_home); -} - -/** @internal Main loop. - * - * The function @c su_port_run() waits for wait objects and the timers - * associated with the port object. When any wait object is signaled or - * timer is expired, it invokes the callbacks, and returns waiting. - * - * The function @c su_port_run() runs until @c su_port_break() is called - * from a callback. - * - * @param self pointer to port object - * - */ -void su_port_run(su_port_t *self) -{ - su_duration_t tout = 0; - - assert(SU_PORT_OWN_THREAD(self)); - - for (self->sup_running = 1; self->sup_running;) { - tout = 2000; - - if (self->sup_prepoll) - self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); - - if (self->sup_head) - su_port_getmsgs(self); - - if (self->sup_timers) - su_timer_expire(&self->sup_timers, &tout, su_now()); - - if (!self->sup_running) - break; - - if (self->sup_head) /* if there are messages do a quick wait */ - tout = 0; - - su_port_wait_events(self, tout); - } -} - -#if tuning -/* This version can help tuning... */ -void su_port_run_tune(su_port_t *self) -{ - int i; - int timers = 0, messages = 0, events = 0; - su_duration_t tout = 0, tout0; - su_time_t started = su_now(), woken = started, bedtime = woken; - - assert(SU_PORT_OWN_THREAD(self)); - - for (self->sup_running = 1; self->sup_running;) { - tout0 = tout, tout = 2000; - - timers = 0, messages = 0; - - if (self->sup_prepoll) - self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); - - if (self->sup_head) - messages = su_port_getmsgs(self); - - if (self->sup_timers) - timers = su_timer_expire(&self->sup_timers, &tout, su_now()); - - if (!self->sup_running) - break; - - if (self->sup_head) /* if there are messages do a quick wait */ - tout = 0; - - bedtime = su_now(); - - events = su_port_wait_events(self, tout); - - woken = su_now(); - - if (messages || timers || events) - SU_DEBUG_1(("su_port_run(%p): %.6f: %u messages %u timers %u " - "events slept %.6f/%.3f\n", - self, su_time_diff(woken, started), messages, timers, events, - su_time_diff(woken, bedtime), tout0 * 1e-3)); - - if (!self->sup_running) - break; - } -} -#endif - -/** @internal - * The function @c su_port_break() is used to terminate execution of @c - * su_port_run(). It can be called from a callback function. - * - * @param self pointer to port - * - */ -void su_port_break(su_port_t *self) -{ - self->sup_running = 0; -} - -/** @internal - * The function @c su_port_wait_events() is used to poll() for wait objects - * - * @param self pointer to port - * @param tout timeout in milliseconds - * - * @return number of events handled - */ -static -int su_port_wait_events(su_port_t *self, su_duration_t tout) -{ - int i, events = 0; - su_wait_t *waits = self->sup_waits; - int n = self->sup_n_waits; - su_root_t *root; -#if HAVE_POLL - unsigned version = self->sup_registers; -#endif -#if HAVE_EPOLL - - if (self->sup_epoll != -1) { - int const M = 4; - struct epoll_event ev[M]; - int j, index; - int *indices = self->sup_indices; - - n = epoll_wait(self->sup_epoll, ev, self->sup_multishot ? M : 1, tout); - - assert(n <= M); - - for (j = 0; j < n; j++) { - su_root_t *root; - su_root_magic_t *magic; - - if (!ev[j].events || ev[j].data.u32 > INDEX_MAX) - continue; - index = (int)ev[j].data.u32; - assert(index > 0 && index <= self->sup_size_waits); - i = indices[index]; assert(i >= 0 && i <= self->sup_n_waits); - root = self->sup_wait_roots[i]; - magic = root ? su_root_magic(root) : NULL; - waits[i].revents = ev[j].events; - self->sup_wait_cbs[i](magic, &waits[i], self->sup_wait_args[i]); - events++; - /* Callback function used su_register()/su_deregister() */ - if (version != self->sup_registers) - break; - } - - return n < 0 ? n : events; - } -#endif - - i = su_wait(waits, (unsigned)n, tout); - - if (i >= 0 && i < n) { -#if HAVE_POLL - /* poll() can return events for multiple wait objects */ - if (self->sup_multishot) { - for (; i < n; i++) { - if (waits[i].revents) { - root = self->sup_wait_roots[i]; - self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, - &waits[i], - self->sup_wait_args[i]); - events++; - /* Callback function used su_register()/su_deregister() */ - if (version != self->sup_registers) - break; - } - } - } -#else /* !HAVE_POLL */ - if (0) { - } -#endif - else { - root = self->sup_wait_roots[i]; - self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, - &self->sup_waits[i], - self->sup_wait_args[i]); - events++; - } - } - - return events; -} - -/** @internal - * Used to check wait events in callbacks that take lots of time - * - * This function does a timeout 0 poll() and runs wait objects. - * - * @param port pointer to port - * - * @return number of events handled - */ -static -int su_port_yield(su_port_t *port) -{ - return su_port_wait_events(port, 0); -} - -/** @internal Block until wait object is signaled or timeout. - * - * This function waits for wait objects and the timers associated with - * the root object. When any wait object is signaled or timer is - * expired, it invokes the callbacks. - * - * This function returns when a callback has been invoked or @c tout - * milliseconds is elapsed. - * - * @param self pointer to port - * @param tout timeout in milliseconds - * - * @return - * Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if - * there are no active timers. - */ -su_duration_t su_port_step(su_port_t *self, su_duration_t tout) -{ - su_time_t now = su_now(); - - assert(SU_PORT_OWN_THREAD(self)); - - if (self->sup_prepoll) - self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root); - - if (self->sup_head) - su_port_getmsgs(self); - - if (self->sup_timers) - su_timer_expire(&self->sup_timers, &tout, now); - - /* if there are messages do a quick wait */ - if (self->sup_head) - tout = 0; - - if (su_port_wait_events(self, tout)) - tout = 0; - else - tout = SU_WAIT_FOREVER; - - if (self->sup_head) - su_port_getmsgs(self); - - if (self->sup_timers) - su_timer_expire(&self->sup_timers, &tout, su_now()); - - if (self->sup_head) - tout = 0; - - return tout; -} - - -/** @internal - * Checks if the calling thread owns the port object. - * - * @param self pointer to a port object - * - * @retval true (nonzero) if the calling thread owns the port, - * @retval false (zero) otherwise. - */ -int su_port_own_thread(su_port_t const *self) -{ - return self == NULL || SU_PORT_OWN_THREAD(self); -} - -#if 0 -/** @internal - * Prints out the contents of the port. - * - * @param self pointer to a port - * @param f pointer to a file (if @c NULL, uses @c stdout). - */ -void su_port_dump(su_port_t const *self, FILE *f) -{ - int i; -#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "") -#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "") -#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "") - - if (f == NULL) - f = stdout; - - fprintf(f, "su_port_t at %p:\n", self); - fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); -#if SU_HAVE_PTHREADS - fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); -#endif -#if SU_HAVE_MBOX - fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0], - IS_WAIT_IN(&self->sup_mbox_wait), - IS_WAIT_OUT(&self->sup_mbox_wait), - IS_WAIT_ACCEPT(&self->sup_mbox_wait)); -#endif - fprintf(f, "\t%d wait objects\n", self->sup_n_waits); - for (i = 0; i < self->sup_n_waits; i++) { - - } -} - -#endif - -/* ========================================================================= - * Pre-poll() callback - */ - -int su_port_add_prepoll(su_port_t *port, - su_root_t *root, - su_prepoll_f *callback, - su_prepoll_magic_t *magic) -{ - if (port->sup_prepoll) - return -1; - - port->sup_prepoll = callback; - port->sup_pp_magic = magic; - port->sup_pp_root = root; - - return 0; -} - -int su_port_remove_prepoll(su_port_t *port, - su_root_t *root) -{ - if (port->sup_pp_root != root) - return -1; - - port->sup_prepoll = NULL; - port->sup_pp_magic = NULL; - port->sup_pp_root = NULL; - - return 0; -} - -/* ========================================================================= - * Timers - */ - -static -su_timer_t **su_port_timers(su_port_t *self) -{ - return &self->sup_timers; -} diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_port.h b/libs/sofia-sip/libsofia-sip-ua/su/su_port.h index 1d13ec15e5..d650dbe5f1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_port.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_port.h @@ -86,7 +86,7 @@ struct su_root_s { #define SU_ROOT_MAGIC(r) ((r) ? (r)->sur_magic : NULL) /** Virtual function table for port */ -typedef struct { +typedef struct su_port_vtable { unsigned su_vtable_size; void (*su_port_lock)(su_port_t *port, char const *who); void (*su_port_unlock)(su_port_t *port, char const *who); @@ -128,80 +128,130 @@ typedef struct { int (*su_port_multishot)(su_port_t *port, int multishot); int (*su_port_threadsafe)(su_port_t *port); - /* Extension from > 1.12.0 */ int (*su_port_yield)(su_port_t *port); + /* Extension from >= 1.12.4 */ + int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout); + int (*su_port_getmsgs)(su_port_t *port); + /* Extension from >= 1.12.5 */ + int (*su_port_getmsgs_from)(su_port_t *port, su_port_t *cloneport); + char const *(*su_port_name)(su_port_t const *port); + int (*su_port_start_shared)(su_root_t *root, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit); + void (*su_port_wait)(su_clone_r rclone); + int (*su_port_execute)(su_task_r const task, + int (*function)(void *), void *arg, + int *return_value); } su_port_vtable_t; SOFIAPUBFUN su_port_t *su_port_create(void) __attribute__((__malloc__)); +/* Extension from >= 1.12.5 */ + +typedef su_port_t *su_port_create_f(void); +typedef int su_clone_start_f(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit); + +SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *); + +SOFIAPUBFUN su_port_t *su_epoll_port_create(void) + __attribute__((__malloc__)); +SOFIAPUBFUN su_port_t *su_poll_port_create(void) + __attribute__((__malloc__)); +SOFIAPUBFUN su_port_t *su_select_port_create(void) + __attribute__((__malloc__)); + +SOFIAPUBFUN su_clone_start_f su_epoll_clone_start; +SOFIAPUBFUN su_clone_start_f su_poll_clone_start; +SOFIAPUBFUN su_clone_start_f su_select_clone_start; + SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg); SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now); SOFIAPUBFUN su_root_t *su_root_create_with_port(su_root_magic_t *magic, - su_port_t *port); + su_port_t *port) + __attribute__((__malloc__)); -#if SU_PORT_IMPLEMENTATION +/* ---------------------------------------------------------------------- */ +/* React to multiple events per one poll() to make sure + * that high-priority events can never completely mask other events. + * Enabled by default on all platforms except WIN32 */ +#if !defined(WIN32) +#define SU_ENABLE_MULTISHOT_POLL 1 #else -struct su_port_s { - su_home_t sup_home[1]; +#define SU_ENABLE_MULTISHOT_POLL 0 +#endif + +/* ---------------------------------------------------------------------- */ +/* Virtual functions */ + +typedef struct su_virtual_port_s { + su_home_t sup_home[1]; su_port_vtable_t const *sup_vtable; -}; +} su_virtual_port_t; + +static inline +su_home_t *su_port_home(su_port_t const *self) +{ + return (su_home_t *)self; +} static inline void su_port_lock(su_port_t *self, char const *who) { - if (self) self->sup_vtable->su_port_lock(self, who); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) base->sup_vtable->su_port_lock(self, who); } -#define SU_PORT_LOCK(p, f) (su_port_lock(p, #f)) - static inline void su_port_unlock(su_port_t *self, char const *who) { - if (self) self->sup_vtable->su_port_unlock(self, who); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) base->sup_vtable->su_port_unlock(self, who); } -#define SU_PORT_UNLOCK(p, f) (su_port_unlock(p, #f)) - static inline void su_port_incref(su_port_t *self, char const *who) { - if (self) self->sup_vtable->su_port_incref(self, who); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) base->sup_vtable->su_port_incref(self, who); } -#define SU_PORT_INCREF(p, f) (su_port_incref(p, #f)) - static inline void su_port_decref(su_port_t *self, char const *who) { - if (self) self->sup_vtable->su_port_decref(self, 0, who); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) base->sup_vtable->su_port_decref(self, 0, who); } -#define SU_PORT_DECREF(p, f) (su_port_decref(p, #f)) - static inline void su_port_zapref(su_port_t *self, char const *who) { - if (self) self->sup_vtable->su_port_decref(self, 1, who); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) base->sup_vtable->su_port_decref(self, 1, who); } -#define SU_PORT_ZAPREF(p, f) (su_port_zapref(p, #f)) - static inline struct _GSource *su_port_gsource(su_port_t *self) { - return self ? self->sup_vtable->su_port_gsource(self) : NULL; + su_virtual_port_t *base = (su_virtual_port_t *)self; + return base ? base->sup_vtable->su_port_gsource(self) : NULL; } - static inline int su_port_send(su_port_t *self, su_msg_r rmsg) { - if (self) - return self->sup_vtable->su_port_send(self, rmsg); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_send(self, rmsg); errno = EINVAL; return -1; } @@ -215,8 +265,9 @@ int su_port_register(su_port_t *self, su_wakeup_arg_t *arg, int priority) { - if (self) - return self->sup_vtable->su_port_register(self, root, wait, + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_register(self, root, wait, callback, arg, priority); errno = EINVAL; return -1; @@ -229,8 +280,9 @@ int su_port_unregister(su_port_t *self, su_wakeup_f callback, su_wakeup_arg_t *arg) { - if (self) - return self->sup_vtable-> + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable-> su_port_unregister(self, root, wait, callback, arg); errno = EINVAL; return -1; @@ -239,9 +291,9 @@ int su_port_unregister(su_port_t *self, static inline int su_port_deregister(su_port_t *self, int i) { - if (self) - return self->sup_vtable-> - su_port_deregister(self, i); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_deregister(self, i); errno = EINVAL; return -1; } @@ -250,8 +302,9 @@ static inline int su_port_unregister_all(su_port_t *self, su_root_t *root) { - if (self) - return self->sup_vtable-> + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable-> su_port_unregister_all(self, root); errno = EINVAL; return -1; @@ -260,10 +313,11 @@ int su_port_unregister_all(su_port_t *self, static inline int su_port_eventmask(su_port_t *self, int index, int socket, int events) { - if (self) - return self->sup_vtable-> + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable-> su_port_eventmask(self, index, socket, events); - assert(self); + assert(base); errno = EINVAL; return -1; } @@ -271,22 +325,25 @@ int su_port_eventmask(su_port_t *self, int index, int socket, int events) static inline void su_port_run(su_port_t *self) { - if (self) - self->sup_vtable->su_port_run(self); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + base->sup_vtable->su_port_run(self); } static inline void su_port_break(su_port_t *self) { - if (self) - self->sup_vtable->su_port_break(self); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + base->sup_vtable->su_port_break(self); } static inline su_duration_t su_port_step(su_port_t *self, su_duration_t tout) { - if (self) - return self->sup_vtable->su_port_step(self, tout); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_step(self, tout); errno = EINVAL; return (su_duration_t)-1; } @@ -295,7 +352,8 @@ su_duration_t su_port_step(su_port_t *self, su_duration_t tout) static inline int su_port_own_thread(su_port_t const *self) { - return self == NULL || self->sup_vtable->su_port_own_thread(self); + su_virtual_port_t const *base = (su_virtual_port_t *)self; + return base == NULL || base->sup_vtable->su_port_own_thread(self); } static inline @@ -304,8 +362,9 @@ int su_port_add_prepoll(su_port_t *self, su_prepoll_f *prepoll, su_prepoll_magic_t *magic) { - if (self) - return self->sup_vtable-> + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable-> su_port_add_prepoll(self, root, prepoll, magic); errno = EINVAL; return -1; @@ -315,8 +374,9 @@ static inline int su_port_remove_prepoll(su_port_t *self, su_root_t *root) { - if (self) - return self->sup_vtable->su_port_remove_prepoll(self, root); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_remove_prepoll(self, root); errno = EINVAL; return -1; } @@ -324,8 +384,9 @@ int su_port_remove_prepoll(su_port_t *self, static inline su_timer_t **su_port_timers(su_port_t *self) { - if (self) - return self->sup_vtable->su_port_timers(self); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_timers(self); errno = EINVAL; return NULL; } @@ -333,10 +394,11 @@ su_timer_t **su_port_timers(su_port_t *self) static inline int su_port_multishot(su_port_t *self, int multishot) { - if (self) - return self->sup_vtable->su_port_multishot(self, multishot); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_multishot(self, multishot); - assert(self); + assert(base); errno = EINVAL; return -1; } @@ -344,14 +406,187 @@ int su_port_multishot(su_port_t *self, int multishot) static inline int su_port_threadsafe(su_port_t *self) { - if (self) - return self->sup_vtable->su_port_threadsafe(self); + su_virtual_port_t *base = (su_virtual_port_t *)self; + if (base) + return base->sup_vtable->su_port_threadsafe(self); - assert(self); + assert(base); errno = EINVAL; return -1; } +static inline +int su_port_getmsgs(su_port_t *self) +{ + su_virtual_port_t *base = (su_virtual_port_t *)self; + + return base->sup_vtable->su_port_getmsgs(self); +} + +static inline +int su_port_getmsgs_from(su_port_t *self, su_port_t *cloneport) +{ + su_virtual_port_t *base = (su_virtual_port_t *)self; + + return base->sup_vtable->su_port_getmsgs_from(self, cloneport); +} + +SOFIAPUBFUN void su_port_wait(su_clone_r rclone); + +SOFIAPUBFUN int su_port_execute(su_task_r const task, + int (*function)(void *), void *arg, + int *return_value); + +/* ---------------------------------------------------------------------- */ + +/** Base port object. + * + * Port is a per-thread reactor. Multiple root objects executed by a single + * thread share the su_port_t object. + */ +typedef struct su_base_port_s { + su_home_t sup_home[1]; + su_port_vtable_t const *sup_vtable; + + /* Implementation may vary stuff below, too. */ + + /* Pre-poll callback */ + su_prepoll_f *sup_prepoll; + su_prepoll_magic_t *sup_pp_magic; + su_root_t *sup_pp_root; + + /* Message list - this is protected by su_port_lock()/su_port_unlock() */ + su_msg_t *sup_head, **sup_tail; + + /* Timer list */ + su_timer_t *sup_timers; + + unsigned sup_running; /**< In su_root_run() loop? */ +} su_base_port_t; + +/* Base methods */ + +SOFIAPUBFUN int su_base_port_init(su_port_t *, su_port_vtable_t const *); +SOFIAPUBFUN void su_base_port_deinit(su_port_t *self); + +SOFIAPUBFUN void su_base_port_lock(su_port_t *self, char const *who); +SOFIAPUBFUN void su_base_port_unlock(su_port_t *self, char const *who); + +SOFIAPUBFUN int su_base_port_own_thread(su_port_t const *self); + +SOFIAPUBFUN void su_base_port_incref(su_port_t *self, char const *who); +SOFIAPUBFUN int su_base_port_decref(su_port_t *self, + int blocking, + char const *who); + +SOFIAPUBFUN struct _GSource *su_base_port_gsource(su_port_t *self); + +SOFIAPUBFUN su_socket_t su_base_port_mbox(su_port_t *self); +SOFIAPUBFUN int su_base_port_send(su_port_t *self, su_msg_r rmsg); +SOFIAPUBFUN int su_base_port_getmsgs(su_port_t *self); +SOFIAPUBFUN int su_base_port_getmsgs_from(su_port_t *self, + su_port_t *from); + +SOFIAPUBFUN void su_base_port_run(su_port_t *self); +SOFIAPUBFUN void su_base_port_break(su_port_t *self); +SOFIAPUBFUN su_duration_t su_base_port_step(su_port_t *self, + su_duration_t tout); + +SOFIAPUBFUN int su_base_port_add_prepoll(su_port_t *self, + su_root_t *root, + su_prepoll_f *, + su_prepoll_magic_t *); + +SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root); + +SOFIAPUBFUN su_timer_t **su_base_port_timers(su_port_t *self); + +SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot); +SOFIAPUBFUN int su_base_port_threadsafe(su_port_t *self); +SOFIAPUBFUN int su_base_port_yield(su_port_t *self); + +SOFIAPUBFUN int su_base_port_start_shared(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit); +SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone); + +/* ---------------------------------------------------------------------- */ + +#if SU_HAVE_PTHREADS + +#include + +#define SU_MBOX_SIZE 2 + +/** Pthread port object */ +typedef struct su_pthread_port_s { + su_base_port_t sup_base[1]; + struct su_pthread_port_waiting_parent + *sup_waiting_parent; + pthread_t sup_tid; + pthread_mutex_t sup_runlock[1]; +#if 0 + pthread_cond_t sup_resume[1]; + short sup_paused; /**< True if thread is paused */ +#endif + short sup_thread; /**< True if thread is active */ + short sup_mbox_index; + su_socket_t sup_mbox[SU_MBOX_SIZE]; +} su_pthread_port_t; + +/* Pthread methods */ + +SOFIAPUBFUN int su_pthread_port_init(su_port_t *, su_port_vtable_t const *); +SOFIAPUBFUN void su_pthread_port_deinit(su_port_t *self); + +SOFIAPUBFUN void su_pthread_port_lock(su_port_t *self, char const *who); +SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who); + +SOFIAPUBFUN int su_pthread_port_own_thread(su_port_t const *self); + +SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg); + +#if 0 /* not yet */ +SOFIAPUBFUN su_port_t *su_pthread_port_create(void); +SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit); +#endif + +SOFIAPUBFUN int su_pthreaded_port_start(su_port_create_f *create, + su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit); + +SOFIAPUBFUN void su_pthread_port_wait(su_clone_r rclone); +SOFIAPUBFUN int su_pthread_port_execute(su_task_r const task, + int (*function)(void *), void *arg, + int *return_value); + + +#if 0 +SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self); +SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self); +#endif + +#else + +typedef su_base_port_t su_pthread_port_t; + +#define su_pthread_port_init su_base_port_init +#define su_pthread_port_deinit su_base_port_deinit +#define su_pthread_port_lock su_base_port_lock +#define su_pthread_port_unlock su_base_port_unlock +#define su_pthread_port_own_thread su_base_port_own_thread +#define su_pthread_port_send su_base_port_send +#define su_pthread_port_wait su_base_port_wait +#define su_pthread_port_execute su_base_port_execute #endif diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c new file mode 100644 index 0000000000..1d7bb256e3 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c @@ -0,0 +1,691 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_pthread_port.c + * + * OS-Independent Syncronization Interface with pthreads + * + * This implements #su_msg_t message passing functionality using pthreads. + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#define su_pthread_port_s su_port_s +#define SU_CLONE_T su_msg_t + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +#if 1 +#define PORT_LOCK_DEBUG(x) ((void)0) +#else +#define PORT_LOCK_DEBUG(x) printf x +#endif + +#define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \ + (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0) + +#if HAVE_SOCKETPAIR +#define SU_MBOX_SEND 1 +#else +#define SU_MBOX_SEND 0 +#endif + +/** @internal Message box wakeup function. */ +static int su_mbox_port_wakeup(su_root_magic_t *magic, /* NULL */ + su_wait_t *w, + su_wakeup_arg_t *arg) +{ + char buf[32]; + su_socket_t socket = *(su_socket_t*)arg; + su_wait_events(w, socket); + recv(socket, buf, sizeof(buf), 0); + return 0; +} + +/**@internal + * + * Initializes a message port. It creates a mailbox used to wake up the + * thread waiting on the port if needed. Currently, the mailbox is a + * socketpair or an UDP socket connected to itself. + */ +int su_pthread_port_init(su_port_t *self, su_port_vtable_t const *vtable) +{ + SU_DEBUG_9(("su_pthread_port_init(%p, %p) called\n", + (void *)self, (void *)vtable)); + + if (su_base_port_init(self, vtable) == 0 && + su_base_port_threadsafe(self) == 0) { + int af; + su_socket_t mb = INVALID_SOCKET; + su_wait_t wait[1] = { SU_WAIT_INIT }; + char const *why; + + self->sup_tid = pthread_self(); + +#if 0 + pthread_mutex_init(self->sup_runlock, NULL); + pthread_mutex_lock(self->sup_runlock); + pthread_cond_init(self->sup_resume, NULL); +#endif + +#if HAVE_SOCKETPAIR +#if defined(AF_LOCAL) + af = AF_LOCAL; +#else + af = AF_UNIX; +#endif + if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) { + why = "socketpair"; goto error; + } + + mb = self->sup_mbox[0]; + su_setblocking(self->sup_mbox[1], 0); + +#else + { + struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 }; + socklen_t sinsize = sizeof sin; + struct sockaddr *sa = (struct sockaddr *)&sin; + + af = PF_INET; + + self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP); + if (mb == INVALID_SOCKET) { + why = "socket"; goto error; + } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */ + + /* Get a port for us */ + if (bind(mb, sa, sizeof sin) == -1) { + why = "bind"; goto error; + } + + if (getsockname(mb, sa, &sinsize) == -1) { + why = "getsockname"; goto error; + } + + if (connect(mb, sa, sinsize) == -1) { + why = "connect"; goto error; + } + } +#endif + + su_setblocking(mb, 0); + + if (su_wait_create(wait, mb, SU_WAIT_IN) == -1) { + why = "su_wait_create"; + goto error; + } + + self->sup_mbox_index = su_port_register(self, NULL, wait, + su_mbox_port_wakeup, + (void *)self->sup_mbox, 0); + + if (self->sup_mbox_index <= 0) { + why = "su_port_register"; + su_wait_destroy(wait); + goto error; + } + + SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", 0)); + + return 0; + + error: + su_log("%s: %s: %s\n", + "su_pthread_port_init", why, su_strerror(su_errno())); + su_pthread_port_deinit(self); + } + + SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", -1)); + + return -1; +} + + +/** @internal Deinit a base implementation of port. */ +void su_pthread_port_deinit(su_port_t *self) +{ + assert(self); + + if (self->sup_mbox_index > 0) + su_port_deregister(self, self->sup_mbox_index); + self->sup_mbox_index = 0; + + if (self->sup_mbox[0] && self->sup_mbox[0] != INVALID_SOCKET) + su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET; +#if HAVE_SOCKETPAIR + if (self->sup_mbox[1] && self->sup_mbox[1] != INVALID_SOCKET) + su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET; +#endif + +#if 0 + pthread_mutex_destroy(self->sup_runlock); + pthread_cond_destroy(self->sup_resume); +#endif + + su_base_port_deinit(self); +} + +void su_pthread_port_lock(su_port_t *self, char const *who) +{ + PORT_LOCK_DEBUG(("%p at %s locking(%p)...", + (void *)pthread_self(), who, self)); + + su_home_mutex_lock(self->sup_base->sup_home); + + PORT_LOCK_DEBUG((" ...%p at %s locked(%p)...", + (void *)pthread_self(), who, self)); +} + +void su_pthread_port_unlock(su_port_t *self, char const *who) +{ + su_home_mutex_unlock(self->sup_base->sup_home); + + PORT_LOCK_DEBUG((" ...%p at %s unlocked(%p)\n", + (void *)pthread_self(), who, self)); +} + +/** @internal Send a message to the port. */ +int su_pthread_port_send(su_port_t *self, su_msg_r rmsg) +{ + int wakeup = su_base_port_send(self, rmsg); + + if (wakeup < 0) + return -1; + if (wakeup == 0) + return 0; + + assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET); + + if (send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) { +#if HAVE_SOCKETPAIR + if (su_errno() != EWOULDBLOCK) +#endif + su_perror("su_msg_send: send()"); + } + return 0; +} + +/** @internal + * Checks if the calling thread owns the port object. + * + * @param self pointer to a port object + * + * @retval true (nonzero) if the calling thread owns the port, + * @retval false (zero) otherwise. + */ +int su_pthread_port_own_thread(su_port_t const *self) +{ + return self == NULL || + pthread_equal(self->sup_tid, pthread_self()); +} + +/* -- Clones ------------------------------------------------------------ */ + +struct clone_args +{ + su_port_create_f*create; + su_root_t *parent; + su_root_magic_t *magic; + su_root_init_f init; + su_root_deinit_f deinit; + pthread_mutex_t mutex[1]; + pthread_cond_t cv[1]; + int retval; + su_msg_r clone; +}; + +static void *su_pthread_port_clone_main(void *varg); +static void su_pthread_port_return_to_parent(struct clone_args *arg, + int retval); +static su_msg_function su_pthread_port_clone_break; + +/* Structure used to synchronize parent and clone in su_clone_wait() */ +struct su_pthread_port_waiting_parent { + pthread_mutex_t deinit[1]; + pthread_mutex_t mutex[1]; + pthread_cond_t cv[1]; + int waiting; +}; + +/** Start a clone task running under a pthread. + * + * @internal + * + * Allocates and initializes a sub-task with its own pthread. The sub-task is + * represented by clone handle to the rest of the application. The function + * su_clone_start() returns the clone handle in @a return_clone. The clone + * handle is used to communicate with the newly created clone task using + * messages. + * + * A new #su_root_t object is created for the sub-task with the @a magic as + * the root context pointer. Because the sub-task may or may not have its + * own thread, all its activity must be scheduled via this root object. In + * other words, the sub-task can be schedule + * -# I/O events with su_root_register() + * -# timers with su_timer_set(), su_timer_set_at() or su_timer_run() + * -# messages with su_msg_send(). + * + * Messages can also be used to pass information between tasks or threads. + * + * After the new thread has been launched, the initialization routine is + * executed by the newly created thread. The calling thread blocks until + * the initialization routine completes. If the initialization routine + * returns #su_success (0), the sub-task is considered to be created + * successfully. After the successful initialization, the sub-task continues + * to execeute the function su_root_run(). + * + * If the initalization function @a init fails, the sub-task (either the + * newly created thread or the current thread executing the su_clone_start() + * function) calls the deinitialization function, and su_clone_start() + * returns NULL. + * + * @param parent root to be cloned (may be NULL if multi-threaded) + * @param return_clone reference to a clone [OUT] + * @param magic pointer to user data + * @param init initialization function + * @param deinit deinitialization function + * + * @return 0 if successfull, -1 upon an error. + * + * @sa su_root_threading(), su_clone_task(), su_clone_stop(), su_clone_wait(), + * su_clone_forget(). + * + */ +int su_pthreaded_port_start(su_port_create_f *create, + su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + struct clone_args arg = { + /* create: */ NULL, + /* parent: */ NULL, + /* magic: */ NULL, + /* init: */ NULL, + /* deinit: */ NULL, + /* mutex: */ { PTHREAD_MUTEX_INITIALIZER }, + /* cv: */ { PTHREAD_COND_INITIALIZER }, + /* retval: */ -1, + /* clone: */ SU_MSG_R_INIT, + }; + + int thread_created = 0; + pthread_t tid; + + arg.create = create; + arg.parent = parent; + arg.magic = magic; + arg.init = init; + arg.deinit = deinit; + + pthread_mutex_lock(arg.mutex); + if (pthread_create(&tid, NULL, su_pthread_port_clone_main, &arg) == 0) { + pthread_cond_wait(arg.cv, arg.mutex); + thread_created = 1; + } + pthread_mutex_unlock(arg.mutex); + + pthread_mutex_destroy(arg.mutex); + pthread_cond_destroy(arg.cv); + + if (arg.retval != 0) { + if (thread_created) + pthread_join(tid, NULL); + return -1; + } + + *return_clone = *arg.clone; + + return 0; +} + +/** Main function for clone thread. + * + * @internal + */ +static void *su_pthread_port_clone_main(void *varg) +{ + struct clone_args *arg = (struct clone_args *)varg; + su_task_r task; + int zap = 1; + +#if SU_HAVE_WINSOCK + su_init(); +#endif + + task->sut_port = arg->create(); + + if (task->sut_port) { + task->sut_port->sup_thread = 1; + + task->sut_root = su_salloc(su_port_home(task->sut_port), + sizeof *task->sut_root); + if (task->sut_root) { + + task->sut_root->sur_threading = 1; /* By default */ + + SU_TASK_COPY(task->sut_root->sur_parent, su_root_task(arg->parent), + su_pthread_port_clone_main); + SU_TASK_COPY(task->sut_root->sur_task, task, + su_pthread_port_clone_main); + + if (su_msg_create(arg->clone, + task, + su_root_task(arg->parent), + su_pthread_port_clone_break, + 0) == 0) { + task->sut_root->sur_magic = arg->magic; + task->sut_root->sur_deinit = arg->deinit; + + if (arg->init(task->sut_root, arg->magic) == 0) { + su_pthread_port_return_to_parent(arg, 0), arg = NULL; + + su_root_run(task->sut_root); /* Do the work */ + + /* Cleanup */ + if (task->sut_port->sup_waiting_parent) { + struct su_pthread_port_waiting_parent *mom; + + mom = task->sut_port->sup_waiting_parent; + pthread_mutex_lock(mom->mutex); + mom->waiting = 0; + pthread_cond_signal(mom->cv); + pthread_mutex_unlock(mom->mutex); + + pthread_mutex_lock(mom->deinit); + su_port_getmsgs(task->sut_port); + pthread_mutex_unlock(mom->deinit); + } + else + zap = 0; + } + else + su_msg_destroy(arg->clone); + + su_root_destroy(task->sut_root); + } + } + + task->sut_port->sup_thread = 0; + + task->sut_port->sup_base->sup_vtable-> + su_port_decref(task->sut_port, zap, + "su_pthread_port_clone_main"); + } + +#if SU_HAVE_WINSOCK + su_deinit(); +#endif + + if (arg) + su_pthread_port_return_to_parent(arg, -1); + + return NULL; /* Exit from thread */ +} + +/* Signal that parent can resume execution */ +static void su_pthread_port_return_to_parent(struct clone_args *arg, + int retval) +{ + arg->retval = retval; + + pthread_mutex_lock(arg->mutex); + pthread_cond_signal(arg->cv); + pthread_mutex_unlock(arg->mutex); +} + +/** "Stop" message function for pthread clone. + * + * @sa su_clone_wait() + * @internal + */ +static void su_pthread_port_clone_break(su_root_magic_t *m, + su_msg_r msg, + su_msg_arg_t *a) +{ + su_root_t *root = su_msg_to(msg)->sut_root; + + root->sur_deiniting = 1; + + su_root_break(root); +} + +/** Wait for the pthread clone to exit. + * @internal + */ +void su_pthread_port_wait(su_clone_r rclone) +{ + su_port_t *clone, *parent; + struct su_pthread_port_waiting_parent mom[1]; + pthread_t tid; + + clone = su_msg_to(rclone)->sut_port; + parent = su_msg_from(rclone)->sut_port; + + if (clone == parent) { + su_base_port_wait(rclone); + return; + } + + assert(parent); assert(clone); + assert(rclone[0]->sum_func == su_pthread_port_clone_break); +#if 0 + assert(!clone->sup_paused); +#endif + + tid = clone->sup_tid; + + if (!clone->sup_thread) { /* Already died */ + su_msg_destroy(rclone); + pthread_join(tid, NULL); + return; + } + + pthread_mutex_init(mom->deinit, NULL); + pthread_mutex_lock(mom->deinit); + + pthread_cond_init(mom->cv, NULL); + pthread_mutex_init(mom->mutex, NULL); + pthread_mutex_lock(mom->mutex); + + mom->waiting = 1; + + clone->sup_waiting_parent = mom; + + su_msg_send(rclone); + + while (mom->waiting) + pthread_cond_wait(mom->cv, mom->mutex); + + /* Run all messages from clone */ + while (su_port_getmsgs_from(parent, clone)) + ; + + /* Allow clone thread to exit */ + pthread_mutex_unlock(mom->deinit); + pthread_join(tid, NULL); + + pthread_mutex_destroy(mom->deinit); + + pthread_mutex_unlock(mom->mutex); + pthread_mutex_destroy(mom->mutex); +} + +struct su_pthread_port_execute +{ + pthread_mutex_t mutex[1]; + pthread_cond_t cond[1]; + int (*function)(void *); + void *arg; + int value; +}; + +static su_msg_function _su_pthread_port_execute; + +/** Execute the @a function by a pthread @a task. + * + * @retval 0 if successful + * @retval -1 upon an error + * + * @sa su_task_execute() + * + * @internal + */ +int su_pthread_port_execute(su_task_r const task, + int (*function)(void *), void *arg, + int *return_value) +{ + int success; + su_msg_r m = SU_MSG_R_INIT; + struct su_pthread_port_execute frame = { + { PTHREAD_MUTEX_INITIALIZER }, + { PTHREAD_COND_INITIALIZER }, + function, arg, 0 + }; + + if (su_msg_create(m, task, su_task_null, + _su_pthread_port_execute, (sizeof &frame)) < 0) + return -1; + + *(struct su_pthread_port_execute **)su_msg_data(m) = &frame; + + pthread_mutex_lock(frame.mutex); + + success = su_msg_send(m); + + if (success == 0) + while (frame.function) + pthread_cond_wait(frame.cond, frame.mutex); + else + su_msg_destroy(m); + + pthread_mutex_unlock(frame.mutex); + pthread_mutex_destroy(frame.mutex); + pthread_cond_destroy(frame.cond); + + if (return_value) + *return_value = frame.value; + + return success; +} + +static void _su_pthread_port_execute(su_root_magic_t *m, + su_msg_r msg, + su_msg_arg_t *a) +{ + struct su_pthread_port_execute *frame; + frame = *(struct su_pthread_port_execute **)a; + pthread_mutex_lock(frame->mutex); + frame->value = frame->function(frame->arg); + frame->function = NULL; /* Mark as completed */ + pthread_cond_signal(frame->cond); + pthread_mutex_unlock(frame->mutex); +} + +#if 0 /* pausing and resuming are not used */ + +/** Pause the pthread port. + * + * This is a message function invoked by su_pthread_port_pause() and called + * from the message dispatcher. It releases the lock sup_runlock and waits + * until the condition variable sup_resume is signaled and sup_paused is + * cleared by su_pthread_port_resume(). + */ +static +void su_pthread_port_paused(su_root_magic_t *magic, + su_msg_r msg, + su_msg_arg_t *arg) +{ + su_port_t *self = su_msg_to(msg)->sut_port; + self->sup_paused = 1; + while (self->sup_paused) + pthread_cond_wait(self->sup_resume, self->sup_runlock); +} + +/** Pause a port. + * + * Obtain an exclusive lock on port's private data. + * + * @retval 0 if successful (and clone is paused) + * @retval -1 upon an error + */ +int su_pthread_port_pause(su_port_t *self) +{ + su_msg_r m = SU_MSG_R_INIT; + _su_task_t task[1] = {{ self, NULL }}; + + if (su_msg_create(m, task, su_task_null, su_pthread_port_paused, 0) < 0) + return -1; + + if (su_msg_send(m) < 0) + return -1; + + if (pthread_mutex_lock(self->sup_runlock) < 0) + return -1; + + return 0; +} + +/** Resume a port. + * + * Give up an exclusive lock on port's private data. + * + * @retval 0 if successful (and clone is resumed) + * @retval -1 upon an error + */ +int su_pthread_port_resume(su_port_t *self) +{ + assert(self && self->sup_paused); + + self->sup_paused = 0; + + if (pthread_cond_signal(self->sup_resume) < 0 || + pthread_mutex_unlock(self->sup_runlock) < 0) + return -1; + + return 0; +} + +#endif diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_root.c b/libs/sofia-sip/libsofia-sip-ua/su/su_root.c index 553bb71a46..1af8ac7168 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_root.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_root.c @@ -48,22 +48,9 @@ struct su_root_s; -typedef struct su_cloned_s { - struct su_root_s *sc_root; - int *sc_wait; -#if SU_HAVE_PTHREADS - pthread_t sc_tid; - pthread_mutex_t sc_pause[1]; - pthread_cond_t sc_resume[1]; - int sc_paused; -#endif -} su_cloned_t; - #define SU_ROOT_MAGIC_T struct su_root_magic_s #define SU_WAKEUP_ARG_T struct su_wakeup_arg_s #define SU_TIMER_ARG_T struct su_timer_arg_s -#define SU_CLONE_T su_msg_t -#define SU_MSG_ARG_T struct su_cloned_s #include "su_port.h" #include "sofia-sip/su_alloc.h" @@ -136,11 +123,11 @@ su_task_r const su_task_null = SU_TASK_R_INIT; #define SU_TASK_ZAP(t, f) \ while (t->sut_port) { \ - SU_PORT_DECREF(t->sut_port, f); t->sut_port = NULL; break; } + su_port_decref(t->sut_port, #f); t->sut_port = NULL; break; } #define SU_TASK_ZAPP(t, f) \ do { if (t->sut_port) { \ - SU_PORT_DECREF(t->sut_port, f); t->sut_port = NULL; } \ + su_port_decref(t->sut_port, #f); t->sut_port = NULL; } \ t->sut_root = NULL; } while(0) /** @@ -186,7 +173,7 @@ _su_task_r su_task_new(su_task_r task, su_root_t *root, su_port_t *port) task->sut_root = root; if ((task->sut_port = port)) { - SU_PORT_INCREF(port, su_task_new); + su_port_incref(port, "su_task_new"); } return task; } @@ -207,14 +194,14 @@ void su_task_copy(su_task_r dst, su_task_r const src) port = src->sut_port; if (port) { - SU_PORT_INCREF(port, su_task_copy); + su_port_incref(port, "su_task_copy"); } dst[0] = src[0]; } #define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \ - (s)->sut_port?(void)SU_PORT_INCREF(s->sut_port, by):(void)0) + (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0) /** * Moves a task handle. @@ -242,8 +229,10 @@ void su_task_move(su_task_r dst, su_task_r src) */ int su_task_cmp(su_task_r const a, su_task_r const b) { - intptr_t retval = a->sut_port - b->sut_port; - retval = retval ? retval : (char *)a->sut_root - (char *)b->sut_root; + intptr_t retval = (char *)a->sut_port - (char *)b->sut_port; + + if (retval == 0) + retval = (char *)a->sut_root - (char *)b->sut_root; if (sizeof(retval) != sizeof(int)) { if (retval < 0) @@ -329,32 +318,7 @@ su_timer_t **su_task_timers(su_task_r const task) return task ? su_port_timers(task->sut_port) : NULL; } -#if SU_HAVE_PTHREADS - -struct su_task_execute -{ - pthread_mutex_t mutex[1]; - pthread_cond_t cond[1]; - int (*function)(void *); - void *arg; - int value; -}; - -static void _su_task_execute(su_root_magic_t *m, - su_msg_r msg, - su_msg_arg_t *a) -{ - struct su_task_execute *frame = *(struct su_task_execute **)a; - pthread_mutex_lock(frame->mutex); - frame->value = frame->function(frame->arg); - frame->function = NULL; /* Mark as completed */ - pthread_cond_signal(frame->cond); - pthread_mutex_unlock(frame->mutex); -} - -#endif - -/** Execute by task thread +/** Execute the @a function by @a task thread. * * @retval 0 if successful * @retval -1 upon an error @@ -367,42 +331,7 @@ int su_task_execute(su_task_r const task, return (errno = EFAULT), -1; if (!su_port_own_thread(task->sut_port)) { -#if SU_HAVE_PTHREADS - int success; - su_msg_r m = SU_MSG_R_INIT; - struct su_task_execute frame = { - { PTHREAD_MUTEX_INITIALIZER }, - { PTHREAD_COND_INITIALIZER }, - function, arg, 0 - }; - - if (su_msg_create(m, task, su_task_null, - _su_task_execute, (sizeof &frame)) < 0) - return -1; - - *(struct su_task_execute **)su_msg_data(m) = &frame; - - pthread_mutex_lock(frame.mutex); - - success = su_msg_send(m); - - if (success == 0) - while (frame.function) - pthread_cond_wait(frame.cond, frame.mutex); - else - su_msg_destroy(m); - - pthread_mutex_unlock(frame.mutex); - pthread_mutex_destroy(frame.mutex); - pthread_cond_destroy(frame.cond); - - if (return_value) - *return_value = frame.value; - - return success; -#else - return (errno = ENOSYS), -1; -#endif + return su_port_execute(task, function, arg, return_value); } else { int value = function(arg); @@ -420,51 +349,6 @@ int su_task_detach(su_task_r self); int su_timer_reset_all(su_timer_t **t0, su_task_r); -/**@ingroup su_wait - * - * @page su_clone_t Clone Objects - * - * The process may be divided into many tasks via cloning. Several tasks may - * run in context of one thread, or each task may be run by its own thread. - * However, only a single thread can execute code within a task. There can - * be a 1-to-N mapping from thread to tasks. Thus, software using tasks can - * be executed by multiple threads in a multithreaded environment and by a - * single thread in a singlethreaded environment. - * - * The clones are useful for handling tasks that can be executed by a - * separate threads, but which do not block excessively. When threads are - * not available or they are not needed, clones can also be run in a - * single-threaded mode. Running in single-threaded mode is especially - * useful while debugging. - * - * A clone task is created with function su_clone_start(). Each clone has - * its own root object (su_root_t), which holds a context pointer - * (su_root_magic_t *). The context object can be different from that of - * parent task. - * - * When a clone is started, the clone initialization function is called. The - * initialization function should do whatever initialization there is to be - * performed, register I/O events and timers, and then return. If the - * initialization is successful, the clone task reverts to run the event - * loop and invoking the event callbacks until its parent stops it by - * calling su_clone_wait() which invokes the deinit function. The clone task - * is destroyed when the deinit function returns. - * - * The public API consists of following functions: - * - su_clone_start() - * - su_clone_task() - * - su_clone_wait() - * - su_clone_forget() - * - * @note - * There is only one event loop for each thread which can be shared by - * multiple clone tasks. Therefore, the clone tasks can not explicitly run - * or step the event loop, but they are limited to event callbacks. A clone - * task may not call su_root_break(), su_root_run() or su_root_step(). - */ - -static void su_root_deinit(su_root_t *self); - /* Note that is *not* necessary same as su_root_t, * as su_root_t can be extended */ @@ -486,9 +370,13 @@ su_root_t *su_root_create(su_root_magic_t *magic) return su_root_create_with_port(magic, su_port_create()); } -/** Create a reactor object using given message port. +/**@internal * - * Allocate and initialize the instance of su_root_t. + * Create a reactor object using given message port. + * + * Allocate and initialize the instance of su_root_t. Note that this + * function always uses a reference to su_port_t, even when creating the + * root fails. * * @param magic pointer to user data * @param port pointer to a message port @@ -503,7 +391,7 @@ su_root_t *su_root_create_with_port(su_root_magic_t *magic, if (!port) return NULL; - self = su_salloc(NULL, sizeof(struct su_root_s)); + self = su_salloc(su_port_home(port), sizeof(struct su_root_s)); if (self) { self->sur_magic = magic; @@ -512,15 +400,17 @@ su_root_t *su_root_create_with_port(su_root_magic_t *magic, #else self->sur_threading = 0; #endif + /* This one creates a new reference to port */ su_task_new(self->sur_task, self, port); - } else { - su_port_decref(port, "su_root_create"); - } + /* ... so we zap the old one below */ + } + + su_port_decref(port, "su_root_create_with_port"); return self; } -/** Destroy a synchronization object. +/** Destroy a root object. * * Stop and free an instance of su_root_t * @@ -528,21 +418,14 @@ su_root_t *su_root_create_with_port(su_root_magic_t *magic, */ void su_root_destroy(su_root_t *self) { - if (self) { - assert(SU_ROOT_OWN_THREAD(self)); - su_root_deinit(self); - su_free(NULL, self); - } -} + su_port_t *port; + int unregistered, reset; + + if (!self) + return; + + assert(SU_ROOT_OWN_THREAD(self)); -/** @internal Deinitialize a synchronization object. - * - * Deinitialize an instance of su_root_t - * - * @param self pointer to a root object. - */ -static void su_root_deinit(su_root_t *self) -{ self->sur_deiniting = 1; if (self->sur_deinit) { @@ -552,17 +435,21 @@ static void su_root_deinit(su_root_t *self) deinit(self, magic); } - if (self->sur_port) { - int n_w = su_port_unregister_all(self->sur_port, self); - int n_t = su_timer_reset_all(su_task_timers(self->sur_task), self->sur_task); + port = self->sur_port; assert(port); - if (n_w || n_t) - SU_DEBUG_1(("su_root_deinit: " - "%u registered waits, %u timers\n", n_w, n_t)); - } + unregistered = su_port_unregister_all(port, self); + reset = su_timer_reset_all(su_task_timers(self->sur_task), self->sur_task); - SU_TASK_ZAP(self->sur_parent, su_root_deinit); - SU_TASK_ZAP(self->sur_task, su_root_deinit); + if (unregistered || reset) + SU_DEBUG_1(("su_root_destroy: " + "%u registered waits, %u timers\n", + unregistered, reset)); + + SU_TASK_ZAP(self->sur_parent, su_root_destroy); + + su_free(su_port_home(port), self); + + su_port_decref(port, "su_root_destroy"); } /** Set the context pointer. @@ -760,7 +647,6 @@ int su_root_multishot(su_root_t *self, int multishot) } } - /** Run event and message loop. * * The function su_root_run() runs the root main loop. The root loop waits @@ -852,12 +738,20 @@ su_duration_t su_root_sleep(su_root_t *self, su_duration_t duration) int su_root_yield(su_root_t *self) { if (self && self->sur_task[0].sut_port) { - su_port_t *port = self->sur_task[0].sut_port; + su_virtual_port_t *port = (su_virtual_port_t *)self->sur_task[0].sut_port; + /* Make sure we have su_port_wait_events extension */ + if (port->sup_vtable->su_vtable_size >= + offsetof(su_port_vtable_t, su_port_wait_events) + && port->sup_vtable->su_port_wait_events) + return port->sup_vtable-> + su_port_wait_events(self->sur_task[0].sut_port, 0); + /* Make sure we have su_port_yield extension */ if (port->sup_vtable->su_vtable_size >= offsetof(su_port_vtable_t, su_port_yield) && port->sup_vtable->su_port_yield) - return port->sup_vtable->su_port_yield(port); + return port->sup_vtable-> + su_port_yield(self->sur_task[0].sut_port); } errno = EINVAL; return -1; @@ -919,467 +813,6 @@ int su_root_remove_prepoll(su_root_t *root) return su_port_remove_prepoll(root->sur_port, root); } -/* ======================================================================== - * su_clone_t - */ - -/* - su_clone_forget() */ - -#if SU_HAVE_PTHREADS -struct clone_args -{ - su_root_t * self; - su_root_init_f init; - su_root_deinit_f deinit; - pthread_mutex_t mutex; - pthread_cond_t cv; - int retval; - su_msg_r clone; - su_root_t const *parent; -}; - -static void su_clone_report2(su_root_magic_t *m, - su_msg_r msg, - su_cloned_t *sc); - -static void su_clone_signal_parent(void *varg) -{ - struct clone_args *arg = (struct clone_args *)varg; - - pthread_mutex_lock(&arg->mutex); - pthread_cond_signal(&arg->cv); - pthread_mutex_unlock(&arg->mutex); -} - -/** Message function for clone message. - * - * This calls the clone task deinitialization function, which should make - * sure that no more messages are sent by clone task. - * - * @sa su_clone_wait() - */ -static void su_clone_break(su_root_magic_t *m, - su_msg_r msg, - su_cloned_t *sc) -{ - su_root_t *root = sc->sc_root; - - root->sur_deiniting = 1; - - if (root->sur_deinit) { - su_root_deinit_f deinit = root->sur_deinit; - su_root_magic_t *magic = root->sur_magic; - root->sur_deinit = NULL; - deinit(root, magic); - } -} - -/** Delivery report function for clone message. - * - * This is executed by parent task. This is the last message sent by clone task. - */ -static void su_clone_report(su_root_magic_t *m, - su_msg_r msg, - su_cloned_t *sc) -{ - su_msg_report(msg, su_clone_report2); -} - -/** Back delivery report function for clone message. - * - * This is executed by clone task. It completes the three way handshake and - * it is used to signal clone that it can destroy its port. - */ -static void su_clone_report2(su_root_magic_t *m, - su_msg_r msg, - su_cloned_t *sc) -{ - su_root_break(sc->sc_root); - if (sc->sc_wait) - *sc->sc_wait = 0; -} - -static void *su_clone_main(void *varg) -{ - struct clone_args *arg = (struct clone_args *)varg; - su_root_t *self = arg->self; - su_port_t *port; - su_cloned_t *sc; - - pthread_cleanup_push(su_clone_signal_parent, varg); - -#if SU_HAVE_WINSOCK - su_init(); -#endif - - port = su_port_create(); - if (!port) - pthread_exit(NULL); - su_port_threadsafe(port); - SU_PORT_INCREF(port, su_clone_main); - - /* Change task ownership */ - SU_PORT_INCREF(self->sur_task->sut_port = port, su_clone_main); - self->sur_task->sut_root = self; - - if (su_msg_create(arg->clone, - self->sur_task, su_root_task(arg->parent), - su_clone_break, sizeof(self)) != 0) { - su_port_decref(self->sur_port, "su_clone_main"); - self->sur_port = NULL; - pthread_exit(NULL); - } - - su_msg_report(arg->clone, su_clone_report); - - sc = su_msg_data(arg->clone); - sc->sc_root = self; - sc->sc_tid = pthread_self(); - - pthread_mutex_init(sc->sc_pause, NULL); - pthread_cond_init(sc->sc_resume, NULL); - pthread_mutex_lock(sc->sc_pause); - - if (arg->init && arg->init(self, self->sur_magic) != 0) { - if (arg->deinit) - arg->deinit(self, self->sur_magic); - su_msg_destroy(arg->clone); - su_port_decref(self->sur_port, "su_clone_main"); - self->sur_port = NULL; - pthread_exit(NULL); - } - - arg->retval = 0; - - pthread_cleanup_pop(1); /* signal change of ownership */ - - su_root_run(self); /* Do the work */ - - su_root_destroy(self); /* Cleanup root */ - - SU_PORT_ZAPREF(port, su_clone_main); - -#if SU_HAVE_WINSOCK - su_deinit(); -#endif - - return NULL; -} -#endif - -static void su_clone_xyzzy(su_root_magic_t *m, - su_msg_r msg, - su_cloned_t *sc) -{ - su_root_destroy(sc->sc_root); - if (sc->sc_wait) - *sc->sc_wait = 0; -} - -/** Start a clone task. - * - * The function su_clone_start() allocates and initializes a sub-task. - * Depending on the settings, a separate thread may be created to execute - * the sub-task. The sub-task is represented by clone handle to the rest of - * the application. The function su_clone_start() returns the clone handle - * in @a return_clone. The clone handle is used to communicate with the - * newly created clone task using messages. - * - * A new #su_root_t object is created for the sub-task with the @a magic as - * the root context pointer. Because the sub-task may or may not have its - * own thread, all its activity must be scheduled via this root object. In - * other words, the sub-task can be schedule - * -# I/O events with su_root_register() - * -# timers with su_timer_set(), su_timer_set_at() or su_timer_run() - * -# messages with su_msg_send(). - * - * Messages can also be used to pass information between tasks or threads. - * - * In multi-threaded implementation, su_clone_start() launches a new thread, - * and the initialization routine is executed by this newly created thread. - * The calling thread blocks until the initialization routine completes. If - * the initialization routine returns #su_success (0), the sub-task is - * considered to be created successfully. After the successful - * initialization, the sub-task continues to execeute the function - * su_root_run(). - * - * In single-threaded implementations, just a new root object is created. - * The initialization routine is called directly from su_clone_start(). - * - * If the initalization function @a init fails, the sub-task (either the - * newly created thread or the current thread executing the su_clone_start() - * function) calls the deinitialization function, and su_clone_start() - * returns NULL. - * - * @param parent root to be cloned (may be NULL if multi-threaded) - * @param return_clone reference to a clone [OUT] - * @param magic pointer to user data - * @param init initialization function - * @param deinit deinitialization function - * - * @return 0 if successfull, -1 upon an error. - * - * @sa su_root_threading(), su_clone_task(), su_clone_stop(), su_clone_wait(), - * su_clone_forget(). - */ -int su_clone_start(su_root_t *parent, - su_clone_r return_clone, - su_root_magic_t *magic, - su_root_init_f init, - su_root_deinit_f deinit) -{ - su_root_t *child; - int retval = -1; - - if (parent) { - assert(SU_ROOT_OWN_THREAD(parent)); - assert(parent->sur_port); - } -#if !SU_HAVE_PTHREADS - else { - /* if we don't have threads, we *must* have parent root */ - return -1; - } -#endif - - child = su_salloc(NULL, sizeof(struct su_root_s)); - -#if SU_HAVE_PTHREADS - if (child && (parent == NULL || parent->sur_threading)) { - struct clone_args arg = { - NULL, NULL, NULL, - PTHREAD_MUTEX_INITIALIZER, - PTHREAD_COND_INITIALIZER, - -1, - SU_MSG_R_INIT, - NULL - }; - - int thread_created = 0; - pthread_t tid; - - su_port_threadsafe(parent->sur_port); - - arg.self = child; - arg.init = init; - arg.deinit = deinit; - arg.parent = parent; - - child->sur_magic = magic; - child->sur_deinit = deinit; - child->sur_threading = parent->sur_threading; - - SU_TASK_COPY(child->sur_parent, su_root_task(parent), su_clone_start); - - pthread_mutex_lock(&arg.mutex); - if (pthread_create(&tid, NULL, su_clone_main, &arg) == 0) { - pthread_cond_wait(&arg.cv, &arg.mutex); - thread_created = 1; - } - pthread_mutex_unlock(&arg.mutex); - - if (arg.retval != 0) { - if (thread_created) - pthread_join(tid, NULL); - su_root_destroy(child), child = NULL; - } - else { - retval = 0; - *return_clone = *arg.clone; - } - } else -#endif - if (child) { - assert(parent); - - child->sur_magic = magic; - child->sur_deinit = deinit; - child->sur_threading = parent->sur_threading; - - SU_TASK_COPY(child->sur_parent, su_root_task(parent), su_clone_start); - SU_TASK_COPY(child->sur_task, child->sur_parent, su_clone_start); - su_task_attach(child->sur_task, child); - - if (su_msg_create(return_clone, - child->sur_task, su_root_task(parent), - su_clone_xyzzy, sizeof(child)) == 0) { - if (init == NULL || init(child, magic) == 0) { - su_cloned_t *sc = su_msg_data(return_clone); - sc->sc_root = child; -#if SU_HAVE_PTHREADS - sc->sc_tid = pthread_self(); - pthread_mutex_init(sc->sc_pause, NULL); - pthread_cond_init(sc->sc_resume, NULL); - pthread_mutex_lock(sc->sc_pause); -#endif - retval = 0; - } else { - if (deinit) - deinit(child, magic); - su_msg_destroy(return_clone); - su_root_destroy(child), child = NULL; - } - } - else { - su_root_destroy(child), child = NULL; - } - } - - return retval; -} - -/** Get reference to clone task. - * - * @param clone Clone pointer - * - * @return A reference to the task structure of the clone. - */ -_su_task_r su_clone_task(su_clone_r clone) -{ - return su_msg_to(clone); -} - -/**Forget the clone. - * - * Normally, the clone task executes until it is stopped. If the parent - * task does not need to stop the task, it can "forget" the clone. The - * clone exits independently of the parent task. - * - * @param rclone Reference to the clone. - */ -void su_clone_forget(su_clone_r rclone) -{ - su_msg_destroy(rclone); -} - -/** Stop the clone. - * - * @deprecated. Use su_clone_wait(). - */ -void su_clone_stop(su_clone_r rclone) -{ - su_msg_send(rclone); -} - -/** Stop a clone and wait until it is has completed. - * - * The function su_clone_wait() is used to stop the clone task and wait - * until it has cleaned up. The clone task is destroyed asynchronously. The - * parent sends a message to clone, clone deinitializes itself and then - * replies. After the reply message is received by the parent, it will send - * a third message back to clone. - * - * The parent destroy all messages to or from clone task before calling - * su_clone_wait(). The parent task may not send any messages to the clone - * after calling su_clone_wait(). The su_clone_wait() function blocks until - * the cloned task is destroyed. During that time, the parent task must be - * prepared to process all the messages sent by clone task. This includes - * all the messages sent by clone before destroy message reached the clone. - */ -void su_clone_wait(su_root_t *root, su_clone_r rclone) -{ - su_cloned_t *sc = su_msg_data(rclone); - - if (sc) { -#if SU_HAVE_PTHREADS - pthread_t clone_tid = sc->sc_tid; -#endif - int one = 1; - /* This does 3-way handshake. - * First, su_clone_break() is executed by clone. - * The message is returned to parent (this task), - * which executes su_clone_report(). - * Then the message is again returned to clone, - * which executes su_clone_report2() and exits. - */ - sc->sc_wait = &one; - su_msg_send(rclone); - - su_root_step(root, 0); - su_root_step(root, 0); - - while (one) - su_root_step(root, 10); - -#if SU_HAVE_PTHREADS - if (!pthread_equal(clone_tid, pthread_self())) - pthread_join(clone_tid, NULL); -#endif - } -} - -#if SU_HAVE_PTHREADS /* No-op without threads */ -static -void su_clone_paused(su_root_magic_t *magic, su_msg_r msg, su_msg_arg_t *arg) -{ - su_cloned_t *cloned = *(su_cloned_t **)arg; - assert(cloned); - pthread_cond_wait(cloned->sc_resume, cloned->sc_pause); -} -#endif - -/** Pause a clone. - * - * Obtain a exclusive lock on clone's private data. - * - * @retval 0 if successful (and clone is paused) - * @retval -1 upon an error - */ -int su_clone_pause(su_clone_r rclone) -{ -#if SU_HAVE_PTHREADS /* No-op without threads */ - su_cloned_t *cloned = su_msg_data(rclone); - su_msg_r m = SU_MSG_R_INIT; - - if (!cloned) - return (errno = EFAULT), -1; - - if (pthread_equal(pthread_self(), cloned->sc_tid)) - return 0; - - if (su_msg_create(m, su_clone_task(rclone), su_task_null, - su_clone_paused, sizeof cloned) < 0) - return -1; - - *(su_cloned_t **)su_msg_data(m) = cloned; - - if (su_msg_send(m) < 0) - return -1; - - if (pthread_mutex_lock(cloned->sc_pause) < 0) - return -1; - pthread_cond_signal(cloned->sc_resume); -#endif - - return 0; -} - -/** Resume a clone. - * - * Give up a exclusive lock on clone's private data. - * - * @retval 0 if successful (and clone is resumed) - * @retval -1 upon an error - */ -int su_clone_resume(su_clone_r rclone) -{ -#if SU_HAVE_PTHREADS /* No-op without threads */ - su_cloned_t *cloned = su_msg_data(rclone); - - if (!cloned) - return (errno = EFAULT), -1; - - if (pthread_equal(pthread_self(), cloned->sc_tid)) - return 0; - - if (pthread_mutex_unlock(cloned->sc_pause) < 0) - return -1; -#endif - - return 0; -} - - /* ========================================================================= * Messages */ @@ -1405,12 +838,9 @@ int su_msg_create(su_msg_r rmsg, su_msg_f wakeup, isize_t size) { - su_port_t *port = to->sut_port; su_msg_t *msg; - SU_PORT_LOCK(port, su_msg_create); - msg = su_zalloc(NULL /*port->sup_home*/, sizeof(*msg) + size); - SU_PORT_UNLOCK(port, su_msg_create); + msg = su_zalloc(NULL, sizeof(*msg) + size); if (msg) { msg->sum_size = sizeof(*msg) + size; @@ -1522,14 +952,14 @@ void su_msg_destroy(su_msg_r rmsg) if (rmsg[0]) { /* su_port_t *port = rmsg[0]->sum_to->sut_port; */ - /* SU_PORT_INCREF(port, su_msg_destroy); */ + /* su_port_incref(port, "su_msg_destroy"); */ SU_TASK_ZAP(rmsg[0]->sum_to, su_msg_destroy); SU_TASK_ZAP(rmsg[0]->sum_from, su_msg_destroy); su_free(NULL /* port->sup_home */, rmsg[0]); /* SU_PORT_UNLOCK(port, su_msg_destroy); */ - /* SU_PORT_DECREF(port, su_msg_destroy); */ + /* su_port_decref(port, "su_msg_destroy"); */ } rmsg[0] = NULL; diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c new file mode 100644 index 0000000000..2b7483544e --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_select_port.c @@ -0,0 +1,667 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_select_port.c + * + * Port implementation using select(). NOT IMPLEMENTED YET! + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#if HAVE_SELECT + +#define su_port_s su_select_port_s + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_SYS_SELECT_H +#include +#elif HAVE_SYS_TIME_H +#include +#endif + +/** Port based on select(). */ + +struct su_select_port_s { + su_pthread_port_t sup_base[1]; + + unsigned sup_multishot; /**< Multishot operation? */ + + unsigned sup_registers; /** Counter incremented by + su_port_register() or + su_port_unregister() + */ + + int sup_n_waits; /**< Active su_wait_t in su_waits */ + int sup_size_waits; /**< Size of allocated su_waits */ + int sup_pri_offset; /**< Offset to prioritized waits */ + + /** Indices from index returned by su_root_register() to tables below. + * + * Free elements are negative. Free elements form a list, value of free + * element is (0 - index of next free element). + * + * First element sup_indices[0] points to first free element. + */ + int *sup_indices; + + int *sup_reverses; /** Reverse index */ + su_wakeup_f *sup_wait_cbs; + su_wakeup_arg_t**sup_wait_args; + su_root_t **sup_wait_roots; + su_wait_t *sup_waits; +}; + +static void su_select_port_decref(su_port_t *, int blocking, char const *who); + +static int su_select_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority); +static int su_select_port_unregister(su_port_t *port, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg); +static int su_select_port_deregister(su_port_t *self, int i); +static int su_select_port_unregister_all(su_port_t *self, su_root_t *root); +static int su_select_port_eventmask(su_port_t *self, + int index, + int socket, + int events); +static int su_select_port_multishot(su_port_t *self, int multishot); +static int su_select_port_wait_events(su_port_t *self, su_duration_t tout); +static char const *su_select_port_name(su_port_t const *self); + +su_port_vtable_t const su_select_port_vtable[1] = + {{ + /* su_vtable_size: */ sizeof su_select_port_vtable, + su_pthread_port_lock, + su_pthread_port_unlock, + su_base_port_incref, + su_select_port_decref, + su_base_port_gsource, + su_pthread_port_send, + su_select_port_register, + su_select_port_unregister, + su_select_port_deregister, + su_select_port_unregister_all, + su_select_port_eventmask, + su_base_port_run, + su_base_port_break, + su_base_port_step, + su_pthread_port_own_thread, + su_base_port_add_prepoll, + su_base_port_remove_prepoll, + su_base_port_timers, + su_select_port_multishot, + su_base_port_threadsafe, + su_base_port_yield, + su_select_port_wait_events, + su_base_port_getmsgs, + su_base_port_getmsgs_from, + su_select_port_name, + su_base_port_start_shared, + su_pthread_port_wait, + su_pthread_port_execute + }}; + +static char const *su_select_port_name(su_port_t const *self) +{ + return "select"; +} + +static void su_select_port_deinit(void *arg) +{ + su_port_t *self = arg; + + SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self)); + + su_pthread_port_deinit(self); + + if (self->sup_waits) + free(self->sup_waits), self->sup_waits = NULL; + if (self->sup_wait_cbs) + free(self->sup_wait_cbs), self->sup_wait_cbs = NULL; + if (self->sup_wait_args) + free(self->sup_wait_args), self->sup_wait_args = NULL; + if (self->sup_wait_roots) + free(self->sup_wait_roots), self->sup_wait_roots = NULL; + if (self->sup_reverses) + free(self->sup_reverses), self->sup_reverses = NULL; + if (self->sup_indices) + free(self->sup_indices), self->sup_indices = NULL; + + SU_DEBUG_9(("%s(%p) freed registrations\n", + "su_select_port_deinit", (void *)self)); +} + +static void su_select_port_decref(su_port_t *self, int blocking, char const *who) +{ + su_base_port_decref(self, blocking, who); +} + +/** @internal + * + * Register a @c su_wait_t object. The wait object, a callback function and + * an argument pointer is stored in the port object. The callback function + * will be called when the wait object is signaled. + * + * Please note if identical wait objects are inserted, only first one is + * ever signalled. + * + * @param self pointer to port + * @param root pointer to root object + * @param waits pointer to wait object + * @param callback callback function pointer + * @param arg argument given to callback function when it is invoked + * @param priority relative priority of the wait object + * (0 is normal, 1 important, 2 realtime) + * + * @return + * Positive index of the wait object, + * or -1 upon an error. + */ +int su_select_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority) +{ + int i, j, n; + + assert(su_port_own_thread(self)); + + n = self->sup_n_waits; + + if (n >= SU_WAIT_MAX) + return su_seterrno(ENOMEM); + + if (n >= self->sup_size_waits) { + /* Reallocate size arrays */ + int size; + int *indices; + int *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t **wait_args; + su_root_t **wait_tasks; + + if (self->sup_size_waits == 0) + size = su_root_size_hint; + else + size = 2 * self->sup_size_waits; + + if (size < SU_WAIT_MIN) + size = SU_WAIT_MIN; + + /* Too large */ + if (-3 - size > 0) + return (errno = ENOMEM), -1; + + indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices)); + if (indices) { + self->sup_indices = indices; + + if (self->sup_size_waits == 0) + indices[0] = -1; + + for (i = self->sup_size_waits + 1; i <= size; i++) + indices[i] = -1 - i; + } + + reverses = realloc(self->sup_reverses, size * sizeof(*waits)); + if (reverses) { + for (i = self->sup_size_waits; i < size; i++) + reverses[i] = -1; + self->sup_reverses = reverses; + } + + waits = realloc(self->sup_waits, size * sizeof(*waits)); + if (waits) + self->sup_waits = waits; + + wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs)); + if (wait_cbs) + self->sup_wait_cbs = wait_cbs; + + wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args)); + if (wait_args) + self->sup_wait_args = wait_args; + + /* Add sup_wait_roots array, if needed */ + wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks)); + if (wait_tasks) + self->sup_wait_roots = wait_tasks; + + if (!(indices && + reverses && waits && wait_cbs && wait_args && wait_tasks)) { + return -1; + } + + self->sup_size_waits = size; + } + + i = -self->sup_indices[0]; assert(i <= self->sup_size_waits); + + if (priority > 0) { + /* Insert */ + for (n = self->sup_n_waits; n > 0; n--) { + j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1); + self->sup_indices[j] = n; + self->sup_reverses[n] = j; + self->sup_waits[n] = self->sup_waits[n-1]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; + self->sup_wait_args[n] = self->sup_wait_args[n-1]; + self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; + } + + self->sup_pri_offset++; + } + else { + /* Append - no need to move anything */ + n = self->sup_n_waits; + } + + self->sup_n_waits++; + + self->sup_indices[0] = self->sup_indices[i]; /* Free index */ + self->sup_indices[i] = n; + + self->sup_reverses[n] = i; + self->sup_waits[n] = *wait; + self->sup_wait_cbs[n] = callback; + self->sup_wait_args[n] = arg; + self->sup_wait_roots[n] = root; + + self->sup_registers++; + + /* We return -1 or positive integer */ + + return i; +} + +/** Deregister a su_wait_t object. */ +static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait) +{ + int n, N, *indices, *reverses; + + indices = self->sup_indices; + reverses = self->sup_reverses; + + n = indices[i]; assert(n >= 0); + + if (destroy_wait) + su_wait_destroy(&self->sup_waits[n]); + + N = --self->sup_n_waits; + + if (n < self->sup_pri_offset) { + int j = --self->sup_pri_offset; + if (n != j) { + assert(reverses[j] > 0); + assert(indices[reverses[j]] == j); + indices[reverses[j]] = n; + reverses[n] = reverses[j]; + + self->sup_waits[n] = self->sup_waits[j]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[j]; + self->sup_wait_args[n] = self->sup_wait_args[j]; + self->sup_wait_roots[n] = self->sup_wait_roots[j]; + n = j; + } + } + + if (n < N) { + assert(reverses[N] > 0); + assert(indices[reverses[N]] == N); + + indices[reverses[N]] = n; + reverses[n] = reverses[N]; + + self->sup_waits[n] = self->sup_waits[N]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[N]; + self->sup_wait_args[n] = self->sup_wait_args[N]; + self->sup_wait_roots[n] = self->sup_wait_roots[N]; + n = N; + } + + reverses[n] = -1; + memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]); + self->sup_wait_cbs[n] = NULL; + self->sup_wait_args[n] = NULL; + self->sup_wait_roots[n] = NULL; + + indices[i] = indices[0]; + indices[0] = -i; + + self->sup_registers++; + + return i; +} + + +/** Unregister a su_wait_t object. + * + * The function su_select_port_unregister() unregisters a su_wait_t object. The + * wait object, a callback function and a argument are removed from the + * port object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * @param wait - pointer to wait object + * @param callback - callback function pointer (may be NULL) + * @param arg - argument given to callback function when it is invoked + * (may be NULL) + * + * @deprecated Use su_select_port_deregister() instead. + * + * @return Nonzero index of the wait object, or -1 upon an error. + */ +int su_select_port_unregister(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, /* XXX - ignored */ + su_wakeup_arg_t *arg) +{ + int n, N; + + assert(self); + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + + for (n = 0; n < N; n++) { + if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { + return su_select_port_deregister0(self, self->sup_reverses[n], 0); + } + } + + su_seterrno(ENOENT); + + return -1; +} + +/** Deregister a su_wait_t object. + * + * Deregisters a registration by index. The wait object, a callback + * function and a argument are removed from the port object. The wait + * object is destroyed. + * + * @param self - pointer to port object + * @param i - registration index + * + * @return Index of the wait object, or -1 upon an error. + */ +int su_select_port_deregister(su_port_t *self, int i) +{ + su_wait_t wait[1] = { SU_WAIT_INIT }; + int retval; + + assert(self); + assert(su_port_own_thread(self)); + + if (i <= 0 || i > self->sup_size_waits) + return su_seterrno(EBADF); + + if (self->sup_indices[i] < 0) + return su_seterrno(EBADF); + + retval = su_select_port_deregister0(self, i, 1); + + su_wait_destroy(wait); + + return retval; +} + + +/** @internal + * Unregister all su_wait_t objects. + * + * The function su_select_port_unregister_all() unregisters all su_wait_t objects + * and destroys all queued timers associated with given root object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * + * @return Number of wait objects removed. + */ +int su_select_port_unregister_all(su_port_t *self, + su_root_t *root) +{ + int i, j, index, N; + int *indices, *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t**wait_args; + su_root_t **wait_roots; + + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + indices = self->sup_indices; + reverses = self->sup_reverses; + waits = self->sup_waits; + wait_cbs = self->sup_wait_cbs; + wait_args = self->sup_wait_args; + wait_roots = self->sup_wait_roots; + + for (i = j = 0; i < N; i++) { + index = reverses[i]; assert(index > 0 && indices[index] == i); + + if (wait_roots[i] == root) { + /* XXX - we should free all resources associated with this, too */ + if (i < self->sup_pri_offset) + self->sup_pri_offset--; + + indices[index] = indices[0]; + indices[0] = -index; + continue; + } + + if (i != j) { + indices[index] = j; + reverses[j] = reverses[i]; + waits[j] = waits[i]; + wait_cbs[j] = wait_cbs[i]; + wait_args[j] = wait_args[i]; + wait_roots[j] = wait_roots[i]; + } + + j++; + } + + for (i = j; i < N; i++) { + reverses[i] = -1; + wait_cbs[i] = NULL; + wait_args[i] = NULL; + wait_roots[i] = NULL; + } + memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]); + + self->sup_n_waits = j; + self->sup_registers++; + + return N - j; +} + +/**Set mask for a registered event. @internal + * + * The function su_select_port_eventmask() sets the mask describing events that can + * signal the registered callback. + * + * @param port pointer to port object + * @param index registration index + * @param socket socket + * @param events new event mask + * + * @retval 0 when successful, + * @retval -1 upon an error. + */ +int su_select_port_eventmask(su_port_t *self, int index, int socket, int events) +{ + int n; + assert(self); + assert(su_port_own_thread(self)); + + if (index <= 0 || index > self->sup_size_waits) + return su_seterrno(EBADF); + n = self->sup_indices[index]; + if (n < 0) + return su_seterrno(EBADF); + + return su_wait_mask(&self->sup_waits[n], socket, events); +} + +/** @internal Enable multishot mode. + * + * Enables, disables or queries the multishot mode for the port. The + * multishot mode determines how the events are scheduled by port. If + * multishot mode is enabled, port serves all the sockets that have received + * network events. If it is disabled, only first socket event is served. + * + * @param self pointer to port object + * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) + * + * @retval 0 multishot mode is disabled + * @retval 1 multishot mode is enabled + * @retval -1 an error occurred + */ +static +int su_select_port_multishot(su_port_t *self, int multishot) +{ + if (multishot < 0) + return self->sup_multishot; + else if (multishot == 0 || multishot == 1) + return self->sup_multishot = multishot; + else + return (errno = EINVAL), -1; +} + + +/** @internal + * Wait (select()) for wait objects in port. + * + * @param self pointer to port + * @param tout timeout in milliseconds + * + * @return number of events handled + */ +static +int su_select_port_wait_events(su_port_t *self, su_duration_t tout) +{ + /* NOT IMPLEMENTED */ + (void)su_select_port_deinit; + + return -1; +} + +#if 0 +/** @internal + * Prints out the contents of the port. + * + * @param self pointer to a port + * @param f pointer to a file (if @c NULL, uses @c stdout). + */ +void su_port_dump(su_port_t const *self, FILE *f) +{ + int i; +#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "") +#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "") +#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "") + + if (f == NULL) + f = stdout; + + fprintf(f, "su_port_t at %p:\n", self); + fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); +#if SU_HAVE_PTHREADS + fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); + fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0], + IS_WAIT_IN(&self->sup_mbox_wait), + IS_WAIT_OUT(&self->sup_mbox_wait), + IS_WAIT_ACCEPT(&self->sup_mbox_wait)); +#endif + fprintf(f, "\t%d wait objects\n", self->sup_n_waits); + for (i = 0; i < self->sup_n_waits; i++) { + + } +} + +#endif + +/** Create a port using select(). + */ +su_port_t *su_select_port_create(void) +{ +#if notyet + su_port_t *self = su_home_new(sizeof *self); + + if (!self) + return self; + + if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0) + return su_home_unref(su_port_home(self)), NULL; + + self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; + + if (su_pthread_port_init(self, su_select_port_vtable) < 0) + return su_home_unref(su_port_home(self)), NULL; + + return self; +#else + return NULL; +#endif +} + +int su_select_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + return su_pthreaded_port_start(su_select_port_create, + parent, return_clone, magic, init, deinit); +} + +#endif diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c b/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c index 67a24b6752..b74db94b74 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_timer.c @@ -295,13 +295,13 @@ int su_timer_set_interval(su_timer_t *t, su_timer_t **timers; if (t == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "NULL argument")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument")); return -1; } timers = su_task_timers(t->sut_task); if (timers == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "invalid timer")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer")); return -1; } @@ -333,7 +333,8 @@ int su_timer_set(su_timer_t *t, assert(t->sut_duration > 0); if (t->sut_duration == 0) { - SU_DEBUG_0(("%s(%p): %s\n", func, t, "timer without default duration")); + SU_DEBUG_0(("%s(%p): %s\n", func, (void *)t, + "timer without default duration")); return -1; } @@ -360,13 +361,13 @@ int su_timer_set_at(su_timer_t *t, su_timer_t **timers; if (t == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "NULL argument")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument")); return -1; } timers = su_task_timers(t->sut_task); if (timers == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "invalid timer")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer")); return -1; } @@ -402,19 +403,20 @@ int su_timer_run(su_timer_t *t, su_time_t now = su_now(); if (t == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "NULL argument")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument")); return -1; } assert(t->sut_duration > 0); if (t->sut_duration == 0) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "timer without default duration")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, + "timer without default duration")); return -1; } timers = su_task_timers(t->sut_task); if (timers == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "invalid timer")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer")); return -1; } @@ -447,24 +449,25 @@ int su_timer_set_for_ever(su_timer_t *t, su_timer_f wakeup, su_timer_arg_t *arg) { - char const *func = "su_timer_run"; + char const *func = "su_timer_set_for_ever"; su_timer_t **timers; su_time_t now = su_now(); if (t == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "NULL argument")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument")); return -1; } assert(t->sut_duration > 0); if (t->sut_duration == 0) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "timer without default duration")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, + "timer without default duration")); return -1; } timers = su_task_timers(t->sut_task); if (timers == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "invalid timer")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer")); return -1; } @@ -477,7 +480,6 @@ int su_timer_set_for_ever(su_timer_t *t, return 0; } - /**Reset the timer. * * Resets (stops) the given timer. @@ -492,7 +494,7 @@ int su_timer_reset(su_timer_t *t) su_timer_t **timers; if (t == NULL) { - SU_DEBUG_1(("%s(%p): %s\n", func, t, "NULL argument")); + SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument")); return -1; } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c b/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c index 7e412b41a0..dabe4f2fc3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c @@ -149,7 +149,7 @@ int su_wait_create(su_wait_t *newwait, su_socket_t socket, int events) *newwait = h; -#elif SU_HAVE_POLL +#elif SU_HAVE_POLL || HAVE_SELECT int mode; if (newwait == NULL || events == 0 || socket == INVALID_SOCKET) { @@ -187,7 +187,9 @@ int su_wait_destroy(su_wait_t *waitobj) su_wait_t w0 = NULL; if (*waitobj) WSACloseEvent(*waitobj); -#elif SU_HAVE_POLL +#elif SU_HAVE_POLL || HAVE_SELECT + su_wait_t w0 = { INVALID_SOCKET, 0, 0 }; +#else su_wait_t w0 = { INVALID_SOCKET, 0, 0 }; #endif assert(waitobj != NULL); @@ -231,7 +233,7 @@ int su_wait(su_wait_t waits[], unsigned n, su_duration_t timeout) else return i; -#elif SU_HAVE_POLL +#elif SU_HAVE_POLL || HAVE_SELECT for (;;) { int i = poll(waits, n, timeout); @@ -273,7 +275,7 @@ int su_wait_events(su_wait_t *waitobj, su_socket_t s) return net_events.lNetworkEvents; -#elif SU_HAVE_POLL +#elif SU_HAVE_POLL || HAVE_SELECT /* poll(e, 1, 0); */ return waitobj->revents; #endif @@ -302,7 +304,7 @@ int su_wait_mask(su_wait_t *waitobj, su_socket_t s, int events) WSASetLastError(error); return -1; } -#elif SU_HAVE_POLL +#elif SU_HAVE_POLL || HAVE_SELECT waitobj->fd = s; waitobj->events = events; waitobj->revents = 0; diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c b/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c new file mode 100644 index 0000000000..ba201647f1 --- /dev/null +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c @@ -0,0 +1,687 @@ +/* + * This file is part of the Sofia-SIP package + * + * Copyright (C) 2005 Nokia Corporation. + * + * Contact: Pekka Pessi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/**@ingroup su_wait + * @CFILE su_poll_port.c + * + * Port implementation using poll() + * + * @author Pekka Pessi + * @author Kai Vehmanen + * + * @date Created: Tue Sep 14 15:51:04 1999 ppessi + */ + +#include "config.h" + +#if HAVE_POLL || HAVE_WIN32 + +#include +#include +#include +#include +#include +#include +#include + +#define su_port_s su_poll_port_s + +#include "sofia-sip/su.h" +#include "su_port.h" +#include "sofia-sip/su_alloc.h" + +/** Port based on poll(). */ + +struct su_poll_port_s { + su_pthread_port_t sup_base[1]; + +#define sup_home sup_base->sup_base->sup_home + + unsigned sup_multishot; /**< Multishot operation? */ + + unsigned sup_registers; /** Counter incremented by + su_port_register() or + su_port_unregister() + */ + + int sup_n_waits; /**< Active su_wait_t in su_waits */ + int sup_size_waits; /**< Size of allocated su_waits */ + int sup_pri_offset; /**< Offset to prioritized waits */ + +#if !SU_HAVE_WINSOCK +#define INDEX_MAX (0x7fffffff) +#else + /* We use WSAWaitForMultipleEvents() */ +#define INDEX_MAX (64) +#endif + + /** Indices from index returned by su_root_register() to tables below. + * + * Free elements are negative. Free elements form a list, value of free + * element is (0 - index of next free element). + * + * First element sup_indices[0] points to first free element. + */ + int *sup_indices; + + int *sup_reverses; /** Reverse index */ + su_wakeup_f *sup_wait_cbs; + su_wakeup_arg_t**sup_wait_args; + su_root_t **sup_wait_roots; + su_wait_t *sup_waits; + +}; + +static void su_poll_port_decref(su_port_t *, int blocking, char const *who); + +static int su_poll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority); +static int su_poll_port_unregister(su_port_t *port, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg); +static int su_poll_port_deregister(su_port_t *self, int i); +static int su_poll_port_unregister_all(su_port_t *self, su_root_t *root); +static int su_poll_port_eventmask(su_port_t *self, + int index, + int socket, + int events); +static int su_poll_port_multishot(su_port_t *self, int multishot); +static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout); +static char const *su_poll_port_name(su_port_t const *self); + +su_port_vtable_t const su_poll_port_vtable[1] = + {{ + /* su_vtable_size: */ sizeof su_poll_port_vtable, + su_pthread_port_lock, + su_pthread_port_unlock, + su_base_port_incref, + su_poll_port_decref, + su_base_port_gsource, + su_pthread_port_send, + su_poll_port_register, + su_poll_port_unregister, + su_poll_port_deregister, + su_poll_port_unregister_all, + su_poll_port_eventmask, + su_base_port_run, + su_base_port_break, + su_base_port_step, + su_pthread_port_own_thread, + su_base_port_add_prepoll, + su_base_port_remove_prepoll, + su_base_port_timers, + su_poll_port_multishot, + su_base_port_threadsafe, + su_base_port_yield, + su_poll_port_wait_events, + su_base_port_getmsgs, + su_base_port_getmsgs_from, + su_poll_port_name, + su_base_port_start_shared, + su_pthread_port_wait, + su_pthread_port_execute, + }}; + +static char const *su_poll_port_name(su_port_t const *self) +{ + return "poll"; +} + +static void su_poll_port_deinit(void *arg) +{ + su_port_t *self = arg; + + SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", self)); + + su_pthread_port_deinit(self); +} + +static void su_poll_port_decref(su_port_t *self, int blocking, char const *who) +{ + su_base_port_decref(self, blocking, who); +} + +/** @internal + * + * Register a @c su_wait_t object. The wait object, a callback function and + * an argument pointer is stored in the port object. The callback function + * will be called when the wait object is signaled. + * + * Please note if identical wait objects are inserted, only first one is + * ever signalled. + * + * @param self pointer to port + * @param root pointer to root object + * @param waits pointer to wait object + * @param callback callback function pointer + * @param arg argument given to callback function when it is invoked + * @param priority relative priority of the wait object + * (0 is normal, 1 important, 2 realtime) + * + * @return + * Positive index of the wait object, + * or -1 upon an error. + */ +int su_poll_port_register(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, + su_wakeup_arg_t *arg, + int priority) +{ + int i, j, n; + + assert(su_port_own_thread(self)); + + n = self->sup_n_waits; + + if (n >= SU_WAIT_MAX) + return su_seterrno(ENOMEM); + + if (n >= self->sup_size_waits) { + su_home_t *h = self->sup_home; + /* Reallocate size arrays */ + int size; + int *indices; + int *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t **wait_args; + su_root_t **wait_tasks; + + if (self->sup_size_waits == 0) + size = su_root_size_hint; + else + size = 2 * self->sup_size_waits; + + if (size < SU_WAIT_MIN) + size = SU_WAIT_MIN; + + /* Too large */ + if (-3 - size > 0) + return (errno = ENOMEM), -1; + + indices = su_realloc(h, self->sup_indices, (size + 1) * sizeof(*indices)); + if (indices) { + self->sup_indices = indices; + + if (self->sup_size_waits == 0) + indices[0] = -1; + + for (i = self->sup_size_waits + 1; i <= size; i++) + indices[i] = -1 - i; + } + + reverses = su_realloc(h, self->sup_reverses, size * sizeof(*waits)); + if (reverses) { + for (i = self->sup_size_waits; i < size; i++) + reverses[i] = -1; + self->sup_reverses = reverses; + } + + waits = su_realloc(h, self->sup_waits, size * sizeof(*waits)); + if (waits) + self->sup_waits = waits; + + wait_cbs = su_realloc(h, self->sup_wait_cbs, size * sizeof(*wait_cbs)); + if (wait_cbs) + self->sup_wait_cbs = wait_cbs; + + wait_args = su_realloc(h, self->sup_wait_args, size * sizeof(*wait_args)); + if (wait_args) + self->sup_wait_args = wait_args; + + /* Add sup_wait_roots array, if needed */ + wait_tasks = su_realloc(h, self->sup_wait_roots, size * sizeof(*wait_tasks)); + if (wait_tasks) + self->sup_wait_roots = wait_tasks; + + if (!(indices && + reverses && waits && wait_cbs && wait_args && wait_tasks)) { + return -1; + } + + self->sup_size_waits = size; + } + + i = -self->sup_indices[0]; assert(i <= self->sup_size_waits); + + if (priority > 0) { + /* Insert */ + for (n = self->sup_n_waits; n > 0; n--) { + j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1); + self->sup_indices[j] = n; + self->sup_reverses[n] = j; + self->sup_waits[n] = self->sup_waits[n-1]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1]; + self->sup_wait_args[n] = self->sup_wait_args[n-1]; + self->sup_wait_roots[n] = self->sup_wait_roots[n-1]; + } + + self->sup_pri_offset++; + } + else { + /* Append - no need to move anything */ + n = self->sup_n_waits; + } + + self->sup_n_waits++; + + self->sup_indices[0] = self->sup_indices[i]; /* Free index */ + self->sup_indices[i] = n; + + self->sup_reverses[n] = i; + self->sup_waits[n] = *wait; + self->sup_wait_cbs[n] = callback; + self->sup_wait_args[n] = arg; + self->sup_wait_roots[n] = root; + + self->sup_registers++; + + /* Just like epoll, we return -1 or positive integer */ + + return i; +} + +/** Deregister a su_wait_t object. */ +static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait) +{ + int n, N, *indices, *reverses; + + indices = self->sup_indices; + reverses = self->sup_reverses; + + n = indices[i]; assert(n >= 0); + + if (destroy_wait) + su_wait_destroy(&self->sup_waits[n]); + + N = --self->sup_n_waits; + + if (n < self->sup_pri_offset) { + int j = --self->sup_pri_offset; + if (n != j) { + assert(reverses[j] > 0); + assert(indices[reverses[j]] == j); + indices[reverses[j]] = n; + reverses[n] = reverses[j]; + + self->sup_waits[n] = self->sup_waits[j]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[j]; + self->sup_wait_args[n] = self->sup_wait_args[j]; + self->sup_wait_roots[n] = self->sup_wait_roots[j]; + n = j; + } + } + + if (n < N) { + assert(reverses[N] > 0); + assert(indices[reverses[N]] == N); + + indices[reverses[N]] = n; + reverses[n] = reverses[N]; + + self->sup_waits[n] = self->sup_waits[N]; + self->sup_wait_cbs[n] = self->sup_wait_cbs[N]; + self->sup_wait_args[n] = self->sup_wait_args[N]; + self->sup_wait_roots[n] = self->sup_wait_roots[N]; + n = N; + } + + reverses[n] = -1; + memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]); + self->sup_wait_cbs[n] = NULL; + self->sup_wait_args[n] = NULL; + self->sup_wait_roots[n] = NULL; + + indices[i] = indices[0]; + indices[0] = -i; + + self->sup_registers++; + + return i; +} + + +/** Unregister a su_wait_t object. + * + * The function su_poll_port_unregister() unregisters a su_wait_t object. The + * wait object, a callback function and a argument are removed from the + * port object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * @param wait - pointer to wait object + * @param callback - callback function pointer (may be NULL) + * @param arg - argument given to callback function when it is invoked + * (may be NULL) + * + * @deprecated Use su_poll_port_deregister() instead. + * + * @return Nonzero index of the wait object, or -1 upon an error. + */ +int su_poll_port_unregister(su_port_t *self, + su_root_t *root, + su_wait_t *wait, + su_wakeup_f callback, /* XXX - ignored */ + su_wakeup_arg_t *arg) +{ + int n, N; + + assert(self); + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + + for (n = 0; n < N; n++) { + if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { + return su_poll_port_deregister0(self, self->sup_reverses[n], 0); + } + } + + su_seterrno(ENOENT); + + return -1; +} + +/** Deregister a su_wait_t object. + * + * Deregisters a registration by index. The wait object, a callback + * function and a argument are removed from the port object. The wait + * object is destroyed. + * + * @param self - pointer to port object + * @param i - registration index + * + * @return Index of the wait object, or -1 upon an error. + */ +int su_poll_port_deregister(su_port_t *self, int i) +{ + su_wait_t wait[1] = { SU_WAIT_INIT }; + int retval; + + assert(self); + assert(su_port_own_thread(self)); + + if (i <= 0 || i > self->sup_size_waits) + return su_seterrno(EBADF); + + if (self->sup_indices[i] < 0) + return su_seterrno(EBADF); + + retval = su_poll_port_deregister0(self, i, 1); + + su_wait_destroy(wait); + + return retval; +} + + +/** @internal + * Unregister all su_wait_t objects. + * + * The function su_poll_port_unregister_all() unregisters all su_wait_t objects + * and destroys all queued timers associated with given root object. + * + * @param self - pointer to port object + * @param root - pointer to root object + * + * @return Number of wait objects removed. + */ +int su_poll_port_unregister_all(su_port_t *self, + su_root_t *root) +{ + int i, j, index, N; + int *indices, *reverses; + su_wait_t *waits; + su_wakeup_f *wait_cbs; + su_wakeup_arg_t**wait_args; + su_root_t **wait_roots; + + assert(su_port_own_thread(self)); + + N = self->sup_n_waits; + indices = self->sup_indices; + reverses = self->sup_reverses; + waits = self->sup_waits; + wait_cbs = self->sup_wait_cbs; + wait_args = self->sup_wait_args; + wait_roots = self->sup_wait_roots; + + for (i = j = 0; i < N; i++) { + index = reverses[i]; assert(index > 0 && indices[index] == i); + + if (wait_roots[i] == root) { + /* XXX - we should free all resources associated with this, too */ + if (i < self->sup_pri_offset) + self->sup_pri_offset--; + + indices[index] = indices[0]; + indices[0] = -index; + continue; + } + + if (i != j) { + indices[index] = j; + reverses[j] = reverses[i]; + waits[j] = waits[i]; + wait_cbs[j] = wait_cbs[i]; + wait_args[j] = wait_args[i]; + wait_roots[j] = wait_roots[i]; + } + + j++; + } + + for (i = j; i < N; i++) { + reverses[i] = -1; + wait_cbs[i] = NULL; + wait_args[i] = NULL; + wait_roots[i] = NULL; + } + memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]); + + self->sup_n_waits = j; + self->sup_registers++; + + return N - j; +} + +/**Set mask for a registered event. @internal + * + * The function su_poll_port_eventmask() sets the mask describing events that can + * signal the registered callback. + * + * @param port pointer to port object + * @param index registration index + * @param socket socket + * @param events new event mask + * + * @retval 0 when successful, + * @retval -1 upon an error. + */ +int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events) +{ + int n; + assert(self); + assert(su_port_own_thread(self)); + + if (index <= 0 || index > self->sup_size_waits) + return su_seterrno(EBADF); + n = self->sup_indices[index]; + if (n < 0) + return su_seterrno(EBADF); + + return su_wait_mask(&self->sup_waits[n], socket, events); +} + +/** @internal Enable multishot mode. + * + * Enables, disables or queries the multishot mode for the port. The + * multishot mode determines how the events are scheduled by port. If + * multishot mode is enabled, port serves all the sockets that have received + * network events. If it is disabled, only first socket event is served. + * + * @param self pointer to port object + * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) + * + * @retval 0 multishot mode is disabled + * @retval 1 multishot mode is enabled + * @retval -1 an error occurred + */ +static +int su_poll_port_multishot(su_port_t *self, int multishot) +{ + if (multishot < 0) + return self->sup_multishot; + else if (multishot == 0 || multishot == 1) + return self->sup_multishot = multishot; + else + return (errno = EINVAL), -1; +} + + +/** @internal + * Wait (poll()) for wait objects in port. + * + * @param self pointer to port + * @param tout timeout in milliseconds + * + * @return number of events handled + */ +static +int su_poll_port_wait_events(su_port_t *self, su_duration_t tout) +{ + int i, events = 0; + su_wait_t *waits = self->sup_waits; + int n = self->sup_n_waits; + su_root_t *root; + + i = su_wait(waits, (unsigned)n, tout); + + if (i >= 0 && i < n) { +#if 0 + /* poll() can return events for multiple wait objects */ + if (self->sup_multishot) { + unsigned version = self->sup_registers; + + for (; i < n; i++) { + if (waits[i].revents) { + root = self->sup_wait_roots[i]; + self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, + &waits[i], + self->sup_wait_args[i]); + events++; + /* Callback function used su_register()/su_deregister() */ + if (version != self->sup_registers) + break; + } + } + } +#else + if (0) ; +#endif + else { + root = self->sup_wait_roots[i]; + self->sup_wait_cbs[i](root ? su_root_magic(root) : NULL, + &self->sup_waits[i], + self->sup_wait_args[i]); + events++; + } + } + + return events; +} + +#if 0 +/** @internal + * Prints out the contents of the port. + * + * @param self pointer to a port + * @param f pointer to a file (if @c NULL, uses @c stdout). + */ +void su_port_dump(su_port_t const *self, FILE *f) +{ + int i; +#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "") +#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "") +#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "") + + if (f == NULL) + f = stdout; + + fprintf(f, "su_port_t at %p:\n", self); + fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); +#if SU_HAVE_PTHREADS + fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); + fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0], + IS_WAIT_IN(&self->sup_mbox_wait), + IS_WAIT_OUT(&self->sup_mbox_wait), + IS_WAIT_ACCEPT(&self->sup_mbox_wait)); +#endif + fprintf(f, "\t%d wait objects\n", self->sup_n_waits); + for (i = 0; i < self->sup_n_waits; i++) { + + } +} + +#endif + +/** Create a port using epoll() or poll(). + */ +su_port_t *su_poll_port_create(void) +{ + su_port_t *self = su_home_new(sizeof *self); + + if (!self) + return self; + + if (su_home_destructor(su_port_home(self), su_poll_port_deinit) < 0) + return su_home_unref(su_port_home(self)), NULL; + + self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; + + if (su_pthread_port_init(self, su_poll_port_vtable) < 0) + return su_home_unref(su_port_home(self)), NULL; + + return self; +} + +int su_poll_clone_start(su_root_t *parent, + su_clone_r return_clone, + su_root_magic_t *magic, + su_root_init_f init, + su_root_deinit_f deinit) +{ + return su_pthreaded_port_start(su_poll_port_create, + parent, return_clone, magic, init, deinit); +} + +#endif /* HAVE_POLL */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/tag_dll.awk b/libs/sofia-sip/libsofia-sip-ua/su/tag_dll.awk index 81df24f948..5631fe8ac1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/tag_dll.awk +++ b/libs/sofia-sip/libsofia-sip-ua/su/tag_dll.awk @@ -110,6 +110,11 @@ HEADER { print "" > DLL; } +/SU_HAVE_EXPERIMENTAL/ { + print $0 > REF; + print $0 > DLL; +} + !DEFS && /^tag_typedef_t/ { DEFS = 1; } DEFS && /tag_typedef_t/ { diff --git a/libs/sofia-sip/libsofia-sip-ua/su/test_su.c b/libs/sofia-sip/libsofia-sip-ua/su/test_su.c index e54867e70a..1e83d1532c 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/test_su.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/test_su.c @@ -36,13 +36,6 @@ #include "config.h" -#include -#include -#include -#include - -#include - struct pinger; #define SU_ROOT_MAGIC_T struct pinger #define SU_INTERNAL_P su_root_t * @@ -53,6 +46,12 @@ struct pinger; #include "sofia-sip/su_log.h" #include "sofia-sip/su_debug.h" +#include +#include +#include + +#include + char const name[] = "su_test"; #if HAVE_FUNC @@ -410,14 +409,6 @@ init_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg) } } -static -RETSIGTYPE term(int n) -{ - enter; - - exit(1); -} - void time_test(void) { @@ -440,10 +431,12 @@ time_test(void) printf("time_test: passed\n"); } -#if HAVE_ALARM +#if HAVE_SIGNAL #include #include +#if HAVE_ALARM + static RETSIGTYPE sig_alarm(int s) { enter; @@ -456,6 +449,18 @@ static char const no_alarm[] = " [--no-alarm]"; static char const no_alarm[] = ""; #endif +static +RETSIGTYPE term(int n) +{ + enter; + + exit(1); +} +#else +static char const no_alarm[] = ""; +#endif + + void usage(int exitcode) { @@ -519,11 +524,10 @@ int main(int argc, char *argv[]) } } - signal(SIGTERM, term); - su_init(); atexit(su_deinit); - time_test(); +#if HAVE_SIGNAL + signal(SIGTERM, term); #if HAVE_ALARM if (opt_alarm) { @@ -532,6 +536,10 @@ int main(int argc, char *argv[]) } #endif +#endif + + time_test(); + root = su_root_create(NULL); if (!root) perror("su_root_create"), exit(1); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su.c index ac2708d680..f18331bf58 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su.c @@ -47,7 +47,7 @@ int tstflags; #define TSTFLAGS tstflags #include -char const *name = "su_torture"; +char const *name = "torture_su"; static int test_sockaddr(void); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_alloc.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_alloc.c index 3149cdcffc..dae3f5f48e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_alloc.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_alloc.c @@ -59,6 +59,12 @@ void exdestructor(void *arg) (*ex->p)++; } +void test_destructor(void *a) +{ + su_home_t *h = a; + h->suh_size = 13; +} + /** Test basic memory home operations */ static int test_alloc(void) { @@ -78,8 +84,8 @@ static int test_alloc(void) d0 = d1a = d1 = d2 = d3 = 0; h0->p = &d0; h1->p = &d1a; - TEST(su_home_desctructor(h0->home, exdestructor), 0); - TEST(su_home_desctructor(h1->home, exdestructor), 0); + TEST(su_home_destructor(h0->home, exdestructor), 0); + TEST(su_home_destructor(h1->home, exdestructor), 0); TEST_1(h2 = su_home_ref(h0->home)); su_home_unref(h0->home); @@ -95,7 +101,7 @@ static int test_alloc(void) TEST(d1a, destructed_once); TEST_1(h1 = su_home_clone(h0->home, sizeof(*h1))); - TEST(su_home_desctructor(h1->home, exdestructor), 0); + TEST(su_home_destructor(h1->home, exdestructor), 0); h1->p = &d1; for (i = 0; i < 128; i++) @@ -125,7 +131,7 @@ static int test_alloc(void) TEST_1(su_in_home(h2->home, m)); TEST_1(!su_in_home(h2->home, (char *)m + 1)); - TEST_1(!su_in_home(h2->home, su_in_home)); + TEST_1(!su_in_home(h2->home, (void *)(intptr_t)su_in_home)); TEST_1(!su_in_home(h3->home, m)); TEST_1(!su_in_home(NULL, m)); TEST_1(!su_in_home(h3->home, NULL)); @@ -161,6 +167,25 @@ static int test_alloc(void) su_home_check(h0->home); su_home_zap(h0->home); + { + su_home_t h1[1]; + + memset(h1, 0, sizeof h1); + + TEST(su_home_init(h1), 0); + TEST(su_home_threadsafe(h1), 0); + + TEST_1(su_home_ref(h1)); + TEST_1(su_home_ref(h1)); + + TEST(su_home_destructor(h1, test_destructor), 0); + + TEST_1(!su_home_unref(h1)); + TEST_1(!su_home_unref(h1)); + TEST_1(su_home_unref(h1)); + TEST(h1->suh_size, 13); + } + END(); } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_bm.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_bm.c index d7d722cb79..10b0be3b8f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_bm.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_bm.c @@ -192,6 +192,8 @@ char const Needle[] = s = bm_memmem(hs, strlen(hs), needle, nlen, fwd); + free(fwd); + TEST_S(s, hs + 1919); TEST_1(bm_memmem(hs, strlen(hs), Needle, nlen, NULL) == 0); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_port.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_port.c index 0d4d9b4e49..d9cf304a42 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_port.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_port.c @@ -24,7 +24,7 @@ /** * @file torture_su_port.c - * @brief Test su_port interface + * @brief Test su_poll_port interface * * @author Pekka Pessi * @date Created: Wed Mar 10 17:05:23 2004 ppessi @@ -39,7 +39,10 @@ struct su_root_magic_s; #define SU_ROOT_MAGIC_T struct su_root_magic_s -#include "su_port.c" +#include "su_poll_port.c" + +#undef HAVE_EPOLL +#define HAVE_EPOLL 0 #if HAVE_FUNC #elif HAVE_FUNCTION @@ -56,7 +59,7 @@ int tstflags; char const *name = "torture_su_port"; -int N0 = SU_HAVE_MBOX, N = 128, I = 128 + 1; +int const N0 = SU_MBOX_SIZE > 0, N = 128, I = 129; int test_sup_indices(su_port_t const *port) { @@ -121,7 +124,7 @@ static int callback(su_root_magic_t *magic, magic->wakeups[i]++; -#if HAVE_POLL +#if HAVE_POLL || HAVE_SELECT if (w->fd != magic->sockets[i]) return ++magic->error; #endif @@ -144,7 +147,8 @@ int test_wakeup(su_port_t *port, su_root_magic_t *magic) su_perror("getsockname"), exit(1); if (su_sendto(magic->sockets[1], "X", 1, 0, su, sulen) < 0) su_perror("su_sendto"), exit(1); - n = su_port_wait_events(port, 100); + n = su_poll_port_wait_events(port, 100); + if (n != 1) return 1; if (magic->error) @@ -188,9 +192,10 @@ int test_register(void) su_root_size_hint = 16; - TEST_1(port = su_port_create()); + TEST_1(port = su_poll_port_create()); TEST(su_port_threadsafe(port), 0); - SU_PORT_INCREF(port, __func__); + /* Before 1.12.4 su_port_create() had reference count 0 after creation */ + /* su_port_incref(port, "test_register"); */ TEST_1(test_sup_indices(port)); @@ -292,7 +297,7 @@ int test_register(void) TEST(su_port_deregister(port, reg[i]), -1); } - TEST_VOID(su_port_decref(port, 1, __func__)); + TEST_VOID(su_port_decref(port, __func__)); END(); } diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c index bdbd76472f..08152b9e2d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c @@ -54,15 +54,19 @@ typedef struct test_ep_s test_ep_t; #include #include +#include -typedef struct test_ep_s { +struct test_ep_s { + test_ep_t *next, **prev, **list; int i; int s; su_wait_t wait[1]; int registered; socklen_t addrlen; su_sockaddr_t addr[1]; -} test_ep_at[1]; +}; + +typedef struct test_ep_s test_ep_at[1]; struct root_test_s { su_home_t rt_home[1]; @@ -81,7 +85,15 @@ struct root_test_s { unsigned rt_success_init:1; unsigned rt_success_deinit:1; + unsigned rt_sent_reporter:1; + unsigned rt_recv_reporter:1; + unsigned rt_reported_reporter:1; + + unsigned :0; + test_ep_at rt_ep[5]; + + int rt_sockets, rt_woken; }; /** Test root initialization */ @@ -179,7 +191,6 @@ static int wakeup4(root_test_t *rt, su_wait_t *w, test_ep_t *ep) static su_wakeup_f wakeups[5] = { wakeup0, wakeup1, wakeup2, wakeup3, wakeup4 }; - static void test_run(root_test_t *rt) { @@ -271,6 +282,133 @@ static int register_test(root_test_t *rt) END(); } + +int wakeup_remove(root_test_t *rt, su_wait_t *w, test_ep_t *node) +{ + char buffer[64]; + ssize_t x; + test_ep_t *n = node->next; + + su_wait_events(w, node->s); + + x = recv(node->s, buffer, sizeof(buffer), 0); + + if (x < 0) + fprintf(stderr, "%s: %s\n", "recv", su_strerror(su_errno())); + + if (node->prev) { /* first run */ + *node->prev = n; + + if (n) { + *node->prev = node->next; + node->next->prev = node->prev; + sendto(n->s, "foo", 3, 0, (void *)n->addr, n->addrlen); + } + + node->next = NULL; + node->prev = NULL; + + if (!*node->list) { + su_root_break(rt->rt_root); + } + } + else { /* second run */ + if (++rt->rt_woken == rt->rt_sockets) + su_root_break(rt->rt_root); + } + + return 0; +} + + +int event_test(root_test_t rt[1]) +{ + BEGIN(); + int i = 0, N = 2048; + test_ep_t *n, *nodes, *list = NULL; + su_sockaddr_t su[1]; + socklen_t sulen; + + TEST_1(nodes = calloc(N, sizeof *nodes)); + + memset(su, 0, sulen = sizeof su->su_sin); + su->su_len = sizeof su->su_sin; + su->su_family = AF_INET; + su->su_sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + + for (i = 0; i < N; i++) { + n = nodes + i; + n->s = su_socket(AF_INET, SOCK_DGRAM, 0); + + if (n->s == INVALID_SOCKET) + break; + + n->addrlen = sizeof n->addr; + + n->addr->su_len = sizeof n->addr; + + if (bind(n->s, (void *)su, sulen) < 0) { + su_perror("bind()"); + su_close(n->s); + break; + } + + if (getsockname(n->s, (void *)n->addr, &n->addrlen)) { + su_perror("getsockname()"); + su_close(n->s); + break; + } + + if (su_wait_create(n->wait, n->s, SU_WAIT_IN)) { + su_perror("su_wait_create()"); + su_close(n->s); + break; + } + + n->registered = su_root_register(rt->rt_root, n->wait, wakeup_remove, n, 0); + if (n->registered < 0) { + su_wait_destroy(n->wait); + su_close(n->s); + break; + } + + n->list = &list, n->prev = &list; + if ((n->next = list)) + n->next->prev = &n->next; + list = n; + } + + TEST_1(i >= 1); + + N = i; + + /* Wake up socket at a time */ + n = list; sendto(n->s, "foo", 3, 0, (void *)n->addr, n->addrlen); + + su_root_run(rt->rt_root); + + for (i = 0; i < N; i++) { + n = nodes + i; + TEST_1(n->prev == NULL); + sendto(n->s, "bar", 3, 0, (void *)n->addr, n->addrlen); + } + + rt->rt_sockets = N; + + /* Wake up all sockets */ + su_root_run(rt->rt_root); + + for (i = 0; i < N; i++) { + n = nodes + i; + su_root_deregister(rt->rt_root, n->registered); + TEST_1(su_close(n->s) == 0); + } + + free(nodes); + + END(); +} + int fail_init(su_root_t *root, root_test_t *rt) { rt->rt_fail_init = 1; @@ -293,14 +431,49 @@ void success_deinit(su_root_t *root, root_test_t *rt) rt->rt_success_deinit = 1; } +void receive_a_reporter(root_test_t *rt, + su_msg_r msg, + su_msg_arg_t *arg) +{ + rt->rt_recv_reporter = 1; +} + +void receive_recv_report(root_test_t *rt, + su_msg_r msg, + su_msg_arg_t *arg) +{ + rt->rt_reported_reporter = 1; +} + +void send_a_reporter_msg(root_test_t *rt, + su_msg_r msg, + su_msg_arg_t *arg) +{ + su_msg_r m = SU_MSG_R_INIT; + + if (su_msg_create(m, + su_msg_from(msg), + su_msg_to(msg), + receive_a_reporter, + 0) == 0 && + su_msg_report(m, receive_recv_report) == 0 && + su_msg_send(m) == 0) + rt->rt_sent_reporter = 1; +} + static int clone_test(root_test_t rt[1]) { BEGIN(); + su_msg_r m = SU_MSG_R_INIT; + rt->rt_fail_init = 0; rt->rt_fail_deinit = 0; rt->rt_success_init = 0; rt->rt_success_deinit = 0; + rt->rt_sent_reporter = 0; + rt->rt_recv_reporter = 0; + rt->rt_reported_reporter = 0; TEST(su_clone_start(rt->rt_root, rt->rt_clone, @@ -318,10 +491,36 @@ static int clone_test(root_test_t rt[1]) TEST_1(rt->rt_success_init); TEST_1(!rt->rt_success_deinit); + /* Make sure 3-way handshake is done as expected */ + TEST(su_msg_create(m, + su_clone_task(rt->rt_clone), + su_root_task(rt->rt_root), + send_a_reporter_msg, + 0), 0); + TEST(su_msg_send(m), 0); + TEST_VOID(su_clone_wait(rt->rt_root, rt->rt_clone)); TEST_1(rt->rt_success_deinit); - + TEST_1(rt->rt_sent_reporter); + TEST_1(rt->rt_recv_reporter); + TEST_1(rt->rt_reported_reporter); + + rt->rt_recv_reporter = 0; + + /* Make sure we can handle messages done as expected */ + TEST(su_msg_create(m, + su_root_task(rt->rt_root), + su_task_null, + receive_a_reporter, + 0), 0); + TEST(su_msg_send(m), 0); + su_root_step(rt->rt_root, 0); + TEST_1(rt->rt_recv_reporter); + + rt->rt_success_init = 0; + rt->rt_success_deinit = 0; + END(); } @@ -353,6 +552,8 @@ int main(int argc, char *argv[]) retval |= init_test(rt); retval |= register_test(rt); + retval |= event_test(rt); + su_root_threading(rt->rt_root, 1); retval |= clone_test(rt); su_root_threading(rt->rt_root, 0); retval |= clone_test(rt); diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_timer.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_timer.c index 1b6a53c5ed..4b7f63654a 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/torture_su_timer.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/torture_su_timer.c @@ -39,7 +39,6 @@ #include #include #include -#include #include @@ -91,6 +90,10 @@ print_X(struct tester *x, su_timer_t *t1, struct timing *ti) putchar('X'); fflush(stdout); } +#if HAVE_SIGNAL + +#include + su_msg_r intr_msg = SU_MSG_R_INIT; static RETSIGTYPE intr_handler(int signum) @@ -103,6 +106,8 @@ static void test_break(struct tester *tester, su_msg_r msg, su_msg_arg_t *arg) su_root_break(tester->root); } +#endif + void end_test(struct tester *tester, su_timer_t *t, struct timing *ti) { @@ -182,6 +187,7 @@ int main(int argc, char *argv[]) tester->root = root = su_root_create(tester); +#if HAVE_SIGNAL su_msg_create(intr_msg, su_root_task(root), su_root_task(root), @@ -189,9 +195,9 @@ int main(int argc, char *argv[]) signal(SIGINT, intr_handler); #if HAVE_SIGPIPE - signal(SIGPIPE, intr_handler); signal(SIGQUIT, intr_handler); signal(SIGHUP, intr_handler); +#endif #endif t = su_timer_create(su_root_task(root), interval); @@ -217,7 +223,9 @@ int main(int argc, char *argv[]) su_root_run(root); +#if HAVE_SIGNAL su_msg_destroy(intr_msg); +#endif su_timer_destroy(t); su_timer_destroy(t1); diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am index 12d9cfaec2..2deb095344 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.am @@ -35,20 +35,28 @@ nobase_include_sofia_HEADERS = \ sofia-sip/tport_plugins.h TLS_SRC = tport_type_tls.c tport_tls.c tport_tls.h - if HAVE_TLS USE_TLS_SRC = $(TLS_SRC) endif +STUN_SRC = tport_stub_stun.c tport_type_stun.c +if HAVE_STUN +USE_STUN_SRC = $(STUN_SRC) +endif + +HTTP_SRC = tport_type_connect.c +if HAVE_NTH +USE_HTTP_SRC = $(HTTP_SRC) +endif + libtport_la_SOURCES = tport.c tport_logging.c \ - tport_stub_stun.c tport_stub_sigcomp.c \ + tport_stub_sigcomp.c \ tport_type_udp.c tport_type_tcp.c tport_type_sctp.c \ - tport_type_connect.c tport_type_stun.c \ tport_internal.h \ - tport_tag.c tport_tag_ref.c $(USE_TLS_SRC) + tport_tag.c tport_tag_ref.c $(USE_HTTP_SRC) $(USE_TLS_SRC) $(USE_STUN_SRC) # to make sure all files end up in the dist package -EXTRA_libtport_la_SOURCES = $(TLS_SRC) +EXTRA_libtport_la_SOURCES = $(TLS_SRC) $(STUN_SRC) $(HTTP_SRC) # Disable for now EXTRA_libtport_la_SOURCES += tport_sigcomp.c tport_threadpool.c @@ -78,4 +86,5 @@ EXTRA_DIST = Doxyfile tport.docs \ # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am + diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.in index 6871012a2b..4af87aa845 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/tport/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. @@ -56,8 +81,12 @@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = check_PROGRAMS = test_tport$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/tport ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -73,16 +102,20 @@ CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtport_la_LIBADD = am__libtport_la_SOURCES_DIST = tport.c tport_logging.c \ - tport_stub_stun.c tport_stub_sigcomp.c tport_type_udp.c \ - tport_type_tcp.c tport_type_sctp.c tport_type_connect.c \ - tport_type_stun.c tport_internal.h tport_tag.c tport_tag_ref.c \ - tport_type_tls.c tport_tls.c tport_tls.h -am__objects_1 = tport_type_tls.lo tport_tls.lo -@HAVE_TLS_TRUE@am__objects_2 = $(am__objects_1) -am_libtport_la_OBJECTS = tport.lo tport_logging.lo tport_stub_stun.lo \ + tport_stub_sigcomp.c tport_type_udp.c tport_type_tcp.c \ + tport_type_sctp.c tport_internal.h tport_tag.c tport_tag_ref.c \ + tport_type_connect.c tport_type_tls.c tport_tls.c tport_tls.h \ + tport_stub_stun.c tport_type_stun.c +am__objects_1 = tport_type_connect.lo +@HAVE_NTH_TRUE@am__objects_2 = $(am__objects_1) +am__objects_3 = tport_type_tls.lo tport_tls.lo +@HAVE_TLS_TRUE@am__objects_4 = $(am__objects_3) +am__objects_5 = tport_stub_stun.lo tport_type_stun.lo +@HAVE_STUN_TRUE@am__objects_6 = $(am__objects_5) +am_libtport_la_OBJECTS = tport.lo tport_logging.lo \ tport_stub_sigcomp.lo tport_type_udp.lo tport_type_tcp.lo \ - tport_type_sctp.lo tport_type_connect.lo tport_type_stun.lo \ - tport_tag.lo tport_tag_ref.lo $(am__objects_2) + tport_type_sctp.lo tport_tag.lo tport_tag_ref.lo \ + $(am__objects_2) $(am__objects_4) $(am__objects_6) libtport_la_OBJECTS = $(am_libtport_la_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(include_sofiadir)" @@ -122,6 +155,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -168,8 +202,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -213,6 +251,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -289,19 +328,22 @@ nobase_include_sofia_HEADERS = \ TLS_SRC = tport_type_tls.c tport_tls.c tport_tls.h @HAVE_TLS_TRUE@USE_TLS_SRC = $(TLS_SRC) +STUN_SRC = tport_stub_stun.c tport_type_stun.c +@HAVE_STUN_TRUE@USE_STUN_SRC = $(STUN_SRC) +HTTP_SRC = tport_type_connect.c +@HAVE_NTH_TRUE@USE_HTTP_SRC = $(HTTP_SRC) libtport_la_SOURCES = tport.c tport_logging.c \ - tport_stub_stun.c tport_stub_sigcomp.c \ + tport_stub_sigcomp.c \ tport_type_udp.c tport_type_tcp.c tport_type_sctp.c \ - tport_type_connect.c tport_type_stun.c \ tport_internal.h \ - tport_tag.c tport_tag_ref.c $(USE_TLS_SRC) + tport_tag.c tport_tag_ref.c $(USE_HTTP_SRC) $(USE_TLS_SRC) $(USE_STUN_SRC) # to make sure all files end up in the dist package # Disable for now -EXTRA_libtport_la_SOURCES = $(TLS_SRC) tport_sigcomp.c \ - tport_threadpool.c +EXTRA_libtport_la_SOURCES = $(TLS_SRC) $(STUN_SRC) $(HTTP_SRC) \ + tport_sigcomp.c tport_threadpool.c BUILT_SOURCES = tport_tag_ref.c COVERAGE_INPUT = $(libtport_la_SOURCES) $(include_sofia_HEADERS) LDADD = libtport.la \ @@ -321,7 +363,7 @@ test_tport_LDFLAGS = -static EXTRA_DIST = Doxyfile tport.docs \ certificates.html agent.pem cafile.pem -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -347,12 +389,14 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -626,7 +670,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -779,6 +823,92 @@ clean-built-sources: ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi + # ---------------------------------------------------------------------- # Sofia specific rules # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h index 634f943b1c..099fb2e534 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/sofia-sip/tport_tag.h @@ -389,6 +389,8 @@ TPORT_DLL extern tag_typedef_t tptag_tos; * Use with tport_tcreate(), tport_tbind(), tport_set_params(), nua_create(), * nta_agent_create(), nta_agent_add_tport(), nth_engine_create(), or * initial nth_site_create(). + * + * @NEW_1_12_5 */ #define TPTAG_TOS(x) tptag_tos, tag_int_v((x)) @@ -402,6 +404,8 @@ TPORT_DLL extern tag_typedef_t tptag_log; * nth_engine_create(), or initial nth_site_create(). * * @sa #TPORT_DUMP, TPTAG_DUMP() + * + * @NEW_1_12_5 */ #define TPTAG_LOG(x) tptag_log, tag_bool_v((x)) @@ -415,6 +419,8 @@ TPORT_DLL extern tag_typedef_t tptag_dump; * nth_engine_create(), or initial nth_site_create(). * * @sa #TPORT_DUMP, TPTAG_LOG(). + * + * @NEW_1_12_5 */ #define TPTAG_DUMP(x) tptag_dump, tag_str_v((x)) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c index b9e9e31b41..a70bdcc43e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c @@ -381,7 +381,7 @@ static void tp_test_error(tp_test_t *tt, { tt->tt_status = -1; fprintf(stderr, "tp_test_error(%p): error %d (%s) from %s\n", - tp, errcode, su_strerror(errcode), + (void *)tp, errcode, su_strerror(errcode), remote ? remote : ""); } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c index fae8bf459f..f46bc6f194 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport.c @@ -292,7 +292,7 @@ int tport_is_connected(tport_t const *self) } /** MTU for transport */ -static inline usize_t tport_mtu(tport_t const *self) +static inline unsigned tport_mtu(tport_t const *self) { return self->tp_params->tpp_mtu; } @@ -453,7 +453,7 @@ tport_t *tport_tcreate(tp_stack_t *stack, if (!mr) return NULL; - SU_DEBUG_7(("%s(): %p\n", "tport_create", mr)); + SU_DEBUG_7(("%s(): %p\n", "tport_create", (void *)mr)); mr->mr_stack = stack; mr->mr_tpac = tpac; @@ -492,7 +492,9 @@ tport_t *tport_tcreate(tp_stack_t *stack, if (tick < 200) tick = 200; +#if HAVE_SOFIA_STUN tport_init_stun_server(mr, ta_args(ta)); +#endif mr->mr_timer = su_timer_create(su_root_task(root), tick); su_timer_set(mr->mr_timer, tport_tick, mr); @@ -516,7 +518,7 @@ void tport_destroy(tport_t *self) /* tpac_address */ NULL }}; - SU_DEBUG_7(("%s(%p)\n", __func__, self)); + SU_DEBUG_7(("%s(%p)\n", __func__, (void *)self)); if (self == NULL) return; @@ -531,7 +533,9 @@ void tport_destroy(tport_t *self) while (mr->mr_primaries) tport_zap_primary(mr->mr_primaries); +#if HAVE_SOFIA_STUN tport_deinit_stun_server(mr); +#endif if (mr->mr_dump_file) fclose(mr->mr_dump_file), mr->mr_dump_file = NULL; @@ -579,7 +583,8 @@ tport_primary_t *tport_alloc_primary(tport_master_t *mr, if (!pri->pri_public) tp->tp_addrinfo->ai_addr = &tp->tp_addr->su_sa; - SU_DEBUG_5(("%s(%p): new primary tport %p\n", __func__, mr, pri)); + SU_DEBUG_5(("%s(%p): new primary tport %p\n", __func__, (void *)mr, + (void *)pri)); } *next = pri; @@ -706,7 +711,7 @@ tport_primary_t *tport_listen(tport_master_t *mr, pri->pri_primary->tp_has_connection = 0; SU_DEBUG_5(("%s(%p): %s " TPN_FORMAT "\n", - __func__, pri, "listening at", + __func__, (void *)pri, "listening at", TPN_ARGS(pri->pri_primary->tp_name))); return pri; @@ -778,8 +783,8 @@ int tport_set_events(tport_t *self, int set, int clear) if (self->tp_pri->pri_vtable->vtp_set_events) return self->tp_pri->pri_vtable->vtp_set_events(self); - - SU_DEBUG_7(("tport_set_events(%p): events%s%s%s\n", self, + + SU_DEBUG_7(("tport_set_events(%p): events%s%s%s\n", (void *)self, (events & SU_WAIT_IN) ? " IN" : "", (events & SU_WAIT_OUT) ? " OUT" : "", SU_WAIT_CONNECT != SU_WAIT_OUT && @@ -818,7 +823,7 @@ tport_t *tport_alloc_secondary(tport_primary_t *pri, self = su_home_clone(mr->mr_home, pri->pri_vtable->vtp_secondary_size); if (self) { - SU_DEBUG_7(("%s(%p): new secondary tport %p\n", __func__, pri, self)); + SU_DEBUG_7(("%s(%p): new secondary tport %p\n", __func__, (void *)pri, (void *)self)); self->tp_refs = -1; /* Freshly allocated */ self->tp_master = mr; @@ -917,8 +922,8 @@ tport_t *tport_base_connect(tport_primary_t *pri, su_wait_destroy(wait), \ (SU_LOG_LEVEL >= errlevel ? \ su_llog(tport_log, errlevel, \ - "%s(%p): %s(pf=%d %s/%s): %s\n", \ - __func__, pri, #what, ai->ai_family, \ + "%s(%p): %s(pf=%d %s/%s): %s\n", \ + __func__, (void *)pri, #what, ai->ai_family, \ tpn->tpn_proto, \ tport_hostport(buf, sizeof(buf), \ (void *)ai->ai_addr, 2), \ @@ -983,11 +988,11 @@ tport_t *tport_base_connect(tport_primary_t *pri, if (ai == real_ai) { SU_DEBUG_5(("%s(%p): %s to " TPN_FORMAT "\n", - __func__, self, what, TPN_ARGS(self->tp_name))); + __func__, (void *)self, what, TPN_ARGS(self->tp_name))); } else { SU_DEBUG_5(("%s(%p): %s via %s to " TPN_FORMAT "\n", - __func__, self, what, + __func__, (void *)self, what, tport_hostport(buf, sizeof(buf), (void *)ai->ai_addr, 2), TPN_ARGS(self->tp_name))); } @@ -1016,7 +1021,7 @@ void tport_zap_secondary(tport_t *self) if (self->tp_msg) { msg_destroy(self->tp_msg), self->tp_msg = NULL; SU_DEBUG_3(("%s(%p): zapped partially received message\n", - __func__, self)); + __func__, (void *)self)); } if (self->tp_queue && self->tp_queue[self->tp_qhead]) { @@ -1026,16 +1031,18 @@ void tport_zap_secondary(tport_t *self) n++; } SU_DEBUG_3(("%s(%p): zapped %lu queued messages\n", - __func__, self, (LU)n)); + __func__, (void *)self, (LU)n)); } if (self->tp_pused) { - SU_DEBUG_3(("%s(%p): zapped with pending requests\n", __func__, self)); + SU_DEBUG_3(("%s(%p): zapped with pending requests\n", __func__, (void *)self)); } mr = self->tp_master; +#if HAVE_SOFIA_STUN tport_stun_server_remove_socket(self); +#endif if (self->tp_index) su_root_deregister(mr->mr_root, self->tp_index); @@ -1226,7 +1233,9 @@ extern tport_vtable_t const tport_threadpool_vtable; tport_vtable_t const *tport_vtables[TPORT_NUMBER_OF_TYPES + 1] = { +#if HAVE_SOFIA_NTH &tport_http_connect_vtable, +#endif #if HAVE_TLS &tport_tls_client_vtable, &tport_tls_vtable, @@ -1294,7 +1303,9 @@ tport_set_f const *tport_set_methods[TPORT_NUMBER_OF_TYPES + 1] = tport_server_bind_set, tport_client_bind_set, tport_threadpool_set, +#if HAVE_SOFIA_NTH tport_http_connect_set, +#endif #if HAVE_TLS tport_tls_set, #endif @@ -1406,8 +1417,8 @@ int tport_bind_client(tport_master_t *mr, if (public == tport_type_local) public = tport_type_client; - - SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, mr, TPN_ARGS(tpn))); + + SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, (void *)mr, TPN_ARGS(tpn))); memset(tpn0, 0, sizeof(tpn0)); @@ -1466,8 +1477,8 @@ int tport_bind_server(tport_master_t *mr, unsigned short step = 0; bind6only_check(mr); - - SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, mr, TPN_ARGS(tpn))); + + SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, (void *)mr, TPN_ARGS(tpn))); if (tpn->tpn_host == NULL || strcmp(tpn->tpn_host, tpn_any) == 0) { /* Use a local IP address */ @@ -1535,7 +1546,7 @@ int tport_bind_server(tport_master_t *mr, tpname->tpn_host = host; SU_DEBUG_9(("%s(%p): calling tport_listen for %s\n", - __func__, mr, ai->ai_canonname)); + __func__, (void *)mr, ai->ai_canonname)); pri = tport_listen(mr, vtable, tpname, ainfo, tags); if (!pri) { @@ -1582,7 +1593,7 @@ int tport_bind_server(tport_master_t *mr, break; SU_DEBUG_3(("%s(%p): cannot bind all transports to port %u, trying %u\n", - __func__, mr, old, port)); + __func__, (void *)mr, old, port)); } tport_freeaddrinfo(res); @@ -1687,7 +1698,7 @@ int tport_server_addrinfo(tport_master_t *mr, int error = tport_getaddrinfo(host, service, hints, return_addrinfo); if (error || !*return_addrinfo) { SU_DEBUG_3(("%s(%p): su_getaddrinfo(%s, %s) for %s: %s\n", - __func__, mr, host ? host : "\"\"", service, protocol, + __func__, (void *)mr, host ? host : "\"\"", service, protocol, su_gai_strerror(error))); return su_seterrno(error != EAI_MEMORY ? ENOENT : ENOMEM); } @@ -1738,13 +1749,13 @@ tport_get_local_addrinfo(tport_master_t *mr, if (error) { #if SU_HAVE_IN6 SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", - __func__, mr, + __func__, (void *)mr, family == AF_INET6 ? "ip6" : family == AF_INET ? "ip4" : "ip", su_gli_strerror(error))); #else SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", - __func__, mr, + __func__, (void *)mr, family == AF_INET ? "ip4" : "ip", su_gli_strerror(error))); #endif @@ -1941,7 +1952,7 @@ int tport_addrinfo_copy(su_addrinfo_t *dst, void *addr, socklen_t addrlen, */ void tport_close(tport_t *self) { - SU_DEBUG_5(("%s(%p): " TPN_FORMAT "\n", "tport_close", self, + SU_DEBUG_5(("%s(%p): " TPN_FORMAT "\n", "tport_close", (void *)self, TPN_ARGS(self->tp_name))); self->tp_closed = 1; @@ -1990,8 +2001,8 @@ int tport_shutdown(tport_t *self, int how) { if (!tport_is_secondary(self)) return -1; - - SU_DEBUG_7(("%s(%p, %d)\n", "tport_shutdown", self, how)); + + SU_DEBUG_7(("%s(%p, %d)\n", "tport_shutdown", (void *)self, how)); if (!tport_is_tcp(self) || how < 0 || @@ -2057,7 +2068,7 @@ void tport_tick(su_root_magic_t *magic, su_timer_t *t, tport_master_t *mr) tp_next = tprb_succ(tp); if (tp->tp_queue && tp->tp_queue[tp->tp_qhead]) { SU_DEBUG_9(("tport_tick(%p) - trying to send to %s/%s:%s\n", - tp, tp->tp_protoname, tp->tp_host, tp->tp_port)); + (void *)tp, tp->tp_protoname, tp->tp_host, tp->tp_port)); tport_send_queue(tp); } } @@ -2073,7 +2084,7 @@ void tport_tick(su_root_magic_t *magic, su_timer_t *t, tport_master_t *mr) (int)tp->tp_params->tpp_timeout < ts - (int)tp->tp_time && !msg_is_streaming(msg)) { SU_DEBUG_5(("tport_tick(%p): incomplete message idle for %d ms\n", - tp, ts - (int)tp->tp_time)); + (void *)tp, ts - (int)tp->tp_time)); msg_set_streaming(msg, 0); msg_set_flags(msg, MSG_FLG_ERROR | MSG_FLG_TRUNC | MSG_FLG_TIMEOUT); tport_deliver(tp, msg, NULL, NULL, now); @@ -2094,10 +2105,10 @@ void tport_tick(su_root_magic_t *magic, su_timer_t *t, tport_master_t *mr) } if (closed) { - SU_DEBUG_5(("tport_tick(%p): closed, zapping\n", tp)); + SU_DEBUG_5(("tport_tick(%p): closed, zapping\n", (void *)tp)); } else { SU_DEBUG_5(("tport_tick(%p): unused for %d ms, closing and zapping\n", - tp, ts - (int)tp->tp_time)); + (void *)tp, ts - (int)tp->tp_time)); if (!tport_is_closed(tp)) tport_close(tp); } @@ -2125,7 +2136,7 @@ int tport_flush(tport_t *tp) continue; SU_DEBUG_1(("tport_flush(%p): %szapping\n", - tp, tport_is_closed(tp) ? "" : "closing and ")); + (void *)tp, tport_is_closed(tp) ? "" : "closing and ")); if (!tport_is_closed(tp)) tport_close(tp); tport_zap_secondary(tp); @@ -2364,10 +2375,10 @@ void tport_error_report(tport_t *self, int errcode, } else { if (tport_is_primary(self)) - SU_DEBUG_3(("%s(%p): %s (with %s)\n", __func__, self, + SU_DEBUG_3(("%s(%p): %s (with %s)\n", __func__, (void *)self, errmsg, self->tp_protoname)); else - SU_DEBUG_3(("%s(%p): %s (with %s/%s:%s)\n", __func__, self, + SU_DEBUG_3(("%s(%p): %s (with %s/%s:%s)\n", __func__, (void *)self, errmsg, self->tp_protoname, self->tp_host, self->tp_port)); } @@ -2433,7 +2444,7 @@ int tport_accept(tport_primary_t *pri, int events) if (tport_setname(self, pri->pri_protoname, ai, NULL) != -1) { SU_DEBUG_5(("%s(%p): new connection from " TPN_FORMAT "\n", - __func__, self, TPN_ARGS(self->tp_name))); + __func__, (void *)self, TPN_ARGS(self->tp_name))); tprb_append(&pri->pri_secondary, self); @@ -2486,8 +2497,8 @@ static int tport_connected(su_root_magic_t *magic, su_wait_t *w, tport_t *self) su_wait_t wait[1] = { SU_WAIT_INIT }; int error; - - SU_DEBUG_7(("tport_connected(%p): events%s%s\n", self, + + SU_DEBUG_7(("tport_connected(%p): events%s%s\n", (void *)self, events & SU_WAIT_CONNECT ? " CONNECTED" : "", events & SU_WAIT_ERR ? " ERR" : "")); @@ -2512,7 +2523,7 @@ static int tport_connected(su_root_magic_t *magic, su_wait_t *w, tport_t *self) su_root_deregister(mr->mr_root, self->tp_index); self->tp_index = -1; - self->tp_events = SU_WAIT_IN | SU_WAIT_ERR; + self->tp_events = SU_WAIT_IN | SU_WAIT_ERR | SU_WAIT_HUP; if (su_wait_create(wait, self->tp_socket, self->tp_events) == -1 || (self->tp_index = su_root_register(mr->mr_root, wait, tport_wakeup, self, 0)) @@ -2537,7 +2548,7 @@ static int tport_wakeup_pri(su_root_magic_t *m, su_wait_t *w, tport_t *self) #endif SU_DEBUG_7(("%s(%p): events%s%s%s%s%s%s\n", - "tport_wakeup_pri", self, + "tport_wakeup_pri", (void *)self, events & SU_WAIT_IN ? " IN" : "", SU_WAIT_ACCEPT != SU_WAIT_IN && (events & SU_WAIT_ACCEPT) ? " ACCEPT" : "", @@ -2563,7 +2574,7 @@ static int tport_wakeup(su_root_magic_t *magic, su_wait_t *w, tport_t *self) #endif SU_DEBUG_7(("%s(%p): events%s%s%s%s%s\n", - "tport_wakeup", self, + "tport_wakeup", (void *)self, events & SU_WAIT_IN ? " IN" : "", events & SU_WAIT_OUT ? " OUT" : "", events & SU_WAIT_HUP ? " HUP" : "", @@ -2617,7 +2628,7 @@ int tport_continue(tport_t *self) */ void tport_hup_event(tport_t *self) { - SU_DEBUG_7(("%s(%p)\n", __func__, self)); + SU_DEBUG_7(("%s(%p)\n", __func__, (void *)self)); if (self->tp_msg) { su_time_t now = su_now(); @@ -2650,8 +2661,8 @@ void tport_recv_event(tport_t *self) { su_time_t now; int again; - - SU_DEBUG_7(("%s(%p)\n", "tport_recv_event", self)); + + SU_DEBUG_7(("%s(%p)\n", "tport_recv_event", (void *)self)); do { now = su_now(); @@ -2661,8 +2672,10 @@ void tport_recv_event(tport_t *self) self->tp_time = su_time_ms(now); +#if HAVE_SOFIA_STUN if (again == 3) /* STUN keepalive */ return; +#endif if (again < 0) { int error = su_errno(); @@ -2718,7 +2731,7 @@ static void tport_parse(tport_t *self, int complete, su_time_t now) if (msg_get_flags(msg, MSG_FLG_TOOLARGE)) SU_DEBUG_3(("%s(%p): too large message from " TPN_FORMAT "\n", - __func__, self, TPN_ARGS(self->tp_name))); + __func__, (void *)self, TPN_ARGS(self->tp_name))); /* Do not try to read anymore from this connection? */ if (tport_is_stream(self) && @@ -2806,9 +2819,9 @@ void tport_deliver(tport_t *self, SU_DEBUG_7(("%s(%p): %smsg %p ("MOD_ZU" bytes)" " from " TPN_FORMAT " next=%p\n", - __func__, self, error ? "bad " : "", - msg, (size_t)msg_size(msg), - TPN_ARGS(d->d_from), next)); + __func__, (void *)self, error ? "bad " : "", + (void *)msg, (size_t)msg_size(msg), + TPN_ARGS(d->d_from), (void *)next)); ref = tport_incref(self); @@ -2895,7 +2908,7 @@ ssize_t tport_recv_iovec(tport_t const *self, if (!(*in_out_msg = msg = tport_msg_alloc(self, N))) { SU_DEBUG_7(("%s(%p): cannot allocate msg for "MOD_ZU" bytes " "from (%s/%s:%s)\n", - __func__, self, N, + __func__, (void *)self, N, self->tp_protoname, self->tp_host, self->tp_port)); return -1; } @@ -2914,7 +2927,7 @@ ssize_t tport_recv_iovec(tport_t const *self, int err = su_errno(); SU_DEBUG_7(("%s(%p): cannot get msg %p buffer for "MOD_ZU" bytes " "from (%s/%s:%s): %s\n", - __func__, self, msg, N, + __func__, (void *)self, (void *)msg, N, self->tp_protoname, self->tp_host, self->tp_port, su_strerror(err))); su_seterrno(err); @@ -2925,8 +2938,8 @@ ssize_t tport_recv_iovec(tport_t const *self, SU_DEBUG_7(("%s(%p) msg %p from (%s/%s:%s) has "MOD_ZU" bytes, " "veclen = "MOD_ZD"\n", - __func__, self, - msg, self->tp_protoname, self->tp_host, self->tp_port, + __func__, (void *)self, + (void *)msg, self->tp_protoname, self->tp_host, self->tp_port, N, veclen)); for (i = 0; veclen > 1 && i < veclen; i++) { @@ -2977,8 +2990,9 @@ tport_t *tport_tsend(tport_t *self, } *tpn = *_tpn; - - SU_DEBUG_7(("tport_tsend(%p) tpn = " TPN_FORMAT "\n", self, TPN_ARGS(tpn))); + + SU_DEBUG_7(("tport_tsend(%p) tpn = " TPN_FORMAT "\n", + (void *)self, TPN_ARGS(tpn))); if (tport_is_master(self)) { primary = (tport_primary_t *)tport_primary_by_name(self, tpn); @@ -3030,7 +3044,7 @@ tport_t *tport_tsend(tport_t *self, if (tpn->tpn_comp) { ai->ai_flags |= TP_AI_COMPRESSED; SU_DEBUG_9(("%s: compressed msg(%p) with %s\n", - __func__, msg, tpn->tpn_comp)); + __func__, (void *)msg, tpn->tpn_comp)); } if (!tpn->tpn_comp || cc == NONE) @@ -3140,7 +3154,7 @@ int tport_prepare_and_send(tport_t *self, msg_t *msg, return -1; } - if (msg_size(msg) > (mtu ? mtu : tport_mtu(self))) { + if (msg_size(msg) > (usize_t)(mtu ? mtu : tport_mtu(self))) { msg_set_errno(msg, EMSGSIZE); return -1; } @@ -3236,9 +3250,9 @@ int tport_send_msg(tport_t *self, msg_t *msg, } else { char const *comp = tpn->tpn_comp; - + SU_DEBUG_1(("tport(%p): send truncated for %s/%s:%s%s%s\n", - self, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, + (void *)self, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp ? ";comp=" : "", comp ? comp : "")); su_seterrno(EIO); @@ -3302,9 +3316,9 @@ ssize_t tport_vsend(tport_t *self, if (tpn == NULL || tport_is_connection_oriented(self)) tpn = self->tp_name; - + SU_DEBUG_7(("tport_vsend(%p): "MOD_ZU" bytes of "MOD_ZU" to %s/%s:%s%s\n", - self, n, m, tpn->tpn_proto, tpn->tpn_host, + (void *)self, n, m, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, (ai->ai_flags & TP_AI_COMPRESSED) ? ";comp=sigcomp" : "")); } @@ -3326,7 +3340,7 @@ int tport_send_error(tport_t *self, msg_t *msg, if (su_is_blocking(error)) { SU_DEBUG_5(("tport_vsend(%p): %s with (s=%d %s/%s:%s%s)\n", - self, "EAGAIN", (int)self->tp_socket, + (void *)self, "EAGAIN", (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)); return 0; } @@ -3335,7 +3349,7 @@ int tport_send_error(tport_t *self, msg_t *msg, if (self->tp_addrinfo->ai_family == AF_INET) { SU_DEBUG_3(("tport_vsend(%p): %s with (s=%d %s/%s:%s%s)\n", - self, su_strerror(error), (int)self->tp_socket, + (void *)self, su_strerror(error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp)); } #if SU_HAVE_IN6 @@ -3343,7 +3357,7 @@ int tport_send_error(tport_t *self, msg_t *msg, su_sockaddr_t const *su = (su_sockaddr_t const *)ai->ai_addr; SU_DEBUG_3(("tport_vsend(%p): %s with " "(s=%d, IP6=%s/%s:%s%s (scope=%i) addrlen=%u)\n", - self, su_strerror(error), (int)self->tp_socket, + (void *)self, su_strerror(error), (int)self->tp_socket, tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port, comp, su->su_scope_id, (unsigned)ai->ai_addrlen)); } @@ -3351,7 +3365,7 @@ int tport_send_error(tport_t *self, msg_t *msg, else { SU_DEBUG_3(("\ttport_vsend(%p): %s with " "(s=%d, AF=%u addrlen=%u)%s\n", - self, su_strerror(error), + (void *)self, su_strerror(error), (int)self->tp_socket, ai->ai_family, (unsigned)ai->ai_addrlen, comp)); } @@ -3359,7 +3373,7 @@ int tport_send_error(tport_t *self, msg_t *msg, int i; for (i = 0; i < iovused; i++) SU_DEBUG_7(("\t\tiov[%d] = { %d bytes @ %p }\n", - i, iov[i].siv_len, iov[i].siv_base)); + i, iov[i].siv_len, (void *)iov[i].siv_base)); #endif if (tport_is_connection_oriented(self)) { @@ -3480,9 +3494,9 @@ int tport_queue(tport_t *self, msg_t *msg) { unsigned short qhead = self->tp_qhead; unsigned short N = self->tp_params->tpp_qsize; - + SU_DEBUG_7(("tport_queue(%p): queueing %p for %s/%s:%s\n", - self, msg, self->tp_protoname, self->tp_host, self->tp_port)); + (void *)self, (void *)msg, self->tp_protoname, self->tp_host, self->tp_port)); if (self->tp_queue == NULL) { assert(N > 0); @@ -3618,9 +3632,9 @@ int tport_tqsend(tport_t *self, msg_t *msg, msg_t *next, void tport_send_event(tport_t *self) { assert(tport_is_connection_oriented(self)); - + SU_DEBUG_7(("tport_send_event(%p) - ready to send to (%s/%s:%s)\n", - self, self->tp_protoname, self->tp_host, self->tp_port)); + (void *)self, self->tp_protoname, self->tp_host, self->tp_port)); tport_send_queue(self); } @@ -3847,9 +3861,9 @@ int tport_pend(tport_t *self, if (self == NULL || msg == NULL || callback == NULL || client == NULL) return -1; - + SU_DEBUG_7(("tport_pend(%p): pending %p for %s/%s:%s (already %u)\n", - self, msg, + (void *)self, (void *)msg, self->tp_protoname, self->tp_host, self->tp_port, self->tp_pused)); @@ -3904,13 +3918,13 @@ int tport_release(tport_t *self, if (pending->p_client != client || pending->p_msg != msg) { - SU_DEBUG_1(("tport_release(%p): %u %p by %p not pending\n", self, - pendd, msg, client)); + SU_DEBUG_1(("tport_release(%p): %u %p by %p not pending\n", (void *)self, + pendd, (void *)msg, (void *)client)); return su_seterrno(EINVAL), -1; } - + SU_DEBUG_7(("tport_release(%p): %p by %p with %p%s\n", - self, msg, client, reply, + (void *)self, (void *)msg, (void *)client, (void *)reply, still_pending ? " (preliminary)" : "")); /* sigcomp can here associate request (msg) with response (reply) */ @@ -4249,7 +4263,7 @@ tport_t *tport_by_name(tport_t const *self, tp_name_t const *tpn) } else { SU_DEBUG_7(("tport(%p): EXPENSIVE unresolved " TPN_FORMAT "\n", - self, TPN_ARGS(tpn))); + (void *)self, TPN_ARGS(tpn))); sub = tprb_first(sub); } @@ -4269,11 +4283,11 @@ tport_t *tport_by_name(tport_t const *self, tp_name_t const *tpn) if ((socklen_t)sub->tp_addrlen != sulen || memcmp(sub->tp_addr, su, sulen)) { SU_DEBUG_7(("tport(%p): not found by name " TPN_FORMAT "\n", - self, TPN_ARGS(tpn))); + (void *)self, TPN_ARGS(tpn))); break; } SU_DEBUG_7(("tport(%p): found %p by name " TPN_FORMAT "\n", - self, sub, TPN_ARGS(tpn))); + (void *)self, (void *)sub, TPN_ARGS(tpn))); } else if ((strcasecmp(canon, sub->tp_canon) && strcasecmp(host, sub->tp_host)) || @@ -4354,10 +4368,10 @@ tport_t *tport_by_addrinfo(tport_primary_t const *pri, if (sub) SU_DEBUG_7(("%s(%p): found %p by name " TPN_FORMAT "\n", - __func__, pri, sub, TPN_ARGS(tpn))); + __func__, (void *)pri, (void *)sub, TPN_ARGS(tpn))); else SU_DEBUG_7(("%s(%p): not found by name " TPN_FORMAT "\n", - __func__, pri, TPN_ARGS(tpn))); + __func__, (void *)pri, TPN_ARGS(tpn))); return (tport_t *)sub; } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h b/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h index a70ecc31ea..6669cb40f4 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h @@ -91,7 +91,7 @@ typedef long unsigned LU; /* for printf() and friends */ /** Transport parameters */ typedef struct { - usize_t tpp_mtu; /**< Maximum packet size */ + unsigned tpp_mtu; /**< Maximum packet size */ unsigned tpp_idle; /**< Allowed connection idle time. */ unsigned tpp_timeout; /**< Allowed idle time for message. */ unsigned tpp_sigcomp_lifetime; /**< SigComp compartment lifetime */ diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_stun.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_stun.c index 61f86aee0a..b5971497a0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_stun.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_stub_stun.c @@ -155,7 +155,7 @@ int tport_recv_stun_dgram(tport_t const *self, } else SU_DEBUG_7(("tport(%p): recv_stun_dgram(): " - "ignoring request with "MOD_ZU" bytes\n", self, n)); + "ignoring request with "MOD_ZU" bytes\n", (void *)self, n)); } else if (request[0] == 0 && self->tp_master->mr_stun_server) { tport_stun_server_vtable_t const *vst = tport_stun_server_vtable; @@ -178,7 +178,7 @@ int tport_recv_stun_dgram(tport_t const *self, elen = (elen + 3) & -4; /* Round up to 4 */ SU_DEBUG_7(("tport(%p): recv_stun_dgram(): " - "responding %u %s\n", self, status, error)); + "responding %u %s\n", (void *)self, status, error)); /* 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -237,7 +237,7 @@ int tport_recv_stun_dgram(tport_t const *self, #undef set16 } else { - SU_DEBUG_0(("tport(%p): recv_stun_dgram(): internal error\n", self)); + SU_DEBUG_0(("tport(%p): recv_stun_dgram(): internal error\n", (void *)self)); su_seterrno(EBADMSG); retval = -1; } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c index 7abebbd84f..f2a5a16e3e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c @@ -55,7 +55,10 @@ #include #include #include + +#if HAVE_SIGPIPE #include +#endif #include "tport_tls.h" @@ -162,8 +165,10 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) } } +#if HAVE_SIGPIPE /* Avoid possible SIGPIPE when sending close_notify */ signal(SIGPIPE, SIG_IGN); +#endif if (tls->bio_err == NULL) tls->bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); @@ -295,7 +300,9 @@ tls_t *tls_init_master(tls_issues_t *ti) unsigned char sessionId[32] = "sofia/tls"; tls_t *tls; +#if HAVE_SIGPIPE signal(SIGPIPE, SIG_IGN); /* Ignore spurios SIGPIPE from OpenSSL */ +#endif tls_set_default(ti); @@ -611,7 +618,7 @@ ssize_t tls_read(tls_t *tls) } if (0) - fprintf(stderr, "tls_read(%p) called on %s (events %u)\n", tls, + fprintf(stderr, "tls_read(%p) called on %s (events %u)\n", (void *)tls, tls->type == tls_slave ? "server" : "client", tls->read_events); @@ -674,7 +681,7 @@ ssize_t tls_write(tls_t *tls, void *buf, size_t size) if (0) fprintf(stderr, "tls_write(%p, %p, "MOD_ZU") called on %s\n", - tls, buf, size, + (void *)tls, buf, size, tls && tls->type == tls_slave ? "server" : "client"); if (tls == NULL || buf == NULL) { diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c index 14ec9faab1..6496c6bda0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_sctp.c @@ -37,8 +37,6 @@ #include "config.h" -#if HAVE_SCTP - #include "tport_internal.h" #if HAVE_NETINET_SCTP_H @@ -76,6 +74,8 @@ typedef struct tport_sctp_t #define TP_SCTP_MSG_MAX (65536) +#if HAVE_SCTP + static int tport_sctp_init_primary(tport_primary_t *, tp_name_t tpn[1], su_addrinfo_t *, tagi_t const *, diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c index 542af84e20..5d5d3fc742 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tcp.c @@ -230,7 +230,7 @@ int tport_recv_stream(tport_t *self) } if (N == -1) { err = su_errno(); - SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, self, + SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self, su_strerror(err), err)); return -1; } diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c index b3a0ce401f..68a651c83e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c @@ -187,7 +187,7 @@ static int tport_tls_init_master(tport_primary_t *pri, ti.CAfile = su_sprintf(autohome, "%s/%s", path, "cafile.pem"); ti.version = tls_version; - SU_DEBUG_9(("%s(%p): tls key = %s\n", __func__, pri, ti.key)); + SU_DEBUG_9(("%s(%p): tls key = %s\n", __func__, (void *)pri, ti.key)); if (ti.key && ti.CAfile && ti.randFile) { tlspri->tlspri_master = tls_init_master(&ti); @@ -271,7 +271,7 @@ int tport_tls_set_events(tport_t const *self) int mask = tls_events(tlstp->tlstp_context, self->tp_events); SU_DEBUG_7(("%s(%p): logical events%s%s real%s%s\n", - "tport_tls_set_events", self, + "tport_tls_set_events", (void *)self, (self->tp_events & SU_WAIT_IN) ? " IN" : "", (self->tp_events & SU_WAIT_OUT) ? " OUT" : "", (mask & SU_WAIT_IN) ? " IN" : "", @@ -325,7 +325,7 @@ int tport_tls_events(tport_t *self, int events) return 0; SU_DEBUG_7(("%s(%p): logical events%s%s real%s%s\n", - "tport_tls_events", self, + "tport_tls_events", (void *)self, (events & SU_WAIT_IN) ? " IN" : "", (events & SU_WAIT_OUT) ? " OUT" : "", (mask & SU_WAIT_IN) ? " IN" : "", @@ -358,7 +358,7 @@ int tport_tls_recv(tport_t *self) N = tls_read(tlstp->tlstp_context); - SU_DEBUG_7(("%s(%p): tls_read() returned "MOD_ZD"\n", __func__, self, N)); + SU_DEBUG_7(("%s(%p): tls_read() returned "MOD_ZD"\n", __func__, (void *)self, N)); if (N == 0) /* End-of-stream */ return 0; @@ -462,7 +462,7 @@ ssize_t tport_tls_send(tport_t const *self, #endif SU_DEBUG_9(("tport_tls_writevec: vec %p %p %lu ("MOD_ZD")\n", - tlstp->tlstp_context, iov[i].siv_base, (LU)iov[i].siv_len, + (void *)tlstp->tlstp_context, (void *)iov[i].siv_base, (LU)iov[i].siv_len, nerror)); if (nerror == -1) { diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c index b513b79991..5dc6b9066f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c @@ -166,7 +166,9 @@ int tport_udp_init_primary(tport_primary_t *pri, tport_check_trunc(pri->pri_primary, ai); +#if HAVE_SOFIA_STUN tport_stun_server_add_socket(pri->pri_primary); +#endif return 0; } @@ -233,7 +235,7 @@ int tport_recv_dgram(tport_t *self) if (self->tp_params->tpp_drop && (unsigned)su_randint(0, 1000) < self->tp_params->tpp_drop) { su_recv(self->tp_socket, sample, 1, 0); - SU_DEBUG_3(("tport(%p): simulated packet loss!\n", self)); + SU_DEBUG_3(("tport(%p): simulated packet loss!\n", (void *)self)); return 0; } @@ -246,7 +248,7 @@ int tport_recv_dgram(tport_t *self) N = (ssize_t)su_getmsgsize(self->tp_socket); if (N == -1) { int err = su_errno(); - SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, self, + SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self, su_strerror(err), err)); return -1; } @@ -276,7 +278,8 @@ int tport_recv_dgram(tport_t *self) return -1; } else if (n <= 1) { - SU_DEBUG_1(("%s(%p): runt of "MOD_ZD" bytes\n", "tport_recv_dgram", self, n)); + SU_DEBUG_1(("%s(%p): runt of "MOD_ZD" bytes\n", + "tport_recv_dgram", (void *)self, n)); msg_destroy(msg), self->tp_msg = NULL; return 0; } @@ -295,9 +298,11 @@ int tport_recv_dgram(tport_t *self) /* SigComp */ return tport_recv_comp_dgram(self, self->tp_comp, &self->tp_msg, from, fromlen); +#if HAVE_SOFIA_STUN else if (sample[0] == 0 || sample[0] == 1) /* STUN request or response */ return tport_recv_stun_dgram(self, &self->tp_msg, from, fromlen); +#endif else return 0; } diff --git a/libs/sofia-sip/libsofia-sip-ua/url/Makefile.am b/libs/sofia-sip/libsofia-sip-ua/url/Makefile.am index 906db1417d..a9d24abf68 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/Makefile.am +++ b/libs/sofia-sip/libsofia-sip-ua/url/Makefile.am @@ -52,6 +52,6 @@ TESTS = torture_url test_urlmap # ---------------------------------------------------------------------- # Sofia specific rules -include ../sofia.am +include $(top_srcdir)/rules/sofia.am TAG_DLL_FLAGS = DLLREF=1 diff --git a/libs/sofia-sip/libsofia-sip-ua/url/Makefile.in b/libs/sofia-sip/libsofia-sip-ua/url/Makefile.in index 17ca2a0ed2..c28dbaa47d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/Makefile.in +++ b/libs/sofia-sip/libsofia-sip-ua/url/Makefile.in @@ -24,8 +24,33 @@ # ---------------------------------------------------------------------- # Header paths -# common Makefile targets for libsofia-sip-ua modules -# --------------------------------------------------- +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. SOURCES = $(liburl_la_SOURCES) $(test_urlmap_SOURCES) torture_url.c @@ -54,8 +79,12 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ check_PROGRAMS = torture_url$(EXEEXT) test_urlmap$(EXEEXT) -DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/../sofia.am \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog +DIST_COMMON = $(nobase_include_sofia_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/sofia.am \ + $(top_srcdir)/rules/valcheck.am ChangeLog + +# Use with --enable-ndebug +@NDEBUG_TRUE@am__append_1 = -DNDEBUG subdir = libsofia-sip-ua/url ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/sac-general.m4 \ @@ -107,6 +136,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -153,8 +183,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -198,6 +232,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -284,7 +319,7 @@ EXTRA_DIST = Doxyfile url.docs $(BUILT_SOURCES) # ---------------------------------------------------------------------- # Tests TESTS = torture_url test_urlmap -AM_CFLAGS = $(CWFLAG) $(SOFIA_CFLAGS) +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(am__append_1) DISTCLEANFILES = $(BUILT_SOURCES) # rules for building tag files @@ -310,6 +345,8 @@ INTERNAL_INCLUDES = \ -I$(srcdir)/../url -I../url \ -I$(srcdir)/../su -I../su +VALGRIND = valgrind +VALGRINDFLAGS = --tool=memcheck # ---------------------------------------------------------------------- # Sofia specific rules @@ -319,7 +356,7 @@ all: $(BUILT_SOURCES) .SUFFIXES: .SUFFIXES: .c .lo .o .obj -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../sofia.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/sofia.am $(top_srcdir)/rules/valcheck.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -571,7 +608,7 @@ check-TESTS: $(TESTS) else :; fi distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/.. $(distdir)/sofia-sip + $(mkdir_p) $(distdir)/../../rules $(distdir)/sofia-sip @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ @@ -721,6 +758,92 @@ clean-built-sources: ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ ../tport/libtport.la ../url/liburl.la: $(MAKE) -C $(@D) $(@F) + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libs/sofia-sip/libsofia-sip-ua/url/torture_url.c b/libs/sofia-sip/libsofia-sip-ua/url/torture_url.c index bbd02f47db..e6b78e9ad3 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/torture_url.c +++ b/libs/sofia-sip/libsofia-sip-ua/url/torture_url.c @@ -108,7 +108,7 @@ int test_quote(void) TEST_S(url_escape(unreserved, UNRESERVED, NULL), UNRESERVED); TEST_S(url_unescape(unreserved, UNRESERVED), UNRESERVED); - d = "%73ip:%55@%68"; + d = "%53ip:%75@%48"; /* Sip:u@H */ u = url_hdup(home, (url_t *)d); TEST_1(u); url_digest(hash1, sizeof(hash1), u, NULL); url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL); @@ -125,9 +125,11 @@ int test_quote(void) d = url_as_string(home, u); TEST_1(d); TEST_S(d, c); - d = "sip:&=+$,;?/:&=+$,@host:56001;param=+$,/:@&;another=@" + d = "sip:&=+$,;?/:&=+$,@[::1]:56001;param=+$,/:@&;another=@" "?header=" RESERVED "&%3b%2f%3f%3a%40%26%3d%2b%24%2c"; u = url_hdup(home, (url_t *)d); TEST_1(u); + TEST_S(u->url_user, "&=+$,;?/"); + TEST_S(u->url_host, "[::1]"); TEST_S(u->url_headers, "header=" RESERVED "&%3B%2F%3F%3A%40%26%3D%2B%24%2C"); url_digest(hash1, sizeof(hash1), u, NULL); url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL); @@ -137,8 +139,10 @@ int test_quote(void) d = url_as_string(home, u); TEST_1(d); TEST_S(d, c); - d = "http://&=+$,;:&=+$,;@host:8080/foo;param=+$,/:@&;another=@?query=" RESERVED; + d = "http://&=+$,;:&=+$,;@host:8080/foo;param=+$,/:@&;another=@" + "?query=" RESERVED; u = url_hdup(home, (url_t *)d); TEST_1(u); + TEST_S(u->url_user, "&=+$,;"); TEST_S(u->url_password, "&=+$,;"); url_digest(hash1, sizeof(hash1), u, NULL); url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL); TEST(memcmp(hash1, hash2, sizeof(hash1)), 0); @@ -333,6 +337,13 @@ int test_sip(void) TEST_P(url_hdup(home, (url_t*)"sip:test@127.0.0.1:55:"), NULL); TEST_P(url_hdup(home, (url_t*)"sip:test@127.0.0.1:sip"), NULL); + u = url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar@127.0.0.1"); TEST_1(u); + TEST(u->url_type, url_sip); + TEST_S(u->url_user, "#**00**#;foo=/bar"); + + TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar@#127.0.0.1")); + TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar;127.0.0.1")); + for (i = 32; i <= 256; i++) { char pu[512]; char param[512]; @@ -827,6 +838,16 @@ int test_http(void) TEST_S(url->url_host, "some.host"); TEST_S(url->url_headers, "query"); TEST_S(url->url_params, NULL); + + TEST_1(u = url_hdup(home, (void *)"http://[::1]/test;ing?here")); + TEST_S(u->url_host, "[::1]"); + TEST_S(u->url_path, "test;ing"); + TEST_S(u->url_headers, "here"); + + url_digest(hash1, sizeof(hash1), u, NULL); + url_digest(hash2, sizeof(hash2), (url_t *)"http://[::1]/test;ing?here", + NULL); + TEST(memcmp(hash1, hash2, sizeof(hash1)), 0); su_home_deinit(home); diff --git a/libs/sofia-sip/libsofia-sip-ua/url/url.c b/libs/sofia-sip/libsofia-sip-ua/url/url.c index 9960f9f5b1..4bad0207a0 100644 --- a/libs/sofia-sip/libsofia-sip-ua/url/url.c +++ b/libs/sofia-sip/libsofia-sip-ua/url/url.c @@ -556,8 +556,8 @@ static int _url_d(url_t *url, char *s) { size_t n, p; - char *s0, rest_c, *host; - int net_path = 1; + char *s0, rest_c, *host, *user; + int have_authority = 1; memset(url, 0, sizeof(*url)); @@ -582,112 +582,123 @@ int _url_d(url_t *url, char *s) url->url_type = url_get_type(url->url_scheme, n); - net_path = !url_type_is_opaque(url->url_type); + have_authority = !url_type_is_opaque(url->url_type); } else { url->url_type = url_unknown; } - host = s; + user = NULL, host = s; if (url->url_type == url_sip || url->url_type == url_sips) { - /* SIP URL may have /; in user part */ - n = strcspn(s, "@#"); /* Opaque part */ - if ((p = strcspn(s, "#")) == n) { - n = strcspn(s, "@"); - if (s[n] != '@') - n = 0; - } + /* SIP URL may have /;? in user part but no path */ + /* user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */ + /* Some #*@#* phones include unescaped # there, too */ + n = strcspn(s, "@/;?#"); + p = strcspn(s + n, "@"); + if (s[n + p] == '@') { + n += p; + user = s; + host = s + n + 1; + } + n += strcspn(s + n, "/;?#"); } - else if (url->url_type == url_wv) { - /* WV URL may have / in user part */ - n = strcspn(s, "@#?;"); - if (s[n] == '@') - n += strcspn(s + n, ";?#"); - } - else if (url->url_type == url_invalid) { - n = strcspn(s, "#"); - } - else if (net_path && host[0] == '/') { - url->url_root = host[0]; /* Absolute path */ - - if (host[1] == '/') { /* We have host-part */ - host += 2; s += 2; + else if (have_authority) { + if (url->url_type == url_wv) { + /* WV URL may have / in user part */ + n = strcspn(s, "@#?;"); + if (s[n] == '@') { + user = s; + host = s + n + 1; + n += strcspn(s + n, ";?#"); + } + } + else if (host[0] == '/' && host[1] != '/') { + /* foo:/bar or /bar - no authority, just path */ + url->url_root = '/'; /* Absolute path */ + host = NULL, n = 0; + } + else { + if (host[0] == '/' && host[1] == '/') { + /* We have authority, / / foo or foo */ + host += 2; s += 2, url->url_root = '/'; + n = strcspn(s, "/?#@[]"); + } + else + n = strcspn(s, "@;/?#"); + + if (s[n] == '@') + user = host, host = user + n + 1; + + n += strcspn(s + n, ";/?#"); /* Find path, query and/or fragment */ } - else - host = NULL; - n = strcspn(s, "/;?#"); /* Find path, query and/or fragment */ } - else { - n = strcspn(s, "/;?#"); /* Find params, query and/or fragment */ + else /* !have_authority */ { + user = host, host = NULL; + if (url->url_type != url_invalid) + n = strcspn(s, "/;?#"); /* Find params, query and/or fragment */ + else + n = strcspn(s, "#"); } rest_c = s[n]; s[n] = 0; s = rest_c ? s + n + 1 : NULL; + if (user) { + if (host) host[-1] = '\0'; + url->url_user = user; + if (url->url_type != url_unknown) { + n = strcspn(user, ":"); + if (user[n]) { + user[n] = '\0'; + url->url_password = user + n + 1; + } + } + } + if (host) { - char *atsign, *port; - - if (!net_path) { - url->url_user = host; - host = NULL; + url->url_host = host; + /* IPv6 (and in some cases, IPv4) addresses are quoted with [] */ + if (host[0] == '[') { + n = strcspn(host, "]"); + if (host[n] && (host[n + 1] == '\0' || host[n + 1] == ':')) + n++; + else + n = 0; } - else if ((atsign = strchr(host, '@'))) { - char *user; - - url->url_user = user = host; - - if (atsign) - *atsign++ = '\0'; - host = atsign; - - if (url->url_type != url_unknown) { - char *colon = strchr(user, ':'); - if (colon) - *colon++ = '\0'; - url->url_password = colon; - } + else { + n = strcspn(host, ":"); } + + if (n == 0 && url->url_type != url_unknown) + return -1; - if ((url->url_host = host)) { - /* IPv6 (and in some cases, IPv4) addresses are quoted with [] */ - if (host[0] == '[') { - port = strchr(host, ']'); - if (!port) + if (host[n] == ':') { + char *port = host + n + 1; + url->url_port = port; + switch (url->url_type) { + case url_any: + case url_sip: + case url_sips: + case url_http: + case url_https: + case url_ftp: + case url_file: + case url_rtsp: + case url_rtspu: + if (!url_canonize2(port, port, SIZE_MAX, RESERVED_MASK)) return -1; - port = strchr(port + 1, ':'); - } - else - port = strchr(host, ':'); - if (port) { - *port++ = '\0'; - url->url_port = port; - switch (url->url_type) { - case url_any: - case url_sip: - case url_sips: - case url_http: - case url_https: - case url_ftp: - case url_file: - case url_rtsp: - case url_rtspu: - - if (!url_canonize2(port, port, SIZE_MAX, RESERVED_MASK)) - return -1; - - /* Check that port is really numeric or wildcard */ - /* Port can be *digit, empty string or "*" */ - while (*port >= '0' && *port <= '9') - port++; - if (port != url->url_port - ? port[0] != '\0' - : port[0] != '\0' - && (port[0] != '*' || port[1] != '\0')) - return -1; - } + /* Check that port is really numeric or wildcard */ + /* Port can be *digit, empty string or "*" */ + while (*port >= '0' && *port <= '9') + port++; + + if (port != url->url_port ? port[0] != '\0' + : (port[0] != '*' || port[1] != '\0')) + return -1; } + host[n] = 0; } } @@ -742,12 +753,15 @@ int url_d(url_t *url, char *s) if (s && !url_canonize(s, s, SIZE_MAX, SIP_USER_UNRESERVED)) return -1; + /* Having different charset in user and password does not make sense */ + /* but that is how it is defined in RFC 3261 */ # define SIP_PASS_UNRESERVED "&=+$," s = (char *)url->url_password; if (s && !url_canonize(s, s, SIZE_MAX, SIP_PASS_UNRESERVED)) return -1; - } else { + } + else { # define USER_UNRESERVED "&=+$,;" s = (char *)url->url_user; @@ -943,7 +957,7 @@ issize_t url_e(char buffer[], isize_t n, url_t const *url) } -/** Calculate the lengh of URL when encoded. +/** Calculate the length of URL when encoded. * */ isize_t url_len(url_t const * url) @@ -1889,8 +1903,8 @@ void canon_update(su_md5_t *md5, char const *s, size_t n, char const *allow) static void url_string_update(su_md5_t *md5, char const *s) { - size_t n; - int hostpart = 1; + size_t n, p; + int have_authority = 1; enum url_type_e type = url_any; char const *at, *colon; char schema[48]; @@ -1910,7 +1924,7 @@ void url_string_update(su_md5_t *md5, char const *s) type = url_get_type(schema, at - schema); su_md5_iupdate(md5, schema, at - schema); - hostpart = !url_type_is_opaque(type); + have_authority = !url_type_is_opaque(type); s += n + 1; } else { @@ -1918,62 +1932,71 @@ void url_string_update(su_md5_t *md5, char const *s) } if (type == url_sip || type == url_sips) { - n = strcspn(s, "@#"); /* Opaque part */ - if (s[n] != '@') - n = 0; + /* SIP URL may have /;? in user part but no path */ + /* user-unreserved = "&" / "=" / "+" / "$" / "," / ";" / "?" / "/" */ + /* Some #*@#* phones include unescaped # there, too */ + n = strcspn(s, "@/;?#"); + p = strcspn(s + n, "@"); + if (s[n + p] == '@') { + n += p; + /* Ignore password in hash */ + colon = memchr(s, ':', n); + p = colon ? (size_t)(colon - s) : n; + canon_update(md5, s, p, SIP_USER_UNRESERVED); + s += n + 1; n = 0; + } + else + su_md5_iupdate(md5, "", 1); /* user */ n += strcspn(s + n, "/;?#"); } - else if (type == url_wv) { /* WV URL may have / in user part */ - n = strcspn(s, "@#?;"); - if (s[n] == '@') - n += strcspn(s + n, ";?#"); + else if (have_authority) { + if (type == url_wv) { /* WV URL may have / in user part */ + n = strcspn(s, "@;?#"); + } + else if (type != url_wv && s[0] == '/' && s[1] != '/') { + /* foo:/bar */ + su_md5_update(md5, "\0\0", 2); /* user, host */ + su_md5_striupdate(md5, url_port_default(type)); + return; + } + else if (s[0] == '/' && s[1] == '/') { + /* We have authority, / / foo or foo */ + s += 2; + n = strcspn(s, "/?#@[]"); + } + else + n = strcspn(s, "@;/?#"); + + if (s[n] == '@') { + /* Ignore password in hash */ + colon = type != url_unknown ? memchr(s, ':', n) : NULL; + p = colon ? (size_t)(colon - s) : n; + canon_update(md5, s, p, SIP_USER_UNRESERVED); + s += n + 1; + n = strcspn(s, "/;?#"); /* Until path, query or fragment */ + } + else { + su_md5_iupdate(md5, "", 1); /* user */ + n += strcspn(s + n, "/;?#"); /* Until path, query or fragment */ + } } - else if (!hostpart || s[0] != '/') { - n = strcspn(s, "/;?#"); /* Opaque part */ - } - else if (s[1] == '/') { - s += 2; - n = strcspn(s, "/;?#"); /* Until host, path, query or fragment */ - } - else { - /* foo:/bar */ - su_md5_update(md5, "\0\0", 2); /* user, host */ - su_md5_striupdate(md5, url_port_default(type)); - return; - } - - if (!hostpart) { - char const *colon = memchr(s, ':', n); + else /* if (!have_authority) */ { + n = strcspn(s, ":/;?#"); /* Until pass, path, query or fragment */ - if (colon) n = colon - s; canon_update(md5, s, n, ""); /* user */ su_md5_update(md5, "\0", 1); /* host, no port */ su_md5_striupdate(md5, url_port_default(type)); return; } - at = memchr(s, '@', n); - - if (at) { - char const *allow = - (type == url_sip || type == url_sips) - ? SIP_USER_UNRESERVED - : USER_UNRESERVED; - - colon = type == url_unknown ? NULL : memchr(s, ':', at - s); - - /* Updated only user part */ - if (colon) - canon_update(md5, s, colon - s, allow); - else - canon_update(md5, s, at - s, allow); - n = n - (at + 1 - s); - s = at + 1; + if (n > 0 && s[0] == '[') { /* IPv6reference */ + colon = memchr(s, ']', n); + if (colon == NULL || ++colon == s + n || *colon != ':') + colon = NULL; } - else - su_md5_iupdate(md5, "", 1); /* user */ + else + colon = memchr(s, ':', n); - colon = memchr(s, ':', n); /* XXX - IPv6! */ if (colon) { canon_update(md5, s, colon - s, ""); /* host */ canon_update(md5, colon + 1, (s + n) - (colon + 1), ""); diff --git a/libs/sofia-sip/ltmain.sh b/libs/sofia-sip/ltmain.sh index 23f82e3b79..06823e057a 100755 --- a/libs/sofia-sip/ltmain.sh +++ b/libs/sofia-sip/ltmain.sh @@ -1,7 +1,7 @@ # ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # @@ -17,7 +17,7 @@ # # 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. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,9 +33,6 @@ basename="s,^.*/,,g" # function. progpath="$0" -# RH: define SED for historic ltconfig's generated by Libtool 1.3 -[ -z "$SED" ] && SED=sed - # The name of this program: progname=`echo "$progpath" | $SED $basename` modename="$progname" @@ -46,9 +43,14 @@ EXIT_FAILURE=1 PROGRAM=ltmain.sh PACKAGE=libtool -VERSION=1.5.6 -TIMESTAMP=" (1.1220.2.95 2004/04/11 05:50:42)" +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi # Check that we have a working $echo. if test "X$1" = X--no-reexec; then @@ -86,14 +88,15 @@ rm="rm -f" Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' # test EBCDIC or ASCII -case `echo A|tr A '\301'` in - A) # EBCDIC based system - SP2NL="tr '\100' '\n'" - NL2SP="tr '\r\n' '\100\100'" +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + SP2NL='tr \040 \012' + NL2SP='tr \015\012 \040\040' ;; - *) # Assume ASCII based system - SP2NL="tr '\040' '\012'" - NL2SP="tr '\015\012' '\040\040'" + *) # EBCDIC based system + SP2NL='tr \100 \n' + NL2SP='tr \r\n \100\100' ;; esac @@ -110,8 +113,9 @@ if test "${LANG+set}" = set; then fi # Make sure IFS has a sensible default -: ${IFS=" -"} +lt_nl=' +' +IFS=" $lt_nl" if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then $echo "$modename: not configured to build any kind of library" 1>&2 @@ -128,6 +132,8 @@ run= show="$echo" show_help= execute_dlfiles= +duplicate_deps=no +preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" @@ -135,13 +141,51 @@ o2lo="s/\\.${objext}\$/.lo/" # Shell function definitions: # This seems to be the best place for them +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. -func_win32_libid () { +func_win32_libid () +{ win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in @@ -152,12 +196,11 @@ func_win32_libid () { if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ - sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` - if test "X$win32_nmres" = "Ximport" ; then - win32_libid_type="x86 archive import" - else - win32_libid_type="x86 archive static" - fi + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac fi ;; *DLL*) @@ -181,7 +224,8 @@ func_win32_libid () { # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' -func_infer_tag () { +func_infer_tag () +{ if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do @@ -238,12 +282,116 @@ func_infer_tag () { esac fi } + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} # End of Shell function definitions ##################################### # Darwin sucks eval std_shrext=\"$shrext_cmds\" +disable_libs=no + # Parse our command line options once, thoroughly. while test "$#" -gt 0 do @@ -308,10 +456,10 @@ do --version) $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" $echo - $echo "Copyright (C) 2003 Free Software Foundation, Inc." + $echo "Copyright (C) 2005 Free Software Foundation, Inc." $echo "This is free software; see the source for copying conditions. There is NO" $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - exit $EXIT_SUCCESS + exit $? ;; --config) @@ -320,7 +468,7 @@ do for tagname in $taglist; do ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" done - exit $EXIT_SUCCESS + exit $? ;; --debug) @@ -345,7 +493,7 @@ do else $echo "disable static libraries" fi - exit $EXIT_SUCCESS + exit $? ;; --finish) mode="finish" ;; @@ -360,7 +508,11 @@ do preserve_args="$preserve_args $arg" ;; - --tag) prevopt="--tag" prev=tag ;; + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; --tag=*) set tag "$optarg" ${1+"$@"} shift @@ -392,6 +544,18 @@ if test -n "$prevopt"; then exit $EXIT_FAILURE fi +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. @@ -402,7 +566,7 @@ if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 - $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 case $nonopt in *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) mode=link @@ -468,7 +632,7 @@ if test -z "$show_help"; then for arg do - case "$arg_mode" in + case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" @@ -550,7 +714,10 @@ if test -z "$show_help"; then case $lastarg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; @@ -624,6 +791,14 @@ if test -z "$show_help"; then esac done + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then @@ -696,12 +871,17 @@ compiler." $run $rm $removelist exit $EXIT_FAILURE fi - $echo $srcfile > "$lockfile" + $echo "$srcfile" > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac $run $rm "$libobj" "${libobj}T" @@ -723,18 +903,18 @@ EOF fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then - command="$base_compile $srcfile $pic_flag" + command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code - command="$base_compile $srcfile" + command="$base_compile $qsrcfile" fi if test ! -d "${xdir}$objdir"; then $show "$mkdir ${xdir}$objdir" $run $mkdir ${xdir}$objdir - status=$? - if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then - exit $status + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then + exit $exit_status fi fi @@ -806,9 +986,9 @@ EOF if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code - command="$base_compile $srcfile" + command="$base_compile $qsrcfile" else - command="$base_compile $srcfile $pic_flag" + command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" @@ -937,6 +1117,7 @@ EOF no_install=no objs= non_pic_objects= + notinst_path= # paths that contain not-installed libtool libraries precious_files_regex= prefer_static_libs=no preload=no @@ -965,14 +1146,15 @@ EOF if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi + prefer_static_libs=yes else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi + prefer_static_libs=built fi build_libtool_libs=no build_old_libs=yes - prefer_static_libs=yes break ;; esac @@ -1147,6 +1329,11 @@ EOF if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. @@ -1230,6 +1417,13 @@ EOF prev= continue ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; *) eval "$prev=\"\$arg\"" prev= @@ -1288,6 +1482,18 @@ EOF continue ;; + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + -inst-prefix-dir) prev=inst_prefix continue @@ -1314,7 +1520,8 @@ EOF absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 - exit $EXIT_FAILURE + absdir="$dir" + notinst_path="$notinst_path $dir" fi dir="$absdir" ;; @@ -1328,10 +1535,15 @@ EOF esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac ;; esac continue @@ -1340,15 +1552,15 @@ EOF -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in - *-*-cygwin* | *-*-pw32* | *-*-beos*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; - *-*-mingw* | *-*-os2*) + *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; - *-*-openbsd* | *-*-freebsd*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; @@ -1356,10 +1568,19 @@ EOF # Rhapsody C and math libraries are in the System framework deplibs="$deplibs -framework System" continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; esac elif test "X$arg" = "X-lc_r"; then case $host in - *-*-openbsd* | *-*-freebsd*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; @@ -1369,8 +1590,20 @@ EOF continue ;; + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) - deplibs="$deplibs $arg" + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" continue ;; @@ -1379,13 +1612,19 @@ EOF continue ;; - # gcc -m* arguments should be passed to the linker via $compiler_flags - # in order to pass architecture information to the linker - # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo - # but this is not reliable with gcc because gcc may use -mfoo to - # select a different linker, different libraries, etc, while - # -Wl,-mfoo simply passes -mfoo to the linker. - -m*) + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` @@ -1396,9 +1635,7 @@ EOF esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" - if test "$with_gcc" = "yes" ; then - compiler_flags="$compiler_flags $arg" - fi + compiler_flags="$compiler_flags $arg" continue ;; @@ -1636,6 +1873,11 @@ EOF if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" fi else # Only an error if not doing a dry-run. @@ -1741,9 +1983,9 @@ EOF if test ! -d "$output_objdir"; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir - status=$? - if test "$status" -ne 0 && test ! -d "$output_objdir"; then - exit $status + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status fi fi @@ -1806,7 +2048,6 @@ EOF newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries - notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" @@ -1858,7 +2099,7 @@ EOF compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else - deplibs="$deplib $deplibs" + compiler_flags="$compiler_flags $deplib" fi continue ;; @@ -1867,10 +2108,6 @@ EOF $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 continue fi - if test "$pass" = conv; then - deplibs="$deplib $deplibs" - continue - fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do for search_ext in .la $std_shrext .so .a; do @@ -1981,7 +2218,22 @@ EOF fi case $linkmode in lib) - if test "$deplibs_check_method" != pass_all; then + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then $echo $echo "*** Warning: Trying to link with static lib archive $deplib." $echo "*** I have the capability to make that library automatically link in when" @@ -2031,7 +2283,7 @@ EOF esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else - $echo "$modename: cannot find the library \`$lib'" 1>&2 + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 exit $EXIT_FAILURE fi @@ -2055,6 +2307,8 @@ EOF # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no + avoidtemprpath= + # Read the .la file case $lib in @@ -2153,11 +2407,19 @@ EOF dir="$libdir" absdir="$libdir" fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else - dir="$ladir/$objdir" - absdir="$abs_ladir/$objdir" - # Remove this search path later - notinst_path="$notinst_path $abs_ladir" + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` @@ -2230,12 +2492,12 @@ EOF if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # We need to hardcode the library path - if test -n "$shlibpath_var"; then + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; - *) temp_rpath="$temp_rpath $dir" ;; + *) temp_rpath="$temp_rpath $absdir" ;; esac fi @@ -2272,8 +2534,12 @@ EOF fi link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi if test -n "$library_names" && - { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + { test "$use_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes @@ -2386,11 +2652,15 @@ EOF if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in - *-*-sco3.2v5* ) add_dir="-L$dir" ;; + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a module then we can not link against # it, someone is ignoring the new warnings I added - if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then $echo "** Warning, lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $echo @@ -2421,7 +2691,7 @@ EOF add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then - case "$libdir" in + case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; @@ -2494,7 +2764,7 @@ EOF add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then - case "$libdir" in + case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; @@ -2555,8 +2825,6 @@ EOF fi fi else - convenience="$convenience $dir/$old_library" - old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi @@ -2674,12 +2942,12 @@ EOF *) continue ;; esac case " $deplibs " in - *" $depdepl "*) ;; - *) deplibs="$depdepl $deplibs" ;; + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; esac case " $deplibs " in - *" $path "*) ;; - *) deplibs="$deplibs $path" ;; + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; esac done fi # link_all_deplibs != no @@ -2944,27 +3212,27 @@ EOF # Check that each of the things are valid numbers. case $current in - [0-9]*) ;; + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $revision in - [0-9]*) ;; + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; esac case $age in - [0-9]*) ;; + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) - $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit $EXIT_FAILURE ;; @@ -2990,7 +3258,7 @@ EOF versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` - verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" ;; freebsd-aout) @@ -3143,9 +3411,9 @@ EOF # Eliminate all temporary directories. for path in $notinst_path; do - lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'` - deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'` - dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` done if test -n "$xrpath"; then @@ -3196,9 +3464,14 @@ EOF *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; - *-*-openbsd* | *-*-freebsd*) + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. - test "X$arg" = "X-lc" && continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. @@ -3242,11 +3515,11 @@ EOF int main() { return 0; } EOF $rm conftest - $LTCC -o conftest conftest.c $deplibs + $LTCC $LTCFLAGS -o conftest conftest.c $deplibs if test "$?" -eq 0 ; then ldd_output=`ldd conftest` for i in $deplibs; do - name="`expr $i : '-l\(.*\)'`" + name=`expr $i : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" -ne "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3283,11 +3556,11 @@ EOF # Error occurred in the first compile. Let's try to salvage # the situation: Compile a separate program for each library. for i in $deplibs; do - name="`expr $i : '-l\(.*\)'`" + name=`expr $i : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" != "0"; then $rm conftest - $LTCC -o conftest conftest.c $i + $LTCC $LTCFLAGS -o conftest conftest.c $i # Did it work? if test "$?" -eq 0 ; then ldd_output=`ldd conftest` @@ -3335,7 +3608,7 @@ EOF set dummy $deplibs_check_method file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do - name="`expr $a_deplib : '-l\(.*\)'`" + name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test "$name" != "" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3404,7 +3677,7 @@ EOF set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do - name="`expr $a_deplib : '-l\(.*\)'`" + name=`expr $a_deplib : '-l\(.*\)'` # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then @@ -3534,6 +3807,35 @@ EOF deplibs=$newdeplibs fi + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). library_names= old_library= @@ -3617,6 +3919,7 @@ EOF fi lib="$output_objdir/$realname" + linknames= for link do linknames="$linknames $link" @@ -3645,6 +3948,9 @@ EOF # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break fi done IFS="$save_ifs" @@ -3678,67 +3984,13 @@ EOF eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" fi fi - + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" @@ -3768,7 +4020,8 @@ EOF fi fi - if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` && + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else @@ -3787,6 +4040,7 @@ EOF save_libobjs=$libobjs fi save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. @@ -3796,13 +4050,13 @@ EOF delfiles= last_robj= k=1 - output=$output_objdir/$save_output-${k}.$objext + output=$output_objdir/$output_la-${k}.$objext # Loop over the list of objects to be linked. for obj in $save_libobjs do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || - { len=`expr "X$test_cmds" : ".*"` && + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else @@ -3816,9 +4070,9 @@ EOF # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi - last_robj=$output_objdir/$save_output-${k}.$objext + last_robj=$output_objdir/$output_la-${k}.$objext k=`expr $k + 1` - output=$output_objdir/$save_output-${k}.$objext + output=$output_objdir/$output_la-${k}.$objext objlist=$obj len=1 fi @@ -3838,13 +4092,13 @@ EOF eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" fi - # Set up a command to remove the reloadale object files + # Set up a command to remove the reloadable object files # after they are used. i=0 while test "$i" -lt "$k" do i=`expr $i + 1` - delfiles="$delfiles $output_objdir/$save_output-${i}.$objext" + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" done $echo "creating a temporary reloadable object file: $output" @@ -3892,13 +4146,30 @@ EOF IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" - $run eval "$cmd" || exit $? + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + exit $EXIT_SUCCESS fi @@ -3976,64 +4247,10 @@ EOF eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - for xlib in $convenience; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi @@ -4134,6 +4351,35 @@ EOF ;; esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" @@ -4178,10 +4424,15 @@ EOF fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac ;; esac done @@ -4295,13 +4546,25 @@ extern \"C\" { # Prepare the list of exported symbols if test -z "$export_symbols"; then - export_symbols="$output_objdir/$output.exp" + export_symbols="$output_objdir/$outputname.exp" $run $rm $export_symbols - $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac else - $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' - $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac fi fi @@ -4352,7 +4615,26 @@ extern \"C\" { #endif /* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ const char *name; lt_ptr address; } @@ -4399,16 +4681,29 @@ static const void *lt_preloaded_setup() { esac # Now compile the dynamic symbol file. - $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" - $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. - compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` - finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 @@ -4433,7 +4728,7 @@ static const void *lt_preloaded_setup() { # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" - status=$? + exit_status=$? # Delete the generated files. if test -n "$dlsyms"; then @@ -4441,7 +4736,7 @@ static const void *lt_preloaded_setup() { $run $rm "$output_objdir/${outputname}S.${objext}" fi - exit $status + exit $exit_status fi if test -n "$shlibpath_var"; then @@ -4581,10 +4876,12 @@ static const void *lt_preloaded_setup() { esac case $host in *cygwin* | *mingw* ) - cwrappersource=`$echo ${objdir}/lt-${output}.c` - cwrapper=`$echo ${output}.exe` - $rm $cwrappersource $cwrapper - trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 cat > $cwrappersource < #include #include +#include +#include +#include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX @@ -4619,15 +4919,19 @@ EOF #endif #ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) -#define HAVE_DOS_BASED_FILE_SYSTEM -#ifndef DIR_SEPARATOR_2 -#define DIR_SEPARATOR_2 '\\' -#endif +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif #endif #ifndef DIR_SEPARATOR_2 @@ -4637,17 +4941,32 @@ EOF (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + const char *program_name = NULL; void * xmalloc (size_t num); char * xstrdup (const char *string); -char * basename (const char *name); -char * fnqualify(const char *path); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); char * strendzap(char *str, const char *pat); void lt_fatal (const char *message, ...); @@ -4657,29 +4976,51 @@ main (int argc, char *argv[]) char **newargz; int i; - program_name = (char *) xstrdup ((char *) basename (argv[0])); + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); newargz = XMALLOC(char *, argc+2); EOF - cat >> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" - newargz[1] = fnqualify(argv[0]); + cat >> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); /* we know the script has the same name, without the .exe */ /* so make sure newargz[1] doesn't end in .exe */ strendzap(newargz[1],".exe"); for (i = 1; i < argc; i++) newargz[i+1] = xstrdup(argv[i]); newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + cat >> $cwrappersource <<"EOF" + return 127; } void * @@ -4699,48 +5040,148 @@ xstrdup (const char *string) ; } -char * -basename (const char *name) +const char * +base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ - if (isalpha (name[0]) && name[1] == ':') + if (isalpha ((unsigned char)name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; - return (char *) base; + return base; } -char * -fnqualify(const char *path) +int +check_executable(const char * path) { - size_t size; - char *p; - char tmp[LT_PATHMAX + 1]; + struct stat st; - assert(path != NULL); + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; - /* Is it qualified already? */ -#if defined (HAVE_DOS_BASED_FILE_SYSTEM) - if (isalpha (path[0]) && path[1] == ':') - return xstrdup (path); + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || #endif - if (IS_DIR_SEPARATOR (path[0])) - return xstrdup (path); +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} - /* prepend the current directory */ - /* doesn't handle '~' */ +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); - size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ - p = XMALLOC(char, size); - sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); - return p; + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; } char * @@ -4784,16 +5225,16 @@ lt_fatal (const char *message, ...) va_end (ap); } EOF - # we should really use a build-platform specific compiler - # here, but OTOH, the wrappers (shell script and this C one) - # are only useful if you want to execute the "real" binary. - # Since the "real" binary is built for $host, then this - # wrapper might as well be built for $host, too. - $run $LTCC -s -o $cwrapper $cwrappersource - ;; - esac - $rm $output - trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 $echo > $output "\ #! $SHELL @@ -4814,7 +5255,7 @@ sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. -if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" @@ -4943,13 +5384,13 @@ else # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ - exec \$progdir\\\\\$program \${1+\"\$@\"} + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $echo >> $output "\ - exec \$progdir/\$program \${1+\"\$@\"} + exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac @@ -4959,7 +5400,7 @@ else fi else # The program doesn't exist. - \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit $EXIT_FAILURE @@ -4991,71 +5432,73 @@ fi\ if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" - $show "${rm}r $gentop" - $run ${rm}r "$gentop" - $show "$mkdir $gentop" - $run $mkdir "$gentop" - status=$? - if test "$status" -ne 0 && test ! -d "$gentop"; then - exit $status - fi generated="$generated $gentop" - # Add in members from convenience archives. - for xlib in $addlibs; do - # Extract the objects. - case $xlib in - [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; - *) xabs=`pwd`"/$xlib" ;; - esac - xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` - xdir="$gentop/$xlib" - - $show "${rm}r $xdir" - $run ${rm}r "$xdir" - $show "$mkdir $xdir" - $run $mkdir "$xdir" - status=$? - if test "$status" -ne 0 && test ! -d "$xdir"; then - exit $status - fi - # We will extract separately just the conflicting names and we will no - # longer touch any unique names. It is faster to leave these extract - # automatically by $AR in one run. - $show "(cd $xdir && $AR x $xabs)" - $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? - if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 - $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 - $AR t "$xabs" | sort | uniq -cd | while read -r count name - do - i=1 - while test "$i" -le "$count" - do - # Put our $i before any first dot (extension) - # Never overwrite any file - name_to="$name" - while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" - do - name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` - done - $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" - $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? - i=`expr $i + 1` - done - done - fi - - oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` - done + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && @@ -5069,20 +5512,7 @@ fi\ objlist= concat_cmds= save_oldobjs=$oldobjs - # GNU ar 2.10+ was changed to match POSIX; thus no paths are - # encoded into archives. This makes 'ar r' malfunction in - # this piecewise linking case whenever conflicting object - # names appear in distinct ar calls; check, warn and compensate. - if (for obj in $save_oldobjs - do - $echo "X$obj" | $Xsed -e 's%^.*/%%' - done | sort | sort -uc >/dev/null 2>&1); then - : - else - $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 - $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 - AR_FLAGS=cq - fi + # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do @@ -5093,7 +5523,7 @@ fi\ oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" - if len=`expr "X$test_cmds" : ".*"` && + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && test "$len" -le "$max_cmd_len"; then : else @@ -5290,11 +5720,11 @@ relink_command=\"$relink_command\"" # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. - $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + $echo "X$nonopt" | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5303,14 +5733,14 @@ relink_command=\"$relink_command\"" shift else install_prog= - arg="$nonopt" + arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5328,28 +5758,31 @@ relink_command=\"$relink_command\"" do if test -n "$dest"; then files="$files $dest" - dest="$arg" + dest=$arg continue fi case $arg in -d) isdir=yes ;; - -f) prev="-f" ;; - -g) prev="-g" ;; - -m) prev="-m" ;; - -o) prev="-o" ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; - -*) ;; - + -*) + ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else - dest="$arg" + dest=$arg continue fi ;; @@ -5358,7 +5791,7 @@ relink_command=\"$relink_command\"" # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac @@ -5527,11 +5960,14 @@ relink_command=\"$relink_command\"" if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. for linkname do if test "$linkname" != "$realname"; then - $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" - $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" fi done fi @@ -5544,7 +5980,16 @@ relink_command=\"$relink_command\"" IFS="$save_ifs" eval cmd=\"$cmd\" $show "$cmd" - $run eval "$cmd" || exit $? + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } done IFS="$save_ifs" fi @@ -5638,17 +6083,15 @@ relink_command=\"$relink_command\"" notinst_deplibs= relink_command= - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; esac # Check the variables that should have been set. @@ -5676,34 +6119,21 @@ relink_command=\"$relink_command\"" done relink_command= - # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." - # which disallows the automatic-append-.exe behavior. - case $build in - *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; - *) wrapperdot=${wrapper} ;; - esac + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # # If there is no directory component, then add one. - case $file in - */* | *\\*) . ${wrapperdot} ;; - *) . ./${wrapperdot} ;; + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then - tmpdir="/tmp" - test -n "$TMPDIR" && tmpdir="$TMPDIR" - tmpdir="$tmpdir/libtool-$$" - save_umask=`umask` - umask 0077 - if $mkdir "$tmpdir"; then - umask $save_umask - else - umask $save_umask - $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 - continue - fi + tmpdir=`func_mktempdir` file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. @@ -5727,7 +6157,7 @@ relink_command=\"$relink_command\"" fi # remove .exe since cygwin /usr/bin/install will append another - # one anyways + # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in @@ -5827,7 +6257,7 @@ relink_command=\"$relink_command\"" # Exit here if they wanted silent mode. test "$show" = : && exit $EXIT_SUCCESS - $echo "----------------------------------------------------------------------" + $echo "X----------------------------------------------------------------------" | $Xsed $echo "Libraries have been installed in:" for libdir in $libdirs; do $echo " $libdir" @@ -5860,7 +6290,7 @@ relink_command=\"$relink_command\"" $echo $echo "See any operating system documentation about shared libraries for" $echo "more information, such as the ld(1) and ld.so(8) manual pages." - $echo "----------------------------------------------------------------------" + $echo "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS ;; @@ -6077,9 +6507,17 @@ relink_command=\"$relink_command\"" rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" - test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" - if test "$mode" = uninstall; then + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. cmds=$postuninstall_cmds @@ -6112,7 +6550,8 @@ relink_command=\"$relink_command\"" IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. - fi + ;; + esac fi ;; @@ -6397,7 +6836,7 @@ esac $echo $echo "Try \`$modename --help' for more information about other modes." -exit $EXIT_SUCCESS +exit $? # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting @@ -6411,12 +6850,11 @@ exit $EXIT_SUCCESS # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared -build_libtool_libs=no -build_old_libs=yes +disable_libs=shared # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static -build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` +disable_libs=static # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: diff --git a/libs/sofia-sip/m4/sac-su2.m4 b/libs/sofia-sip/m4/sac-su2.m4 index 5cde2c149a..bd0a7d1a73 100644 --- a/libs/sofia-sip/m4/sac-su2.m4 +++ b/libs/sofia-sip/m4/sac-su2.m4 @@ -46,6 +46,14 @@ else SAC_SU_DEFINE([SU_HAVE_PTHREADS], 1, [Sofia SU uses pthreads]) fi +AC_ARG_ENABLE(experimental, +[ --enable-experimental enable experimental features (disabled)], + , enable_experimental=no) + +if test $enable_experimental = yes ; then + SAC_SU_DEFINE([SU_HAVE_EXPERIMENTAL], 1, [Enable experimental features]) +fi + dnl =========================================================================== dnl Checks for typedefs, headers, structures, and compiler characteristics. dnl =========================================================================== @@ -119,21 +127,17 @@ fi ### Test if we have stack suitable for handling tags directly ### -test -z "$ac_cv_tagstack" && -case "$target" in -i?86-*-* ) ac_cv_tagstack=yes ;; -esac - AC_CACHE_CHECK([for stack suitable for tags],[ac_cv_tagstack],[ ac_cv_tagstack=no -AC_RUN_IFELSE([ +AC_RUN_IFELSE([AC_LANG_SOURCE([[ #if HAVE_INTTYPES_H #include #endif #if HAVE_STDINT_H #include #endif + #include typedef void *tp; @@ -169,7 +173,12 @@ int main(int avc, char **av) (tv)1, (tv)2, (tv)3, (tv)4, (tv)5, (tv)6, (tv)7, (tv)8, (tv)9, (tv)10); } -],[ac_cv_tagstack=yes],[ac_cv_tagstack=no],[ac_cv_tagstack=no])]) +]])],[ac_cv_tagstack=yes],[ac_cv_tagstack=no],[ +case "$target" in +i?86-*-* ) ac_cv_tagstack=yes ;; +* ) ac_cv_tagstack=no ;; +esac +])]) if test $ac_cv_tagstack = yes ; then SAC_SU_DEFINE([SU_HAVE_TAGSTACK], 1, [ @@ -227,9 +236,10 @@ AC_CHECK_HEADERS([winsock2.h], [ GetSystemTimeAsFileTime().]) ],[ dnl no winsock2 + SAC_SU_DEFINE([SU_HAVE_BSDSOCK], 1, [Define to 1 if you have BSD socket interface]) AC_CHECK_HEADERS([sys/socket.h sys/ioctl.h sys/filio.h sys/sockio.h \ - sys/select.h]) + sys/select.h sys/epoll.h]) AC_CHECK_HEADERS([netinet/in.h arpa/inet.h netdb.h \ net/if.h net/if_types.h ifaddr.h netpacket/packet.h],,, [ @@ -429,9 +439,12 @@ AC_SEARCH_LIBS(getipnodebyname, xnet socket nsl) AC_SEARCH_LIBS(gethostbyname, xnet nsl) AC_SEARCH_LIBS(getaddrinfo, xnet socket nsl) -AC_CHECK_FUNCS([gettimeofday strerror random initstate tcsetattr flock alarm \ +AC_FUNC_ALLOCA + +AC_CHECK_FUNCS([gettimeofday strerror random initstate tcsetattr flock \ socketpair gethostname gethostbyname getipnodebyname \ poll epoll_create select if_nameindex \ + signal alarm \ getaddrinfo getnameinfo freeaddrinfo gai_strerror getifaddrs \ getline getdelim getpass]) # getline getdelim getpass are _GNU_SOURCE stuff @@ -440,7 +453,8 @@ if test $ac_cv_func_poll = yes ; then SAC_SU_DEFINE([SU_HAVE_POLL], 1, [Define to 1 if you have poll().]) fi -if test $ac_cv_func_epoll_create = yes ; then +if test $ac_cv_func_epoll_create = yes && test $ac_cv_header_sys_epoll_h = yes +then AC_DEFINE([HAVE_EPOLL], 1, [Define to 1 if you have epoll interface.]) fi @@ -455,8 +469,32 @@ if test "${with_rt}" != no; then fi SAC_REPLACE_FUNCS([memmem memccpy memspn memcspn strcasestr strtoull \ - inet_ntop inet_pton]) + inet_ntop inet_pton poll]) +if test $ac_cv_func_signal = yes ; then +AC_CHECK_DECL([SIGPIPE], [ +AC_DEFINE([HAVE_SIGPIPE], 1, [Define to 1 if you have SIGPIPE])],,[ +#include +]) +dnl add SIGHUP SIGQUIT if needed +fi + +# =========================================================================== +# Check how to implement su_port +# =========================================================================== + +AC_ARG_ENABLE(poll-port, +[ --disable-poll-port disable su_poll_port (enabled) + Use this option in systems emulating poll + with select], , enable_poll_port=maybe) + +if test $enable_poll_port = maybe ; then + if test $ac_cv_func_poll = yes ; then + AC_DEFINE([HAVE_POLL_PORT], 1, [Define to 1 if you use poll in su_port.]) + fi +elif test $enable_poll_port = yes ; then + AC_DEFINE([HAVE_POLL_PORT], 1, [Define to 1 if you use poll in su_port.]) +fi # =========================================================================== # Check pthread_rwlock_unlock() diff --git a/libs/sofia-sip/packages/Makefile.in b/libs/sofia-sip/packages/Makefile.in index 8b5783877d..e7c60d6423 100644 --- a/libs/sofia-sip/packages/Makefile.in +++ b/libs/sofia-sip/packages/Makefile.in @@ -78,6 +78,7 @@ DATA = $(pkgconfig_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -124,8 +125,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -169,6 +174,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ diff --git a/libs/sofia-sip/rules/recursive.am b/libs/sofia-sip/rules/recursive.am new file mode 100644 index 0000000000..2a68877eab --- /dev/null +++ b/libs/sofia-sip/rules/recursive.am @@ -0,0 +1,52 @@ +# Recursive Makefile targets +# -------------------------- + +if ENABLE_COVERAGE +COVERAGE_RECURSIVE = coverage-recursive +coverage: $(COVERAGE_RECURSIVE) +endif + +all-recursive: built-sources-recursive +built-sources: built-sources-recursive +clean-built-sources: clean-built-sources-recursive +valcheck: valcheck-recursive + +SOFIA_RECURSIVE = \ + valcheck-recursive \ + $(COVERAGE_RECURSIVE) + +SOFIA_DIST_RECURSIVE = \ + built-sources-recursive \ + clean-built-sources-recursive + +$(SOFIA_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ + || eval $$failcom; \ + done; \ + test -z "$$fail" + +$(SOFIA_DIST_RECURSIVE): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target) \ + || eval $$failcom; \ + done; \ + test -z "$$fail" diff --git a/libs/sofia-sip/rules/sofia.am b/libs/sofia-sip/rules/sofia.am new file mode 100644 index 0000000000..9e2922447a --- /dev/null +++ b/libs/sofia-sip/rules/sofia.am @@ -0,0 +1,60 @@ +# common Makefile targets for libsofia-sip-ua(-glib) modules +# ---------------------------------------------------------- + +AM_CFLAGS = $(CWFLAG) $(SOFIA_COVERAGE) $(SOFIA_CFLAGS) + +# Use with --enable-ndebug +if NDEBUG +AM_CFLAGS += -DNDEBUG +endif + +built-sources: $(BUILT_SOURCES) + +DISTCLEANFILES = $(BUILT_SOURCES) + +clean-built-sources: + -rm -rf $(BUILT_SOURCES) $(BUILT_SOURCES:%=$(srcdir)/%) + +# rules for building tag files + +TAG_AWK=$(top_srcdir)/libsofia-sip-ua/su/tag_dll.awk + +*_tag_ref.c: $(TAG_AWK) + +%_tag_ref.c: %_tag.c + $(AWK) -f $(TAG_AWK) NODLL=1 $(TAG_DLL_FLAGS) $< + +if ENABLE_COVERAGE +coverage: + @$(top_srcdir)/scripts/coverage $(COVERAGE_FLAGS) $(COVERAGE_INPUT) +endif + +../bnf/libbnf.la ../http/libhttp.la ../ipt/libipt.la ../iptsec/libiptsec.la \ + ../msg/libmsg.la ../nea/libnea.la ../nta/libnta.la ../nth/libnth.la \ + ../nua/libnua.la ../sdp/libsdp.la ../sip/libsip.la ../soa/libsoa.la \ + ../sresolv/libsresolv.la ../stun/libstun.la ../su/libsu.la \ + ../tport/libtport.la ../url/liburl.la: + $(MAKE) -C $(@D) $(@F) + +INTERNAL_INCLUDES = \ + -I$(srcdir)/../features -I../features \ + -I$(srcdir)/../ipt -I../ipt \ + -I$(srcdir)/../iptsec -I../iptsec \ + -I$(srcdir)/../bnf -I../bnf \ + -I$(srcdir)/../http -I../http \ + -I$(srcdir)/../msg -I../msg \ + -I$(srcdir)/../nth -I../nth \ + -I$(srcdir)/../nta -I../nta \ + -I$(srcdir)/../nea -I../nea \ + -I$(srcdir)/../nua -I../nua \ + -I$(srcdir)/../soa -I../soa \ + -I$(srcdir)/../sdp -I../sdp \ + -I$(srcdir)/../sip -I../sip \ + -I$(srcdir)/../soa -I../soa \ + -I$(srcdir)/../sresolv -I../sresolv \ + -I$(srcdir)/../tport -I../tport \ + -I$(srcdir)/../stun -I../stun \ + -I$(srcdir)/../url -I../url \ + -I$(srcdir)/../su -I../su + +include $(top_srcdir)/rules/valcheck.am \ No newline at end of file diff --git a/libs/sofia-sip/rules/valcheck.am b/libs/sofia-sip/rules/valcheck.am new file mode 100644 index 0000000000..f9c6900f8a --- /dev/null +++ b/libs/sofia-sip/rules/valcheck.am @@ -0,0 +1,114 @@ +# +# run tests with valgrind +# + +# Copyright (C) 2007 Nokia Corporation. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. + +# This file contains free software from Makefile.in by the Free Software +# Foundation: + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +VALGRIND = valgrind + +VALGRINDFLAGS = --tool=memcheck + +valcheck: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) valcheck-am + +valcheck-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) valcheck-TESTS + +# Run tests with valgrind in +valcheck-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if case $$tst in \ + run*) VALGRIND="$(VALGRIND) $(VALGRINDFLAGS)" \ + $(TESTS_ENVIRONMENT) $${dir}$$tst ;; \ + *) $(TESTS_ENVIRONMENT) $(VALGRIND) $(VALGRINDFLAGS) \ + $${dir}$$tst ;; \ + esac ; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst"; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + echo "SKIP: $$tst"; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + skipped="($$skip tests were not run)"; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi diff --git a/libs/sofia-sip/utils/Makefile.in b/libs/sofia-sip/utils/Makefile.in index ef19c7eadf..f1c9f07657 100644 --- a/libs/sofia-sip/utils/Makefile.in +++ b/libs/sofia-sip/utils/Makefile.in @@ -104,6 +104,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -150,8 +151,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -195,6 +200,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ diff --git a/libs/sofia-sip/utils/sip-options.c b/libs/sofia-sip/utils/sip-options.c index 911bbfb9f1..219ea4e83e 100644 --- a/libs/sofia-sip/utils/sip-options.c +++ b/libs/sofia-sip/utils/sip-options.c @@ -331,7 +331,7 @@ int main(int argc, char *argv[]) return context->c_retval; } -/** Handle responses to registration request */ +/** Handle responses to OPTIONS request */ static int response_to_options(context_t *context, nta_outgoing_t *oreq, @@ -355,12 +355,16 @@ int response_to_options(context_t *context, sip_is_content_length(h)) continue; } - if (h->sh_class->hc_name) { - snprintf(hname, sizeof hname, "%s: %%s\n", h->sh_class->hc_name); - sl_header_print(stdout, hname, h); + + if (h->sh_class->hc_name == NULL) { + sl_header_print(stdout, NULL, h); + } + else if (h->sh_class->hc_name[0] == '\0') { + sl_header_print(stdout, "%s\n", h); } else { - sl_header_print(stdout, NULL, h); + snprintf(hname, sizeof hname, "%s: %%s\n", h->sh_class->hc_name); + sl_header_print(stdout, hname, h); } } } diff --git a/libs/sofia-sip/win32/Makefile.am b/libs/sofia-sip/win32/Makefile.am index fa6d7a5a90..89947af6a6 100644 --- a/libs/sofia-sip/win32/Makefile.am +++ b/libs/sofia-sip/win32/Makefile.am @@ -44,6 +44,31 @@ EXTRA_DIST = SofiaSIP.dsw \ autogen.cmd build_sources.cmd version_files.cmd version.awk \ install.cmd check.cmd +# VC2005 Project files +EXTRA_DIST += SofiaSIP.sln \ + libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj \ + libsofia-sip-ua/libsofia_sip_ua.vcproj \ + tests/test_htable/test_htable.vcproj \ + tests/test_memmem/test_memmem.vcproj \ + tests/test_nta/test_nta.vcproj \ + tests/test_nua/test_nua.vcproj \ + tests/test_su/test_su.vcproj \ + tests/test_tport/test_tport.vcproj \ + tests/torture_rbtree/torture_rbtree.vcproj \ + tests/torture_su/torture_su.vcproj \ + tests/torture_su_alloc/torture_su_alloc.vcproj \ + tests/torture_su_bm/torture_su_bm.vcproj \ + tests/torture_su_port/torture_su_port.vcproj \ + tests/torture_su_root/torture_su_root.vcproj \ + tests/torture_su_tag/torture_su_tag.vcproj \ + tests/torture_su_time/torture_su_time.vcproj \ + tests/torture_su_timer/torture_su_timer.vcproj \ + utils/localinfo/localinfo.vcproj \ + utils/sip_dig/sip_dig.vcproj \ + utils/sip_options/sip_options.vcproj \ + utils/sip_options_static/sip_options_static.vcproj \ + utils/stunc/stunc.vcproj + PTHREAD_DIST = \ pthread/ChangeLog \ pthread/md5.sum.txt \ diff --git a/libs/sofia-sip/win32/Makefile.in b/libs/sofia-sip/win32/Makefile.in index cc35a9aa71..f023f0bb62 100644 --- a/libs/sofia-sip/win32/Makefile.in +++ b/libs/sofia-sip/win32/Makefile.in @@ -71,6 +71,7 @@ CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ AMDEP_FALSE = @AMDEP_FALSE@ AMDEP_TRUE = @AMDEP_TRUE@ AMTAR = @AMTAR@ @@ -117,8 +118,12 @@ HAVE_GLIB_FALSE = @HAVE_GLIB_FALSE@ HAVE_GLIB_TRUE = @HAVE_GLIB_TRUE@ HAVE_MINGW32_FALSE = @HAVE_MINGW32_FALSE@ HAVE_MINGW32_TRUE = @HAVE_MINGW32_TRUE@ +HAVE_NTH_FALSE = @HAVE_NTH_FALSE@ +HAVE_NTH_TRUE = @HAVE_NTH_TRUE@ HAVE_NTLM_FALSE = @HAVE_NTLM_FALSE@ HAVE_NTLM_TRUE = @HAVE_NTLM_TRUE@ +HAVE_STUN_FALSE = @HAVE_STUN_FALSE@ +HAVE_STUN_TRUE = @HAVE_STUN_TRUE@ HAVE_TLS_FALSE = @HAVE_TLS_FALSE@ HAVE_TLS_TRUE = @HAVE_TLS_TRUE@ INSTALL_DATA = @INSTALL_DATA@ @@ -162,6 +167,7 @@ REPLACE_LIBADD = @REPLACE_LIBADD@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOFIA_CFLAGS = @SOFIA_CFLAGS@ +SOFIA_COVERAGE = @SOFIA_COVERAGE@ SOFIA_GLIB_PKG_REQUIRES = @SOFIA_GLIB_PKG_REQUIRES@ STRIP = @STRIP@ TESTS_ENVIRONMENT = @TESTS_ENVIRONMENT@ @@ -217,14 +223,13 @@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ noinst_HEADERS = sofia-sip/su_configure.h unistd.h config.h -EXTRA_DIST = SofiaSIP.dsw \ - libsofia-sip-ua/libsofia_sip_ua.dsp \ + +# VC2005 Project files +EXTRA_DIST = SofiaSIP.dsw libsofia-sip-ua/libsofia_sip_ua.dsp \ libsofia-sip-ua/sofia-sip-ua.def \ libsofia-sip-ua-static/libsofia_sip_ua_static.dsp \ - tests/test_nua/test_nua.dsp \ - tests/test_nua/test_nat_tags.cpp \ - tests/test_nta/test_nta.dsp \ - tests/test_tport/test_tport.dsp \ + tests/test_nua/test_nua.dsp tests/test_nua/test_nat_tags.cpp \ + tests/test_nta/test_nta.dsp tests/test_tport/test_tport.dsp \ tests/test_tport/test_class.cpp \ tests/test_tport/test_table.cpp \ tests/torture_su_alloc/torture_su_alloc.dsp \ @@ -240,14 +245,30 @@ EXTRA_DIST = SofiaSIP.dsw \ tests/torture_su_bm/torture_su_bm.dsp \ tests/torture_su_port/torture_su_port.dsp \ utils/localinfo/localinfo.dsp \ - utils/sip_options/sip_options.dsp \ - utils/sip_dig/sip_dig.dsp \ - utils/stunc/stunc.dsp \ - $(PTHREAD_DIST) \ - README.txt \ - autogen.cmd build_sources.cmd version_files.cmd version.awk \ - install.cmd check.cmd - + utils/sip_options/sip_options.dsp utils/sip_dig/sip_dig.dsp \ + utils/stunc/stunc.dsp $(PTHREAD_DIST) README.txt autogen.cmd \ + build_sources.cmd version_files.cmd version.awk install.cmd \ + check.cmd SofiaSIP.sln \ + libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj \ + libsofia-sip-ua/libsofia_sip_ua.vcproj \ + tests/test_htable/test_htable.vcproj \ + tests/test_memmem/test_memmem.vcproj \ + tests/test_nta/test_nta.vcproj tests/test_nua/test_nua.vcproj \ + tests/test_su/test_su.vcproj \ + tests/test_tport/test_tport.vcproj \ + tests/torture_rbtree/torture_rbtree.vcproj \ + tests/torture_su/torture_su.vcproj \ + tests/torture_su_alloc/torture_su_alloc.vcproj \ + tests/torture_su_bm/torture_su_bm.vcproj \ + tests/torture_su_port/torture_su_port.vcproj \ + tests/torture_su_root/torture_su_root.vcproj \ + tests/torture_su_tag/torture_su_tag.vcproj \ + tests/torture_su_time/torture_su_time.vcproj \ + tests/torture_su_timer/torture_su_timer.vcproj \ + utils/localinfo/localinfo.vcproj utils/sip_dig/sip_dig.vcproj \ + utils/sip_options/sip_options.vcproj \ + utils/sip_options_static/sip_options_static.vcproj \ + utils/stunc/stunc.vcproj PTHREAD_DIST = \ pthread/ChangeLog \ pthread/md5.sum.txt \ @@ -351,7 +372,7 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/libsofia-sip-ua $(distdir)/libsofia-sip-ua-static $(distdir)/pthread $(distdir)/sofia-sip $(distdir)/tests/test_htable $(distdir)/tests/test_memmem $(distdir)/tests/test_nta $(distdir)/tests/test_nua $(distdir)/tests/test_su $(distdir)/tests/test_tport $(distdir)/tests/torture_rbtree $(distdir)/tests/torture_su $(distdir)/tests/torture_su_alloc $(distdir)/tests/torture_su_bm $(distdir)/tests/torture_su_port $(distdir)/tests/torture_su_root $(distdir)/tests/torture_su_tag $(distdir)/tests/torture_su_time $(distdir)/tests/torture_su_timer $(distdir)/utils/localinfo $(distdir)/utils/sip_dig $(distdir)/utils/sip_options $(distdir)/utils/stunc + $(mkdir_p) $(distdir)/libsofia-sip-ua $(distdir)/libsofia-sip-ua-static $(distdir)/pthread $(distdir)/sofia-sip $(distdir)/tests/test_htable $(distdir)/tests/test_memmem $(distdir)/tests/test_nta $(distdir)/tests/test_nua $(distdir)/tests/test_su $(distdir)/tests/test_tport $(distdir)/tests/torture_rbtree $(distdir)/tests/torture_su $(distdir)/tests/torture_su_alloc $(distdir)/tests/torture_su_bm $(distdir)/tests/torture_su_port $(distdir)/tests/torture_su_root $(distdir)/tests/torture_su_tag $(distdir)/tests/torture_su_time $(distdir)/tests/torture_su_timer $(distdir)/utils/localinfo $(distdir)/utils/sip_dig $(distdir)/utils/sip_options $(distdir)/utils/sip_options_static $(distdir)/utils/stunc @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ list='$(DISTFILES)'; for file in $$list; do \ diff --git a/libs/sofia-sip/win32/SofiaSIP.sln b/libs/sofia-sip/win32/SofiaSIP.sln new file mode 100644 index 0000000000..bab60a6e9f --- /dev/null +++ b/libs/sofia-sip/win32/SofiaSIP.sln @@ -0,0 +1,197 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsofia_sip_ua", "libsofia-sip-ua\libsofia_sip_ua.vcproj", "{0D85D39A-C7FB-4C52-A541-73665FB478E6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsofia_sip_ua_static", "libsofia-sip-ua-static\libsofia_sip_ua_static.vcproj", "{5A6E80AB-5335-4F14-9030-D4DA3A13109B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "localinfo", "utils\localinfo\localinfo.vcproj", "{CD3CE1A9-BABD-43F1-9CEB-6F047AEE2FC5}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sip_dig", "utils\sip_dig\sip_dig.vcproj", "{627985F5-C1A1-406F-8184-464B34E36F1B}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sip_options", "utils\sip_options\sip_options.vcproj", "{FDBA680D-D560-49CC-B72F-EC9B3CA52B9C}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sip_options_static", "utils\sip_options_static\sip_options_static.vcproj", "{4E9B7192-4242-47A9-B449-E3E18F8B4216}" + ProjectSection(ProjectDependencies) = postProject + {5A6E80AB-5335-4F14-9030-D4DA3A13109B} = {5A6E80AB-5335-4F14-9030-D4DA3A13109B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stunc", "utils\stunc\stunc.vcproj", "{0AE740B8-54A3-486F-AA84-F19B592B29D3}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_htable", "tests\test_htable\test_htable.vcproj", "{41C72ECB-BF92-4C98-9B57-89BFCE1FA772}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_memmem", "tests\test_memmem\test_memmem.vcproj", "{B87FBA69-5616-48E5-8A3A-46CB9B95F3F8}" + ProjectSection(ProjectDependencies) = postProject + {5A6E80AB-5335-4F14-9030-D4DA3A13109B} = {5A6E80AB-5335-4F14-9030-D4DA3A13109B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nta", "tests\test_nta\test_nta.vcproj", "{C9AEEF0E-D3F6-4346-A9CF-5B775CEE4EC8}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nua", "tests\test_nua\test_nua.vcproj", "{2919D919-41FC-4138-8243-676F0EDFCCCB}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_su", "tests\test_su\test_su.vcproj", "{9E207F42-049E-46E3-ACE5-1A5AFF8E7A05}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tport", "tests\test_tport\test_tport.vcproj", "{D02963A2-AED0-4825-82D3-0F9DC1475AF3}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_rbtree", "tests\torture_rbtree\torture_rbtree.vcproj", "{74AF1B59-64D3-4D22-8F30-98B2868123C8}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su", "tests\torture_su\torture_su.vcproj", "{A4C22592-4EBA-407C-A739-9AFF43141140}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_alloc", "tests\torture_su_alloc\torture_su_alloc.vcproj", "{2B20EC13-8E2E-45F0-A865-E52FC35638D6}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_bm", "tests\torture_su_bm\torture_su_bm.vcproj", "{44EB96E2-6863-4D5D-853A-1288E95261E6}" + ProjectSection(ProjectDependencies) = postProject + {5A6E80AB-5335-4F14-9030-D4DA3A13109B} = {5A6E80AB-5335-4F14-9030-D4DA3A13109B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_root", "tests\torture_su_root\torture_su_root.vcproj", "{62F73F70-88D5-4FC9-B166-4CFF4BB9E61B}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_tag", "tests\torture_su_tag\torture_su_tag.vcproj", "{2560F904-8A51-42D5-A1F9-411B452F899D}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_time", "tests\torture_su_time\torture_su_time.vcproj", "{6D10B051-BD5B-486D-AE4E-02F70DDE59AA}" + ProjectSection(ProjectDependencies) = postProject + {5A6E80AB-5335-4F14-9030-D4DA3A13109B} = {5A6E80AB-5335-4F14-9030-D4DA3A13109B} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "torture_su_timer", "tests\torture_su_timer\torture_su_timer.vcproj", "{01B062BA-DF7B-4F0C-967A-6F485D2F7C44}" + ProjectSection(ProjectDependencies) = postProject + {0D85D39A-C7FB-4C52-A541-73665FB478E6} = {0D85D39A-C7FB-4C52-A541-73665FB478E6} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0D85D39A-C7FB-4C52-A541-73665FB478E6}.Debug|Win32.ActiveCfg = Debug|Win32 + {0D85D39A-C7FB-4C52-A541-73665FB478E6}.Debug|Win32.Build.0 = Debug|Win32 + {0D85D39A-C7FB-4C52-A541-73665FB478E6}.Release|Win32.ActiveCfg = Release|Win32 + {0D85D39A-C7FB-4C52-A541-73665FB478E6}.Release|Win32.Build.0 = Release|Win32 + {5A6E80AB-5335-4F14-9030-D4DA3A13109B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5A6E80AB-5335-4F14-9030-D4DA3A13109B}.Debug|Win32.Build.0 = Debug|Win32 + {5A6E80AB-5335-4F14-9030-D4DA3A13109B}.Release|Win32.ActiveCfg = Release|Win32 + {5A6E80AB-5335-4F14-9030-D4DA3A13109B}.Release|Win32.Build.0 = Release|Win32 + {CD3CE1A9-BABD-43F1-9CEB-6F047AEE2FC5}.Debug|Win32.ActiveCfg = Debug|Win32 + {CD3CE1A9-BABD-43F1-9CEB-6F047AEE2FC5}.Debug|Win32.Build.0 = Debug|Win32 + {CD3CE1A9-BABD-43F1-9CEB-6F047AEE2FC5}.Release|Win32.ActiveCfg = Release|Win32 + {CD3CE1A9-BABD-43F1-9CEB-6F047AEE2FC5}.Release|Win32.Build.0 = Release|Win32 + {627985F5-C1A1-406F-8184-464B34E36F1B}.Debug|Win32.ActiveCfg = Debug|Win32 + {627985F5-C1A1-406F-8184-464B34E36F1B}.Debug|Win32.Build.0 = Debug|Win32 + {627985F5-C1A1-406F-8184-464B34E36F1B}.Release|Win32.ActiveCfg = Release|Win32 + {627985F5-C1A1-406F-8184-464B34E36F1B}.Release|Win32.Build.0 = Release|Win32 + {FDBA680D-D560-49CC-B72F-EC9B3CA52B9C}.Debug|Win32.ActiveCfg = Debug|Win32 + {FDBA680D-D560-49CC-B72F-EC9B3CA52B9C}.Debug|Win32.Build.0 = Debug|Win32 + {FDBA680D-D560-49CC-B72F-EC9B3CA52B9C}.Release|Win32.ActiveCfg = Release|Win32 + {FDBA680D-D560-49CC-B72F-EC9B3CA52B9C}.Release|Win32.Build.0 = Release|Win32 + {4E9B7192-4242-47A9-B449-E3E18F8B4216}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E9B7192-4242-47A9-B449-E3E18F8B4216}.Debug|Win32.Build.0 = Debug|Win32 + {4E9B7192-4242-47A9-B449-E3E18F8B4216}.Release|Win32.ActiveCfg = Release|Win32 + {4E9B7192-4242-47A9-B449-E3E18F8B4216}.Release|Win32.Build.0 = Release|Win32 + {0AE740B8-54A3-486F-AA84-F19B592B29D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {0AE740B8-54A3-486F-AA84-F19B592B29D3}.Debug|Win32.Build.0 = Debug|Win32 + {0AE740B8-54A3-486F-AA84-F19B592B29D3}.Release|Win32.ActiveCfg = Release|Win32 + {0AE740B8-54A3-486F-AA84-F19B592B29D3}.Release|Win32.Build.0 = Release|Win32 + {41C72ECB-BF92-4C98-9B57-89BFCE1FA772}.Debug|Win32.ActiveCfg = Debug|Win32 + {41C72ECB-BF92-4C98-9B57-89BFCE1FA772}.Debug|Win32.Build.0 = Debug|Win32 + {41C72ECB-BF92-4C98-9B57-89BFCE1FA772}.Release|Win32.ActiveCfg = Release|Win32 + {41C72ECB-BF92-4C98-9B57-89BFCE1FA772}.Release|Win32.Build.0 = Release|Win32 + {B87FBA69-5616-48E5-8A3A-46CB9B95F3F8}.Debug|Win32.ActiveCfg = Debug|Win32 + {B87FBA69-5616-48E5-8A3A-46CB9B95F3F8}.Debug|Win32.Build.0 = Debug|Win32 + {B87FBA69-5616-48E5-8A3A-46CB9B95F3F8}.Release|Win32.ActiveCfg = Release|Win32 + {B87FBA69-5616-48E5-8A3A-46CB9B95F3F8}.Release|Win32.Build.0 = Release|Win32 + {C9AEEF0E-D3F6-4346-A9CF-5B775CEE4EC8}.Debug|Win32.ActiveCfg = Debug|Win32 + {C9AEEF0E-D3F6-4346-A9CF-5B775CEE4EC8}.Debug|Win32.Build.0 = Debug|Win32 + {C9AEEF0E-D3F6-4346-A9CF-5B775CEE4EC8}.Release|Win32.ActiveCfg = Release|Win32 + {C9AEEF0E-D3F6-4346-A9CF-5B775CEE4EC8}.Release|Win32.Build.0 = Release|Win32 + {2919D919-41FC-4138-8243-676F0EDFCCCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {2919D919-41FC-4138-8243-676F0EDFCCCB}.Debug|Win32.Build.0 = Debug|Win32 + {2919D919-41FC-4138-8243-676F0EDFCCCB}.Release|Win32.ActiveCfg = Release|Win32 + {2919D919-41FC-4138-8243-676F0EDFCCCB}.Release|Win32.Build.0 = Release|Win32 + {9E207F42-049E-46E3-ACE5-1A5AFF8E7A05}.Debug|Win32.ActiveCfg = Debug|Win32 + {9E207F42-049E-46E3-ACE5-1A5AFF8E7A05}.Debug|Win32.Build.0 = Debug|Win32 + {9E207F42-049E-46E3-ACE5-1A5AFF8E7A05}.Release|Win32.ActiveCfg = Release|Win32 + {9E207F42-049E-46E3-ACE5-1A5AFF8E7A05}.Release|Win32.Build.0 = Release|Win32 + {D02963A2-AED0-4825-82D3-0F9DC1475AF3}.Debug|Win32.ActiveCfg = Debug|Win32 + {D02963A2-AED0-4825-82D3-0F9DC1475AF3}.Debug|Win32.Build.0 = Debug|Win32 + {D02963A2-AED0-4825-82D3-0F9DC1475AF3}.Release|Win32.ActiveCfg = Release|Win32 + {D02963A2-AED0-4825-82D3-0F9DC1475AF3}.Release|Win32.Build.0 = Release|Win32 + {74AF1B59-64D3-4D22-8F30-98B2868123C8}.Debug|Win32.ActiveCfg = Debug|Win32 + {74AF1B59-64D3-4D22-8F30-98B2868123C8}.Debug|Win32.Build.0 = Debug|Win32 + {74AF1B59-64D3-4D22-8F30-98B2868123C8}.Release|Win32.ActiveCfg = Release|Win32 + {74AF1B59-64D3-4D22-8F30-98B2868123C8}.Release|Win32.Build.0 = Release|Win32 + {A4C22592-4EBA-407C-A739-9AFF43141140}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4C22592-4EBA-407C-A739-9AFF43141140}.Debug|Win32.Build.0 = Debug|Win32 + {A4C22592-4EBA-407C-A739-9AFF43141140}.Release|Win32.ActiveCfg = Release|Win32 + {A4C22592-4EBA-407C-A739-9AFF43141140}.Release|Win32.Build.0 = Release|Win32 + {2B20EC13-8E2E-45F0-A865-E52FC35638D6}.Debug|Win32.ActiveCfg = Debug|Win32 + {2B20EC13-8E2E-45F0-A865-E52FC35638D6}.Debug|Win32.Build.0 = Debug|Win32 + {2B20EC13-8E2E-45F0-A865-E52FC35638D6}.Release|Win32.ActiveCfg = Release|Win32 + {2B20EC13-8E2E-45F0-A865-E52FC35638D6}.Release|Win32.Build.0 = Release|Win32 + {44EB96E2-6863-4D5D-853A-1288E95261E6}.Debug|Win32.ActiveCfg = Debug|Win32 + {44EB96E2-6863-4D5D-853A-1288E95261E6}.Debug|Win32.Build.0 = Debug|Win32 + {44EB96E2-6863-4D5D-853A-1288E95261E6}.Release|Win32.ActiveCfg = Release|Win32 + {44EB96E2-6863-4D5D-853A-1288E95261E6}.Release|Win32.Build.0 = Release|Win32 + {62F73F70-88D5-4FC9-B166-4CFF4BB9E61B}.Debug|Win32.ActiveCfg = Debug|Win32 + {62F73F70-88D5-4FC9-B166-4CFF4BB9E61B}.Debug|Win32.Build.0 = Debug|Win32 + {62F73F70-88D5-4FC9-B166-4CFF4BB9E61B}.Release|Win32.ActiveCfg = Release|Win32 + {62F73F70-88D5-4FC9-B166-4CFF4BB9E61B}.Release|Win32.Build.0 = Release|Win32 + {2560F904-8A51-42D5-A1F9-411B452F899D}.Debug|Win32.ActiveCfg = Debug|Win32 + {2560F904-8A51-42D5-A1F9-411B452F899D}.Debug|Win32.Build.0 = Debug|Win32 + {2560F904-8A51-42D5-A1F9-411B452F899D}.Release|Win32.ActiveCfg = Release|Win32 + {2560F904-8A51-42D5-A1F9-411B452F899D}.Release|Win32.Build.0 = Release|Win32 + {6D10B051-BD5B-486D-AE4E-02F70DDE59AA}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D10B051-BD5B-486D-AE4E-02F70DDE59AA}.Debug|Win32.Build.0 = Debug|Win32 + {6D10B051-BD5B-486D-AE4E-02F70DDE59AA}.Release|Win32.ActiveCfg = Release|Win32 + {6D10B051-BD5B-486D-AE4E-02F70DDE59AA}.Release|Win32.Build.0 = Release|Win32 + {01B062BA-DF7B-4F0C-967A-6F485D2F7C44}.Debug|Win32.ActiveCfg = Debug|Win32 + {01B062BA-DF7B-4F0C-967A-6F485D2F7C44}.Debug|Win32.Build.0 = Debug|Win32 + {01B062BA-DF7B-4F0C-967A-6F485D2F7C44}.Release|Win32.ActiveCfg = Release|Win32 + {01B062BA-DF7B-4F0C-967A-6F485D2F7C44}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/sofia-sip/win32/build_sources.cmd b/libs/sofia-sip/win32/build_sources.cmd index afc75faa15..2e62dbedf3 100644 --- a/libs/sofia-sip/win32/build_sources.cmd +++ b/libs/sofia-sip/win32/build_sources.cmd @@ -3,21 +3,22 @@ :: @setlocal -@if x%AWK%==x set AWK=gawk +@if x%AWK%==x set AWK=mawk @set CHECK=@IF errorlevel 1 GOTO failed :: Check that we really have awk @%AWK% "{ exit(0); }" < NUL >NUL @if not errorlevel 9009 goto have_awk -@echo *** install %AWK% (GNU awk) into your PATH *** +@echo *** install %AWK% (mawk or GNU awk) into your PATH *** +@echo *** see http://gnuwin32.sourceforge.net/packages/mawk.htm *** @goto failed :have_awk -@set MSG_AWK=gawk -v BINMODE=rw -f ../libsofia-sip-ua/msg/msg_parser.awk +@set MSG_AWK=%AWK% -v BINMODE=rw -f ../libsofia-sip-ua/msg/msg_parser.awk :: in Win32 exit 0; from gawk 3.1.3 gets converted to errorlevel 1 :: If you have gawk 3.1.3 uncomment the following line -:: @set MSG_AWK=gawk -v BINMODE=rw -f ../libsofia-sip-ua/msg/msg_parser.awk success=-1 -@set TAG_AWK=gawk -f ../libsofia-sip-ua/su/tag_dll.awk BINMODE=rw +:: @set MSG_AWK=%AWK% -v BINMODE=rw -f ../libsofia-sip-ua/msg/msg_parser.awk success=-1 +@set TAG_AWK=%AWK% -f ../libsofia-sip-ua/su/tag_dll.awk BINMODE=rw @set IN=../libsofia-sip-ua/msg/test_class.h @set PR=../libsofia-sip-ua/msg/test_protos.h diff --git a/libs/sofia-sip/win32/check.cmd b/libs/sofia-sip/win32/check.cmd index e4cdb40bce..197efef69a 100644 --- a/libs/sofia-sip/win32/check.cmd +++ b/libs/sofia-sip/win32/check.cmd @@ -63,5 +63,5 @@ tests\torture_rbtree\Debug\torture_rbtree.exe tests\torture_su_bm\Debug\torture_su_bm.exe @if errorlevel 1 ( echo torture_su_bm: FAIL ) else echo torture_su_bm: PASS -tests\torture_su_port\Debug\torture_su_port.exe -@if errorlevel 1 ( echo torture_su_port: FAIL ) else echo torture_su_port: PASS +:: tests\torture_su_port\Debug\torture_su_port.exe +:: @if errorlevel 1 ( echo torture_su_port: FAIL ) else echo torture_su_port: PASS diff --git a/libs/sofia-sip/win32/config.h.in b/libs/sofia-sip/win32/config.h.in index 13bde115c4..c0b9f9ef08 100644 --- a/libs/sofia-sip/win32/config.h.in +++ b/libs/sofia-sip/win32/config.h.in @@ -32,10 +32,10 @@ * @date Created: Tue Sep 12 19:22:54 2000 ppessi */ -/* Define this as the random number source name. */ +/* Define to as the random number source name. */ #undef DEV_URANDOM -/* Define this as 1 if you have addrinfo structure. */ +/* Define to 1 if you have addrinfo structure. */ #define HAVE_ADDRINFO 1 /* Define to 1 if you have the `alarm' function. */ @@ -50,15 +50,21 @@ /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME -/* Define this as 1 if you have /dev/urandom. */ +/* Define to 1 if you have /dev/urandom. */ #undef HAVE_DEV_URANDOM +/* Define to 1 if you have the header file. */ +#undef HAVE_DIRENT_H + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H -/* Define to 1 if you have the `epoll' function. */ +/* Define to 1 if you have epoll interface. */ #undef HAVE_EPOLL +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + /* Define this as 1 if you have WIN32 FILETIME type and GetSystemTimeAsFileTime(). */ #define HAVE_FILETIME 1 @@ -69,10 +75,10 @@ /* Define to 1 if you have the `freeaddrinfo' function. */ #define HAVE_FREEADDRINFO 1 -/* Define as 1 if the C compiler supports __func__ */ +/* Define to 1 if the C compiler supports __func__ */ #undef HAVE_FUNC -/* Define as 1 if the C compiler supports __FUNCTION__ */ +/* Define to 1 if the C compiler supports __FUNCTION__ */ #undef HAVE_FUNCTION /* Define to 1 if you have the `gai_strerror' function. */ @@ -111,16 +117,16 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IFADDR_H -/* Define this as 1 if you have SIOCGIFCONF */ +/* Define to 1 if you have SIOCGIFCONF */ #undef HAVE_IFCONF -/* Define this as 1 if you have SIOCGIFNUM ioctl */ +/* Define to 1 if you have SIOCGIFNUM ioctl */ #undef HAVE_IFNUM -/* Define this as 1 if you have ifr_ifindex in */ +/* Define to 1 if you have ifr_ifindex in */ #undef HAVE_IFR_IFINDEX -/* Define this as 1 if you have ifr_index in */ +/* Define to 1 if you have ifr_index in */ #undef HAVE_IFR_INDEX /* Define to 1 if you have the `if_nameindex' function. */ @@ -135,23 +141,23 @@ /* Define to 1 if you have the `initstate' function. */ #undef HAVE_INITSTATE -/* Define this as 1 if you have inlining compiler */ +/* Define to 1 if you have inlining compiler */ #define HAVE_INLINE 1 -/* Define this as 1 if you have WIN32 INTERFACE_INFO_EX type. */ +/* Define to 1 if you have WIN32 INTERFACE_INFO_EX type. */ #undef HAVE_INTERFACE_INFO_EX /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H -/* Define as 1 you have WIN32 */ +/* Define to 1 if you have the header file. */ // XXX: vehmanek-win32-fix: #undef HAVE_IPHLPAPI_H -/* Define this as 1 if you have IPV6_RECVERR in */ +/* Define to 1 if you have IPV6_RECVERR in */ #undef HAVE_IPV6_RECVERR -/* Define this as 1 if you have IP_RECVERR in */ +/* Define to 1 if you have IP_RECVERR in */ #undef HAVE_IP_RECVERR /* Define to 1 if you have the `crypto' library (-lcrypto). */ @@ -181,9 +187,12 @@ /* Define to 1 if you have the `memspn' function. */ #undef HAVE_MEMSPN -/* Define this as 1 if you are compiling in MinGW environment */ +/* Define to 1 if you are compiling in MinGW environment */ #undef HAVE_MINGW +/* Define to 1 if you have MSG_TRUNC flag */ +#undef HAVE_MSG_TRUNC + /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H @@ -205,7 +214,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TYPES_H -/* Define this as 1 if you have OpenSSL */ +/* Define to 1 if you have OpenSSL */ #undef HAVE_OPENSSL /* Define to 1 if you have the header file. */ @@ -214,9 +223,19 @@ /* Define to 1 if you have the `poll' function. */ #undef HAVE_POLL -/* Define this as 1 if you have /proc/net/if_inet6 control file */ +/* Define to 1 if you use poll in su_port. */ +#define HAVE_POLL_PORT 1 + +/* Define to 1 if you have /proc/net/if_inet6 control file */ #undef HAVE_PROC_NET_IF_INET6 +/* Define to 1 if you have working pthread_rwlock_t implementation. A thread + may hold multiple concurrent read locks on rwlock - that is, successfully + call the pthread_rwlock_rdlock() function n times. If so, the application + shall ensure that the thread performs matching unlocks - that is, it calls + the pthread_rwlock_unlock() function n times. */ +#undef HAVE_PTHREAD_RWLOCK + /* Define to 1 if you have the header file. */ #define HAVE_PTHREAD_H 1 @@ -224,52 +243,61 @@ /* See later */ #define HAVE_RANDOM 1 -/* Define this as 1 if you have sa_len in struct sockaddr */ +/* Define to 1 if you have sa_len in struct sockaddr */ #undef HAVE_SA_LEN -/* Define this a 1 if you have SCTP */ +/* Define to 1 if you have SCTP */ #undef HAVE_SCTP /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT -/* Define this as 1 if you have Sofia sigcomp >= 2.5 */ +/* Define to 1 if you have Sofia sigcomp >= 2.5 */ #undef HAVE_SIGCOMP /* Define to 1 if you have the header file. */ #undef HAVE_SIGCOMP_H -/* Define as 1 if you have SIGPIPE */ +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have SIGPIPE */ #undef HAVE_SIGPIPE -/* Define this as 1 if you have IPv6 structures and constants */ +/* Define to 1 if you have IPv6 structures and constants */ #define HAVE_SIN6 1 -/* Define this as 1 if you have WIN32 WSAIoctl SIO_ADDRESS_LIST_QUERY. */ +/* Define to 1 if you have WIN32 WSAIoctl SIO_ADDRESS_LIST_QUERY. */ #define HAVE_SIO_ADDRESS_LIST_QUERY 1 /* Define to 1 if you have the `socketpair' function. */ #undef HAVE_SOCKETPAIR -/* Define this as 1 if you have Sofia sigcomp >= 2.5 */ +/* Define to 1 if we use NTH library */ +#define HAVE_SOFIA_NTH 1 + +/* Define to 1 if we use NTLM library */ +#undef HAVE_SOFIA_NTLM + +/* Define to 1 if you have Sofia sigcomp >= 2.5 */ #undef HAVE_SOFIA_SIGCOMP -/* Define as 1 always */ +/* Define to 1 always */ #define HAVE_SOFIA_SIP 1 -/* Define as 1 if we use S/MIME library */ +/* Define to 1 if we use S/MIME library */ #undef HAVE_SOFIA_SMIME -/* Define as 1 if we use DNS library */ +/* Define to 1 if we use DNS library */ #define HAVE_SOFIA_SRESOLV 1 -/* Define as 1 if we use STUN library */ +/* Define to 1 if we use STUN library */ #undef HAVE_SOFIA_STUN -/* Define as 1 always */ +/* Define to 1 always */ #define HAVE_SOFIA_SU 1 -/* Define as 1 if we use SRTP */ +/* Define to 1 if we use SRTP */ #undef HAVE_SRTP /* Define to 1 if you have the header file. */ @@ -293,15 +321,21 @@ /* Define to 1 if you have the `strtoull' function. */ #undef HAVE_STRTOULL -/* Define this as 1 if your CC supports C99 struct initialization */ +/* Define to 1 if your CC supports C99 struct initialization */ #undef HAVE_STRUCT_KEYWORDS /* Define to 1 if you have the header file. */ #define HAVE_SU_WAIT_H 1 +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_EPOLL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILIO_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H @@ -323,16 +357,16 @@ /* Define to 1 if you have the `tcsetattr' function. */ #undef HAVE_TCSETATTR -/* Define this as 1 if you have TLS */ +/* Define to 1 if you have TLS */ #undef HAVE_TLS /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define as 1 if we use UPnP */ +/* Define to 1 if we use UPnP */ #undef HAVE_UPNP -/* Define as 1 you have WIN32 */ +/* Define to 1 you have WIN32 */ #define HAVE_WIN32 1 /* Define to 1 if you have the header file. */ @@ -344,13 +378,13 @@ /* Define to 1 if you have the header file. */ #define HAVE_WS2TCPIP_H 1 -/* Define as format (%lli) for long long */ +/* Define to format (%lli) for long long */ #define LLI "%I64i" -/* Define as format (%llu) for unsigned long long */ +/* Define to format (%llu) for unsigned long long */ #define LLU "%I64u" -/* Define as format (%llx) for long long hex */ +/* Define to format (%llx) for long long hex */ #define LLX "%I64x" /* Name of package */ @@ -427,20 +461,20 @@ /* This is GCC magic */ #define __attribute__(x) -/* Define this as 1 if you have TimeGetTime() */ +/* Define to 1 if you have TimeGetTime() */ #define HAVE_TIMEGETTIME 1 #define PATH_MAX _MAX_PATH #define HAVE_WINMM 1 -/* Define this as 1 if you have FILETIME */ +/* Define to 1 if you have FILETIME */ #define HAVE_FILETIME 1 -/* Define this as 1 if you have WinSock2 ioctl SIO_ADDRESS_LIST_QUERY */ +/* Define to 1 if you have WinSock2 ioctl SIO_ADDRESS_LIST_QUERY */ #define HAVE_SIO_ADDRESS_LIST_QUERY 1 -/* Define this as 1 if you have INTERFACE_INFO ioctl */ +/* Define to 1 if you have INTERFACE_INFO ioctl */ #define HAVE_INTERFACE_INFO (1) /* Ignore certain warnings */ diff --git a/libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj b/libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj new file mode 100644 index 0000000000..e95673a7c4 --- /dev/null +++ b/libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj @@ -0,0 +1,4353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.vcproj b/libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.vcproj new file mode 100644 index 0000000000..c0ee45fc16 --- /dev/null +++ b/libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.vcproj @@ -0,0 +1,4400 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_htable/test_htable.vcproj b/libs/sofia-sip/win32/tests/test_htable/test_htable.vcproj new file mode 100644 index 0000000000..f902eed6fb --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_htable/test_htable.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_memmem/test_memmem.vcproj b/libs/sofia-sip/win32/tests/test_memmem/test_memmem.vcproj new file mode 100644 index 0000000000..3e396b2237 --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_memmem/test_memmem.vcproj @@ -0,0 +1,237 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_nta/test_nta.vcproj b/libs/sofia-sip/win32/tests/test_nta/test_nta.vcproj new file mode 100644 index 0000000000..cd82d5b6f7 --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_nta/test_nta.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_nua/test_nua.vcproj b/libs/sofia-sip/win32/tests/test_nua/test_nua.vcproj new file mode 100644 index 0000000000..2a759a6666 --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_nua/test_nua.vcproj @@ -0,0 +1,669 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_su/test_su.vcproj b/libs/sofia-sip/win32/tests/test_su/test_su.vcproj new file mode 100644 index 0000000000..7f4a2ee533 --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_su/test_su.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/test_tport/test_tport.vcproj b/libs/sofia-sip/win32/tests/test_tport/test_tport.vcproj new file mode 100644 index 0000000000..7eac861383 --- /dev/null +++ b/libs/sofia-sip/win32/tests/test_tport/test_tport.vcproj @@ -0,0 +1,289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_rbtree/torture_rbtree.vcproj b/libs/sofia-sip/win32/tests/torture_rbtree/torture_rbtree.vcproj new file mode 100644 index 0000000000..59e2d7f6e4 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_rbtree/torture_rbtree.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su/torture_su.vcproj b/libs/sofia-sip/win32/tests/torture_su/torture_su.vcproj new file mode 100644 index 0000000000..2cbd7af42c --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su/torture_su.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_alloc/torture_su_alloc.vcproj b/libs/sofia-sip/win32/tests/torture_su_alloc/torture_su_alloc.vcproj new file mode 100644 index 0000000000..aadb551938 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_alloc/torture_su_alloc.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_bm/torture_su_bm.vcproj b/libs/sofia-sip/win32/tests/torture_su_bm/torture_su_bm.vcproj new file mode 100644 index 0000000000..29a00a34a8 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_bm/torture_su_bm.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_port/torture_su_port.vcproj b/libs/sofia-sip/win32/tests/torture_su_port/torture_su_port.vcproj new file mode 100644 index 0000000000..1da158bd55 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_port/torture_su_port.vcproj @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_root/torture_su_root.vcproj b/libs/sofia-sip/win32/tests/torture_su_root/torture_su_root.vcproj new file mode 100644 index 0000000000..0d1b17c268 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_root/torture_su_root.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_tag/torture_su_tag.vcproj b/libs/sofia-sip/win32/tests/torture_su_tag/torture_su_tag.vcproj new file mode 100644 index 0000000000..ff2a2e270f --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_tag/torture_su_tag.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_time/torture_su_time.vcproj b/libs/sofia-sip/win32/tests/torture_su_time/torture_su_time.vcproj new file mode 100644 index 0000000000..5e627eb26b --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_time/torture_su_time.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/tests/torture_su_timer/torture_su_timer.vcproj b/libs/sofia-sip/win32/tests/torture_su_timer/torture_su_timer.vcproj new file mode 100644 index 0000000000..80dff8d2d8 --- /dev/null +++ b/libs/sofia-sip/win32/tests/torture_su_timer/torture_su_timer.vcproj @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/utils/localinfo/localinfo.vcproj b/libs/sofia-sip/win32/utils/localinfo/localinfo.vcproj new file mode 100644 index 0000000000..d58de10d9f --- /dev/null +++ b/libs/sofia-sip/win32/utils/localinfo/localinfo.vcproj @@ -0,0 +1,282 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/utils/sip_dig/sip_dig.vcproj b/libs/sofia-sip/win32/utils/sip_dig/sip_dig.vcproj new file mode 100644 index 0000000000..106dba2059 --- /dev/null +++ b/libs/sofia-sip/win32/utils/sip_dig/sip_dig.vcproj @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/utils/sip_options/sip_options.vcproj b/libs/sofia-sip/win32/utils/sip_options/sip_options.vcproj new file mode 100644 index 0000000000..8769020b04 --- /dev/null +++ b/libs/sofia-sip/win32/utils/sip_options/sip_options.vcproj @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/utils/sip_options_static/sip_options_static.vcproj b/libs/sofia-sip/win32/utils/sip_options_static/sip_options_static.vcproj new file mode 100644 index 0000000000..4c6b680dd8 --- /dev/null +++ b/libs/sofia-sip/win32/utils/sip_options_static/sip_options_static.vcproj @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/utils/stunc/stunc.vcproj b/libs/sofia-sip/win32/utils/stunc/stunc.vcproj new file mode 100644 index 0000000000..662fc85f17 --- /dev/null +++ b/libs/sofia-sip/win32/utils/stunc/stunc.vcproj @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/sofia-sip/win32/version_files.cmd b/libs/sofia-sip/win32/version_files.cmd index d18adf962d..840a206b4a 100644 --- a/libs/sofia-sip/win32/version_files.cmd +++ b/libs/sofia-sip/win32/version_files.cmd @@ -26,14 +26,15 @@ :: @setlocal -@if x%AWK%==x set AWK=gawk +@if x%AWK%==x set AWK=mawk @set VERSION=%AWK% -v BINMODE="rw" -f version.awk @set AC=..\configure.ac :: Check that we really have awk @%AWK% "{ exit(0); }" < NUL >NUL @if not errorlevel 9009 goto have_awk -@echo *** install %AWK% (GNU awk) into your PATH *** +@echo *** install %AWK% (mawk or GNU awk) into your PATH *** +@echo *** see http://gnuwin32.sourceforge.net/packages/mawk.htm *** @goto end :have_awk