merge changes from current sofia-sip tree.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4153 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2007-02-07 21:59:38 +00:00
parent 7f8c4decad
commit cad28828b2
212 changed files with 36824 additions and 13384 deletions

View File

@ -1 +1 @@
Wed Jan 17 17:00:56 EST 2007
Wed Feb 7 16:58:19 EST 2007

View File

@ -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

View File

@ -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

View File

@ -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
----------

View File

@ -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 <sofia-sip/sip_extra.h> 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 <sofia-sip/sip_extra.h> 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 <sofia-sip/sip_extra.h> 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.
<information about major new features
- new/changed/removed functionality
- links to further documentation
@ -88,7 +131,13 @@ Bugs fixed in this release
/>
- **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.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define to 1 if you have the <arpa/inet.h> 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 <sigcomp.h> 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 <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
/* Define to 1 if you have the <sys/filio.h> 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

View File

@ -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 <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
#
@ -70,7 +71,7 @@ Report bugs and patches to <config-patches@gnu.org>."
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)

5612
libs/sofia-sip/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -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 <signal.h>
])
### checks for types
### ----------------

View File

@ -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
================

View File

@ -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
--------

View File

@ -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

View File

@ -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.

View File

@ -58,4 +58,4 @@ AUTOMAKE_OPTIONS = foreign
# ----------------------------------------------------------------------
# Sofia specific rules
include ../../libsofia-sip-ua/sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -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

View File

@ -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 <Pekka.Pessi@nokia.com>.
*
* @date Created: Thu Mar 4 15:15:15 2004 ppessi
@ -36,12 +40,6 @@
#include "config.h"
#endif
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <glib.h>
#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 <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#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);
}

View File

@ -0,0 +1,269 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005,2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* 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 <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <first.surname@nokia.com>
*
* @internal
*
* @date Created: Fri Oct 19 08:53:55 2001 pessi
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <assert.h>
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 <sofia-sip/su_glib.h>
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;
}

View File

@ -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

View File

@ -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 ; \

View File

@ -43,4 +43,5 @@ TESTS = torture_bnf
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -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) {

View File

@ -45,4 +45,5 @@ ALIASES = \
"VERSION_1_12_4=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.4.txt\">1.12.4</a>" \
"VERSION_1_12_5=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.5.txt\">1.12.5</a>" \
"NEW_1_12_5=@since New in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.5.txt\">1.12.5</a>" \
"EXP_1_12_5=@since Experimental in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.5.txt\">1.12.5</a>, available if --enable-experimental configuration option is given" \

View File

@ -47,4 +47,4 @@ CLEANFILES = Doxyfile.rfc
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -31,4 +31,5 @@ EXTRA_DIST = Doxyfile features.docs
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -51,4 +51,5 @@ EXTRA_DIST += Doxyfile ipt.docs
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -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 */

View File

@ -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

View File

@ -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.

View File

@ -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;
}

View File

@ -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 <sys/file.h>
#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

View File

@ -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";

View File

@ -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 */

View File

@ -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"),

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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, \

View File

@ -59,4 +59,5 @@ EXTRA_DIST = Doxyfile nea.docs $(BUILT_SOURCES)
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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;)

View File

@ -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;
}

View File

@ -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 */

View File

@ -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,

View File

@ -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)

View File

@ -654,7 +654,7 @@ int readfile(FILE *f, void **contents)
*contents = buffer;
return len;
return (int)len;
}
#if HAVE_DIRENT_H

View File

@ -63,4 +63,4 @@ EXTRA_DIST = Doxyfile nth.docs $(BUILT_SOURCES) \
# ----------------------------------------------------------------------
# Sofia specific rules
include ../sofia.am
include $(top_srcdir)/rules/sofia.am

View File

@ -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.

View File

@ -38,7 +38,10 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#if HAVE_SIGNAL
#include <signal.h>
#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) {

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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 <sofia-sip/su_debug.h>, 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 <sofia-sip/tport_tag.h>
*
* @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;

View File

@ -1124,7 +1124,7 @@ follows:
<td>terminating</td>
<td>Process answer</td>
<td>
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.
</td></tr>
@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -48,36 +48,72 @@ typedef NUA_OWNER_T nua_owner_t;
#include <sofia-sip/nta.h>
#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 */

View File

@ -45,9 +45,6 @@
#include <sofia-sip/sip_status.h>
#include <sofia-sip/su_tagarg.h>
#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);
}

View File

@ -43,17 +43,8 @@
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#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,
};

View File

@ -43,9 +43,6 @@
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#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;
}

File diff suppressed because it is too large Load Diff

View File

@ -45,9 +45,6 @@
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#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);
}

View File

@ -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);

View File

@ -45,9 +45,6 @@
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#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;
}

View File

@ -27,6 +27,7 @@
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti.Mela@nokia.com>
* @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
*
* @date Created: Wed Mar 8 11:48:49 EET 2006 ppessi
*/
@ -45,8 +46,6 @@
#include <sofia-sip/sip_util.h>
#include <sofia-sip/sip_status.h>
#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);

View File

@ -44,8 +44,6 @@
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sip_util.h>
#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,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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, ...);

View File

@ -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
* <a href="http://www.ietf.org/rfc/rfc3265.txt">RFC 3265</a>
* 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

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -35,6 +35,8 @@
#include "test_nua.h"
#include <sofia-sip/tport_tag.h>
#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");

View File

@ -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;
}

View File

@ -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. */

View File

@ -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))

View File

@ -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);

View File

@ -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() */

View File

@ -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)

View File

@ -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, ...)
{

View File

@ -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();
}

Some files were not shown because too many files have changed in this diff Show More