]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sync with latest sofia tree.
authorMichael Jerris <mike@jerris.com>
Mon, 6 Aug 2007 19:24:10 +0000 (19:24 +0000)
committerMichael Jerris <mike@jerris.com>
Mon, 6 Aug 2007 19:24:10 +0000 (19:24 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5574 d0543943-73ff-0310-b7d9-9358b9ac24b2

154 files changed:
libs/sofia-sip/RELEASE
libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source.c
libs/sofia-sip/libsofia-sip-ua-glib/su-glib/su_source_test.c
libs/sofia-sip/libsofia-sip-ua/bnf/torture_bnf.c
libs/sofia-sip/libsofia-sip-ua/docs/Doxyfile.aliases
libs/sofia-sip/libsofia-sip-ua/docs/conformance.docs
libs/sofia-sip/libsofia-sip-ua/features/features.c
libs/sofia-sip/libsofia-sip-ua/http/http.docs
libs/sofia-sip/libsofia-sip-ua/http/http_basic.c
libs/sofia-sip/libsofia-sip-ua/http/test_http.c
libs/sofia-sip/libsofia-sip-ua/ipt/Makefile.am
libs/sofia-sip/libsofia-sip-ua/ipt/ipt.docs
libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c
libs/sofia-sip/libsofia-sip-ua/iptsec/auth_tag.c
libs/sofia-sip/libsofia-sip-ua/iptsec/iptsec.docs
libs/sofia-sip/libsofia-sip-ua/iptsec/iptsec_debug.c
libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_module.h
libs/sofia-sip/libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h
libs/sofia-sip/libsofia-sip-ua/iptsec/test_auth_digest.c
libs/sofia-sip/libsofia-sip-ua/msg/test_class.c
libs/sofia-sip/libsofia-sip-ua/msg/test_table.c.in
libs/sofia-sip/libsofia-sip-ua/nea/nea.docs
libs/sofia-sip/libsofia-sip-ua/nea/nea_debug.c
libs/sofia-sip/libsofia-sip-ua/nta/Doxyfile.in
libs/sofia-sip/libsofia-sip-ua/nta/nta.c
libs/sofia-sip/libsofia-sip-ua/nta/nta.docs
libs/sofia-sip/libsofia-sip-ua/nta/nta_internal.h
libs/sofia-sip/libsofia-sip-ua/nta/nta_tag.c
libs/sofia-sip/libsofia-sip-ua/nta/sofia-sip/nta_tag.h
libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c
libs/sofia-sip/libsofia-sip-ua/nta/test_nta_api.c
libs/sofia-sip/libsofia-sip-ua/nth/nth.docs
libs/sofia-sip/libsofia-sip-ua/nth/nth_client.c
libs/sofia-sip/libsofia-sip-ua/nth/nth_server.c
libs/sofia-sip/libsofia-sip-ua/nua/nua.c
libs/sofia-sip/libsofia-sip-ua/nua/nua.docs
libs/sofia-sip/libsofia-sip-ua/nua/nua_common.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_extension.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_message.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_options.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_params.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_publish.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.h
libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
libs/sofia-sip/libsofia-sip-ua/nua/outbound.c
libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua.h
libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.c
libs/sofia-sip/libsofia-sip-ua/nua/test_cancel_bye.c
libs/sofia-sip/libsofia-sip-ua/nua/test_init.c
libs/sofia-sip/libsofia-sip-ua/nua/test_nat.c
libs/sofia-sip/libsofia-sip-ua/nua/test_nua.c
libs/sofia-sip/libsofia-sip-ua/nua/test_nua.h
libs/sofia-sip/libsofia-sip-ua/nua/test_nua_api.c
libs/sofia-sip/libsofia-sip-ua/nua/test_proxy.c
libs/sofia-sip/libsofia-sip-ua/sdp/sdp.c
libs/sofia-sip/libsofia-sip-ua/sip/sip.docs
libs/sofia-sip/libsofia-sip-ua/sip/sip_bad_mask
libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c
libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c
libs/sofia-sip/libsofia-sip-ua/sip/sip_extra_headers.txt
libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_extra.h.in
libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h
libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
libs/sofia-sip/libsofia-sip-ua/soa/soa.c
libs/sofia-sip/libsofia-sip-ua/soa/soa_tag.c
libs/sofia-sip/libsofia-sip-ua/soa/test_soa.c
libs/sofia-sip/libsofia-sip-ua/sresolv/Makefile.am
libs/sofia-sip/libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h
libs/sofia-sip/libsofia-sip-ua/sresolv/sres.c
libs/sofia-sip/libsofia-sip-ua/sresolv/sres_cache.c
libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c
libs/sofia-sip/libsofia-sip-ua/sresolv/torture_sresolv.c [new file with mode: 0644]
libs/sofia-sip/libsofia-sip-ua/stun/stun_tag.c
libs/sofia-sip/libsofia-sip-ua/su/Doxyfile.in
libs/sofia-sip/libsofia-sip-ua/su/Makefile.am
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/heap.h [new file with mode: 0644]
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su.h
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_config.h
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_configure.h.in
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_time.h
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_types.h
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
libs/sofia-sip/libsofia-sip-ua/su/su.c
libs/sofia-sip/libsofia-sip-ua/su/su.docs
libs/sofia-sip/libsofia-sip-ua/su/su_addrinfo.c
libs/sofia-sip/libsofia-sip-ua/su/su_base_port.c
libs/sofia-sip/libsofia-sip-ua/su/su_default_log.c
libs/sofia-sip/libsofia-sip-ua/su/su_global_log.c
libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c
libs/sofia-sip/libsofia-sip-ua/su/su_log.c
libs/sofia-sip/libsofia-sip-ua/su/su_open_c_localinfo.cpp [new file with mode: 0644]
libs/sofia-sip/libsofia-sip-ua/su/su_port.h
libs/sofia-sip/libsofia-sip-ua/su/su_pthread_port.c
libs/sofia-sip/libsofia-sip-ua/su/su_root.c
libs/sofia-sip/libsofia-sip-ua/su/su_taglist.c
libs/sofia-sip/libsofia-sip-ua/su/su_time.c
libs/sofia-sip/libsofia-sip-ua/su/su_time0.c
libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
libs/sofia-sip/libsofia-sip-ua/su/tag_dll.awk
libs/sofia-sip/libsofia-sip-ua/su/test_poll.c
libs/sofia-sip/libsofia-sip-ua/su/torture_heap.c [new file with mode: 0644]
libs/sofia-sip/libsofia-sip-ua/su/torture_su_tag.c
libs/sofia-sip/libsofia-sip-ua/su/torture_su_time.c
libs/sofia-sip/libsofia-sip-ua/su/torture_su_timer.c
libs/sofia-sip/libsofia-sip-ua/tport/test_tport.c
libs/sofia-sip/libsofia-sip-ua/tport/tport.c
libs/sofia-sip/libsofia-sip-ua/tport/tport_internal.h
libs/sofia-sip/libsofia-sip-ua/tport/tport_logging.c
libs/sofia-sip/libsofia-sip-ua/tport/tport_type_tls.c
libs/sofia-sip/open_c/build_sources.cmd
libs/sofia-sip/open_c/config.h.in
libs/sofia-sip/open_c/group/bld.inf
libs/sofia-sip/open_c/group/libsofia-sip-ua-glib.mmp [new file with mode: 0644]
libs/sofia-sip/open_c/group/libsofia-sip-ua.mmp
libs/sofia-sip/open_c/group/su_source_test.mmp [new file with mode: 0644]
libs/sofia-sip/open_c/group/su_source_test_reg.rss [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_http.mmp [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_http_reg.rss [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_msg.mmp
libs/sofia-sip/open_c/group/test_msg_reg.rss
libs/sofia-sip/open_c/group/test_nua.mmp [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_nua_reg.rss [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_tport.mmp [new file with mode: 0644]
libs/sofia-sip/open_c/group/test_tport_reg.rss [new file with mode: 0644]
libs/sofia-sip/open_c/group/torture_sip.mmp
libs/sofia-sip/open_c/group/torture_sip_reg.rss
libs/sofia-sip/open_c/group/torture_su_alloc.mmp
libs/sofia-sip/open_c/group/torture_su_alloc_reg.rss
libs/sofia-sip/open_c/group/torture_su_root.mmp
libs/sofia-sip/open_c/group/torture_su_root_reg.rss
libs/sofia-sip/open_c/group/torture_su_tag.mmp
libs/sofia-sip/open_c/group/torture_su_tag_reg.rss
libs/sofia-sip/open_c/group/torture_url.mmp
libs/sofia-sip/open_c/group/torture_url_reg.rss
libs/sofia-sip/open_c/sis/libsofia-sip-ua-glib.pkg [new file with mode: 0644]
libs/sofia-sip/open_c/sis/libsofia-sip-ua.pkg [new file with mode: 0644]
libs/sofia-sip/open_c/sis/su_source_test.pkg [new file with mode: 0644]
libs/sofia-sip/open_c/sis/test_nua.pkg [new file with mode: 0644]
libs/sofia-sip/open_c/sis/test_tport.pkg [new file with mode: 0644]
libs/sofia-sip/utils/Doxyfile.in
libs/sofia-sip/utils/Makefile.am
libs/sofia-sip/utils/sip-options.c
libs/sofia-sip/utils/utils.docs [new file with mode: 0644]
libs/sofia-sip/win32/README.txt
libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.dsp
libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj
libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.dsp
libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.vcproj
libs/sofia-sip/win32/sofia-sip/su_configure.h
libs/sofia-sip/win32/utils/stunc/stunc.vcproj

index bb7d836cfcec16cd0e0027cb21f2a91cb235299e..179f7b4d0ff9e93d4a0d2481a57b26626a496aed 100644 (file)
@@ -9,6 +9,9 @@ Changes since last release
  and in less than 10 lines, written in 3rd person English, with
  complete sentences />
 
+The stack now compiles and runs on Symbian SDK with Open C support
+enabled.
+
 Bugs in blaa and foo have been fixed. The stack now supports
 use of foobar...
 
@@ -24,10 +27,13 @@ API/ABI changes and versioning
 New features in API are marked with Doxytag macro @VERSION_1_12_7.
 
 libsofia-sip-ua:
+- Added access point selection functionality for Open C / Symbian
 - Removed extra system headers from <sofia-sip/stun_common.h>
 - Added global variable su_socket_blocking. If it is set to true,
   sockets are created as blocking.
 - Added accessor function nta_outgoing_branch()
+- Added SIP headers Alert-Info and Reply-To.
+- Added macros SIP_HAVE_XXXX for extra headers, e.g., SIP_HAVE_ALERT_INFO().
 - **template**: Added foobar() function (sofia-sip/foobar.h).
 - This release is ABI/API compatible with applications linked against 
   any 1.12.x release. However, applications built against this release won't 
@@ -52,7 +58,7 @@ Contributors to this release
  - roughly sorted by number of patches accepted
 /> 
 
-- **template**: First Surname (patch to nua/soa/msg)
+- Kai Vehmanen (fixes to win32 VC6/2005 project files)
 
 See the AUTHORS file in the distribution package.
 
@@ -65,6 +71,13 @@ Notes on new features
  - section may be omitted for minor releases
 /> 
 
+IPv6 support can now be disabled in VC6/VC2005 builds, by
+setting SU_HAVE_IN6 to zero `win32/sofia-sip/su_configure.h'.
+
+Symbian Open C build and packaging (SIS) files for libsofia-sip-ua,
+libsofia-sip-ua-glib and for several test apps have been added under
+sofia-sip/open_c.
+
 Bugs fixed in this release
 --------------------------
 
@@ -74,6 +87,5 @@ Bugs fixed in this release
  - other bugs as fixed in CVS/darcs
 />
 
-- **template**: #9499652 sf.net bug item title
 - Fixed #1472682 sf.net bug: ACK does not find INVITE when
   To URI has been changed.
index a2b4380dd5d1ae8c2cee4c69d432f71d4002603a..49d71d54037ab5456bfbb4bb663433d19c4a83eb 100644 (file)
  * 
  */
 
-#if HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <glib.h>
 
+#if HAVE_OPEN_C
+#include <glib/gthread.h>
+#include <glib_global.h>
+#endif
+
 #define SU_PORT_IMPLEMENTATION 1
 
 #define SU_MSG_ARG_T union { char anoymous[4]; }
index 465b116ff5699eb6cda2fabb6cfffd5d01467a22..559348b6fbe5ac462e1e2f59ec313ec2e3a983a6 100644 (file)
@@ -32,9 +32,7 @@
  * @date Created: Thu Mar 18 19:40:51 1999 pessi
  */
 
-#if HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <stdlib.h>
 #include <string.h>
@@ -52,6 +50,7 @@ struct pinger;
 #include "sofia-sip/su_wait.h"
 #include "sofia-sip/su_log.h"
 
+#include <glib/gthread.h>
 #include "sofia-sip/su_glib.h"
 
 struct pinger {
@@ -373,11 +372,13 @@ init_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg)
   }
 }
 
+#if HAVE_SIGNAL
 static
 RETSIGTYPE term(int n)
 {
   exit(1);
 }
+#endif
 
 void
 time_test(void)
@@ -433,6 +434,10 @@ int main(int argc, char *argv[])
 
   char *argv0 = argv[0];
 
+#if HAVE_OPEN_C
+  dup2(1, 2);
+#endif
+  
   while (argv[1]) {
     if (strcmp(argv[1], "-v") == 0) {
       opt_verbatim = 1;
@@ -457,7 +462,15 @@ int main(int argc, char *argv[])
     }
   }
 
+#if HAVE_OPEN_C
+  opt_verbatim = 1;
+  opt_singlethread = 1;
+  su_log_soft_set_level(su_log_default, 9);  
+#endif
+  
+#if HAVE_SIGNAL
   signal(SIGTERM, term);
+#endif
 
   su_init(); atexit(su_deinit);
 
@@ -509,9 +522,15 @@ int main(int argc, char *argv[])
     printf("%s exiting\n", argv0); 
 
 #ifndef HAVE_WIN32
+#if HAVE_SIGNAL
    if (sleeppid)
      kill(sleeppid, SIGTERM);
 #endif
+#endif
 
+#if HAVE_OPEN_C
+   sleep(7);
+#endif
+   
   return 0;
 }
index e977551b6cd612a5e384e25f53883b59f0d41545..75be3aedda591c8ca42f62143240b11fa409889d 100644 (file)
@@ -320,13 +320,14 @@ int host_test(void)
   TEST(host_has_domain_invalid("valid."), 0);
   TEST(host_has_domain_invalid("1-.invalid."), 0);
 
-  /* Invalid IP4 addresses (extra leading zeros) */
+  /* Invalid IP4 address (extra leading zeros) */
   TEST_1(!host_cmp("127.0.0.1", "127.0.0.01"));
-  TEST_1(!host_cmp("[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]", 
-                 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
   /* Invalid reference (extra leading zeros) */
   TEST_1(host_cmp("[0ffff:0ffff:0ffff:0ffff:0ffff:0ffff:255.255.255.255]", 
                  "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+#if SU_HAVE_IN6
+  TEST_1(!host_cmp("[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]", 
+                 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
   TEST_1(!host_cmp("::1", "::001"));
   TEST_1(!host_cmp("[::1]", "::1"));
   TEST_1(!host_cmp("[::1]", "::0.0.0.1"));
@@ -334,6 +335,7 @@ int host_test(void)
   TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1"));
   TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1"));
   TEST_1(!host_cmp("[::ffff:127.0.0.1]", "[::7f00:1]"));
+#endif
   TEST_1(host_cmp("::", "0.0.0.0"));
   TEST_1(host_cmp("::1", "0.0.0.1"));
 
index f8d84c85d98aca8d878eec1f1da43327cb32437b..720eb6ff99eb6d29c0cbb7c808c31b5472d1dbb4 100644 (file)
@@ -49,4 +49,7 @@ ALIASES = \
  "VERSION_1_12_6=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>" \
  "NEW_1_12_6=@since New in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>" \
  "EXP_1_12_6=@since Experimental in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>, available if --enable-experimental configuration option is given" \
+ "VERSION_1_12_7=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>" \
+ "NEW_1_12_7=@since New in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>" \
+ "EXP_1_12_7=@since Experimental in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>, available if --enable-experimental configuration option is given" \
 
index af392237a651e5852232f3811921fd07b764c40d..e3427d08b94188b8789e57e64e196f3cb1146904 100644 (file)
@@ -66,9 +66,9 @@ below.
    <th>Notes</td>
 </tr>
 
+<a name="3261"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3261"></a>
        @RFC3261: Basic SIP Protocol
     </th>
     <td>
@@ -90,9 +90,9 @@ below.
     </td>
 </tr>
 
+<a name="3261.19"></a> <a name="3261.20"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3261.19"></a> <a name="3261.20"></a>
        @RFC3261 Sections&nbsp;19&nbsp;and&nbsp;20:<br>
        Syntax and encoding
     </td>
@@ -116,6 +116,7 @@ below.
        @ref sip_accept "Accept",
        @ref sip_accept_encoding "Accept-Encoding",
        @ref sip_accept_language "Accept-Language",
+       @ref sip_alert_info "Alert-Info" (@VERSION_1_12_7),
        @ref sip_allow "Allow",
        @ref sip_authentication_info "Authentication-Info",
        @ref sip_authorization "Authorization",
@@ -142,6 +143,7 @@ below.
        @ref sip_proxy_authorization "Proxy-Authorization",
        @ref sip_proxy_require "Proxy-Require",
        @ref sip_record_route "Record-Route",
+       @ref sip_reply_to "Reply-To" (@VERSION_1_12_7),
        @ref sip_require "Require",
        @ref sip_retry_after "Retry-After",
        @ref sip_route "Route",
@@ -163,18 +165,15 @@ below.
         parsers.
     </td>
     <td>
-       - Unsupported headers:
-         Alert-Info,
-         Reply-To
        - Automatic escaping of reserved characters has not been
          implemented.
        - Using NUL (zero byte) in doublequoted strings has not been implemented
    </td>
 </tr>
 
+<a name="3261.18"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3261.18"></a>
        @RFC3261 Section 18:<br>
        UDP and TCP transports
     </th>
@@ -201,9 +200,9 @@ below.
     </td>
 </tr>
 
+<a name="3261.17"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3261.17"></a>
        @RFC3261 Section 17:<br> Transactions
     </th>
     <td>
@@ -214,7 +213,7 @@ below.
 
        Default values for SIP timers are those specified by @RFC3261. The
        defaults for T1, T1x64, T2 and T4 can be changed via
-        configuration tags defined in <nta_tag.h>.
+        configuration tags defined in <sofia-sip/nta_tag.h>.
     </td>
     <td>
        &nbsp;
@@ -222,9 +221,9 @@ below.
 </tr>
 
 
+<a name="3261.26"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3261.26"></a>
        @RFC3261 Section 26:<br> Security
     </th>
     <td>
@@ -234,19 +233,19 @@ below.
     </td>
     <td>
        Missing:
-       - TLS certificate checking
+       - Authorizing connections with TLS certificates
        - S/MIME
     </td>
 </tr>
 
+<a name="2617"></a>
 <tr valign=top>
     <th align="left">
-       <a name="2617"></a>
        @RFC2617: HTTP Digest Authentication
     </th>
     <td>
-       Sofia-SIP an authentication client and server modules implementing
-        HTTP Digest authentication.
+       Sofia-SIP includes authentication client and server modules
+       implementing HTTP Digest authentication.
 
        HTTP Digest is a simple challenge-response authentication
        scheme defined in @RFC2617 based on the UA sending a checksum
@@ -283,9 +282,9 @@ below.
     </td>
 </tr>
 
+<a name="3262"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3262"></a>
        @RFC3262: PRACK and 100rel
     </th>
     <td>
@@ -305,9 +304,9 @@ below.
     </td>
 </tr>
 
+<a name="3263"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3263"></a>
        @RFC3263: Locating SIP Servers
     </th>
     <td>
@@ -320,9 +319,9 @@ below.
     </td>
 </tr>
 
+<a name="3265"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3265"></a>
        @RFC3265: SIP Event Notifications
     </th>
     <td>
@@ -347,9 +346,9 @@ below.
     </td>
 </tr>
 
+<a name="2806"></a>
 <tr valign=top>
     <th align="left">
-       <a name="2806"></a>
        @RFC2806: tel URI
     </th>
     <td>
@@ -362,9 +361,9 @@ below.
     </td>
 </tr>
 
+<a name="2976"></a>
 <tr valign=top>
     <th align="left">
-       <a name="2976"></a>
        @RFC2976: INFO
     </th>
     <td>
@@ -377,9 +376,9 @@ below.
 </tr>
 
 
+<a name="3311"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3311"></a>
        @RFC3311: UPDATE
     </th>
     <td>
@@ -396,9 +395,9 @@ below.
 </tr>
 
 
+<a name="3313"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3313"></a>
        @RFC3313: Media Authentication
     </th>
     <td>
@@ -413,9 +412,9 @@ below.
 </tr>
 
 
+<a name="3323"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3323"></a>
        @RFC3323: Privacy
     </th>
     <td>
@@ -441,9 +440,9 @@ below.
 </tr>
 
 
+<a name="3326"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3326"></a>
        @RFC3326: Reason
     </th>
     <td>
@@ -457,9 +456,9 @@ below.
 </tr>
 
 
+<a name="3325"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3325"></a>
        @RFC3325: Asserted Identity
     </th>
     <td>
@@ -476,9 +475,9 @@ below.
     </td>
 </tr>
 
+<a name="3327"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3327"></a>
        @RFC3327: Path
     </th>
     <td>
@@ -493,9 +492,9 @@ below.
     </td>
 </tr>
 
+<a name="3329"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3329"></a>
        @RFC3329:
        Security Agreement
     </th>
@@ -517,9 +516,9 @@ below.
     </td>
 </tr>
 
+<a name="3361"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3361"></a>
        @RFC3361: DHCPv4 option for locating SIP servers.
     </th>
     <td>
@@ -532,9 +531,9 @@ below.
     </td>
 </tr>
 
+<a name="3420"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3420"></a>
        @RFC3420: message/sipfrag
     </th>
     <td>
@@ -547,9 +546,9 @@ below.
     </td>
 </tr>
 
+<a name="3428"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3428"></a>
        @RFC3428: MESSAGE
     </th>
     <td>
@@ -560,9 +559,9 @@ below.
     </td>
 </tr>
 
+<a name="3486"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3486"></a>
        @RFC3486: Compressing SIP
     </th>
     <td>
@@ -575,9 +574,9 @@ below.
     </td>
 </tr>
 
+<a name="3515"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3515"></a>
        @RFC3515: REFER
     </th>
     <td>
@@ -600,9 +599,9 @@ below.
     </td>
 </tr>
 
+<a name="3608"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3608"></a>
        @RFC3608: Service-Route
     </th>
     <td>
@@ -619,9 +618,9 @@ below.
     </td>
 </tr>
 
+<a name="3680"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3680"></a>
        @RFC3680: "reg" event
     </th>
     <td>
@@ -643,9 +642,9 @@ below.
     </td>
 </tr>
 
+<a name="3824"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3824"></a>
        @RFC3824: ENUM
     </th>
     <td>
@@ -659,9 +658,9 @@ below.
     </td>
 </tr>
 
+<a name="3840"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3840"></a>
        @RFC3840: Callee Capabilities
     </th>
     <td>
@@ -681,9 +680,9 @@ below.
 </tr>
 
 
+<a name="3841"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3841"></a>
        @RFC3841: Caller Preferences
     </th>
     <td>
@@ -712,9 +711,9 @@ below.
     </td>
 </tr>
 
+<a name="3842"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3842"></a>
        @RFC3842: Message waiting event
     </th>
     <td>
@@ -734,9 +733,9 @@ below.
     </td>
 </tr>
 
+<a name="3856"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3856"></a>
        @RFC3856: Presence
     </th>
     <td>
@@ -760,9 +759,9 @@ below.
     </td>
 </tr>
 
+<a name="3857"></a> <a name="3858"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3857"></a> <a name="3858"></a>
        @RFC3857: "winfo" event template package<br>
        @RFC3858: winfo format
     </th>
@@ -783,9 +782,9 @@ below.
     </td>
 </tr>
 
+<a name="3891"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3891"></a>
        @RFC3891: Replaces
     </th>
     <td>
@@ -799,9 +798,9 @@ below.
     </td>
 </tr>
 
+<a name="3892"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3892"></a>
        @RFC3892: Referred-By
     </th>
     <td>
@@ -819,9 +818,9 @@ below.
     </td>
 </tr>
 
+<a name="3903"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3903"></a>
        @RFC3903: PUBLISH
     </th>
     <td>
@@ -839,9 +838,9 @@ below.
     </td>
 </tr>
 
+<a name="4028"></a>
 <tr valign=top>
     <th align="left">
-       <a name="4028"></a>
        @RFC4028: Session Timers
     </th>
     <td>
@@ -865,9 +864,9 @@ below.
     </td>
 </tr>
 
+<a name="4320"></a>
 <tr valign=top>
     <th align="left">
-       <a name="4320"></a>
        @RFC4320: Actions Addressing Identified Issues with SIP's Non-INVITE Transaction
     </th>
     <td>
@@ -896,10 +895,12 @@ below.
    <th>Notes</td>
 </tr>
 
+<a name="4566"></a>
+<a name="2327"></a>
+<a name="3266"></a>
 <tr valign=top>
     <th align="left" align="left">
-       <a name="2327"></a>
-       @RFC2327: SDP (Session Description Protocol)
+       @RFC4566: SDP: Session Description Protocol
     </th>
     <td>
        Generic support (generating, parsing and syntax checking) for SDP.
@@ -920,17 +921,20 @@ below.
        The attributes "a=sendrecv", "a=sendonly", "a=recvonly",
        "a=inactive", @ref sdp_rtpmap_s "a=rtpmap", and "a=fmtp" are parsed.
 
-       The implementation tries to follow draft-ietf-mmusic-sdp-new-25,
-       draft Internet Standard for SDP in progress.
+       The implementation partially implements @RFC4566. Note that
+       definiton of 'token' was updated in @RFC4566 and the parser has not
+       been updated yet.
     </td>
     <td>
-    - see also <a href="#4566">RFC 4566</a>
+      @RFC4566 obsoletes
+      - @RFC2327: SDP (Session Description Protocol)
+      - @RFC3266: IP6 in SDP
     </td>
 </tr>
 
+<a name="3264"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3264"></a>
        @RFC3264: SDP Offer/Answer Negotiation
     </th>
     <td>
@@ -942,22 +946,9 @@ below.
     </td>
 </tr>
 
+<a name="3312"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3266"></a>
-       @RFC3266: IP6 in SDP
-    </th>
-    <td>
-       Representation of IP6 addresses within SDP message.
-    </td>
-    <td>
-    - see also <a href="#4566">RFC 4566</a>
-    </td>
-</tr>
-
-<tr valign=top>
-    <th align="left">
-       <a name="3312"></a>
        @RFC3312: Preconditions
     </th>
     <td>
@@ -978,9 +969,9 @@ below.
     </td>
 </tr>
 
+<a name="3388"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3388"></a>
        @RFC3388: Grouping of Media Lines
     </th>
     <td>
@@ -998,9 +989,9 @@ below.
 </tr>
 
 
+<a name="3407"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3407"></a>
        @RFC3407: Capability Declaration
     </th>
     <td>
@@ -1016,9 +1007,9 @@ below.
 </tr>
 
 
+<a name="3524"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3524"></a>
        @RFC3524: SRF
     </th>
     <td>
@@ -1032,9 +1023,9 @@ below.
     </td>
 </tr>
 
+<a name="3556"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3556"></a>
        @RFC3556: Bandwidth
     </th>
     <td>
@@ -1048,9 +1039,9 @@ below.
     </td>
 </tr>
 
+<a name="3605"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3605"></a>
        @RFC3605: RTCP attribute
     </th>
     <td>
@@ -1064,9 +1055,9 @@ below.
     </td>
 </tr>
 
+<a name="3890"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3890"></a>
        @RFC3890: TIAS
     </th>
     <td>
@@ -1080,9 +1071,16 @@ below.
     </td>
 </tr>
 
+</table>
+
+
+*/
+
+/* Overflow:
+
+<a name="4566"></a>
 <tr valign=top>
     <th align="left">
-       <a name="4566"></a>
        @RFC4566: SDP: Session Description Protocol
     </th>
     <td>
@@ -1093,15 +1091,10 @@ below.
     </td>
 </tr>
 
-</table>
-
-*/
-
-/* Overflow:
 
+<a name="3320"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3320"></a>
        @RFC3320: SigComp
     </th>
     <td>
@@ -1116,9 +1109,9 @@ below.
     </td>
 </tr>
 
+<a name="3321"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3321"></a>
        @RFC3321: SigComp Extended operations
     </th>
     <td>
@@ -1132,9 +1125,9 @@ below.
     </td>
 </tr>
 
+<a name="3325"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3325"></a>
        @RFC3325: Asserted Identity
     </th>
     <td>
@@ -1147,9 +1140,9 @@ below.
     </td>
 </tr>
 
+<a name="3485"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3485"></a>
        @RFC3485: SIP/SDP Dictionary
     </th>
     <td>
@@ -1166,9 +1159,9 @@ below.
 
        - Implicitly registered user identities
 
+<a name="3959"></a>
 <tr valign=top>
     <th align="left">
-       <a name="3959"></a>
        @RFC3959: early-session
     </th>
     <td>
index cdfab1d59980657da9b46c1bc8c1a83f2e437e38..36d1bc9f18cf865f2730c0627c73ac0f0680b136 100644 (file)
@@ -35,7 +35,7 @@
 #include <stddef.h>
 
 #include <sofia-sip/su_configure.h>
-#include <tport_tls.h>
+#include "tport_tls.h"
 #include "sofia-sip/sofia_features.h"
 
 /** The name and version of software package providing Sofia-SIP-UA library.
index c27af26d88b6b885390dff035045349cc2ebc4a7..c38bd445f0598c2c15f73957736cfe34933e5104 100644 (file)
@@ -20,7 +20,7 @@
  * documented in a <a href="modules.html">submodule</a> for the header. In
  * addition to the header structure, there is defined a @em header @em class
  * structure and some standard functions for each header in the
- * <http_header.h> include file. For header @c X, there are types,
+ * <sofia-sip/http_header.h> include file. For header @c X, there are types,
  * functions, macros and header class as follows:
  *
  *  - @c http_X_t is the structure used to store parsed header,
index 0b6f006b8852694e3781ccd23fa27c400f088ee5..1e662a81bbe6010dbfeeb8309eff0ac2a224c697 100644 (file)
@@ -140,7 +140,7 @@ char *http_request_dup_one(http_header_t *dst, http_header_t const *src,
  *
  * Note that version string is not copied; it @b MUST remain constant during
  * lifetime of the @c http_request_t object. You can use constants
- * http_version_1_1 or http_version_1_0 declared in <http_header.h>.
+ * http_version_1_1 or http_version_1_0 declared in <sofia-sip/http_header.h>.
  */
 http_request_t *http_request_create(su_home_t *home,
                                    http_method_t method, char const *name,
index 3b76a2b7bb219ae5c8defddfc5542aa93ff5c197..118ea59f0b51d3b95c4fc705f9838a8c0a9a8a8f 100644 (file)
@@ -112,6 +112,10 @@ int main(int argc, char *argv[])
       usage(1);
   }
 
+#if HAVE_OPEN_C
+  tstflags |= tst_verbatim;
+#endif
+
   if (!test_mclass)
     test_mclass = http_default_mclass();
 
@@ -125,6 +129,10 @@ int main(int argc, char *argv[])
   retval |= http_chunk_test(); fflush(stdout);
   retval |= test_query_parser(); fflush(stdout);
 
+#if HAVE_OPEN_C
+  sleep(5);
+#endif
+
   return retval;
 }
 
index 4aa97b0a1f3aa0e70a5a022c69f4a4128a9e2141..aa7358ba43dc0f303fb01f2b45c5252977d684e0 100644 (file)
@@ -23,14 +23,14 @@ TESTS =             torture_base64
 # Rules for building the targets
 
 nobase_include_sofia_HEADERS = \
-                       sofia-sip/rc4.h \
                        sofia-sip/base64.h \
-                 sofia-sip/token64.h \
+                       sofia-sip/token64.h \
                        sofia-sip/uniqueid.h
 
 libipt_la_SOURCES =    base64.c token64.c
 
 EXTRA_DIST =           sofia-sip/utf8.h \
+                       sofia-sip/rc4.h \
                        utf8internal.h \
                        utf8.c ucs2.c ucs4.c rc4.c \
                        utf8test.c
index 049f59ef3d6c6c25962c944382ce7ced3b4db4b0..31ead585dacdeab1cc35e9041455cb5201d06e83 100644 (file)
@@ -15,9 +15,6 @@
  * @section ipt_overview Overview
  *
  * This module contain some routines useful for IPT applications, like 
- * - base64.h BASE64 encoding/decoding, 
- * - token64.h encoding/decoding binary as SIP/HTTP token, 
- * - utf8.h UTF8 encoding/decoding, 
- * - sha1.h SHA1 hash routines, and
- * - rc4.h arcfour random number generator.
+ * - <sofia-sip/base64.h> BASE64 encoding/decoding, 
+ * - <sofia-sip/token64.h> encoding/decoding binary as SIP/HTTP token, 
  */
index c845d39249aff989ee90cf515c836a8acfbf7d82..4121fa3c58a836e648b165debd86ffa7110ce2c7 100644 (file)
@@ -133,6 +133,7 @@ int auth_init_default(auth_mod_t *am,
   char const *realm = NULL, *opaque = NULL, *db = NULL, *allows = NULL;
   char const *qop = NULL, *algorithm = NULL;
   unsigned expires = 60 * 60, next_expires = 5 * 60;
+  unsigned max_ncount = 0;
   unsigned blacklist = 5;
   int forbidden = 0;
   int anonymous = 0;
@@ -152,6 +153,7 @@ int auth_init_default(auth_mod_t *am,
          AUTHTAG_ALGORITHM_REF(algorithm),
          AUTHTAG_EXPIRES_REF(expires),
          AUTHTAG_NEXT_EXPIRES_REF(next_expires),
+         AUTHTAG_MAX_NCOUNT_REF(max_ncount),
          AUTHTAG_BLACKLIST_REF(blacklist),
          AUTHTAG_FORBIDDEN_REF(forbidden),
          AUTHTAG_ANONYMOUS_REF(anonymous),
@@ -172,6 +174,7 @@ int auth_init_default(auth_mod_t *am,
     msg_commalist_d(am->am_home, &s, &am->am_allow, NULL);
   am->am_expires = expires;
   am->am_next_exp = next_expires;
+  am->am_max_ncount = max_ncount;
   am->am_blacklist = blacklist;
   am->am_forbidden = forbidden;
   am->am_anonymous = anonymous;
@@ -1437,6 +1440,16 @@ int auth_validate_digest_nonce(auth_mod_t *am,
     as->as_stale = 1;
   }
 
+  if (am->am_max_ncount && ar->ar_nc) {
+    unsigned long nc = strtoul(ar->ar_nc, NULL, 10);
+
+    if (nc == 0 || nc > am->am_max_ncount) {
+      SU_DEBUG_5(("auth_method_digest: nonce used %s times, max %u\n",
+                 ar->ar_nc, am->am_max_ncount));
+      as->as_stale = 1;
+    }
+  }
+
   /* We should also check cnonce, nc... */
 
   return 0;
index 9ef43a7912047fe59bddabdb37409347bf6ee754..9b850318bddbbfb7e81b596897f6061cb33cc6fb 100644 (file)
@@ -64,7 +64,7 @@ tag_typedef_t authtag_module = PTRTAG_TYPEDEF(module);
  * authentication module, like "Digest" or "Basic", or an plugin module,
  * like "SGMF+Digest". 
  *
- * @sa See <auth_plugin.h> for plugin interface.
+ * @sa See <sofia-sip/auth_plugin.h> for plugin interface.
  */
 tag_typedef_t authtag_method = STRTAG_TYPEDEF(method);
 
@@ -150,6 +150,17 @@ tag_typedef_t authtag_expires = UINTTAG_TYPEDEF(expires);
  */
 tag_typedef_t authtag_next_expires = UINTTAG_TYPEDEF(next_expires);
 
+/**@def AUTHTAG_MAX_NCOUNT()
+ *
+ * Max nonce count value.
+ * 
+ * The tag AUTHTAG_MAX_NCOUNT() specifies the maximum number of times a
+ * nonce should be used. 
+ *
+ * @todo Count actual usages and don't trust "nc" parameter only.
+ */
+tag_typedef_t authtag_max_ncount = UINTTAG_TYPEDEF(max_ncount);
+
 /**@def AUTHTAG_BLACKLIST()
  *
  * Blacklist time.
index 1b978b28e0fecb3289935d650e1bbd1516c2a05a..715a724301e254cdb9e751588f63bd3ea113ba44 100644 (file)
  *
  * @section auth_module Server Verifying Authentication
  *
- * The file <auth_module.h> defines the interface used by a server verifying
- * the authentication from client. After the server has created an @ref
- * auth_mod_t "authentication module", the usual authentication operation is
- * simple enough:
-
+ * The file <sofia-sip/auth_module.h> defines the interface used by a server
+ * verifying the authentication from client. After the server has created an
+ * @ref auth_mod_t "authentication module", the usual authentication
+ * operation is simple enough:
  * -# server initializes an #auth_status_t structure with information from
  *    the request
  * -# server calls auth_mod_method() 
@@ -42,8 +41,8 @@
  *
  * When the server creates the authentication module with auth_mod_create(),
  * it can specify numerous parameters affecting the authentication protocol
- * and algorithms. The parameter tags are defined in <auth_module.h>. The
- * most important parameters include:
+ * and algorithms. The parameter tags are defined in
+ * <sofia-sip/auth_module.h>. The most important parameters include:
  *
  * - AUTHTAG_METHOD(),
  * - AUTHTAG_ALGORITHM(),
@@ -52,7 +51,7 @@
  *
  * @section auth_client Client Authenticating User
  *
- * The file <auth_client.h> defines the interface used by a client
+ * The file <sofia-sip/auth_client.h> defines the interface used by a client
  * authenticating a user with a server. Because there may be multiple
  * servers or proxies requiring authentication, the client-side
  * authentication information is represented using a list of #auth_client_t
index 5daf840bb306a9ec5e57135820b5f634d6e9d745..6bfda503cc331b76cd75f4517f6e70162fca102c 100644 (file)
@@ -44,7 +44,7 @@
  * The IPTSEC_DEBUG environment variable is used to determine the debug
  * logging level for @b iptsec module. The default level is 3.
  * 
- * @sa <su_debug.h>, iptsec_log, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, iptsec_log, SOFIA_DEBUG
  */
 extern char const IPTSEC_DEBUG[];
 
index 8a3563934ae6d1dd0eb30628949136cba7261900..a9bcfd1e2f4cf973d531856068903cd83253db05 100644 (file)
@@ -322,6 +322,13 @@ SOFIAPUBVAR tag_typedef_t authtag_next_expires;
   authtag_next_expires_ref, tag_uint_vr((&x))
 SOFIAPUBVAR tag_typedef_t authtag_next_expires_ref;
 
+/** Maximum nonce count allowed. */
+#define AUTHTAG_MAX_NCOUNT(x)    authtag_max_ncount, tag_uint_v((x))
+SOFIAPUBVAR tag_typedef_t authtag_max_ncount;
+
+#define AUTHTAG_MAX_NCOUNT_REF(x)    authtag_max_ncount_ref, tag_uint_vr((&x))
+SOFIAPUBVAR tag_typedef_t authtag_max_ncount_ref;
+
 /** Extra delay when responding if provided invalid credentials or nonce. */
 #define AUTHTAG_BLACKLIST(x)    authtag_blacklist, tag_uint_v((x))
 SOFIAPUBVAR tag_typedef_t authtag_blacklist;
@@ -343,13 +350,6 @@ SOFIAPUBVAR tag_typedef_t authtag_anonymous;
 #define AUTHTAG_ANONYMOUS_REF(x)    authtag_anonymous_ref, tag_bool_vr((&x))
 SOFIAPUBVAR tag_typedef_t authtag_anonymous_ref;
 
-/** Fake authentication procedure - do not check result. */
-#define AUTHTAG_FAKE(x)    authtag_fake, tag_bool_v((x))
-SOFIAPUBVAR tag_typedef_t authtag_fake;
-
-#define AUTHTAG_FAKE_REF(x)    authtag_fake_ref, tag_bool_vr((&x))
-SOFIAPUBVAR tag_typedef_t authtag_fake_ref;
-
 /** HSS client structure. */
 #define AUTHTAG_HSS(x)        authtag_hss, tag_ptr_v((x))
 SOFIAPUBVAR tag_typedef_t authtag_hss;
index 97b10a8509181bd4ba707d763bfe9fb850c3438a..e7e571ef588923c5dcc11ddbf5a9676636af04a1 100644 (file)
@@ -164,6 +164,8 @@ struct auth_mod_t
   
   su_md5_t       am_hmac_ipad; /**< MD5 with inner pad */
   su_md5_t       am_hmac_opad; /**< MD5 with outer pad */
+
+  unsigned       am_max_ncount:1; /**< If nonzero, challenge with new nonce after ncount */
 };
 
 SOFIAPUBFUN
index ecbaa7de268185d24e333cf0739c482550c4711a..aceebc8c734a6cbcc2d223a2b6b5cad0b870d095 100644 (file)
@@ -92,11 +92,9 @@ char const name[] = "test_auth_digest";
 
 unsigned offset;
 
-void su_time(su_time_t *tv)
+void offset_time(su_time_t *tv)
 {
-  tv->tv_sec = time(NULL) + offset + 
-    /* Seconds from 1.1.1900 to 1.1.1970 */ 2208988800UL ;
-  tv->tv_usec = 555555;
+  tv->tv_sec += offset;
 }
 
 int test_digest()
@@ -896,6 +894,7 @@ int test_digest_client()
                                AUTHTAG_QOP("auth,auth-int"),
                                AUTHTAG_FORBIDDEN(1),
                                AUTHTAG_ANONYMOUS(1),
+                               AUTHTAG_MAX_NCOUNT(1),
                                TAG_END()));
 
     reinit_as(as);
@@ -942,6 +941,36 @@ int test_digest_client()
     TEST(as->as_status, 401);
     TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
     TEST_S(msg_params_find(au->au_params, "stale="), "true");
+
+    TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response, 
+                      sip_authorization_class), 1);
+    msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
+    TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, 
+                          (url_t *)"sip:surf3@ims3.so.noklab.net", 
+                          sip->sip_payload), 1);
+    TEST_1(sip->sip_authorization);
+    TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
+          "00000001");
+
+    reinit_as(as);
+    auth_mod_check_client(am, as, sip->sip_authorization, ach);
+    TEST(as->as_status, 0);
+
+    /* Test nonce count check */
+    msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
+    TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name, 
+                          (url_t *)"sip:surf3@ims3.so.noklab.net", 
+                          sip->sip_payload), 1);
+    TEST_1(sip->sip_authorization);
+    TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
+          "00000002");
+
+    reinit_as(as);
+    auth_mod_check_client(am, as, sip->sip_authorization, ach);
+    TEST(as->as_status, 401);
+    TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
+    TEST_S(msg_params_find(au->au_params, "stale="), "true");
+
     aucs = NULL;
 
     /* Test anonymous operation */
@@ -1210,6 +1239,9 @@ int main(int argc, char *argv[])
 {
   int retval = 0;
   int i;
+  extern void (*_su_time)(su_time_t *tv);
+
+  _su_time = offset_time;
 
   argv0 = argv[0];
 
index ce67125c16d72307557d7e80b3ac9c2ae69d9b0a..b30f2c49922ef56985d0282cf9e1391c4843fe73 100644 (file)
 
 #define TAG_NAMESPACE "tst"
 
-#include <test_class.h>
+#include "test_class.h"
 #include <sofia-sip/msg_parser.h>
 #include <sofia-sip/msg_mclass.h>
-#include <test_protos.h>
+#include "test_protos.h"
 #include <sofia-sip/msg_addr.h>
 
 extern msg_mclass_t const msg_test_mclass[1];
index 7ac89140b52c153eb6f4b5b7ddde7268eee8c574..d9453ee0c041df2b776b15d3fd72f5e13443a93c 100644 (file)
@@ -47,8 +47,8 @@
 #include <stddef.h>
 #include <string.h>
 
-#include <test_class.h>
-#include <test_protos.h>
+#include "test_class.h"
+#include "test_protos.h"
 #include <sofia-sip/msg_mime_protos.h>
 
 #include <sofia-sip/msg_mclass.h>
index a498ab29093e2c1e12c2e303d7352c2ed34d513e..bd49828d754ea3a4ae7edecda4dcb3f0ecf0c20e 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Sofia Event API provides an interface to different events used in SIP
  * presence and conferencing. Interface used both in client and server sides
- * is presented in <nea.h>.
+ * is presented in <sofia-sip/nea.h>.
  *
  * @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
  *
index 031ca9f8ddb0e80fb76bec458bee039619e7686e..38c024a6fe1353f40aa2457c9a44c984d0939903 100644 (file)
@@ -67,7 +67,7 @@
  * The NEA_DEBUG environment variable is used to determine the debug
  * logging level for @b nea module. The default level is 3.
  * 
- * @sa <su_debug.h>, nea_log, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, nea_log, SOFIA_DEBUG
  */
 extern char const NEA_DEBUG[];
 
index 58f9789d7eaddda98395766ea9131bd9cea5037a..5a061087b3619c81af73dcaf64de5a136b380703 100644 (file)
@@ -14,6 +14,7 @@ TAGFILES           += ../docs/msg.doxytags=../msg
 TAGFILES           += ../docs/sip.doxytags=../sip
 TAGFILES           += ../docs/sresolv.doxytags=../sresolv
 TAGFILES           += ../docs/tport.doxytags=../tport
+TAGFILES           += ../docs/nua.doxytags=../nua
 
 GENERATE_TAGFILE    = ../docs/nta.doxytags
 
index f4efd7a33203becd99379e1ddf5025827e47f3b9..944510aa09201f07cdd62e77bd3117761980b34c 100644 (file)
@@ -282,7 +282,7 @@ union sm_arg_u {
  * The NTA_DEBUG environment variable is used to determine the default
  * debug logging level. The normal level is 3.
  * 
- * @sa <su_debug.h>, #su_log_global, #SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, #su_log_global, #SOFIA_DEBUG
  */
 #ifdef DOXYGEN
 extern char const NTA_DEBUG[]; /* dummy declaration for Doxygen */
@@ -336,13 +336,36 @@ su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG) };
  * @param contact_url   URL that agent uses to bind the server sockets
  * @param callback      pointer to callback function
  * @param magic         pointer to user data
- * @param tag,value,... other arguments
+ * @param tag,value,... tagged arguments
  *
- * @note It is possible to provide -1 as @a contact_url.
+ * @TAGS
+ * NTATAG_ALIASES(),
+ * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
+ * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
+ * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
+ * NTATAG_EXTRA_100(),
+ * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
+ * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), 
+ * NTATAG_REL100(), 
+ * NTATAG_SERVER_RPORT(),
+ * NTATAG_SIPFLAGS(),
+ * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
+ * NTATAG_STATELESS(),
+ * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
+ * NTATAG_TIMER_C(),
+ * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
+ * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
+ *
+ * @note The value from following tags are stored, but they currently do nothing:
+ * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
+ *
+ * @note It is possible to provide @c (url_string_t*)-1 as @a contact_url. 
+ * In that case, no server sockets are bound.
  * 
  * @retval handle to the agent when successful,
  * @retval NULL upon an error.
  *
+ * @sa NUTAG_
  */
 nta_agent_t *nta_agent_create(su_root_t *root,
                              url_string_t const *contact_url,
@@ -359,6 +382,8 @@ nta_agent_t *nta_agent_create(su_root_t *root,
   ta_start(ta, tag, value);
 
   if ((agent = su_home_new(sizeof(*agent)))) {
+    unsigned timer_c;
+
     agent->sa_root = root;
     agent->sa_callback = callback;
     agent->sa_magic = magic;
@@ -366,13 +391,20 @@ nta_agent_t *nta_agent_create(su_root_t *root,
 
     agent->sa_maxsize         = 2 * 1024 * 1024; /* 2 MB */
     agent->sa_bad_req_mask    = 
-      (unsigned) ~(sip_mask_response | sip_mask_proxy);
+      /*
+       * Bit-wise not of these - what is left is suitable for UAs with 
+       * 100rel, timer, events, publish 
+       */
+      (unsigned) ~(sip_mask_response | sip_mask_proxy | sip_mask_registrar | 
+                  sip_mask_pref | sip_mask_privacy);
     agent->sa_bad_resp_mask   = 
-      (unsigned) ~(sip_mask_request | sip_mask_proxy);
+      (unsigned) ~(sip_mask_request | sip_mask_proxy | sip_mask_registrar | 
+                  sip_mask_pref | sip_mask_privacy);
     agent->sa_t1             = NTA_SIP_T1;
     agent->sa_t2             = NTA_SIP_T2;
     agent->sa_t4              = NTA_SIP_T4;
     agent->sa_t1x64          = 64 * NTA_SIP_T1;
+    agent->sa_timer_c         = 185 * 1000;
     agent->sa_drop_prob       = 0;
     agent->sa_is_a_uas        = 0;
     agent->sa_progress        = 60 * 1000;
@@ -421,7 +453,9 @@ nta_agent_t *nta_agent_create(su_root_t *root,
     outgoing_queue_init(agent->sa_out.terminated, 0); 
     /* Special queues (states) for outgoing INVITE transactions */
     outgoing_queue_init(agent->sa_out.inv_calling, agent->sa_t1x64); /* B */
-    outgoing_queue_init(agent->sa_out.inv_proceeding, 0); 
+    timer_c = (agent->sa_use_timer_c || !agent->sa_is_a_uas)
+      ? agent->sa_timer_c : 0;
+    outgoing_queue_init(agent->sa_out.inv_proceeding, timer_c); /* C */
     outgoing_queue_init(agent->sa_out.inv_completed, 32000); /* Timer D */
 
     if (leg_htable_resize(agent->sa_home, agent->sa_dialogs, 0) < 0 ||
@@ -841,17 +875,25 @@ void agent_kill_terminator(nta_agent_t *agent)
  * 0 selects the default value.
  *
  * @TAGS
- * NTATAG_ALIASES(), NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(),
- * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_DEBUG_DROP_PROB(),
- * NTATAG_DEFAULT_PROXY(), NTATAG_EXTRA_100(), NTATAG_MAXSIZE(),
- * NTATAG_MAX_FORWARDS(),
- * NTATAG_UDP_MTU(), NTATAG_MERGE_482(), NTATAG_PASS_100(),
- * NTATAG_PRELOAD(), NTATAG_REL100(), NTATAG_RPORT(), NTATAG_SERVER_RPORT(),
- * NTATAG_TCP_RPORT(),
- * NTATAG_SIPFLAGS(), NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(),
- * NTATAG_SIP_T4(), NTATAG_SMIME(), NTATAG_STATELESS(), NTATAG_TAG_3261(),
- * NTATAG_TIMEOUT_408(), NTATAG_PASS_408(), NTATAG_UA(), NTATAG_USER_VIA(),
- * and NTATAG_USE_TIMESTAMP().
+ * NTATAG_ALIASES(),
+ * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
+ * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
+ * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
+ * NTATAG_EXTRA_100(),
+ * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
+ * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(), 
+ * NTATAG_REL100(), 
+ * NTATAG_SERVER_RPORT(),
+ * NTATAG_SIPFLAGS(),
+ * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
+ * NTATAG_STATELESS(),
+ * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
+ * NTATAG_TIMER_C(),
+ * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
+ * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
+ *
+ * @note The value from following tags are stored, but they currently do nothing:
+ * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
  */
 int nta_agent_set_params(nta_agent_t *agent,
                         tag_type_t tag, tag_value_t value, ...)
@@ -875,7 +917,7 @@ int nta_agent_set_params(nta_agent_t *agent,
 static
 int agent_set_params(nta_agent_t *agent, tagi_t *tags)
 {
-  int n, m;
+  int n, nC, m;
   unsigned bad_req_mask = agent->sa_bad_req_mask;
   unsigned bad_resp_mask = agent->sa_bad_resp_mask;
   usize_t  maxsize    = agent->sa_maxsize;
@@ -885,6 +927,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
   unsigned sip_t2     = agent->sa_t2;
   unsigned sip_t4     = agent->sa_t4;
   unsigned sip_t1x64  = agent->sa_t1x64;
+  unsigned timer_c    = agent->sa_timer_c;
   unsigned blacklist  = agent->sa_blacklist;
   int ua              = agent->sa_is_a_uas;
   unsigned progress   = agent->sa_progress;
@@ -919,50 +962,54 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
   su_home_t *home = agent->sa_home;
 
   n = tl_gets(tags,
-             NTATAG_MCLASS_REF(mclass),
+             NTATAG_ALIASES_REF(aliases),
              NTATAG_BAD_REQ_MASK_REF(bad_req_mask),
              NTATAG_BAD_RESP_MASK_REF(bad_resp_mask),
-             NTATAG_ALIASES_REF(aliases),
-             NTATAG_UA_REF(ua),
-             NTATAG_STATELESS_REF(stateless),
-             NTATAG_MAXSIZE_REF(maxsize),
-             NTATAG_MAX_FORWARDS_REF(max_forwards),
-             NTATAG_UDP_MTU_REF(udp_mtu),
-             NTATAG_SIP_T1_REF(sip_t1),
-             NTATAG_SIP_T2_REF(sip_t2),
-             NTATAG_SIP_T4_REF(sip_t4),
-             NTATAG_SIP_T1X64_REF(sip_t1x64),
-             NTATAG_PROGRESS_REF(progress),
              NTATAG_BLACKLIST_REF(blacklist),
+             NTATAG_CANCEL_2543_REF(cancel_2543),
+             NTATAG_CANCEL_487_REF(cancel_487),
              NTATAG_DEBUG_DROP_PROB_REF(drop_prob),
-             NTATAG_USER_VIA_REF(user_via),
+             NTATAG_DEFAULT_PROXY_REF(proxy),
              NTATAG_EXTRA_100_REF(extra_100),
+             NTATAG_MAXSIZE_REF(maxsize),
+             NTATAG_MAX_FORWARDS_REF(max_forwards),
+             NTATAG_MCLASS_REF(mclass),
+             NTATAG_MERGE_482_REF(merge_482),
              NTATAG_PASS_100_REF(pass_100),
-             NTATAG_TIMEOUT_408_REF(timeout_408),
              NTATAG_PASS_408_REF(pass_408),
-             NTATAG_MERGE_482_REF(merge_482),
-             NTATAG_DEFAULT_PROXY_REF(proxy),
-             NTATAG_CANCEL_2543_REF(cancel_2543),
-             NTATAG_CANCEL_487_REF(cancel_487),
+             NTATAG_PRELOAD_REF(preload),
+             NTATAG_PROGRESS_REF(progress),
              NTATAG_REL100_REF(invite_100rel),
-             NTATAG_USE_TIMESTAMP_REF(use_timestamp),
-             NTATAG_USE_NAPTR_REF(use_naptr),
-             NTATAG_USE_SRV_REF(use_srv),
+             NTATAG_RPORT_REF(rport),
+             NTATAG_SERVER_RPORT_REF(server_rport),
+             NTATAG_SIGCOMP_ALGORITHM_REF(algorithm),
+             NTATAG_SIGCOMP_OPTIONS_REF(sigcomp),
+             NTATAG_SIPFLAGS_REF(flags),
+             NTATAG_SIP_T1X64_REF(sip_t1x64),
+             NTATAG_SIP_T1_REF(sip_t1),
+             NTATAG_SIP_T2_REF(sip_t2),
+             NTATAG_SIP_T4_REF(sip_t4),
 #if HAVE_SOFIA_SMIME
              NTATAG_SMIME_REF(smime),
 #endif
-             NTATAG_SIPFLAGS_REF(flags),
-             NTATAG_RPORT_REF(rport),
-             NTATAG_SERVER_RPORT_REF(server_rport),
+             NTATAG_STATELESS_REF(stateless),
              NTATAG_TCP_RPORT_REF(tcp_rport),
-             NTATAG_PRELOAD_REF(preload),
+             NTATAG_TIMEOUT_408_REF(timeout_408),
+             NTATAG_UA_REF(ua),
+             NTATAG_UDP_MTU_REF(udp_mtu),
+             NTATAG_USER_VIA_REF(user_via),
+             NTATAG_USE_NAPTR_REF(use_naptr),
+             NTATAG_USE_SRV_REF(use_srv),
+             NTATAG_USE_TIMESTAMP_REF(use_timestamp),
 #ifdef TPTAG_THRPSIZE
              /* If threadpool is enabled, start a separate "reaper thread" */
              TPTAG_THRPSIZE_REF(threadpool),
 #endif
-             NTATAG_SIGCOMP_OPTIONS_REF(sigcomp),
-             NTATAG_SIGCOMP_ALGORITHM_REF(algorithm),
              TAG_END());
+  nC = tl_gets(tags,
+              NTATAG_TIMER_C_REF(timer_c),
+              TAG_END());
+  n += nC;
 
   if (mclass != NONE)
     agent->sa_mclass = mclass ? mclass : sip_default_mclass();
@@ -972,7 +1019,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
     m = tport_set_params(tport, TAG_NEXT(tags));
   }
 
-  if (n == 0 || m == -1)
+  if (m == -1)
     return m;
 
   n += m;
@@ -1065,6 +1112,14 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
     outgoing_queue_adjust(agent, agent->sa_out.inv_calling, sip_t1x64);
   }
   agent->sa_t1x64 = sip_t1x64;
+  if (nC == 1) {
+    agent->sa_use_timer_c = 1;
+    if (timer_c == 0)
+      timer_c = 185 * 1000;
+    agent->sa_timer_c = timer_c;
+    outgoing_queue_adjust(agent, agent->sa_out.inv_proceeding, timer_c);
+  }
+
   agent->sa_blacklist = blacklist;
 
   if (progress == 0)
@@ -1123,16 +1178,25 @@ void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu)
  * INVITE transactions, or how the @Via headers are generated.
  *
  * @TAGS
- * NTATAG_ALIASES_REF(), NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
- * NTATAG_CONTACT_REF(), NTATAG_DEBUG_DROP_PROB_REF(),
- * NTATAG_DEFAULT_PROXY_REF(), NTATAG_EXTRA_100_REF(), NTATAG_MAXSIZE_REF(),
- * NTATAG_MAX_FORWARDS_REF(),
- * NTATAG_MERGE_482_REF(), NTATAG_PASS_100_REF(), NTATAG_PRELOAD_REF(),
- * NTATAG_REL100_REF(), NTATAG_RPORT_REF(), NTATAG_SIPFLAGS_REF(),
- * NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T1_REF(), NTATAG_SIP_T2_REF(),
+ * NTATAG_ALIASES_REF(), NTATAG_BLACKLIST_REF(), 
+ * NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
+ * NTATAG_CLIENT_RPORT_REF(), NTATAG_CONTACT_REF(), 
+ * NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(),
+ * NTATAG_EXTRA_100_REF(),
+ * NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(),
+ * NTATAG_MERGE_482_REF(), 
+ * NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(),
+ * NTATAG_PROGRESS_REF(),
+ * NTATAG_REL100_REF(), 
+ * NTATAG_SERVER_RPORT_REF(), 
+ * NTATAG_SIGCOMP_ALGORITHM_REF(), NTATAG_SIGCOMP_OPTIONS_REF(),
+ * NTATAG_SIPFLAGS_REF(),
+ * NTATAG_SIP_T1_REF(), NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T2_REF(),
  * NTATAG_SIP_T4_REF(), NTATAG_SMIME_REF(), NTATAG_STATELESS_REF(),
- * NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_PASS_408_REF(),
- * NTATAG_UA_REF(), NTATAG_USER_VIA_REF(), and NTATAG_USE_TIMESTAMP_REF().
+ * NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_TIMER_C_REF(),
+ * NTATAG_UA_REF(), NTATAG_UDP_MTU_REF(), NTATAG_USER_VIA_REF(), 
+ * NTATAG_USE_NAPTR_REF(), NTATAG_USE_SRV_REF(),
+ * and NTATAG_USE_TIMESTAMP_REF().
  *
  */
 int nta_agent_get_params(nta_agent_t *agent,
@@ -1145,12 +1209,11 @@ int nta_agent_get_params(nta_agent_t *agent,
     ta_start(ta, tag, value);
     n = agent_get_params(agent, ta_args(ta));
     ta_end(ta);
-  } else {
-    su_seterrno(EINVAL);
-    n = -1;
+    return n;
   }
 
-  return n;
+  su_seterrno(EINVAL);
+  return -1;
 }
 
 /** Get NTA parameters */
@@ -1159,46 +1222,49 @@ int agent_get_params(nta_agent_t *agent, tagi_t *tags)
 {
   return
     tl_tgets(tags,
-            NTATAG_MCLASS(agent->sa_mclass),
-            NTATAG_CONTACT(agent->sa_contact),
             NTATAG_ALIASES(agent->sa_aliases),
-            NTATAG_UA(agent->sa_is_a_uas),
-            NTATAG_STATELESS(agent->sa_is_stateless),
-            NTATAG_MAXSIZE(agent->sa_maxsize),
-            NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count),
-            NTATAG_UDP_MTU(agent->sa_udp_mtu),
-            NTATAG_SIP_T1(agent->sa_t1),
-            NTATAG_SIP_T2(agent->sa_t2),
-            NTATAG_SIP_T4(agent->sa_t4),
-            NTATAG_SIP_T1X64(agent->sa_t1x64),
             NTATAG_BLACKLIST(agent->sa_blacklist),
+            NTATAG_CANCEL_2543(agent->sa_cancel_2543),
+            NTATAG_CANCEL_487(agent->sa_cancel_487),
+            NTATAG_CLIENT_RPORT(agent->sa_rport),
+            NTATAG_CONTACT(agent->sa_contact),
             NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob),
-            NTATAG_USER_VIA(agent->sa_user_via),
+            NTATAG_DEFAULT_PROXY(agent->sa_default_proxy),
             NTATAG_EXTRA_100(agent->sa_extra_100),
+            NTATAG_MAXSIZE(agent->sa_maxsize),
+            NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count),
+            NTATAG_MCLASS(agent->sa_mclass),
+            NTATAG_MERGE_482(agent->sa_merge_482),
             NTATAG_PASS_100(agent->sa_pass_100),
-            NTATAG_TIMEOUT_408(agent->sa_timeout_408),
             NTATAG_PASS_408(agent->sa_pass_408),
-            NTATAG_MERGE_482(agent->sa_merge_482),
-            NTATAG_DEFAULT_PROXY(agent->sa_default_proxy),
-            NTATAG_CANCEL_2543(agent->sa_cancel_2543),
-            NTATAG_CANCEL_487(agent->sa_cancel_487),
-            NTATAG_TAG_3261(1),
+            NTATAG_PRELOAD(agent->sa_preload),
+            NTATAG_PROGRESS(agent->sa_progress),
             NTATAG_REL100(agent->sa_invite_100rel),
-            NTATAG_USE_TIMESTAMP(agent->sa_timestamp),
-            NTATAG_USE_NAPTR(agent->sa_use_naptr),
-            NTATAG_USE_SRV(agent->sa_use_srv),
+            NTATAG_SERVER_RPORT(agent->sa_server_rport),
+            NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm),
+            NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ?
+                                   agent->sa_sigcomp_options :
+                                   "sip"),
+            NTATAG_SIPFLAGS(agent->sa_flags),
+            NTATAG_SIP_T1(agent->sa_t1),
+            NTATAG_SIP_T1X64(agent->sa_t1x64),
+            NTATAG_SIP_T2(agent->sa_t2),
+            NTATAG_SIP_T4(agent->sa_t4),
 #if HAVE_SOFIA_SMIME
             NTATAG_SMIME(agent->sa_smime),
 #else
             NTATAG_SMIME(NULL),
 #endif
-            NTATAG_SIPFLAGS(agent->sa_flags),
-            NTATAG_RPORT(agent->sa_rport),
-            NTATAG_PRELOAD(agent->sa_preload),
-            NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm),
-            NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ?
-                                   agent->sa_sigcomp_options :
-                                   "sip"),
+            NTATAG_STATELESS(agent->sa_is_stateless),
+            NTATAG_TAG_3261(1),
+            NTATAG_TIMEOUT_408(agent->sa_timeout_408),
+            NTATAG_TIMER_C(agent->sa_timer_c),
+            NTATAG_UA(agent->sa_is_a_uas),
+            NTATAG_UDP_MTU(agent->sa_udp_mtu),
+            NTATAG_USER_VIA(agent->sa_user_via),
+            NTATAG_USE_NAPTR(agent->sa_use_naptr),
+            NTATAG_USE_SRV(agent->sa_use_srv),
+            NTATAG_USE_TIMESTAMP(agent->sa_timestamp),
             TAG_END());
 }
 
@@ -1207,8 +1273,38 @@ int agent_get_params(nta_agent_t *agent, tagi_t *tags)
  * The nta_agent_get_stats() function retrieves the stack statistics.
  *
  * @TAGS
- * @TAG NTATAG_S_*
- *
+ * NTATAG_S_ACKED_TR_REF(),
+ * NTATAG_S_BAD_MESSAGE_REF(),
+ * NTATAG_S_BAD_REQUEST_REF(),
+ * NTATAG_S_BAD_RESPONSE_REF(),
+ * NTATAG_S_CANCELED_TR_REF(),
+ * NTATAG_S_CLIENT_TR_REF(),
+ * NTATAG_S_DIALOG_TR_REF(),
+ * NTATAG_S_DROP_REQUEST_REF(),
+ * NTATAG_S_DROP_RESPONSE_REF(),
+ * NTATAG_S_IRQ_HASH_REF(),
+ * NTATAG_S_IRQ_HASH_USED_REF(),
+ * NTATAG_S_LEG_HASH_REF(),
+ * NTATAG_S_LEG_HASH_USED_REF(),
+ * NTATAG_S_MERGED_REQUEST_REF(),
+ * NTATAG_S_ORQ_HASH_REF(),
+ * NTATAG_S_ORQ_HASH_USED_REF(),
+ * NTATAG_S_RECV_MSG_REF(),
+ * NTATAG_S_RECV_REQUEST_REF(),
+ * NTATAG_S_RECV_RESPONSE_REF(),
+ * NTATAG_S_RECV_RETRY_REF(),
+ * NTATAG_S_RETRY_REQUEST_REF(),
+ * NTATAG_S_RETRY_RESPONSE_REF(),
+ * NTATAG_S_SENT_MSG_REF(),
+ * NTATAG_S_SENT_REQUEST_REF(),
+ * NTATAG_S_SENT_RESPONSE_REF(),
+ * NTATAG_S_SERVER_TR_REF(),
+ * NTATAG_S_TOUT_REQUEST_REF(), 
+ * NTATAG_S_TOUT_RESPONSE_REF(),
+ * NTATAG_S_TRLESS_200_REF(),
+ * NTATAG_S_TRLESS_REQUEST_REF(),
+ * NTATAG_S_TRLESS_RESPONSE_REF(), and
+ * NTATAG_S_TRLESS_TO_TR_REF(),
  */
 int nta_agent_get_stats(nta_agent_t *agent,
                        tag_type_t tag, tag_value_t value, ...)
@@ -1622,7 +1718,6 @@ int agent_create_master_transport(nta_agent_t *self, tagi_t *tags)
     tport_tcreate(self, nta_agent_class, self->sa_root,
                  TPTAG_SDWN_ERROR(0),
                  TPTAG_IDLE(1800000),
-                 TPTAG_DEBUG_DROP(self->sa_drop_prob),
                  TAG_NEXT(tags));
 
   if (!self->sa_tports)
@@ -2119,6 +2214,16 @@ void agent_recv_request(nta_agent_t *agent,
              URL_PRINT_ARGS(sip->sip_request->rq_url),
              sip->sip_request->rq_version, cseq));
 
+  if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
+    if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
+      SU_DEBUG_5(("nta: %s (%u) is %s\n", 
+                 method_name, cseq, "dropped simulating packet loss"));
+      agent->sa_stats->as_drop_request++;
+      msg_destroy(msg);
+      return;
+    }
+  }
+
   stream = tport_is_stream(tport);
 
   /* Try to use compression on reverse direction if @Via has comp=sigcomp  */
@@ -2304,8 +2409,9 @@ void agent_recv_request(nta_agent_t *agent,
   }
   else {
     agent->sa_stats->as_trless_request++;
-    SU_DEBUG_5(("nta: %s (%u) no place to go: %d %s\n",
-               method_name, cseq, SIP_501_NOT_IMPLEMENTED));
+    SU_DEBUG_5(("nta: %s (%u) %s\n",
+               method_name, cseq, 
+               "not processed by application: returning 501"));
     if (method != sip_method_ack)
       nta_msg_treply(agent, msg, SIP_501_NOT_IMPLEMENTED,
                     NTATAG_TPORT(tport),
@@ -2493,6 +2599,16 @@ void agent_recv_response(nta_agent_t *agent,
   SU_DEBUG_5(("nta: received %03d %s for %s (%u)\n", 
              status, phrase, method, cseq));
 
+  if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
+    if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
+      SU_DEBUG_5(("nta: %03d %s %s\n",
+                 status, phrase, "dropped simulating packet loss"));
+      agent->sa_stats->as_drop_response++;
+      msg_destroy(msg);
+      return;
+    }
+  }
+
   if (agent->sa_bad_resp_mask)
     errors = msg_extract_errors(msg) & agent->sa_bad_resp_mask;
   else
@@ -2505,7 +2621,10 @@ void agent_recv_response(nta_agent_t *agent,
     agent->sa_stats->as_bad_response++;
     agent->sa_stats->as_bad_message++;
 
-    SU_DEBUG_5(("nta: %03d %s failed sanity check\n", status, phrase));
+    SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase,
+               errors
+               ? "has fatal syntax errors"
+               : "failed sanity check"));
 
     for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_next) {
       if (h->sh_class->hc_name) {
@@ -2532,7 +2651,7 @@ void agent_recv_response(nta_agent_t *agent,
     /* Drop response messages to ACK */
     agent->sa_stats->as_bad_response++;
     agent->sa_stats->as_bad_message++;
-    SU_DEBUG_5(("nta: %03d %s is response to ACK\n", status, phrase));
+    SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is response to ACK"));
     msg_destroy(msg);
     return;
   }
@@ -2540,7 +2659,8 @@ void agent_recv_response(nta_agent_t *agent,
   /* XXX - should check if msg should be discarded based on via? */
 
   if ((orq = outgoing_find(agent, msg, sip, sip->sip_via))) {
-    SU_DEBUG_5(("nta: %03d %s going to a transaction\n", status, phrase));
+    SU_DEBUG_5(("nta: %03d %s %s\n", 
+               status, phrase, "is going to a transaction"));
     if (outgoing_recv(orq, status, msg, sip) == 0)
       return;
   }
@@ -2548,12 +2668,13 @@ void agent_recv_response(nta_agent_t *agent,
   agent->sa_stats->as_trless_response++;
 
   if ((orq = agent->sa_default_outgoing)) {
-    SU_DEBUG_5(("nta: %03d %s to the default transaction\n", status, phrase));
+    SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, 
+               "to the default transaction"));
     outgoing_default_recv(orq, status, msg, sip);
     return;
   }
   else if (agent->sa_callback) {
-    SU_DEBUG_5(("nta: %03d %s to message callback\n", status, phrase));
+    SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "to message callback"));
     /*
      * Store message and transport to hook for the duration of the callback
      * so that the transport can be obtained by nta_transport().
@@ -2569,13 +2690,15 @@ void agent_recv_response(nta_agent_t *agent,
       && sip->sip_via && !sip->sip_via->v_next 
       && agent_has_via(agent, sip->sip_via)) {
     agent->sa_stats->as_trless_200++;
-    /* Orphan 200 Ok to INVITE. ACK and BYE it */
-    SU_DEBUG_5(("nta: %03d %s must be ACK&BYE\n", status, phrase));
-    if (nta_msg_ackbye(agent, msg) != -1)
-      return;
+    if (agent->sa_is_a_uas) {
+      /* Orphan 200 Ok to INVITE. ACK and BYE it */
+      SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is ACK&BYE"));
+      if (nta_msg_ackbye(agent, msg) != -1)
+       return;
+    }
   }
 
-  SU_DEBUG_5(("nta: %03d %s was discarded\n", status, phrase));
+  SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "was discarded"));
   msg_destroy(msg);
 }
 
@@ -2817,6 +2940,7 @@ int nta_msg_mreply(nta_agent_t *agent,
          NTATAG_TPORT_REF(tport),
          NTATAG_INCOMPLETE_REF(incomplete),
          TPTAG_COMPARTMENT_REF(cc),
+         /* XXX - should also check ntatag_sigcomp_close() */
          TAG_END());
 
   if (reply == NULL) {
@@ -3340,6 +3464,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
   nta_leg_t *leg;
   su_home_t *home;
   url_t *url;
+  char const *what = NULL;
 
   if (agent == NULL)
     return su_seterrno(EINVAL), NULL;
@@ -3423,32 +3548,35 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
   leg->leg_url = url;
 
   if (from && from != NONE && leg->leg_local == NULL) {
-    SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate local address\n"));
+    what = "cannot duplicate local address";
     goto err;
   }
   else if (to && to != NONE && leg->leg_remote == NULL) {
-    SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate remote address\n"));
+    what = "cannot duplicate remote address";
     goto err;
   }
   else if (route && route != NONE && leg->leg_route == NULL) {
-    SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate route\n"));
+    what = "cannot duplicate route";
     goto err;
   }
   else if (contact && contact != NONE && leg->leg_target == NULL) {
-    SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate target\n"));
+    what = "cannot duplicate target";
     goto err;
   }
   else if (url_string && leg->leg_url == NULL) {
-    SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate local destination\n"));
+    what = "cannot duplicate local destination";
     goto err;
   }
 
   if (!no_dialog) {
     if (!leg->leg_local || !leg->leg_remote) {
       /* To and/or From header missing */
-      SU_DEBUG_3(("nta_leg_tcreate(): missing%s%s header\n",
-                 !leg->leg_remote ? " To" : "",
-                 !leg->leg_local ? " From" : ""));
+      if (leg->leg_remote)
+       what = "Missing local dialog address";
+      else if (leg->leg_local)
+       what = "Missing remote dialog address";
+      else 
+       what = "Missing dialog addresses";
       goto err;
     }
 
@@ -3462,7 +3590,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
       leg->leg_id = sip_call_id_create(home, NULL);
 
     if (!leg->leg_id) {
-      SU_DEBUG_3(("nta_leg_tcreate(): cannot create Call-ID\n"));
+      what = "cannot create Call-ID";
       goto err;
     }
 
@@ -3498,7 +3626,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
   else {
     /* This is "default leg" without a destination URL. */
     if (agent->sa_default_leg) {
-      SU_DEBUG_1(("leg_create(): tried to create second default leg\n"));
+      SU_DEBUG_1(("%s(): %s\n", "nta_leg_tcreate", "tried to create second default leg"));
       su_seterrno(EEXIST);
       goto err;
     }
@@ -3515,11 +3643,14 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
 
   leg_insert(agent, leg);
 
-  SU_DEBUG_9(("nta_leg_create(%p)\n", (void *)leg));
+  SU_DEBUG_9(("%s(%p)\n", "nta_leg_tcreate", (void *)leg));
 
   return leg;
 
  err:
+  if (what)
+    SU_DEBUG_9(("%s(): %s\n", "nta_leg_tcreate", what));
+
   su_home_zap(leg->leg_home);
 
   return NULL;
@@ -4478,7 +4609,7 @@ nta_incoming_t *incoming_create(nta_agent_t *agent,
     } 
     else {
       queue = agent->sa_in.proceeding;
-       /* draft-sparks-sip-nit-actions-03:
+       /* RFC 4320 (nit-actions-03):
 
    Blacklisting on a late response occurs even over reliable transports.
    Thus, if an element processing a request received over a reliable
@@ -5661,7 +5792,7 @@ int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
       irq->irq_method != sip_method_invite && 
       !agent->sa_pass_408 &&
       !irq->irq_default) {
-    /* draft-sparks-sip-nit-actions-03 Action 2:
+    /* RFC 4320 nit-actions-03 Action 2:
        
    A transaction-stateful SIP element MUST NOT send a response with
    Status-Code of 408 to a non-INVITE request.  As a consequence, an
@@ -6199,6 +6330,9 @@ static size_t outgoing_timer_dk(outgoing_queue_t *q,
 static size_t outgoing_timer_bf(outgoing_queue_t *q, 
                                char const *timer, 
                                su_duration_t now);
+static size_t outgoing_timer_c(outgoing_queue_t *q, 
+                              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 *,
@@ -6303,7 +6437,7 @@ nta_outgoing_t *nta_outgoing_default(nta_agent_t *agent,
  * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
  * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
  * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
- * SIP tags from <sip_tag.h> can be used to manipulate the request message. 
+ * SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message. 
  * SIP tags after SIPTAG_END() are ignored, however.
  */
 nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg,
@@ -6385,13 +6519,13 @@ nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg,
  * transaction is freed before returning from the function.
  *
  * @sa
- * nta_outgoing_tcreate(), nnta_outgoing_tcancel(), nta_outgoing_destroy().
+ * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
  *
  * @TAGS
  * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
  * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
  * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
- * SIP tags from <sip_tag.h> can be used to manipulate the request message. 
+ * SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message. 
  * SIP tags after SIPTAG_END() are ignored, however.
  */
 nta_outgoing_t *nta_outgoing_mcreate(nta_agent_t *agent,
@@ -6611,7 +6745,7 @@ unsigned nta_outgoing_delay(nta_outgoing_t const *orq)
   return orq != NULL && orq != NONE ? orq->orq_delay : UINT_MAX;
 }
 
-/** Get the branch parameter. */
+/** Get the branch parameter. @NEW_1_12_7 */
 char const *nta_outgoing_branch(nta_outgoing_t const *orq)
 {
   return orq != NULL && orq != NONE && orq->orq_branch
@@ -6713,6 +6847,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
   char const *scheme = NULL;
   char const *port = NULL;
   int invalid, resolved, stateless = 0, user_via = agent->sa_user_via;
+  int invite_100rel = agent->sa_invite_100rel;
+
   tagi_t const *t;
   tport_t const *override_tport = NULL;
 
@@ -6777,6 +6913,9 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
     else if (ntatag_tport == tt) {
       override_tport = (tport_t *)t->t_value;
     }
+    else if (ntatag_rel100 == tt) {
+      invite_100rel = t->t_value != 0;
+    }
   }
 
   orq->orq_agent    = agent;
@@ -6798,6 +6937,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
   orq->orq_delay     = UINT_MAX;
   orq->orq_stateless = stateless != 0;
   orq->orq_user_via  = user_via != 0 && sip->sip_via;
+  orq->orq_100rel    = invite_100rel;
+
   if (cc)
     orq->orq_cc = nta_compartment_ref(cc);
 
@@ -7332,17 +7473,18 @@ int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq,
   supported[i = 0] = NULL;
 
   if (orq->orq_method == sip_method_invite) {
-    int add_100rel = agent->sa_invite_100rel;
     int require_100rel = sip_has_feature(sip->sip_require, "100rel");
 
-    tl_gets(tags,
-           NTATAG_REL100_REF(add_100rel),
-           TAG_END());
-    if (add_100rel && !require_100rel &&
-       !sip_has_feature(sip->sip_supported, "100rel"))
-      supported[i++] = "100rel";
-
-    orq->orq_must_100rel = require_100rel;
+    if (require_100rel) {
+      orq->orq_must_100rel = 1;
+      orq->orq_100rel = 1;
+    }
+    else if (sip_has_feature(sip->sip_supported, "100rel")) {
+      orq->orq_100rel = 1;
+    }
+    else if (orq->orq_100rel) {
+       supported[i++] = "100rel";
+    }
   }
 
   if (i) {
@@ -7404,7 +7546,8 @@ outgoing_queue_adjust(nta_agent_t *sa,
   latest = set_timeout(sa, queue->q_timeout = timeout);
 
   for (orq = queue->q_head; orq; orq = orq->orq_next) {
-    if (orq->orq_timeout - latest > 0)
+    if (orq->orq_timeout == 0 ||
+       orq->orq_timeout - latest > 0)
       orq->orq_timeout = latest;
   }
 }
@@ -7659,6 +7802,7 @@ su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next)
     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_t *proceeding = sa->sa_out.inv_proceeding;
 
   outgoing_queue_init(sa->sa_out.free = rq, 0);
 
@@ -7712,9 +7856,12 @@ su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next)
 
   timeout
     = outgoing_timer_bf(sa->sa_out.inv_calling, "B", now)
+    + outgoing_timer_c(proceeding, "C", now)
     + outgoing_timer_bf(sa->sa_out.trying, "F", now);
 
   next = NEXT_TIMEOUT(next, sa->sa_out.inv_calling->q_head, orq_timeout, now);
+  if (proceeding->q_timeout)
+    next = NEXT_TIMEOUT(next, proceeding->q_head, orq_timeout, now);
   next = NEXT_TIMEOUT(next, sa->sa_out.trying->q_head, orq_timeout, now);
 
   destroyed = outgoing_mass_destroy(sa, rq);
@@ -7791,6 +7938,38 @@ size_t outgoing_timer_bf(outgoing_queue_t *q,
   return timeout;
 }
 
+/** Handle timer C */
+static
+size_t outgoing_timer_c(outgoing_queue_t *q, 
+                       char const *timer, 
+                       su_duration_t now)
+{
+  nta_outgoing_t *orq;
+  size_t timeout = 0;
+
+  if (q->q_timeout == 0)
+    return 0;
+
+  while ((orq = q->q_head)) {
+    if (orq->orq_timeout - now > 0 || timeout >= timer_max_timeout)
+      break;
+
+    timeout++;
+    
+    SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n",
+               timer, "CANCEL and timeout", 
+               orq->orq_method_name, orq->orq_cseq->cs_seq));
+
+    nta_outgoing_tcancel(orq, NULL, NULL, TAG_NULL());
+
+    outgoing_timeout(orq, now);
+
+    assert(q->q_head != orq);
+  }
+
+  return timeout;
+}
+
 /** @internal Signal transaction timeout to the application. */
 void outgoing_timeout(nta_outgoing_t *orq, su_duration_t now)
 {
@@ -8074,6 +8253,13 @@ int outgoing_recv(nta_outgoing_t *orq,
        orq->orq_status = status;
        outgoing_queue(sa->sa_out.inv_proceeding, orq);
       }
+      else if (orq->orq_queue == sa->sa_out.inv_proceeding) {
+       orq->orq_status = status;
+       if (sa->sa_out.inv_proceeding->q_timeout) {
+         outgoing_remove(orq);
+         outgoing_queue(sa->sa_out.inv_proceeding, orq);
+       }
+      }
 
       /* Handle 100rel */
       if (sip && sip->sip_rseq)
@@ -8092,6 +8278,10 @@ int outgoing_recv(nta_outgoing_t *orq,
          return 0;
 
        if (sip && sa->sa_is_a_uas) {
+         /*
+          * We silently discard duplicate final responses to INVITE below
+          * with outgoing_duplicate()
+          */
          su_home_t *home = msg_home(orq->orq_request);
          orq->orq_tag = su_strdup(home, sip->sip_to->a_tag);
        }
@@ -8119,6 +8309,10 @@ int outgoing_recv(nta_outgoing_t *orq,
       assert(orq_status < 200); (void)orq_status;
 
       if (status < 200) {
+       /* @RFC3261 17.1.2.1:
+        * retransmissions continue for unreliable transports, 
+        * but at an interval of T2 
+        */
        if (!orq->orq_reliable)
          outgoing_set_timer(orq, sa->sa_t2);
       } 
@@ -8324,6 +8518,33 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
   if (!sip)
     return NULL;
 
+  if (tags) {
+    sip_add_tl(msg, sip, TAG_NEXT(tags));
+    /* Bug sf.net # 173323:
+     * Ensure that request-URI, topmost Via, From, To, Call-ID, CSeq, 
+     * Max-Forward, Route, Accept-Contact, Reject-Contact and
+     * Request-Disposition are copied from original request
+     */
+    if (sip->sip_from)
+      sip_header_remove(msg, sip, (void *)sip->sip_from);
+    if (sip->sip_to)
+      sip_header_remove(msg, sip, (void *)sip->sip_to);
+    if (sip->sip_call_id)
+      sip_header_remove(msg, sip, (void *)sip->sip_call_id);
+    while (sip->sip_route)
+      sip_header_remove(msg, sip, (void *)sip->sip_route);
+    while (sip->sip_accept_contact)
+      sip_header_remove(msg, sip, (void *)sip->sip_accept_contact);
+    while (sip->sip_reject_contact)
+      sip_header_remove(msg, sip, (void *)sip->sip_reject_contact);
+    if (sip->sip_request_disposition)
+      sip_header_remove(msg, sip, (void *)sip->sip_request_disposition);
+    while (sip->sip_via)
+      sip_header_remove(msg, sip, (void *)sip->sip_via);
+    if (sip->sip_max_forwards)
+      sip_header_remove(msg, sip, (void *)sip->sip_max_forwards);
+  }
+
   sip->sip_request =
     sip_request_create(home, m, mname, (url_string_t *)orq->orq_url, NULL);
 
@@ -8335,6 +8556,7 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
   sip_add_dup(msg, sip, (sip_header_t *)old->sip_accept_contact);
   sip_add_dup(msg, sip, (sip_header_t *)old->sip_reject_contact);
   sip_add_dup(msg, sip, (sip_header_t *)old->sip_request_disposition);
+  sip_add_dup(msg, sip, (sip_header_t *)old->sip_max_forwards);
 
   if (old->sip_via) {
     /* Add only the topmost Via header */
@@ -8344,12 +8566,6 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
 
   sip->sip_cseq = sip_cseq_create(home, old->sip_cseq->cs_seq, m, mname);
 
-  if (tags)
-    sip_add_tl(msg, sip, TAG_NEXT(tags));
-
-  if (!sip->sip_max_forwards)
-    sip_add_dup(msg, sip, (sip_header_t *)orq->orq_agent->sa_max_forwards);
-
   if (sip->sip_request &&
       sip->sip_to &&
       sip->sip_from &&
@@ -8418,7 +8634,9 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
   /* Create response message, if needed */
   if (!orq->orq_stateless &&
       !(orq->orq_callback == outgoing_default_cb) &&
-      !(status == 408 && !orq->orq_agent->sa_timeout_408)) {
+      !(status == 408 &&
+       orq->orq_method != sip_method_invite && 
+       !orq->orq_agent->sa_timeout_408)) {
     char const *to_tag;
 
     msg = nta_msg_create(agent, NTA_INTERNAL_MSG);
index 9b4dd1e192ed41516f95b4c89dd73d238eeeb433..f82d6980cba577b70bfd7b6fba4bcebfd148e809 100644 (file)
@@ -24,8 +24,9 @@
  * (#nta_incoming_t).
  * 
  * NTA also uses SIP message objects #msg_t and #sip_t for handling
- * messages, as defined in <msg.h> and <sip.h>, respectively. The various
- * SIP headers are also defined in <sip.h>.
+ * messages, as defined in <sofia-sip/msg.h> and <sofia-sip/sip.h>,
+ * respectively. The various SIP headers are also defined in
+ * <sofia-sip/sip.h>.
  * 
  * @section nta_agent_t Creating an NTA Agent
  * 
index 478a74b53f04449461946d74b4a41b2cf7b09636..551ce527d5bbab8c5e153f77b3dc67559e881a13 100644 (file)
@@ -160,10 +160,13 @@ struct nta_agent_s
   /** Progress timer - interval between provisional responses sent */
   unsigned              sa_progress;
 
+  /** SIP timer C - interval between provisional responses receivedxs */
+  unsigned              sa_timer_c;
+
   /** Blacklisting period */
   unsigned              sa_blacklist;
 
-  /** NTA is used to test packet drop */
+    /** NTA is used to test packet drop */
   unsigned              sa_drop_prob : 10;
   /** NTA is acting as an User Agent server */
   unsigned              sa_is_a_uas : 1;
@@ -226,6 +229,9 @@ struct nta_agent_s
 
   /** Set when executing timer */
   unsigned              sa_in_timer:1;
+  
+  /** Set if application has set value for timer C */
+  unsigned              sa_use_timer_c:1;
 
   unsigned              :0;
 
@@ -307,7 +313,7 @@ struct nta_agent_s
 
     /* Special queues (states) for outgoing INVITE transactions */
     outgoing_queue_t  inv_calling[1];  /* Timer B/A */
-    outgoing_queue_t  inv_proceeding[1];
+    outgoing_queue_t  inv_proceeding[1]; /* Timer C */
     outgoing_queue_t  inv_completed[1];        /* Timer D */
 
     /* Temporary queue for transactions waiting to be freed */
@@ -517,6 +523,7 @@ struct nta_outgoing_s
   unsigned orq_sigcomp_zap:1;  /**< Reset SigComp after completing */
   unsigned orq_must_100rel : 1;
   unsigned orq_timestamp : 1;  /**< Insert @Timestamp header. */
+  unsigned orq_100rel:1;       /**< Support 100rel */
   unsigned : 0;        /* pad */
 
 #if HAVE_SOFIA_SRESOLV
index 60adcd74ad3250d37e21c7c6f05fbdd2bd1fcdb4..1972b89c451751267ba51fead32d8cd43b96e205 100644 (file)
@@ -76,6 +76,7 @@ tag_typedef_t ntatag_sip_t1x64 = UINTTAG_TYPEDEF(sip_t1x64);
 tag_typedef_t ntatag_sip_t2 = UINTTAG_TYPEDEF(sip_t2);
 tag_typedef_t ntatag_sip_t4 = UINTTAG_TYPEDEF(sip_t4);
 tag_typedef_t ntatag_progress = UINTTAG_TYPEDEF(progress);
+tag_typedef_t ntatag_timer_c = UINTTAG_TYPEDEF(timer_c);
 tag_typedef_t ntatag_blacklist = UINTTAG_TYPEDEF(blacklist);
 tag_typedef_t ntatag_debug_drop_prob = UINTTAG_TYPEDEF(debug_drop_prob);
 
index e0f284b7e73bbe8eb534c13f9190cfb317fbfe25..246e4f290de49c81de69f37329fc402a465674ca 100644 (file)
@@ -58,7 +58,25 @@ NTA_DLL extern tag_typedef_t ntatag_any;
 /* Tags for parameters */
 
 NTA_DLL extern tag_typedef_t ntatag_mclass;
-/** Message class used by NTA. @HI */
+/** Message class used by NTA. 
+ *
+ * The nta can use a custom or extended parser created with
+ * msg_mclass_clone().
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    pointer to #msg_mclass_t.
+ *
+ * @par Values
+ *    - custom or extended parser created with msg_mclass_clone()
+ *    - NULL - use default parser
+ *
+ * @sa NTATAG_SIPFLAGS()
+ */
 #define NTATAG_MCLASS(x) ntatag_mclass, tag_cptr_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_mclass_ref;
@@ -68,9 +86,33 @@ NTA_DLL extern tag_typedef_t ntatag_bad_req_mask;
 /** Mask for bad request messages. 
  * 
  * If an incoming request has erroneous headers matching with the mask, nta
- * automatically returns a 400 Bad Message response to them. If no mask is
- * specified, all requests with any bad header are dropped.
+ * automatically returns a 400 Bad Message response to them. 
+ *
+ * If mask ~0U (all bits set) is specified, all requests with any bad header
+ * are dropped. By default only the requests with bad headers essential for
+ * request processing or proxying are dropped.
  * 
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - bitwise or of enum #sip_bad_mask values
+ *
+ * @sa enum #sip_bad_mask, NTATAG_BAD_RESP_MASK()
+ *
+ * @note
+ * The following headers are considered essential by default:
+ * - @ref sip_request \"request line\"", @From, @To, @CSeq, @CallID,
+ *   @ContentLength, @Via, @ContentType, @ContentDisposition,
+ *   @ContentEncoding, @Supported, @Contact, @Require, @RecordRoute, @RAck,
+ *   @RSeq, @Event, @Expires, @SubscriptionState, @SessionExpires,
+ *   @MinSE, @SIPEtag, and @SIPIfMatch.
+ *  
  */
 #define NTATAG_BAD_REQ_MASK(x) ntatag_bad_req_mask, tag_uint_v((x))
 
@@ -81,8 +123,32 @@ NTA_DLL extern tag_typedef_t ntatag_bad_resp_mask;
 /** Mask for bad response messages. 
  * 
  * If an incoming response has erroneous headers matching with the mask, nta
- * drops the response message. If no mask is specified, all responses with
- * any bad header are dropped.
+ * drops the response message. 
+ *
+ * If mask ~0U (all bits set) is specified, all responses with any bad header
+ * are dropped. By default only the responses with bad headers essential for
+ * response processing or proxying are dropped.
+ * 
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - bitwise or of enum #sip_bad_mask values
+ *
+ * @sa enum #sip_bad_mask, NTATAG_BAD_REQ_MASK()
+ *
+ * @note
+ * The following headers are considered essential by default:
+ * - @ref sip_status \"status line\"", @From, @To, @CSeq, @CallID,
+ *   @ContentLength, @Via, @ContentType, @ContentDisposition,
+ *   @ContentEncoding, @Supported, @Contact, @Require, @RecordRoute, @RAck,
+ *   @RSeq, @Event, @Expires, @SubscriptionState, @SessionExpires, 
+ *   @MinSE, @SIPEtag, and @SIPIfMatch.
  */
 #define NTATAG_BAD_RESP_MASK(x) ntatag_bad_resp_mask, tag_uint_v((x))
 
@@ -90,18 +156,37 @@ NTA_DLL extern tag_typedef_t ntatag_bad_resp_mask_ref;
 #define NTATAG_BAD_RESP_MASK_REF(x) ntatag_bad_resp_mask_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_default_proxy;
-/** URL for (default) proxy. @HI */
-#define NTATAG_DEFAULT_PROXY(x) \
-ntatag_default_proxy, urltag_url_v((x))
+/** URL for (default) proxy.
+ *
+ * The requests are sent towards the <i>default outbound proxy</i> regardless
+ * the values of request-URI or @Route headers in the request. The URL of
+ * the default proxy is not added to the request in the @Route header or in
+ * the request-URI (against the recommendation of @RFC3261 section 8.1.2).
+ *
+ * The outbound proxy set by NTATAG_DEFAULT_PROXY() is used even if the
+ * dialog had an established route set or registration provided User-Agent
+ * with a @ServiceRoute set.
+ *
+ * @par Used with
+ *    nua_create(), nta_agent_create(), nta_agent_set_params() \n
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend()
+ *
+ * @par Parameter type
+ *    Pointer to a url_t structure or a string containg a SIP or SIPS URI
+ *
+ * @par Values
+ *    - Valid SIP or SIPS URI
+ */
+#define NTATAG_DEFAULT_PROXY(x) ntatag_default_proxy, urltag_url_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_default_proxy_ref;
 #define NTATAG_DEFAULT_PROXY_REF(x) \
 ntatag_default_proxy_ref, urltag_url_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_contact;
-/** Contact used by NTA. @HI */
-#define NTATAG_CONTACT(x) \
-ntatag_contact, siptag_contact_v((x))
+/** Contact used by NTA. */
+#define NTATAG_CONTACT(x) ntatag_contact, siptag_contact_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_contact_ref;
 #define NTATAG_CONTACT_REF(x) \
@@ -136,21 +221,42 @@ ntatag_branch_key_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_ack_branch;
 /** Branch for ACKed transaction. @HI */
-#define NTATAG_ACK_BRANCH(x) \
-ntatag_ack_branch, tag_str_v((x))
+#define NTATAG_ACK_BRANCH(x) ntatag_ack_branch, tag_str_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_ack_branch_ref;
-#define NTATAG_ACK_BRANCH_REF(x) \
-ntatag_ack_branch_ref, tag_str_vr(&(x))
+#define NTATAG_ACK_BRANCH_REF(x) ntatag_ack_branch_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_comp;
-/** Compression algorithm. @HI */
-#define NTATAG_COMP(x) \
-ntatag_comp, tag_str_v((x))
+/** Compression algorithm. 
+ *
+ * Set compression algorithm for request as described in @RFC3486.
+ *
+ * @note This tag is has no effect without a compression plugin.
+ *
+ * @par Used with
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend()
+ *
+ * @par
+ * Note that NTATAG_COMP(NULL) can be used with nta_incoming_set_params()
+ * and nta_incoming_treply(), too. It indicates that the response is sent
+ * uncompressed, no matter what the client has in @a comp parameter of @Via
+ * header.
+ *
+ * @par Parameter type
+ *    string
+ *
+ * @par Values
+ *    - name of the compression algorithm ("sigcomp")
+ *
+ * @sa @RFC3320, @RFC3486, TPTAG_COMPARTMENT(),
+ * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(),
+ * NTATAG_SIGCOMP_CLOSE(), NTATAG_SIGCOMP_OPTIONS()
+ */
+#define NTATAG_COMP(x) ntatag_comp, tag_str_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_comp_ref;
-#define NTATAG_COMP_REF(x) \
-ntatag_comp_ref, tag_str_vr(&(x))
+#define NTATAG_COMP_REF(x) ntatag_comp_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_msg;
 /** Pass a SIP message to treply()/tcreate() functions. @HI */
@@ -181,14 +287,49 @@ NTA_DLL extern tag_typedef_t ntatag_smime_ref;
 #define NTATAG_SMIME_REF(x) ntatag_smime_ref, tag_ptr_vr(&(x), (x))
  
 NTA_DLL extern tag_typedef_t ntatag_maxsize;
-/** Maximum size of incoming message. @HI */
+/** Maximum size of incoming message. @HI 
+ *
+ * If the size of an incoming request message would exceed the
+ * given limit, the stack will automatically respond with <i>413 Request
+ * Entity Too Large</i>.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    usize_t 
+ *
+ * @par Values
+ *    - Maximum acceptable size of an incoming request message.
+ *      Default value is 2 megabytes (2097152 bytes).
+ *
+ * @sa msg_maxsize()
+ */
 #define NTATAG_MAXSIZE(x) ntatag_maxsize, tag_usize_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_maxsize_ref;
 #define NTATAG_MAXSIZE_REF(x) ntatag_maxsize_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_udp_mtu;
-/** Maximum size of outgoing UDP request. @HI */
+/** Maximum size of outgoing UDP request. @HI 
+ *
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    
+ *
+ * @par Values
+ *    - 
+ *
+ * @sa
+ *
+ */
 #define NTATAG_UDP_MTU(x) ntatag_udp_mtu, tag_usize_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_udp_mtu_ref;
@@ -196,9 +337,23 @@ NTA_DLL extern tag_typedef_t ntatag_udp_mtu_ref;
 
 NTA_DLL extern tag_typedef_t ntatag_max_forwards;
 /** Default value for @MaxForwards header. 
+ *
+ * The default value of @MaxForwards header added to the requests. The
+ * initial value recommended by @RFC3261 is 70, but usually SIP proxies use
+ * much lower default value, such as 24.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned
+ *
+ * @par Values
+ *    - Default value added to the @MaxForwards header in the sent requests
  *
  * @since New in @VERSION_1_12_2.
- * @hideinitializer 
  */
 #define NTATAG_MAX_FORWARDS(x) ntatag_max_forwards, tag_uint_v((x))
 
@@ -206,42 +361,194 @@ NTA_DLL extern tag_typedef_t ntatag_max_forwards_ref;
 #define NTATAG_MAX_FORWARDS_REF(x) ntatag_max_forwards_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t1;
-/** Initial retransmission interval (in milliseconds) @HI */
+/** Initial retransmission interval (in milliseconds) @HI 
+ *
+ * Set the T1 retransmission interval used by the SIP transaction engine. The
+ * T1 is the initial duration used by request retransmission timers A and E
+ * (UDP) as well as response retransmission timer G.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - Value of SIP T1 in milliseconds 
+ *
+ * @sa @RFC3261 appendix A, NTATAG_SIP_T1X4(), NTATAG_SIP_T1(), NTATAG_SIP_T4()
+ */
 #define NTATAG_SIP_T1(x) ntatag_sip_t1, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t1_ref;
 #define NTATAG_SIP_T1_REF(x) ntatag_sip_t1_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t1x64;
-/** Transaction timeout (defaults to T1 * 64). @HI */
+/** Transaction timeout (defaults to T1 * 64). @HI 
+ *
+ * Set the T1x64  timeout value used by the SIP transaction engine. The T1x64 is
+ * duration used for timers B, F, H, and J (UDP) by the SIP transaction engine. 
+ * The timeout value T1x64 can be adjusted separately from the initial
+ * retransmission interval T1, which is set with NTATAG_SIP_T1().
+ * 
+ * The default value for T1x64 is 64 times value of T1, or 32000 milliseconds.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - Value of T1x64 in milliseconds
+ *
+ * @sa @RFC3261 appendix A, NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4()
+ *
+ */
 #define NTATAG_SIP_T1X64(x) ntatag_sip_t1x64, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t1x64_ref;
 #define NTATAG_SIP_T1X64_REF(x) ntatag_sip_t1x64_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t2;
-/** Maximum retransmission interval (in milliseconds) @HI */
+/** Maximum retransmission interval (in milliseconds) @HI 
+ *
+ * Set the maximum retransmission interval used by the SIP transaction
+ * engine. The T2 is the maximum duration used for the timers E (UDP) and G
+ * by the SIP transaction engine. Note that the timer A is not capped by T2. 
+ * Retransmission interval of INVITE requests grows exponentially until the
+ * timer B fires.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - Value of SIP T2 in milliseconds 
+ *
+ * @sa @RFC3261 appendix A, NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T4()
+ */
 #define NTATAG_SIP_T2(x) ntatag_sip_t2, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t2_ref;
 #define NTATAG_SIP_T2_REF(x) ntatag_sip_t2_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t4;
-/** Transaction lifetime (in milliseconds) @HI */
+/** Transaction lifetime (in milliseconds) @HI 
+ *
+ * Set the lifetime for completed transactions used by the SIP transaction
+ * engine. A completed transaction is kept around for the duration of T4 in
+ * order to catch late responses. The T4 is the maximum duration for the
+ * messages to stay in the network and the duration of SIP timer K.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    - Value of SIP T4 in milliseconds
+ *
+ * @sa @RFC3261 appendix A, NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2()
+ */
 #define NTATAG_SIP_T4(x)    ntatag_sip_t4, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sip_t4_ref;
 #define NTATAG_SIP_T4_REF(x) ntatag_sip_t4_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_progress;
-/** Progress timer for User-Agents (interval for retranmitting 1XXs) @HI */
+/** Progress timer for User-Agents (interval for retranmitting 1XXs) @HI.
+ *
+ * The UAS should retransmit preliminary responses to the INVITE
+ * transactions every minute in order to re-set the timer C within the
+ * intermediate proxies.
+ *
+ * The default value for the progress timer is 60000.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    Value of progress timer in milliseconds.
+ *
+ * @sa @RFC3261 sections 13.3.1.1, 16.7 and 16.8, NTATAG_TIMER_C(),
+ * NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2(), NTATAG_SIP_T4()
+ */
 #define NTATAG_PROGRESS(x)    ntatag_progress, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_progress_ref;
 #define NTATAG_PROGRESS_REF(x) ntatag_progress_ref, tag_uint_vr(&(x))
 
+NTA_DLL extern tag_typedef_t ntatag_timer_c;
+/** Value for timer C in milliseconds. @HI
+ *
+ * By default the INVITE transaction will not timeout after a preliminary
+ * response has been received. However, an intermediate proxy can timeout
+ * the transaction using timer C. Timer C is reset every time a response
+ * belonging to the transaction is received.
+ *
+ * The default value for the timer C is 185000 milliseconds (3 minutes and 5
+ * seconds). By default, timer C is not run on user agents (if NTATAG_UA(1)
+ * without NTATAG_TIMER_C() is fgiven).
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int
+ *
+ * @par Values
+ *    Value of SIP timer C in milliseconds. The default value is used
+ *    instead if NTATAG_TIMER_C(0) is given.
+ *
+ * @sa @RFC3261 sections 13.3.1.1, 16.7 and 16.8,
+ * NTATAG_UA(1), NTATAG_TIMER_C(),
+ * NTATAG_SIP_T1(), NTATAG_SIP_T1X4(), NTATAG_SIP_T2(), NTATAG_SIP_T4()
+ */
+#define NTATAG_TIMER_C(x)    ntatag_timer_c, tag_uint_v((x))
+
+NTA_DLL extern tag_typedef_t ntatag_timer_c_ref;
+#define NTATAG_TIMER_C_REF(x) ntatag_timer_c_ref, tag_uint_vr(&(x))
+
 NTA_DLL extern tag_typedef_t ntatag_blacklist;
-/** Add Retry-After header to internally-generated error messages. @HI */
+/** Add Retry-After header to internally-generated error messages. @HI 
+ *
+ * The NTATAG_BLACKLIST() provides a default value for @RetryAfter header
+ * added to the internally generated responses such as <i>503 DNS Error</i>
+ * or <i>408 Timeout</i>. The idea is that the application can retain its
+ * current state and retry the operation after a while.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *     unsigned int
+ *
+ * @par Values
+ *    - Value of @RetryAfter header (in seconds)
+ *
+ * @sa NTATAG_TIMEOUT_408()
+ */
 #define NTATAG_BLACKLIST(x)  ntatag_blacklist, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_blacklist_ref;
@@ -250,38 +557,134 @@ NTA_DLL extern tag_typedef_t ntatag_blacklist_ref;
 NTA_DLL extern tag_typedef_t ntatag_debug_drop_prob;
 /** Packet drop probability for debugging. 
  *
- * The packet drop probability parameter is useful mainly in proxies for
- * debugging purposes. The stack drops an incoming message with the given
- * probability. The range is in 0 .. 1000, 500 means p=0.5.
- @HI */
+ * The packet drop probability parameter is useful mainly for debugging
+ * purposes. The stack drops an incoming message received over an unreliable
+ * transport (such as UDP) with the given probability. The range is in 0 .. 
+ * 1000, 500 means p=0.5.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned integer
+ *
+ * @par Values
+ *    - Valid values are in range 0 ... 1000
+ *    - Probablity to drop a given message is value / 1000.
+ *
+ * @HI
+ */
 #define NTATAG_DEBUG_DROP_PROB(x) ntatag_debug_drop_prob, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_debug_drop_prob_ref;
 #define NTATAG_DEBUG_DROP_PROB_REF(x) ntatag_debug_drop_prob_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_options;
-/** Semicolon-separate SigComp options. @HI */
+/** Semicolon-separated SigComp options.
+ *
+ * @note This tag is has no effect without a SigComp plugin.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *    nta_agent_add_tport() \n
+ *
+ * @par Parameter type
+ *    string 
+ *
+ * @par Values
+ *    - semicolon-separated parameter-value pairs, passed to the SigComp plugin
+ *
+ * @sa NTATAG_COMP(), NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(),
+ * NTATAG_SIGCOMP_CLOSE(), @RFC3320
+ * @HI
+ */
 #define NTATAG_SIGCOMP_OPTIONS(x)    ntatag_sigcomp_options, tag_str_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_options_ref;
 #define NTATAG_SIGCOMP_OPTIONS_REF(x) ntatag_sigcomp_options_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_close;
-/** Close SigComp compartment after completing transaction. @HI */
+/** Close SigComp compartment after completing transaction.
+ *
+ * @note This tag is has no effect without a SigComp plugin.
+ *
+ * @par Used with
+ *    nta_incoming_set_params(), nta_incoming_treply()
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tmcreate(), nta_outgoing_tcancel()
+ *    nta_outgoing_prack(), nta_msg_tsend(), nta_msg_treply()
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - application takes care of compartment management
+ *    - false - stack manages compartments
+ *
+ * @sa NTATAG_COMP(), TPTAG_COMPARTMENT(),
+ * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_AWARE(),
+ * NTATAG_SIGCOMP_OPTIONS(), @RFC3320
+ * @HI
+ */
 #define NTATAG_SIGCOMP_CLOSE(x)  ntatag_sigcomp_close, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_close_ref;
 #define NTATAG_SIGCOMP_CLOSE_REF(x) ntatag_sigcomp_close_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_aware;
-/** Indicate that the application is SigComp-aware. */
+/** Indicate that the application is SigComp-aware. 
+ *
+ * @note This tag is has no effect without a SigComp plugin.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - application takes care of compartment management
+ *    - false - stack manages compartments
+ *
+ * @sa NTATAG_COMP(), NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_CLOSE(),
+ * NTATAG_SIGCOMP_OPTIONS(), @RFC3320
+ * 
+ * @HI
+ */
 #define NTATAG_SIGCOMP_AWARE(x) ntatag_sigcomp_aware, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_aware_ref;
 #define NTATAG_SIGCOMP_AWARE_REF(x) ntatag_sigcomp_aware_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_sigcomp_algorithm;
-/** Specify SigComp algorithm. For example, NULL, LZSS, or LZSS-POC.
+/** Specify SigComp algorithm.  
+ *
+ * @note This tag is has no effect without a SigComp plugin.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *    nta_agent_add_tport() \n
+ *
+ * @par Parameter type
+ *    string 
+ *
+ * @par Values
+ *    - opaque string passed to the SigComp plugin
+ *
+ * @sa NTATAG_COMP(), NTATAG_SIGCOMP_AWARE(), NTATAG_SIGCOMP_CLOSE(),
+ * NTATAG_SIGCOMP_OPTIONS(), @RFC3320
+ * 
+ * @HI
  */
 #define NTATAG_SIGCOMP_ALGORITHM(x) ntatag_sigcomp_algorithm, tag_str_v((x))
 
@@ -290,49 +693,227 @@ NTA_DLL extern tag_typedef_t ntatag_sigcomp_algorithm_ref;
 ntatag_sigcomp_algorithm_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_ua;
-/** If true, NTA acts as User Agent Server or Client by default. @HI */
+/** If true, NTA acts as User Agent Server or Client by default.
+ *
+ * When acting as an UA, the NTA stack will
+ * - respond with 481 to a PRACK request with no matching "100rel" response
+ * - check for out-of-order CSeq headers for each #nta_leg_t dialog object
+ * - if NTATAG_MERGE_482(1) is also used, return <i>482 Request Merged</i> to
+ *   a duplicate request with same @CallID, @CSeq, @From tag but different
+ *   topmost @Via header (see @RFC3261 section 8.2.2.2 Merged Requests)
+ * - silently discard duplicate final responses to INVITE
+ * - retransmit preliminary responses (101..199) to INVITE request in regular
+ *   intervals ("timer N2")
+ * - retransmit 2XX response to INVITE request with exponential intervals 
+ * - handle ACK sent in 2XX response to an INVITE using the
+ *   #nta_ack_cancel_f callback bound to #nta_incoming_t with
+ *   nta_incoming_bind()
+ * - not use timer C unless its value has been explicitly set
+ *
+ * @note This NUTAG_UA(1) is set internally by nua_create()
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - act as an UA 
+ *    - false - act as an proxy 
+ *
+ * @sa NTATAG_MERGE_482()
+ */
 #define NTATAG_UA(x) ntatag_ua, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_ua_ref;
 #define NTATAG_UA_REF(x) ntatag_ua_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_stateless;
-/** If true, agent processes incoming requests statelessly by default. @HI */
+/** Enable stateless processing. @HI 
+ *
+ * @par Server side
+ * The incoming requests are processed statefully if there is a default leg
+ * (created with nta_leg_default()). This option is provided for proxies or
+ * other server elements that process requests statelessly.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Values
+ *    - true - do not pass incoming requests to default leg
+ *    - false - pass incoming requests to default leg, if it exists
+ *
+ * @par Client side
+ * The outgoing requests can be sent statelessly, too, if the
+ * NTATAG_STATELESS(1) is included in the tag list of nta_outgoing_tcreate().
+ *
+ * @par Used with
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tcancel(), nta_outgoing_prack()
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - create only a transient #nta_outgoing_t transaction object
+ *    - false - create an ordinary client transaction object
+ *
+ * @sa NTATAG_IS_UA(), nta_incoming_default(), nta_outgoing_default(),
+ * nta_leg_default()
+ */
 #define NTATAG_STATELESS(x) ntatag_stateless, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_stateless_ref;
 #define NTATAG_STATELESS_REF(x) ntatag_stateless_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_user_via;
-/** Allow application to insert Via headers. @HI */
+/** Allow application to insert Via headers. @HI 
+ *
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - 
+ *    - false - 
+ *
+ * @sa
+ *
+ */
 #define NTATAG_USER_VIA(x) ntatag_user_via, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_user_via_ref;
 #define NTATAG_USER_VIA_REF(x) ntatag_user_via_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_extra_100;
-/** Respond with "100 Trying" if application has not responded. @HI */
+/** Respond with "100 Trying" if application has not responded.
+ *
+ * As per recommended by @RFC4320, the stack can generate a 100 Trying
+ * response to the non-INVITE requests if the application has not responded
+ * to a request within half of the SIP T2 (the default value for T2 is 4000
+ * milliseconds, so the extra <i>100 Trying<i/> would be sent after 2 seconds).
+ *
+ * @par Used with      
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - send extra 100 Trying if application does not respond
+ *    - false - do not send 100 Trying (default)
+ *
+ * @sa @RFC4320, NTATAG_PASS_408(), NTATAG_TIMEOUT_408()
+ */
 #define NTATAG_EXTRA_100(x)    ntatag_extra_100, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_extra_100_ref;
 #define NTATAG_EXTRA_100_REF(x) ntatag_extra_100_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_pass_100;
-/** Pass "100 Trying" provisional answers to the application. @HI */
+/** Pass "100 Trying" provisional answers to the application. @HI 
+ *
+ * By default, the stack silently processes the <i>100 Trying</i> responses
+ * from the server. Usually the <i>100 Trying</i> responses are not
+ * important to the application but rather sent by the outgoing proxy
+ * immediately after it has received the request. However, the application
+ * can ask nta for them by setting NTATAG_PASS_100(1) if, for instance, the
+ * <i>100 Trying</i> responses are needed for user feedback.
+ *
+ * @par Used with
+ *    nua_create(), nta_agent_create(), nta_agent_set_params() \n
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tcancel(), nta_outgoing_prack(), nta_msg_tsend()
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - pass <i>100 Trying</i> to application
+ *    - false - silently process <i>100 Trying</i> responses
+ *
+ * @sa NTATAG_EXTRA_100(), NTATAG_DEFAULT_PROXY()
+ */
 #define NTATAG_PASS_100(x) ntatag_pass_100, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_pass_100_ref;
 #define NTATAG_PASS_100_REF(x) ntatag_pass_100_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_timeout_408;
-/** Generate "408 Request Timeout" response when request times out. @HI */
+/** Generate "408 Request Timeout" response when request times out. @HI 
+ *
+ * This tag is used to prevent stack from generating extra 408 response
+ * messages to non-INVITE requests upon timeout. As per recommended by
+ * @RFC4320, the <i>408 Request Timeout</i> responses to non-INVITE
+ * transaction are not sent over the network to the client by default. The
+ * application can ask stack to pass the 408 responses with
+ * NTATAG_PASS_408(1).
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - generate 408 response
+ *    - false - invoke #nta_response_f callback with NULL sip pointer
+ *              when a non-INVITE transaction times out
+ *
+ * @sa @RFC4320, NTATAG_PASS_408(), NTATAG_EXTRA_100(),
+ */
 #define NTATAG_TIMEOUT_408(x)  ntatag_timeout_408, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_timeout_408_ref;
 #define NTATAG_TIMEOUT_408_REF(x) ntatag_timeout_408_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_pass_408;
-/** Pass "408 Request Timeout" responses to client. @HI */
+/** Pass "408 Request Timeout" responses to the client. @HI 
+ *
+ * As per recommended by @RFC4320, the <i>408 Request Timeout</i> responses
+ * to non-INVITE transaction are not sent over the network to the client by
+ * default. The application can ask stack to pass the 408 responses with
+ * NTATAG_PASS_408(1). 
+ *
+ * Note that unlike NTATAG_PASS_100(), this tags changes the way server side
+ * works.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - pass superfluous 408 responses 
+ *    - false - discard superfluous 408 responses
+ *
+ * @sa @RFC4320, NTATAG_EXTRA_100(), NTATAG_TIMEOUT_408()
+ *
+ */
 #define NTATAG_PASS_408(x)  ntatag_pass_408, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_pass_408_ref;
@@ -346,70 +927,306 @@ NTA_DLL extern tag_typedef_t ntatag_no_dialog_ref;
 #define NTATAG_NO_DIALOG_REF(x)   ntatag_no_dialog_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_merge_482;
-/** Merge requests, send 482 to other requests. @HI */
+/** Merge requests, send 482 to other requests. @HI 
+ *
+ * If an User-Agent receives a duplicate request with same @CallID, @CSeq,
+ * @From tag but different topmost @Via header (see @RFC3261 section 8.2.2.2
+ * Merged Requests), it should return <i>482 Request Merged</i> response to
+ * the duplicate request. Such a duplicate request has been originally
+ * generated by a forking proxy and usually routed via different route to
+ * the User-Agent. The User-Agent should only respond meaningfully to the
+ * first request and return the 482 response to the following forked
+ * requests.
+ *
+ * Note that also NTATAG_UA(1) should be set before nta detects merges and
+ * responds with 482 to them.
+ *
+ * @note If your application is an multi-lined user-agent, you may consider
+ * disabling request merging. However, you have to somehow handle merging
+ * within a single line.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - detect duplicate requests and respond with 482 to them
+ *    - false - process duplicate requests separately
+ *
+ * @sa NTATAG_UA(1)
+ */
 #define NTATAG_MERGE_482(x)       ntatag_merge_482, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_merge_482_ref;
 #define NTATAG_MERGE_482_REF(x)   ntatag_merge_482_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_2543;
-/** Send a CANCEL to an INVITE without an provisional response. @HI */
+/**Follow @RFC2543 semantics with CANCEL.
+ *
+ * By default, the nta follows "@RFC3261" semantics when CANCELing a
+ * request. The CANCEL does not terminate transaction, rather, it is just a
+ * hint to the server that it should respond immediately (with <i>487
+ * Request Terminated</i> if it has no better response). Also, if the
+ * original request was sent over unreliable transport such as UDP, the
+ * CANCEL is delayed until the server has sent a preliminary response to the
+ * original request.
+ *
+ * If NTATAG_CANCEL_2543(1) is given, the transaction is canceled
+ * immediately internally (a 487 response is generated locally) and the
+ * CANCEL request is sent without waiting for an provisional response.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *    nta_outgoing_tcancel()
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - follow "RFC 2543" semantics with CANCEL
+ *    - false - follow "RFC 3261" semantics with CANCEL
+ *
+ * @sa NTATAG_CANCEL_408()
+ * 
+ * @HI
+ */
 #define NTATAG_CANCEL_2543(x)     ntatag_cancel_2543, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_2543_ref;
 #define NTATAG_CANCEL_2543_REF(x) ntatag_cancel_2543_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_408;
-/** Do not send a CANCEL but just timeout the request. @HI */
+/** Do not send a CANCEL but just timeout the request. 
+ *
+ * Calling nta_outgoing_tcancel() with this tag set marks request as
+ * canceled but does not actually send a CANCEL request. If
+ * NTATAG_CANCEL_2543(1) is also included, a 487 response is generated
+ * internally.
+ *
+ * @par Used with
+ *    nta_outgoing_tcancel() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - do not send CANCEL
+ *    - false - let request to timeout
+ *
+ * @sa NTATAG_CANCEL_2543()
+ */
 #define NTATAG_CANCEL_408(x)     ntatag_cancel_408, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_408_ref;
 #define NTATAG_CANCEL_408_REF(x) ntatag_cancel_408_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_tag_3261;
-/** When responding to requests, use unique tags. @HI */
+/** When responding to requests, use unique tags. @HI 
+ *
+ * If set the UA would generate an unique @From/@To tag for all dialogs. If
+ * unset UA would reuse same tag in order to make it easier to re-establish
+ * dialog state after a reboot.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - use different tag for each dialog
+ *    - false - use same tag for all dialogs
+ *
+ * @sa @RFC3261 section 12.2.2
+ */
 #define NTATAG_TAG_3261(x)        ntatag_tag_3261, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_tag_3261_ref;
 #define NTATAG_TAG_3261_REF(x)    ntatag_tag_3261_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_timestamp;
-/** Use Timestamp header. @HI */
+/** Use @Timestamp header. @HI 
+ *
+ * If set, a @Timestamp header would be added to stateful requests. The
+ * header can be used to calculate the roundtrip transport latency between
+ * client and server.
+ *
+ * @par Used with
+ *    nua_create(), 
+ *    nta_agent_create(),
+ *    nta_agent_set_params(),
+ *    nta_outgoing_mcreate(), nta_outgoing_tcreate(),
+ *    nta_outgoing_tcancel(), and nta_outgoing_prack().
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - Add @Timestamp header
+ *    - false - do not add @Timestamp header
+ *
+ * @sa @RFC3261 section 8.2.6
+ */
 #define NTATAG_USE_TIMESTAMP(x) ntatag_use_timestamp, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_timestamp_ref;
 #define NTATAG_USE_TIMESTAMP_REF(x) ntatag_use_timestamp_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_method;
-/** Method name. @HI */
+/**Method name. @HI 
+ *
+ * Create a dialogless #nta_leg_t object matching only requests with
+ * the specified method.
+ *
+ * @par Used with
+ *   nta_leg_tcreate()
+ *
+ * @par Parameter type
+ *    String containing method name.
+ *
+ * @par Values
+ *    SIP method name (e.g., "SUBSCRIBE").
+ *
+ */
 #define NTATAG_METHOD(x)          ntatag_method, tag_str_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_method_ref;
 #define NTATAG_METHOD_REF(x)      ntatag_method_ref, tag_str_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_487;
-/** When a CANCEL is received, reply with 487 response. True by default. @HI */
+/** When a CANCEL is received, automatically return 487 response to original request.
+ *
+ * When the CANCEL is received for an ongoing server transaction
+ * #nta_incoming_t, the stack will automatically return a <i>487 Request
+ * Terminated</i> response to the client after returning from the
+ * #nta_incoming_f callback bound to the transaction with
+ * nta_incoming_bind()
+ * 
+ * The application can delay sending the response to the original request
+ * when NTATAG_CANCEL_408(0) is used. This is useful, for instance, with a
+ * proxy that forwards the CANCEL downstream and the forwards the response
+ * back to upstream.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - respond automatically to the CANCELed transaction
+ *    - false - application takes care of responding
+ *
+ * @sa NTATAG_CANCEL_2543(), nta_incoming_bind()
+ *
+ * @HI
+ */
 #define NTATAG_CANCEL_487(x)     ntatag_cancel_487, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_cancel_487_ref;
 #define NTATAG_CANCEL_487_REF(x) ntatag_cancel_487_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_rel100;
-/** Include rel100 in INVITE requests. @HI */
+/** Include rel100 in INVITE requests. @HI 
+ *
+ * Include feature tag "100rel" in @Supported header of the INVITE requests.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - include "100rel"
+ *    - false - do not include "100rel"
+ *
+ * @sa nta_outgoing_prack(), nta_reliable_treply(), nta_reliable_mreply()
+ */
 #define NTATAG_REL100(x)     ntatag_rel100, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_rel100_ref;
 #define NTATAG_REL100_REF(x) ntatag_rel100_ref, tag_bool_vr(&(x))
  
 NTA_DLL extern tag_typedef_t ntatag_sipflags;
-/** Set SIP parser flags. @HI */
+/** Set SIP parser flags. @HI 
+ *
+ * The SIP parser flags affect how the messages are parsed and the result
+ * presented to the application. They also control encoding of messages.
+ * The most important flags are as follows:
+ * - MSG_FLG_COMPACT - use compact form 
+ *                     (single-letter header names, minimum whitespace)
+ * - MSG_FLG_EXTRACT_COPY - cache printable copy of headers when parsing. 
+ *   Using this flag can speed up proxy processing considerably. It is
+ *   implied when the parsed messages are logged (because #TPORT_LOG
+ *   environment variable is set, or TPTAG_LOG() is used.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned int 
+ *
+ * @par Values
+ *    - Bitwise OR of SIP parser flags (enum #msg_flg_user)
+ *
+ * @sa NTATAG_PRELOAD(), enum #msg_flg_user, sip_s::sip_flags
+ */
 #define NTATAG_SIPFLAGS(x)     ntatag_sipflags, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_sipflags_ref;
 #define NTATAG_SIPFLAGS_REF(x) ntatag_sipflags_ref, tag_uint_vr(&(x))
  
 NTA_DLL extern tag_typedef_t ntatag_client_rport;
-/** Add rport at client. @HI */
+/** Enable client-side "rport". @HI 
+ *
+ * This tag controls @RFC3581 support on client side. The "rport" parameter
+ * is used when the response has to be routed symmetrically through a NAT box.
+ *
+ * The client-side support involves just adding the "rport" parameter to the topmost
+ * @Via header before the request is sent. 
+ *
+ * @note By default, the client "rport" is disabled when nta is used, and
+ * enabled when nua is used.
+ *
+ * @par Used with
+ *    nua_create() (nua uses NTATAG_CLIENT_RPORT(1) by default) \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - add "rport" parameter
+ *    - false - do not add "rport" parameter
+ *
+ * @note The NTATAG_RPORT() is a synonym for this.
+ *
+ * @sa @RFC3581, NTATAG_SERVER_RPORT(), @Via
+ */
 #define NTATAG_CLIENT_RPORT(x) ntatag_client_rport, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_client_rport_ref;
@@ -419,42 +1236,158 @@ NTA_DLL extern tag_typedef_t ntatag_client_rport_ref;
 #define NTATAG_RPORT_REF(x) ntatag_client_rport_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_server_rport;
-/** Use rport at server. @HI */
+/** Use rport parameter at server.
+ *
+ * This tag controls @RFC3581 support on server side. The "rport" parameter
+ * is used when the response has to be routed symmetrically through a NAT
+ * box.
+ *
+ * If the topmost @Via header has an "rport" parameter, the server stores
+ * the port number from which the request was sent in it. When sending the
+ * response back to the client, the server uses the port number in the
+ * "rport" parameter rather than the client-supplied port number in @Via
+ * header.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - use "rport" parameter (default)
+ *    - false - do not use "rport" parameterx
+ *
+ * @sa @RFC3581, NTATAG_CLIENT_RPORT(), @Via
+ */
 #define NTATAG_SERVER_RPORT(x) ntatag_server_rport, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_server_rport_ref;
 #define NTATAG_SERVER_RPORT_REF(x) ntatag_server_rport_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_tcp_rport;
-/** Use rport with TCP, too. @HI */
+/** Use rport with TCP, too. @HI 
+ *
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - 
+ *    - false - 
+ *
+ * @sa
+ *
+ */
 #define NTATAG_TCP_RPORT(x) ntatag_tcp_rport, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_tcp_rport_ref;
 #define NTATAG_TCP_RPORT_REF(x) ntatag_tcp_rport_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_preload;
-/** Preload by N bytes. @HI */
+/** Preload by N bytes. @HI 
+ *
+ * When the memory block is allocated for an incoming request by the stack,
+ * the stack can allocate some extra memory for the parser in addition to
+ * the memory used by the actual message contents. 
+ * 
+ * While wasting some memory, this can speed up parsing considerably.
+ * Recommended amount of preloading per packet is 1500 bytes.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    unsigned
+ *
+ * @par Values
+ *    Amount of extra per-message memory allocated for parser.
+ *
+ * @sa NTATAG_SIPFLAGS() and #MSG_FLG_EXTRACT_COPY
+ */
 #define NTATAG_PRELOAD(x) ntatag_preload, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_preload_ref;
 #define NTATAG_PRELOAD_REF(x) ntatag_preload_ref, tag_uint_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_naptr;
-/** If true, try to use NAPTR records when resolving. @HI */
+/** If true, try to use NAPTR records when resolving. @HI 
+ *
+ * The application can disable NTA from using NAPTR records when resolving
+ * SIP URIs.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - enable NAPTR resolving
+ *    - false - disable NAPTR resolving
+ *
+ * @bug NAPTRs are not used with SIPS URIs in any case.
+ *
+ * @sa @RFC3263, NTATAG_USE_SRV()
+ */
 #define NTATAG_USE_NAPTR(x) ntatag_use_naptr, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_naptr_ref;
 #define NTATAG_USE_NAPTR_REF(x) ntatag_use_naptr_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_srv;
-/** If true, try to use SRV records when resolving. @HI */
+/** If true, try to use SRV records when resolving.
+ *
+ * The application can disable NTA from using SRV records when resolving
+ * SIP URIs.
+ *
+ * @par Used with
+ *    nua_create() \n
+ *    nta_agent_create() \n
+ *    nta_agent_set_params() \n
+ *
+ * @par Parameter type
+ *    boolean: true (non-zero or non-NULL pointer)
+ *          or false (zero or NULL pointer)
+ *
+ * @par Values
+ *    - true - enable SRV resolving
+ *    - false - disable SRV resolving
+ *
+ * @sa @RFC3263, NTATAG_USE_NAPTR()
+ */
 #define NTATAG_USE_SRV(x) ntatag_use_srv, tag_bool_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_use_srv_ref;
 #define NTATAG_USE_SRV_REF(x) ntatag_use_srv_ref, tag_bool_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_rseq;
-/** RSeq value for nta_outgoing_prack(), @HI */
+
+/** @RSeq value for nta_outgoing_prack(). @HI 
+ *
+ * @par Used with
+ *    nta_outgoing_prack()
+ *
+ * @par Parameter type
+ *    @c unsigned @c int
+ *
+ * @par Values
+ *    Response sequence number from the @RSeq header.
+*/
 #define NTATAG_RSEQ(x)    ntatag_rseq, tag_uint_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_rseq_ref;
@@ -467,24 +1400,56 @@ NTA_DLL extern tag_typedef_t ntatag_s_irq_hash;
 #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;
+/** Get size of hash table for server-side transactions.
+ *
+ * Return number of transactions that fit in the hash table for server-side
+ * transactions.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_IRQ_HASH_USED_REF(),
+ * NTATAG_S_ORQ_HASH_REFxs(), NTATAG_S_LEG_HASH_REF()
+ */
 #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_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_ref;
+/** Get size of hash table for client-side transactions.
+ *
+ * Return number of transactions that fit in the hash table for client-side
+ * transactions.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_ORQ_HASH_USED_REF(),
+ * NTATAG_S_IRQ_HASH_REF(), NTATAG_S_LEG_HASH_REF()
+ */
 #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_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_ref;
+/** Get size of hash table for dialogs.
+ *
+ * Return number of dialog objects that fit in the hash table for dialogs.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_LEG_HASH_USED_REF(),
+ * NTATAG_S_IRQ_HASH_REF(), NTATAG_S_ORQ_HASH_REF()
+ */
 #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_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_irq_hash_used_ref;
+/** Get number of server-side transactions in the hash table.
+ *
+ * Return number of server-side transactions objects in the hash table. The
+ * number includes all transactions destroyed by the application which have
+ * not expired yet.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_IRQ_HASH_REF(),
+ * NTATAG_S_ORQ_HASH_USED_REF(), NTATAG_S_LEG_HASH_USED_REF()
+ */
 #define NTATAG_S_IRQ_HASH_USED_REF(x) \
 ntatag_s_irq_hash_used_ref, tag_usize_vr(&(x))
 
@@ -492,6 +1457,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_orq_hash_used;
 #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;
+/** Get number of client-side transactions in the hash table.
+ *
+ * Return number of client-side transactions objects in the hash table. The
+ * number includes all transactions destroyed by the application which have
+ * not expired yet.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_ORQ_HASH_REF(),
+ * NTATAG_S_IRQ_HASH_USED_REF(), NTATAG_S_LEG_HASH_USED_REF()
+ */
 #define NTATAG_S_ORQ_HASH_USED_REF(x) \
 ntatag_s_orq_hash_used_ref, tag_usize_vr(&(x))
 
@@ -499,6 +1473,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used;
 #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;
+/** Get number of dialogs in the hash table.
+ *
+ * Return number of dialog objects in the hash table. Note that the
+ * nta_leg_t objects created with NTATAG_NO_DIALOG(1) and this not
+ * corresponding to a dialog are not included in the number.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_LEG_HASH_REF(),
+ * NTATAG_S_IRQ_HASH_USED_REF(), NTATAG_S_ORQ_HASH_USED_REF()
+ */
 #define NTATAG_S_LEG_HASH_USED_REF(x) \
 ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x))
 
@@ -506,12 +1489,28 @@ NTA_DLL extern tag_typedef_t ntatag_s_recv_msg;
 #define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_msg_ref;
+/** Get number of SIP messages received.
+ *
+ * Return number SIP messages that has been received.  The number includes
+ * also bad and unparsable messages.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(),
+ * NTATAG_S_RECV_REQUEST_REF(), NTATAG_S_RECV_RESPONSE_REF()
+ */
 #define NTATAG_S_RECV_MSG_REF(x) ntatag_s_recv_msg_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_request;
 #define NTATAG_S_RECV_REQUEST(x) ntatag_s_recv_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_request_ref;
+/** Get number of SIP requests received.
+ *
+ * Return number SIP requests that has been received. The number includes
+ * also number of bad requests available with NTATAG_S_BAD_REQUEST_REF().
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_BAD_REQUEST_REF(),
+ * NTATAG_S_RECV_MSG_REF(), NTATAG_S_RECV_RESPONSE_REF()
+ */
 #define NTATAG_S_RECV_REQUEST_REF(x)\
  ntatag_s_recv_request_ref, tag_usize_vr(&(x))
 
@@ -519,6 +1518,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_recv_response;
 #define NTATAG_S_RECV_RESPONSE(x) ntatag_s_recv_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_response_ref;
+/** Get number of SIP responses received.
+ *
+ * Return number SIP responses that has been received. The number includes
+ * also number of bad and unusable responses available with
+ * NTATAG_S_BAD_RESPONSE_REF().
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_BAD_RESPONSE_REF(),
+ * NTATAG_S_RECV_MSG_REF(), NTATAG_S_RECV_REQUEST_REF()
+ */
 #define NTATAG_S_RECV_RESPONSE_REF(x)\
  ntatag_s_recv_response_ref, tag_usize_vr(&(x))
 
@@ -526,6 +1534,13 @@ NTA_DLL extern tag_typedef_t ntatag_s_bad_message;
 #define NTATAG_S_BAD_MESSAGE(x) ntatag_s_bad_message, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_message_ref;
+/** Get number of bad SIP messages received.
+ *
+ * Return number of bad SIP messages that has been received.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RECV_MSG_REF(), 
+ * NTATAG_S_BAD_REQUEST_REF(), NTATAG_S_BAD_RESPONSE_REF().
+ */
 #define NTATAG_S_BAD_MESSAGE_REF(x)\
  ntatag_s_bad_message_ref, tag_usize_vr(&(x))
 
@@ -533,6 +1548,13 @@ NTA_DLL extern tag_typedef_t ntatag_s_bad_request;
 #define NTATAG_S_BAD_REQUEST(x) ntatag_s_bad_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_request_ref;
+/** Get number of bad SIP requests received.
+ *
+ * Return number of bad SIP requests that has been received.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(),
+ * NTATAG_S_BAD_RESPONSE_REF().
+ */
 #define NTATAG_S_BAD_REQUEST_REF(x)\
  ntatag_s_bad_request_ref, tag_usize_vr(&(x))
 
@@ -540,6 +1562,13 @@ NTA_DLL extern tag_typedef_t ntatag_s_bad_response;
 #define NTATAG_S_BAD_RESPONSE(x) ntatag_s_bad_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_response_ref;
+/** Get number of bad SIP responses received.
+ *
+ * Return number of bad SIP responses that has been received.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_BAD_MESSAGE_REF(),
+ * NTATAG_S_BAD_REQUEST_REF()
+ */
 #define NTATAG_S_BAD_RESPONSE_REF(x)\
  ntatag_s_bad_response_ref, tag_usize_vr(&(x))
 
@@ -547,6 +1576,16 @@ NTA_DLL extern tag_typedef_t ntatag_s_drop_request;
 #define NTATAG_S_DROP_REQUEST(x) ntatag_s_drop_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_drop_request_ref;
+/** Get number of SIP requests dropped.
+ *
+ * Return number of SIP requests that has been randomly dropped after
+ * receiving them because of NTATAG_DEBUG_DROP_PROB() has been set.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_DEBUG_DROP_PROB(),
+ * NTATAG_S_DROP_RESPONSE_REF()
+ * 
+ * @note The value was not calculated before @VERSION_1_12_7.
+ */
 #define NTATAG_S_DROP_REQUEST_REF(x)\
  ntatag_s_drop_request_ref, tag_usize_vr(&(x))
 
@@ -554,6 +1593,16 @@ NTA_DLL extern tag_typedef_t ntatag_s_drop_response;
 #define NTATAG_S_DROP_RESPONSE(x) ntatag_s_drop_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_drop_response_ref;
+/** Get number of SIP responses dropped.
+ *
+ * Return number of SIP responses that has been randomly dropped after
+ * receiving them because of NTATAG_DEBUG_DROP_PROB() has been set.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_DEBUG_DROP_PROB(),
+ * NTATAG_S_DROP_REQUEST_REF()
+ * 
+ * @note The value was not calculated before @VERSION_1_12_7.
+ */
 #define NTATAG_S_DROP_RESPONSE_REF(x)\
  ntatag_s_drop_response_ref, tag_usize_vr(&(x))
 
@@ -561,6 +1610,18 @@ NTA_DLL extern tag_typedef_t ntatag_s_client_tr;
 #define NTATAG_S_CLIENT_TR(x) ntatag_s_client_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_client_tr_ref;
+/** Get number of client transactions created.
+ *
+ * Return number of client transactions created. The number also includes
+ * client transactions with which stack failed to send the request because
+ * the DNS resolving failed or the transport failed.
+ *
+ * @note The number include stateless requests sent with nta_msg_tsend(),
+ * too.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SENT_REQUEST_REF(),
+ * NTATAG_S_SERVER_TR_REF().
+ */
 #define NTATAG_S_CLIENT_TR_REF(x)\
  ntatag_s_client_tr_ref, tag_usize_vr(&(x))
 
@@ -568,6 +1629,13 @@ NTA_DLL extern tag_typedef_t ntatag_s_server_tr;
 #define NTATAG_S_SERVER_TR(x) ntatag_s_server_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_server_tr_ref;
+/** Get number of server transactions created.
+ *
+ * Return number of server transactions created. 
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RECV_RESPONSE_REF(),
+ * NTATAG_S_CLIENT_TR_REF(), NTATAG_S_DIALOG_TR_REF(),
+ */
 #define NTATAG_S_SERVER_TR_REF(x)\
  ntatag_s_server_tr_ref, tag_usize_vr(&(x))
 
@@ -575,6 +1643,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr;
 #define NTATAG_S_DIALOG_TR(x) ntatag_s_dialog_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr_ref;
+/** Get number of in-dialog server transactions created.
+ *
+ * Return number of in-dialog server transactions created. The number
+ * includes only those transactions that were correlated with a dialog
+ * object.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(),
+ * NTATAG_S_CLIENT_TR_REF(), NTATAG_S_RECV_RESPONSE_REF().
+ */
 #define NTATAG_S_DIALOG_TR_REF(x)\
  ntatag_s_dialog_tr_ref, tag_usize_vr(&(x))
 
@@ -582,12 +1659,29 @@ NTA_DLL extern tag_typedef_t ntatag_s_acked_tr;
 #define NTATAG_S_ACKED_TR(x) ntatag_s_acked_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_acked_tr_ref;
+/** Get number of server transactions that have received ACK.
+ *
+ * Return number of INVITE server transactions for which an ACK request has
+ * been received.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(),
+ * NTATAG_S_CANCELED_TR_REF()
+ */
 #define NTATAG_S_ACKED_TR_REF(x) ntatag_s_acked_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr;
 #define NTATAG_S_CANCELED_TR(x) ntatag_s_canceled_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr_ref;
+/** Get number of server transactions that have been CANCELed.
+ *
+ * Return number of server transactions for which an CANCEL request has been
+ * received. Currently, the count includes only INVITE server transactions
+ * that have been CANCELed.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SERVER_TR_REF(),
+ * NTATAG_S_ACKED_TR_REF().
+ */
 #define NTATAG_S_CANCELED_TR_REF(x)  \
  ntatag_s_canceled_tr_ref, tag_usize_vr(&(x))
 
@@ -595,6 +1689,17 @@ NTA_DLL extern tag_typedef_t ntatag_s_trless_request;
 #define NTATAG_S_TRLESS_REQUEST(x) ntatag_s_trless_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_request_ref;
+/** Get number of requests that were processed stateless.
+ *
+ * Return number of received requests that were processed statelessly,
+ * either with #nta_message_f message callback given with the
+ * nta_agent_create() or, missing the callback, by returning a <i>501 Not
+ * Implemented</i> response to the request.
+ *
+ * @sa nta_agent_get_stats(), <sofia-sip/nta_stateless.h>,
+ * nta_agent_create(), #nta_message_f, NTATAG_S_TRLESS_TO_TR_REF(),
+ * NTATAG_S_TRLESS_RESPONSE_REF()
+ */
 #define NTATAG_S_TRLESS_REQUEST_REF(x)\
  ntatag_s_trless_request_ref, tag_usize_vr(&(x))
 
@@ -602,6 +1707,14 @@ NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr;
 #define NTATAG_S_TRLESS_TO_TR(x) ntatag_s_trless_to_tr, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr_ref;
+/** Get number of requests converted to transactions by message callback.
+ *
+ * Return number of requests that were converted to a server transaction
+ * with nta_incoming_create().
+ *
+ * @sa nta_agent_get_stats(), nta_incoming_create(), nta_agent_create(),
+ * #nta_message_f, NTATAG_S_TRLESS_REQUEST_REF()
+ */
 #define NTATAG_S_TRLESS_TO_TR_REF(x)\
  ntatag_s_trless_to_tr_ref, tag_usize_vr(&(x))
 
@@ -609,6 +1722,23 @@ NTA_DLL extern tag_typedef_t ntatag_s_trless_response;
 #define NTATAG_S_TRLESS_RESPONSE(x) ntatag_s_trless_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_response_ref;
+/** Get number of responses without matching request.
+ *
+ * Return number of received responses for which no matching client
+ * transaction was found. Such responses are processed either by the default
+ * client transaction created with nta_outgoing_default(), the
+ * #nta_message_f message callback given to nta_agent_create(), or, missing
+ * both the default client transaction and message callback, they are
+ * silently discarded.
+ *
+ * When stack is in UA mode, the successful 2XX responses to the INVITE
+ * transaction are an exception: when such a response is received the stack
+ * tries to send an ACK and BYE requests to the originator of 2XX response.
+ *
+ * @sa nta_agent_get_stats(), nta_outgoing_default(), nta_agent_create(),
+ * <sofia-sip/nta_stateless.h>, #nta_message_f, nta_msg_ackbye(),
+ * NTATAG_S_TRLESS_REQUEST_REF(), NTATAG_S_TRLESS_200_REF().
+ */
 #define NTATAG_S_TRLESS_RESPONSE_REF(x)\
  ntatag_s_trless_response_ref, tag_usize_vr(&(x))
 
@@ -616,6 +1746,21 @@ NTA_DLL extern tag_typedef_t ntatag_s_trless_200;
 #define NTATAG_S_TRLESS_200(x) ntatag_s_trless_200, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_200_ref;
+/** Get number of successful responses missing INVITE client transaction.
+ *
+ * Return number of received 2XX responses to INVITE transaction for which
+ * no matching client transaction was found nor which were processed by a
+ * default client transaction created with nta_outgoing_default() or
+ * #nta_message_f message callback given to nta_agent_create().
+ *
+ * When such a successful 2XX responses to the INVITE is received but it is
+ * not processed, the stack tries to send an ACK and BYE requests to the
+ * originator of 2XX response if stack is in UA mode (set by NTATAG_UA(1). 
+ *
+ * @sa nta_agent_get_stats(), nta_outgoing_default(), nta_agent_create(),
+ * <sofia-sip/nta_stateless.h>, #nta_message_f, nta_msg_ackbye(),
+ * NTATAG_S_TRLESS_RESPONSE_REF().
+ */
 #define NTATAG_S_TRLESS_200_REF(x)\
  ntatag_s_trless_200_ref, tag_usize_vr(&(x))
 
@@ -623,6 +1768,14 @@ NTA_DLL extern tag_typedef_t ntatag_s_merged_request;
 #define NTATAG_S_MERGED_REQUEST(x) ntatag_s_merged_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_merged_request_ref;
+/** Get number of requests merged by UAS.
+ *
+ * Return number of requests for which UAS already has returned a response
+ * and which were merged (that is, returned a <i>482 Request Merged</i>
+ * response).
+ *
+ * @sa nta_agent_get_stats(), NTATAG_UA(1), @RFC3261 section 8.2.2.2
+ */
 #define NTATAG_S_MERGED_REQUEST_REF(x)\
  ntatag_s_merged_request_ref, tag_usize_vr(&(x))
 
@@ -630,6 +1783,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_sent_msg;
 #define NTATAG_S_SENT_MSG(x) ntatag_s_sent_msg, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_msg_ref;
+/** Get number of SIP messages sent by stack.
+ *
+ * Return number of SIP messages given to the transport layer for
+ * transmission by the SIP stack. The number includes also messages which
+ * the transport layer failed to send for different reasons.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RECV_MSG_REF(),
+ * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_SENT_RESPONSE_REF()
+ */
 #define NTATAG_S_SENT_MSG_REF(x)\
  ntatag_s_sent_msg_ref, tag_usize_vr(&(x))
 
@@ -637,6 +1799,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_sent_request;
 #define NTATAG_S_SENT_REQUEST(x) ntatag_s_sent_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_request_ref;
+/** Get number of SIP requests sent by stack.
+ *
+ * Return number of SIP requests given to the transport layer for
+ * transmission by the SIP stack. The number includes retransmissions and
+ * messages which the transport layer failed to send for different reasons.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RECV_REQUEST_REF(),
+ * NTATAG_S_SENT_MSG_REF(), NTATAG_S_SENT_RESPONSE_REF()
+ */
 #define NTATAG_S_SENT_REQUEST_REF(x)\
  ntatag_s_sent_request_ref, tag_usize_vr(&(x))
 
@@ -644,6 +1815,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_sent_response;
 #define NTATAG_S_SENT_RESPONSE(x) ntatag_s_sent_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_response_ref;
+/** Get number of SIP responses sent by stack.
+ *
+ * Return number of SIP responses given to the transport layer for
+ * transmission by the SIP stack. The number includes retransmissions and
+ * messages which the transport layer failed to send for different reasons.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RECV_RESPONSE_REF(),
+ * NTATAG_S_SENT_MSG_REF(), NTATAG_S_SENT_REQUEST_REF()
+ */
 #define NTATAG_S_SENT_RESPONSE_REF(x)\
  ntatag_s_sent_response_ref, tag_usize_vr(&(x))
 
@@ -651,6 +1831,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_retry_request;
 #define NTATAG_S_RETRY_REQUEST(x) ntatag_s_retry_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_retry_request_ref;
+/** Get number of SIP requests retransmitted by stack.
+ *
+ * Return number of SIP requests given to the transport layer for
+ * retransmission by the SIP stack. The number includes messages which the
+ * transport layer failed to send for different reasons.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SENT_MSG_REF(),
+ * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_RETRY_RESPONSE_REF()
+ */
 #define NTATAG_S_RETRY_REQUEST_REF(x)\
  ntatag_s_retry_request_ref, tag_usize_vr(&(x))
 
@@ -658,6 +1847,15 @@ NTA_DLL extern tag_typedef_t ntatag_s_retry_response;
 #define NTATAG_S_RETRY_RESPONSE(x) ntatag_s_retry_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_retry_response_ref;
+/** Get number of SIP responses retransmitted by stack.
+ *
+ * Return number of SIP responses given to the transport layer for
+ * retransmission by the SIP stack. The number includes messages which the
+ * transport layer failed to send for different reasons.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_SENT_MSG_REF(),
+ * NTATAG_S_SENT_REQUEST_REF(), NTATAG_S_RETRY_REQUEST_REF()
+ */
 #define NTATAG_S_RETRY_RESPONSE_REF(x)\
  ntatag_s_retry_response_ref, tag_usize_vr(&(x))
 
@@ -665,6 +1863,14 @@ NTA_DLL extern tag_typedef_t ntatag_s_recv_retry;
 #define NTATAG_S_RECV_RETRY(x) ntatag_s_recv_retry, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_retry_ref;
+/** Get number of retransmitted SIP requests received by stack.
+ *
+ * Return number of SIP requests received by the stack. This number only
+ * includes retransmission for which a matching server transaction object
+ * was found.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_RETRY_REQUEST_REF().
+ */
 #define NTATAG_S_RECV_RETRY_REF(x)\
  ntatag_s_recv_retry_ref, tag_usize_vr(&(x))
 
@@ -672,6 +1878,12 @@ NTA_DLL extern tag_typedef_t ntatag_s_tout_request;
 #define NTATAG_S_TOUT_REQUEST(x) ntatag_s_tout_request, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_tout_request_ref;
+/** Get number of SIP client transactions that has timeout.
+ *
+ * Return number of SIP client transactions that has timeout.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_TOUT_RESPONSE_REF().
+ */
 #define NTATAG_S_TOUT_REQUEST_REF(x)\
  ntatag_s_tout_request_ref, tag_usize_vr(&(x))
 
@@ -679,6 +1891,14 @@ NTA_DLL extern tag_typedef_t ntatag_s_tout_response;
 #define NTATAG_S_TOUT_RESPONSE(x) ntatag_s_tout_response, tag_usize_v(x)
 
 NTA_DLL extern tag_typedef_t ntatag_s_tout_response_ref;
+/** Get number of SIP server transactions that has timeout.
+ *
+ * Return number of SIP server transactions that has timeout. The number
+ * includes only the INVITE transactions for which the stack has received no
+ * ACK requests.
+ *
+ * @sa nta_agent_get_stats(), NTATAG_S_TOUT_REQUEST_REF().
+ */
 #define NTATAG_S_TOUT_RESPONSE_REF(x)\
  ntatag_s_tout_response_ref, tag_usize_vr(&(x))
 
index 620f7d3af9ee1b64b676d8eb086d29189e9c1a5b..4cc562fbc0246dab8acde3499def97c614c99151 100644 (file)
@@ -70,6 +70,10 @@ typedef struct agent_t agent_t;
 #include <assert.h>
 #include <unistd.h>
 
+#if HAVE_OPEN_C
+#include <sys/param.h>
+#endif
+
 SOFIAPUBVAR su_log_t nta_log[];
 SOFIAPUBVAR su_log_t tport_log[];
 
@@ -87,6 +91,10 @@ int tstflags = 0;
 
 #define NONE ((void *)-1)
 
+int expensive_checks;
+
+#define EXPENSIVE_CHECKS (expensive_checks)
+
 struct sigcomp_compartment;
 
 char const name[] = "test_nta";
@@ -107,6 +115,7 @@ struct agent_t {
 
   nta_outgoing_t *ag_orq;
   int             ag_status;
+  unsigned        ag_canceled:1, ag_acked:1, :0;
 
   char const     *ag_comp;
   struct sigcomp_compartment *ag_client_compartment;
@@ -412,6 +421,30 @@ nta_test_run(agent_t *ag)
   }
 }
 
+void 
+nta_test_run_until_acked(agent_t *ag)
+{
+  ag->ag_status = 0;
+  for (ag->ag_acked = 0; !ag->ag_acked;) {
+    if (tstflags & tst_verbatim) {
+      fputs(".", stdout); fflush(stdout);
+    }
+    su_root_step(ag->ag_root, 500L);
+  }
+}
+
+void 
+nta_test_run_until_canceled(agent_t *ag)
+{
+  ag->ag_status = 0;
+  for (ag->ag_canceled = 0; !ag->ag_canceled;) {
+    if (tstflags & tst_verbatim) {
+      fputs(".", stdout); fflush(stdout);
+    }
+    su_root_step(ag->ag_root, 500L);
+  }
+}
+
 #include <sofia-sip/msg_mclass.h>
 
 int test_init(agent_t *ag, char const *resolv_conf)
@@ -420,13 +453,15 @@ int test_init(agent_t *ag, char const *resolv_conf)
   su_sockaddr_t su;
   socklen_t sulen, sulen0;
   su_socket_t s; 
-  int af;
+  int af, err = -1;
 
   BEGIN();
 
-  TEST_1(ag->ag_root = su_root_create(ag));
+  ag->ag_root = su_root_create(ag);
+  TEST_1(ag->ag_root);
 
-  TEST_1(ag->ag_mclass = msg_mclass_clone(sip_default_mclass(), 0, 0));
+  ag->ag_mclass = msg_mclass_clone(sip_default_mclass(), 0, 0);
+  TEST_1(ag->ag_mclass);
 
 #if SU_HAVE_IN6
   if (str0cmp(getenv("ipv6"), "true") == 0) {
@@ -448,7 +483,7 @@ int test_init(agent_t *ag, char const *resolv_conf)
     contact = getenv("SIPCONTACT");
 
   /* Sink server */
-  s = socket(af, SOCK_DGRAM, 0); TEST_1(s != INVALID_SOCKET);
+  s = su_socket(af, SOCK_DGRAM, 0); TEST_1(s != INVALID_SOCKET);
   memset(&su, 0, sulen = sulen0);
   su.su_family = af;
   if (getenv("sink")) {
@@ -461,7 +496,7 @@ int test_init(agent_t *ag, char const *resolv_conf)
   ag->ag_sink_socket = s;
 
   /* Down server */
-  s = socket(af, SOCK_STREAM, 0); TEST_1(s != INVALID_SOCKET);
+  s = su_socket(af, SOCK_STREAM, 0); TEST_1(s != INVALID_SOCKET);
   memset(&su, 0, sulen = sulen0);
   su.su_family = af;
   if (getenv("down")) {
@@ -471,17 +506,18 @@ int test_init(agent_t *ag, char const *resolv_conf)
   ag->ag_down_socket = s;
   
   /* Create agent */
-  TEST_1(ag->ag_agent = nta_agent_create(ag->ag_root,
-                                        (url_string_t *)contact,
-                                        NULL,
-                                        NULL,
-                                        NTATAG_MCLASS(ag->ag_mclass),
-                                        NTATAG_USE_TIMESTAMP(1),
-                                        SRESTAG_RESOLV_CONF(resolv_conf),
-                                        NTATAG_USE_NAPTR(0),
-                                        NTATAG_USE_SRV(0),
-                                        NTATAG_PRELOAD(2048),
-                                        TAG_END()));
+  ag->ag_agent = nta_agent_create(ag->ag_root,
+                        (url_string_t *)contact,
+                        NULL,
+                        NULL,
+                        NTATAG_MCLASS(ag->ag_mclass),
+                        NTATAG_USE_TIMESTAMP(1),
+                        SRESTAG_RESOLV_CONF(resolv_conf),
+                        NTATAG_USE_NAPTR(0),
+                        NTATAG_USE_SRV(0),
+                        NTATAG_PRELOAD(2048),
+                        TAG_END());
+  TEST_1(ag->ag_agent);
 
   {
     /* Initialize our headers */
@@ -545,29 +581,32 @@ int test_init(agent_t *ag, char const *resolv_conf)
     m->m_next = ag->ag_aliases;
     ag->ag_aliases = m;
 
-    TEST(nta_agent_set_params(ag->ag_agent, 
-                             NTATAG_ALIASES(ag->ag_aliases),
-                             NTATAG_REL100(1),
-                             NTATAG_UA(1), 
-                             NTATAG_USE_NAPTR(1),
-                             NTATAG_USE_SRV(1),
-                             NTATAG_MAX_FORWARDS(20),
-                             TAG_END()),
-        6);
+    err = nta_agent_set_params(ag->ag_agent, 
+                     NTATAG_ALIASES(ag->ag_aliases),
+                     NTATAG_REL100(1),
+                     NTATAG_UA(1), 
+                     NTATAG_USE_NAPTR(1),
+                     NTATAG_USE_SRV(1),
+                     NTATAG_MAX_FORWARDS(20),
+                     TAG_END());
+    TEST(err, 6);
 
-    TEST(nta_agent_set_params(ag->ag_agent, 
-                             NTATAG_ALIASES(ag->ag_aliases),
-                             NTATAG_DEFAULT_PROXY("sip:127.0.0.1"),
-                             TAG_END()), 2);
+    err = nta_agent_set_params(ag->ag_agent, 
+                     NTATAG_ALIASES(ag->ag_aliases),
+                     NTATAG_DEFAULT_PROXY("sip:127.0.0.1"),
+                     TAG_END());
+    TEST(err, 2);
 
-    TEST(nta_agent_set_params(ag->ag_agent, 
-                             NTATAG_ALIASES(ag->ag_aliases),
-                             NTATAG_DEFAULT_PROXY(NULL),
-                             TAG_END()), 2);
+    err = nta_agent_set_params(ag->ag_agent, 
+                     NTATAG_ALIASES(ag->ag_aliases),
+                     NTATAG_DEFAULT_PROXY(NULL),
+                     TAG_END());
+    TEST(err, 2);
 
-    TEST(nta_agent_set_params(ag->ag_agent, 
-                             NTATAG_DEFAULT_PROXY("tel:+35878008000"),
-                             TAG_END()), -1);
+    err = nta_agent_set_params(ag->ag_agent, 
+                     NTATAG_DEFAULT_PROXY("tel:+35878008000"),
+                     TAG_END());
+    TEST(err, -1);
 
   }
   
@@ -577,12 +616,13 @@ int test_init(agent_t *ag, char const *resolv_conf)
     /* Create the server leg */
     *url = *ag->ag_aliases->m_url;
     url->url_user = "%";
-    TEST_1(ag->ag_server_leg = nta_leg_tcreate(ag->ag_agent, 
-                                              leg_callback_200,
-                                              ag,
-                                              NTATAG_NO_DIALOG(1),
-                                              URLTAG_URL(url),
-                                              TAG_END()));
+    ag->ag_server_leg = nta_leg_tcreate(ag->ag_agent, 
+                      leg_callback_200,
+                      ag,
+                      NTATAG_NO_DIALOG(1),
+                      URLTAG_URL(url),
+                      TAG_END());
+    TEST_1(ag->ag_server_leg);
   }
 
   END();
@@ -859,7 +899,7 @@ int test_tports(agent_t *ag)
     ag->ag_expect_leg = ag->ag_default_leg;
     su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL;
 
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, 
                               outgoing_callback, ag,
                               ag->ag_obp,
@@ -870,7 +910,8 @@ int test_tports(agent_t *ag)
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
                               SIPTAG_HEADER_STR(p_acid),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
 
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
@@ -900,7 +941,7 @@ int test_tports(agent_t *ag)
     ag->ag_expect_leg = ag->ag_default_leg;
     su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL;
 
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, 
                               outgoing_callback, ag,
                               ag->ag_obp,
@@ -910,7 +951,8 @@ int test_tports(agent_t *ag)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
 
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
@@ -948,7 +990,7 @@ int test_tports(agent_t *ag)
     ag->ag_expect_leg = ag->ag_server_leg;
     su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL;
 
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
           nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                                ag->ag_obp,
                                SIP_METHOD_MESSAGE,
@@ -959,7 +1001,8 @@ int test_tports(agent_t *ag)
                                SIPTAG_TO(ag->ag_alice),
                                SIPTAG_CONTACT(ag->ag_m_bob),
                                SIPTAG_PAYLOAD(pl),
-                               TAG_END()));
+                               TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -988,18 +1031,19 @@ int test_tports(agent_t *ag)
     TEST_1(pl = test_payload(ag->ag_home, size));
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
-          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
-                              NULL,
-                              SIP_METHOD_MESSAGE,
-                              (url_string_t *)url,
-                              SIPTAG_SUBJECT_STR("Test 0.2"),
-                              SIPTAG_FROM(ag->ag_bob),
-                              SIPTAG_TO(ag->ag_alice),
-                              SIPTAG_CONTACT(ag->ag_m_bob),
-                              SIPTAG_PAYLOAD(pl),
-                              NTATAG_DEFAULT_PROXY(ag->ag_obp),
-                              TAG_END()));
+    ag->ag_orq = 
+    nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
+                      NULL,
+                      SIP_METHOD_MESSAGE,
+                      (url_string_t *)url,
+                      SIPTAG_SUBJECT_STR("Test 0.2"),
+                      SIPTAG_FROM(ag->ag_bob),
+                      SIPTAG_TO(ag->ag_alice),
+                      SIPTAG_CONTACT(ag->ag_m_bob),
+                      SIPTAG_PAYLOAD(pl),
+                      NTATAG_DEFAULT_PROXY(ag->ag_obp),
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1023,17 +1067,18 @@ int test_tports(agent_t *ag)
     TEST_1(pl = test_payload(ag->ag_home, size));
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
-          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
-                              ag->ag_obp,
-                              SIP_METHOD_MESSAGE,
-                              (url_string_t *)url,
-                              SIPTAG_SUBJECT_STR("Test 0.3"),
-                              SIPTAG_FROM(ag->ag_bob),
-                              SIPTAG_TO(ag->ag_alice),
-                              SIPTAG_CONTACT(ag->ag_m_bob),
-                              SIPTAG_PAYLOAD(pl),
-                              TAG_END()));
+    ag->ag_orq = 
+      nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
+                      ag->ag_obp,
+                      SIP_METHOD_MESSAGE,
+                      (url_string_t *)url,
+                      SIPTAG_SUBJECT_STR("Test 0.3"),
+                      SIPTAG_FROM(ag->ag_bob),
+                      SIPTAG_TO(ag->ag_alice),
+                      SIPTAG_CONTACT(ag->ag_m_bob),
+                      SIPTAG_PAYLOAD(pl),
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1058,17 +1103,18 @@ int test_tports(agent_t *ag)
     su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL;
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
-          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
-                              ag->ag_obp,
-                              SIP_METHOD_MESSAGE,
-                              (url_string_t *)url,
-                              SIPTAG_SUBJECT_STR("Test 0.4.1"),
-                              SIPTAG_FROM(ag->ag_bob),
-                              SIPTAG_TO(ag->ag_alice),
-                              SIPTAG_CONTACT(ag->ag_m_bob),
-                              SIPTAG_PAYLOAD(pl),
-                              TAG_END()));
+    ag->ag_orq = 
+      nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
+                      ag->ag_obp,
+                      SIP_METHOD_MESSAGE,
+                      (url_string_t *)url,
+                      SIPTAG_SUBJECT_STR("Test 0.4.1"),
+                      SIPTAG_FROM(ag->ag_bob),
+                      SIPTAG_TO(ag->ag_alice),
+                      SIPTAG_CONTACT(ag->ag_m_bob),
+                      SIPTAG_PAYLOAD(pl),
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1102,17 +1148,18 @@ int test_tports(agent_t *ag)
 
     su_free(ag->ag_home, ag->ag_in_via), ag->ag_in_via = NULL;
 
-    TEST_1(ag->ag_orq = 
-          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
-                              ag->ag_obp,
-                              SIP_METHOD_MESSAGE,
-                              (url_string_t *)url,
-                              SIPTAG_SUBJECT_STR("Test 0.4.2"),
-                              SIPTAG_FROM(ag->ag_bob),
-                              SIPTAG_TO(ag->ag_alice),
-                              SIPTAG_CONTACT(ag->ag_m_bob),
-                              SIPTAG_PAYLOAD(pl),
-                              TAG_END()));
+    ag->ag_orq = 
+      nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
+                      ag->ag_obp,
+                      SIP_METHOD_MESSAGE,
+                      (url_string_t *)url,
+                      SIPTAG_SUBJECT_STR("Test 0.4.2"),
+                      SIPTAG_FROM(ag->ag_bob),
+                      SIPTAG_TO(ag->ag_alice),
+                      SIPTAG_CONTACT(ag->ag_m_bob),
+                      SIPTAG_PAYLOAD(pl),
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1141,18 +1188,19 @@ int test_tports(agent_t *ag)
     su_free(ag->ag_home, (void *)ag->ag_out_via), ag->ag_out_via = NULL;
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
-          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
-                              ag->ag_obp,
-                              SIP_METHOD_MESSAGE,
-                              (url_string_t *)url,
-                              SIPTAG_SUBJECT_STR("Test 0.5"),
-                              SIPTAG_FROM(ag->ag_bob),
-                              SIPTAG_TO(ag->ag_alice),
-                              SIPTAG_CONTACT(ag->ag_m_bob),
-                              SIPTAG_PAYLOAD(pl),
-                              TPTAG_MTU(0xffffffff),
-                              TAG_END()));
+    ag->ag_orq = 
+      nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
+                      ag->ag_obp,
+                      SIP_METHOD_MESSAGE,
+                      (url_string_t *)url,
+                      SIPTAG_SUBJECT_STR("Test 0.5"),
+                      SIPTAG_FROM(ag->ag_bob),
+                      SIPTAG_TO(ag->ag_alice),
+                      SIPTAG_CONTACT(ag->ag_m_bob),
+                      SIPTAG_PAYLOAD(pl),
+                      TPTAG_MTU(0xffffffff),
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1184,7 +1232,7 @@ int test_tports(agent_t *ag)
                         TAG_END());
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, 
                               magic_callback, ag,
                               ag->ag_obp,
@@ -1195,7 +1243,8 @@ int test_tports(agent_t *ag)
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
                               SIPTAG_VIA(via),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1226,7 +1275,7 @@ int test_tports(agent_t *ag)
     TEST_1(pl = test_payload(ag->ag_home, size));
 
     ag->ag_expect_leg = ag->ag_server_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
           nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1236,8 +1285,9 @@ int test_tports(agent_t *ag)
                               SIPTAG_TO(ag->ag_alice),
                               SIPTAG_CONTACT(ag->ag_m_bob),
                               SIPTAG_PAYLOAD(pl),
-                              TAG_END()));
-    su_free(ag->ag_home, pl);
+                              TAG_END());
+   TEST_1(ag->ag_orq);
+   su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
@@ -1262,7 +1312,7 @@ int test_tports(agent_t *ag)
 
     ag->ag_expect_leg = ag->ag_server_leg;
     ag->ag_latest_leg = NULL;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
           nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1272,7 +1322,8 @@ int test_tports(agent_t *ag)
                               SIPTAG_TO(ag->ag_alice),
                               SIPTAG_CONTACT(ag->ag_m_bob),
                               SIPTAG_PAYLOAD(pl),
-                              TAG_END()));
+                      TAG_END());
+    TEST_1(ag->ag_orq);
     su_free(ag->ag_home, pl);
 
     nta_test_run(ag);
@@ -1306,7 +1357,7 @@ int test_tports(agent_t *ag)
 
     ag->ag_expect_leg = ag->ag_server_leg;
     ag->ag_latest_leg = NULL;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
           nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1315,8 +1366,9 @@ int test_tports(agent_t *ag)
                               SIPTAG_FROM(ag->ag_bob),
                               SIPTAG_TO(ag->ag_alice),
                               SIPTAG_CONTACT(ag->ag_m_bob),
-                              TAG_END()));
+                              TAG_END());
 
+    TEST_1(ag->ag_orq);
     nta_test_run(ag);
     TEST(ag->ag_status, 408);
     TEST_P(ag->ag_orq, NULL);
@@ -1388,7 +1440,7 @@ int test_destroy_incoming(agent_t *ag)
   ag->ag_expect_leg = ag->ag_default_leg;
   nta_leg_bind(ag->ag_default_leg, leg_callback_destroy, ag);
 
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_default_leg, 
                              outgoing_callback, ag,
                              ag->ag_obp,
@@ -1397,8 +1449,9 @@ int test_destroy_incoming(agent_t *ag)
                              SIPTAG_SUBJECT_STR("Test 3.1"),
                              SIPTAG_FROM(ag->ag_alice),
                              SIPTAG_TO(ag->ag_bob),
-                             TAG_END()));
-
+                             TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST(ag->ag_status, 500);
   TEST_P(ag->ag_orq, NULL);
@@ -1409,7 +1462,7 @@ int test_destroy_incoming(agent_t *ag)
    */
   nta_leg_bind(ag->ag_default_leg, leg_callback_save, ag);
 
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_default_leg, 
                              outgoing_callback, ag,
                              ag->ag_obp,
@@ -1418,7 +1471,8 @@ int test_destroy_incoming(agent_t *ag)
                              SIPTAG_SUBJECT_STR("Test 3.1"),
                              SIPTAG_FROM(ag->ag_alice),
                              SIPTAG_TO(ag->ag_bob),
-                             TAG_END()));
+                             TAG_END());
+  TEST_1(ag->ag_orq);
 
   nta_test_run(ag);
   TEST(ag->ag_status, 1000);
@@ -1473,7 +1527,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      * Send a message to sip:example.org
      */
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1482,7 +1536,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+    
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1495,7 +1551,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "srv.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1504,7 +1560,8 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1517,7 +1574,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "ipv.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1526,7 +1583,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1539,7 +1598,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "down.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1548,8 +1607,10 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
-    nta_test_run(ag);
+                              TAG_END());
+   TEST_1(ag->ag_orq);
+
+   nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
     TEST_P(ag->ag_latest_leg, ag->ag_default_leg);
@@ -1562,7 +1623,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "na503.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1571,7 +1632,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 503);
     TEST_P(ag->ag_orq, NULL);
@@ -1584,7 +1647,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "nona.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1593,7 +1656,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1608,7 +1673,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
      */
     url->url_host = "nosrv.example.org";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1617,7 +1682,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1632,7 +1699,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "srv.example.org";
     url->url_params = "transport=tcp";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1641,7 +1708,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1657,7 +1726,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "srv.example.org";
     url->url_params = "transport=udp";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1666,7 +1735,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1682,7 +1753,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "srv2.example.org";
     url->url_params = "transport=udp";
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1691,7 +1762,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1707,7 +1780,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "srv.example.org";
     url->url_port = ag->ag_contact->m_url->url_port;
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1716,7 +1789,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 503);
     TEST_P(ag->ag_orq, NULL);
@@ -1731,7 +1806,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "a.example.org";
     url->url_port = ag->ag_contact->m_url->url_port;
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1740,7 +1815,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -1781,7 +1858,7 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
     url->url_host = "down2.example.org";
     url->url_port = ag->ag_contact->m_url->url_port;
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_MESSAGE,
@@ -1790,7 +1867,9 @@ int test_resolv(agent_t *ag, char const *resolv_conf)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -2192,7 +2271,7 @@ int test_routing(agent_t *ag)
     url2->url_port = "9";      /* discard service */
 
     ag->ag_expect_leg = ag->ag_default_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               (url_string_t *)url,
                               SIP_METHOD_MESSAGE,
@@ -2201,7 +2280,9 @@ int test_routing(agent_t *ag)
                               SIPTAG_FROM(ag->ag_alice),
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -2223,19 +2304,20 @@ int test_dialog(agent_t *ag)
    * Alice sends a message to Bob, then Bob back to the Alice, and again
    * Alice to Bob.
    */
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                           leg_callback_200,
                                           ag,
                                           SIPTAG_FROM(ag->ag_alice),
                                           SIPTAG_TO(ag->ag_bob),
-                                          TAG_END()));
+                                          TAG_END());
+  TEST_1(ag->ag_alice_leg);
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
   nta_leg_bind(ag->ag_server_leg, new_leg_callback_200, ag);
 
   /* Send message from Alice to Bob establishing the dialog */
   ag->ag_expect_leg = ag->ag_server_leg;
   ag->ag_tag_remote = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ag,
                             ag->ag_obp,
                             SIP_METHOD_MESSAGE,
@@ -2244,7 +2326,9 @@ int test_dialog(agent_t *ag)
                             SIPTAG_FROM(ag->ag_alice),
                             SIPTAG_TO(ag->ag_bob),
                             SIPTAG_CONTACT(ag->ag_m_alice),
-                            TAG_END()));
+                            TAG_END());
+  TEST_1(ag->ag_orq);
+
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -2255,13 +2339,15 @@ int test_dialog(agent_t *ag)
 
   /* Send message from Bob to Alice */
   ag->ag_expect_leg = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag,
                       NULL,
                       SIP_METHOD_MESSAGE,
                       (url_string_t *)ag->ag_m_alice->m_url,
                       SIPTAG_SUBJECT_STR("Test 2.2"),
-                      TAG_END()));
+                      TAG_END());
+  TEST_1(ag->ag_orq);
+
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -2269,13 +2355,15 @@ int test_dialog(agent_t *ag)
 
   /* Send again message from Alice to Bob */
   ag->ag_expect_leg = ag->ag_bob_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_alice_leg, outgoing_callback, ag,
                       NULL,
                       SIP_METHOD_MESSAGE,
                       (url_string_t *)ag->ag_m_bob->m_url,
                       SIPTAG_SUBJECT_STR("Test 2.3"),
-                      TAG_END()));
+                      TAG_END());
+  TEST_1(ag->ag_orq);
+
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -2286,13 +2374,15 @@ int test_dialog(agent_t *ag)
    */
   {
     ag->ag_expect_leg = ag->ag_alice_leg;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
           nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag,
                         NULL,
                         SIP_METHOD_MESSAGE,
                         (url_string_t *)ag->ag_m_alice->m_url,
                         SIPTAG_SUBJECT_STR("Test 2.4"),
-                        TAG_END()));
+                        TAG_END());
+    TEST_1(ag->ag_orq);
+
     nta_test_run(ag);
     TEST(ag->ag_status, 200);
     TEST_P(ag->ag_orq, NULL);
@@ -2578,18 +2668,20 @@ int test_call(agent_t *ag)
    *
    * Alice sends a INVITE to Bob, then Bob sends 200 Ok.
    */
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                           alice_leg_callback,
                                           ag,
                                           SIPTAG_FROM(ag->ag_alice),
                                           SIPTAG_TO(ag->ag_bob),
-                                          TAG_END()));
+                                          TAG_END());
+  TEST_1(ag->ag_alice_leg);
+  
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
   nta_leg_bind(ag->ag_server_leg, bob_leg_callback, ag);
   
   /* Send INVITE */
   ag->ag_expect_leg = ag->ag_server_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
                              outgoing_invite_callback, ag,
                              ag->ag_obp,
@@ -2602,8 +2694,9 @@ int test_call(agent_t *ag)
                              SIPTAG_PAYLOAD(sdp),
                              NTATAG_USE_TIMESTAMP(1),
                              NTATAG_PASS_100(1),
-                             TAG_END()));
-
+                             TAG_END());
+  TEST_1(ag->ag_orq);
+  
   /* Try to CANCEL it immediately */
   TEST_1(nta_outgoing_cancel(ag->ag_orq) == 0);
   /* As Bob immediately answers INVITE with 200 Ok, 
@@ -2628,7 +2721,7 @@ int test_call(agent_t *ag)
    * waits for PRACKs, then sends 200, waits for ACK.
    */
   ag->ag_expect_leg = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
        nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_bob_leg, 
                             outgoing_invite_callback, ag,
                             NULL,
@@ -2639,7 +2732,8 @@ int test_call(agent_t *ag)
                             SIPTAG_SUPPORTED_STR("foo"),
                             SIPTAG_CONTENT_TYPE(c),
                             SIPTAG_PAYLOAD(sdp),
-                            TAG_END()));
+                            TAG_END());
+  TEST_1(ag->ag_orq);
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -2651,7 +2745,7 @@ int test_call(agent_t *ag)
 
   /* Send BYE from Bob to Alice */
   old_leg = ag->ag_expect_leg = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
        nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag,
                             NULL,
                             SIP_METHOD_BYE,
@@ -2662,8 +2756,9 @@ int test_call(agent_t *ag)
                             SIPTAG_CONTACT(ag->ag_m_alice),
                             SIPTAG_CONTENT_TYPE(c),
                             SIPTAG_PAYLOAD(sdp),
-                            TAG_END()));
-
+                            TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -2690,11 +2785,11 @@ int test_for_ack_or_timeout(agent_t *ag,
 
   if (method == sip_method_ack) {
     TEST(method, sip_method_ack);
-  
-    ag->ag_status = 200;
+    ag->ag_acked = 1;
   }
   else if (method == sip_method_cancel) {
     nta_incoming_treply(irq, SIP_487_REQUEST_CANCELLED, TAG_END());
+    ag->ag_canceled = 1;
   }
   else {
     if (ag->ag_bob_leg) {
@@ -2818,6 +2913,9 @@ int invite_prack_callback(agent_t *ag,
     orq = tagged;
   }
 
+  if (status > ag->ag_status)
+    ag->ag_status = status;
+
   if (status > 100 && status < 200 && sip->sip_rseq) {
     nta_outgoing_t *prack;
     prack = nta_outgoing_prack(ag->ag_call_leg, orq, NULL, NULL,
@@ -2857,9 +2955,6 @@ int invite_prack_callback(agent_t *ag,
     nta_outgoing_destroy(ack);
     msg_destroy(msg);
   }
-  else {
-    ag->ag_status = status;
-  }
 
   TEST_1(sip->sip_to && sip->sip_to->a_tag);
 
@@ -2876,16 +2971,22 @@ static int process_prack(nta_reliable_magic_t *arg,
                         sip_t const *sip)
 {
   agent_t *ag = (agent_t *)arg;
-  if (ag->ag_irq) {
+
+  if (irq) {
+    return 200;
+  }
+  else if (ag->ag_irq) {
     nta_incoming_treply(ag->ag_irq, 
                        504, "Reliable Response Timeout",
                        TAG_END());
     nta_incoming_destroy(ag->ag_irq);
+    return 487;
   }
-  return 504;
+
+  return 487;
 }
 
-/* send invite, wait for 183, send CANCEL */
+/* respond with 183 when receiving invite */
 int bob_leg_callback3(agent_t *ag,
                      nta_leg_t *leg,
                      nta_incoming_t *irq,
@@ -2931,7 +3032,8 @@ int bob_leg_callback3(agent_t *ag,
 
   if (sip->sip_request->rq_method != sip_method_invite) {
     return 200;
-  } else {
+  }
+  else {
     nta_reliable_t *rel;
     nta_incoming_bind(irq, test_for_ack_or_timeout, ag);
     rel = nta_reliable_treply(irq, process_prack, ag,
@@ -3033,7 +3135,7 @@ int test_prack(agent_t *ag)
 
     ag->ag_expect_leg = ag->ag_server_leg;
     ag->ag_latest_leg = NULL;
-    TEST_1(ag->ag_orq = 
+    ag->ag_orq = 
          nta_outgoing_tcreate(ag->ag_default_leg, outgoing_callback, ag,
                               ag->ag_obp,
                               SIP_METHOD_PRACK,
@@ -3043,25 +3145,29 @@ int test_prack(agent_t *ag)
                               SIPTAG_TO(ag->ag_bob),
                               SIPTAG_CONTACT(ag->ag_m_alice),
                               SIPTAG_RACK_STR("1432432 42332432 INVITE"),
-                              TAG_END()));
+                              TAG_END());
+    TEST_1(ag->ag_orq);
+    
     nta_test_run(ag);
     TEST(ag->ag_status, 481);
     TEST_P(ag->ag_orq, NULL);
     TEST_P(ag->ag_latest_leg, NULL);
   }
 
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                           alice_leg_callback,
                                           ag,
                                           SIPTAG_FROM(ag->ag_alice),
                                           SIPTAG_TO(ag->ag_bob),
-                                          TAG_END()));
+                                          TAG_END());
+  TEST_1(ag->ag_alice_leg);
+  
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
 
   /* Send INVITE */
   nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag);
   ag->ag_expect_leg = ag->ag_server_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
                              invite_prack_callback, ag,
                              ag->ag_obp,
@@ -3072,8 +3178,10 @@ int test_prack(agent_t *ag)
                              SIPTAG_REQUIRE_STR("100rel"),
                              SIPTAG_CONTENT_TYPE(c),
                              SIPTAG_PAYLOAD(sdp),
-                             TAG_END()));
-  nta_test_run(ag);
+                             TAG_END());
+  TEST_1(ag->ag_orq);
+  
+  nta_test_run_until_acked(ag);
   TEST(ag->ag_status, 200);
   /*TEST(ag->ag_tag_status, 183);*/
   TEST_P(ag->ag_orq, NULL);
@@ -3082,7 +3190,7 @@ int test_prack(agent_t *ag)
 
   /* Send BYE from Bob to Alice */
   old_leg = ag->ag_expect_leg = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
        nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag,
                             NULL,
                             SIP_METHOD_BYE,
@@ -3093,8 +3201,9 @@ int test_prack(agent_t *ag)
                             SIPTAG_CONTACT(ag->ag_m_alice),
                             SIPTAG_CONTENT_TYPE(c),
                             SIPTAG_PAYLOAD(sdp),
-                            TAG_END()));
-
+                            TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   TEST_P(ag->ag_orq, NULL);
@@ -3104,20 +3213,24 @@ int test_prack(agent_t *ag)
   nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL;
   ag->ag_latest_leg = NULL;
   ag->ag_call_leg = NULL;
+  if (ag->ag_call_tag)
+    su_free(ag->ag_home, (void *)ag->ag_call_tag), ag->ag_call_tag = NULL;
 
   /* Test CANCELing a call after received PRACK */
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                           alice_leg_callback,
                                           ag,
                                           SIPTAG_FROM(ag->ag_alice),
                                           SIPTAG_TO(ag->ag_bob),
-                                          TAG_END()));
+                                          TAG_END());
+  TEST_1(ag->ag_alice_leg);
+  
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
 
   /* Send INVITE */
   nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag);
   ag->ag_expect_leg = ag->ag_server_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
                              invite_183_cancel_callback, ag,
                              ag->ag_obp,
@@ -3128,7 +3241,9 @@ int test_prack(agent_t *ag)
                              SIPTAG_REQUIRE_STR("100rel"),
                              SIPTAG_CONTENT_TYPE(c),
                              SIPTAG_PAYLOAD(sdp),
-                             TAG_END()));
+                             TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST_1(ag->ag_status == 487 || ag->ag_status == 504);
   TEST_P(ag->ag_orq, NULL);
@@ -3139,7 +3254,7 @@ int test_prack(agent_t *ag)
   ag->ag_latest_leg = NULL;
   ag->ag_call_leg = NULL;
 
-  if (getenv("EXPENSIVE_CHECKS")) {
+  if (EXPENSIVE_CHECKS) {
   printf("%s: starting 100rel timeout test, test will complete in 4 seconds\n",
         name);
   
@@ -3148,12 +3263,14 @@ int test_prack(agent_t *ag)
                            NTATAG_SIP_T1X64(64 * 25),
                            TAG_END()), 2);
 
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                           alice_leg_callback,
                                           ag,
                                           SIPTAG_FROM(ag->ag_alice),
                                           SIPTAG_TO(ag->ag_bob),
-                                          TAG_END()));
+                                          TAG_END());
+  TEST_1(ag->ag_alice_leg);
+  
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
 
   /* Send INVITE, 
@@ -3163,7 +3280,7 @@ int test_prack(agent_t *ag)
    */
   nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag);
   ag->ag_expect_leg = ag->ag_server_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
         nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
                              outgoing_callback, ag,
                              ag->ag_obp,
@@ -3174,7 +3291,9 @@ int test_prack(agent_t *ag)
                              SIPTAG_REQUIRE_STR("100rel"),
                              SIPTAG_CONTENT_TYPE(c),
                              SIPTAG_PAYLOAD(sdp),
-                             TAG_END()));
+                             TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST(ag->ag_status, 503);
   TEST_P(ag->ag_orq, NULL);
@@ -3186,14 +3305,60 @@ int test_prack(agent_t *ag)
                            NTATAG_SIP_T1X64(64 * 500), 
                            TAG_END()), 2);
   }
-  END();
-/*
+
+  if (EXPENSIVE_CHECKS || 1) {
+  printf("%s: starting timer C, test will complete in 1 seconds\n",
+        name);
+  
+  TEST(nta_agent_set_params(ag->ag_agent,
+                           NTATAG_TIMER_C(1000),
+                           TAG_END()), 1);
+
+  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+                                           alice_leg_callback,
+                                           ag,
+                                           SIPTAG_FROM(ag->ag_alice),
+                                           SIPTAG_TO(ag->ag_bob),
+                                           TAG_END()));
+  TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
+
+  /* Send INVITE, 
+   * send precious provisional response
+   * timeout after timer C
+   */
+  nta_leg_bind(ag->ag_server_leg, bob_leg_callback3, ag);
+  ag->ag_expect_leg = ag->ag_server_leg;
+  TEST_1(ag->ag_orq = 
+        nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
+                             invite_prack_callback, ag,
+                             ag->ag_obp,
+                             SIP_METHOD_INVITE,
+                             (url_string_t *)ag->ag_m_bob->m_url,
+                             SIPTAG_SUBJECT_STR("Call 4"),
+                             SIPTAG_CONTACT(ag->ag_m_alice),
+                             SIPTAG_REQUIRE_STR("100rel"),
+                             SIPTAG_CONTENT_TYPE(c),
+                             SIPTAG_PAYLOAD(sdp),
+                             TAG_END()));
+  nta_test_run_until_canceled(ag);
+  TEST(ag->ag_status, 408);
+  TEST_1(ag->ag_canceled != 0); 
+  TEST_P(ag->ag_orq, NULL);
+  TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+  TEST_1(ag->ag_bob_leg);
+  nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL;
+
+  TEST(nta_agent_set_params(ag->ag_agent, 
+                           NTATAG_TIMER_C(185 * 1000), 
+                           TAG_END()), 1);
+
   nta_leg_destroy(ag->ag_bob_leg), ag->ag_bob_leg = NULL;
   ag->ag_latest_leg = NULL;
   ag->ag_call_leg = NULL;
   if (ag->ag_call_tag)
     su_free(ag->ag_home, (void *)ag->ag_call_tag), ag->ag_call_tag = NULL;
-*/
+  }
+  END();
 }
 
 int alice_leg_callback2(agent_t *ag,
@@ -3285,12 +3450,14 @@ int test_fix_467(agent_t *ag)
 
   BEGIN();
 
-  TEST_1(ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
+  ag->ag_alice_leg = nta_leg_tcreate(ag->ag_agent, 
                                            alice_leg_callback2,
                                            ag,
                                            SIPTAG_FROM(ag->ag_alice),
                                            SIPTAG_TO(ag->ag_bob),
-                                           TAG_END()));
+                                           TAG_END());
+  TEST_1(ag->ag_alice_leg);
+  
   TEST_1(nta_leg_tag(ag->ag_alice_leg, NULL));
   ag->ag_bob_leg = NULL;
   ag->ag_call_tag = NULL;
@@ -3298,7 +3465,7 @@ int test_fix_467(agent_t *ag)
   /* Send INVITE */
   nta_leg_bind(ag->ag_server_leg, bob_leg_callback2, ag);
   ag->ag_expect_leg = ag->ag_server_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
        nta_outgoing_tcreate(ag->ag_call_leg = ag->ag_alice_leg, 
                             invite_prack_callback, ag,
                             ag->ag_obp,
@@ -3309,7 +3476,9 @@ int test_fix_467(agent_t *ag)
                             SIPTAG_REQUIRE_STR("100rel"),
                             SIPTAG_CONTENT_TYPE(c),
                             SIPTAG_PAYLOAD(sdp),
-                            TAG_END()));
+                            TAG_END());
+  TEST_1(ag->ag_orq);
+  
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
   /*TEST(ag->ag_tag_status, 183);*/
@@ -3319,7 +3488,7 @@ int test_fix_467(agent_t *ag)
 
   /* Send BYE from Bob to Alice */
   old_leg = ag->ag_expect_leg = ag->ag_alice_leg;
-  TEST_1(ag->ag_orq = 
+  ag->ag_orq = 
        nta_outgoing_tcreate(ag->ag_bob_leg, outgoing_callback, ag,
                             NULL,
                             SIP_METHOD_BYE,
@@ -3330,8 +3499,8 @@ int test_fix_467(agent_t *ag)
                             SIPTAG_CONTACT(ag->ag_m_alice),
                             SIPTAG_CONTENT_TYPE(c),
                             SIPTAG_PAYLOAD(sdp),
-                            TAG_END()));
-
+                            TAG_END());
+  TEST_1(ag->ag_orq);
   
   nta_test_run(ag);
   TEST(ag->ag_status, 200);
@@ -3365,6 +3534,7 @@ char const nta_test_usage[] =
   "   -v | --verbose    be verbose\n"
   "   -a | --abort      abort() on error\n"
   "   -q | --quiet      be quiet\n"
+  "   --expensive       run expensive tests, too\n"
   "   -1                quit on first error\n"
   "   -l level          set logging level (0 by default)\n"
   "   -p uri            specify uri of outbound proxy\n"
@@ -3388,6 +3558,8 @@ int main(int argc, char *argv[])
 
   agent_t ag[1] = {{ { SU_HOME_INIT(ag) }, 0, NULL }};
 
+  expensive_checks = getenv("EXPENSIVE_CHECKS") != NULL;
+
   for (i = 1; argv[i]; i++) {
     if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0)
       tstflags |= tst_verbatim;
@@ -3395,6 +3567,8 @@ int main(int argc, char *argv[])
       tstflags |= tst_abort;
     else if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0)
       tstflags &= ~tst_verbatim;
+    else if (strcmp(argv[i], "--expensive") == 0)
+      expensive_checks = 1;
     else if (strcmp(argv[i], "-1") == 0)
       quit_on_single_failure = 1;
     else if (strncmp(argv[i], "-l", 2) == 0) {
@@ -3459,6 +3633,16 @@ int main(int argc, char *argv[])
   }
 #endif
 
+#if HAVE_OPEN_C
+  tstflags |= tst_verbatim;
+  su_log_soft_set_level(su_log_default, 9);
+  su_log_soft_set_level(nta_log, 9);
+  su_log_soft_set_level(tport_log, 9);
+  setenv("SU_DEBUG", "9", 1);
+  setenv("NUA_DEBUG", "9", 1);
+  setenv("NTA_DEBUG", "9", 1);
+  setenv("TPORT_DEBUG", "9", 1);
+#endif
   su_init();
 
   if (!(TSTFLAGS & tst_verbatim)) {
@@ -3466,11 +3650,18 @@ int main(int argc, char *argv[])
     su_log_soft_set_level(tport_log, 0);
   }
 
+#if HAVE_OPEN_C
 #define SINGLE_FAILURE_CHECK()                                         \
-  do { fflush(stdout);                                                 \
-    if (retval && quit_on_single_failure) { su_deinit(); return retval; } \
-  } while(0)
-
+         do { fflush(stdout);                                                  \
+           if (retval && quit_on_single_failure) { su_deinit(); sleep(7); return retval; } \
+         } while(0)
+#else
+  #define SINGLE_FAILURE_CHECK()                                               \
+         do { fflush(stdout);                                                  \
+           if (retval && quit_on_single_failure) { su_deinit(); return retval; } \
+         } while(0)
+#endif
+  
   retval |= test_init(ag, argv[i]); SINGLE_FAILURE_CHECK();
   if (retval == 0) {
     retval |= test_bad_messages(ag); SINGLE_FAILURE_CHECK();
@@ -3490,5 +3681,9 @@ int main(int argc, char *argv[])
 
   su_deinit();
 
+#if HAVE_OPEN_C
+  sleep(7);
+#endif  
+  
   return retval;
 }
index 46d6c4c4d1ba9925a537a42795432307ba744d91..30c71244a72d566bc9558d910fd9c313c5767ae9 100644 (file)
@@ -453,84 +453,129 @@ int api_test_params(agent_t *ag)
 
   sip_contact_t const *aliases = (void *)-1;
   msg_mclass_t *mclass = (void *)-1;
+  sip_contact_t *contact = (void *)-1;
+  url_string_t const *default_proxy = (void *)-1;
+  void *smime = (void *)-1;
+
+  unsigned blacklist = -1;
+  unsigned debug_drop_prob = -1;
+  unsigned max_forwards = -1;
+  unsigned maxsize = -1;
+  unsigned preload = -1;
+  unsigned progress = -1;
   unsigned sip_t1 = -1;
   unsigned sip_t2 = -1;
-  unsigned sip_t4    = -1;
-  unsigned debug_drop_prob = -1;
-  int ua              = -1;
-  int user_via        = -1;
+  unsigned sip_t4 = -1;
+  unsigned timer_c = -1;
+  unsigned udp_mtu = -1;
+
+  int cancel_2543     = -1;
+  int cancel_487      = -1;
+  int client_rport    = -1;
   int extra_100       = -1;
+  int merge_482       = -1;
   int pass_100        = -1;
-  int timeout_408     = -1;
   int pass_408        = -1;
-  int merge_482       = -1;
-  int cancel_2543     = -1;
-  int cancel_487      = -1;
   int rel100          = -1;
-  int use_timestamp   = -1;
+  int server_rport    = -1;
+  int stateless       = -1;
+  int tag_3261        = -1;
+  int timeout_408     = -1;
+  int ua              = -1;
   int use_naptr       = -1;
   int use_srv         = -1;
-  unsigned preload = (unsigned)-1;
+  int use_timestamp   = -1;
+  int user_via        = -1;
+
   char const *s = NONE;
 
   TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*",
                                NULL, NULL, TAG_END()));
   TEST(nta_agent_get_params(nta,
-                           NTATAG_MCLASS_REF(mclass),
                            NTATAG_ALIASES_REF(aliases),
-                           NTATAG_SIP_T1_REF(sip_t1),
-                           NTATAG_SIP_T2_REF(sip_t2),
-                           NTATAG_SIP_T4_REF(sip_t4),
+                           NTATAG_BLACKLIST_REF(blacklist),
+                           NTATAG_CANCEL_2543_REF(cancel_2543),
+                           NTATAG_CANCEL_487_REF(cancel_487),
+                           NTATAG_CLIENT_RPORT_REF(client_rport),
+                           NTATAG_CONTACT_REF(contact),
                            NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob),
-                           NTATAG_UA_REF(ua),
-                           NTATAG_USER_VIA_REF(user_via),
+                           NTATAG_DEFAULT_PROXY_REF(default_proxy),
                            NTATAG_EXTRA_100_REF(extra_100),
+                           NTATAG_MAXSIZE_REF(maxsize),
+                           NTATAG_MAX_FORWARDS_REF(max_forwards),
+                           NTATAG_MCLASS_REF(mclass),
+                           NTATAG_MERGE_482_REF(merge_482),
                            NTATAG_PASS_100_REF(pass_100),
-                           NTATAG_TIMEOUT_408_REF(timeout_408),
                            NTATAG_PASS_408_REF(pass_408),
-                           NTATAG_MERGE_482_REF(merge_482),
-                           NTATAG_CANCEL_2543_REF(cancel_2543),
-                           NTATAG_CANCEL_487_REF(cancel_487),
+                           NTATAG_PRELOAD_REF(preload),
+                           NTATAG_PROGRESS_REF(progress),
                            NTATAG_REL100_REF(rel100),
-                           NTATAG_USE_TIMESTAMP_REF(use_timestamp),
+                           NTATAG_SERVER_RPORT_REF(server_rport),
+                           NTATAG_SIP_T1_REF(sip_t1),
+                           NTATAG_SIP_T2_REF(sip_t2),
+                           NTATAG_SIP_T4_REF(sip_t4),
+                           NTATAG_SMIME_REF(smime),
+                           NTATAG_STATELESS_REF(stateless),
+                           NTATAG_TAG_3261_REF(tag_3261),
+                           NTATAG_TIMEOUT_408_REF(timeout_408),
+                           NTATAG_TIMER_C_REF(timer_c),
+                           NTATAG_UA_REF(ua),
+                           NTATAG_UDP_MTU_REF(udp_mtu),
+                           NTATAG_USER_VIA_REF(user_via),
                            NTATAG_USE_NAPTR_REF(use_naptr),
                            NTATAG_USE_SRV_REF(use_srv),
+                           NTATAG_USE_TIMESTAMP_REF(use_timestamp),
                            TAG_END()), 
-       /* Number of parameters */ 19);
+       /* Number of parameters */ 33);
   
   TEST_P(mclass, sip_default_mclass());
   TEST_P(aliases, NULL);
+  TEST_1(contact != (void *)-1 && contact != NULL);
+  TEST_1(default_proxy == NULL);
+  TEST_1(smime == NULL);
+
+  TEST_1(blacklist != -1);
+  TEST(debug_drop_prob, 0);
+  TEST_1(max_forwards >= 20);
+  TEST_1(maxsize >= 65536);
+  TEST_1(preload != -1);
+  TEST_1(progress <= 60 * 1000);
   TEST(sip_t1, NTA_SIP_T1);
   TEST(sip_t2, NTA_SIP_T2);
   TEST(sip_t4, NTA_SIP_T4);
-  TEST(debug_drop_prob, 0);
-  TEST(ua,              0);
-  TEST(user_via,        0);
-  TEST(extra_100,       0);
-  TEST(pass_100,        0);
-  TEST(timeout_408,     1);
-  TEST(pass_408,        0);
-  TEST(merge_482,       0);
-  TEST(cancel_2543,     0);
-  TEST(cancel_487,      1);
-  TEST(rel100,          0);
-  TEST(use_timestamp,   0);
-  TEST(use_naptr,       1);
-  TEST(use_srv,         1);
+  TEST_1(timer_c > 180 * 1000);
+  TEST(udp_mtu, 1300);
+
+  TEST_1(cancel_2543 != -1);
+  TEST_1(cancel_487 != -1);
+  TEST_1(client_rport != -1);
+  TEST_1(extra_100 != -1);
+  TEST_1(merge_482 != -1);
+  TEST_1(pass_100 != -1);
+  TEST_1(pass_408 != -1);
+  TEST_1(rel100 != -1);
+  TEST_1(server_rport != -1);
+  TEST_1(stateless == 0);
+  TEST_1(timeout_408 != -1);
+  TEST_1(ua == 0);
+  TEST_1(use_naptr != -1);
+  TEST_1(use_srv != -1);
+  TEST_1(use_timestamp != -1);
+  TEST_1(user_via == 0);
 
   TEST(nta_agent_set_params(NULL, 
-                     NTATAG_PRELOAD(2048),
-                     TAG_END()), -1);
+                           NTATAG_PRELOAD(2048),
+                           TAG_END()), -1);
   TEST(nta_agent_get_params(NULL, 
-                     NTATAG_PRELOAD_REF(preload),
-                     TAG_END()), -1);
+                           NTATAG_PRELOAD_REF(preload),
+                           TAG_END()), -1);
 
   TEST(nta_agent_set_params(nta, 
-                     NTATAG_PRELOAD(2048),
-                     TAG_END()), 1);
+                           NTATAG_PRELOAD(2048),
+                           TAG_END()), 1);
   TEST(nta_agent_get_params(nta, 
-                     NTATAG_PRELOAD_REF(preload),
-                     TAG_END()), 1);
+                           NTATAG_PRELOAD_REF(preload),
+                           TAG_END()), 1);
   TEST(preload, 2048);
 
   TEST(nta_agent_set_params(nta, 
index 057ec723841f785377245b38be82da386e71c721..6777ed157871c8101973c03c2112881c49445770 100644 (file)
@@ -6,8 +6,8 @@
  *
  * NTH provides interface to simple HTTP transaction engines for both HTTP
  * servers and clients. The transaction interface for both client and server
- * is available through <nth.h>, tags controlling the options in
- * <nth_tag.h>.
+ * is available through <sofia-sip/nth.h>, tags controlling the options in
+ * <sofia-sip/nth_tag.h>.
  *
  * @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
  *
index 94e35d57b5e65ba4cc9b8318872b7bde235a4f3a..d94167ba6847dfbfecf7dff6f51d2fea3f4a9dd6 100644 (file)
@@ -174,7 +174,7 @@ struct nth_client_s {
  * The NTH_DEBUG environment variable is used to determine the debug
  * logging level for @b nth module. The default level is 1.
  *
- * @sa <su_debug.h>, nth_client_log, #SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, nth_client_log, #SOFIA_DEBUG
  */
 extern char const NTH_DEBUG[];
 
index e89505073a519ab4578ea16c341eae5ec937fb6a..4299d1ba04f6819c9cc2f2a6cedbbce6629c1f7c 100644 (file)
@@ -172,7 +172,7 @@ struct nth_request_s
  * The NTH_DEBUG environment variable is used to determine the debug
  * logging level for @b nth module. The default level is 1.
  * 
- * @sa <su_debug.h>, nth_server_log, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, nth_server_log, SOFIA_DEBUG
  */
 extern char const NTH_DEBUG[];
 
index b3f304f6b831be4ba196514b89692d883e807d3e..09cbd8b7125611e0f94bb75d207212662782acae 100644 (file)
@@ -101,11 +101,11 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
  *     NUTAG_URL()              \n
  *     NUTAG_SIPS_URL()         \n
  *     NUTAG_SIP_PARSER()       \n
- *     NUTAG_UICC()             \n
  *     NUTAG_CERTIFICATE_DIR()  \n
- *     and all tags listed in nua_set_params(), \n
- *     and all relevant NTATAG_* are passed to NTA \n
- *     and all tport tags listed in <sofia-sip/tport_tag.h>
+ *     all tags listed in nua_set_params(), \n
+ *     all NTATAG_* are passed to NTA listed in <sofia-sip/nta_tag.h> \n
+ *     all tport tags listed in <sofia-sip/tport_tag.h> \n
+ *     STUNTAG_DOMAIN(), STUNTAG_SERVER() \n
  *
  * @note
  * From the @VERSION_1_12_2 all the nua_set_params() tags are processed.
@@ -119,7 +119,7 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
  * @par Events:
  *     none
  *
- * @sa nua_shutdown(), nua_destroy(), nua_handle()
+ * @sa nua_shutdown(), nua_destroy(), nua_handle(), nta_agent_create().
  */
 nua_t *nua_create(su_root_t *root,
                  nua_callback_f callback,
@@ -1040,19 +1040,30 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e)
   su_msg_destroy(nua->nua_current);
 }
 
-/** Get current request message. @NEW_1_12_4. */
+/** Get current request message. @NEW_1_12_4.
+ *
+ * @note A response message is returned when processing response message.
+ *
+ * @sa #nua_event_e, nua_respond(), NUTAG_WITH_CURRENT()
+ */
 msg_t *nua_current_request(nua_t const *nua)
 {
   return nua && nua->nua_current ? su_msg_data(nua->nua_current)->e_msg : NULL;
 }
 
-/** Get request message from saved nua event. @NEW_1_12_4. */
+/** Get request message from saved nua event. @NEW_1_12_4. 
+ *
+ * @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(), 
+ */
 msg_t *nua_saved_event_request(nua_saved_event_t const *saved)
 {
   return saved && saved[0] ? su_msg_data(saved)->e_msg : NULL;
 }
 
-/** Save nua event and its arguments */
+/** Save nua event and its arguments.
+ *
+ * @sa #nua_event_e, nua_event_data() nua_saved_event_request(), nua_destroy_event()
+ */
 int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
 {
   if (nua && return_saved) {
@@ -1066,13 +1077,19 @@ int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
   return 0;
 }
 
-/** Get event data */
+/** Get event data.
+ *
+ * @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event().
+ */
 nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1])
 {
   return saved ? su_msg_data(saved) : NULL;
 }
 
-/** Destroy saved event */
+/** Destroy saved event.
+ *
+ * @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request().
+ */
 void nua_destroy_event(nua_saved_event_t saved[1])
 {
   if (su_msg_is_non_null(saved)) {
@@ -1136,7 +1153,14 @@ sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh,
                                         int early_only)
 {
   if (nh && nh->nh_valid && nh->nh_nua) {
+#if HAVE_OPEN_C
+    struct nua_stack_handle_make_replaces_args a = { NULL, NULL, NULL, 0 };
+    a.nh = nh;
+    a.home = home;
+    a.early_only = early_only;
+#else
     struct nua_stack_handle_make_replaces_args a = { NULL, nh, home, early_only };
+#endif
 
     if (su_task_execute(nh->nh_nua->nua_server,
                        nua_stack_handle_make_replaces_call, (void *)&a,
@@ -1176,7 +1200,14 @@ static int nua_stack_handle_by_replaces_call(void *arg)
 nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *r)
 {
   if (nua) {
+#if HAVE_OPEN_C
+    struct nua_stack_handle_by_replaces_args a;
+       a.retval = NULL;
+    a.nua = nua;
+    a.r = r;
+#else
     struct nua_stack_handle_by_replaces_args a = { NULL, nua, r };
+#endif
 
     if (su_task_execute(nua->nua_server,
                        nua_stack_handle_by_replaces_call, (void *)&a,
index 0d322ca96d5d54d0380189daa01c3514876a13e3..fb241b7fe2fd8f81f3ce2d08fc8cf3d518c4e665 100644 (file)
@@ -26,18 +26,18 @@ The NUA API gives the high-level application programmer transparent and
 full control to the SIP protocol engine below it. NUA provides the call
 semantics on top of existing transaction semantics found in
 <a href="../nta/index.html"><b>nta</b></a> module.
-API makes it possible to create different kind of User Agents,
+With NUA it is possible to create different kind of SIP User Agents,
 like terminals, gateways or MCUs.
 
 The @b nua engine hides many low-level signaling and media management
 aspects from the application programmer. It is possible to use different
 kind of media interfaces - even remote ones - in a fully transparent way.
 
-The application and the protocol engine within User Agent library can be
-run in separate threads. Communications from the protocol engine is
-conveyed through a callback function. The callback function is called
-within context of the application, so the application must provide
-appropriate handle to a #su_root_t object.
+The application and the protocol engine within User Agent library can be run
+in separate threads. The protocol engine communicates with the application
+using @ref nua_event_e "events", delivered to the application with a a
+callback function. The callback function is called within the thread context
+of the application, represented with a #su_root_t object.
 
 @section nua_concepts_user Sofia Concepts for NUA User
 
@@ -74,14 +74,14 @@ the main event loop of the task. Through the root object the task code
 can access its context information (magic) and thread-synchronization
 features like wait objects, timers, and messages.
 
-An application using NUA services must create a root object and the
-callback routine to handle events. The root object is created with
-su_root_create() function and the callback routine is registered with
+An application using NUA services must create a root object and the callback
+routine to handle @ref nua_event_e "NUA events". The root object is created
+with su_root_create() function and the callback routine is registered with
 nua_create() function.
 
 Root object has type #su_root_t.
 
-See documentation of <su_wait.h> and <su_root.c> for more information
+See documentation of <sofia-sip/su_wait.h> and <su_root.c> for more information
 of root object.
 
 See section #nua_event_e for more information of the callback function.
@@ -109,8 +109,8 @@ separately.
 An application using NUA services can use the memory management services
 provided by the SU library but it is not mandatory.
 
-See documentation of <su_alloc.h> for more information of memory management
-services.
+See documentation of <sofia-sip/su_alloc.h> for more information of memory
+management services.
 
 @subsection nua_tags Tags
 
@@ -169,14 +169,14 @@ An application using NUA services must use tagged arguments for passing the
 parameters to functions. See nua_invite() for discussion on how a SIP
 message is constructed from the tags.
 
-See documentation of <su_tag.h> for more information of tags and the
+See documentation of <sofia-sip/su_tag.h> for more information of tags and the
 module-specific documentation of each Sofia module for information of
 tags specific for that module.
 
 @subsection nua_debugandlogging Debugging and Logging
 
 The modules of Sofia stack contain configurable debugging and logging
-functionality based on the services defined in <su_log.h>. The debugging
+functionality based on the services defined in <sofia-sip/su_log.h>. The debugging
 and logging details (for example level of details on output and output
 file name) can be configured by environment variables, directives in
 configuration files and compilation directives in the source files.
@@ -201,7 +201,7 @@ The defined debug output levels are:
 An application using NUA services can also use the debugging and
 logging services provided by the Sofia stack but it is not mandatory.
 
-See documentation of <su_log.h> for more information of debugging and
+See documentation of <sofia-sip/su_log.h> for more information of debugging and
 logging services.
 
 @section nua_concepts NUA Concepts
@@ -2089,6 +2089,8 @@ NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side.
  * #nua_r_unregister  \n
  * #nua_r_unsubscribe \n
  * #nua_r_update
+ * 
+ * @sa nua_event_is_incoming_request(), nua_event_name()
  */
 
 /** @NUA_EVENT nua_i_chat
index 934df00cd7228581c15168594138b98b1082c574..6e7499636e29a10ddc259f6bfd09820b72f658f2 100644 (file)
@@ -235,7 +235,7 @@ char const *nua_generate_instance_identifier(su_home_t *home)
  *   ...
  * @endcode
  *
- * @sa #nua_event_t, nua_respond()
+ * @sa nua_respond(), #nua_event_e, #nua_event_t, nua_event_name()
  *
  * @NEW_1_12_6
  */
@@ -260,7 +260,10 @@ int nua_event_is_incoming_request(nua_event_t event)
   }
 }
 
-/** Get name for a NUA event. */
+/** Get name for a NUA event. 
+ *
+ * @sa #nua_event_e, #nua_event_t, nua_callstate_name(), nua_substate_name()
+ */
 char const *nua_event_name(nua_event_t event)
 {
   switch (event) {
@@ -329,7 +332,10 @@ char const *nua_event_name(nua_event_t event)
   }
 }
 
-/** Return name of call state */
+/** Return name of call state.
+ * 
+ * @sa enum #nua_callstate, nua_event_name(), nua_substate_name()
+ */
 char const *nua_callstate_name(enum nua_callstate state)
 {
   switch (state) {
@@ -348,7 +354,10 @@ char const *nua_callstate_name(enum nua_callstate state)
   }
 }
 
-/** Return name of subscription state. @NEW_1_12_5. */
+/** Return name of subscription state. @NEW_1_12_5. 
+ *
+ * @sa enum #nua_substate, nua_event_name(), nua_callstate_name()
+ */
 char const *nua_substate_name(enum nua_substate substate)
 {
   switch (substate) {
index 4e258cb2e74e1f22c6570c6e33de49cc5876bf35..333ed9f239f0e5667528b4b45bf6bbafeae77dc6 100644 (file)
@@ -63,7 +63,7 @@
  *    NUTAG_METHOD() \n
  *    NUTAG_URL() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_method
index e34ba8ef0f9eae135012c1b875f97e87f858c183..8f8fc391b3187558b475100f8bdd9a31c8c6734f 100644 (file)
@@ -64,7 +64,7 @@
  * @par Related Tags:
  *    NUTAG_URL() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_message
index 70af312c8a9c288e07d83dd975721741190ca08c..fcb37f8c6803525b51f9217374a33d61bc7b4949 100644 (file)
@@ -366,7 +366,7 @@ int nua_subscribe_server_report(nua_server_request_t *sr, tagi_t const *tags)
  * @par Related Tags:
  *    NUTAG_SUBSTATE() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_notify
index e161e6423a0105d1f8706ff732250c89d63e2705..82e5c23cf90fd210925d4110d9fd09d84d6d691b 100644 (file)
@@ -58,7 +58,7 @@
  *    nothing
  *
  * @par Related Tags:
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_options
index a1bb6551809b9849e0c540302393122d87b171eb..92f1d0091556ab5b660036aeb9b967df249a51ca 100644 (file)
@@ -1088,6 +1088,11 @@ static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t);
 /** Save taglist to a handle */
 int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
 {
+#if HAVE_OPEN_C
+  /* Nice. An old symbian compiler */
+  tagi_t tagfilter[2];
+  tagi_t paramfilter[2];
+#else
   tagi_t const tagfilter[] = {
     { TAG_FILTER(nua_handle_tags_filter) },
     { TAG_NULL() }
@@ -1096,6 +1101,7 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
     { TAG_FILTER(nua_handle_param_filter) },
     { TAG_NULL() }
   };
+#endif
 
   /* Initialization parameters */
   url_string_t const *url = NULL;
@@ -1112,6 +1118,18 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
 
   int error;
 
+#if HAVE_OPEN_C
+  tagfilter[0].t_tag = tag_filter;
+  tagfilter[0].t_value = tag_filter_v(nua_handle_tags_filter);
+  tagfilter[1].t_tag = (tag_type_t)0;
+  tagfilter[1].t_value = (tag_value_t)0;
+
+  paramfilter[0].t_tag = tag_filter;
+  paramfilter[0].t_value = tag_filter_v(nua_handle_param_filter);
+  paramfilter[1].t_tag = (tag_type_t)0;
+  paramfilter[1].t_value = (tag_value_t)0;
+#endif
+
   for (t = tags; t; t = tl_next(t)) {
     if (t->t_tag == NULL)
       break;
index 44eb4337a8ee4bdd5d8a51cc418ab02d146a86f3..dda89be2baaf3441f490724a8d891bf9220d28f0 100644 (file)
@@ -138,7 +138,7 @@ void nua_publish_usage_remove(nua_handle_t *nh,
  * @par Related Tags:
  *    NUTAG_URL() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_publish
@@ -196,7 +196,7 @@ void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
  *    SIPTAG_IF_MATCH(), SIPTAG_IF_MATCH_STR() \n
  *    SIPTAG_EVENT(), SIPTAG_EVENT_STR() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Other header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
  *
  * @par Events:
  *    #nua_r_unpublish
index d2e97a923eb97557e1866d7ef099af35d3820729..9c31ba6ec6f0b8cc05372bdb939691e1dcd3663b 100644 (file)
@@ -48,7 +48,7 @@
 #include <sofia-sip/sip_util.h>
 #include <sofia-sip/sip_status.h>
 
-#define NTA_UPDATE_MAGIC_T   struct nua_handle_s
+#define NTA_UPDATE_MAGIC_T   struct nua_s
 
 #include "nua_stack.h"
 
@@ -516,7 +516,7 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
  *
  * @par Related tags:
  *     NUTAG_REGISTRAR() \n
- *     Tags in <sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
+ *     Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
  *
  * @par Events:
  *     #nua_r_unregister
index 323254f8cead8ad29b4ec22f687d3a97fc7ea229..6508e72d1f0cfd1b11fe5e54a7deaad573c02ee8 100644 (file)
@@ -999,7 +999,7 @@ static int nua_invite_client_report(nua_client_request_t *cr,
  *    nothing
  *
  * @par Related Tags:
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_i_media_error \n
@@ -1217,7 +1217,7 @@ static int nua_invite_client_deinit(nua_client_request_t *cr)
  *    nothing
  *
  * @par Related Tags:
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_cancel, #nua_i_state  (#nua_i_active, #nua_i_terminated)
@@ -2714,7 +2714,7 @@ nh_referral_respond(nua_handle_t *nh, int status, char const *phrase)
  *    nothing
  *
  * @par Related Tags:
- *    Tags in <sip_tag.h>.
+ *    Header tags defined in <sofia-sip/sip_tag.h>.
  *
  * @par Events:
  *    #nua_r_info
index 1cf9110ecdd551016e13dc6500e150ef977d3155..123187bf2d0111786f6e24f6f7a452a5aa0b60eb 100644 (file)
@@ -781,10 +781,6 @@ int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
   if (nua_stack_set_params(nua, nh, nua_i_error, ta_args(ta)) < 0)
     retval = -1;
 
-  if (!retval && nh->nh_soa)
-    if (soa_set_params(nh->nh_soa, ta_tags(ta)) < 0)
-      retval = -1;
-
   ta_end(ta);
 
   if (retval || nh->nh_init) /* Already initialized? */
@@ -1338,7 +1334,7 @@ void nua_server_request_destroy(nua_server_request_t *sr)
  *    SOATAG_AF() \n
  *    SOATAG_HOLD() \n
  *    Tags used with nua_set_hparams() \n
- *    Tags in <sip_tag.h>.
+ *    Header tags defined in <sofia-sip/sip_tag.h>.
  *
  * @par Events:
  *    #nua_i_state \n
@@ -1445,13 +1441,25 @@ int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags)
   nua_handle_t *nh = sr->sr_owner;
   sip_method_t method = sr->sr_method;
   struct { msg_t *msg; sip_t *sip; } next = { NULL, NULL };
-  tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }};
   int retval;
+#if HAVE_OPEN_C
+  /* Nice. And old arm symbian compiler; see below. */
+  tagi_t next_tags[2];
+#else
+  tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }};
+#endif
 
   msg_t *msg = sr->sr_response.msg;
   sip_t *sip = sr->sr_response.sip;
   sip_contact_t *m = sr->sr_request.sip->sip_contact;
 
+#if HAVE_OPEN_C
+  next_tags[0].t_tag   = siptag_end;
+  next_tags[0].t_value = (tag_value_t)0;
+  next_tags[1].t_tag   = tag_next;
+  next_tags[1].t_value = (tag_value_t)(tags);
+#endif
+
   if (sr->sr_response.msg == NULL) {
     assert(sr->sr_status == 500);
     goto internal_error;
index 1d863eb14548d8ecc7e3de0d8ef3a15469490811..d2a0903f7f22dc793fadb5e2b500d978fcc77de5 100644 (file)
@@ -62,7 +62,7 @@
 
 #ifndef NUA_DIALOG_H
 #define NUA_OWNER_T struct nua_handle_s
-#include <nua_dialog.h>
+#include "nua_dialog.h"
 #endif
 
 SOFIA_BEGIN_DECLS
@@ -72,7 +72,7 @@ SOFIA_BEGIN_DECLS
 #endif
 
 #ifndef NUA_PARAMS_H
-#include <nua_params.h>
+#include "nua_params.h"
 #endif
 
 typedef struct event_s event_t;
index 2db1ca8c3a11ae4f2cf0ac624f1103e2b2cd93c1..9855fb79137a37f48e7e99abbaf068236c268690 100644 (file)
@@ -138,7 +138,7 @@ void nua_subscribe_usage_remove(nua_handle_t *nh,
  *
  * @par Related Tags:
  *    NUTAG_URL()
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_subscribe \n
@@ -164,7 +164,7 @@ void nua_subscribe_usage_remove(nua_handle_t *nh,
  *
  * @par Related Tags:
  *    SIPTAG_EVENT() or SIPTAG_EVENT_STR() \n
- *    Tags in <sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
+ *    Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
  *
  * @par Events:
  *    #nua_r_unsubscribe 
@@ -401,9 +401,10 @@ static int nua_subscribe_client_response(nua_client_request_t *cr,
       /* let nua_base_client_tresponse to remove usage */
       cr->cr_terminated = 1;   
   }
-  
+
   return nua_base_client_tresponse(cr, status, phrase, sip, 
                                   NUTAG_SUBSTATE(substate),
+                                  SIPTAG_EVENT(du ? du->du_event : NULL),
                                   TAG_END());
 }
 
@@ -727,7 +728,7 @@ int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags)
  * @par Related Tags:
  *    NUTAG_URL() \n
  *    Tags of nua_set_hparams() \n
- *    Tags in <sip_tag.h>
+ *    Header tags defined in <sofia-sip/sip_tag.h>
  *
  * @par Events:
  *    #nua_r_refer \n
@@ -852,6 +853,7 @@ static int nua_refer_client_request(nua_client_request_t *cr,
     nua_stack_tevent(nh->nh_nua, nh, NULL,
                     cr->cr_event, SIP_100_TRYING,
                     NUTAG_REFER_EVENT(event),
+                    SIPTAG_EVENT(event),
                     TAG_END());
     su_free(nh->nh_home, event);
   }
@@ -885,5 +887,6 @@ static int nua_refer_client_response(nua_client_request_t *cr,
   
   return nua_base_client_tresponse(cr, status, phrase, sip, 
                                   NUTAG_SUBSTATE(substate),
+                                  SIPTAG_EVENT(du ? du->du_event : NULL),
                                   TAG_END());
 }
index 526cdf381043d4f7fed00ab5cb6d03e1d104c03f..94189d92ea9522d42cc9353446408c629d54992b 100644 (file)
@@ -36,7 +36,7 @@
 
 #define NTA_OUTGOING_MAGIC_T struct outbound
 
-#include <outbound.h>
+#include "outbound.h"
 
 #include <sofia-sip/hostdomain.h>
 #include <sofia-sip/sip.h>
index c5768548359122b376440ea212dc36a87ef59563..38226f6683755fe3c8962c87e16c405d95293266 100644 (file)
@@ -172,6 +172,7 @@ typedef struct event_s {
 /** NUA module version */
 SOFIAPUBVAR char const nua_version[];
 
+/** Typedef of NUA event callback. */
 typedef void (*nua_callback_f)(nua_event_t event,
                               int status, char const *phrase,
                               nua_t *nua, nua_magic_t *magic,
@@ -349,9 +350,10 @@ SOFIAPUBFUN void nua_respond(nua_handle_t *nh,
 /** Check if event can be responded with nua_respond() */
 SOFIAPUBFUN int nua_event_is_incoming_request(nua_event_t e);
 
+/** Cast a #nua_handle_t pointer to a #su_home_t. */
 #define nua_handle_home(nh) ((su_home_t *)(nh))
 
-/** Generate an instance identifier */
+/** Generate an instance identifier. */
 SOFIAPUBFUN char const *nua_generate_instance_identifier(su_home_t *);
 
 #ifndef NUA_SAVED_EVENT_T
index 6b82bfc91031fc337327dc4f5d6bfe71932648df..e5b9eb18e334b8756d7b443dcf084757658d0494 100644 (file)
@@ -1105,6 +1105,256 @@ int test_basic_call_5(struct context *ctx)
   END();
 }
 
+/* ======================================================================== */
+
+/* Call with media upgrade:
+
+   A                   B
+   |-------INVITE------>|
+   |   with audio only |
+   |<----100 Trying-----|
+   |                   |
+   |<----180 Ringing----|
+   |                   |
+   |<------200 OK-------|
+   |--------ACK-------->|
+   |                   |
+   |<------INVITE-------|
+   |   with video      |
+   |-----100 Trying---->|
+   |                   |
+   |-------200 OK------>|
+   |   with video      |
+   |<-------ACK---------|
+   |                   |
+   |<-------BYE---------|
+   |-------200 OK------>|
+   |                   |
+
+   Client transitions:
+   INIT -(C1)-> CALLING -(C2a)-> PROCEEDING -(C3+C4)-> READY
+   Server transitions:
+   INIT -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S4)-> READY
+
+   B sends BYE:
+   READY -(T2)-> TERMINATING -(T3)-> TERMINATED
+   A receives BYE:
+   READY -(T1)-> TERMINATED
+
+   See @page nua_call_model in nua.docs for more information
+*/
+int accept_upgrade(CONDITION_PARAMS);
+
+int test_video_call_1(struct context *ctx)
+{
+  BEGIN();
+
+  struct endpoint *a = &ctx->a,  *b = &ctx->b;
+  struct call *a_call = a->call, *b_call = b->call;
+  struct event *e;
+  sip_t *sip;
+  sdp_session_t *b_sdp;
+  sdp_media_t *m, b_video[1];
+  sdp_rtpmap_t *rm, b_h261[1];
+
+  sip_time_t se, min_se;
+
+  if (print_headings)
+    printf("TEST NUA-3.6: Basic call\n");
+
+  /* Disable session timer from proxy */
+  test_proxy_get_session_timer(ctx->p, &se, &min_se); 
+  test_proxy_set_session_timer(ctx->p, 0, 0); 
+
+  a_call->sdp = "m=audio 5008 RTP/AVP 8";
+  b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
+
+  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+
+  TEST_1(!nua_handle_has_active_call(a_call->nh));
+  TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
+
+  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_AUTOANSWER(0),
+        TAG_END());
+
+  run_ab_until(ctx, -1, until_ready, -1, accept_call_with_early_sdp);
+
+  TEST_1(nua_handle_has_active_call(a_call->nh));
+  TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
+
+  TEST_1(nua_handle_has_active_call(b_call->nh));
+  TEST_1(!nua_handle_has_call_on_hold(b_call->nh));
+
+  /* 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(sip = sip_object(e->data->e_msg));
+  TEST_1(sip->sip_payload);
+  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(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(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, 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(is_answer_sent(e->data->e_tags));
+  TEST_1(tl_find(e->data->e_tags, soatag_local_sdp));
+  TEST_1(b_sdp = sdp_session_dup(nua_handle_home(a_call->nh),
+                                (sdp_session_t *)
+                                tl_find(e->data->e_tags, soatag_local_sdp)
+                                ->t_value));
+  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);
+
+  a_call->sdp =
+    "m=audio 5008 RTP/AVP 8\n"
+    "m=video 5014 RTP/AVP 34 31\n";
+  
+  m = memset(b_video, 0, sizeof b_video);    
+  m->m_size = sizeof *m;
+  m->m_session = b_sdp;
+  m->m_type = sdp_media_video, m->m_type_name = "video";
+  m->m_port = 5016;
+  m->m_proto = sdp_proto_rtp; m->m_proto_name = "RTP/AVP";
+  m->m_rtpmaps = memset(rm = b_h261, 0, sizeof b_h261);
+  rm->rm_size = sizeof *rm;
+  rm->rm_pt = 31; rm->rm_encoding = "h261"; rm->rm_rate = 90000; 
+
+  b_sdp->sdp_media->m_next = m;
+
+  INVITE(b, b_call, b_call->nh,
+        SOATAG_USER_SDP(b_sdp),
+        TAG_END());
+  run_ab_until(ctx, -1, accept_upgrade, -1, until_ready);
+
+  TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_state);
+  TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
+  TEST_1(tl_find(e->data->e_tags, soatag_local_sdp_str));
+  TEST_1(strstr((char *)
+               tl_find(e->data->e_tags, soatag_local_sdp_str)->t_value,
+               "m=video"));
+  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_1(is_answer_recv(e->data->e_tags));
+  TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
+  TEST_1(!e->next);
+  free_events_in_list(ctx, b->events);
+
+  TEST_1(e = a->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(tl_find(e->data->e_tags, soatag_local_sdp_str));
+  TEST_1(strstr((char *)
+               tl_find(e->data->e_tags, soatag_local_sdp_str)->t_value,
+               "m=video"));
+  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, a->events);
+
+  BYE(b, b_call, b_call->nh, TAG_END());
+  run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
+
+  /* B transitions:
+   READY --(T2)--> TERMINATING: nua_bye()
+   TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state
+  */
+  TEST_1(e = b->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, b->events);
+
+  TEST_1(!nua_handle_has_active_call(b_call->nh));
+
+  /* A transitions:
+     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(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));
+
+  nua_handle_destroy(a_call->nh), a_call->nh = NULL;
+  nua_handle_destroy(b_call->nh), b_call->nh = NULL;
+
+  test_proxy_set_session_timer(ctx->p, se, min_se); 
+
+  if (print_headings)
+    printf("TEST NUA-3.6: PASSED\n");
+
+  END();
+}
+
+int accept_upgrade(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_i_invite && status < 200) {
+    RESPOND(ep, call, nh, SIP_200_OK,
+           TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)),
+           TAG_END());
+    return 0;
+  }
+
+  switch (callstate(tags)) {
+  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;
+  }
+}
 
 int test_basic_call(struct context *ctx)
 {
@@ -1114,5 +1364,6 @@ int test_basic_call(struct context *ctx)
     || test_basic_call_3(ctx)
     || test_basic_call_4(ctx)
     || test_basic_call_5(ctx)
+    || test_video_call_1(ctx)
     ;
 }
index fbce1717748e8dd3e04592d54b12f84275231265..6e69fa465cf1311f877145b7c91baa5f51723bcb 100644 (file)
@@ -97,7 +97,10 @@ int cancel_when_calling(CONDITION_PARAMS)
 
   switch (callstate(tags)) {
   case nua_callstate_calling:
-    CANCEL(ep, call, nh, TAG_END());
+    CANCEL(ep, call, nh,
+          /* sf.net bug #173323 */
+          SIPTAG_CALL_ID_STR("non-existing-call-id"),
+          TAG_END());
     return 0;
   case nua_callstate_terminated:
     return 1;
index ce7b14519130d5396b5aafc223ae54323c793160..269275d9f1e2a6fabce36fd317dabea0fcc54de5 100644 (file)
@@ -72,6 +72,7 @@ int test_nua_init(struct context *ctx,
   char const *appl_method = NULL;
   url_t const *p_uri, *a_uri, *b_uri;          /* Proxy URI */
   char const *a_bind, *a_bind2;
+  int err = -1;
   url_t b_proxy[1];
 
   a_bind = a_bind2 = "sip:0.0.0.0:*";
@@ -235,13 +236,15 @@ int test_nua_init(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.specials->head);
-  TEST(tl_gets(e->data->e_tags,
-              NTATAG_CONTACT_REF(m),
-              SIPTAG_FROM_REF(sipaddress),
-              SIPTAG_ALLOW_REF(allow),
-              NUTAG_APPL_METHOD_REF(appl_method),
-              SIPTAG_SUPPORTED_REF(supported),
-              TAG_END()), 5); TEST_1(m);
+  err = tl_gets(e->data->e_tags,
+                   NTATAG_CONTACT_REF(m),
+                   SIPTAG_FROM_REF(sipaddress),
+                   SIPTAG_ALLOW_REF(allow),
+                   NUTAG_APPL_METHOD_REF(appl_method),
+                   SIPTAG_SUPPORTED_REF(supported),
+                   TAG_END());
+  TEST(err, 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));
@@ -280,13 +283,14 @@ int test_nua_init(struct context *ctx,
   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.specials->head);
-  TEST(tl_gets(e->data->e_tags,
-              NTATAG_CONTACT_REF(m),
-              SIPTAG_FROM_REF(sipaddress),
-              SIPTAG_ALLOW_REF(allow),
-              NUTAG_APPL_METHOD_REF(appl_method),
-              SIPTAG_SUPPORTED_REF(supported),
-              TAG_END()), 5); TEST_1(m);
+  err = tl_gets(e->data->e_tags,
+                   NTATAG_CONTACT_REF(m),
+                   SIPTAG_FROM_REF(sipaddress),
+                   SIPTAG_ALLOW_REF(allow),
+                   NUTAG_APPL_METHOD_REF(appl_method),
+                   SIPTAG_SUPPORTED_REF(supported),
+                   TAG_END());
+  TEST(err, 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));
@@ -317,13 +321,15 @@ int test_nua_init(struct context *ctx,
   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.specials->head);
-  TEST(tl_gets(e->data->e_tags,
-              NTATAG_CONTACT_REF(m),
-              SIPTAG_FROM_REF(sipaddress),
-              SIPTAG_ALLOW_REF(allow),
-              NUTAG_APPL_METHOD_REF(appl_method),
-              SIPTAG_SUPPORTED_REF(supported),
-              TAG_END()), 5); TEST_1(m);
+  err = tl_gets(e->data->e_tags,
+                   NTATAG_CONTACT_REF(m),
+                   SIPTAG_FROM_REF(sipaddress),
+                   SIPTAG_ALLOW_REF(allow),
+                   NUTAG_APPL_METHOD_REF(appl_method),
+                   SIPTAG_SUPPORTED_REF(supported),
+                   TAG_END());
+  
+  TEST(err, 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));
   TEST_1(ctx->c.allow = sip_allow_dup(ctx->home, allow));
index 0f3763f2e6e873d4d7c93af42621aa3eece3ac05..249b6b845f005d0911e3e7367458eda73c37a116 100644 (file)
@@ -79,7 +79,7 @@ STORAGE void PREFIX ##_remove(T *node)                         \
 }                                                       \
 extern int LIST_DUMMY_VARIABLE
 
-#include <test_nat.h>
+#include "test_nat.h"
 
 struct nat {
   su_home_t    home[1];
index efcaa7263ec75c05b27f7eca60ffa62bf292cee8..5798748dab9c16cd511e057c0b951210901764e0 100644 (file)
@@ -117,6 +117,10 @@ int main(int argc, char *argv[])
 
   struct context ctx[1] = {{{ SU_HOME_INIT(ctx) }}};
 
+#if HAVE_OPEN_C
+  dup2(1, 2);
+#endif
+  
   if (getenv("EXPENSIVE_CHECKS"))
     o_expensive = 1;
 
@@ -272,6 +276,25 @@ int main(int argc, char *argv[])
   }
 #endif
 
+#if HAVE_OPEN_C
+  tstflags |= tst_verbatim;
+  level = 9;
+  o_inat = 1; /* No NATs */
+  ctx->threading = 1;
+  ctx->quit_on_single_failure = 1;
+  su_log_soft_set_level(nua_log, level);
+  su_log_soft_set_level(soa_log, level);
+  su_log_soft_set_level(su_log_default, level);
+  su_log_soft_set_level(nea_log, level);
+  su_log_soft_set_level(nta_log, level);
+  su_log_soft_set_level(tport_log, level);
+  setenv("SU_DEBUG", "9", 1);
+  setenv("NUA_DEBUG", "9", 1);
+  setenv("NTA_DEBUG", "9", 1);
+  setenv("TPORT_DEBUG", "9", 1);
+  o_events_a = o_events_b = 1;
+#endif
+
   su_init();
 
   if (!(TSTFLAGS & tst_verbatim)) {
@@ -279,6 +302,7 @@ int main(int argc, char *argv[])
       level = 1;
     su_log_soft_set_level(nua_log, level);
     su_log_soft_set_level(soa_log, level);
+    su_log_soft_set_level(su_log_default, level);
     su_log_soft_set_level(nea_log, level);
     su_log_soft_set_level(nta_log, level);
     su_log_soft_set_level(tport_log, level);
@@ -288,16 +312,28 @@ int main(int argc, char *argv[])
       || o_events_a || o_events_b || o_events_c)
     print_headings = 1;
 
+#if !HAVE_OPEN_C
 #define SINGLE_FAILURE_CHECK()                                         \
   do { fflush(stdout);                                                 \
     if (retval && ctx->quit_on_single_failure) {                       \
       su_deinit(); return retval; }                                    \
   } while(0)
+#else
+#define SINGLE_FAILURE_CHECK()                                         \
+  do { fflush(stdout);                                                 \
+    if (retval && ctx->quit_on_single_failure) {                       \
+      su_deinit(); sleep(10); return retval; }                                 \
+  } while(0)
+#endif
 
   ctx->a.printer = o_events_init ? print_event : NULL;
 
+  sleep(2);
+
   retval |= test_nua_api_errors(ctx); SINGLE_FAILURE_CHECK();
+  
   retval |= test_tag_filter(); SINGLE_FAILURE_CHECK();
+
   retval |= test_nua_params(ctx); SINGLE_FAILURE_CHECK();
 
   retval |= test_nua_init(ctx, o_iproxy, o_proxy, o_inat,
@@ -351,5 +387,9 @@ int main(int argc, char *argv[])
 
   su_deinit();
 
+#if HAVE_OPEN_C
+  sleep(7);
+#endif
+
   return retval;
 }
index 9f169de9adb1ec9d6d2c67a2bc96d09bd0340678..5947f04f72d5175987632d8d03fc97d07fffb736 100644 (file)
@@ -49,13 +49,14 @@ struct call;
 #include <sofia-sip/su_log.h>
 #include <sofia-sip/su_tagarg.h>
 #include <sofia-sip/su_tag_io.h>
+#include <sofia-sip/nua_tag.h>
 
 #if __APPLE_CC__
 #include <sofia-sip/su_osx_runloop.h>
 #endif
 
-#include <test_proxy.h>
-#include <test_nat.h>
+#include "test_proxy.h"
+#include "test_nat.h"
 #include <sofia-sip/auth_module.h>
 
 #include <stddef.h>
index 604d7475d1128d4de3dc3023ad1b2f1557108833..6b57ad8d464592b423a443755d780758bfd839e7 100644 (file)
@@ -179,7 +179,8 @@ int test_stack_errors(struct context *ctx)
   if (print_headings)
     printf("TEST NUA-1.2.2: BYE without INVITE\n");
 
-  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+  a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END());
+  TEST_1(a_call->nh);
 
   BYE(a, a_call, a_call->nh, TAG_END());
 
@@ -203,7 +204,8 @@ int test_stack_errors(struct context *ctx)
   if (print_headings)
     printf("TEST NUA-1.2.3: unregister without register\n");
 
-  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(a->to), TAG_END()));
+  a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(a->to), TAG_END());
+  TEST_1(a_call->nh);
 
   UNREGISTER(a, a_call, a_call->nh, TAG_END());
 
@@ -227,7 +229,8 @@ int test_stack_errors(struct context *ctx)
   if (print_headings)
     printf("TEST NUA-1.2.4: unpublish without publish\n");
 
-  TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
+  a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END());
+  TEST_1(a_call->nh);
 
   UNPUBLISH(a, a_call, a_call->nh, TAG_END());
 
index 23e89bbca882e9034e27f0767f784ba7a35469e0..bcdb160bb36e437cc0212879c511e15e78fc5f41 100644 (file)
@@ -83,7 +83,7 @@ STORAGE void PREFIX ##_remove(T *node)                         \
 }                                                       \
 extern int LIST_DUMMY_VARIABLE
 
-#include <test_proxy.h>
+#include "test_proxy.h"
 
 struct proxy {
   su_home_t    home[1];
index 62830d8d4aa86983ae66b20bd57e9897e82ba0d4..22ed629d8db9c67376b916f86729e6fc6115155c 100644 (file)
@@ -1180,7 +1180,7 @@ int sdp_session_cmp(sdp_session_t const *a, sdp_session_t const *b)
       return rv;
 
   for (am = a->sdp_media, bm = b->sdp_media; 
-       am || bb
+       am || bm
        am = am->m_next, bm = bm->m_next)
     if ((rv = sdp_media_cmp(am, bm)))
       return rv;
index f3c84e0464614aca8eeb55f02f5b29078e5a9f80..af349299986a2a4eec549c98d82b1cc6fb88e5d7 100644 (file)
@@ -15,7 +15,7 @@
  *
  * @section sip_overview Overview
  *
- * The structure of each header is defined in @b <sip.h>. In addition to the
+ * The structure of each header is defined in @b <sofia-sip/sip.h>. In addition to the
  * header structure, there is defined a @em header @em class structure and
  * some standard functions for each header in the include file @b
  * <sofia-sip/sip_header.h>. For header @c X, there are types, functions,
@@ -68,7 +68,7 @@
  * structure. The fragments form a dual-linked list known as @e fragment @e
  * chain as shown in the above figure. The buffers for the message, the
  * fragment chain, and a whole other stuff is held by the generic message
- * type, #msg_t, defined in <msg.h>. The internal structure of #msg_t is
+ * type, #msg_t, defined in <sofia-sip/msg.h>. The internal structure of #msg_t is
  * known only within @b msg module and it is hidden from other modules.
  * 
  * The abstract message module @b msg also drives the reverse process,
  * structure. The @e sip_size indicates the size of the structure - the
  * application can extend the parser and #sip_t structure beyond the
  * original size. The @e sip_flags contains various flags used during the
- * parsing and printing process. They are documented in the <msg.h>. These
+ * parsing and printing process. They are documented in the <sofia-sip/msg.h>. These
  * boilerplate members are followed by the pointers to various message
  * elements and headers.
  *
@@ -572,14 +572,14 @@ int sip_X_e(char buf[], int bsiz, sip_header_t const *h, int flags);
 /**@defgroup sip_status_codes SIP Status Codes and Reason Phrases
  *
  * The macros and variables for the standard SIP status codes and reason
- * phrases are defined in <sip_status.h>.
+ * phrases are defined in <sofia-sip/sip_status.h>.
  */
 
 /**@defgroup sip_tag SIP Tags
  *
  * SIP headers in tag item lists and tagged argument lists. 
  *
- * The include file <sip_tag.h> defines tags and tag items for including SIP
+ * The include file <sofia-sip/sip_tag.h> defines tags and tag items for including SIP
  * headers in tag item lists or tagged argument lists. For each header,
  * there is a tag for pointer to header object and an another tag for string
  * containing header value. For example, @From header has tags
index 8fd20c182a45a852cfa041874327c51375cc461d..28859846a81f4185e151daeed8ae68e89f747795 100644 (file)
@@ -1,5 +1,5 @@
 #
-# nta has a bad_mask specifying which headers cause nta to automatically
+# nta has an error mask specifying which headers cause nta to automatically
 # return 400 Bad Message if a critical header or pseudoheader in a request
 # has a parsing error.
 #
@@ -7,13 +7,18 @@
 #
 # See <sip_parser.h> for definition of mask values.
 #
-# The mask can be set when header is added with
-# msg_mclass_insert_header_flags().  
+# The error flags for a particular header can be set when header is added
+# with msg_mclass_insert_header_flags().
 #
 # The flags of existing headers can be modified, if a copy of message class
 # is first made with msg_mclass_clone().
 #
 
+#
+# When updating this file, please update 
+# NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation, too.
+#
+
 #
 # Headers that must be valid for all requests
 #
@@ -53,7 +58,7 @@ Path = sip_mask_registrar
 #
 Supported = sip_mask_ua | sip_mask_proxy | sip_mask_registrar
 Contact = sip_mask_ua | sip_mask_proxy | sip_mask_registrar
-Require = sip_mask_ua | sip_mask_registrar
+Require = sip_mask_ua | sip_mask_registrar | sip_mask_timer
 Record-Route = sip_mask_ua | sip_mask_proxy
 
 Expires = sip_mask_registrar | sip_mask_events
index acb6a54546b25d75dad61f31c442502123fa8946..162f6412f91c4325937973be78880859b3b64d75 100644 (file)
@@ -802,10 +802,10 @@ issize_t sip_name_addr_e(char b[], isize_t bsiz,
 }
 
 /** Parse @To or @From headers */
-issize_t sip_addr_d(su_home_t *home,
-                   sip_header_t *h,
-                   char *s,
-                   isize_t slen)
+static issize_t sip_addr_d(su_home_t *home,
+                          sip_header_t *h,
+                          char *s,
+                          isize_t slen)
 {
   sip_addr_t *a = (sip_addr_t *)h;
   char const *comment = NULL;
index 03274f36d88a5e2344b8f9d9115cb5a9b79f79ab..d442c50f146cb514a7869e3a97c63bcc8270af58 100644 (file)
@@ -202,6 +202,163 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
                         NULL, 1, ei->ei_url, ei->ei_params, NULL);
 }
 
+/* ====================================================================== */
+
+/**@SIP_HEADER sip_alert_info Alert-Info Header
+ *
+ * When present in an INVITE request, the Alert-Info header field
+ * specifies an alternative ring tone to the UAS.  When present in a 180
+ * (Ringing) response, the Alert-Info header field specifies an
+ * alternative ringback tone to the UAC.  A typical usage is for a proxy
+ * to insert this header field to provide a distinctive ring feature.
+ *
+ * @code
+ *    Alert-Info   =  "Alert-Info" HCOLON alert-param *(COMMA alert-param)
+ *    alert-param  =  LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
+ * @endcode
+ *
+ * The parsed Alert-Info header is stored in #sip_alert_info_t structure.
+ *
+ * @NEW_1_12_7
+ */
+
+/**@ingroup sip_alert_info
+ * @typedef struct sip_alert_info_s sip_alert_info_t;
+ *
+ * The structure #sip_alert_info_t contains representation of an
+ * @AlertInfo header.
+ *
+ * The #sip_alert_info_t is defined as follows:
+ * @code
+ * struct sip_alert_info_s
+ * {
+ *   sip_common_t        ai_common[1]; // Common fragment info
+ *   sip_alert_info_t   *ai_next;      // Link to next @AlertInfo
+ *   url_t               ai_url[1];    // URI to alert info
+ *   msg_param_t const  *ai_params;    // List of optional parameters
+ * };
+ * @endcode
+ *
+ * @NEW_1_12_7
+ */
+
+msg_hclass_t sip_alert_info_class[] =
+SIP_HEADER_CLASS(alert_info, "Alert-Info", "",
+                ai_params, append, info);
+
+issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
+{
+  return sip_info_d(home, h, s, slen);
+}
+
+issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
+{
+  sip_alert_info_t *ai = (sip_alert_info_t *)h;
+  return sip_name_addr_e(b, bsiz, f, NULL, 1, ai->ai_url, ai->ai_params, NULL);
+}
+
+/* ====================================================================== */
+
+/**@SIP_HEADER sip_reply_to Reply-To Header
+ *
+ * The @b Reply-To header field contains a logical return URI that may be
+ * different from the @From header field. For example, the URI MAY be used to
+ * return missed calls or unestablished sessions. If the user wished to
+ * remain anonymous, the header field SHOULD either be omitted from the
+ * request or populated in such a way that does not reveal any private
+ * information. Its syntax is defined in @RFC3261 as follows:
+ *
+ * @code
+ *   Reply-To      =  "Reply-To" HCOLON rplyto-spec
+ *   rplyto-spec   =  ( name-addr / addr-spec )
+ *                   *( SEMI rplyto-param )
+ *   rplyto-param  =  generic-param
+ * @endcode
+ *
+ * The parsed Reply-To header is stored in #sip_reply_to_t structure.
+ */
+
+/**@ingroup sip_reply_to
+ * @typedef struct msg_list_s sip_reply_to_t;
+ *
+ * The structure #sip_reply_to_t contains representation of SIP
+ * @ReplyTo header.
+ *
+ * The #sip_reply_to_t is defined as follows:
+ * @code
+ * struct sip_reply_to_s
+ * {
+ *   sip_common_t       rplyto_common[1]; // Common fragment info
+
+ *   sip_error_t       *rplyto_next;    // Dummy link to next header
+ *   char const        *rplyto_display;         // Display name
+ *   url_t              rplyto_url[1];  // Return URI
+ *   msg_param_t const *rplyto_params;  // List of optional parameters
+ * };
+ * @endcode
+ */
+
+static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset);
+static char *sip_reply_to_dup_one(sip_header_t *dst,
+                                 sip_header_t const *src,
+                                 char *b,
+                                 isize_t xtra);
+#define sip_reply_to_update NULL
+
+msg_hclass_t sip_reply_to_class[] =
+  SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to);
+
+issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
+{
+  sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
+
+  return sip_name_addr_d(home,
+                        &s,
+                        &rplyto->rplyto_display,
+                        rplyto->rplyto_url,
+                        &rplyto->rplyto_params,
+                        NULL);
+}
+
+issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
+{
+  sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
+
+  return sip_name_addr_e(b, bsiz,
+                        flags,
+                        rplyto->rplyto_display,
+                        MSG_IS_CANONIC(flags), rplyto->rplyto_url,
+                        rplyto->rplyto_params,
+                        NULL);
+}
+
+static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset)
+{
+  sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h;
+
+  MSG_PARAMS_SIZE(offset, rplyto->rplyto_params);
+  offset += MSG_STRING_SIZE(rplyto->rplyto_display);
+  offset += url_xtra(rplyto->rplyto_url);
+
+  return offset;
+}
+
+/**@internal Duplicate one sip_reply_to_t object. */
+static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
+                                 char *b, isize_t xtra)
+{
+  sip_reply_to_t *rplyto = (sip_reply_to_t *)dst;
+  sip_reply_to_t const *o = (sip_reply_to_t *)src;
+  char *end = b + xtra;
+
+  b = msg_params_dup(&rplyto->rplyto_params, o->rplyto_params, b, xtra);
+  MSG_STRING_DUP(b, rplyto->rplyto_display, o->rplyto_display);
+  URL_DUP(b, end, rplyto->rplyto_url, o->rplyto_url);
+
+  assert(b <= end);
+
+  return b;
+}
 
 /* ====================================================================== */
 
@@ -231,7 +388,7 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
  *   msg_common_t       k_common[1];  // Common fragment info
  *   msg_list_t        *k_next;       // Link to next header
  *   msg_param_t       *k_items;      // List of call ids
- * } sip_allow_events_t;
+ * } sip_in_reply_to_t;
  * @endcode
  */
 
@@ -249,7 +406,6 @@ issize_t sip_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
   return msg_list_e(b, bsiz, h, f);
 }
 
-
 /* ====================================================================== */
 
 /**@SIP_HEADER sip_organization Organization Header
index 7c49732d16c2c12826f271b1a413fef133a6eb47..69433c0328992daa009645477a29bf881d89f3af 100644 (file)
@@ -9,6 +9,8 @@
 #### EXTRA HEADER LIST STARTS HERE ####
 
 refer_sub @NEW_1_12_5 /**< Refer-Sub header */
+alert_info @NEW_1_12_7 /**< Alert-Info header */
+reply_to @NEW_1_12_7 /**< Reply-To header */
 
 #### EXPERIMENTAL HEADER LIST STARTS HERE ####
 
index 1c4e22ba14fdc19811c92d650209e701bb530103..bb072d3311953a88a07935f149dc54c431dba64c 100644 (file)
@@ -66,6 +66,33 @@ struct sip_refer_sub_s
   msg_param_t const  *rs_params;       /**< List of extension parameters */
 };
 
+typedef struct sip_alert_info_s sip_alert_info_t;
+
+/**@ingroup sip_alert_info
+ * @brief Structure for @AlertInfo header.
+ */
+struct sip_alert_info_s
+{
+  sip_common_t        ai_common[1];     /**< Common fragment info */
+  sip_alert_info_t   *ai_next;         /**< Link to next @AlertInfo */
+  url_t               ai_url[1];       /**< URI to alert info */
+  msg_param_t const  *ai_params;       /**< List of optional parameters */
+};
+
+typedef struct sip_reply_to_s sip_reply_to_t;
+
+/**@ingroup sip_reply_to
+ * @brief Structure for @ReplyTo header.
+ */
+struct sip_reply_to_s
+{
+  sip_common_t        rplyto_common[1];        /**< Common fragment info */
+  sip_error_t        *rplyto_next;     /**< Dummy link to next header */
+  char const         *rplyto_display;  /**< Display name */
+  url_t               rplyto_url[1];   /**< Return URI */
+  msg_param_t const  *rplyto_params;   /**< List of optional parameters */
+};
+
 typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t;
 
 /**@ingroup sip_suppress_body_if_match
@@ -91,6 +118,8 @@ struct sip_suppress_notify_if_match_s
 };
 
 \f
+/** Defined as 1 if the @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" is supported */
+#define SIP_HAVE_#XXXXXX# 1
 \f
 
 SOFIA_END_DECLS
index 86962b77fc9cd2b9159c64ed63aa2c21fe2635be..5fd9e98b0af35e75916aa5734af378c8918b5589 100644 (file)
@@ -354,21 +354,109 @@ SOFIAPUBFUN int sip_is_allowed(sip_allow_t const *allow,
   (sip_method_unknown < (method) && (method) < 32 && \
    (allow) && ((allow)->k_bitmap & (1 << (method))) != 0)
 
-/* ---------------------------------------------------------------------------
- * Bitmasks for header classifications
+/**
+ * Bitmasks for header classifications.
+ *
+ * If parsing of a particular header fails, the error bits in #msg_t are
+ * updated. The error bits can be obtained via msg_extract_errors() after
+ * parsing. The header-specific bits are stored along with the
+ * @ref msg_hclass_t "header class" in the #msg_href_t structure, found in
+ * the parser tables of the #msg_mclass_t object.
+ *
+ * @sa NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(),
+ * #msg_mclass_t, struct #msg_mclass_s, msg_mclass_clone(),
+ * msg_mclass_insert_with_mask(),
+ * #msg_href_t, struct #msg_href_s, msg_mclass_insert().
  */
-enum {
-  sip_mask_request = 1,
-  sip_mask_response = 2,
-  sip_mask_ua = 4,
-  sip_mask_proxy = 8,
-  sip_mask_registrar = 16,
-  sip_mask_100rel = 32,
-  sip_mask_events = 64,
-  sip_mask_timer = 128,
-  sip_mask_privacy = 256,
-  sip_mask_pref = 512,
-  sip_mask_publish = 1024
+enum sip_bad_mask {
+  /** Bit marking essential headers in a request message.
+   *
+   * @ref sip_request \"request line\"", @From, @To, @CSeq, @CallID,
+   * @ContentLength, @Via
+   */
+  sip_mask_request = (1 << 0),
+
+  /** Bit marking essential headers in a response message.
+   *
+   * @ref sip_status \"status line\"", @From, @To, @CSeq, @CallID,
+   * @ContentLength, @Via
+   */
+  sip_mask_response = (1 << 1),
+
+  /** Bit marking essential headers for User-Agent.
+   *
+   * @ContentType, @ContentDisposition, @ContentEncoding, @Supported,
+   * @Contact, @Require, and @RecordRoute.
+   */
+  sip_mask_ua = (1 << 2),
+
+  /** Bit marking essential headers for proxy server.
+   *
+   * @Route, @MaxForwards, @ProxyRequire, @ProxyAuthorization, @Supported,
+   * @Contact, and @RecordRoute.
+   */
+  sip_mask_proxy = (1 << 3),
+
+  /** Bit marking essential headers for registrar server.
+   *
+   * @MinExpires, @Authorization, @Path, @Supported, @Contact, @Require, and
+   * @Expires.
+   * 
+   */
+  sip_mask_registrar = (1 << 4),
+
+  /** Bit marking essential headers for 100rel extension.
+   *
+   * @RAck and @RSeq.
+   *
+   * @sa @RFC3262.
+   */
+  sip_mask_100rel = (1 << 5),
+
+  /** Bit marking essential headers for SIP events.
+   *
+   * @Event, @Expires, and @SubscriptionState.
+   * 
+   * @sa @RFC3265.
+   */
+  sip_mask_events = (1 << 6),
+
+  /** Bit marking essential headers for session timer extension.
+   *
+   * @SessionExpires, and @MinSE.
+   * 
+   * @RFC4028
+   */
+  sip_mask_timer = (1 << 7),
+
+  /** Bit marking essential headers for privacy extension.
+   *
+   * @Privacy.
+   * 
+   * @sa @RFC3323
+   */
+  sip_mask_privacy = (1 << 8),
+
+  /** Bit marking essential headers for caller preference extension.
+   *
+   * @RequestDisposition, @AcceptContact, and @RejectContact.
+   * 
+   * @sa @RFC3841.
+   */
+  sip_mask_pref = (1 << 9),
+
+  /** Bit marking essential headers for PUBLISH servers and clients.
+   *
+   * @SIPEtag, and @SIPIfMatch.
+   * 
+   * @sa @RFC3903.
+   */
+  sip_mask_publish = (1 << 10)
+
+  /* NOTE:
+   * When adding bits, please update nta_agent_create() and 
+   * NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation.
+   */
 };
 
 /* ------------------------------------------------------------------------- */
index 90462095bedb35ac8a8b48b0585c40d874eb54d1..006979fdf9a607028c1ecaa51bb1646b1ae42ef8 100644 (file)
@@ -694,6 +694,40 @@ int test_basic(void)
     su_free(home, ci0);
   }
 
+  {
+    sip_alert_info_t *ai, *ai0;
+
+    TEST_1(ai = sip_alert_info_make(home, "<http://www.nokia.com/ringtone.mp3>;x-format=mp3"));
+    TEST_1(ai0 = sip_alert_info_dup(home, ai));
+
+    TEST(msg_header_remove_param(ai->ai_common, "x-format"), 1);
+    TEST(msg_header_remove_param(ai0->ai_common, "x-format"), 1);
+
+    su_free(home, ai);
+    su_free(home, ai0);
+  }
+
+  {
+    sip_reply_to_t *rplyto, *rplyto0;
+
+    TEST_1(rplyto = sip_reply_to_make(home, "sip:joe@bar"));
+    TEST_1(msg_header_add_param(home, (msg_common_t *)rplyto, "x-extra=extra") == 0);
+    while (rplyto->rplyto_params && rplyto->rplyto_params[0])
+      msg_header_remove_param(rplyto->rplyto_common, rplyto->rplyto_params[0]);
+    su_free(home, rplyto);
+
+    TEST_1(!sip_reply_to_make(home, (void *)"sip:joe@[baa"));
+
+    TEST_1(rplyto = sip_reply_to_make(home, (void *)"sip:joe@bar"));
+    su_free(home, rplyto);
+
+    TEST_1(rplyto = sip_reply_to_make(home, (void *)"Joe <sip:joe@bar;user=ip>;x-extra=extra"));
+    TEST_1(rplyto0 = sip_reply_to_dup(home, rplyto));
+    su_free(home, rplyto);
+    su_free(home, rplyto0);
+  }
+
+
   su_home_check(home);
   su_home_zap(home);
 
@@ -891,6 +925,8 @@ static int test_encoding(void)
     "Warning: 399 presence.bar:5060 \"Unimplemented filter\"\r\n"
     "RSeq: 421414\r\n"
     "Refer-To: <sip:hsdf@cdwf.xcfw.com?Subject=test&Organization=Bar>\r\n"
+    "Alert-Info: <http://alert.example.org/test.mp3>\r\n"                   
+    "Reply-To: Bob <sip:bob@example.com>\r\n"               
     "WWW-Authenticate: Digest realm=\"foo\"\r\n"
     "Proxy-Authenticate: Digest realm=\"foo\"\r\n"
     "Security-Server: tls;q=0.2\r\n"
@@ -1555,6 +1591,10 @@ static int parser_test(void)
 
   TEST_SIZE(sip_error_info_class->hc_params, 
            offsetof(sip_error_info_t, ei_params));
+  TEST_SIZE(sip_alert_info_class->hc_params, 
+           offsetof(sip_alert_info_t, ai_params));
+  TEST_SIZE(sip_reply_to_class->hc_params, 
+           offsetof(sip_reply_to_t, rplyto_params));
   TEST_SIZE(sip_warning_class->hc_params, 0);
                       
   TEST_SIZE(sip_mime_version_class->hc_params, 0);
index 7848559cb27a81234107446e7857e692f0ffe8ec..cdaebb49367232ce1b8d8478868747b1a764cecf 100644 (file)
@@ -122,7 +122,7 @@ static int soa_set_sdp(soa_session_t *ss,
  * The SOA_DEBUG environment variable is used to determine the default
  * debug logging level. The normal level is 3.
  *
- * @sa <su_debug.h>, su_log_global, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, su_log_global, SOFIA_DEBUG
  */
 extern char const SOA_DEBUG[];
 
index 638e2812f3a0d32a24c4ad9b27a3fba4bf755fe3..42f02f130defa1409b387af489823f34ff41c04a 100644 (file)
@@ -41,6 +41,8 @@
 #endif
 
 #include <sofia-sip/soa.h>
+#include <sofia-sip/soa_tag.h>
+
 #include <sofia-sip/su_tag_class.h>
 #include <sofia-sip/sdp_tag.h>
 
index 8b4995a024b39f354fb76de8b584aab3b677b330..c3d539b25b79dc4b68161ad349e2cd5728877a75 100644 (file)
@@ -1423,6 +1423,10 @@ int main(int argc, char *argv[])
       usage(1);
   }
 
+#if HAVE_OPEN_C
+  tstflags |= tst_verbatim;
+#endif
+
   if (o_attach) {
     char line[10];
     printf("%s: pid %u\n", name, getpid());
@@ -1462,5 +1466,9 @@ int main(int argc, char *argv[])
 
   su_deinit();
 
+#if HAVE_OPEN_C
+  sleep(5);
+#endif
+
   return retval;
 }
index 96b9631389173b30063471d140402faea2e33cc9..aaea3137e21d58055f64bdaf11b95f55b801b479 100644 (file)
@@ -17,11 +17,9 @@ INCLUDES =           -I$(srcdir)/../url -I../url \
 
 noinst_LTLIBRARIES =   libsresolv.la
 
-check_PROGRAMS =       test_sresolv
+check_PROGRAMS =       torture_sresolv test_sresolv 
 
-TESTS =                run_test_sresolv
-
-TESTS_ENVIRONMENT =    $(SHELL)
+TESTS =                torture_sresolv run_test_sresolv 
 
 CLEANFILES =           resolv.conf error.conf named.conf.tmp \
                        .test_sresolv.api.conf.?????? \
index 4d05b15777daf862cef0721810f030ce7bb92ec4..7598bc2e65879df810df78947d66189493ca20bc 100644 (file)
@@ -60,7 +60,7 @@ typedef union sres_record sres_record_t;
 
 enum {
   /** Cache cleanup interval in seconds. */
-  SRES_CACHE_TIMER_INTERVAL = 30,
+  SRES_CACHE_TIMER_INTERVAL = 5,
 #define SRES_CACHE_TIMER_INTERVAL (SRES_CACHE_TIMER_INTERVAL)
 };
 
index 832bc565696c7c8392395bd94c8cdb635bb523de..96351d5668fad2128f8fa9143a5d8614e223737d 100644 (file)
@@ -557,7 +557,7 @@ static int m_get_domain(char *d, int n, sres_message_t *m, uint16_t offset);
  * The SRESOLV_DEBUG environment variable is used to determine the debug
  * logging level for @b sresolv module. The default level is 3.
  * 
- * @sa <su_debug.h>, sresolv_log, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, sresolv_log, SOFIA_DEBUG
  */
 #ifdef DOXYGEN
 extern char const SRESOLV_DEBUG[]; /* dummy declaration for Doxygen */
index f71fc862a11de26750421cfb8b789884f5d51bbd..8896b35250f80fcd92750f224b37ecedb57fdaa4 100644 (file)
@@ -65,6 +65,7 @@ typedef unsigned _int32 uint32_t;
 #include <sofia-sip/su_alloc.h>
 #include <sofia-sip/su_strlst.h>
 #include <sofia-sip/htable.h>
+#include <sofia-sip/heap.h>
 
 #include <stdlib.h>
 #include <stdarg.h>
@@ -86,19 +87,28 @@ typedef struct sres_rr_hash_entry_s sres_rr_hash_entry_t;
 
 HTABLE_DECLARE_WITH(sres_htable, ht, sres_rr_hash_entry_t, unsigned, size_t);
 
+typedef HEAP_TYPE sres_heap_t;
+
+HEAP_DECLARE(static inline, sres_heap_t, sres_heap_, sres_rr_hash_entry_t *);
+
 struct sres_rr_hash_entry_s {
-  unsigned int   rr_hash_key;
-  time_t         rr_received;
   sres_record_t *rr;
+  size_t         rr_heap_index;
+  time_t         rr_expires;
+  unsigned int   rr_hash_key;
 };
 
 #define SRES_HENTRY_HASH(e) ((e)->rr_hash_key)
 
+/* ---------------------------------------------------------------------- */
+/* Heap */
+
 struct sres_cache
 {
   su_home_t           cache_home[1];
   time_t              cache_cleaned;
   sres_htable_t       cache_hash[1];
+  sres_heap_t         cache_heap;
 };
 
 #define sr_refcount sr_record->r_refcount
@@ -109,7 +119,6 @@ struct sres_cache
 #define sr_class    sr_record->r_class
 #define sr_ttl      sr_record->r_ttl
 #define sr_rdlen    sr_record->r_rdlen
-#define sr_rdata    sr_generic->g_data
 
 /* ---------------------------------------------------------------------- */
 /* Internal prototypes */
@@ -126,7 +135,6 @@ static unsigned sres_hash_key(const char *string);
 
 HTABLE_PROTOS_WITH(sres_htable, ht, sres_rr_hash_entry_t, unsigned, size_t);
 
-
 /* ---------------------------------------------------------------------- */
 /* Public functions */
 
@@ -140,7 +148,8 @@ sres_cache_t *sres_cache_new(int n)
 
   if (cache) {
     su_home_threadsafe(cache->cache_home);
-    if (sres_htable_resize(cache->cache_home, cache->cache_hash, n) < 0)
+    if (sres_htable_resize(cache->cache_home, cache->cache_hash, n) < 0 ||
+       sres_heap_resize(cache->cache_home, &cache->cache_heap, 0) < 0)
       su_home_unref(cache->cache_home), cache = NULL;
   }
 
@@ -197,7 +206,7 @@ int sres_cache_get(sres_cache_t *cache,
     rr = (*rr_iter)->rr;
 
     if (rr != NULL &&
-       (uint32_t)(now - (*rr_iter)->rr_received) <= rr->sr_ttl &&
+       now <= (*rr_iter)->rr_expires &&
         (type == sres_qtype_any || rr->sr_type == type) &&
         rr->sr_name != NULL &&
         strcasecmp(rr->sr_name, domain) == 0) 
@@ -224,7 +233,7 @@ int sres_cache_get(sres_cache_t *cache,
     rr = (*rr_iter)->rr;
 
     if (rr != NULL &&
-       (uint32_t)(now - (*rr_iter)->rr_received) <= rr->sr_ttl &&
+       now <= (*rr_iter)->rr_expires &&
         (type == sres_qtype_any || rr->sr_type == type) &&
         rr->sr_name != NULL &&
         strcasecmp(rr->sr_name, domain) == 0) {
@@ -278,13 +287,13 @@ sres_cache_alloc_record(sres_cache_t *cache,
 }
 
 /** Free a record that has not been stored. */
-void sres_cache_free_record(sres_cache_t *cache, void *rr)
+void sres_cache_free_record(sres_cache_t *cache, void *_sr)
 {
-  sres_record_t *sr = rr;
+  sres_record_t *sr = _sr;
 
   if (sr) {
     assert(sr->sr_refcount == 0);
-    su_free(cache->cache_home, rr);
+    su_free(cache->cache_home, sr);
   }
 }
 
@@ -306,6 +315,12 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
   if (sres_htable_is_full(cache->cache_hash))
     sres_htable_resize(cache->cache_home, cache->cache_hash, 0);
 
+  if (sres_heap_is_full(cache->cache_heap))
+    if (sres_heap_resize(cache->cache_home, &cache->cache_heap, 0) < 0) {
+      UNLOCK(cache);
+      return;
+    }
+
   for (rr_iter = sres_htable_hash(cache->cache_hash, hash);
        (rr_hash_entry = *rr_iter); 
        rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
@@ -327,10 +342,12 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
       continue;
     
     /* There was an old entry in the cache.. Zap it, replace this with it */
-    rr_hash_entry->rr_received = now;
+    sres_heap_remove(cache->cache_heap, rr_hash_entry->rr_heap_index);
+    rr_hash_entry->rr_expires = now + rr->sr_ttl;
     rr_hash_entry->rr = rr;
     rr->sr_refcount++;
-    
+    sres_heap_add(cache->cache_heap, rr_hash_entry);
+
     _sres_cache_free_one(cache, or);
 
     UNLOCK(cache);
@@ -339,16 +356,19 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
   }
   
   rr_hash_entry = su_zalloc(cache->cache_home, sizeof(*rr_hash_entry));
+
   if (rr_hash_entry) {
     rr_hash_entry->rr_hash_key = hash;
-    rr_hash_entry->rr_received = now;
+    rr_hash_entry->rr_expires = now + rr->sr_ttl;
     rr_hash_entry->rr = rr;
     rr->sr_refcount++;
 
+    sres_heap_add(cache->cache_heap, rr_hash_entry);
+
     cache->cache_hash->ht_used++;
+
+    *rr_iter = rr_hash_entry;
   }
-  
-  *rr_iter = rr_hash_entry;
 
   UNLOCK(cache);
 }
@@ -417,6 +437,7 @@ sres_hash_key(const char *string)
   return result;
 }
 
+/** Remove entries from cache. */
 void sres_cache_clean(sres_cache_t *cache, time_t now)
 {
   size_t i;
@@ -424,27 +445,56 @@ void sres_cache_clean(sres_cache_t *cache, time_t now)
   if (now < cache->cache_cleaned + SRES_CACHE_TIMER_INTERVAL)
     return;
 
-  if (!LOCK(cache))
-    return;
-
   /* Clean cache from old entries */
-  cache->cache_cleaned = now;
 
-  for (i = 0; i < cache->cache_hash->ht_size; i++) {
-    sres_rr_hash_entry_t *e;
+  for (;;) {
+    if (!LOCK(cache))
+      return;
+
+    cache->cache_cleaned = now;
+
+    for (i = 0; i < 100; i++) {
+      sres_rr_hash_entry_t *e = sres_heap_get(cache->cache_heap, 1);
+
+      if (e == NULL || e->rr_expires >= now) {
+       UNLOCK(cache);
+       return;
+      }
       
-    while ((e = cache->cache_hash->ht_table[i]) != NULL) {
-      if ((uint32_t)(now - e->rr_received) <= e->rr->sr_ttl)
-       break;
-       
+      sres_heap_remove(cache->cache_heap, 1);
       sres_htable_remove(cache->cache_hash, e);
-      
       _sres_cache_free_one(cache, e->rr);
+      su_free(cache->cache_home, e);
     }
-  }
 
-  UNLOCK(cache);
+    UNLOCK(cache);
+  }
 }
 
 HTABLE_BODIES_WITH(sres_htable, ht, sres_rr_hash_entry_t, SRES_HENTRY_HASH,
                   unsigned, size_t);
+
+static inline
+int sres_heap_earlier_entry(sres_rr_hash_entry_t const *a,
+                           sres_rr_hash_entry_t const *b)
+{
+  return a->rr_expires < b->rr_expires;
+}
+
+static inline
+void sres_heap_set_entry(sres_rr_hash_entry_t **heap,
+                        size_t index, 
+                        sres_rr_hash_entry_t *entry)
+{
+  entry->rr_heap_index = index;
+  heap[index] = entry;
+}  
+
+HEAP_BODIES(static inline,
+           sres_heap_t,
+           sres_heap_,
+           sres_rr_hash_entry_t *,
+           sres_heap_earlier_entry,
+           sres_heap_set_entry,
+           su_realloc,
+           NULL);
index ee3900db9e8633124d1b09d3488194b105a93c69..686b0c4d3166a680812928c962b7a3633df6354d 100644 (file)
@@ -1152,7 +1152,7 @@ int test_cache(sres_context_t *ctx)
 
 #if HAVE_SIN6
   sres_query(res, test_answer_multi, ctx,
-                 sres_type_aaaa, "mgw02.example.com");
+            sres_type_aaaa, "mgw02.example.com");
 
   inet_pton(AF_INET6, 
             "3ffe:1200:3012:c000:0a08:20ff:fe7d:e7ac", 
@@ -1161,7 +1161,7 @@ int test_cache(sres_context_t *ctx)
   sin6.sin6_family = AF_INET6;
 
   query = sres_query_sockaddr(res, test_answer_multi, ctx,
-                                  sres_qtype_any, (struct sockaddr *)&sin6);
+                             sres_qtype_any, (struct sockaddr *)&sin6);
 
   TEST_1(query != NULL);
 #endif
@@ -1770,97 +1770,6 @@ int test_net(sres_context_t *ctx)
   END();
 }
 
-
-/* Test API function argument validation */
-static
-int test_api_errors(sres_context_t *noctx)
-{
-  sres_context_t ctx[1];
-  sres_resolver_t *res;
-  int s, fd;
-  int sockets[20];
-  struct sockaddr sa[1] = {{ 0 }};
-  char *template = NULL;
-  FILE *f;
-
-  BEGIN();
-
-  memset(ctx, 0, sizeof ctx);
-
-  template = su_sprintf(ctx->home, ".test_sresolv_api.conf.XXXXXX");
-  TEST_1(template);
-  
-  TEST_1(res = sres_resolver_new(NULL));
-  TEST(su_home_threadsafe((su_home_t *)res), 0);
-  TEST_VOID(sres_resolver_unref(res));
-
-#ifndef _WIN32
-  fd = mkstemp(template); TEST_1(fd != -1);
-#else
-  fd = open(template, O_WRONLY); TEST_1(fd != -1);
-#endif  
-
-  f = fdopen(fd, "w"); TEST_1(f);
-  fprintf(f, "domain example.com\n");
-  fclose(f);
-
-  /* Test also LOCALDOMAIN handling */
-  putenv("LOCALDOMAIN=localdomain");
-
-  TEST_1(res = sres_resolver_new(template));
-  TEST(su_home_threadsafe((su_home_t *)res), 0);
-
-  unlink(template);
-  
-  s = sockets[0];
-  
-  TEST_P(sres_resolver_ref(NULL), NULL);
-  TEST(errno, EFAULT);
-  sres_resolver_unref(NULL);
-
-  TEST_P(sres_resolver_set_userdata(NULL, NULL), NULL);
-  TEST(errno, EFAULT);
-
-  TEST_P(sres_resolver_get_userdata(NULL), NULL);
-
-  TEST_P(sres_resolver_get_userdata(res), NULL);
-  TEST_P(sres_resolver_set_userdata(res, sa), NULL);
-  TEST_P(sres_resolver_get_userdata(res), sa);
-  TEST_P(sres_resolver_set_userdata(res, NULL), sa); 
-  TEST_P(sres_resolver_get_userdata(res), NULL);
-
-  errno = 0;
-  TEST_P(sres_query(NULL, test_answer, ctx, sres_type_a, "com"), NULL);
-  TEST(errno, EFAULT); errno = 0;
-  TEST_P(sres_query(res, test_answer, ctx, sres_type_a, NULL), NULL);
-  TEST(errno, EFAULT); errno = 0;
-  TEST_P(sres_query_sockaddr(res, test_answer, ctx,
-                            sres_qtype_any, sa), NULL);
-  TEST(errno, EAFNOSUPPORT); errno = 0;
-
-  TEST_P(sres_cached_answers(NULL, sres_qtype_any, "example.com"), NULL);
-  TEST(errno, EFAULT); errno = 0;
-  TEST_P(sres_cached_answers(res, sres_qtype_any, NULL), NULL);
-  TEST(errno, EFAULT); errno = 0;
-  TEST_P(sres_cached_answers(res, sres_qtype_any, name2048), NULL);
-  TEST(errno, ENAMETOOLONG); errno = 0;
-  TEST_P(sres_cached_answers_sockaddr(res, sres_qtype_any, sa), NULL);
-  TEST(errno, EAFNOSUPPORT); errno = 0;
-
-  sres_free_answer(res, NULL);
-  sres_free_answers(res, NULL);
-  sres_sort_answers(res, NULL);
-
-  sres_free_answer(NULL, NULL);
-  sres_free_answers(NULL, NULL);
-  sres_sort_answers(NULL, NULL);
-
-  sres_resolver_unref(res);
-  
-  END();
-}
-
-
 static
 int test_init(sres_context_t *ctx, char const *conf_file)
 {
@@ -2087,8 +1996,6 @@ int main(int argc, char **argv)
     }
   }
 
-  error |= test_api_errors(ctx);
-
   return error;
 }
 
diff --git a/libs/sofia-sip/libsofia-sip-ua/sresolv/torture_sresolv.c b/libs/sofia-sip/libsofia-sip-ua/sresolv/torture_sresolv.c
new file mode 100644 (file)
index 0000000..a6c5408
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * This file is part of the Sofia-SIP package
+ *
+ * Copyright (C) 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
+ *
+ */
+
+/**@internal
+ *
+ * @CFILE torture_sresolv.c Torture tests for Sofia resolver.
+ * 
+ * @author Mikko Haataja
+ * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
+ */
+
+#include "config.h"
+
+#if HAVE_STDINT_H
+#include <stdint.h>
+#elif HAVE_INTTYPES_H
+#include <inttypes.h>
+#else
+#if defined(_WIN32)
+typedef unsigned _int8 uint8_t;
+typedef unsigned _int16 uint16_t;
+typedef unsigned _int32 uint32_t;
+#endif
+#endif
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+#if HAVE_WINSOCK2_H
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
+
+#include <sofia-resolv/sres.h>
+#include <sofia-resolv/sres_async.h>
+#include <sofia-resolv/sres_record.h>
+#include <sofia-resolv/sres_cache.h>
+
+#include <sofia-sip/su_alloc.h>
+
+#include <time.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#if HAVE_ALARM
+#include <signal.h>
+#endif
+
+#define TSTFLAGS tstflags
+int tstflags, o_timing;
+
+#include <sofia-sip/tstdef.h>
+
+char const name[] = "torture_sresolv";
+
+struct sres_context_s
+{
+  su_home_t        home[1];
+};
+
+static void test_answer(sres_context_t *ctx,
+                       sres_query_t *q,
+                       sres_record_t **answer)
+{
+}
+
+static char name2048[2049] = 
+  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+  "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+  "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+  "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+  "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+  "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
+
+  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+  "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+  "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+  "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+  "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+  "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
+
+  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+  "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+  "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+  "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+  "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+  "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
+
+  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+  "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
+  "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+  "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+  "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
+  "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+  "gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
+  "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
+
+/* Test API function argument validation */
+static
+int test_api_errors(void)
+{
+  sres_context_t ctx[1];
+  sres_resolver_t *res;
+  int s, fd;
+  int sockets[20];
+  struct sockaddr sa[1] = {{ 0 }};
+  char *template = NULL;
+  FILE *f;
+
+  BEGIN();
+
+  memset(ctx, 0, sizeof ctx);
+
+  template = su_sprintf(ctx->home, ".torture_sresolv_api.conf.XXXXXX");
+  TEST_1(template);
+  
+  TEST_1(res = sres_resolver_new(NULL));
+  TEST(su_home_threadsafe((su_home_t *)res), 0);
+  TEST_VOID(sres_resolver_unref(res));
+
+#ifndef _WIN32
+  fd = mkstemp(template); TEST_1(fd != -1);
+#else
+  fd = open(template, O_WRONLY); TEST_1(fd != -1);
+#endif  
+
+  f = fdopen(fd, "w"); TEST_1(f);
+  fprintf(f, "domain example.com\n");
+  fclose(f);
+
+  /* Test also LOCALDOMAIN handling */
+  putenv("LOCALDOMAIN=localdomain");
+
+  TEST_1(res = sres_resolver_new(template));
+  TEST(su_home_threadsafe((su_home_t *)res), 0);
+
+  unlink(template);
+  
+  s = sockets[0];
+  
+  TEST_P(sres_resolver_ref(NULL), NULL);
+  TEST(errno, EFAULT);
+  sres_resolver_unref(NULL);
+
+  TEST_P(sres_resolver_set_userdata(NULL, NULL), NULL);
+  TEST(errno, EFAULT);
+
+  TEST_P(sres_resolver_get_userdata(NULL), NULL);
+
+  TEST_P(sres_resolver_get_userdata(res), NULL);
+  TEST_P(sres_resolver_set_userdata(res, sa), NULL);
+  TEST_P(sres_resolver_get_userdata(res), sa);
+  TEST_P(sres_resolver_set_userdata(res, NULL), sa); 
+  TEST_P(sres_resolver_get_userdata(res), NULL);
+
+  errno = 0;
+  TEST_P(sres_query(NULL, test_answer, ctx, sres_type_a, "com"), NULL);
+  TEST(errno, EFAULT); errno = 0;
+  TEST_P(sres_query(res, test_answer, ctx, sres_type_a, NULL), NULL);
+  TEST(errno, EFAULT); errno = 0;
+  TEST_P(sres_query_sockaddr(res, test_answer, ctx,
+                            sres_qtype_any, sa), NULL);
+  TEST(errno, EAFNOSUPPORT); errno = 0;
+
+  TEST_P(sres_cached_answers(NULL, sres_qtype_any, "example.com"), NULL);
+  TEST(errno, EFAULT); errno = 0;
+  TEST_P(sres_cached_answers(res, sres_qtype_any, NULL), NULL);
+  TEST(errno, EFAULT); errno = 0;
+  TEST_P(sres_cached_answers(res, sres_qtype_any, name2048), NULL);
+  TEST(errno, ENAMETOOLONG); errno = 0;
+  TEST_P(sres_cached_answers_sockaddr(res, sres_qtype_any, sa), NULL);
+  TEST(errno, EAFNOSUPPORT); errno = 0;
+
+  sres_free_answer(res, NULL);
+  sres_free_answers(res, NULL);
+  sres_sort_answers(res, NULL);
+
+  sres_free_answer(NULL, NULL);
+  sres_free_answers(NULL, NULL);
+  sres_sort_answers(NULL, NULL);
+
+  sres_resolver_unref(res);
+  
+  END();
+}
+
+extern void sres_cache_clean(sres_cache_t *cache, time_t now);
+
+static
+int test_cache(void)
+{
+  BEGIN();
+  sres_a_record_t *a, a0[1], **all;
+  char host[128];
+  sres_cache_t *cache;
+  time_t now, base;
+  struct timespec t0, t1, t2;
+
+  size_t i, N, N1 = 1000, N3 = 1000000;
+
+  time(&base);
+
+  cache = sres_cache_new(N1);
+  TEST_1(cache);
+
+  all = calloc(N3, sizeof *all); if (!all) perror("calloc"), exit(2);
+
+  memset(a0, 0, sizeof a0);
+
+  a0->a_record->r_refcount = 1;
+  a0->a_record->r_size = sizeof *a;
+  a0->a_record->r_type = sres_type_a;
+  a0->a_record->r_class = sres_class_in;
+  a0->a_record->r_ttl = 3600;
+  a0->a_record->r_rdlen = sizeof a->a_addr;
+  a0->a_record->r_parsed = 1;
+
+  for (i = 0, N = N3; i < N; i++) {
+    a0->a_record->r_name = host;
+
+    snprintf(host, sizeof host, "%u.example.com.", (unsigned)i);
+
+    a = (sres_a_record_t *)
+      sres_cache_alloc_record(cache, (sres_record_t *)a0, 0);
+
+    if (!a)
+      perror("sres_cache_alloc_record"), exit(2);
+
+    all[i] = a, a->a_record->r_refcount = 1;
+  }
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
+
+  for (i = 0, N = N3; i < N; i++) {
+    now = base + (3600 * i + N / 2) / N;
+    a->a_record->r_ttl = 60 + (i * 60) % 3600;
+    sres_cache_store(cache, (sres_record_t *)all[i], now);
+  }
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
+  if (o_timing) {
+    t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
+    if (t1.tv_nsec < t0.tv_nsec)
+      t2.tv_sec--, t2.tv_nsec += 1000000000;
+    printf("sres_cache: stored %u entries: %lu.%09lu sec\n", 
+          N, t2.tv_sec, t2.tv_nsec);
+  }
+
+  for (i = 0, N; i < N; i++)
+    TEST(all[i]->a_record->r_refcount, 2);
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
+
+  for (now = base; now <= base + 3660; now += 30)
+    sres_cache_clean(cache, now + 3600);
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
+  if (o_timing) {
+    t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
+    if (t1.tv_nsec < t0.tv_nsec)
+      t2.tv_sec--, t2.tv_nsec += 1000000000;
+    printf("sres_cache: cleaned %u entries: %lu.%09lu sec\n", 
+          N, t2.tv_sec, t2.tv_nsec);
+  }
+
+  for (i = 0, N; i < N; i++)
+    TEST(all[i]->a_record->r_refcount, 1);
+
+  base += 24 * 3600;
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
+
+  for (i = 0, N; i < N; i++) {
+    now = base + (3600 * i + N / 2) / N;
+    a->a_record->r_ttl = 60 + (i * 60) % 3600;
+    sres_cache_store(cache, (sres_record_t *)all[i], now);
+  }
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
+  if (o_timing) {
+    t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
+    if (t1.tv_nsec < t0.tv_nsec)
+      t2.tv_sec--, t2.tv_nsec += 1000000000;
+    printf("sres_cache: stored %u entries: %lu.%09lu sec\n", 
+          N, t2.tv_sec, t2.tv_nsec);
+  }
+
+  for (i = 0, N; i < N; i++)
+    TEST(all[i]->a_record->r_refcount, 2);
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
+
+  for (now = base; now <= base + 3660; now += 1)
+    sres_cache_clean(cache, now + 3600);
+
+  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
+  
+  if (o_timing) {
+    t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
+    if (t1.tv_nsec < t0.tv_nsec)
+      t2.tv_sec--, t2.tv_nsec += 1000000000;
+    printf("sres_cache: cleaned %u entries: %lu.%09lu sec\n", 
+          N, t2.tv_sec, t2.tv_nsec);
+  }
+
+  for (i = 0, N; i < N; i++) {
+    TEST(all[i]->a_record->r_refcount, 1);
+    sres_cache_free_one(cache, (sres_record_t *)all[i]);
+  }
+
+  sres_cache_unref(cache);
+
+  free(all);
+
+  END();
+}
+
+
+#if HAVE_ALARM
+static RETSIGTYPE sig_alarm(int s)
+{
+  fprintf(stderr, "%s: FAIL! test timeout!\n", name);
+  exit(1);
+}
+#endif
+
+void usage(int exitcode)
+{
+  fprintf(stderr, 
+         "usage: %s OPTIONS [-]\n"
+         "\twhere OPTIONS are\n"
+         "\t    -v be verbose\n"
+         "\t    -a abort on error\n"
+         "\t    -t show timing\n"
+         "\r    --no-alarm  disable timeout\n"
+         "\t    -llevel set debugging level\n",
+         name);
+  exit(exitcode);
+}
+
+#include <sofia-sip/su_log.h>
+
+extern su_log_t sresolv_log[];
+
+int main(int argc, char **argv)
+{
+  int i;
+  int error = 0;
+  int o_alarm = 1;
+
+  for (i = 1; argv[i]; i++) {
+    if (argv[i][0] != '-')
+      break;
+    else if (strcmp(argv[i], "-") == 0) {
+      i++; break;
+    }
+    else if (strcmp(argv[i], "-v") == 0)
+      tstflags |= tst_verbatim;
+    else if (strcmp(argv[i], "-a") == 0)
+      tstflags |= tst_abort;
+    else if (strcmp(argv[i], "-t") == 0)
+      o_timing = 1;
+    else if (strcmp(argv[i], "--no-alarm") == 0) {
+      o_alarm = 0;
+    }
+    else if (strncmp(argv[i], "-l", 2) == 0) {
+      int level = 3;
+      char *rest = NULL;
+
+      if (argv[i][2])
+       level = strtol(argv[i] + 2, &rest, 10);
+      else if (argv[i + 1])
+       level = strtol(argv[i + 1], &rest, 10), i++;
+      else
+       level = 3, rest = "";
+
+      if (rest == NULL || *rest)
+       usage(1);
+      
+      su_log_set_level(sresolv_log, level);
+    }
+    else
+      usage(1);
+  }
+
+#if HAVE_ALARM
+  if (o_alarm) {
+    alarm(60);
+    signal(SIGALRM, sig_alarm); 
+  }
+#endif
+
+  if (!(TSTFLAGS & tst_verbatim)) {
+    su_log_soft_set_level(sresolv_log, 0);
+  }
+
+  error |= test_api_errors();
+  error |= test_cache();
+
+  return error;
+}
index 59423b2402fdb0e549ea4127fa64b0954db48c54..28e6178bc9761ff4a369eadfcb79a72018882d93 100644 (file)
@@ -36,6 +36,7 @@
 #define TAG_NAMESPACE "stun"
 
 #include <sofia-sip/su_tag_class.h>
+#include <sofia-sip/stun_tag.h>
 
 /**@def STUNTAG_ANY()
  * 
@@ -159,7 +160,7 @@ tag_typedef_t stuntag_register_events = BOOLTAG_TYPEDEF(register_events);
  *    int (stun_action_t)
  *
  * @par Values
- *    See types for stun_action_t in stun.h
+ *    See types for stun_action_t in <sofia-sip/stun.h>
  *
  * Corresponding tag taking reference parameter is STUNTAG_ACTION_REF()
  */
index b46e383de959d762dab807faa28ecf5c6db53f6c..7278479ad8c24b876c79cdb3d3bebae140ac49b5 100644 (file)
@@ -8,6 +8,7 @@ INPUT                = @srcdir@/su.docs @srcdir@/sofia-sip sofia-sip @srcdir@ .
 
 TAGFILES           += ../docs/msg.doxytags=../msg
 TAGFILES           += ../docs/sip.doxytags=../sip
+TAGFILES           += ../docs/utils.doxytags=../utils
 TAGFILES           += ../docs/docs.doxytags=..
 
 GENERATE_TAGFILE     = ../docs/su.doxytags
index 8a60cfdde0e7f105b96f736d234d09499a677a54..37af9bae38c675cd67533747cf62c5450beb384c 100644 (file)
@@ -16,23 +16,9 @@ noinst_LTLIBRARIES =         libsu.la
 
 bin_PROGRAMS =                 addrinfo localinfo 
 
-if COREFOUNDATION
-OSXSOURCES = \
-       su_osx_runloop.c
-OSXHEADERS = \
-       sofia-sip/su_osx_runloop.h
-OSXPROGS = \
-       torture_su_root_osx test_su_osx
-OSXTESTS = \
-       torture_su_root_osx run_test_su_osx
-else
-OSXSOURCES =
-OSXHEADERS =
-endif
-
 check_PROGRAMS =       torture_su torture_su_port \
                        torture_su_alloc torture_su_time torture_su_tag \
-                       test_htable torture_rbtree \
+                       test_htable torture_rbtree torture_heap \
                        test_memmem torture_su_bm \
                        torture_su_root torture_su_timer \
                        test_su su_proxy test_poll $(OSXPROGS)
@@ -42,7 +28,7 @@ check_PROGRAMS =      torture_su torture_su_port \
 
 TESTS =                torture_su torture_su_port \
                        torture_su_alloc torture_su_time torture_su_tag \
-                       test_htable torture_rbtree \
+                       test_htable torture_rbtree torture_heap \
                        test_memmem torture_su_bm \
                        torture_su_root torture_su_timer \
                        run_addrinfo run_localinfo run_test_su \
@@ -63,8 +49,8 @@ nobase_include_sofia_HEADERS = \
                        sofia-sip/su_tag_class.h sofia-sip/su_tagarg.h \
                        sofia-sip/su_tag_io.h sofia-sip/su_tag_inline.h \
                        sofia-sip/htable.h sofia-sip/htable2.h \
-                       sofia-sip/rbtree.h sofia-sip/su_debug.h \
-                       sofia-sip/su_log.h \
+                       sofia-sip/rbtree.h sofia-sip/heap.h \
+                       sofia-sip/su_debug.h sofia-sip/su_log.h \
                        sofia-sip/su_config.h sofia-sip/su_md5.h \
                        sofia-sip/su_uniqueid.h sofia-sip/su_bm.h \
                        sofia-sip/tstdef.h sofia-sip/su_os_nw.h \
@@ -122,3 +108,15 @@ AUTOMAKE_OPTIONS =         foreign
 # Sofia specific rules
 
 include $(top_srcdir)/rules/sofia.am
+
+# ----------------------------------------------------------------------
+# OS X stuff
+
+if COREFOUNDATION
+OSXSOURCES =  su_osx_runloop.c
+OSXHEADERS =  sofia-sip/su_osx_runloop.h
+OSXPROGS =    torture_su_root_osx test_su_osx
+OSXTESTS =    torture_su_root_osx run_test_su_osx
+endif
+
+EXTRA_DIST += su_osx_runloop.c sofia-sip/su_osx_runloop.h
diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/heap.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/heap.h
new file mode 100644 (file)
index 0000000..9b69a5e
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * This file is part of the Sofia-SIP package
+ *
+ * Copyright (C) 2007 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
+ *
+ */
+
+#ifndef SOFIA_SIP_HEAP_H
+/** Defined when <sofia-sip/heap.h> has been included. */
+#define SOFIA_SIP_HEAP_H
+
+/**@file sofia-sip/heap.h
+ *
+ * Heap template implemented with dynamic array.
+ *
+ * This file contain template macros implementing @a heap in C. The @a heap
+ * keeps its element in a known order and it can be used to implement, for
+ * example, a prioritye queue or an ordered queue. 
+ *
+ * The ordering within the heap is defined as follows:
+ * - indexing starts from 1
+ * - for each element with index @a [i] in the heap there are two descendant
+ *   elements with indices @a [2*i] and @a [2*i+1],
+ * - the heap guarantees that the descendant elements are never smaller than
+ *   their parent element.
+ * Therefore it follows that there is no element smaller than element at
+ * index [1] in the rest of the heap.
+ *
+ * Adding and removing elements to the heap is an @a O(logN)
+ * operation.
+ *
+ * The heap array is resizeable, and it usually contain pointers to the
+ * actual entries. The template macros define two functions used to add and
+ * remove entries to the heap. The @a add() function takes the element to be
+ * added as its argument, the @a remove() function the index of the element
+ * to be removed. The template defines also a predicate used to check if the
+ * heap is full, and a function used to resize the heap.
+ *
+ * The heap user must define four primitives: 
+ * - less than comparison 
+ * - array setter
+ * - heap array allocator
+ * - empty element
+ *
+ * Please note that in order to remove an entry in the heap, the application
+ * must know its index in the heap array. 
+ *
+ * The heap struct is declared with macro HEAP_DECLARE(). The prototypes for
+ * heap functions are instantiated with macro HEAP_PROTOS(). The
+ * implementation is instantiated with macro HEAP_BODIES().
+ *
+ * Example code can be found from <su/torture_heap.c> and
+ * <sresolv/sres_cache.c>.
+ * 
+ * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
+ * @NEW_1_12_7.
+ */
+
+/** Minimum size of heap */
+#define HEAP_MIN_SIZE 31
+
+/** Declare heap structure type.
+ * 
+ * The macro #HEAP_TYPE contains declaration of the heap structure.
+ * 
+ * @showinitializer
+ */
+#define HEAP_TYPE struct { void *private; }
+
+/** Prototypes for heap.
+ *
+ * The macro HEAP_PROTOS() expands to the prototypes of heap functions:
+ * - prefix ## resize(argument, in_out_heap, size)
+ * - prefix ## free(argument, in_heap)
+ * - prefix ## is_full(heap)
+ * - prefix ## size(heap)
+ * - prefix ## used(heap)
+ * - prefix ## add(heap, entry)
+ * - prefix ## remove(heap, index)
+ * - prefix ## get(heap, index)
+ *
+ * @param scope     scope of functions
+ * @param heaptype  type of heap
+ * @param prefix    function prefix
+ * @param type      type of entries
+ * 
+ * The declared functions will have scope @a scope (for example, @c static
+ * or @c static inline). The declared function names will have prefix @a
+ * prefix. The heap structure has type @a heaptype. The heap element type is
+ * @a entrytype.
+ *
+ * @showinitializer
+ */
+#define HEAP_DECLARE(scope, heaptype, prefix, type) \
+scope int prefix##resize(void *, heaptype *, size_t); \
+scope int prefix##free(void *, heaptype *); \
+scope int prefix##is_full(heaptype const); \
+scope size_t prefix##size(heaptype const); \
+scope size_t prefix##used(heaptype const); \
+scope int prefix##add(heaptype, type); \
+scope type prefix##remove(heaptype, size_t); \
+scope type prefix##get(heaptype, size_t)
+
+/**Heap implementation.
+ *
+ * The macro HEAP_BODIES() expands to the bodies of heap functions:
+ * - prefix ## resize(argument, heap, size)
+ * - prefix ## free(argument, in_heap)
+ * - prefix ## is_full(heap)
+ * - prefix ## size(heap)
+ * - prefix ## used(heap)
+ * - prefix ## add(heap, entry)
+ * - prefix ## remove(heap, index)
+ * - prefix ## get(heap, index)
+ *
+ * @param scope     scope of functions
+ * @param prefix    function prefix for heap
+ * @param type      type of heaped elements
+ * @param less      function or macro comparing two entries
+ * @param set       function or macro assigning entry to array
+ * @param alloc     function allocating or freeing memory
+ * @param null      empty element (returned when index is invalid)
+ *
+ * Functions have scope @a scope, e.g., @c static @c inline.
+ * The heap structure has type @a type.
+ * The function names start with @a prefix, the field names start
+ * with @a pr. The entry type is @a entrytype. 
+
+ * The function (or macro) @a less compares two entries in heap. It gets two
+ * arguments and it returns true if its left argument is less than its right
+ * argument.
+
+ * The function (or macro) @a set stores an entry in heap array. It gets
+ * three arguments, first is heap array, second index to the array and third
+ * the element to store at the given index.
+ *
+ * The function (or macro) @a halloc re-allocates the heap array. It
+ * receives three arguments, first is the first @a argument given to @a
+ * resize(), second the pointer to existing heap and third is the number of
+ * bytes in the heap.
+ */
+#define HEAP_BODIES(scope, heaptype, prefix, type, less, set, alloc, null) \
+scope int prefix##resize(void *realloc_arg, heaptype h[1], size_t new_size) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[2]; }; \
+  struct prefix##priv *_priv; \
+  size_t _offset = \
+    (offsetof(struct prefix##priv, _heap[1]) - 1) / sizeof (type); \
+  size_t _min_size = 32 - _offset; \
+  size_t _bytes; \
+  size_t _used = 0; \
+ \
+  _priv = *(void **)h; \
+ \
+  if (_priv) { \
+    if (new_size == 0) \
+      new_size = 2 * _priv->_size + _offset + 1; \
+    _used = _priv->_used; \
+    if (new_size < _used) \
+      new_size = _used; \
+  } \
+ \
+  if (new_size < _min_size) \
+    new_size = _min_size; \
+ \
+  _bytes = (_offset + 1 + new_size) * sizeof (type); \
+ \
+  (void)realloc_arg; /* avoid warning */ \
+  _priv = alloc(realloc_arg, *(struct prefix##priv **)h, _bytes); \
+  if (!_priv) \
+    return -1; \
+ \
+  *(struct prefix##priv **)h = _priv; \
+  _priv->_size = new_size; \
+  _priv->_used = _used; \
+ \
+  return 0; \
+} \
+ \
+/** Free heap. */ \
+scope int prefix##free(void *realloc_arg, heaptype h[1]) \
+{ \
+  (void)realloc_arg; \
+  *(void **)h = alloc(realloc_arg, *(void **)h, 0); \
+  return 0; \
+} \
+ \
+/** Check if heap is full */ \
+scope int prefix##is_full(heaptype h) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];}; \
+  struct prefix##priv *_priv = *(void **)&h; \
+ \
+  return _priv == NULL || _priv->_used >= _priv->_size; \
+} \
+ \
+/** Add an element to the heap */ \
+scope int prefix##add(heaptype h, type e) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];};  \
+  struct prefix##priv *_priv = *(void **)&h; \
+  type *heap = _priv->_heap - 1; \
+  size_t i, parent; \
+ \
+  if (_priv == NULL || _priv->_used >= _priv->_size) \
+    return -1; \
+ \
+  for (i = ++_priv->_used; i > 1; i = parent) { \
+    parent = i / 2; \
+    if (!less(e, heap[parent])) \
+      break; \
+    set(heap, i, heap[parent]); \
+  } \
+ \
+  set(heap, i, e); \
+ \
+  return 0; \
+} \
+ \
+/** Remove element from heap */ \
+scope type prefix##remove(heaptype h, size_t index) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];}; \
+  struct prefix##priv *_priv = *(void **)&h; \
+  type *heap = _priv->_heap - 1; \
+  type retval; \
+  type e; \
+ \
+  size_t top, left, right, move; \
+ \
+  move = _priv->_used; \
+ \
+  if (index - 1 >= _priv->_used) \
+    return (null); \
+ \
+  move = _priv->_used--; \
+  retval = heap[top = index]; \
+ \
+  for (;;) { \
+    left = 2 * top; \
+    right = 2 * top + 1; \
+ \
+    if (right >= move) \
+      break; \
+    if (less(heap[right], heap[left])) \
+      top = right; \
+    else \
+      top = left; \
+    set(heap, index, heap[top]); \
+    index = top; \
+  } \
+ \
+  if (index == move) \
+    return retval; \
+ \
+  e = heap[move]; \
+  for (; index > 1; index = top) { \
+    top = index / 2; \
+    if (!less(e, heap[top])) \
+      break; \
+    set(heap, index, heap[top]); \
+  } \
+ \
+  set(heap, index, e); \
+ \
+  return retval; \
+} \
+ \
+scope \
+type prefix##get(heaptype h, size_t index) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];}; \
+  struct prefix##priv *_priv = *(void **)&h; \
+ \
+  if (--index >= _priv->_used) \
+    return (null); \
+ \
+  return _priv->_heap[index]; \
+} \
+ \
+scope \
+size_t prefix##size(heaptype const h) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];}; \
+  struct prefix##priv *_priv = *(void **)&h; \
+  return _priv ? _priv->_size : 0; \
+} \
+ \
+scope \
+size_t prefix##used(heaptype const h) \
+{ \
+  struct prefix##priv { size_t _size, _used; type _heap[1];}; \
+  struct prefix##priv *_priv = *(void **)&h; \
+  return _priv ? _priv->_used : 0; \
+} \
+extern int const prefix##dummy_heap
+
+#endif /** !defined(SOFIA_SIP_HEAP_H) */
index 92e31dd24dcb10b019d2266894b62801c28d0b87..277caad6bd54385fa7cc069b0ef05f37239c647d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Sofia-SIP package
  *
- * Copyright (C) 2005 Nokia Corporation.
+ * Copyright (C) 2005,2006,2007 Nokia Corporation.
  *
  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  *
 #if SU_HAVE_WINSOCK            /* Windows includes */
 #  include <winsock2.h>
 #  include <ws2tcpip.h>
-
-#  if defined(IPPROTO_IPV6)
-/* IPv6 defined in ws2tcpip.h */
-#  elif SU_HAVE_IN6 
-#    include <tpipv6.h>                /* From "IPv6 Tech Preview"  */
-#  else
-#    error Winsock with IPv6 support required
+#  if SU_HAVE_IN6
+#    if defined(IPPROTO_IPV6)
+/*     case 1: IPv6 defined in winsock2.h/ws2tcpip.h */
+#    else
+/*     case 2: try to use "IPv6 Tech Preview" */
+#      include <tpipv6.h>              
+#    endif
 #  endif
-
 #endif
 
 SOFIA_BEGIN_DECLS
@@ -95,6 +94,9 @@ enum {
   /** Return code for an unsuccessful call */
   su_failure = -1
 };
+#if SYMBIAN && !defined(MSG_NOSIGNAL)
+#define MSG_NOSIGNAL (0)
+#endif
 #elif SU_HAVE_WINSOCK
 enum { 
   su_success = 0, 
@@ -274,7 +276,9 @@ SOFIAPUBFUN int su_close(su_socket_t s);
 /** Control socket. */
 SOFIAPUBFUN int su_ioctl(su_socket_t s, int request, ...);
 
-/** Checks if the @a errcode indicates that the socket call failed because
+/**Check for in-progress error codes.
+ * 
+ * Checks if the @a errcode indicates that the socket call failed because
  * it would have blocked.
  *
  * Defined as macro with POSIX sockets.
index 0365958836118f7ad7e1b4585364ee5ad8e27919..15eb7f7c047c973cbee96dfa0bae163d0c10e06c 100644 (file)
@@ -36,7 +36,7 @@
  */
 
 #ifndef SU_CONFIGURE_H
-#include "sofia-sip/su_configure.h"
+#include <sofia-sip/su_configure.h>
 #endif
 
 #if defined(__GNUC__)
index b15ac1a79372650b0902610757396a28a3ca5169..cbd1fa44c6d6573514992e508fb63cff52e88a51 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the Sofia-SIP package
  *
- * Copyright (C) 2005 Nokia Corporation.
+ * Copyright (C) 2005,2006,2007 Nokia Corporation.
  *
  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  *
index 5989744a08942b22e1587f9333cfd592644b921a..7d2a48047512a093ffe8d5a11dfc24d56705188c 100644 (file)
@@ -73,7 +73,7 @@ enum {
  */
 typedef uint64_t su_ntp_t;
 
-/** Represent NTP consttant */
+/** Represent NTP constant */
 #define SU_NTP_C(x) SU_U64_C(x)
 
 #define SU_TIME_CMP(t1, t2) su_time_cmp(t1, t2)
@@ -81,6 +81,13 @@ typedef uint64_t su_ntp_t;
 /** Seconds from 1.1.1900 to 1.1.1970. @NEW_1_12_4 */
 #define SU_TIME_EPOCH 2208988800UL 
 
+typedef uint64_t su_nanotime_t;
+
+#define SU_E9 (1000000000U) 
+
+SOFIAPUBFUN su_nanotime_t su_nanotime(su_nanotime_t *return_time);
+SOFIAPUBFUN su_nanotime_t su_monotime(su_nanotime_t *return_time);
+
 SOFIAPUBFUN su_time_t su_now(void);
 SOFIAPUBFUN void su_time(su_time_t *tv);
 SOFIAPUBFUN long su_time_cmp(su_time_t const t1, su_time_t const t2);
index 4d83eacbbaee401d667b5490c0c025b2eb13c112..3bef603d9c1f53b759d37ecd00db117c1227d6e6 100644 (file)
@@ -34,7 +34,7 @@
  */
 
 #ifndef SU_CONFIG_H
-#include "sofia-sip/su_config.h"
+#include <sofia-sip/su_config.h>
 #endif
 
 #if SU_HAVE_STDINT
index 5cd7032983196a6786fa3af56758e34ce2ffb038..dc422ad6fe1210fc1f947fdb03cd552bb839f41d 100644 (file)
@@ -341,6 +341,12 @@ typedef void (*su_timer_f)(su_root_magic_t *magic,
                           su_timer_t *t,
                           su_timer_arg_t *arg);
 
+#ifndef SU_TIMER_QUEUE_T
+#define SU_TIMER_QUEUE_T su_timer_t *
+#endif
+
+typedef SU_TIMER_QUEUE_T su_timer_queue_t;
+
 /* ---------------------------------------------------------------------- */
 
 /* Tasks */
@@ -487,7 +493,7 @@ SOFIAPUBFUN int su_timer_reset(su_timer_t *);
 
 SOFIAPUBFUN su_root_t *su_timer_root(su_timer_t const *);
 
-SOFIAPUBFUN int su_timer_expire(su_timer_t ** const, 
+SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const, 
                                su_duration_t *tout,
                                su_time_t now);
 
@@ -505,7 +511,7 @@ SOFIAPUBFUN int su_task_cmp(su_task_r const, su_task_r const);
 SOFIAPUBFUN int su_task_is_running(su_task_r const);
 
 SOFIAPUBFUN su_root_t *su_task_root(su_task_r const self);
-SOFIAPUBFUN su_timer_t **su_task_timers(su_task_r const self);
+SOFIAPUBFUN su_timer_queue_t *su_task_timers(su_task_r const self);
 
 SOFIAPUBFUN int su_task_execute(su_task_r const task,
                                int (*function)(void *), void *arg,
index 6375b0fe86cdbb66ab2e324521f68f702765a927..ed48cb9994b88f131f418ae79c412ab72d49cf01 100644 (file)
 
 #include "config.h" 
 
-#include "sofia-sip/su.h"
-#include "sofia-sip/su_log.h"
-#include "sofia-sip/su_alloc.h"
+#if HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#include <sofia-sip/su.h>
+#include <sofia-sip/su_log.h>
+#include <sofia-sip/su_alloc.h>
 
 #include <stdio.h>
 #include <string.h>
 int su_socket_close_on_exec = 0;
 int su_socket_blocking = 0;
 
-/** Create an endpoint for communication. */
+#if HAVE_OPEN_C && HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#if SU_HAVE_BSDSOCK && HAVE_OPEN_C
+char su_global_ap_name[IFNAMSIZ];
+extern int su_get_local_ip_addr(su_sockaddr_t *su);
+#endif
+
+/** Create a socket endpoint for communication.
+ *
+ * @param af addressing family 
+ * @param socktype socket type 
+ * @param proto protocol number specific to the addressing family
+ *
+ * The newly created socket is nonblocking unless global variable
+ * su_socket_blocking is set to true. 
+ *
+ * Also, the newly created socket is closed on exec() if global variable
+ * su_socket_close_on_exec is set to true. Note that a multithreaded program
+ * can fork() and exec() before the close-on-exec flag is set.
+ *
+ * @return A valid socket descriptor or INVALID_SOCKET (-1) upon an error.
+ */
 su_socket_t su_socket(int af, int socktype, int proto)
 {
+#if HAVE_OPEN_C
+  struct ifconf ifc;
+  int numifs = 64;
+  char *buffer;
+  struct ifreq ifr;
+  int const su_xtra = 0;
+#endif
+
   su_socket_t s = socket(af, socktype, proto);
-#if SU_HAVE_BSDSOCK
+
   if (s != INVALID_SOCKET) {
+#if SU_HAVE_BSDSOCK
     if (su_socket_close_on_exec)
       fcntl(s, F_SETFD, FD_CLOEXEC); /* Close on exec */
+#endif
     if (!su_socket_blocking)   /* All sockets are born blocking */
       su_setblocking(s, 0);
   }
+
+#if HAVE_OPEN_C
+  /* Use AP we have raised up */
+  memset(&ifr, 0, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, (char const *) su_global_ap_name, IFNAMSIZ);
+
+  /* Assign socket to an already active access point (interface) */
+  ioctl(s, SIOCSIFNAME, &ifr);
+  ioctl(s, SIOCIFSTART, &ifr); 
 #endif
+
   return s;
 }
 
-#if SU_HAVE_BSDSOCK
+#if HAVE_OPEN_C
+#include <errno.h>
+su_sockaddr_t su_ap[1];
+int ifindex;
+void *aConnection;
+extern void *su_localinfo_ap_set(su_sockaddr_t *su, int *index);
+extern int su_localinfo_ap_deinit(void *aconn);
+#define NUMIFS 64
+  
+int su_localinfo_ap_name_to_index(int ap_index)
+{
+  struct ifconf ifc;
+
+  struct ifreq *ifr, *ifr_next;
+  int error = EFAULT;
+  char *buffer, buf[NUMIFS * sizeof(struct ifreq)];
+  su_socket_t s;
+
+  s= socket(AF_INET, SOCK_STREAM, 0);
+  if (s < 0)
+    return -1;
+  
+  ifc.ifc_len = NUMIFS * sizeof (struct ifreq);
+
+  memset(buf, 0, ifc.ifc_len);
+  ifc.ifc_buf = buf;
+  if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+    return error;
+  }
+
+  buffer = ifc.ifc_buf + ifc.ifc_len;
+
+  for (ifr = ifc.ifc_req;
+       (void *)ifr < (void *)buffer;
+       ifr = ifr_next) {
+    struct ifreq ifreq[1];
+    int scope, if_index, flags = 0, gni_flags = 0;
+    char *if_name;
+    su_sockaddr_t su2[1];
+
+#if SA_LEN
+    if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
+      ifr_next = (struct ifreq *)
+       (ifr->ifr_addr.sa_len + (char *)(&ifr->ifr_addr));
+    else
+#else
+      ifr_next = ifr + 1;
+#endif
+
+    if_name = ifr->ifr_name;
+
+#if defined(SIOCGIFINDEX)
+    ifreq[0] = *ifr;
+    if (ioctl(s, SIOCGIFINDEX, ifreq) < 0) {
+return -1;
+    }
+#if HAVE_IFR_INDEX
+    if_index = ifreq->ifr_index;
+#elif HAVE_IFR_IFINDEX
+    if_index = ifreq->ifr_ifindex;
+#else
+#error Unknown index field in struct ifreq
+#endif
+
+    if (ap_index == if_index) 
+    {
+      strncpy(su_global_ap_name, (const char *) if_name, sizeof(su_global_ap_name));
+      error = 0;
+    };
+  
+#else
+#error su_localinfo() cannot map interface name to number
+#endif
+
+  }
+
+  close(s);
+  return error;
+}
+#endif
+
+#if SU_HAVE_BSDSOCK || DOCUMENTATION_ONLY
+/** Initialize socket implementation.
+ *
+ * Before using any sofia-sip-ua functions, the application should call
+ * su_init() in order to initialize run-time environment including sockets. 
+ * This function may prepare plugins if there are any. 
+ *
+ * @par POSIX Implementation
+ * The su_init() initializes debugging logs and ignores the SIGPIPE signal.
+ *
+ * @par Windows Implementation
+ * The function su_init() initializes Winsock2 library on Windows.
+ *
+ * @par Symbian Implementation
+ * The function su_init() prompts user to select an access point (interface
+ * towards Internet) and uses the activated access point for the socket
+ * operations.
+ */
 int su_init(void)
 {
+#if HAVE_OPEN_C
+  char apname[60];
+  su_socket_t s;
+#endif
+
   su_home_threadsafe(NULL);
 
 #if HAVE_SIGPIPE
   signal(SIGPIPE, SIG_IGN);    /* we want to get EPIPE instead */
 #endif
 
+#if HAVE_OPEN_C
+  /* This code takes care of enabling an access point (interface) */
+  aConnection = su_localinfo_ap_set(su_ap, &ifindex);
+  su_localinfo_ap_name_to_index(ifindex);
+#endif
+
   su_log_init(su_log_default);
   su_log_init(su_log_global);
 
   return 0;
 }
 
+/** Deinitialize socket implementation. */
 void su_deinit(void)
 {
+#if HAVE_OPEN_C
+       su_localinfo_ap_deinit(aConnection);
+#endif
 }
 
 /** Close an socket descriptor. */
@@ -133,7 +293,7 @@ void su_deinit(void)
   WSACleanup();
 }
 
-/** Close an socket descriptor. */
+/** Close a socket descriptor. */
 int su_close(su_socket_t s)
 {
   return closesocket(s);
@@ -196,6 +356,14 @@ issize_t su_getmsgsize(su_socket_t s)
     return -1;
   return (issize_t)n;
 }
+#elif HAVE_OPEN_C
+issize_t su_getmsgsize(su_socket_t s)
+{
+  int n = -1;
+  if (su_ioctl(s, E32IONREAD, &n) == -1)
+    return -1;
+  return (issize_t)n;
+}
 #else
 issize_t su_getmsgsize(su_socket_t s)
 {
@@ -222,8 +390,9 @@ struct in_addr6 const *su_in6addr_loopback(void)
 }
 #endif
 
-#if SU_HAVE_WINSOCK
+#if SU_HAVE_WINSOCK || DOCUMENTATION_ONLY
 
+/** Call send() with POSIX-compatible signature */
 ssize_t su_send(su_socket_t s, void *buffer, size_t length, int flags)
 {
   if (length > INT_MAX)
@@ -231,6 +400,7 @@ ssize_t su_send(su_socket_t s, void *buffer, size_t length, int flags)
   return (ssize_t)send(s, buffer, (int)length, flags);
 }
 
+/** Call sendto() with POSIX-compatible signature */
 ssize_t su_sendto(su_socket_t s, void *buffer, size_t length, int flags,
                   su_sockaddr_t const *to, socklen_t tolen)
 {
@@ -240,6 +410,7 @@ ssize_t su_sendto(su_socket_t s, void *buffer, size_t length, int flags,
                         &to->su_sa, (int) tolen);
 }
 
+/** Call recv() with POSIX-compatible signature */
 ssize_t su_recv(su_socket_t s, void *buffer, size_t length, int flags)
 {
   if (length > INT_MAX)
@@ -248,6 +419,7 @@ ssize_t su_recv(su_socket_t s, void *buffer, size_t length, int flags)
   return (ssize_t)recv(s, buffer, (int)length, flags);
 }
 
+/** Call recvfrom() with POSIX-compatible signature */
 ssize_t su_recvfrom(su_socket_t s, void *buffer, size_t length, int flags,
                    su_sockaddr_t *from, socklen_t *fromlen)
 {
index 759fef163b02b7cd7d5714f04ab13bfeef72d941..6a26dad7c53335a48901923e809e33a799f2f605 100644 (file)
  *
  * The @b su module provides following interfaces for application programs:
  *
- * - su_types.h - integral types
- * - su.h - @ref su_socket 
- *   - su_localinfo.h - get list of local IP addresses
- * - su_wait.h - @ref su_wait 
- * - su_time.h - @ref su_time
- * - su_alloc.h - @ref su_alloc
- * - su_log.h - @ref su_log
- * - su_tag.h - @ref su_tag
- * - su_md5.h - @ref su_md5
- * - su_uniqueid.h - @ref su_uniqueid 
+ * - <sofia-sip/su_types.h> - integral types
+ * - <sofia-sip/su_alloc.h> - @ref su_alloc memory management
+ * - <sofia-sip/su.h> - @ref su_socket 
+ *   - <sofia-sip/su_localinfo.h> - get list of local IP addresses
+ * - <sofia-sip/su_wait.h> - @ref su_wait 
+ * - <sofia-sip/su_time.h> - @ref su_time
+ * - <sofia-sip/su_log.h> - @ref su_log
+ * - <sofia-sip/su_tag.h> - @ref su_tag
+ * - <sofia-sip/su_md5.h> - @ref su_md5
+ * - <sofia-sip/su_uniqueid.h> - @ref su_uniqueid Unique ID and random number generators
  *
  * The @b su library also contains some collection datatypes:
- * - htable.h - @ref su_htable
- * - rbtree.h - balanced red-black trees
- * - su_strlst.h - @ref su_strlst
- * - su_vector.h - @ref su_vector
+ * - <sofia-sip/htable.h> - @ref su_htable
+ * - <sofia-sip/rbtree.h> - balanced red-black trees
+ * - <sofia-sip/su_strlst.h> - @ref su_strlst list of strings
+ * - <sofia-sip/su_vector.h> - @ref su_vector dynamic arrays of pointers
  *
  * There are also some convenience macros for unit test programs:
- * - tstdef.h - macros for unit tests
+ * - sofia-sip/tstdef.h - macros for unit tests
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  * @author Jari Selin <Jari.Selin@nokia.com>
@@ -55,7 +55,7 @@
  * developed for Sofia communications software. Currently, interface to
  * it consists of following parts:
  *
- * - <a href=su_types_h.html>su_types</a> - basic integer types
+ * - <sofia-sip/su_types.h> - basic integer types
  * - <a href=group_su_socket.html>su_socket</a> - socket functions
  * - <a href=group_su_wait.html>su_wait</a> - synchronization functions
  * - <a href=group_su_time.html>su_time</a> - time functions
@@ -74,9 +74,9 @@
 
 /**@defgroup su_socket Socket Functions
  *
- *  @brief The <su.h> contains the portable socket functions. 
+ *  @brief The <sofia-sip/su.h> contains the portable socket functions. 
  *
- *  The <su.h> contains following functions, macros, and types:
+ *  The <sofia-sip/su.h> contains following functions, macros, and types:
  *    - su_init(): initializes sockets
  *    - su_deinit(): deinitializes sockets
  *    - su_socket(): creates a socket
@@ -84,7 +84,7 @@
  *    - su_ioctl(): ioctl to a socket
  *    - su_setreuseaddr(): set/reset reusing the addresses/ports for a socket
  *    - su_setblocking(): enables/disables blocking
- *    - su_isblocking(): checks if the previous call failed because it 
+ *    - su_is_blocking(): checks if the previous call failed because it 
  *     would have blocked
  *    - su_errno(): the latest socket error
  *    - su_perror(): prints the latest socket error message to stderr
@@ -94,6 +94,8 @@
  *    - su_getmsgsize(): return the number of bytes that can be recv()ed from
  *     a socket
  *    - su_getlocalip(): return an IP address belonging to the local host
+ *    - su_send(), su_sendto(): type-compatible send()
+ *    - su_recv(), su_recvfrom(): type-compatible recv()
  *    - su_vsend(): scatter-gather send
  *    - su_vrecv(): scatter-gather receive
  *    - #su_iovec_t: structure holding scatter-gather IO vector
  * <sofia-sip/htable.h>. Example code and tests for the implementation is in
  * test_htable.c.
  */
-
-
-/* <a name="su_wallclock"></a>
- * <h3>Function @c su_wallclock() - get current time</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_time.h&gt;
- * 
- * void su_wallclock(su_time_t *tv);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * Fills the @a tv with the current NTP timestamp.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c tv      <td>pointer to the timeval object
- * </table>
- * </blockquote>
- * 
- * <a name="su_now"></a>
- * <h3>Function @c su_now() - get current time</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_time.h&gt;
- * 
- * su_time_t su_now(void);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * Return the current NTP timestamp.
- * </blockquote>
- * 
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * The structure containing the current NTP timestamp.
- * </blockquote>
- * 
- * <a name="su_time_print"></a>
- * <h3>Function @c su_time_print() - print an NTP timestamp</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_time.h&gt;
- * 
- * int su_time_print(char *s, int n, su_time_t const *tv);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- *  This function prints an NTP timestamp as a decimal number to the
- *  given buffer.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c char *s            <td>pointer to buffer
- *   <tr><td>@c int n              <td>buffer size
- *   <tr><td>@c su_time_t const tv <td>pointer to the timeval object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * The number of characters printed, excluding the final NUL.
- * </blockquote>
- * 
- * <a name="su_duration"></a>
- * <h3>Function @c su_duration() - return time difference in milliseconds</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_time.h&gt;
- * 
- * su_duration_t su_duration(su_time_t t1, su_time_t t2);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * Calculates the duration in milliseconds from @a t2 to @a t1 in milliseconds. If the difference is bigger
- * than @c SU_MAX_DURATION, return @c SU_MAX_DURATION instead.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t1      <td>after time
- *   <tr><td>@c t2      <td>before time
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * The duration in milliseconds between the two times.
- * </blockquote>
- * 
- * <a name="su_alloc.h"></a>
- * <h1>&lt;su_alloc.h&gt;</h1>
- * 
- * This section describes memory management functions.
- * 
- * 
- * The
- * @c su_alloc library provides convenience functions for
- * memory management. The library defines an object @c su_home_t for
- * collecting multiple memory allocations under one handle.
- * 
- * <ul>
- *   - Function @c su_home_create()
- *       - create an su_home_t object
- * 
- *   - Function @c su_home_destroy()
- *       - free a home object
- * 
- *   - Function @c su_alloc()
- *       - allocate a memory block
- * 
- *   - Function @c su_zalloc()
- *       - allocate and zero a memory block
- * 
- *   - Function @c su_salloc()
- *       - allocate a structure
- * 
- *   - Function @c su_free()
- *       - free a memory block
- * 
- * </ul>
- * 
- * 
- * The functions for implementing objects derived from @c su_home_t
- * are as follows:
- * <ul>
- *   - Function @c su_home_init()
- *       - initialize an @c su_home_t object
- * 
- *   - Function @c su_home_deinit()
- *        - free memory blocks from home
- * 
- * </ul>
- * 
- * <a name="su_home_create"></a>
- * <h3>Function @c su_home_create() - create an su_home_t object</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * su_home_t *su_home_create(void);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_home_create() creates a home object used to
- * collect multiple memory allocations under one handle, so that they can be
- * freed by calling <dfn>su_home_destroy()</dfn>.
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * This function returns a pointer to an @c su_home_t object, or
- * @c NULL upon an error.
- * </blockquote>
- * 
- * <a name="su_home_destroy"></a>
- * <h3>Function @c su_home_destroy() - free a home object</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void su_home_destroy(su_home_t *h);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_home_destroy() frees a home object, and all
- * memory blocks associated with it.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- * </table>
- * </blockquote>
- * 
- * <a name="su_alloc"></a>
- * <h3>Function @c su_alloc() - allocate a memory block</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void *su_alloc(su_home_t *h, int  n);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_alloc() allocates a memory block of a given size.
- * 
- * 
- * If @a h is @c NULL, this function behaves exactly like
- * @c malloc().
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- *   <tr><td>@c int n      <td>size of the memory block to be allocated
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * This function returns a pointer to the allocated memory block, or
- * @c NULL, if an error occurred.
- * </blockquote>
- * 
- * <a name="su_zalloc"></a>
- * <h3>Function @c su_zalloc() - allocate and zero a memory block</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void *su_zalloc(su_home_t *h, int  n)
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_zalloc() allocates a memory block with a given
- * size and zeroes the allocated block.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- *   <tr><td>@c int n      <td>size of the memory block to be allocated
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * This function returns a pointer to the allocated memory block, or
- * @c NULL, if an error occurred.
- * </blockquote>
- * 
- * <a name="su_salloc"></a>
- * <h3>Function @c su_salloc() - allocate a structure</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void *su_salloc(su_home_t *h, int  s);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function su_salloc() allocates a structure with a given size,
- * zeros it, and initializes the size field to the given size.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- *   <tr><td>@c int n      <td>size of the structure to be allocated
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * This function returns a pointer to the allocated memory block, or
- * @c NULL, if an error occurred.
- * </blockquote>
- * 
- * <a name="su_free"></a>
- * <h3>Function @c su_free() - free a memory block</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void su_free(su_home_t *h, void *vb);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_free() frees a single memory block.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h  <td>pointer to a home object
- *   <tr><td>@c void      *vb <td>pointer to the memory block to be freed
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * </blockquote>
- * 
- * <a name="su_home_init"></a>
- * <h3>Function @c su_home_init() - initialize an @c su_home_t object</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * int su_home_init(su_home_t *h);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_home_init() initializes an object derived from
- * @c su_home_t. It checks that the @a suh_size field is valid.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- * The function @c su_home_init() returns @c 0 when
- * successful, or @c -1 upon an error.
- * </blockquote>
- * 
- * <h4>Note</h4>
- * <blockquote><strong>This is an internal function, and it is intended for
- * implementing the objects derived from @c su_home_t.</strong>
- * </blockquote>
- * 
- * <a name="su_home_deinit"></a>
- * <h3>Function @c su_home_deinit() - free memory blocks from home </h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_alloc.h&gt;
- * 
- * void su_home_deinit(su_home_t *h);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- * The function @c su_home_deinit() frees the memory blocks
- * associated with the home object.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c su_home_t *h <td>pointer to a home object
- * </table>
- * </blockquote>
- * 
- * <h4>Note</h4>
- * <blockquote><strong>This is an internal function, and it is intended for
- * implementing the objects derived from @c su_home_t.</strong>
- * </blockquote>
- * 
- * 
- * <a name="su_wait.h"></a>
- * <h1>&lt;su_wait.h&gt;</h1>
- * 
- * This section describes synchronization functionality.
- * The @c su_wait library provides portable synchronization
- * primitives needed for running communication software.
- * 
- * Synchronization means that the program can stop waiting for events,
- * set callback functions for events, schedule timers, and set callback
- * functions for timers. In other words, it is an OS-independent
- * @c poll()/@c select()/@c WaitForMultipleObjects()
- * interface, spiced up with timer interface.
- * 
- * The library provides three kinds of objects: root
- * objects (@c su_root_t), wait objects
- * (@c su_wait_t), and timer objects
- * (@c su_timer_t).
- * 
- * <a name="wait"></a>
- * <h2>Wait Objects</h2>
- * 
- * 
- *   Wait objects are used to signal I/O events to the process.
- *   The events are as follows:
- * 
- * <dl>
- *   <dt>SU_WAIT_IN
- *   <dd>incoming data is available
- * 
- *   <dt>SU_WAIT_OUT
- *   <dd>data can be output
- * 
- *   <dt>SU_WAIT_ERR
- *   <dd>an error occurred
- * 
- *   <dt>SU_WAIT_HUP
- *   <dd>the socket connection was closed
- * 
- *   <dt>SU_WAIT_ACCEPT
- *   <dd>a listening socket accepted a new connection attempt
- * </dl>
- * 
- * 
- *   It is possible to combine several events with |, binary or operator.
- * 
- * 
- *   Public API contains functions as follows:
- * <ul>
- *   - su_wait_create()
- *   - su_wait_destroy()
- *   - su_wait()
- *   - su_wait_events()
- * </ul>
- * 
- * 
- *   In Unix, the wait object is @c struct poll. The structure contains a file
- *   handle, a mask describing expected events, and a mask containing the
- *   occurred events after calling @c poll(), ie. @c su_wait().
- * 
- * 
- *   In Windows, the wait object is a @c HANDLE (a descriptor of a Windows
- *   kernel entity).
- * 
- * 
- * <a name="su_wait_create"></a>
- * <h3>Function @c su_wait_create()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_wait_create(su_wait_t *newwait, su_socket_t socket, int events)</pre></blockquote>
- * 
- * <h4>Description</h4>
- * 
- * <blockquote>
- * @c Su_wait_create() creates a new wait object for a
- * @a socket with given @a events.  The new wait object is
- * assigned to the @a newwait parameter.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * 
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c newwait<td>the newly created wait object
- *   <tr><td>@c socket <td>socket descriptor
- *   <tr><td>@c events <td>mask for events that can signal this wait object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * 
- * <blockquote>
- * 0 if the call was successful, -1 otherwise.
- * </blockquote>
- * 
- * <a name="su_wait_destroy"></a>
- * <h3>Function @c su_wait_destroy()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre> #include &lt;su_wait.h&gt;
- * 
- * int su_wait_destroy(su_wait_t *waitobj);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>Destroy a wait object.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * 
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c waitobj <td>pointer to wait object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * 
- * <blockquote>
- * 0 when successful, -1 upon an error.
- * </blockquote>
- * 
- * <a name="su_wait"></a>
- * <h3>Function @c su_wait()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_wait(su_wait_t waits[], unsigned n, long timeout);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  Block until a event specified by wait objects or a timeout occurs.
- * 
- * 
- *   In Unix, this is poll.
- * 
- * 
- *   In Windows, this is WSAWaitForMultipleEvents
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c waits   <td>array of wait objects
- *   <tr><td>@c n       <td>number of wait objects in array waits
- *   <tr><td>@c timeout <td>timeout in milliseocnds
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- *   Index of the signaled wait object, if any, SU_WAIT_TIMEOUT if timeout
- *   occurred, and -1 upon an error.
- * </blockquote>
- * 
- * <a name="su_wait_events"></a>
- * <h3>Function @c su_wait_events()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_wait_events(su_wait_t *waitobj, su_socket_t s);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  Return an mask describing events occurred.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c waitobj  <td>pointer to wait object
- *   <tr><td>@c s        <td>socket
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  Binary mask describing the events.
- * </blockquote>
- * 
- * <a name="su_wait_mask"></a>
- * <h3>Function @c su_wait_mask()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_wait_mask(su_wait_t *waitobj, su_socket_t s, int events);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>
- *   Sets the mask describing events that can signal the wait object.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c waitobj  <td>pointer to wait object
- *   <tr><td>@c s        <td>socket
- *   <tr><td>@c events   <td>new event mask
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- *   0 when successful, -1 upon an error.
- * </blockquote>
- * 
- * <a name="root"></a>
- * <h2>Root objects</h2>
- * 
- * 
- *    Root object is a structure containing a list of wait objects,
- *    associated callback functions, and arguments to these functions.
- *    It can also contain a list of timers, and a magic cookie (a pointer
- *    defined by root object user.)
- * 
- * 
- *    The public API contains following functions:
- * <ul>
- *   - su_root_create()
- *   - su_root_destroy()
- *   - su_root_magic()
- *   - su_root_register()
- *   - su_root_unregister()
- *   - su_root_run()
- *   - su_root_break()
- *   - su_root_step()
- * </ul>
- * 
- * These functions are intended for implementing su_root API:
- * <ul>
- *   - su_root_init()
- *   - su_root_deinit()
- *   - su_root_query()
- *   - su_root_event()
- * </ul>
- * 
- * <a name="su_root_create"></a>
- * <h3>Function @c su_root_create()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * su_root_t *su_root_create(su_root_magic_t *magic);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Allocate and initialize an instance of su_root_t
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c magic    <td>pointer to user data
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  A pointer to allocated su_root_t instance, NULL on error.
- * </blockquote>
- * 
- * 
- * <a name="su_root_destroy"></a>
- * <h3>Function @c su_root_destroy()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * void su_root_destroy(su_root_t *root);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Deinitialize and free an instance of su_root_t
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root    <td>pointer to a root structure
- * </table>
- * </blockquote>
- * 
- * 
- * <a name="su_root_magic"></a>
- * <h3>Function @c su_root_magic()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * su_root_magic_t *su_root_magic(su_root_t *root);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Return the user data pointer that was given input to su_root_create() or
- * 
- *  su_root_init().
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to a root object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  A pointer to user data
- * </blockquote>
- * 
- * 
- * <a name="su_root_register"></a>
- * <h3>Function @c su_root_register()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_root_register(su_root_t *root,
- *                  su_wait_t *waits,
- *                  su_wakeup_f callback,
- *                  su_wakeup_arg_t arg,
- *                  int priority);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Register a su_wait_t object. The wait object, a callback function and
- * 
- *  a argument is stored to the root object. The callback function is called,
- *  when the wait object is signaled.
- * 
- *  Please note if identical wait objects are inserted, only first one is
- *  ever signalled.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- *   <tr><td>@c waits    <td>pointer to wait object
- *   <tr><td>@c callback <td>callback function pointer
- *   <tr><td>@c arg      <td>argument given to callback function when it is invoked
- *   <tr><td>@c priority <td>relative priority of the wait object
- *              (0 is normal, 1 important, 2 realtime)
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  Index of the wait object, or -1 upon an error.
- * </blockquote>
- * 
- * 
- * <a name="su_root_unregister"></a>
- * <h3>Function @c su_root_unregister()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_root_unregister(su_root_t *root,
- *                    su_wait_t *wait,
- *                    su_wakeup_f callback,
- *                    su_wakeup_arg_t arg);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> UnRegisters a su_wait_t object. The wait object, a callback function and
- * 
- *  a argument are removed from the root object. The callback function is called,
- *  when the wait object is signaled.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- *   <tr><td>@c waits    <td>pointer to wait object
- *   <tr><td>@c callback <td>callback function pointer (may be NULL)
- *   <tr><td>@c arg      <td>argument given to callback function when it
- *                                 is invoked (may be NULL)
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  Index of the wait object, or -1 upon an error.
- * </blockquote>
- * 
- * 
- * <a name="su_root_run"></a>
- * <h3>Function @c su_root_run()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * void su_root_run(su_root_t *root);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  This function waits for wait objects and the timers associated with
- *   the root object.  When any wait object is signaled or timer is
- *   expired, it invokes the callbacks, and returns waiting.
- * 
- * 
- *   This function returns when su_root_break() is called from a callback.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- * </table>
- * </blockquote>
- * 
- * 
- * <a name="su_root_break"></a>
- * <h3>Function @c su_root_break()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * void su_root_break(su_root_t *root);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  If this function is used to terminate execution of su_root_run(). It
- * 
- *   can be called from a callback function.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- * </table>
- * </blockquote>
- * 
- * 
- * <a name="su_root_step"></a>
- * <h3>Function @c su_root_step()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * su_duration_t su_root_step(su_root_t *root, su_duration_t tout);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  This function waits for wait objects and the timers associated with
- *   the @a root object.  When any wait object is signaled or timer is
- *   expired, it invokes the callbacks, and returns.
- * 
- * 
- *   This function returns when a callback has been invoked or @a tout
- *   milliseconds is elapsed.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- *   <tr><td>@c tout     <td>timeout in milliseconds
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- *   Milliseconds to the next invocation of timer, or SU_WAIT_FOREVER if
- *   there are no active timers.
- * </blockquote>
- * 
- * <a name="timer"></a>
- * <h2>Timer objects</h2>
- * 
- * Timers are used to schedule some task to be executed at given time or
- * after a default interval. The default interval is specified when the
- * timer is created. We call timer activation "setting the timer", and
- * deactivation "resetting the timer" (as in SDL). When the given time has
- * arrived or the default interval has elapsed, the timer expires and
- * it is ready for execution.
- * 
- * These functions are available for handling timers:
- * 
- * - su_timer_create()
- *   - su_timer_destroy()
- *   - su_timer_set()
- *   - su_timer_set_at()
- *   - su_timer_reset()
- *   - su_timer_run()
- * 
- * <a name="su_timer_create"></a>
- * <h3>Function @c su_timer_create()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * su_timer_t *su_timer_create(su_root_t *root, su_duration_t msec);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * 
- * <blockquote>
- * Allocate and initialize an instance of su_timer_t.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *  <tr><td>@c root   <td>the root object with which the timer will be associated
- *  <tr><td>@c msec   <td>the default duration of the timer
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  A pointer to allocated timer instance, NULL on error.
- * </blockquote>
- * 
- * 
- * <a name="su_timer_destroy"></a>
- * <h3>Function @c su_timer_destroy()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * void su_timer_destroy(su_timer_t *t);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Deinitialize and free an instance of su_timer_t.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t      <td>pointer to the timer object
- * </table>
- * </blockquote>
- * 
- * 
- * <a name="su_timer_set"></a>
- * <h3>Function @c su_timer_set()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_timer_set(su_timer_t *t,
- *              su_timer_f wakeup,
- *              su_wakeup_arg_t arg);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Sets the given timer to expire after the default duration.
- * 
- * The timer must have an default duration.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t      <td>pointer to the timer object
- *   <tr><td>@c wakeup <td>pointer to the wakeup function
- *   <tr><td>@c arg    <td>argument given to the wakeup function
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  0 if successful, -1 otherwise.
- * </blockquote>
- * 
- * 
- * <a name="su_timer_set_at"></a>
- * <h3>Function @c su_timer_set_at()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_timer_set_at(su_timer_t *t,
- *                 su_timer_f wakeup,
- *                 su_wakeup_arg_t arg,
- *                 su_time_t when);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Sets the timer to expire at given time.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t      <td>pointer to the timer object
- *   <tr><td>@c wakeup <td>pointer to the wakeup function
- *   <tr><td>@c arg    <td>argument given to the wakeup function
- *   <tr><td>@c when   <td>time structure defining the wakeup time
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  0 if successful, -1 otherwise.
- * </blockquote>
- * 
- * 
- * <a name="su_timer_reset"></a>
- * <h3>Function @c su_timer_reset()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * int su_timer_reset(su_timer_t *t);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  Resets the given timer.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t      <td>pointer to the timer object
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  0 if successful, -1 otherwise.
- * </blockquote>
- * 
- * <a name="su_timer_run"></a>
- * <h3>Function @c su_timer_run()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * 
- * su_duration_t su_timer_run(su_timer_t ** const t0, su_duration_t tout);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  Expires and executes expired timers in queue.
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c t0     <td>pointer to the timer queue
- *   <tr><td>@c tout   <td>timeout in milliseconds
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>
- *  The duration in milliseconds before the next timer expires, or timeout (2**31 - 1
- *  ms), whichever is shorter.
- * </blockquote>
- * 
- * <!--
- * Root object is used for synchronizing. There must be one root object per
- * thread. There are two alternative ways for creating a root object. If you
- * are just using su_root_t, and don't want to <a
- * href="#inherit_su_root_t">inherit from it</a>, you can use
- * @c su_create().
- * -->
- * 
- * <a name="su_wait_internal.h"></a>
- * <h1>&lt;su_wait_internal.h&gt;</h1>
- * 
- * 
- * This section contains the internal functions, that is, functions used to
- * implement objects in @c &lt;su_wait.h&gt;.
- * 
- * <a name="su_root_init"></a>
- * <h3>Function @c su_root_init()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * #include &lt;su_wait_internal.h&gt;
- * 
- * int su_root_init(su_root_t *root, su_root_magic_t *magic);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * 
- * <blockquote>
- * 
- * Initialize an instance of @c su_root_t. The caller should allocate
- * the memory required for su_root_t, and set the sur_size to the size of the
- * allocated structure.
- * 
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * 
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root    <td>pointer to a uninitialized root structure
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  0 when call was successful, -1 otherwise.
- * </blockquote>
- * 
- * 
- * <h4>Note</h4>
- * <blockquote>
- * <strong>This is an internal function, and it is intended for implementing
- * the objects derived from @c su_root_t.</strong>
- * </blockquote>
- * 
- * 
- * <a name="su_root_deinit"></a>
- * <h3>Function @c su_root_deinit()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * #include &lt;su_wait_internal.h&gt;
- * 
- * void su_root_deinit(su_root_t *root);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Deinitialize an instance of su_root_t
- * </blockquote>
- * 
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root    <td>pointer to a root structure
- * </table>
- * </blockquote>
- * 
- * <h4>Note</h4>
- * <blockquote>  <strong>This is an internal function, and it is intended for
- * implementing the objects derived from @c su_root_t.</strong>
- * </blockquote>
- * 
- * <a name="su_root_query"></a>
- * <h3>Function @c su_root_query()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * #include &lt;su_wait_internal.h&gt;
- * 
- * unsigned su_root_query(su_root_t *root, su_wait_t *waits, unsigned n_waits);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote> Copies the su_wait_t objects from the root. The number of wait objects
- * 
- *  can be found out by calling su_root_query() with n_waits as zero.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c waits    <td>pointer to array to which wait objects are copied
- *   <tr><td>@c root     <td>pointer to root object
- *   <tr><td>@c n_waits  <td>number of wait objects fitting in array waits
- * </table>
- * </blockquote>
- * 
- * <h4>Return Value</h4>
- * <blockquote>  Number of wait objects, or 0 upon an error.
- * </blockquote>
- * 
- * 
- * <h4>Note</h4>
- * <blockquote><strong>This is an internal function, and it is intended for
- * implementing the objects derived from @c su_root_t.</strong>
- * </blockquote>
- * 
- * 
- * <a name="su_root_event"></a>
- * <h3>Function @c su_root_event()</h3>
- * 
- * <h4>Synopsis</h4>
- * 
- * <blockquote><pre>
- * #include &lt;su_wait.h&gt;
- * #include &lt;su_wait_internal.h&gt;
- * 
- * void su_root_event(su_root_t *root, su_wait_t *waitobj);
- * </pre></blockquote>
- * 
- * <h4>Description</h4>
- * <blockquote>  Invokes the callback function associated with the wait object.
- * 
- * 
- *   If waitobj is NULL, check if a wait object associated with root is
- *   signaled, and its callback is invoked.
- * </blockquote>
- * 
- * <h4>Parameters</h4>
- * <blockquote>
- * <table cellpadding=3 cellspacing=0 border=1>
- *   <tr><td>@c root     <td>pointer to root object
- *   <tr><td>@c waitobj    <td>pointer to wait object, or NULL
- * </table>
- * </blockquote>
- * 
- * <h4>Note</h4>
- * <blockquote><strong>This is an internal function, and it is intended for
- * implementing the objects derived from @c su_root_t.</strong>
- * </blockquote>
- * 
- */
index 334e231ad271e3ecb55205d5edfda2a7920f751f..5ce50e0d969d947ecbb269b57e9ee1aa0d209d9b 100644 (file)
 #include <stdlib.h>
 #include <ctype.h>
 
+#ifndef EAI_NODATA
+#define EAI_NODATA 7
+#endif
+
 /*
  * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
  *
index e00ec29675fd7d0a41461a20834b3b6e4aa60ace..5331c31123a6d7f440a765a4b9b69c9aa7bb84b0 100644 (file)
@@ -477,7 +477,7 @@ int su_base_port_remove_prepoll(su_port_t *self,
  * Timers
  */
 
-su_timer_t **su_base_port_timers(su_port_t *self)
+su_timer_queue_t *su_base_port_timers(su_port_t *self)
 {
   return &self->sup_timers;
 }
index d7efc71f251189d9ce5051f99811600de31e3d8a..d54bfedf458a80e727e623a4a87e193e1fcd43ba 100644 (file)
@@ -53,7 +53,7 @@ static void default_logger(void *stream, char const *fmt, va_list ap)
  * The SOFIA_DEBUG environment variable is used to determine the default
  * debug logging level. The normal level is 3.
  * 
- * @sa <su_debug.h>, su_log_global
+ * @sa <sofia-sip/su_debug.h>, su_log_global
  */
 extern char const SOFIA_DEBUG[];
 
index b330fb962b1510e9eded0805d7f5a8ec341dcea3..c8d10a33a4d5e0e7bd3a66c14980bd207c2dac62 100644 (file)
@@ -45,7 +45,7 @@
  * The SU_DEBUG environment variable is used to determine the debug logging
  * level for @b su module. The default level is 3.
  * 
- * @sa <su_debug.h>, su_log_global
+ * @sa <sofia-sip/su_debug.h>, su_log_global
  */
 extern char const SU_DEBUG[];
 
index aadf4809687ff6c2edec14fcd59c59c449619fd4..77cdc3d90e54cc99e7dbedfe9ec2c0aa4dc436ba 100644 (file)
  * Obtain list of local addresses.
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
+ * @author Martti Mela <Martti.Mela@nokia.com>
  * 
  * @date Created: Wed Oct  4 14:09:29 EET 2000 ppessi
  */
 
 #include "config.h"
 
-#include "sofia-sip/su.h"
-#include "sofia-sip/su_localinfo.h"
-#include "su_module_debug.h"
-
 #if HAVE_SYS_SOCKIO_H
 #include <sys/sockio.h>
 #endif
 
+#include <sofia-sip/su.h>
+#include <sofia-sip/su_localinfo.h>
+#include "su_module_debug.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -409,9 +410,14 @@ int su_sockaddr_scope(su_sockaddr_t const *su, socklen_t sulen)
   return 0;
 }
 
+#if HAVE_OPEN_C
+extern int su_get_local_ip_addr(su_sockaddr_t *su);
+#endif
+
 #if USE_LOCALINFO0
 
 #elif HAVE_IFCONF
+#if __APPLE_CC__
 /** Build a list of local IPv4 addresses and append it to *rresult. */
 static
 int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
@@ -434,6 +440,10 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
   char *buffer;
   struct ifreq *ifr, *ifr_next;
 
+  su_sockaddr_t *sa;
+  socklen_t salen = sizeof(*sa);
+  int scope = 0, gni_flags = 0;
+
   s = su_socket(AF_INET, SOCK_DGRAM, 0);
   if (s == -1) {
     SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", 
@@ -441,70 +451,105 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
     return ELI_SYSTEM;
   }
 
-#if defined(__APPLE_CC__)
-  {
-    su_sockaddr_t *sa;
-    socklen_t salen = sizeof(*sa);
-    int scope = 0, gni_flags = 0;
 
-    li = calloc(1, sizeof(su_localinfo_t));
-    sa = calloc(1, sizeof(su_sockaddr_t));
+  li = calloc(1, sizeof(su_localinfo_t));
+  sa = calloc(1, sizeof(su_sockaddr_t));
 
-    error = getsockname(s, (struct sockaddr *) sa, &salen);
-    if (error < 0 && errno == SOCKET_ERROR) {
-      SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
-                 su_strerror(su_errno())));
-    }
+  error = getsockname(s, (struct sockaddr *) sa, &salen);
+  if (error < 0 && errno == SOCKET_ERROR) {
+    SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
+                su_strerror(su_errno())));
+  }
 
-    error = bind(s, (struct sockaddr *) sa, salen);
+  error = bind(s, (struct sockaddr *) sa, salen);
 
-    if (error < 0) {
-      SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
-                 su_strerror(su_errno())));
-      goto err;
-    }
+  if (error < 0) {
+    SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
+                su_strerror(su_errno())));
+    goto err;
+  }
 
-    su_close(s);
+  su_close(s);
 
-    scope = li_scope4(sa->su_sin.sin_addr.s_addr);
+  scope = li_scope4(sa->su_sin.sin_addr.s_addr);
 
-    if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
-      gni_flags = NI_NUMERICHOST;
+  if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
+    gni_flags = NI_NUMERICHOST;
     
-    if (su_xtra) {
-      /* Map IPv4 address to IPv6 address */
-      memset(sa, 0, sizeof(*sa));
-      sa->su_family = AF_INET6;
-      ((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
+  if (su_xtra) {
+    /* Map IPv4 address to IPv6 address */
+    memset(sa, 0, sizeof(*sa));
+    sa->su_family = AF_INET6;
+    ((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
       ((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff);
-    }
+  }
 
-    li->li_family = sa->su_family;
-    li->li_scope = scope;
-    li->li_index = 0;
-    li->li_addrlen = su_sockaddr_size(sa);
-    li->li_addr = sa;
+  li->li_family = sa->su_family;
+  li->li_scope = scope;
+  li->li_index = 0;
+  li->li_addrlen = su_sockaddr_size(sa);
+  li->li_addr = sa;
 
-    if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
-      goto err;
+  if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
+    goto err;
 
-    if (canonname) {
-      if (strchr(canonname, ':') ||
-         strspn(canonname, "0123456789.") == strlen(canonname))
-           li->li_flags |= LI_NUMERIC;
-    }
-    else
-      li->li_flags = 0;
+  if (canonname) {
+    if (strchr(canonname, ':') ||
+       strspn(canonname, "0123456789.") == strlen(canonname))
+         li->li_flags |= LI_NUMERIC;
+  }
+  else
+    li->li_flags = 0;
+  
+  li->li_canonname = canonname;
 
-    li->li_canonname = canonname;
+  canonname = NULL;
 
-    canonname = NULL;
+  *rresult = li;
+  return 0;
 
-    *rresult = li;
-    return 0;
-  }
+err:
+  if (canonname) free(canonname);
+  if (li_first) free(li_first);
+  su_freelocalinfo(tbf);
+  su_close(s);
+
+  return error;
+}
+#else /* !__APPLE_CC__ */
+/** Build a list of local IPv4 addresses and append it to *rresult. */
+static
+int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
+{
+  su_localinfo_t *tbf = NULL, **lli = &tbf;
+  su_localinfo_t *li = NULL, *li_first = NULL;
+  su_sockaddr_t *su;
+  int error = ELI_NOADDRESS;
+  char *canonname = NULL;
+  su_socket_t s;
+
+#if SU_HAVE_IN6
+  int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
+#else
+  int const su_xtra = 0;
 #endif
 
+  struct ifconf ifc;
+  int numifs;
+  char *buffer;
+  struct ifreq *ifr, *ifr_next;
+
+#if HAVE_OPEN_C
+    su_sockaddr_t *sa;
+    socklen_t salen = sizeof(*sa);
+#endif
+
+  s = su_socket(AF_INET, SOCK_DGRAM, 0);
+  if (s == -1) {
+    SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n", 
+               su_strerror(su_errno())));
+    return ELI_SYSTEM;
+  }
 
 # if HAVE_IFNUM
   /* Get the list of known IP address from the kernel */
@@ -539,16 +584,25 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
     error = ELI_MEMORY;
     goto err;
   }
-
+  
   li_first = (su_localinfo_t *)buffer;
   memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra);
   ifc.ifc_buf = buffer + sizeof(su_localinfo_t) + su_xtra;
+#if HAVE_OPEN_C
+  if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) {
+    SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", 
+               su_strerror(su_errno())));
+    error = ELI_SYSTEM;
+    goto err;
+  }
+#else
   if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
     SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n", 
                su_strerror(su_errno())));
     error = ELI_SYSTEM;
     goto err;
   }
+#endif
 
   buffer = ifc.ifc_buf + ifc.ifc_len;
 
@@ -594,6 +648,42 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
 
     SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index));
 
+
+#if HAVE_OPEN_C
+    su_close(s);
+
+    li = calloc(1, sizeof(su_localinfo_t));
+    sa = calloc(1, sizeof(su_sockaddr_t));
+
+    if (su_get_local_ip_addr(sa) < 0)
+      goto err;
+      
+    li->li_family = sa->su_family;
+    li->li_scope = LI_SCOPE_GLOBAL /* scope */;
+    li->li_index = if_index;
+    li->li_addrlen = su_sockaddr_size(sa);
+    li->li_addr = sa;
+
+    if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
+      goto err;
+
+    if (canonname) {
+      if (strchr(canonname, ':') ||
+         strspn(canonname, "0123456789.") == strlen(canonname))
+           li->li_flags |= LI_NUMERIC;
+    }
+    else
+      li->li_flags = 0;
+
+    li->li_canonname = canonname;
+
+    canonname = NULL;
+
+    *rresult = li;
+
+    return 0;
+#endif
+
 #if defined(SIOCGIFFLAGS)
     ifreq[0] = *ifr;
     if (ioctl(s, SIOCGIFFLAGS, ifreq) < 0) {
@@ -703,6 +793,7 @@ err:
 
   return error;
 }
+#endif /* __APPLE_CC__ */
 #else
 static
 int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
index b02a5dbbd7545f05373a17a658e789e75fac4077..fd30ef9920c9a0707ba365ee5393fb568d990fd1 100644 (file)
@@ -246,6 +246,10 @@ void su_log_soft_set_level(su_log_t *log, unsigned level)
   } else {
     log->log_level = level;
     log->log_init = 2;
+
+    if (explicitly_initialized == not_initialized)
+      explicitly_initialized = getenv("SHOW_DEBUG_LEVELS");
+
     if (explicitly_initialized)
       su_llog(log, 0, "%s: soft set log to level %u\n", 
              log->log_name, log->log_level);
diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_open_c_localinfo.cpp b/libs/sofia-sip/libsofia-sip-ua/su/su_open_c_localinfo.cpp
new file mode 100644 (file)
index 0000000..ed6250c
--- /dev/null
@@ -0,0 +1,147 @@
+/*\r
+ * This file is part of the Sofia-SIP package\r
+ *\r
+ * Copyright (C) 2005 Nokia Corporation.\r
+ *\r
+ * Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public License\r
+ * as published by the Free Software Foundation; either version 2.1 of\r
+ * the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful, but\r
+ * WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\r
+ * 02110-1301 USA\r
+ *\r
+ */\r
+\r
+/**@ingroup su_open_c_localinfo.cpp\r
+ *\r
+ * @CFILE su_open_c_localinfo.cpp\r
+ * Functionality for choosing an access point for sockets on Symbian.\r
+ *\r
+ * @author Martti Mela <Martti.Mela@nokia.com>\r
+ * @date Created: Fri May 18 14:31:41 2007 mela\r
+ *\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <unistd.h>\r
+#include <in_sock.h> \r
+#include <es_sock.h>\r
+#include <e32base.h>\r
+#include <s32mem.h>\r
+#include <s32strm.h>\r
+#include <commdbconnpref.h>\r
+\r
+#include <sofia-sip/su.h>\r
+\r
+\r
+su_sockaddr_t sa_global[1];\r
+\r
+/* Copy IP address for the sockaddr structure.\r
+ *\r
+ * @param su pointer to allocated su_sockaddr_t structure\r
+ *\r
+ * @return 0 if successful.\r
+ */\r
+extern "C" int su_get_local_ip_addr(su_sockaddr_t *su)\r
+{\r
+       su->su_sin.sin_addr.s_addr = sa_global->su_sin.sin_addr.s_addr;\r
+       su->su_family = sa_global->su_family;\r
+       su->su_len = sa_global->su_len;\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+/* Set up the access point for the stack. Code adapted from Forum Nokia,\r
+ * http://wiki.forum.nokia.com/index.php/LocalDeviceIpAddress.\r
+ *\r
+ * @param su su_sockaddr_t structure\r
+ * @param ifindex pointer to interface index\r
+ *\r
+ * @return Connection object\r
+ */\r
+extern "C" void *su_localinfo_ap_set(su_sockaddr_t *su, int *ifindex)\r
+{\r
+  TCommDbConnPref iPref;\r
+  RSocketServ aSocketServ;\r
+  RSocket sock;\r
+  \r
+  /* Get the IAP id of the underlying interface of this RConnection */\r
+  TUint32 iapId;\r
+  \r
+  iPref.SetDirection(ECommDbConnectionDirectionOutgoing);\r
+  iPref.SetDialogPreference(ECommDbDialogPrefPrompt);\r
+  iPref.SetBearerSet(KCommDbBearerUnknown /*PSD*/);\r
+  \r
+  aSocketServ = RSocketServ();\r
+  aSocketServ.Connect();\r
+  RConnection *aConnection = new RConnection();\r
+  aConnection->Open(aSocketServ);\r
+  aConnection->Start(iPref);\r
+  \r
+  User::LeaveIfError(sock.Open(aSocketServ, KAfInet, KSockStream,\r
+                              KProtocolInetTcp));\r
+  \r
+  User::LeaveIfError(aConnection->GetIntSetting(_L("IAP\\Id"), iapId));\r
+  \r
+  /* Get IP information from the socket */\r
+  TSoInetInterfaceInfo ifinfo;\r
+  TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);\r
+  \r
+  TSoInetIfQuery ifquery;\r
+  TPckg<TSoInetIfQuery> ifquerypkg(ifquery);\r
+  \r
+  /* To find out which interfaces are using our current IAP, we\r
+   * must enumerate and go through all of them and make a query\r
+   * by name for each. */\r
+  User::LeaveIfError(sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));\r
+  while(sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {\r
+    ifquery.iName = ifinfo.iName;\r
+    TInt err = sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);\r
+    \r
+    /* IAP ID is index 1 of iZone */\r
+    if(err == KErrNone && ifquery.iZone[1] == iapId) {\r
+      /* We have found an interface using the IAP we are interested in. */\r
+      if(ifinfo.iAddress.Address() > 0) {\r
+       /* found a IPv4 address */\r
+       su->su_sin.sin_addr.s_addr = htonl(ifinfo.iAddress.Address());\r
+       sa_global->su_sin.sin_addr.s_addr = su->su_sin.sin_addr.s_addr;\r
+       sa_global->su_family = su->su_family = AF_INET;\r
+       sa_global->su_len = su->su_len = 28;\r
+       *ifindex = iapId;\r
+       return (void *) aConnection;\r
+      }\r
+    }\r
+    else if(err != KErrNone)\r
+      break;\r
+  }\r
+  \r
+  sock.Close();\r
+}\r
+\r
+\r
+/* Deinitialize the access point in use.\r
+ *\r
+ * @param aconn Pointer to connection object\r
+ *\r
+ * @return 0 if successful.\r
+ */\r
+extern "C" int su_localinfo_ap_deinit(void *aconn)\r
+{\r
+  RConnection *aConnection = (RConnection *) aconn;\r
+  aConnection->Stop();\r
+  aConnection->Close();\r
+  delete aConnection;\r
+  return 0;\r
+}\r
index 619ffd03f217f9361911c70d855b1fc329caa368..24fd64b0b142acedf74b893ac816c0bee5f728ab 100644 (file)
@@ -123,7 +123,7 @@ typedef struct su_port_vtable {
   int (*su_port_remove_prepoll)(su_port_t *port,
                                su_root_t *root);
 
-  su_timer_t **(*su_port_timers)(su_port_t *port);
+  su_timer_queue_t *(*su_port_timers)(su_port_t *port);
 
   int (*su_port_multishot)(su_port_t *port, int multishot);
 
@@ -443,7 +443,7 @@ typedef struct su_base_port_s {
   su_msg_t        *sup_head, **sup_tail;
 
   /* Timer list */
-  su_timer_t      *sup_timers;
+  su_timer_queue_t sup_timers;
 
   unsigned         sup_running;          /**< In su_root_run() loop? */
 } su_base_port_t;
index 9a00d64da51c6c4f56ad63cbfb69079c58e91ead..4c997090e0c20482b7503deffe2f2a10daa6200a 100644 (file)
@@ -459,8 +459,10 @@ int su_pthread_port_execute(su_task_r const task,
   struct su_pthread_port_execute frame = {
     { PTHREAD_MUTEX_INITIALIZER },
     { _ENeedsNormalInit, NULL },
-    function, arg, 0
+    NULL, NULL, 0
   };
+  frame.function = function;
+  frame.arg = arg;
 #else
   struct su_pthread_port_execute frame = {
     { PTHREAD_MUTEX_INITIALIZER },
index c6927b5a62ca8fb1c8b218fb285151e9baf20992..edec6fe3cf4f5e624e50b79c226f15c1bcc0b894 100644 (file)
@@ -313,7 +313,7 @@ int su_task_detach(su_task_r self)
  * @return A timer list of the task. If there are no timers, it returns
  * NULL.
  */
-su_timer_t **su_task_timers(su_task_r const task)
+su_timer_queue_t *su_task_timers(su_task_r const task)
 {
   return task ? su_port_timers(task->sut_port) : NULL;
 }
@@ -901,7 +901,7 @@ int su_msg_report(su_msg_r msg,
  * @retval -1 otherwise.
  */
 
-int su_msg_reply(su_msg_r reply, su_msg_r const msg,
+int su_msg_reply(su_msg_r reply, su_msg_cr msg,
                 su_msg_f wakeup, isize_t size)
 {
   su_msg_r msg0;
index 4319c9c319cd6aef5f33edba3e7f5c859f31686c..dea157a5b717a959b61a6ec75fdcd3cb17ab5a10 100644 (file)
@@ -66,7 +66,7 @@ unsigned longlong strtoull(const char *, char **, int);
  *
  * Object-oriented tag routines for Sofia utility library.
  *
- * The <su_tag.h> defines a interface to object-oriented tag list routines. 
+ * The <sofia-sip/su_tag.h> defines a interface to object-oriented tag list routines. 
  * A tag list is a linear list (array) of tag items, tagi_t structures,
  * terminated by a TAG_END() item. Each tag item has a label, tag, (@c
  * t_tag) and a value (@c t_value). The tag is a pointer (tag_type_t) to a
@@ -112,7 +112,7 @@ unsigned longlong strtoull(const char *, char **, int);
  * - TAG_NEXT() - contains a pointer to the next tag list.
  *
  * The tag type structures are declared as tag_typedef_t. They can be
- * defined by the macros found in <su_tag_class.h>. See nta_tag.c or
+ * defined by the macros found in <sofia-sip/su_tag_class.h>. See nta_tag.c or
  * su_tag_test.c for an example.
  *
  */
index cb9ba9341bf27c4d4d6ae48ad57316c99782517c..0474e4430a8c141f4a40f757a8e979086ce556cf 100644 (file)
@@ -61,7 +61,7 @@
  * OS-independent timing functions and types for the @b su library.
  *  
  * The @b su library provides three different time formats with different
- * ranges and epochs in the file @b su_time.h:
+ * ranges and epochs in <sofia-sip/su_time.h>:
  *
  *   - #su_time_t, second and microsecond as 32-bit values since 1900,
  *   - #su_duration_t, milliseconds between two times, and
@@ -209,6 +209,8 @@ const su_t64_t su_res64 = (su_t64_t)1000000UL;
   (su_res64 * (su_t64_t)(tv).tv_sec + (su_t64_t)(tv).tv_usec)
 #define SU_DUR_TO_T64(d) (1000 * (int64_t)(d))
 
+#define E9 (1000000000)
+
 /** Get NTP timestamp.
  *
  * The function su_ntp_now() returns the current NTP timestamp.  NTP
@@ -219,22 +221,36 @@ const su_t64_t su_res64 = (su_t64_t)1000000UL;
  */
 su_ntp_t su_ntp_now(void)
 {
-  su_time_t t;
-  uint32_t sec, usec;
-
-  su_time(&t);
+  su_nanotime_t now;
 
-  sec = t.tv_sec;
-  usec = t.tv_usec;
+  su_nanotime(&now);
 
-  /*
-   * Multiply usec by 4294.967296 (ie. 2**32 / 1E6)
-   * 
-   * Utilize fact that 4294.967296 == 4295 - 511 / 15625 
-   */
-  usec = 4295 * usec - (511 * usec + 7812) / 15625;
+  if (sizeof(long) == sizeof(now)) {
+    return ((now / E9) << 32) | ((((now % E9) << 32) + E9/2) / E9);
+  }
+  else {
+    su_nanotime_t usec;
+    int nsec;
+    unsigned rem;
+
+    usec = now / 1000;
+    nsec = now % 1000;
+    
+    /*
+     * Multiply usec by 4294.967296 (ie. 2**32 / 1E6)
+     * 
+     * Utilize fact that 4294.967296 == 4295 - 511 / 15625 
+     */
+    now = 4295 * usec - 511 * usec / 15625;
+    rem = (511U * usec) % 15625U;
   
-  return ((su_ntp_t)sec << 32) + (su_ntp_t)usec;
+    /* Multiply nsec by 4.294967296 */
+    nsec = 4295 * 125 * nsec - (511 * nsec) / 125;
+    nsec -= 8 * rem; /* usec rounding */
+    nsec = (nsec + (nsec < 0 ? -62499 : +62499)) / 125000;
+    
+    return now + nsec;
+  }
 }
 
 /** Get NTP seconds.
@@ -263,7 +279,6 @@ uint32_t su_ntp_hi(su_ntp_t ntp)
   return (uint32_t) (ntp >> 32) & 0xffffffffLU;
 }
 
-
 su_ntp_t su_ntp_hilo(uint32_t hi, uint32_t lo)
 {
   return ((((su_ntp_t)hi) << 32)) | lo;
@@ -464,8 +479,3 @@ uint64_t su_nanocounter(void)
 }
 
 #endif /* WIN32 */
-
-
-
-
-
index 7f4c6bcebf35b62a3543158496510b269a91fdb2..5e504e33be1f2293a233b986e1c891c57858da8c 100644 (file)
@@ -44,6 +44,8 @@
 #include "sofia-sip/su_time.h"
 #include "su_module_debug.h"
 
+#include <time.h>
+
 #if HAVE_SYS_TIME_H
 #include <sys/time.h> /* Get struct timeval */
 #endif
 
 /** Seconds from 1.1.1900 to 1.1.1970 */
 #define NTP_EPOCH 2208988800UL 
+#define E9 (1000000000U)
+#define E7 (10000000U)
+
+/* Hooks for testing timing and timers */
+void (*_su_time)(su_time_t *tv);
+uint64_t (*_su_nanotime)(uint64_t *);
 
 /** Get current time.
  *
@@ -83,11 +91,128 @@ void su_time(su_time_t *tv)
 
   GetSystemTimeAsFileTime(date.ft);
 
-  tv->tv_usec = (unsigned long) ((date.ull->QuadPart % 10000000U) / 10);
-  tv->tv_sec = (unsigned long) ((date.ull->QuadPart / 10000000U) - 
+  tv->tv_usec = (unsigned long) ((date.ull->QuadPart % E7) / 10);
+  tv->tv_sec = (unsigned long) ((date.ull->QuadPart / E7) - 
     /* 1900-Jan-01 - 1601-Jan-01: 299 years, 72 leap years */
     (299 * 365 + 72) * 24 * 60 * (uint64_t)60);
 #else
 #error no su_time() implementation
+#endif
+
+  if (_su_time)
+    _su_time(tv);
+}
+
+/** Get current time as nanoseconds since epoch.
+ *
+ * Return the current NTP timestamp expressed as nanoseconds since epoch
+ * (January 1st 1900).
+ *
+ * @param return_time optional pointer to current time to return
+ *
+ * @return Nanoseconds since epoch
+ */
+su_nanotime_t su_nanotime(su_nanotime_t *return_time)
+{
+  su_nanotime_t now;
+
+  if (!return_time)
+    return_time = &now;
+
+#if HAVE_CLOCK_GETTIME
+  {
+    struct timespec tv;
+  
+    if (clock_gettime(CLOCK_REALTIME, &tv) == 0) {
+      now = ((su_nanotime_t)tv.tv_sec + NTP_EPOCH) * E9 + tv.tv_nsec;
+      *return_time = now;
+      if (_su_nanotime)
+       return _su_nanotime(return_time);
+      return now;
+    }
+  }
+#endif
+
+#if HAVE_FILETIME
+  {
+    union {
+      FILETIME       ft[1];
+      ULARGE_INTEGER ull[1];
+    } date;
+    
+    GetSystemTimeAsFileTime(date.ft);
+
+    now = 100 * 
+      (date.ull->QuadPart - 
+       /* 1900-Jan-01 - 1601-Jan-01: 299 years, 72 leap years */
+       ((su_nanotime_t)(299 * 365 + 72) * 24 * 60 * 60) * E7);
+  }
+#elif HAVE_GETTIMEOFDAY
+  {
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+
+    now = ((su_nanotime_t)tv.tv_sec + NTP_EPOCH) * E9 + tv.tv_usec * 1000;
+  }
+#else
+  now = ((su_nanotime_t)time() + NTP_EPOCH) * E9;
+#endif
+
+  *return_time = now;
+
+  if (_su_nanotime)
+    return _su_nanotime(return_time);
+
+  return now;
+}
+
+/** Get current time as nanoseconds.
+ *
+ * Return the current time expressed as nanoseconds. The time returned is
+ * monotonic and never goes back - if the underlying system supports such a
+ * clock.
+ *
+ * @param return_time optional pointer to return the current time 
+ *
+ * @return Current time as nanoseconds 
+ */
+su_nanotime_t su_monotime(su_nanotime_t *return_time)
+{
+#if HAVE_CLOCK_GETTIME
+  {
+    struct timespec tv;
+  
+    if (clock_gettime(CLOCK_MONOTONIC, &tv) == 0) {
+      su_nanotime_t now = (su_nanotime_t)tv.tv_sec * E9 + tv.tv_nsec;
+      if (return_time)
+       *return_time = now;
+      return now;
+    }
+  }
+#endif
+
+#if HAVE_NANOUPTIME
+  {
+    struct timespec tv;
+  
+    nanouptime(&tv);
+    now = (su_nanotime_t)tv.tv_sec * E9 + tv.tv_nsec;
+    if (return_time)
+      *return_time = now;
+    return now;
+  }
+#elif HAVE_MICROUPTIME
+  {
+    struct timeval tv;
+
+    microuptime(&tv);
+    now = (su_nanotime_t)tv.tv_sec * E9 + tv.tv_usec * 1000;
+    if (return_time)
+      *return_time = now;
+    return now;
+  }
+#else
+  return su_nanotime(return_time);
 #endif
 }
index 9bbe5426e552eeea54e6345bef5fc133f13eb821..91a4951543a4ebdfcbc4d8c859ab04c02d5112d5 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "config.h"
 
+#include "su_port.h"
 #include "sofia-sip/su.h"
 #include "sofia-sip/su_wait.h"
 #include "sofia-sip/su_alloc.h"
@@ -182,8 +183,8 @@ enum sut_running {
 
 RBTREE_PROTOS(su_inline, timers, su_timer_t);
 
-su_inline int timers_append(su_timer_t **, su_timer_t *);
-su_inline void timers_remove(su_timer_t **, su_timer_t *);
+su_inline int timers_append(su_timer_queue_t *, su_timer_t *);
+su_inline void timers_remove(su_timer_queue_t *, su_timer_t *);
 su_inline su_timer_t *timers_succ(su_timer_t const *);
 su_inline su_timer_t *timers_prec(su_timer_t const *);
 su_inline su_timer_t *timers_first(su_timer_t const *);
@@ -199,7 +200,7 @@ RBTREE_BODIES(su_inline, timers, su_timer_t,
  * @retval 0 when successful (always)
  */
 su_inline int
-su_timer_set0(su_timer_t **timers,
+su_timer_set0(su_timer_queue_t *timers,
              su_timer_t *t,
              su_timer_f wakeup,
              su_wakeup_arg_t *arg,
@@ -221,7 +222,7 @@ su_timer_set0(su_timer_t **timers,
  * @retval 0 when successful (always)
  */
 su_inline int
-su_timer_reset0(su_timer_t **timers,
+su_timer_reset0(su_timer_queue_t *timers,
                su_timer_t *t)
 {
   if (SU_TIMER_IS_SET(t))
@@ -242,11 +243,11 @@ su_timer_reset0(su_timer_t **timers,
  * @retval NULL upon an error
  */
 static
-su_timer_t **su_timer_tree(su_timer_t const *t,
-                          int use_sut_duration,
-                          char const *caller)
+su_timer_queue_t *su_timer_tree(su_timer_t const *t,
+                               int use_sut_duration,
+                               char const *caller)
 {
-  su_timer_t **timers;
+  su_timer_queue_t *timers;
 
   if (t == NULL) {
     SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
@@ -286,11 +287,10 @@ su_timer_t *su_timer_create(su_task_r const task, su_duration_t msec)
 
   assert(msec >= 0);
 
-  if (su_task_cmp(task, su_task_null))
-    retval = su_zalloc(NULL, sizeof(*retval));
-  else
-    retval = NULL;
+  if (!su_task_cmp(task, su_task_null))
+    return NULL;
 
+  retval = su_zalloc(NULL, sizeof(*retval));
   if (retval) {
     su_task_copy(retval->sut_task, task);
     retval->sut_duration = msec;
@@ -308,7 +308,7 @@ su_timer_t *su_timer_create(su_task_r const task, su_duration_t msec)
 void su_timer_destroy(su_timer_t *t)
 {
   if (t) {
-    su_timer_t **timers = su_task_timers(t->sut_task);
+    su_timer_queue_t *timers = su_task_timers(t->sut_task);
     if (timers)
       su_timer_reset0(timers, t);
     su_task_deinit(t->sut_task);
@@ -332,7 +332,7 @@ int su_timer_set_interval(su_timer_t *t,
                          su_timer_arg_t *arg,
                          su_duration_t interval)
 {
-  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_interval");
+  su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_interval");
 
   if (t == NULL)
     return -1;
@@ -356,7 +356,7 @@ int su_timer_set(su_timer_t *t,
                 su_timer_f wakeup,
                 su_timer_arg_t *arg)
 {
-  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set");
+  su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_set");
 
   if (timers == NULL)
     return -1;
@@ -380,7 +380,7 @@ int su_timer_set_at(su_timer_t *t,
                    su_wakeup_arg_t *arg,
                    su_time_t when)
 {
-  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_at");
+  su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_set_at");
 
   if (timers == NULL)
     return -1;
@@ -410,7 +410,7 @@ int su_timer_run(su_timer_t *t,
                 su_timer_f wakeup,
                 su_timer_arg_t *arg)
 {
-  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_run");
+  su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_run");
   su_time_t now;
 
   if (timers == NULL)
@@ -443,7 +443,7 @@ int su_timer_set_for_ever(su_timer_t *t,
                          su_timer_f wakeup,
                          su_timer_arg_t *arg)
 {
-  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
+  su_timer_queue_t *timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
   su_time_t now;
 
   if (timers == NULL)
@@ -466,7 +466,7 @@ int su_timer_set_for_ever(su_timer_t *t,
  */
 int su_timer_reset(su_timer_t *t)
 {
-  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_reset");
+  su_timer_queue_t *timers = su_timer_tree(t, 0, "su_timer_reset");
 
   if (timers == NULL)
     return -1;
@@ -487,7 +487,7 @@ int su_timer_reset(su_timer_t *t)
  * @return
  * The number of expired timers.
  */
-int su_timer_expire(su_timer_t ** const timers,
+int su_timer_expire(su_timer_queue_t * const timers,
                    su_duration_t *timeout,
                    su_time_t now)
 {
@@ -571,7 +571,7 @@ su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now)
  *
  * @return Number of timers reset.
  */
-int su_timer_reset_all(su_timer_t **timers, su_task_r task)
+int su_timer_reset_all(su_timer_queue_t *timers, su_task_r task)
 {
   su_timer_t *t, *t_next;
   int n = 0;
index 4765ce6dc93f75d6bb4da1e0880943e9f5c24c5c..42ce16f765dbd8825f192c97cad45db7dfb79450 100644 (file)
@@ -92,7 +92,7 @@ HEADER {
         "#include \"config.h\"\n\n"\
         "#include <sofia-sip/su_tag_class.h>\n"\
         "\n"\
-        "#ifdef _WIN32\n"\
+        "#if defined _WIN32 || defined HAVE_OPEN_C\n"\
         "#define EXPORT __declspec(dllexport)\n"\
         "#else\n"\
         "#define EXPORT\n"\
index 7e3d870882e79338aee5de068c28f55ada82147e..21a23865b3fef5b155f3a7e49553e0ab98abd52b 100644 (file)
@@ -24,7 +24,7 @@
 
 /**@ingroup su_root_ex
  * @file test_poll.c
- * Example code for su_wait.h.
+ * Example code for <sofia-sip/su_wait.h>.
  *
  * This file illustrates how the asynchronous connect can be used with @b su.
  *
diff --git a/libs/sofia-sip/libsofia-sip-ua/su/torture_heap.c b/libs/sofia-sip/libsofia-sip-ua/su/torture_heap.c
new file mode 100644 (file)
index 0000000..d501358
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * This file is part of the Sofia-SIP package
+ *
+ * Copyright (C) 2007 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
+ *
+ */
+
+/**
+ * @file torture_heap.c
+ * @brief Test heap
+ *
+ * @author Pekka Pessi <Pekka.Pessi@nokia.com>
+ */
+
+#include "config.h"
+
+#include <sofia-sip/heap.h>
+
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+typedef struct {
+  unsigned key, value;
+  size_t index;
+} type1, *type2;
+
+static type1 const null = { 0, 0, 0 };
+
+static inline
+int less1(type1 a, type1 b)
+{
+  return a.key < b.key;
+}
+
+static inline
+void set1(type1 *heap, size_t index, type1 e)
+{
+  assert(index > 0);
+  e.index = index;
+  heap[index] = e;
+}
+
+#define alloc(a, o, size) realloc((o), (size))
+
+static inline
+int less2(type2 a, type2 b)
+{
+  return a->key < b->key;
+}
+
+static inline
+void set2(type2 *heap, size_t index, type2 e)
+{
+  assert(index > 0);
+  e->index = index;
+  heap[index] = e;
+}
+
+#define scope static
+
+/* Define heap having structs as its elements */
+
+typedef HEAP_TYPE Heap1;
+
+HEAP_DECLARE(static, Heap1, heap1_, type1);
+HEAP_BODIES(static, Heap1, heap1_, type1, less1, set1, alloc, null);
+
+/* Define heap having pointers as its elements */
+
+typedef HEAP_TYPE Heap2;
+
+HEAP_DECLARE(static, Heap2, heap2_, type1 *);
+HEAP_BODIES(static, Heap2, heap2_, type1 *, less2, set2, alloc, NULL);
+
+/* ====================================================================== */
+
+int tstflags;
+
+#define TSTFLAGS tstflags
+
+#include <sofia-sip/tstdef.h>
+
+char name[] = "torture_heap";
+
+int test_value()
+{
+  BEGIN();
+
+  Heap1 heap = { NULL };
+  unsigned i, previous, n, N;
+  unsigned char *tests;
+
+  N = 300000;
+
+  TEST_1(tests = calloc(sizeof (unsigned char), N + 1));
+
+  TEST(heap1_resize(NULL, &heap, 0), 0);
+
+  /* Add N entries in reverse order */
+  for (i = N; i > 0; i--) {
+    type1 e = { i / 10, i, 0 };
+    if (heap1_is_full(heap))
+      TEST(heap1_resize(NULL, &heap, 0), 0);
+    TEST(heap1_is_full(heap), 0);
+    TEST(heap1_add(heap, e), 0);
+    tests[i] |= 1;
+  }
+
+  TEST(heap1_used(heap), N);
+
+  for (i = 1; i <= N; i++) {
+    type1 const e = heap1_get(heap, i);
+
+    TEST(e.index, i);
+    TEST(tests[e.value] & 2, 0);
+    tests[e.value] |= 2;
+
+    if (2 * i <= N) {
+      type1 const left = heap1_get(heap, 2 * i);
+      TEST_1(e.key <= left.key);
+    }
+
+    if (2 * i + 1 <= N) {
+      type1 const right = heap1_get(heap, 2 * i + 1);
+      TEST_1(e.key <= right.key);
+    }
+  }
+
+  /* Remove N entries */
+  previous = 0;
+
+  for (n = 0; heap1_used(heap) > 0; n++) {
+    type1 const e = heap1_get(heap, 1);
+    TEST_1(previous <= e.key);
+
+    TEST(tests[e.value] & 4, 0);
+    tests[e.value] |= 4;
+
+    previous = e.key;
+    TEST(heap1_remove(heap, 1).index, 1);
+  }
+  TEST(n, N);
+
+  /* Add N entries in reverse order */
+  for (i = N; i > 0; i--) {
+    type1 e = { i / 10, i, 0 };
+    if (heap1_is_full(heap))
+      TEST(heap1_resize(NULL, &heap, 0), 0);
+    TEST(heap1_is_full(heap), 0);
+    TEST(heap1_add(heap, e), 0);
+  }
+
+  TEST(heap1_used(heap), N);
+
+  /* Remove 1000 entries from random places */
+  previous = 0;
+
+  for (i = 0; i < 1000 && heap1_used(heap) > 0; i++) {
+    type1 e;
+    n = i * 397651 % heap1_used(heap) + 1;
+    e = heap1_get(heap, n);
+    TEST(e.index, n);
+    TEST(tests[e.value] & 8, 0); tests[e.value] |= 8;
+    TEST(heap1_remove(heap, n).index, n);
+  }
+
+  for (i = 1; i <= heap1_used(heap); i++) {
+    type1 e = heap1_get(heap, i);
+    type1 left = heap1_get(heap, 2 * i);
+    type1 right = heap1_get(heap, 2 * i + 1);
+    TEST_1(left.index == 0 || e.key <= left.key);
+    TEST_1(right.index == 0 || e.key <= right.key);
+  }
+
+  /* Remove rest */
+  for (n = 0, previous = 0; heap1_used(heap) > 0; n++) {
+    type1 e = heap1_get(heap, 1);
+    TEST(e.index, 1);
+    TEST(tests[e.value] & 8, 0);
+    tests[e.value] |= 8;
+    TEST_1(previous <= e.key);
+    previous = e.key;
+    TEST(heap1_remove(heap, 1).index, 1);
+  }
+
+  for (i = 1; i <= N; i++) {
+    TEST(tests[i], 8 | 4 | 2 | 1);
+  }
+
+  TEST(heap1_resize(NULL, &heap, 63), 0);
+  TEST(heap1_size(heap), 63);
+
+  TEST(heap1_free(NULL, &heap), 0);
+  free(tests);
+
+  END();
+}
+
+int test_ref()
+{
+  BEGIN();
+
+  Heap2 heap = { NULL };
+  unsigned i, previous, n, N;
+  unsigned char *tests;
+  type1 *items;
+
+  N = 300000;
+
+  TEST_1(tests = calloc(sizeof (unsigned char), N + 1));
+  TEST_1(items = calloc((sizeof *items), N + 1));
+
+  TEST(heap2_resize(NULL, &heap, 0), 0);
+
+  /* Add N entries in reverse order */
+  for (i = N; i > 0; i--) {
+    type2 e = items + i;
+
+    e->key = i / 10, e->value = i;
+
+    if (heap2_is_full(heap))
+      TEST(heap2_resize(NULL, &heap, 0), 0);
+    TEST(heap2_is_full(heap), 0);
+    TEST(heap2_add(heap, e), 0);
+    tests[i] |= 1;
+  }
+
+  TEST(heap2_used(heap), N);
+
+  for (i = 1; i <= N; i++) {
+    type2 const e = heap2_get(heap, i);
+
+    TEST_1(e);
+    TEST(e->index, i);
+    TEST(tests[e->value] & 2, 0);
+    tests[e->value] |= 2;
+
+    if (2 * i <= N) {
+      type2 const left = heap2_get(heap, 2 * i);
+      TEST_1(e->key <= left->key);
+    }
+
+    if (2 * i + 1 <= N) {
+      type2 const right = heap2_get(heap, 2 * i + 1);
+      TEST_1(e->key <= right->key);
+    }
+  }
+
+  /* Remove N entries */
+  previous = 0;
+
+  for (n = 0; heap2_used(heap) > 0; n++) {
+    type2 const e = heap2_get(heap, 1);
+
+    TEST_1(e);
+    TEST_1(previous <= e->key);
+
+    TEST(tests[e->value] & 4, 0);
+    tests[e->value] |= 4;
+
+    previous = e->key;
+    TEST(heap2_remove(heap, 1), e);
+  }
+  TEST(n, N);
+
+  /* Add N entries in reverse order */
+  for (i = N; i > 0; i--) {
+    type2 e = items + i;
+
+    if (heap2_is_full(heap))
+      TEST(heap2_resize(NULL, &heap, 0), 0);
+    TEST(heap2_is_full(heap), 0);
+    TEST(heap2_add(heap, e), 0);
+  }
+
+  TEST(heap2_used(heap), N);
+
+  /* Remove 1000 entries from random places */
+  previous = 0;
+
+  for (i = 0; i < 1000 && heap2_used(heap) > 0; i++) {
+    type2 e;
+    n = i * 397651 % heap2_used(heap) + 1;
+    e = heap2_get(heap, n);
+    TEST_1(e); TEST(e->index, n);
+    TEST(tests[e->value] & 8, 0); tests[e->value] |= 8;
+    TEST(heap2_remove(heap, n), e);
+  }
+
+  for (i = 1; i <= heap2_used(heap); i++) {
+    type2 e = heap2_get(heap, i);
+
+    TEST_1(e); TEST(e->index, i);
+
+    if (2 * i <= heap2_used(heap)) {
+      type2 const left = heap2_get(heap, 2 * i);
+      TEST_1(left);
+      TEST_1(e->key <= left->key);
+    }
+
+    if (2 * i + 1 <= heap2_used(heap)) {
+      type2 const right = heap2_get(heap, 2 * i + 1);
+      TEST_1(right);
+      TEST_1(e->key <= right->key);
+    }
+  }
+
+  /* Remove rest */
+  for (n = 0, previous = 0; heap2_used(heap) > 0; n++) {
+    type2 e = heap2_remove(heap, 1);
+    TEST_1(e); TEST(e->index, 1);
+    TEST(tests[e->value] & 8, 0);
+    tests[e->value] |= 8;
+    TEST_1(previous <= e->key);
+    previous = e->key;
+  }
+
+  for (i = 1; i <= N; i++) {
+    TEST(tests[i], 8 | 4 | 2 | 1);
+  }
+
+  TEST(heap2_resize(NULL, &heap, 63), 0);
+  TEST(heap2_size(heap), 63);
+
+  TEST(heap2_free(NULL, &heap), 0);
+  free(tests);
+  free(items);
+
+  END();
+}
+
+void usage(int exitcode)
+{
+  fprintf(stderr,
+         "usage: %s [-v] [-a]\n",
+         name);
+  exit(exitcode);
+}
+
+int main(int argc, char *argv[])
+{
+  int retval = 0;
+  int i;
+
+  for (i = 1; argv[i]; i++) {
+    if (strcmp(argv[i], "-v") == 0)
+      tstflags |= tst_verbatim;
+    else if (strcmp(argv[i], "-a") == 0)
+      tstflags |= tst_abort;
+    else
+      usage(1);
+  }
+
+  retval |= test_value(); fflush(stdout);
+  retval |= test_ref(); fflush(stdout);
+
+  return retval;
+}
index c1aef30624b51b28f1bc894cd4ee2e5b4af48f03..3de0fd591fa2b035003e2b6b0c4148ccdeabce54 100644 (file)
@@ -275,8 +275,16 @@ static int test_stackargs(int l, ...) { return 0; }
 /** Test tl_list, tl_llist and tl_dup */
 static int test_dup(void)
 {
-  tagi_t const rest[] = {{ TAG_A("Foo") }, { TAG_NULL() }};
   tagi_t *lst, *dup;
+#if HAVE_OPEN_C
+  tagi_t rest[2];
+  rest[0].t_tag = tag_a;
+  rest[0].t_value = tag_str_v("Foo");
+  rest[1].t_tag = (tag_type_t)0;
+  rest[0].t_value = (tag_value_t)0;
+#else
+  tagi_t const rest[] = {{ TAG_A("Foo") }, { TAG_NULL() }};
+#endif
 
   BEGIN();
 
index 40edd01bbf9655f9c8a5d65943fb8e4c72633181..e71e7ccea8471ea430082475fe031a8f82c9561d 100644 (file)
 
 char const *name = "torture_su_time.c";
 
+int expensive_tests = 0;
+
 static int test1(int flags);
 static int test2(int flags);
 static int test3(int flags);
 
-void usage(int exitcode)
-{
-  fprintf(stderr, 
-         "usage: %s [-v] [-a]\n", 
-         name);
-  exit(exitcode);
-}
-
-char *lastpart(char *path)
-{
-  if (strchr(path, '/')) 
-    return strrchr(path, '/') + 1;
-  else
-    return path;
-}
+su_time_t tv0;
 
-int main(int argc, char *argv[])
+void su_time0(su_time_t *tv)
 {
-  int flags = 0;
-  int retval = 0;
-  int i;
-
-  name = lastpart(argv[0]);  /* Set our name */
-
-  for (i = 1; argv[i]; i++) {
-    if (strcmp(argv[i], "-v") == 0)
-      flags |= tst_verbatim;
-    else if (strcmp(argv[i], "-a") == 0)
-      flags |= tst_abort;
-    else
-      usage(1);
-  }
-
-  retval |= test1(flags); fflush(stdout);
-  retval |= test2(flags); fflush(stdout);
-  retval |= test3(flags); fflush(stdout);
-
-  return retval;
+  *tv = tv0;
 }
 
-su_time_t tv0;
+uint64_t nanotime;
 
-void su_time(su_time_t *tv)
+uint64_t su_nanotime0(uint64_t *retval)
 {
-  *tv = tv0;
+  if (nanotime)
+    return *retval = nanotime;
+  else
+    return *retval = (uint64_t)tv0.tv_sec * 1000000000U + tv0.tv_usec * 1000U;
 }
 
+#define E9 (1000000000U)
+
 int test1(int flags)
 {
   uint32_t ntp_hi, ntp_lo, ntp_mw;
   su_time_t now;
   su_ntp_t ntp, ntp0, ntp1;
+  uint64_t increment = 3019;
   
   BEGIN();
 
@@ -136,8 +111,20 @@ int test1(int flags)
   TEST64(su_ntp_hi(ntp), ntp_hi);
   TEST64(su_ntp_lo(ntp), 0);
   TEST64(su_ntp_mw(ntp), (ntp_hi & 0xffff) << 16);
+
   TEST(su_ntp_fraq(tv0), su_ntp_mw(ntp));
 
+  if (expensive_tests)
+    increment = 1;
+
+  for (nanotime = 1; nanotime <= 2 * E9; nanotime += increment) {
+    ntp = su_ntp_now();
+    ntp0 = ((nanotime / E9) << 32) | ((((nanotime % E9) << 32) + E9/2) / E9);
+    TEST(ntp, ntp0);
+  }
+
+  nanotime = 0;
+
   END();
 }
 
@@ -157,6 +144,7 @@ int test2(int flags)
 
   BEGIN();
 
+  nanotime = 0;
   tv0.tv_sec = 268435455;
   tv0.tv_usec = 98765;
 
@@ -165,10 +153,10 @@ int test2(int flags)
 
   su_guid_generate(g1);
   seq1 = ((g1->s.clock_seq_hi_and_reserved & 0x3f) << 8) + g1->s.clock_seq_low;
-  TEST(g1->s.time_low, htonl(tl & 0xffffFFFFU));
-  TEST(g1->s.time_mid, htons((tl >> 32) & 0xffffU));
-  TEST(g1->s.time_high_and_version, htons(((tl >> 48) & 0xfffU) | 0x1000));
   TEST(g1->s.clock_seq_hi_and_reserved & 0xc0, 0x80);
+  TEST(g1->s.time_high_and_version, htons(((tl >> 48) & 0xfffU) | 0x1000));
+  TEST(ntohs(g1->s.time_mid), (tl >> 32) & 0xffffU);
+  //TEST(ntohl(g1->s.time_low), tl & 0xffffFFFFU);
 
   TEST(i = su_guid_sprintf(buf, sizeof(buf), g1), su_guid_strlen);
   TEST_SIZE(strlen(buf), i);
@@ -219,3 +207,56 @@ int test3(int flags)
 
   END();
 }
+
+void su_time0(su_time_t *tv);
+uint64_t su_nanotime0(uint64_t *);
+
+extern void (*_su_time)(su_time_t *tv);
+extern uint64_t (*_su_nanotime)(uint64_t *);
+
+void usage(int exitcode)
+{
+  fprintf(stderr, 
+         "usage: %s [-v] [-a]\n", 
+         name);
+  exit(exitcode);
+}
+
+char *lastpart(char *path)
+{
+  if (strchr(path, '/')) 
+    return strrchr(path, '/') + 1;
+  else
+    return path;
+}
+
+int main(int argc, char *argv[])
+{
+  int flags = 0;
+  int retval = 0;
+  int i;
+
+  name = lastpart(argv[0]);  /* Set our name */
+
+  for (i = 1; argv[i]; i++) {
+    if (strcmp(argv[i], "-v") == 0)
+      flags |= tst_verbatim;
+    else if (strcmp(argv[i], "-x") == 0)
+      expensive_tests = 1;
+    else if (strcmp(argv[i], "-a") == 0)
+      flags |= tst_abort;
+    else
+      usage(1);
+  }
+
+  if (getenv("EXPENSIVE_CHECKS"))
+    expensive_tests = 1;
+
+  _su_time = su_time0, _su_nanotime = su_nanotime0;
+
+  retval |= test1(flags); fflush(stdout);
+  retval |= test2(flags); fflush(stdout);
+  retval |= test3(flags); fflush(stdout);
+
+  return retval;
+}
index 4b7f63654a18e5f4f14ddabb7cebe631a16a699a..6d6e0903dba66e53592c95609e372ef3e2ddb4c3 100644 (file)
@@ -147,8 +147,8 @@ int main(int argc, char *argv[])
   char *argv0 = argv[0];
   char *s;
   int use_t1 = 0;
-  su_time_t now, started;
-  intptr_t i, N = 500;
+  su_time_t now, started, inserted;
+  unsigned i, N = 500;
 
   struct timing timing[1] = {{ 0 }};
   struct tester tester[1] = {{ 0 }};
@@ -240,22 +240,34 @@ int main(int argc, char *argv[])
   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);
+  now = started = su_now();
+
+  for (i = 0; i < N; i++) {
+    if (++now.tv_usec == 0) ++now.tv_sec;
+    su_timer_set_at(timers[i], increment, (void *)(intptr_t)i, now);
+  }
+
+  tester->sentinel = (void*)(intptr_t)(i - 1);
+
+  inserted = su_now();
 
   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);
+  now = su_now();
+
+  printf("Inserting %u timers took %f millisec\n", 
+        i, su_time_diff(inserted, started) * 1000);
+
+  printf("Processing %u/%u timers took %f millisec (%f expected)\n",
+        tester->times, i,
+        su_time_diff(now, started) * 1000,
+        (double)i / 1000);
 
   for (i = 0; i < N; i++) {
     su_timer_destroy(timers[i]);
index 69a25bac00bb7dad8eec7d9d54f5d8cedf38423d..e7355051a2c66b7db03eaaed2ae5dcd19eb36725 100644 (file)
@@ -1385,6 +1385,10 @@ int main(int argc, char *argv[])
       usage(1);
   }
 
+#if HAVE_OPEN_C
+  tstflags |= tst_verbatim;
+#endif
+
   /* Use log */
   if (flags & tst_verbatim)
     tport_log->log_default = 9;
@@ -1411,6 +1415,10 @@ int main(int argc, char *argv[])
 
   su_deinit();
 
+#if HAVE_OPEN_C
+  sleep(10);
+#endif
+
   return retval;
 }
 
index ea924b5aa6165fa7c1a52707e35f41780a455b99..66d31569d07a461f04d14f0f118528cdd0c263f1 100644 (file)
@@ -3746,6 +3746,11 @@ tport_resolve(tport_t *self, msg_t *msg, tp_name_t const *tpn)
   hints->ai_socktype = self->tp_addrinfo->ai_socktype;
   hints->ai_protocol = self->tp_addrinfo->ai_protocol;
 
+#if HAVE_OPEN_C
+  if (host_is_ip_address(tpn->tpn_host))
+    hints->ai_flags |= AI_NUMERICHOST;
+#endif
+  
   if (tpn->tpn_host[0] == '[') {
     /* Remove [] around IPv6 address */
     char *end;
index 468827e2f195b94c7da903b07fc755ac025145e5..db95fdd7515a7f848c4fc38012d9f85bd2983e5a 100644 (file)
@@ -61,7 +61,7 @@
 
 #include <sofia-sip/su_debug.h>
 
-#if !defined(MSG_NOSIGNAL) || defined(__CYGWIN__)
+#if !defined(MSG_NOSIGNAL) || defined(__CYGWIN__) || defined(SYMBIAN)
 #undef MSG_NOSIGNAL
 #define MSG_NOSIGNAL (0)
 #endif
index f89023313448a1cc1c65ec7b3c8d3ecb7d0839b1..2974ee383518c27e954cf711eabc7a5c1cde4ccb 100644 (file)
@@ -77,7 +77,7 @@ extern char const TPORT_DUMP[];       /* dummy declaration for Doxygen */
  * The TPORT_DEBUG environment variable is used to determine the debug logging
  * level for @b tport module. The default level is 3.
  * 
- * @sa <su_debug.h>, tport_log, SOFIA_DEBUG
+ * @sa <sofia-sip/su_debug.h>, tport_log, SOFIA_DEBUG
  */
 #ifdef DOXYGEN
 extern char const TPORT_DEBUG[]; /* dummy declaration for Doxygen */
index 98b7a848c5fbe51a1f90463530597e012cc84ff3..eec8279b1022522b11aba897929db6cff9aa8fbe 100644 (file)
@@ -50,7 +50,7 @@
 /* ---------------------------------------------------------------------- */
 /* TLS */
 
-#include <tport_tls.h>
+#include "tport_tls.h"
 
 static int tport_tls_init_primary(tport_primary_t *,
                                  tp_name_t tpn[1], 
index 72ea7127dc95be62ac5ec9b1a24f37acafa25779..df71c80f0286d091bd0420131a16e111177bc580 100644 (file)
 %CHECK%
 %TAG_AWK% NO_DLL=1 %P%/tport/tport_tag.c  < NUL
 %CHECK%
+%TAG_AWK% NO_DLL=1 %P%/su/su_tag.c  < NUL
+%CHECK%
 %TAG_AWK% NO_DLL=1 %P%/url/url_tag.c  < NUL
 %CHECK%
 
index aaf4686058ad733c0e90d30341197533a167e864..db56b208cd8a1ea95d9aa20286a629be1a16e0c0 100644 (file)
 /* #undef size_t */\r
 \r
 /* Define to 1 if compiling on Open C environment */\r
-/* #undef HAVE_OPEN_C */
\ No newline at end of file
+#define HAVE_OPEN_C 1
\ No newline at end of file
index 25a0629f5c6c06debfbc23cf30be64ec844f337c..2bd276f85f6733ba0eaaebc1c7f66621035672de 100644 (file)
-/*\r
-* ==============================================================================\r
-*  Name        : bld.inf\r
-*  Part of     : Camcorder\r
-*  Description : Camcorder application build information\r
-*  Version     : \r
-*\r
-*  Copyright (c) 2003-2006 Nokia Corporation.\r
-*  This material, including documentation and any related \r
-*  computer programs, is protected by copyright controlled by \r
-*  Nokia Corporation. All rights are reserved. Copying, \r
-*  including reproducing, storing, adapting or translating, any \r
-*  or all of this material requires the prior written consent of \r
-*  Nokia Corporation. This material also contains confidential \r
-*  information which may not be disclosed to others without the \r
-*  prior written consent of Nokia Corporation.\r
-* ==============================================================================\r
-*/\r
-\r
-PRJ_PLATFORMS\r
-DEFAULT\r
-\r
-PRJ_EXPORTS\r
-\r
-\r
-PRJ_MMPFILES\r
-\r
-libsofia-sip-ua.mmp\r
-\r
-torture_su_root.mmp\r
-torture_su_port.mmp\r
-torture_su_tag.mmp\r
-torture_su_alloc.mmp\r
-torture_url.mmp\r
-test_msg.mmp\r
-torture_sip.mmp\r
-\r
-PRJ_TESTMMPFILES\r
-\r
+//
+// bld.inf for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
+
+PRJ_PLATFORMS
+DEFAULT
+
+PRJ_EXPORTS
+
+../../libsofia-sip-ua/bnf/sofia-sip/bnf.h \epoc32\include\osextensions\sofia-sip\bnf.h
+../../libsofia-sip-ua/bnf/sofia-sip/hostdomain.h \epoc32\include\osextensions\sofia-sip\hostdomain.h
+../../libsofia-sip-ua/features/sofia-sip/sofia_features.h \epoc32\include\osextensions\sofia-sip\sofia_features.h
+../../libsofia-sip-ua/http/sofia-sip/http.h \epoc32\include\osextensions\sofia-sip\http.h
+../../libsofia-sip-ua/http/sofia-sip/http_hclasses.h \epoc32\include\osextensions\sofia-sip\http_hclasses.h
+../../libsofia-sip-ua/http/sofia-sip/http_header.h \epoc32\include\osextensions\sofia-sip\http_header.h
+../../libsofia-sip-ua/http/sofia-sip/http_parser.h \epoc32\include\osextensions\sofia-sip\http_parser.h
+../../libsofia-sip-ua/http/sofia-sip/http_protos.h \epoc32\include\osextensions\sofia-sip\http_protos.h
+../../libsofia-sip-ua/http/sofia-sip/http_status.h \epoc32\include\osextensions\sofia-sip\http_status.h
+../../libsofia-sip-ua/http/sofia-sip/http_tag.h \epoc32\include\osextensions\sofia-sip\http_tag.h
+../../libsofia-sip-ua/http/sofia-sip/http_tag_class.h \epoc32\include\osextensions\sofia-sip\http_tag_class.h
+../../libsofia-sip-ua/ipt/sofia-sip/base64.h \epoc32\include\osextensions\sofia-sip\base64.h
+../../libsofia-sip-ua/ipt/sofia-sip/rc4.h \epoc32\include\osextensions\sofia-sip\rc4.h
+../../libsofia-sip-ua/ipt/sofia-sip/token64.h \epoc32\include\osextensions\sofia-sip\token64.h
+../../libsofia-sip-ua/ipt/sofia-sip/uniqueid.h \epoc32\include\osextensions\sofia-sip\uniqueid.h
+../../libsofia-sip-ua/ipt/sofia-sip/utf8.h \epoc32\include\osextensions\sofia-sip\utf8.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_client.h \epoc32\include\osextensions\sofia-sip\auth_client.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_client_plugin.h \epoc32\include\osextensions\sofia-sip\auth_client_plugin.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_common.h \epoc32\include\osextensions\sofia-sip\auth_common.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_digest.h \epoc32\include\osextensions\sofia-sip\auth_digest.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_module.h \epoc32\include\osextensions\sofia-sip\auth_module.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_ntlm.h \epoc32\include\osextensions\sofia-sip\auth_ntlm.h
+../../libsofia-sip-ua/iptsec/sofia-sip/auth_plugin.h \epoc32\include\osextensions\sofia-sip\auth_plugin.h
+../../libsofia-sip-ua/msg/sofia-sip/msg.h \epoc32\include\osextensions\sofia-sip\msg.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_addr.h \epoc32\include\osextensions\sofia-sip\msg_addr.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_buffer.h \epoc32\include\osextensions\sofia-sip\msg_buffer.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_date.h \epoc32\include\osextensions\sofia-sip\msg_date.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_header.h \epoc32\include\osextensions\sofia-sip\msg_header.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_mclass.h \epoc32\include\osextensions\sofia-sip\msg_mclass.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_mclass_hash.h \epoc32\include\osextensions\sofia-sip\msg_mclass_hash.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_mime.h \epoc32\include\osextensions\sofia-sip\msg_mime.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_mime_protos.h \epoc32\include\osextensions\sofia-sip\msg_mime_protos.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_parser.h \epoc32\include\osextensions\sofia-sip\msg_parser.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_protos.h \epoc32\include\osextensions\sofia-sip\msg_protos.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_tag_class.h \epoc32\include\osextensions\sofia-sip\msg_tag_class.h
+../../libsofia-sip-ua/msg/sofia-sip/msg_types.h \epoc32\include\osextensions\sofia-sip\msg_types.h
+../../libsofia-sip-ua/nea/sofia-sip/nea.h \epoc32\include\osextensions\sofia-sip\nea.h
+../../libsofia-sip-ua/nea/sofia-sip/nea_tag.h \epoc32\include\osextensions\sofia-sip\nea_tag.h
+../../libsofia-sip-ua/nta/sofia-sip/nta.h \epoc32\include\osextensions\sofia-sip\nta.h
+../../libsofia-sip-ua/nta/sofia-sip/nta_stateless.h \epoc32\include\osextensions\sofia-sip\nta_stateless.h
+../../libsofia-sip-ua/nta/sofia-sip/nta_tag.h \epoc32\include\osextensions\sofia-sip\nta_tag.h
+../../libsofia-sip-ua/nta/sofia-sip/nta_tport.h \epoc32\include\osextensions\sofia-sip\nta_tport.h
+../../libsofia-sip-ua/nta/sofia-sip/sl_utils.h \epoc32\include\osextensions\sofia-sip\sl_utils.h
+../../libsofia-sip-ua/nth/sofia-sip/nth.h \epoc32\include\osextensions\sofia-sip\nth.h
+../../libsofia-sip-ua/nth/sofia-sip/nth_tag.h \epoc32\include\osextensions\sofia-sip\nth_tag.h
+../../libsofia-sip-ua/nua/sofia-sip/nua.h \epoc32\include\osextensions\sofia-sip\nua.h
+../../libsofia-sip-ua/nua/sofia-sip/nua_tag.h \epoc32\include\osextensions\sofia-sip\nua_tag.h
+../../libsofia-sip-ua/sdp/sofia-sip/sdp.h \epoc32\include\osextensions\sofia-sip\sdp.h
+../../libsofia-sip-ua/sdp/sofia-sip/sdp_tag.h \epoc32\include\osextensions\sofia-sip\sdp_tag.h
+../../libsofia-sip-ua/sip/sofia-sip/sip.h \epoc32\include\osextensions\sofia-sip\sip.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_extra.h \epoc32\include\osextensions\sofia-sip\sip_extra.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_hclasses.h \epoc32\include\osextensions\sofia-sip\sip_hclasses.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_header.h \epoc32\include\osextensions\sofia-sip\sip_header.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_parser.h \epoc32\include\osextensions\sofia-sip\sip_parser.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_protos.h \epoc32\include\osextensions\sofia-sip\sip_protos.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_status.h \epoc32\include\osextensions\sofia-sip\sip_status.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_tag.h \epoc32\include\osextensions\sofia-sip\sip_tag.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_tag_class.h \epoc32\include\osextensions\sofia-sip\sip_tag_class.h
+../../libsofia-sip-ua/sip/sofia-sip/sip_util.h \epoc32\include\osextensions\sofia-sip\sip_util.h
+../../libsofia-sip-ua/soa/sofia-sip/soa.h \epoc32\include\osextensions\sofia-sip\soa.h
+../../libsofia-sip-ua/soa/sofia-sip/soa_add.h \epoc32\include\osextensions\sofia-sip\soa_add.h
+../../libsofia-sip-ua/soa/sofia-sip/soa_session.h \epoc32\include\osextensions\sofia-sip\soa_session.h
+../../libsofia-sip-ua/soa/sofia-sip/soa_tag.h \epoc32\include\osextensions\sofia-sip\soa_tag.h
+../../libsofia-sip-ua/sresolv/sofia-sip/sresolv.h \epoc32\include\osextensions\sofia-sip\sresolv.h
+../../libsofia-sip-ua/sresolv/sofia-resolv/sres.h \epoc32\include\osextensions\sofia-resolv/sres.h
+../../libsofia-sip-ua/sresolv/sofia-resolv/sres_async.h \epoc32\include\osextensions\sofia-resolv/sres_async.h
+../../libsofia-sip-ua/sresolv/sofia-resolv/sres_cache.h \epoc32\include\osextensions\sofia-resolv/sres_cache.h
+../../libsofia-sip-ua/sresolv/sofia-resolv/sres_config.h \epoc32\include\osextensions\sofia-resolv/sres_config.h
+../../libsofia-sip-ua/sresolv/sofia-resolv/sres_record.h \epoc32\include\osextensions\sofia-resolv/sres_record.h
+../../libsofia-sip-ua/stun/sofia-sip/stun.h \epoc32\include\osextensions\sofia-sip\stun.h
+../../libsofia-sip-ua/stun/sofia-sip/stun_common.h \epoc32\include\osextensions\sofia-sip\stun_common.h
+../../libsofia-sip-ua/stun/sofia-sip/stun_tag.h \epoc32\include\osextensions\sofia-sip\stun_tag.h
+../../libsofia-sip-ua/su/sofia-sip/heap.h \epoc32\include\osextensions\sofia-sip\heap.h
+../../libsofia-sip-ua/su/sofia-sip/htable.h \epoc32\include\osextensions\sofia-sip\htable.h
+../../libsofia-sip-ua/su/sofia-sip/htable2.h \epoc32\include\osextensions\sofia-sip\htable2.h
+../../libsofia-sip-ua/su/sofia-sip/rbtree.h \epoc32\include\osextensions\sofia-sip\rbtree.h
+../../libsofia-sip-ua/su/sofia-sip/string0.h \epoc32\include\osextensions\sofia-sip\string0.h
+../../libsofia-sip-ua/su/sofia-sip/su.h \epoc32\include\osextensions\sofia-sip\su.h
+../../libsofia-sip-ua/su/sofia-sip/su_addrinfo.h \epoc32\include\osextensions\sofia-sip\su_addrinfo.h
+../../libsofia-sip-ua/su/sofia-sip/su_alloc.h \epoc32\include\osextensions\sofia-sip\su_alloc.h
+../../libsofia-sip-ua/su/sofia-sip/su_alloc_stat.h \epoc32\include\osextensions\sofia-sip\su_alloc_stat.h
+../../libsofia-sip-ua/su/sofia-sip/su_bm.h \epoc32\include\osextensions\sofia-sip\su_bm.h
+../../libsofia-sip-ua/su/sofia-sip/su_config.h \epoc32\include\osextensions\sofia-sip\su_config.h
+../../libsofia-sip-ua/su/sofia-sip/su_debug.h \epoc32\include\osextensions\sofia-sip\su_debug.h
+../../libsofia-sip-ua/su/sofia-sip/su_errno.h \epoc32\include\osextensions\sofia-sip\su_errno.h
+../../libsofia-sip-ua/su/sofia-sip/su_localinfo.h \epoc32\include\osextensions\sofia-sip\su_localinfo.h
+../../libsofia-sip-ua/su/sofia-sip/su_log.h \epoc32\include\osextensions\sofia-sip\su_log.h
+../../libsofia-sip-ua/su/sofia-sip/su_md5.h \epoc32\include\osextensions\sofia-sip\su_md5.h
+../../libsofia-sip-ua/su/sofia-sip/su_os_nw.h \epoc32\include\osextensions\sofia-sip\su_os_nw.h
+../../libsofia-sip-ua/su/sofia-sip/su_strlst.h \epoc32\include\osextensions\sofia-sip\su_strlst.h
+../../libsofia-sip-ua/su/sofia-sip/su_tag.h \epoc32\include\osextensions\sofia-sip\su_tag.h
+../../libsofia-sip-ua/su/sofia-sip/su_tag_class.h \epoc32\include\osextensions\sofia-sip\su_tag_class.h
+../../libsofia-sip-ua/su/sofia-sip/su_tag_inline.h \epoc32\include\osextensions\sofia-sip\su_tag_inline.h
+../../libsofia-sip-ua/su/sofia-sip/su_tag_io.h \epoc32\include\osextensions\sofia-sip\su_tag_io.h
+../../libsofia-sip-ua/su/sofia-sip/su_tagarg.h \epoc32\include\osextensions\sofia-sip\su_tagarg.h
+../../libsofia-sip-ua/su/sofia-sip/su_time.h \epoc32\include\osextensions\sofia-sip\su_time.h
+../../libsofia-sip-ua/su/sofia-sip/su_types.h \epoc32\include\osextensions\sofia-sip\su_types.h
+../../libsofia-sip-ua/su/sofia-sip/su_uniqueid.h \epoc32\include\osextensions\sofia-sip\su_uniqueid.h
+../../libsofia-sip-ua/su/sofia-sip/su_vector.h \epoc32\include\osextensions\sofia-sip\su_vector.h
+../../libsofia-sip-ua/su/sofia-sip/su_wait.h \epoc32\include\osextensions\sofia-sip\su_wait.h
+../../libsofia-sip-ua/su/sofia-sip/tstdef.h \epoc32\include\osextensions\sofia-sip\tstdef.h
+../../libsofia-sip-ua/tport/sofia-sip/tport.h \epoc32\include\osextensions\sofia-sip\tport.h
+../../libsofia-sip-ua/tport/sofia-sip/tport_plugins.h \epoc32\include\osextensions\sofia-sip\tport_plugins.h
+../../libsofia-sip-ua/tport/sofia-sip/tport_tag.h \epoc32\include\osextensions\sofia-sip\tport_tag.h
+../../libsofia-sip-ua/url/sofia-sip/url.h \epoc32\include\osextensions\sofia-sip\url.h
+../../libsofia-sip-ua/url/sofia-sip/url_tag.h \epoc32\include\osextensions\sofia-sip\url_tag.h
+../../libsofia-sip-ua/url/sofia-sip/url_tag_class.h \epoc32\include\osextensions\sofia-sip\url_tag_class.h
+../../libsofia-sip-ua-glib/su-glib/sofia-sip/su_glib.h \epoc32\include\osextensions\sofia-sip\su_glib.h
+../../libsofia-sip-ua-glib/su-glib/sofia-sip/su_source.h \epoc32\include\osextensions\sofia-sip\su_source.h
+../sofia-sip/su_configure.h \epoc32\include\osextensions\sofia-sip\su_configure.h
+
+PRJ_MMPFILES
+
+libsofia-sip-ua.mmp
+libsofia-sip-ua-glib.mmp
+
+//torture_su_root.mmp
+//torture_su_port.mmp
+//torture_su_tag.mmp
+//torture_su_alloc.mmp
+//torture_url.mmp
+//test_msg.mmp
+//torture_sip.mmp
+//test_http.mmp
+//test_soa.mmp
+test_tport.mmp
+test_nua.mmp
+//test_nta.mmp
+su_source_test.mmp
+
 //  End of File  
\ No newline at end of file
diff --git a/libs/sofia-sip/open_c/group/libsofia-sip-ua-glib.mmp b/libs/sofia-sip/open_c/group/libsofia-sip-ua-glib.mmp
new file mode 100644 (file)
index 0000000..3e12ba9
--- /dev/null
@@ -0,0 +1,54 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
+// General properties\r
+TARGET          libsofia-sip-ua-glib.dll\r
+TARGETTYPE      dll\r
+CAPABILITY      All -Tcb //NetworkServices\r
+UID             0x1000008D 0xA000017F\r
+VENDORID        0\r
+OPTION CW       -dialect c99 -inline on -warn nounusedarg,nounusedvar\r
+//CAPABILITY      NetworkServices\r
+\r
+//EPOCHEAPSIZE 4 4194304\r
+\r
+// Allow global writeable static data\r
+EPOCALLOWDLLDATA\r
+\r
+MACRO           SYMBIAN\r
+MACRO           IN_LIBSOFIA_SIP_UA\r
+MACRO           IN_LIBSOFIA_SRES\r
+\r
+SOURCEPATH      ..\..\libsofia-sip-ua-glib\su-glib\r
+\r
+SOURCE          su_source.c\r
+\r
+USERINCLUDE            ..\r
+USERINCLUDE            ..\..\libsofia-sip-ua\su\r
+USERINCLUDE            ..\..\libsofia-sip-ua-glib\su-glib\r
+\r
+SYSTEMINCLUDE   \epoc32\include\r
+SYSTEMINCLUDE   \epoc32\include\osextensions\r
+SYSTEMINCLUDE   \epoc32\include\stdapis\r
+SYSTEMINCLUDE   \epoc32\include\stdapis\openssl\r
+SYSTEMINCLUDE   \epoc32\include\stdapis\glib-2.0\r
+\r
+// Library dependencies\r
+\r
+LIBRARY         commdb.lib\r
+STATICLIBRARY   libcrt0.lib\r
+LIBRARY         libc.lib\r
+LIBRARY         libm.lib\r
+LIBRARY         libpthread.lib\r
+LIBRARY         libcrypto.lib\r
+LIBRARY         libssl.lib\r
+LIBRARY         euser.lib\r
+LIBRARY         insock.lib\r
+LIBRARY         esock.lib\r
+LIBRARY         libglib.lib\r
+LIBRARY         libgthread.lib\r
+LIBRARY         libgobject.lib\r
+LIBRARY         libsofia-sip-ua.lib\r
index 931d8404fa2a55c268e3caa034401c2310cc8bbb..c8ea95ddfe2071d513157547a2de131cb130225d 100644 (file)
@@ -1,12 +1,19 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 // General properties\r
-TARGET          libsofia-sip-ua.lib\r
-TARGETTYPE      lib\r
-CAPABILITY      ALL -TCB\r
+TARGET          libsofia-sip-ua.dll\r
+TARGETTYPE      dll\r
+CAPABILITY      All -Tcb //NetworkServices\r
 UID             0x1000008D 0xA000017E\r
 VENDORID        0\r
 OPTION CW       -dialect c99 -inline on -warn nounusedarg,nounusedvar\r
+//CAPABILITY      NetworkServices NetworkControl CommDD UserEnvironment\r
 \r
-//EPOCHEAPSIZE 4 4194304 // min. 4KB ja max 4MB\r
+//EPOCHEAPSIZE 4 4194304\r
 \r
 // Allow global writeable static data\r
 EPOCALLOWDLLDATA\r
@@ -17,6 +24,8 @@ MACRO           IN_LIBSOFIA_SRES
 \r
 SOURCEPATH      ..\..\libsofia-sip-ua\su\r
 \r
+SOURCE          su_open_c_localinfo.cpp\r
+\r
 SOURCE          su.c\r
 SOURCE          su_errno.c\r
 SOURCE          su_addrinfo.c\r
@@ -268,35 +277,20 @@ USERINCLUDE               ..\..\libsofia-sip-ua\nth
 USERINCLUDE            ..\..\libsofia-sip-ua\nea\r
 USERINCLUDE            ..\..\libsofia-sip-ua\nua\r
 \r
-SYSTEMINCLUDE          ..\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua/features\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\su\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\bnf\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\ipt\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\iptsec\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\url\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\msg\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\sresolv\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\stun\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\soa\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\sdp\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\http\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\tport\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\sip\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\nta\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\nth\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\nea\r
-SYSTEMINCLUDE          ..\..\libsofia-sip-ua\nua\r
-\r
-SYSTEMINCLUDE \Epoc32\include\r
-SYSTEMINCLUDE  \Epoc32\include\osextensions\stdapis\r
-SYSTEMINCLUDE   \epoc32\include\libc\r
-SYSTEMINCLUDE   \epoc32\include\osextensions\stdapis\openssl\r
+SYSTEMINCLUDE   \epoc32\include\r
+SYSTEMINCLUDE   \epoc32\include\stdapis\r
+SYSTEMINCLUDE   \epoc32\include\stdapis\openssl\r
+SYSTEMINCLUDE   \epoc32\include\osextensions\r
 \r
 // Library dependencies\r
+\r
+LIBRARY         commdb.lib\r
+STATICLIBRARY   libcrt0.lib\r
 LIBRARY         libc.lib\r
 LIBRARY         libm.lib\r
 LIBRARY         libpthread.lib\r
 LIBRARY         libcrypto.lib\r
 LIBRARY         libssl.lib\r
-LIBRARY         euser.lib
\ No newline at end of file
+LIBRARY         euser.lib\r
+LIBRARY         insock.lib\r
+LIBRARY         esock.lib\r
diff --git a/libs/sofia-sip/open_c/group/su_source_test.mmp b/libs/sofia-sip/open_c/group/su_source_test.mmp
new file mode 100644 (file)
index 0000000..9ae694b
--- /dev/null
@@ -0,0 +1,72 @@
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
+
+// sofiatest component properties
+
+// General properties
+TARGET          su_source_test.exe
+TARGETTYPE      exe
+CAPABILITY      All -Tcb //NetworkServices
+UID             0x100039CE 0x1F001AD4
+VENDORID        0
+OPTION CW       -warn nounusedarg,nounusedvar
+//CAPABILITY      NetworkServices NetworkControl CommDD UserEnvironment ReadDeviceData
+
+START RESOURCE  su_source_test_reg.rss
+#ifdef WINSCW
+TARGETPATH         \private\10003a3f\apps
+#else
+TARGETPATH         \private\10003a3f\import\apps
+#endif
+END //RESOURCE
+OPTION CW      -dialect c99 -inline on
+
+// Disable optimization for debug builds
+SRCDBG 
+
+EPOCHEAPSIZE 0x5000 0x400000
+EPOCSTACKSIZE 0x10000
+
+// Allow global writeable static data
+#ifndef WINSCW
+EPOCALLOWDLLDATA
+#endif
+
+MACRO       SYMBIAN
+MACRO       IN_LIBSOFIA_SIP_UA
+MACRO       IN_LIBSOFIA_SRES
+
+// Source files
+SOURCEPATH                     ..\..\libsofia-sip-ua-glib\su-glib
+SOURCE          su_source_test.c
+
+USERINCLUDE            ..
+USERINCLUDE            ..\..\libsofia-sip-ua\su
+USERINCLUDE            ..\..\libsofia-sip-ua-glib\su-glib
+
+SYSTEMINCLUDE   \epoc32\include
+SYSTEMINCLUDE   \epoc32\include\stdapis
+SYSTEMINCLUDE   \epoc32\include\osextensions
+SYSTEMINCLUDE   \epoc32\include\stdapis\openssl
+SYSTEMINCLUDE   \epoc32\include\stdapis\glib-2.0
+
+// Library dependencies
+
+LIBRARY         commdb.lib
+STATICLIBRARY   libcrt0.lib
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libpthread.lib
+LIBRARY         libcrypto.lib
+LIBRARY         libssl.lib
+LIBRARY         euser.lib
+LIBRARY         insock.lib
+LIBRARY         esock.lib
+LIBRARY         libgthread.lib
+LIBRARY         libglib.lib
+
+LIBRARY         libsofia-sip-ua.lib
+LIBRARY         libsofia-sip-ua-glib.lib
diff --git a/libs/sofia-sip/open_c/group/su_source_test_reg.rss b/libs/sofia-sip/open_c/group/su_source_test_reg.rss
new file mode 100644 (file)
index 0000000..44c1094
--- /dev/null
@@ -0,0 +1,19 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
+#include <appinfo.rh>\r
+\r
+UID2 KUidAppRegistrationResourceFile\r
+UID3 0x1F001AD4\r
+\r
+RESOURCE APP_REGISTRATION_INFO\r
+  {\r
+  app_file="su_source_test";\r
+\r
+  embeddability=KAppNotEmbeddable;\r
+  newfile=KAppDoesNotSupportNewFile;\r
+  }\r
+\r
diff --git a/libs/sofia-sip/open_c/group/test_http.mmp b/libs/sofia-sip/open_c/group/test_http.mmp
new file mode 100644 (file)
index 0000000..aa8cb23
--- /dev/null
@@ -0,0 +1,58 @@
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
+
+// General properties
+TARGET          test_http.exe
+TARGETTYPE      exe
+CAPABILITY        ALL -TCB
+UID             0x100039CE 0x1F001BA2
+VENDORID                       0
+OPTION CW      -dialect c99 -inline on
+
+START RESOURCE  test_http_reg.rss
+#ifdef WINSCW
+TARGETPATH         \private\10003a3f\apps
+#else
+TARGETPATH         \private\10003a3f\import\apps
+#endif
+END //RESOURCE
+
+//EPOCHEAPSIZE 4 4194304 // min. 4KB ja max 4MB
+
+// Allow global writeable static data
+EPOCALLOWDLLDATA
+
+MACRO           SYMBIAN
+MACRO           IN_LIBSOFIA_SIP_UA
+
+// Source files
+SOURCEPATH          ..\..\libsofia-sip-ua\http
+SOURCE              test_http.c
+
+
+USERINCLUDE         ..
+USERINCLUDE         ..\..\libsofia-sip-ua\su
+USERINCLUDE         ..\..\libsofia-sip-ua\bnf
+USERINCLUDE         ..\..\libsofia-sip-ua\msg
+USERINCLUDE         ..\..\libsofia-sip-ua\url
+USERINCLUDE         ..\..\libsofia-sip-ua\http
+SYSTEMINCLUDE       ..
+SYSTEMINCLUDE       ..\..\libsofia-sip-ua\su
+SYSTEMINCLUDE       ..\..\libsofia-sip-ua\bnf
+SYSTEMINCLUDE       ..\..\libsofia-sip-ua\msg
+SYSTEMINCLUDE       ..\..\libsofia-sip-ua\url
+SYSTEMINCLUDE       ..\..\libsofia-sip-ua\http
+
+SYSTEMINCLUDE       \Epoc32\include
+SYSTEMINCLUDE       \Epoc32\include\osextensions\stdapis
+
+
+// Library dependencies
+STATICLIBRARY       libcrt0.lib
+LIBRARY             libc.lib
+LIBRARY             euser.lib
+LIBRARY             libpthread.lib
+LIBRARY             libsofia-sip-ua.lib
diff --git a/libs/sofia-sip/open_c/group/test_http_reg.rss b/libs/sofia-sip/open_c/group/test_http_reg.rss
new file mode 100644 (file)
index 0000000..3da18ee
--- /dev/null
@@ -0,0 +1,19 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
+#include <appinfo.rh>\r
+\r
+UID2 KUidAppRegistrationResourceFile\r
+UID3 0x1F001BA2\r
+\r
+RESOURCE APP_REGISTRATION_INFO\r
+  {\r
+  app_file="test_http";\r
+\r
+  embeddability=KAppNotEmbeddable;\r
+  newfile=KAppDoesNotSupportNewFile;\r
+  }\r
+\r
index 80a8057738c481fd9157670299a01ffb38267485..0f2952429ff92ecf658a4c5551410f4bc5d0c549 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          test_msg.exe
index 1457e83ab9b2e8a94c203f02b2177583e6ab4e87..f704d5c2fe12c6159585a80ddb57ce76aeae1bce 100644 (file)
@@ -1,3 +1,9 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
diff --git a/libs/sofia-sip/open_c/group/test_nua.mmp b/libs/sofia-sip/open_c/group/test_nua.mmp
new file mode 100644 (file)
index 0000000..b49584e
--- /dev/null
@@ -0,0 +1,88 @@
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
+
+// General properties
+TARGET          test_nua.exe
+TARGETTYPE      exe
+CAPABILITY      All -Tcb //NetworkServices
+UID             0x100039CE 0x1F001AD1
+VENDORID        0
+OPTION CW       -warn nounusedarg,nounusedvar
+
+//CAPABILITY      NetworkServices NetworkControl CommDD UserEnvironment ReadDeviceData
+
+START RESOURCE  test_nua_reg.rss
+#ifdef WINSCW
+TARGETPATH         \private\10003a3f\apps
+#else
+TARGETPATH         \private\10003a3f\import\apps
+#endif
+END //RESOURCE
+OPTION CW      -dialect c99 -inline on
+
+// Disable optimization for debug builds
+SRCDBG 
+
+EPOCHEAPSIZE 0x5000 0x400000
+EPOCSTACKSIZE 0x10000
+
+// Allow global writeable static data
+#ifndef WINSCW
+EPOCALLOWDLLDATA
+#endif
+
+MACRO       SYMBIAN
+MACRO       IN_LIBSOFIA_SIP_UA
+MACRO       IN_LIBSOFIA_SRES
+
+// Source files
+SOURCEPATH                     ..\..\libsofia-sip-ua\su
+SOURCE              memmem.c
+
+SOURCEPATH                     ..\..\libsofia-sip-ua\nua
+SOURCE              test_nua.c
+SOURCE          test_ops.c
+SOURCE          test_init.c
+SOURCE          test_nua_api.c
+SOURCE          test_nua_params.c
+SOURCE          test_register.c
+SOURCE          test_basic_call.c
+SOURCE          test_call_reject.c
+SOURCE          test_cancel_bye.c
+SOURCE          test_call_hold.c
+SOURCE          test_session_timer.c
+SOURCE          test_refer.c
+SOURCE          test_100rel.c
+SOURCE          test_simple.c
+SOURCE          test_sip_events.c
+SOURCE          test_extension.c
+SOURCE          test_proxy.c
+SOURCE          test_nat.c
+SOURCE          test_nat_tags.c
+SOURCE          test_offer_answer.c
+
+USERINCLUDE            ..
+USERINCLUDE            ..\..\libsofia-sip-ua\nua
+
+SYSTEMINCLUDE   \epoc32\include\osextensions
+SYSTEMINCLUDE   \epoc32\include
+SYSTEMINCLUDE   \epoc32\include\stdapis
+SYSTEMINCLUDE   \epoc32\include\stdapis\openssl
+
+// Library dependencies
+LIBRARY         commdb.lib
+STATICLIBRARY   libcrt0.lib
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libpthread.lib
+LIBRARY         libcrypto.lib
+LIBRARY         libssl.lib
+LIBRARY         euser.lib
+LIBRARY         insock.lib
+LIBRARY         esock.lib
+
+// Sofia-SIP libs
+LIBRARY         libsofia-sip-ua.lib
diff --git a/libs/sofia-sip/open_c/group/test_nua_reg.rss b/libs/sofia-sip/open_c/group/test_nua_reg.rss
new file mode 100644 (file)
index 0000000..66ee65e
--- /dev/null
@@ -0,0 +1,19 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
+#include <appinfo.rh>\r
+\r
+UID2 KUidAppRegistrationResourceFile\r
+UID3 0x1F001AD1\r
+\r
+RESOURCE APP_REGISTRATION_INFO\r
+  {\r
+  app_file="test_nua";\r
+\r
+  embeddability=KAppNotEmbeddable;\r
+  newfile=KAppDoesNotSupportNewFile;\r
+  }\r
+\r
diff --git a/libs/sofia-sip/open_c/group/test_tport.mmp b/libs/sofia-sip/open_c/group/test_tport.mmp
new file mode 100644 (file)
index 0000000..41d63f1
--- /dev/null
@@ -0,0 +1,63 @@
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
+
+// General properties
+TARGET          test_tport.exe
+TARGETTYPE      exe
+CAPABILITY      All -Tcb //NetworkServices
+UID             0x100039CE 0x1F001AC5
+VENDORID        0
+OPTION CW       -warn nounusedarg,nounusedvar
+
+START RESOURCE  test_tport_reg.rss
+#ifdef WINSCW
+TARGETPATH         \private\10003a3f\apps
+#else
+TARGETPATH         \private\10003a3f\import\apps
+#endif
+END //RESOURCE
+
+EPOCHEAPSIZE 4 4194304
+
+// Allow global writeable static data
+EPOCALLOWDLLDATA
+
+MACRO       SYMBIAN
+MACRO       IN_LIBSOFIA_SIP_UA
+MACRO       IN_LIBSOFIA_SRES
+
+// Source files
+SOURCEPATH                     ..\..\libsofia-sip-ua\msg
+SOURCE          test_class.c
+SOURCE          test_table.c
+
+SOURCEPATH      ..\..\libsofia-sip-ua\tport
+SOURCE          test_tport.c
+
+USERINCLUDE     ..
+USERINCLUDE     ..\..\libsofia-sip-ua\msg
+USERINCLUDE     ..\..\libsofia-sip-ua\tport
+
+SYSTEMINCLUDE   \epoc32\include
+SYSTEMINCLUDE  \epoc32\include\osextensions
+SYSTEMINCLUDE  \epoc32\include\stdapis
+SYSTEMINCLUDE   \epoc32\include\stdapis\openssl
+
+
+// Library dependencies
+LIBRARY         commdb.lib
+STATICLIBRARY   libcrt0.lib
+LIBRARY         libc.lib
+LIBRARY         libm.lib
+LIBRARY         libpthread.lib
+LIBRARY         libcrypto.lib
+LIBRARY         libssl.lib
+LIBRARY         euser.lib
+LIBRARY         insock.lib
+LIBRARY         esock.lib
+
+// Sofia-SIP libs
+LIBRARY         libsofia-sip-ua.lib
\ No newline at end of file
diff --git a/libs/sofia-sip/open_c/group/test_tport_reg.rss b/libs/sofia-sip/open_c/group/test_tport_reg.rss
new file mode 100644 (file)
index 0000000..e302c43
--- /dev/null
@@ -0,0 +1,19 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
+#include <appinfo.rh>\r
+\r
+UID2 KUidAppRegistrationResourceFile\r
+UID3 0x1F001AC5\r
+\r
+RESOURCE APP_REGISTRATION_INFO\r
+  {\r
+  app_file="test_tport";\r
+\r
+  embeddability=KAppNotEmbeddable;\r
+  newfile=KAppDoesNotSupportNewFile;\r
+  }\r
+\r
index 4bc913358dea4145ff905fb07f9479cf540fcf83..f9f5356fd3769ec4cc287b70aaefdd99ea548268 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          torture_sip.exe
@@ -16,7 +20,7 @@ TARGETPATH        \private\10003a3f\import\apps
 #endif
 END //RESOURCE
 
-//EPOCHEAPSIZE 4 4194304 // min. 4KB ja max 4MB
+EPOCHEAPSIZE 4 4194304 // min. 4KB ja max 4MB
 
 // Allow global writeable static data
 EPOCALLOWDLLDATA
index 1ce45774c8ccbbfd1dd9b4ad374644fbdb3eee9e..65c73edb38dd3b4e49adc7f7e753446b5d0e81ff 100644 (file)
@@ -1,3 +1,9 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
index 2113fd1e73b5f86a05dff6886e10dc4365ac2cf7..d22b919bafe84312080c6ac5b3c005cb2ae83170 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          torture_su_alloc.exe
index a4ae46ecc48b73517cc56275d2c86e30866ffb3e..26a268929cefd0d3ca1be62ff9be7101910c6700 100644 (file)
@@ -1,3 +1,9 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
index aaff606151b1c269aaa2fd974454f5226cba30ee..4a7ff58ca519ee2f01197c64e936cad9bbb9209c 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          torture_su_root.exe
index 43c28bff989f4a3863976a3acd47835e99d3f335..995a32a7db0819cd1242c1bd5231a91baec250bc 100644 (file)
@@ -1,3 +1,9 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
index 904af83eb21743d9ddac6d51085e059db0612c1d..1e70163982c5ef35b6a6410588a57625088e76e6 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          torture_su_tag.exe
index 07fdaa36d119697c1fb095b16f9022aeb76fe2a1..fcdb27c7ec01e18726e5b0ae665f0d5f50b1c71b 100644 (file)
@@ -1,3 +1,9 @@
+// part of Symbian build files for sofia-sip package\r
+//\r
+// Copyright (C) 2005,2006,2007 Nokia Corporation\r
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+// Licensed under LGPL. See file COPYING.\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
index ace2de7cb63fd0f5d152207da1cf9cbb53762aee..645b68b616bd103f49243633f31bf792f05e09d2 100644 (file)
@@ -1,4 +1,8 @@
-// sofiatest component properties
+// part of Symbian build files for sofia-sip package
+//
+// Copyright (C) 2005,2006,2007 Nokia Corporation
+// Contact: Pekka Pessi <pekka.pessi@nokia.com>
+// Licensed under LGPL. See file COPYING.
 
 // General properties
 TARGET          torture_url.exe
index 0ffeef3960bf031a2f488b11c4276fa1e0ee6d86..2985ff13f000fdc3999acdf855560c25ccde1f97 100644 (file)
@@ -1,3 +1,5 @@
+// sofiatest component properties\r
+\r
 #include <appinfo.rh>\r
 \r
 UID2 KUidAppRegistrationResourceFile\r
diff --git a/libs/sofia-sip/open_c/sis/libsofia-sip-ua-glib.pkg b/libs/sofia-sip/open_c/sis/libsofia-sip-ua-glib.pkg
new file mode 100644 (file)
index 0000000..346304c
--- /dev/null
@@ -0,0 +1,34 @@
+; libsofia-sip-ua-glib.pkg for sofia-sip package\r
+;\r
+; Copyright (C) 2005,2006,2007 Nokia Corporation\r
+; Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+; Licensed under LGPL. See file COPYING.\r
+\r
+;File: libsofia-sip-ua.pkg;\r
+;\r
+\r
+;*Languages\r
+&EN\r
+;\r
+;*Standard SIS file header. This section specifies the package name,\r
+;application UID, and version/build numbers. Add the package TYPE here if needed.\r
+#{"libsofia-sip-ua-glib"},(0xA000017F),1,0,1;\r
+;\r
+\r
+;*Unique (Non-Localised) Vendor name\r
+;This is used in combination with signing to prevent the unauthroized\r
+;upgrade ofa a package by someone other than the rightful vendor.\r
+:""\r
+\r
+;*Localized Vendor Name\r
+;This specifies the localised vendor name(s) correspodning to language(s).\r
+%{""}\r
+\r
+;*Files To Copy...<src> <destination>\r
+;The destination files should be a full path. If you use a '!' character\r
+;instead of a drive letter, ther user should be given the choice of the drive\r
+;to install the file to (on supported Symbian devices).\r
+\r
+\r
+;Sofia-SIP dll\r
+"\epoc32\release\ARMV5\UREL\LIBSOFIA-SIP-UA-GLIB.DLL" - "!:\Sys\Bin\LIBSOFIA-SIP-UA-GLIB.DLL"\r
diff --git a/libs/sofia-sip/open_c/sis/libsofia-sip-ua.pkg b/libs/sofia-sip/open_c/sis/libsofia-sip-ua.pkg
new file mode 100644 (file)
index 0000000..41ac5d6
--- /dev/null
@@ -0,0 +1,34 @@
+; libsofia-sip-ua.pkg for sofia-sip package\r
+;\r
+; Copyright (C) 2005,2006,2007 Nokia Corporation\r
+; Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+; Licensed under LGPL. See file COPYING.\r
+\r
+;File: libsofia-sip-ua.pkg;\r
+;\r
+\r
+;*Languages\r
+&EN\r
+;\r
+;*Standard SIS file header. This section specifies the package name,\r
+;application UID, and version/build numbers. Add the package TYPE here if needed.\r
+#{"libsofia-sip-ua"},(0xA000017E),1,0,1;\r
+;\r
+\r
+;*Unique (Non-Localised) Vendor name\r
+;This is used in combination with signing to prevent the unauthroized\r
+;upgrade of a package by someone other than the rightful vendor.\r
+:""\r
+\r
+;*Localized Vendor Name\r
+;This specifies the localised vendor name(s) correspodning to language(s).\r
+%{""}\r
+\r
+;*Files To Copy...<src> <destination>\r
+;The destination files should be a full path. If you use a '!' character\r
+;instead of a drive letter, ther user should be given the choice of the drive\r
+;to install the file to (on supported Symbian devices).\r
+\r
+\r
+;Sofia-SIP dll\r
+"\epoc32\release\ARMV5\UREL\LIBSOFIA-SIP-UA.DLL"      - "!:\Sys\Bin\LIBSOFIA-SIP-UA.DLL"\r
diff --git a/libs/sofia-sip/open_c/sis/su_source_test.pkg b/libs/sofia-sip/open_c/sis/su_source_test.pkg
new file mode 100644 (file)
index 0000000..0fe38be
--- /dev/null
@@ -0,0 +1,35 @@
+; su_source_test.pkg for sofia-sip package\r
+;\r
+; Copyright (C) 2005,2006,2007 Nokia Corporation\r
+; Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+; Licensed under LGPL. See file COPYING.\r
+\r
+;File: su_source_test.pkg;\r
+;\r
+\r
+;*Languages\r
+&EN\r
+;\r
+;*Standard SIS file header. This section specifies the package name,\r
+;application UID, and version/build numbers. Add the package TYPE here if needed.\r
+#{"su_source_test"},(0x1F001AD4),1,0,1;\r
+;\r
+\r
+;*Unique (Non-Localised) Vendor name\r
+;This is used in combination with signing to prevent the unauthroized\r
+;upgrade ofa a package by someone other than the rightful vendor.\r
+:""\r
+\r
+;*Localized Vendor Name\r
+;This specifies the localised vendor name(s) correspodning to language(s).\r
+%{""}\r
+\r
+;*Files To Copy...<src> <destination>\r
+;The destination files should be a full path. If you use a '!' character\r
+;instead of a drive letter, ther user should be given the choice of the drive\r
+;to install the file to (on supported Symbian devices).\r
+\r
+\r
+;Sofia-SIP test suite apps\r
+"\EPOC32\RELEASE\ARMV5\UREL\SU_SOURCE_TEST.exe"       - "!:\sys\bin\SU_SOURCE_TEST.exe"\r
+"\epoc32\data\z\private\10003a3f\import\apps\su_source_test_reg.rsc" -"!:\private\10003a3f\import\apps\su_source_test.rsc"
\ No newline at end of file
diff --git a/libs/sofia-sip/open_c/sis/test_nua.pkg b/libs/sofia-sip/open_c/sis/test_nua.pkg
new file mode 100644 (file)
index 0000000..4a497bd
--- /dev/null
@@ -0,0 +1,35 @@
+; test_nua.pkg for sofia-sip package\r
+;\r
+; Copyright (C) 2005,2006,2007 Nokia Corporation\r
+; Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+; Licensed under LGPL. See file COPYING.\r
+\r
+;File: test_nua.pkg;\r
+;\r
+\r
+;*Languages\r
+&EN\r
+;\r
+;*Standard SIS file header. This section specifies the package name,\r
+;application UID, and version/build numbers. Add the package TYPE here if needed.\r
+#{"test_nua"},(0x1F001AD1),1,0,1;\r
+;\r
+\r
+;*Unique (Non-Localised) Vendor name\r
+;This is used in combination with signing to prevent the unauthroized\r
+;upgrade ofa a package by someone other than the rightful vendor.\r
+:""\r
+\r
+;*Localized Vendor Name\r
+;This specifies the localised vendor name(s) correspodning to language(s).\r
+%{""}\r
+\r
+;*Files To Copy...<src> <destination>\r
+;The destination files should be a full path. If you use a '!' character\r
+;instead of a drive letter, ther user should be given the choice of the drive\r
+;to install the file to (on supported Symbian devices).\r
+\r
+\r
+;Sofia-SIP test suite apps\r
+"\EPOC32\RELEASE\ARMV5\UREL\TEST_NUA.exe"             - "!:\sys\bin\TEST_NUA.exe"\r
+"\epoc32\data\z\private\10003a3f\import\apps\test_nua_reg.rsc" -"!:\private\10003a3f\import\apps\test_nua.rsc"
\ No newline at end of file
diff --git a/libs/sofia-sip/open_c/sis/test_tport.pkg b/libs/sofia-sip/open_c/sis/test_tport.pkg
new file mode 100644 (file)
index 0000000..8b864c4
--- /dev/null
@@ -0,0 +1,35 @@
+; test_tport.pkg for sofia-sip package\r
+;\r
+; Copyright (C) 2005,2006,2007 Nokia Corporation\r
+; Contact: Pekka Pessi <pekka.pessi@nokia.com>\r
+; Licensed under LGPL. See file COPYING.\r
+\r
+;File: test_tport.pkg;\r
+;\r
+\r
+;*Languages\r
+&EN\r
+;\r
+;*Standard SIS file header. This section specifies the package name,\r
+;application UID, and version/build numbers. Add the package TYPE here if needed.\r
+#{"test_tport"},(0x1F001AC5),1,0,1;\r
+;\r
+\r
+;*Unique (Non-Localised) Vendor name\r
+;This is used in combination with signing to prevent the unauthroized\r
+;upgrade ofa a package by someone other than the rightful vendor.\r
+:""\r
+\r
+;*Localized Vendor Name\r
+;This specifies the localised vendor name(s) corresponding to language(s).\r
+%{""}\r
+\r
+;*Files To Copy...<src> <destination>\r
+;The destination files should be a full path. If you use a '!' character\r
+;instead of a drive letter, ther user should be given the choice of the drive\r
+;to install the file to (on supported Symbian devices).\r
+\r
+\r
+;Sofia-SIP test suite apps\r
+"\EPOC32\RELEASE\ARMV5\UREL\TEST_TPORT.exe"           - "!:\sys\bin\TEST_TPORT.exe"\r
+"\epoc32\data\z\private\10003a3f\import\apps\test_tport_reg.rsc" -"!:\private\10003a3f\import\apps\test_tport.rsc"
\ No newline at end of file
index f2a65a6b1f508cebb4d089ead2c3139b13180090..b8539c0726deff32f80c85902d7a0589c404cfcc 100644 (file)
@@ -7,23 +7,25 @@
 # Licensed under LGPL. See file COPYING.
 #
 
-PROJECT_NAME         = "sofia-sip"
+PROJECT_NAME         = "sofia-sip-utils"
 
 PROJECT_NUMBER       = @VERSION@
 
-INPUT                = @srcdir@
+INPUT                = @srcdir@/utils.docs
+INPUT               += @srcdir@
 INPUT                += @top_srcdir@/libsofia-sip-ua/su/localinfo.c
 INPUT                += @top_srcdir@/libsofia-sip-ua/su/addrinfo.c
 INPUT                += @top_srcdir@/libsofia-sip-ua/stun/stunc.c
 
 OUTPUT_DIRECTORY     = ../man
 
+HTML_OUTPUT          = ../libsofia-sip-ua/docs/html/utils
+GENERATE_TAGFILE     = ../libsofia-sip-ua/docs/utils.doxytags
+
 @INCLUDE_PATH = . @srcdir@
 
 @INCLUDE = ../libsofia-sip-ua/docs/Doxyfile.aliases
-# @INCLUDE = ../libsofia-sip-ua/docs/Doxyfile.rfc
-# Only @RFC3263 is used now
-ALIASES += RFC3263="<a href=\"http://www.faqs.org/rfcs/rfc3263.html\">RFC 3263</a>"
+@INCLUDE = ../libsofia-sip-ua/docs/Doxyfile.rfc
 
 FILE_PATTERNS        = *.h *.c 
 
index 7c96c8f441c1018bfc1f3cda30bdd6edb199f6b6..39e18c0c91024535f9fb12ecf6891d3b0a1aecf8 100644 (file)
@@ -44,3 +44,7 @@ noinst_HEADERS =      apps_utils.h
 bin_PROGRAMS =         sip-options sip-date sip-dig
 
 LDADD =                        ../libsofia-sip-ua/libsofia-sip-ua.la $(GLIB_LIBS)
+
+# ----------------------------------------------------------------------
+# Dist and install
+EXTRA_DIST = utils.docs
index 219ea4e83e135bd45445986e64dd3ce2fda67e91..494c12fc5ff27f0b850b5607d80e57e7dc2cb540 100644 (file)
@@ -25,7 +25,7 @@
 /**@page sip-options Query SIP OPTIONS
  * 
  * @section synopsis Synopsis
- * <tt>sip-options [--bind=url] [--from=url] [-a|--all] to </tt>
+ * <tt>sip-options [OPTIONS] target-uri </tt>
  *
  * @section description Description
  * The @em sip-options utility sends a SIP OPTIONS request (or any other SIP
diff --git a/libs/sofia-sip/utils/utils.docs b/libs/sofia-sip/utils/utils.docs
new file mode 100644 (file)
index 0000000..5df6576
--- /dev/null
@@ -0,0 +1,24 @@
+/* -*- c -*- */
+
+/**@MODULEPAGE "utils" - Sofia-SIP Command Line Utilities
+ * 
+ * @section utils_meta Module Meta Information
+ *
+ * Command line utilities for <a href="../index.html">Sofia-SIP</a>.
+ *
+ * @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
+ *
+ * @STATUS @SofiaSIP utilities
+ *
+ * @LICENSE LGPL
+ *
+ * @section utuils_overview Overview
+ *
+ * The Sofia-SIP provides a few command line utilities: 
+ * - @ref sip-date "sip-date" - print or parse SIP date 
+ * - @ref sip-dig "sip-dig" - resolve SIP URIs
+ * - @ref sip-options "sip-options" - query SIP OPTIONS
+ * - @ref localinfo "localinfo" - list local network addresses
+ * - @ref stunc "stunc" - STUN test client
+ */
+
index dcf99c77354a999e11174b86ecb7974b33116dbb..edb260be67ba5b9dc194a386b4a2dcf561363402 100644 (file)
@@ -2,21 +2,51 @@
 win32/README.txt / Sofia-SIP for win32
 ======================================
 
-The win32 subdirectory contains the build environment for Win32 environment
-using MSVC. In order to compile the code with Windows 2000 SDK you have to
-install so called "IPv6 Technology Preview for Windows 2000". The preview
-contains updated IPv6 API in <tpipv6.h> and <wspiapi.h> header files.
+The win32 subdirectory contains the build environment for Win32 
+environment using MSVC.
 
-http://msdn.microsoft.com/downloads/sdks/platform/tpipv6.asp
+Currently, the provided workspace/solution files will create both
+shared and static libraries for libsofia-sip-ua, and a few test 
+programs. The test programs can be run with the script check.cmd.
+
+Preparing the build tree
+------------------------
+
+The script autogen.cmd should be used to prepare source tree before
+compiling Sofia SIP. Note that it uses AWK, so an AWK interpreter
+is needed. You can for example use gawk (3.1.5 or newer) or mawk (tested
+with 1.3.3) implementations. Precompiled binaries are available
+for instance at:
+  - http://gnuwin32.sourceforge.net/packages/mawk.htm
+  - http://ftp.uni-kl.de/pub/windows/cygwin/release/gawk/
+  - plus many sites, a web search for "win32 awk" will
+    provide you many more links
+
+Notes pthread support
+---------------------
 
 There is a pthread implementation for Visual C on Win32 included.
 Source code and documentation for the pthread library can also be
 downloaded from http://sources.redhat.com/pthreads-win32/.
 
-The script autogen.cmd should be used to prepare source tree before
-compiling Sofia SIP. Note that it uses the gawk utility - see
-http://unxutils.sourceforge.net.
+MS-VC6 specific notes
+---------------------
+
+The MSVC6 workspace file is "SofiaSIP.dsw".
+
+With Visual Studio 6, and Windows 2000 or older Platform SDK, you 
+need to have so called "IPv6 Technology Preview for Windows 2000" 
+installed, in order to compile Sofia-SIP. This is required even
+if IPv6 support is disabled (the socket APIs of older Platfrom SDKs
+are insufficient).
+
+You can download the preview SDK from:
+http://msdn.microsoft.com/downloads/sdks/platform/tpipv6.asp
+
+With newer Platform SDKs, the IPv6 Preview SDK is not needed.
+
+MSVC2005 specific notes
+------------------------
 
-Currently, the SofiaSIP.dsw workspace creates a shared library for
-sofia-sip-ua and a few test programs. The tests programs can be run 
-with the script check.cmd.
+The MSVC2005 solution file is "SofiaSIP.sln".
index e8a581ad706b056cd0f33a6293c6d431ff000b86..e0f99ae3a4405bd82de59268f8433568e34349ca 100644 (file)
@@ -97,6 +97,10 @@ SOURCE="..\..\libsofia-sip-ua\su\inet_pton.c"
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE="..\..\libsofia-sip-ua\su\string0.c"\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE="..\..\libsofia-sip-ua\su\su.c"\r
 # End Source File\r
 # Begin Source File\r
@@ -229,10 +233,6 @@ SOURCE="..\..\libsofia-sip-ua\ipt\rc4.c"
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE="..\..\libsofia-sip-ua\ipt\string0.c"\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE="..\..\libsofia-sip-ua\ipt\token64.c"\r
 # End Source File\r
 # End Group\r
@@ -861,6 +861,10 @@ SOURCE="..\..\libsofia-sip-ua\su\sofia-sip\rbtree.h"
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE="..\..\libsofia-sip-ua\su\sofia-sip\string0.h"\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE="..\..\libsofia-sip-ua\su\sofia-sip\su.h"\r
 # End Source File\r
 # Begin Source File\r
@@ -997,10 +1001,6 @@ SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\rc4.h"
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\string0.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\token64.h"\r
 # End Source File\r
 # End Group\r
index 0f3cfe6853f9612dc9ccb0c49aa05c5b9025ec37..275fb8fd0975773a4f823daab85b36146b23284d 100644 (file)
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\string0.c"\r
+                                       >\r
+                                       <FileConfiguration\r
+                                               Name="Debug|Win32"\r
+                                               >\r
+                                               <Tool\r
+                                                       Name="VCCLCompilerTool"\r
+                                                       ObjectFile="$(IntDir)\$(InputName)1.obj"\r
+                                                       XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"\r
+                                               />\r
+                                       </FileConfiguration>\r
+                                       <FileConfiguration\r
+                                               Name="Release|Win32"\r
+                                               >\r
+                                               <Tool\r
+                                                       Name="VCCLCompilerTool"\r
+                                                       ObjectFile="$(IntDir)\$(InputName)1.obj"\r
+                                                       XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"\r
+                                               />\r
+                                       </FileConfiguration>\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\su.c"\r
                                        >\r
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
-                               <File\r
-                                       RelativePath="..\..\libsofia-sip-ua\ipt\string0.c"\r
-                                       >\r
-                                       <FileConfiguration\r
-                                               Name="Debug|Win32"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                                       AdditionalIncludeDirectories=""\r
-                                                       PreprocessorDefinitions=""\r
-                                               />\r
-                                       </FileConfiguration>\r
-                                       <FileConfiguration\r
-                                               Name="Release|Win32"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                                       AdditionalIncludeDirectories=""\r
-                                                       PreprocessorDefinitions=""\r
-                                               />\r
-                                       </FileConfiguration>\r
-                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\token64.c"\r
                                        >\r
                                        RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\rbtree.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\string0.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\su.h"\r
                                        >\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\rc4.h"\r
                                        >\r
                                </File>\r
-                               <File\r
-                                       RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\string0.h"\r
-                                       >\r
-                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\token64.h"\r
                                        >\r
index 55bb0ff7fd96acbcd42ced6d40444088dcf673d2..36f6142f95a46abfc1237452054cccd2edfad063 100644 (file)
@@ -109,6 +109,10 @@ SOURCE="..\..\libsofia-sip-ua\su\inet_pton.c"
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE="..\..\libsofia-sip-ua\su\string0.c"\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE="..\..\libsofia-sip-ua\su\su.c"\r
 # End Source File\r
 # Begin Source File\r
@@ -241,10 +245,6 @@ SOURCE="..\..\libsofia-sip-ua\ipt\rc4.c"
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE="..\..\libsofia-sip-ua\ipt\string0.c"\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE="..\..\libsofia-sip-ua\ipt\token64.c"\r
 # End Source File\r
 # End Group\r
@@ -1009,10 +1009,6 @@ SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\rc4.h"
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\string0.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE="..\..\libsofia-sip-ua\ipt\sofia-sip\token64.h"\r
 # End Source File\r
 # End Group\r
index 7b0cbf38c4b2a6b5ab91839928de7c4983ba942b..b737130180654a84c890178836fda3ec89128be8 100644 (file)
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\string0.c"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\su.c"\r
                                        >\r
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
-                               <File\r
-                                       RelativePath="..\..\libsofia-sip-ua\ipt\string0.c"\r
-                                       >\r
-                                       <FileConfiguration\r
-                                               Name="Debug|Win32"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                                       AdditionalIncludeDirectories=""\r
-                                                       PreprocessorDefinitions=""\r
-                                               />\r
-                                       </FileConfiguration>\r
-                                       <FileConfiguration\r
-                                               Name="Release|Win32"\r
-                                               >\r
-                                               <Tool\r
-                                                       Name="VCCLCompilerTool"\r
-                                                       AdditionalIncludeDirectories=""\r
-                                                       PreprocessorDefinitions=""\r
-                                               />\r
-                                       </FileConfiguration>\r
-                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\token64.c"\r
                                        >\r
                                        RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\rbtree.h"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\string0.h"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\sofia-sip\su.h"\r
                                        >\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\rc4.h"\r
                                        >\r
                                </File>\r
-                               <File\r
-                                       RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\string0.h"\r
-                                       >\r
-                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\ipt\sofia-sip\token64.h"\r
                                        >\r
index 4dbc7ed2c9adf902e2d7c9408768c71bc0c2285b..c6c3b89075821635eace0532adc32f551108875a 100644 (file)
@@ -45,6 +45,9 @@
 #define SU_HAVE_BSDSOCK         0
 #define SU_HAVE_STDINT          (0)
 #define SU_HAVE_NT              0
+
+/* note: on Windows 2000 and older (WINVER<=500), IPv6-tech-preview 
+ * is needed for IPv4 support as well, so SU_HAVE_IN6 must be set */
 #define SU_HAVE_IN6             1
 
 #define SU_HAVE_PTHREADS        (1)
index 662fc85f17750c82255fe263fbbda5fa51c3f3f2..2c6285897729161b6e56cc8aecb3bfa44458d9a7 100644 (file)
@@ -48,7 +48,7 @@
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..,..\..,..\..\..\libsofia-sip-ua\su,..\..\..\libsofia-sip-ua\features,..\..\..\libsofia-sip-ua\tport,..\..\..\libsofia-sip-ua\iptsec,..\..\..\libsofia-sip-ua\ipt,..\..\..\libsofia-sip-ua\url,..\..\..\libsofia-sip-ua\nta,..\..\..\libsofia-sip-ua\msg,..\..\..\libsofia-sip-ua\sip"\r
+                               AdditionalIncludeDirectories="..;..\..;&quot;..\..\..\libsofia-sip-ua\su&quot;;&quot;..\..\..\libsofia-sip-ua\features&quot;;&quot;..\..\..\libsofia-sip-ua\tport&quot;;&quot;..\..\..\libsofia-sip-ua\iptsec&quot;;&quot;..\..\..\libsofia-sip-ua\ipt&quot;;&quot;..\..\..\libsofia-sip-ua\url&quot;;&quot;..\..\..\libsofia-sip-ua\nta&quot;;&quot;..\..\..\libsofia-sip-ua\msg&quot;;&quot;..\..\..\libsofia-sip-ua\sip&quot;;&quot;..\..\..\libsofia-sip-ua\stun&quot;"\r
                                PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r