]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
sync back up again with sofia tree prior to their release
authorMichael Jerris <mike@jerris.com>
Fri, 9 Feb 2007 17:32:17 +0000 (17:32 +0000)
committerMichael Jerris <mike@jerris.com>
Fri, 9 Feb 2007 17:32:17 +0000 (17:32 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4177 d0543943-73ff-0310-b7d9-9358b9ac24b2

55 files changed:
libs/sofia-sip/AUTHORS
libs/sofia-sip/COPYRIGHTS
libs/sofia-sip/RELEASE
libs/sofia-sip/RELEASE.template
libs/sofia-sip/configure.ac
libs/sofia-sip/libsofia-sip-ua/ChangeLog
libs/sofia-sip/libsofia-sip-ua/http/http_parser.c
libs/sofia-sip/libsofia-sip-ua/http/sofia-sip/http_header.h
libs/sofia-sip/libsofia-sip-ua/http/test_http.c
libs/sofia-sip/libsofia-sip-ua/nta/nta.c
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_api.c
libs/sofia-sip/libsofia-sip-ua/nth/nth_server.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_register.c
libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c
libs/sofia-sip/libsofia-sip-ua/nua/outbound.c
libs/sofia-sip/libsofia-sip-ua/nua/outbound.h
libs/sofia-sip/libsofia-sip-ua/nua/sofia-sip/nua_tag.h
libs/sofia-sip/libsofia-sip-ua/nua/test_basic_call.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_register.c
libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c
libs/sofia-sip/libsofia-sip-ua/sip/sip_parser.c
libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h
libs/sofia-sip/libsofia-sip-ua/sip/test_sip_msg.c
libs/sofia-sip/libsofia-sip-ua/sip/torture_sip.c
libs/sofia-sip/libsofia-sip-ua/sip/validator.c
libs/sofia-sip/libsofia-sip-ua/sresolv/run_test_sresolv
libs/sofia-sip/libsofia-sip-ua/sresolv/test_sresolv.c
libs/sofia-sip/libsofia-sip-ua/su/Makefile.am
libs/sofia-sip/libsofia-sip-ua/su/poll.c
libs/sofia-sip/libsofia-sip-ua/su/run_test_su
libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
libs/sofia-sip/libsofia-sip-ua/su/su_epoll_port.c
libs/sofia-sip/libsofia-sip-ua/su/su_localinfo.c
libs/sofia-sip/libsofia-sip-ua/su/su_osx_runloop.c
libs/sofia-sip/libsofia-sip-ua/su/su_poll_port.c
libs/sofia-sip/libsofia-sip-ua/su/su_port.c
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_select_port.c
libs/sofia-sip/libsofia-sip-ua/su/su_timer.c
libs/sofia-sip/libsofia-sip-ua/su/su_win32_port.c
libs/sofia-sip/libsofia-sip-ua/su/torture_su.c
libs/sofia-sip/libsofia-sip-ua/su/torture_su_root.c
libs/sofia-sip/libsofia-sip-ua/tport/tport.c
libs/sofia-sip/win32/config.h.in
libs/sofia-sip/win32/libsofia-sip-ua-static/libsofia_sip_ua_static.vcproj
libs/sofia-sip/win32/libsofia-sip-ua/libsofia_sip_ua.vcproj
libs/sofia-sip/win32/utils/localinfo/localinfo.vcproj
libs/sofia-sip/win32/utils/sip_options_static/sip_options_static.vcproj

index 5d1f563250bf6852ce6f15c5efa06c83cf85c2e6..4adcf4e6861968d181b5ebd64212e0abdcf3854e 100644 (file)
@@ -10,6 +10,8 @@ Contributors (in alphabetical order, surname first)
 
 Chan, Tat <first.surname@nokia.com>
 Ciarkowski, Andrzej <wp-voigtkampff -at users -dot sourceforge -dot net>
+Denis-Courmont, Remi <first.surname@nokia.com>
+Filonenko Roman <shkoder -at ua -dot fm>
 Haataja, Mikko <first.surname@nokia.com>
 Jacobs, Remeres <first.surname@nokia.com>
 Jalava, Teemu <first.surname@nokia.com>
@@ -26,9 +28,7 @@ Urpalainen, Jari <first.surname@nokia.com>
 Whittaker, Colin <colinw -at occamnetworks -dot com>
 Zabaluev, Mikhail <first.surname@nokia.com>
 
-
 Note: for details on who did what, see the version control 
       system change history, and release notes for past releases at
       http://sofia-sip.sourceforge.net/relnotes/
-
-      
\ No newline at end of file
\ No newline at end of file
index 8aff640204a45d432d63cbbc7f2b9be6684196ba..09a1d2f70e36388efdba770fa2cfbcac35f1beb8 100644 (file)
@@ -221,3 +221,31 @@ other special, indirect and consequential damages, even if author has
 been advised of the possibility of such damages.
 
 ----------------------------------------------------------------------------
+
+libsofia-sip-ua/su/poll.c
+
+The package also contains files from GNU C Library by Free Software
+Foundation.
+
+These files are distributed with the following copyright notice:
+
+Copyright (C) 1994,1996,1997,1998,1999,2001,2002
+Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with the GNU C Library; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+----------------------------------------------------------------------------
index c217713741eee656b2b073400357c2220dcfb638..41f09c83cfa2ef46bc210bad567e9755a424cbfd 100644 (file)
@@ -5,21 +5,17 @@ Release notes for current version of Sofia-SIP
 Changes since last release
 --------------------------
 
-<changes since last written in freshmeat.net "Changes:" style;
- and in less than 10 lines />
-
-Bugs in blaa and foo have been fixed. The stack now supports
-use of foobar...
+Support for request queuing has been added to the high-level user-agent 
+API. Various portability improvements have been made related to Linux, 
+Mac OS X, Windows and Solaris ports. SIP registrations have been 
+modified to utilize persistent transport connections. The GObject 
+interface to 'nua' (nua-glib) has been dropped from the package and is 
+now distributed separately. Severe bugs in 'su', 'nua', 'nta', 'stun' and 
+'su-glib' modules have been fixed.
 
 API/ABI changes and versioning
 ------------------------------
 
-<see previous release notes at
- http://sofia-sip.sourceforge.net/relnotes/ for examples ;
- - should include all changes to public headers, and 
-   other important information to developers; 
- - and should be updated _continuously_! />
-
 New features in API are marked with Doxytag macro @NEW_1_12_5.
 Experimental features are marked with Doxytag macro @EXP_1_12_5.
 
@@ -38,8 +34,9 @@ libsofia-sip-ua:
 - Added sip_is_allowed() function and k_bitmap field to the 
   sip_allow_t structure 
 - Added sl_header_log implementation, updated its prototype
-- Added experimental SIP headers and related functions, 
-  enabled with ./configure option --enable-experimental 
+- Added experimental SIP headers Suppress-Notify-If-Match and
+  Suppress-Body-If-Match and functions related to them,
+  enabled with ./configure option --enable-experimental
 - Added SIP header Refer-Sub and related functions
 - Added <sofia-sip/sip_extra.h> include file
 - Added auc_info() function (sofia-sip/auth_client.h)
@@ -61,34 +58,32 @@ libsofia-sip-ua-glib:
   is now considered stable and will be API/ABI compatible with later 
   releases in the 1.12.x series.
 - ABI has been modified and applications built against 1.12.4 and earlier 
-  releases need to be rebuilt.
+  releases, need to be rebuilt.
 - Added su_glib_prefer_gsource() which makes glib-based su_port_t
   implementation the default choice when su_root_create() is called
 
 Contributors to this release
 ----------------------------
 
-<list of people who contributed to _this_ release
- - update as people's patches are added, or when you commit stuff
- - current development team members (see AUTHORS) may be omitted
- - name of the contributor should be enough (email addresses in AUTHORS),
-   plus a brief description of what was contributed
- - roughly sorted by number of patches accepted
-/> 
-
-- **template**: First Surname (patch to nua/soa/msg)
 - Petteri Puolakka (patch to stun)
-- Mikhail Zabluev (patch to su-glib mainloop integration)
+- Mikhail Zabaluev (patch to su-glib mainloop integration)
 - Michael Jerris (patch to url parsing # in sip/sips userpart)
 - Colin Whittaker (TPTAG_TOS())
 - Roman Filonenko (TPTAG_LOG(), TPTAG_DUMP(), 
                   patch to query DNS-servers with IP-Helper on win32)
+- Remi Denis-Courmont (patch to network change API)
+- Martti Mela (poll() emulation with select(), IPv6 and OS X fixes)
+- Kai Vehmanen (persistent registrations, release management)
+- Pekka Pessi (all the rest)
 
 See the AUTHORS file in the distribution package.
 
 Notes on new features
 ---------------------
 
+- The su_root_t reactor uses different implementation (epoll, poll or select
+  on Linux), depending on SU_PORT environment variable.
+
 - nua now supports request queuing, for instance, an application can send
   overlapping BYE and NOTIFY requests. The stack engine takes care of
   sending the new request only after the previous one has been responded.
@@ -115,22 +110,12 @@ Notes on new features
   STUN and HTTP support. See 'docs/devel_platform_notes.txt' for some
   additional notes to distributors.
 
-<information about major new features
- - new/changed/removed functionality
- - links to further documentation
- - section may be omitted for minor releases
-/> 
-
 Bugs fixed in this release
 --------------------------
 
-< notable bugs fixed in this release
- - check the sf.net bug tracker; see closed bugs,
-   sorted by closing date
- - other bugs as fixed in CVS/darcs
-/>
-
-- **template**: #9499652 sf.net bug item title
+- Fixed su_from_create() returning a sip_to_t instance. Problem reported by
+  Ludovico Cavedon.
+- Partially fixed problem #1633969 with too frequent timer
 - Fixed problem in dialog matching. Problem reported by Fabio Margarido.
 - Fixed #1624446 - su_wait_clone() (and nua_destroy()) blocking for ever if
   the root object was created using su_glib
index 87c8f4ccdb63ce1ed9928f621a11b37c6ee5e2fc..611367c1e3da69de18546abe360cb05b0b62fb30 100644 (file)
@@ -6,7 +6,8 @@ Changes since last release
 --------------------------
 
 <changes since last written in freshmeat.net "Changes:" style;
- and in less than 10 lines />
+ and in less than 10 lines, written in 3rd person English, with
+ complete sentences />
 
 Bugs in blaa and foo have been fixed. The stack now supports
 use of foobar...
@@ -39,9 +40,11 @@ Contributors to this release
 
 <list of people who contributed to _this_ release
  - update as people's patches are added, or when you commit stuff
- - current development team members (see AUTHORS) may be omitted
+ - current development team members (see AUTHORS) may be omitted,
+   or listed at the end of the contribur list (depending on the scope 
+   of the work done since the last release)
  - name of the contributor should be enough (email addresses in AUTHORS),
-   plus a brief description of what was contributed
+   plus a _brief_ description of what was contributed
  - roughly sorted by number of patches accepted
 /> 
 
index fead869c00548b284f37ff90567fd6ca48375f0d..bd4fbe4d194a0de5698381fc08e45e937b4b5a3c 100644 (file)
@@ -11,14 +11,14 @@ dnl information on the package
 dnl ---------------------------
 
 dnl update both the version for AC_INIT and the LIBSOFIA_SIP_UA_MAJOR_MINOR
-AC_INIT([sofia-sip], [1.12.4work])
+AC_INIT([sofia-sip], [1.12.5])
 AC_CONFIG_SRCDIR([libsofia-sip-ua/sip/sofia-sip/sip.h])
 AC_SUBST(VER_LIBSOFIA_SIP_UA_MAJOR_MINOR, [1.12])
 dnl Includedir specific to this sofia version
 AC_SUBST(include_sofiadir, '${includedir}/sofia-sip-1.12')
-AC_SUBST(LIBVER_SOFIA_SIP_UA_CUR, [3])
+AC_SUBST(LIBVER_SOFIA_SIP_UA_CUR, [4])
 AC_SUBST(LIBVER_SOFIA_SIP_UA_REV, [0])
-AC_SUBST(LIBVER_SOFIA_SIP_UA_AGE, [3])
+AC_SUBST(LIBVER_SOFIA_SIP_UA_AGE, [4])
 AC_SUBST(LIBVER_SOFIA_SIP_UA_SOVER, [0]) # CUR-AGE
 AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_CUR, [3])
 AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_REV, [0])
index b85f3bad3839a41f54d95703ec56734360589dea..9b33ad7b5bf22acf6d7638db06140c8ffdebf0f8 100644 (file)
@@ -1,3 +1,11 @@
+2007-02-09  Kai Vehmanen  <kai.vehmanen@nokia.com>
+
+       * libsofia-sip-ua interface v4 frozen (4:0:4) for the 1.12.5 release
+
+2006-10-12  Kai Vehmanen  <kai.vehmanen@nokia.com>
+
+       * libsofia-sip-ua interface v3 frozen (3:0:3) for the 1.12.3 release
+       
 2006-09-26  Kai Vehmanen  <kai.vehmanen@nokia.com>
 
        * libsofia-sip-ua interface v2 frozen (2:0:2) for the 1.12.2 release
index 1848086dabcfbed99bc104bd26b48143db573981..d3b2b3578120ea71a4ce128b3bc217df051c0a52 100644 (file)
@@ -61,9 +61,9 @@ char const http_version_1_0[] = "HTTP/1.0";
 /** HTTP version 0.9 is an empty string. */
 char const http_version_0_9[] = "";
 
-msg_mclass_t *http_default_mclass(void)
+msg_mclass_t const *http_default_mclass(void)
 {
-  extern msg_mclass_t http_mclass[];
+  extern msg_mclass_t const http_mclass[];
 
   return http_mclass;
 }
index 94234a62f731cf354e0ee392bfcc46835424ea93..6f8cf29fa95fcfd2a75571c470b84f8027eed79e 100644 (file)
@@ -95,7 +95,7 @@ SOFIAPUBVAR char const http_version_1_1[];
  */
 
 /** HTTP parser description. */
-SOFIAPUBFUN msg_mclass_t *http_default_mclass(void);
+SOFIAPUBFUN msg_mclass_t const *http_default_mclass(void);
 
 /** Complete a HTTP request. */
 SOFIAPUBFUN int http_request_complete(msg_t *msg);
index f282d233d85974bb9c81c719faa32497214cce81..8463e990573cf61d6eba860755b7bf66bd50bd5b 100644 (file)
@@ -76,7 +76,7 @@ static int http_tag_test(void);
 static int test_query_parser(void);
 
 static msg_t *read_message(char const string[]);
-msg_mclass_t *test_mclass = NULL;
+msg_mclass_t const *test_mclass = NULL;
 
 void usage(void)
 {
index 69871d9d11ce3a55a3909ad53e42eff696db0b7d..6ce0f7c95ae13427f204cc285562f7661ca3758b 100644 (file)
@@ -890,7 +890,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
   unsigned threadpool      = agent->sa_tport_threadpool;
   char const *sigcomp = agent->sa_sigcomp_options;
   char const *algorithm = NONE;
-  msg_mclass_t *mclass = NONE;
+  msg_mclass_t const *mclass = NONE;
   sip_contact_t const *aliases = NONE;
   url_string_t const *proxy = NONE;
   tport_t *tport;
@@ -4983,15 +4983,16 @@ static inline
 nta_incoming_t *incoming_find(nta_agent_t const *agent,
                              sip_t const *sip,
                              sip_via_t const *v,
-                             nta_incoming_t **merge,
-                             nta_incoming_t **ack)
+                             nta_incoming_t **return_merge,
+                             nta_incoming_t **return_ack)
 {
   sip_cseq_t const *cseq = sip->sip_cseq;
   sip_call_id_t const *i = sip->sip_call_id;
   sip_to_t const *to = sip->sip_to;
   sip_from_t const *from = sip->sip_from;
   sip_request_t *rq = sip->sip_request;
-  int is_uas_ack = ack && agent->sa_is_a_uas && rq->rq_method == sip_method_ack;
+  int is_uas_ack = return_ack && 
+    agent->sa_is_a_uas && rq->rq_method == sip_method_ack;
   incoming_htable_t const *iht = agent->sa_incoming;
   hash_value_t hash = NTA_HASH(i, cseq->cs_seq);
 
@@ -5008,6 +5009,30 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
       continue;
     if (str0casecmp(irq->irq_from->a_tag, from->a_tag))
       continue;
+
+    if (str0casecmp(irq->irq_via->v_branch, v->v_branch) != 0 ||
+       strcasecmp(irq->irq_via->v_host, v->v_host) != 0) {
+      if (!agent->sa_is_a_uas)
+       continue;
+      
+      if (is_uas_ack &&
+         irq->irq_method == sip_method_invite && 
+         200 <= irq->irq_status && irq->irq_status < 300 &&
+         addr_match(irq->irq_to, to))
+       *return_ack = irq;
+      /* RFC3261 - section 8.2.2.2 Merged Requests */
+      else if (return_merge && agent->sa_merge_482 &&
+              irq->irq_cseq->cs_method == cseq->cs_method &&
+              (irq->irq_cseq->cs_method != sip_method_unknown ||
+               strcmp(irq->irq_cseq->cs_method_name, 
+                      cseq->cs_method_name) == 0)) {
+       *return_merge = irq;
+       continue;
+      }
+      else
+       continue;
+    }
+
     if (is_uas_ack) {
       if (!addr_match(irq->irq_to, to))
        continue;
@@ -5020,16 +5045,6 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
     else if (str0casecmp(irq->irq_to->a_tag, to->a_tag))
       continue;
 
-    if (str0casecmp(irq->irq_via->v_branch, v->v_branch) != 0) {
-      if (!agent->sa_is_a_uas)
-       continue;
-      if (is_uas_ack && irq->irq_status >= 200 && irq->irq_status < 300)
-       *ack = irq;
-      /* RFC3261 - section 8.2.2.2 Merged Requests */
-      else if (merge && !to->a_tag && agent->sa_merge_482)
-       *merge = irq;
-      continue;
-    }
     if (!is_uas_ack && url_cmp(irq->irq_rq->rq_url, rq->rq_url))
       continue;
 
@@ -5041,18 +5056,18 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
     if (irq->irq_method == rq->rq_method)
       break;           /* found */
 
-    if (ack && rq->rq_method == sip_method_cancel)
-      *ack = irq;
-    else if (ack && rq->rq_method == sip_method_ack && 
+    if (return_ack && rq->rq_method == sip_method_cancel)
+      *return_ack = irq;
+    else if (return_ack && rq->rq_method == sip_method_ack && 
             irq->irq_method == sip_method_invite)
-      *ack = irq;
+      *return_ack = irq;
   }
 
   if (irq)
     return irq;
 
   /* Check PRACKed requests */
-  if (ack && rq->rq_method == sip_method_prack && sip->sip_rack) {
+  if (return_ack && rq->rq_method == sip_method_prack && sip->sip_rack) {
     sip_rack_t const *rack = sip->sip_rack;
     hash = NTA_HASH(i, rack->ra_cseq);
 
@@ -5072,7 +5087,7 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
        continue;
       if (!irq->irq_from->a_tag != !from->a_tag)
        continue;
-      *ack = irq;
+      *return_ack = irq;
 
       return NULL;
     }
index cf3ff53a8e85b00e93b8634c894ffb0a0220d76e..1a8440b34306aa93cf0167619009efaf09117712 100644 (file)
@@ -108,7 +108,7 @@ struct nta_agent_s
   uint32_t              sa_nw_updates; /* Shall we enable network detector? */
 
   uint32_t              sa_flags;      /**< Message flags */
-  msg_mclass_t         *sa_mclass;
+  msg_mclass_t const   *sa_mclass;
 
   sip_contact_t        *sa_contact;
   sip_via_t            *sa_vias;   /**< @Via headers for all transports */
index d6548234d95bf36c48d84a2d096127f09db16333..60adcd74ad3250d37e21c7c6f05fbdd2bd1fcdb4 100644 (file)
@@ -110,38 +110,38 @@ tag_typedef_t ntatag_rseq = UINTTAG_TYPEDEF(rseq);
 
 /* Status */
 
-tag_typedef_t ntatag_s_irq_hash =         UINTTAG_TYPEDEF(s_irq_hash);
-tag_typedef_t ntatag_s_orq_hash =         UINTTAG_TYPEDEF(s_orq_hash);
-tag_typedef_t ntatag_s_leg_hash =         UINTTAG_TYPEDEF(s_leg_hash);
-tag_typedef_t ntatag_s_irq_hash_used =    UINTTAG_TYPEDEF(s_irq_hash_used);
-tag_typedef_t ntatag_s_orq_hash_used =    UINTTAG_TYPEDEF(s_orq_hash_used);
-tag_typedef_t ntatag_s_leg_hash_used =    UINTTAG_TYPEDEF(s_leg_hash_used);
-tag_typedef_t ntatag_s_recv_msg =         UINTTAG_TYPEDEF(s_recv_msg);
-tag_typedef_t ntatag_s_recv_request =     UINTTAG_TYPEDEF(s_recv_request);
-tag_typedef_t ntatag_s_recv_response =    UINTTAG_TYPEDEF(s_recv_response);
-tag_typedef_t ntatag_s_bad_message =      UINTTAG_TYPEDEF(s_bad_message);
-tag_typedef_t ntatag_s_bad_request =      UINTTAG_TYPEDEF(s_bad_request);
-tag_typedef_t ntatag_s_bad_response =     UINTTAG_TYPEDEF(s_bad_response);
-tag_typedef_t ntatag_s_drop_request =     UINTTAG_TYPEDEF(s_drop_request);
-tag_typedef_t ntatag_s_drop_response =    UINTTAG_TYPEDEF(s_drop_response);
-tag_typedef_t ntatag_s_client_tr =        UINTTAG_TYPEDEF(s_client_tr);
-tag_typedef_t ntatag_s_server_tr =        UINTTAG_TYPEDEF(s_server_tr);
-tag_typedef_t ntatag_s_dialog_tr =        UINTTAG_TYPEDEF(s_dialog_tr);
-tag_typedef_t ntatag_s_acked_tr =         UINTTAG_TYPEDEF(s_acked_tr);
-tag_typedef_t ntatag_s_canceled_tr =      UINTTAG_TYPEDEF(s_canceled_tr);
-tag_typedef_t ntatag_s_trless_request =   UINTTAG_TYPEDEF(s_trless_request);
-tag_typedef_t ntatag_s_trless_to_tr =     UINTTAG_TYPEDEF(s_trless_to_tr);
-tag_typedef_t ntatag_s_trless_response =  UINTTAG_TYPEDEF(s_trless_response);
-tag_typedef_t ntatag_s_trless_200 =       UINTTAG_TYPEDEF(s_trless_200);
-tag_typedef_t ntatag_s_merged_request =   UINTTAG_TYPEDEF(s_merged_request);
-tag_typedef_t ntatag_s_sent_msg =                UINTTAG_TYPEDEF(s_sent_msg);
-tag_typedef_t ntatag_s_sent_request =            UINTTAG_TYPEDEF(s_sent_request);
-tag_typedef_t ntatag_s_sent_response =           UINTTAG_TYPEDEF(s_sent_response);
-tag_typedef_t ntatag_s_retry_request =           UINTTAG_TYPEDEF(s_retry_request);
-tag_typedef_t ntatag_s_retry_response =   UINTTAG_TYPEDEF(s_retry_response);
-tag_typedef_t ntatag_s_recv_retry =       UINTTAG_TYPEDEF(s_recv_retry);
-tag_typedef_t ntatag_s_tout_request =     UINTTAG_TYPEDEF(s_tout_request);
-tag_typedef_t ntatag_s_tout_response =    UINTTAG_TYPEDEF(s_tout_response);
+tag_typedef_t ntatag_s_irq_hash =         USIZETAG_TYPEDEF(s_irq_hash);
+tag_typedef_t ntatag_s_orq_hash =         USIZETAG_TYPEDEF(s_orq_hash);
+tag_typedef_t ntatag_s_leg_hash =         USIZETAG_TYPEDEF(s_leg_hash);
+tag_typedef_t ntatag_s_irq_hash_used =    USIZETAG_TYPEDEF(s_irq_hash_used);
+tag_typedef_t ntatag_s_orq_hash_used =    USIZETAG_TYPEDEF(s_orq_hash_used);
+tag_typedef_t ntatag_s_leg_hash_used =    USIZETAG_TYPEDEF(s_leg_hash_used);
+tag_typedef_t ntatag_s_recv_msg =         USIZETAG_TYPEDEF(s_recv_msg);
+tag_typedef_t ntatag_s_recv_request =     USIZETAG_TYPEDEF(s_recv_request);
+tag_typedef_t ntatag_s_recv_response =    USIZETAG_TYPEDEF(s_recv_response);
+tag_typedef_t ntatag_s_bad_message =      USIZETAG_TYPEDEF(s_bad_message);
+tag_typedef_t ntatag_s_bad_request =      USIZETAG_TYPEDEF(s_bad_request);
+tag_typedef_t ntatag_s_bad_response =     USIZETAG_TYPEDEF(s_bad_response);
+tag_typedef_t ntatag_s_drop_request =     USIZETAG_TYPEDEF(s_drop_request);
+tag_typedef_t ntatag_s_drop_response =    USIZETAG_TYPEDEF(s_drop_response);
+tag_typedef_t ntatag_s_client_tr =        USIZETAG_TYPEDEF(s_client_tr);
+tag_typedef_t ntatag_s_server_tr =        USIZETAG_TYPEDEF(s_server_tr);
+tag_typedef_t ntatag_s_dialog_tr =        USIZETAG_TYPEDEF(s_dialog_tr);
+tag_typedef_t ntatag_s_acked_tr =         USIZETAG_TYPEDEF(s_acked_tr);
+tag_typedef_t ntatag_s_canceled_tr =      USIZETAG_TYPEDEF(s_canceled_tr);
+tag_typedef_t ntatag_s_trless_request =   USIZETAG_TYPEDEF(s_trless_request);
+tag_typedef_t ntatag_s_trless_to_tr =     USIZETAG_TYPEDEF(s_trless_to_tr);
+tag_typedef_t ntatag_s_trless_response =  USIZETAG_TYPEDEF(s_trless_response);
+tag_typedef_t ntatag_s_trless_200 =       USIZETAG_TYPEDEF(s_trless_200);
+tag_typedef_t ntatag_s_merged_request =   USIZETAG_TYPEDEF(s_merged_request);
+tag_typedef_t ntatag_s_sent_msg =                USIZETAG_TYPEDEF(s_sent_msg);
+tag_typedef_t ntatag_s_sent_request =            USIZETAG_TYPEDEF(s_sent_request);
+tag_typedef_t ntatag_s_sent_response =           USIZETAG_TYPEDEF(s_sent_response);
+tag_typedef_t ntatag_s_retry_request =           USIZETAG_TYPEDEF(s_retry_request);
+tag_typedef_t ntatag_s_retry_response =   USIZETAG_TYPEDEF(s_retry_response);
+tag_typedef_t ntatag_s_recv_retry =       USIZETAG_TYPEDEF(s_recv_retry);
+tag_typedef_t ntatag_s_tout_request =     USIZETAG_TYPEDEF(s_tout_request);
+tag_typedef_t ntatag_s_tout_response =    USIZETAG_TYPEDEF(s_tout_response);
 
 /* Internal */
 tag_typedef_t ntatag_delay_sending = BOOLTAG_TYPEDEF(delay_sending);
index eaeee457c7b96160e11cdfe2a24bea3e56331730..e0f284b7e73bbe8eb534c13f9190cfb317fbfe25 100644 (file)
@@ -59,10 +59,10 @@ NTA_DLL extern tag_typedef_t ntatag_any;
 
 NTA_DLL extern tag_typedef_t ntatag_mclass;
 /** Message class used by NTA. @HI */
-#define NTATAG_MCLASS(x) ntatag_mclass, tag_ptr_v((x))
+#define NTATAG_MCLASS(x) ntatag_mclass, tag_cptr_v((x))
 
 NTA_DLL extern tag_typedef_t ntatag_mclass_ref;
-#define NTATAG_MCLASS_REF(x) ntatag_mclass_ref, tag_ptr_vr(&(x), (x))
+#define NTATAG_MCLASS_REF(x) ntatag_mclass_ref, tag_cptr_vr(&(x), (x))
 
 NTA_DLL extern tag_typedef_t ntatag_bad_req_mask;
 /** Mask for bad request messages. 
@@ -503,184 +503,184 @@ NTA_DLL extern tag_typedef_t ntatag_s_leg_hash_used_ref;
 ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_msg;
-#define NTATAG_S_RECV_MSG(x) ntatag_s_recv_msg, tag_uint_v(x)
+#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;
-#define NTATAG_S_RECV_MSG_REF(x) ntatag_s_recv_msg_ref, tag_uint_vr(&(x))
+#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_uint_v(x)
+#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;
 #define NTATAG_S_RECV_REQUEST_REF(x)\
- ntatag_s_recv_request_ref, tag_uint_vr(&(x))
+ ntatag_s_recv_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_response;
-#define NTATAG_S_RECV_RESPONSE(x) ntatag_s_recv_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_RECV_RESPONSE_REF(x)\
- ntatag_s_recv_response_ref, tag_uint_vr(&(x))
+ ntatag_s_recv_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_message;
-#define NTATAG_S_BAD_MESSAGE(x) ntatag_s_bad_message, tag_uint_v(x)
+#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;
 #define NTATAG_S_BAD_MESSAGE_REF(x)\
- ntatag_s_bad_message_ref, tag_uint_vr(&(x))
+ ntatag_s_bad_message_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_request;
-#define NTATAG_S_BAD_REQUEST(x) ntatag_s_bad_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_BAD_REQUEST_REF(x)\
- ntatag_s_bad_request_ref, tag_uint_vr(&(x))
+ ntatag_s_bad_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_bad_response;
-#define NTATAG_S_BAD_RESPONSE(x) ntatag_s_bad_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_BAD_RESPONSE_REF(x)\
- ntatag_s_bad_response_ref, tag_uint_vr(&(x))
+ ntatag_s_bad_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_drop_request;
-#define NTATAG_S_DROP_REQUEST(x) ntatag_s_drop_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_DROP_REQUEST_REF(x)\
- ntatag_s_drop_request_ref, tag_uint_vr(&(x))
+ ntatag_s_drop_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_drop_response;
-#define NTATAG_S_DROP_RESPONSE(x) ntatag_s_drop_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_DROP_RESPONSE_REF(x)\
- ntatag_s_drop_response_ref, tag_uint_vr(&(x))
+ ntatag_s_drop_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_client_tr;
-#define NTATAG_S_CLIENT_TR(x) ntatag_s_client_tr, tag_uint_v(x)
+#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;
 #define NTATAG_S_CLIENT_TR_REF(x)\
- ntatag_s_client_tr_ref, tag_uint_vr(&(x))
+ ntatag_s_client_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_server_tr;
-#define NTATAG_S_SERVER_TR(x) ntatag_s_server_tr, tag_uint_v(x)
+#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;
 #define NTATAG_S_SERVER_TR_REF(x)\
- ntatag_s_server_tr_ref, tag_uint_vr(&(x))
+ ntatag_s_server_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr;
-#define NTATAG_S_DIALOG_TR(x) ntatag_s_dialog_tr, tag_uint_v(x)
+#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;
 #define NTATAG_S_DIALOG_TR_REF(x)\
- ntatag_s_dialog_tr_ref, tag_uint_vr(&(x))
+ ntatag_s_dialog_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_acked_tr;
-#define NTATAG_S_ACKED_TR(x) ntatag_s_acked_tr, tag_uint_v(x)
+#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;
-#define NTATAG_S_ACKED_TR_REF(x) ntatag_s_acked_tr_ref, tag_uint_vr(&(x))
+#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_uint_v(x)
+#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;
 #define NTATAG_S_CANCELED_TR_REF(x)  \
- ntatag_s_canceled_tr_ref, tag_uint_vr(&(x))
+ ntatag_s_canceled_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_request;
-#define NTATAG_S_TRLESS_REQUEST(x) ntatag_s_trless_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_TRLESS_REQUEST_REF(x)\
- ntatag_s_trless_request_ref, tag_uint_vr(&(x))
+ ntatag_s_trless_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr;
-#define NTATAG_S_TRLESS_TO_TR(x) ntatag_s_trless_to_tr, tag_uint_v(x)
+#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;
 #define NTATAG_S_TRLESS_TO_TR_REF(x)\
- ntatag_s_trless_to_tr_ref, tag_uint_vr(&(x))
+ ntatag_s_trless_to_tr_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_response;
-#define NTATAG_S_TRLESS_RESPONSE(x) ntatag_s_trless_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_TRLESS_RESPONSE_REF(x)\
- ntatag_s_trless_response_ref, tag_uint_vr(&(x))
+ ntatag_s_trless_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_trless_200;
-#define NTATAG_S_TRLESS_200(x) ntatag_s_trless_200, tag_uint_v(x)
+#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;
 #define NTATAG_S_TRLESS_200_REF(x)\
- ntatag_s_trless_200_ref, tag_uint_vr(&(x))
+ ntatag_s_trless_200_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_merged_request;
-#define NTATAG_S_MERGED_REQUEST(x) ntatag_s_merged_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_MERGED_REQUEST_REF(x)\
- ntatag_s_merged_request_ref, tag_uint_vr(&(x))
+ ntatag_s_merged_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_msg;
-#define NTATAG_S_SENT_MSG(x) ntatag_s_sent_msg, tag_uint_v(x)
+#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;
 #define NTATAG_S_SENT_MSG_REF(x)\
- ntatag_s_sent_msg_ref, tag_uint_vr(&(x))
+ ntatag_s_sent_msg_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_request;
-#define NTATAG_S_SENT_REQUEST(x) ntatag_s_sent_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_SENT_REQUEST_REF(x)\
- ntatag_s_sent_request_ref, tag_uint_vr(&(x))
+ ntatag_s_sent_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_sent_response;
-#define NTATAG_S_SENT_RESPONSE(x) ntatag_s_sent_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_SENT_RESPONSE_REF(x)\
- ntatag_s_sent_response_ref, tag_uint_vr(&(x))
+ ntatag_s_sent_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_retry_request;
-#define NTATAG_S_RETRY_REQUEST(x) ntatag_s_retry_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_RETRY_REQUEST_REF(x)\
- ntatag_s_retry_request_ref, tag_uint_vr(&(x))
+ ntatag_s_retry_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_retry_response;
-#define NTATAG_S_RETRY_RESPONSE(x) ntatag_s_retry_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_RETRY_RESPONSE_REF(x)\
- ntatag_s_retry_response_ref, tag_uint_vr(&(x))
+ ntatag_s_retry_response_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_recv_retry;
-#define NTATAG_S_RECV_RETRY(x) ntatag_s_recv_retry, tag_uint_v(x)
+#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;
 #define NTATAG_S_RECV_RETRY_REF(x)\
- ntatag_s_recv_retry_ref, tag_uint_vr(&(x))
+ ntatag_s_recv_retry_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_tout_request;
-#define NTATAG_S_TOUT_REQUEST(x) ntatag_s_tout_request, tag_uint_v(x)
+#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;
 #define NTATAG_S_TOUT_REQUEST_REF(x)\
- ntatag_s_tout_request_ref, tag_uint_vr(&(x))
+ ntatag_s_tout_request_ref, tag_usize_vr(&(x))
 
 NTA_DLL extern tag_typedef_t ntatag_s_tout_response;
-#define NTATAG_S_TOUT_RESPONSE(x) ntatag_s_tout_response, tag_uint_v(x)
+#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;
 #define NTATAG_S_TOUT_RESPONSE_REF(x)\
- ntatag_s_tout_response_ref, tag_uint_vr(&(x))
+ ntatag_s_tout_response_ref, tag_usize_vr(&(x))
 
 SOFIA_END_DECLS
 
index 84f38cc3edb41f9e5d1c31038990b5f4d9b93a51..57dae90b332c78a72a15b601b6ca971784a820a2 100644 (file)
@@ -559,18 +559,18 @@ int api_test_stats(agent_t *ag)
 
   nta_agent_t *nta;
 
-  uint32_t irq_hash = -1, orq_hash = -1, leg_hash = -1;
-  uint32_t recv_msg = -1, sent_msg = -1;
-  uint32_t recv_request = -1, recv_response = -1;
-  uint32_t bad_message = -1, bad_request = -1, bad_response = -1;
-  uint32_t drop_request = -1, drop_response = -1;
-  uint32_t client_tr = -1, server_tr = -1, dialog_tr = -1;
-  uint32_t acked_tr = -1, canceled_tr = -1;
-  uint32_t trless_request = -1, trless_to_tr = -1, trless_response = -1;
-  uint32_t trless_200 = -1, merged_request = -1;
-  uint32_t sent_request = -1, sent_response = -1;
-  uint32_t retry_request = -1, retry_response = -1, recv_retry = -1;
-  uint32_t tout_request = -1, tout_response = -1;
+  usize_t irq_hash = -1, orq_hash = -1, leg_hash = -1;
+  usize_t recv_msg = -1, sent_msg = -1;
+  usize_t recv_request = -1, recv_response = -1;
+  usize_t bad_message = -1, bad_request = -1, bad_response = -1;
+  usize_t drop_request = -1, drop_response = -1;
+  usize_t client_tr = -1, server_tr = -1, dialog_tr = -1;
+  usize_t acked_tr = -1, canceled_tr = -1;
+  usize_t trless_request = -1, trless_to_tr = -1, trless_response = -1;
+  usize_t trless_200 = -1, merged_request = -1;
+  usize_t sent_request = -1, sent_response = -1;
+  usize_t retry_request = -1, retry_response = -1, recv_retry = -1;
+  usize_t tout_request = -1, tout_response = -1;
 
   TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*",
                                NULL, NULL, TAG_END()));
@@ -1301,10 +1301,10 @@ int main(int argc, char *argv[])
   }
 
   if (o_attach) {
-    char line[10];
+    char *response, line[10];
     printf("nua_test: pid %lu\n", (unsigned long)getpid());
     printf("<Press RETURN to continue>\n");
-    fgets(line, sizeof line, stdin);
+    response = fgets(line, sizeof line, stdin);
   }
 #if HAVE_ALARM
   else if (o_alarm) {
index 288c83a8ec6f4e2f0ab193f6d75087772538e9ae..0eb56bedf8f9ef97e943698234a8fdc3ae90db36 100644 (file)
@@ -704,7 +704,7 @@ server_t *server_create(url_t const *url,
                        tag_type_t tag, tag_value_t value, ...)
 {
   server_t *srv;
-  msg_mclass_t *mclass = NULL;
+  msg_mclass_t const *mclass = NULL;
   tp_name_t tpn[1] = {{ NULL }};
   su_root_t *root = NULL;
   http_server_t const *server = NULL;
index dcb8aa6f7011eef27a8cf7e2139b7bd66d6e6960..1be85fc9b72266d70a1ac682dedf963b84eaf7f9 100644 (file)
@@ -378,11 +378,9 @@ void nua_dialog_usage_remove_at(nua_owner_t *own,
     su_free(own, du);
   }
 
-  /* Zap dialog if there is no more usages */
+  /* Zap dialog if there are no more usages */
   if (ds->ds_usage == NULL) {
-    nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL;
-    su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL;
-    ds->ds_route = 0;
+    nua_dialog_remove(own, ds, NULL);
     ds->ds_has_events = 0;
     ds->ds_terminated = 0;
     return;
index 51cc6d3891dcc0d2a75dfa8f728288e1a14d928f..ce1b3f451b29f3dddab038182957fcee98f376e6 100644 (file)
@@ -119,8 +119,11 @@ struct register_usage {
   nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */
   sip_from_t *nr_aor;          /**< AoR for this registration, NULL if none */
   sip_contact_t *nr_contact;   /**< Our Contact */
+  sip_contact_t nr_dcontact[1];        /**< Contact in dialog */
   sip_via_t *nr_via;           /**< Corresponding Via headers */
 
+  unsigned long nr_min_expires;        /**< Value from 423 negotiation */
+
   /** Status of registration */
   unsigned nr_ready:1;
   /** Kind of registration.
@@ -222,14 +225,13 @@ static void nua_register_usage_peer_info(nua_dialog_usage_t *du,
 /* Interface towards outbound_t */
 sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
                                         su_home_t *home,
+                                        int in_dialog,
                                         char const *extra_username,
                                         sip_via_t const *v,
                                         char const *transport,
                                         char const *m_param,
                                         ...);
 
-static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob);
-
 static int nua_stack_outbound_refresh(nua_handle_t *,
                                      outbound_t *ob);
 
@@ -431,6 +433,11 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
  * the desired transport-layer keepalive interval for stream-based
  * transports like TLS and TCP.
  *
+ * As alternative to OPTIONS/STUN keepalives, the client can propose
+ * a more frequent registration refresh interval with
+ * NUTAG_M_FEATURES() (e.g. NUTAG_M_FEATURES("expires=120") given as 
+ * parameter to nua_register()).
+ * 
  * @sa #nua_r_register, nua_unregister(), #nua_r_unregister, 
  * #nua_i_register,
  * @RFC3261 section 10,
@@ -659,7 +666,6 @@ static int nua_register_client_init(nua_client_request_t *cr,
                         NH_PISSET(nh, keepalive_stream)
                         ? NH_PGET(nh, keepalive_stream)
                         : NH_PGET(nh, keepalive));
-    nua_stack_outbound_features(nh, ob);
 
     if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0)
       return nua_client_return(cr, 900, "Cannot set outbound contact", msg);
@@ -676,7 +682,8 @@ int nua_register_client_request(nua_client_request_t *cr,
   nua_handle_t *nh = cr->cr_owner;
   nua_dialog_usage_t *du = cr->cr_usage;
   nua_registration_t *nr;
-  sip_contact_t *m = NULL, *contacts = sip->sip_contact, *previous = NULL;
+  sip_contact_t *m, *contacts = sip->sip_contact;
+  char const *min_expires = NULL;
   int unreg;
 
   (void)nh;
@@ -698,48 +705,58 @@ int nua_register_client_request(nua_client_request_t *cr,
       if (m == NULL)
        nua_client_terminating(cr);
     }
-
-    if (cr->cr_terminating) {
-      /* Remove the expire parameters from contacts */
-      for (m = sip->sip_contact; m; m = m->m_next) {
-       if (m->m_url->url_type == url_any) {
-         /* If there is a '*' in contact list, remove everything else */
-         while (m != sip->sip_contact)
-           sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact);
-         while (m->m_next)
-           sip_header_remove(msg, sip, (sip_header_t *)m->m_next);
-         contacts = m;
-         break;
-       }
-       msg_header_remove_param(m->m_common, "expires");
-      }
-    }
   }
 
   unreg = cr->cr_terminating;
 
-  if (du) {
-    nr = nua_dialog_usage_private(du);
+  nr = nua_dialog_usage_private(du);
 
+  if (nr) {
     if (nr->nr_ob) {
       outbound_stop_keepalive(nr->nr_ob);
       outbound_start_registering(nr->nr_ob);
     }
 
     if (nr->nr_by_stack) {
-      m = nr->nr_contact;
+      sip_contact_t *m = nr->nr_contact, *previous = NULL;
+
       outbound_get_contacts(nr->nr_ob, &m, &previous);
+
+      sip_add_dup(msg, sip, (sip_header_t *)m);
+      /* previous is an outdated contact generated by stack 
+       * and it is now unregistered */
+      if (previous)
+       sip_add_dup(msg, sip, (sip_header_t *)previous);
+    }
+  }
+
+  for (m = sip->sip_contact; m; m = m->m_next) {
+    if (m->m_url->url_type == url_any) {
+      /* If there is a '*' in contact list, remove everything else */
+      while (m != sip->sip_contact)
+       sip_header_remove(msg, sip, (sip_header_t *)sip->sip_contact);
+      while (m->m_next)
+       sip_header_remove(msg, sip, (sip_header_t *)m->m_next);
+      contacts = m;
+      break;
+    }
+
+    if (!m->m_expires)
+      continue;
+    if (unreg) {
+      /* Remove the expire parameters from contacts */
+      msg_header_remove_param(m->m_common, "expires");
+    }
+    else if (nr && nr->nr_min_expires && 
+            strtoul(m->m_expires, 0, 10) < nr->nr_min_expires) {
+      if (min_expires == NULL) 
+       min_expires = su_sprintf(msg_home(msg), "expires=%lu", 
+                                nr->nr_min_expires);
+      msg_header_replace_param(msg_home(msg), m->m_common, min_expires);
     }
   }
 
   return nua_base_client_trequest(cr, msg, sip,
-                                 /* m is stack-generated contact */
-                                 SIPTAG_CONTACT(m),
-                                 /* 
-                                  * previous is outdated stack-generated contact
-                                  * which is now unregistered
-                                  */
-                                 SIPTAG_CONTACT(previous),
                                  TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")),
 #if 0
                                  TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)),
@@ -772,6 +789,11 @@ static int nua_register_client_check_restart(nua_client_request_t *cr,
       /* XXX - report an error? */;
   }
 
+  if (nr && status == 423) {
+    if (sip->sip_min_expires)
+      nr->nr_min_expires = sip->sip_min_expires->me_delta;
+  }
+
   /* Check for status-specific reasons to retry */
   if (nua_base_client_check_restart(cr, status, phrase, sip))
     return 1;
@@ -1262,11 +1284,8 @@ int nua_registration_from_via(nua_registration_t **list,
 
     v2[1].v_next = NULL;
 
-#if 1
-    contact = nua_handle_contact_by_via(nh, home, NULL, v2, protocol, NULL);
-#else
-    contact = sip_contact_create_from_via_with_transport(home, v2, NULL, protocol);
-#endif
+    contact = nua_handle_contact_by_via(nh, home, 0, NULL, v2, protocol, NULL);
+
     v = sip_via_dup(home, v2);
 
     if (!contact || !v) {
@@ -1277,6 +1296,7 @@ int nua_registration_from_via(nua_registration_t **list,
     nr->nr_ready = 1, nr->nr_default = 1, nr->nr_public = public;
     nr->nr_secure = contact->m_url->url_type == url_sips;
     nr->nr_contact = contact;
+    *nr->nr_dcontact = *contact, nr->nr_dcontact->m_params = NULL;
     nr->nr_via = v;
     nr->nr_ip4 = host_is_ip4_address(contact->m_url->url_host);
     nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(contact->m_url->url_host);
@@ -1446,7 +1466,10 @@ sip_contact_t const *nua_registration_contact(nua_registration_t const *nr)
       return m;
   }
 
-  return nr->nr_contact;
+  if (nr->nr_contact)
+    return nr->nr_dcontact;
+  else
+    return NULL;
 }
 
 /** Return initial route. */
@@ -1458,7 +1481,7 @@ sip_route_t const *nua_registration_route(nua_registration_t const *nr)
 sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr)
 {
   nr = nua_registration_by_aor(nr, NULL, NULL, 1);
-  return nr ? nr->nr_contact : NULL;
+  return nr && nr->nr_contact ? nr->nr_dcontact : NULL;
 }
 
 /** Add a Contact (and Route) header to request */
@@ -1531,23 +1554,51 @@ int nua_registration_add_contact_and_route(nua_handle_t *nh,
     return -1;
 
   if (add_contact) {
-    sip_contact_t const *m = nua_registration_contact(nr);
+    sip_contact_t const *m = NULL;
+    char const *m_display;
+    char const *m_username;
+    char const *m_params;
+    url_t const *u;
 
-    char const *m_display = NH_PGET(nh, m_display);
-    char const *m_username = NH_PGET(nh, m_username);
-    char const *m_params = NH_PGET(nh, m_params);
-    url_t const *u = m->m_url;
+    if (nr->nr_by_stack && nr->nr_ob) {
+      m = outbound_dialog_gruu(nr->nr_ob);
+
+      if (m)
+       return msg_header_add_dup(msg, (msg_pub_t *)sip, (void const *)m);
+
+      m = outbound_dialog_contact(nr->nr_ob);
+    }
+
+    if (m == NULL)
+      m = nr->nr_contact;
 
     if (!m)
       return -1;
 
-    if (str0cmp(m_params, u->url_params) == 0)
+    u = m->m_url;
+
+    if (NH_PISSET(nh, m_display))
+      m_display = NH_PGET(nh, m_display);
+    else
+      m_display = m->m_display;
+
+    if (NH_PISSET(nh, m_username))
+      m_username = NH_PGET(nh, m_username);
+    else
+      m_username = m->m_url->url_user;
+
+    if (NH_PISSET(nh, m_params)) {
+      m_params = NH_PGET(nh, m_params);
+
+      if (u->url_params && m_params && strstr(u->url_params, m_params) == 0)
+       m_params = NULL;
+    }
+    else
       m_params = NULL;
 
     m = sip_contact_format(msg_home(msg),
                           "%s<%s:%s%s%s%s%s%s%s%s%s>",
-                          m_display ? m_display : 
-                          m->m_display ? m->m_display : "",
+                          m_display ? m_display : "",
                           u->url_scheme,
                           m_username ? m_username : "",
                           m_username ? "@" : "",
@@ -1648,7 +1699,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
 
     if (nr0 && nr0->nr_via) {
       char const *tport = nr0->nr_via->v_next ? NULL : nr0->nr_via->v_protocol;
-      m = nua_handle_contact_by_via(nh, nh->nh_home,
+      m = nua_handle_contact_by_via(nh, nh->nh_home, 0,
                                    NULL, nr0->nr_via, tport, NULL);
     }
   }
@@ -1657,6 +1708,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
     return -1;
 
   nr->nr_contact = m;
+  *nr->nr_dcontact = *m, nr->nr_dcontact->m_params = NULL;
   nr->nr_ip4 = host_is_ip4_address(m->m_url->url_host);
   nr->nr_ip6 = !nr->nr_ip4 && host_is_ip6_reference(m->m_url->url_host);
   nr->nr_by_stack = !application_contact;
@@ -1785,6 +1837,7 @@ static int nua_stack_outbound_credentials(nua_handle_t *nh,
 /** @internal Generate a @Contact header. */
 sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
                                         su_home_t *home,
+                                        int in_dialog,
                                         char const *extra_username,
                                         sip_via_t const *v,
                                         char const *transport,
@@ -1868,7 +1921,7 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
     su_strlst_append(l, ";comp="), su_strlst_append(l, comp);
   s = NH_PGET(nh, m_params);
   if (s) 
-    su_strlst_append(l, s[0] == ';' ? "" : ";"), su_strlst_append(l, s);
+    s[0] == ';' ? "" : su_strlst_append(l, ";"), su_strlst_append(l, s);
   su_strlst_append(l, ">");
 
   va_start(va, m_param);
@@ -1882,81 +1935,42 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
   
   va_end(va);
 
-  m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), ""));
-  
-  su_strlst_destroy(l);
-  
-  return m;
-}
-
-/** @internal Return a string describing our features. */
-static char *nua_handle_features(nua_handle_t *nh)
-{
-  char *retval = NULL;
-  su_strlst_t *l = su_strlst_create(NULL);
-  su_home_t *home = su_strlst_home(l);
-
-  if (!l)
-    return NULL;
-
-  if (NH_PGET(nh, m_features)) {
-    char const *m_features = NH_PGET(nh, m_features);
-
-    if (m_features[0] != ';')
-      su_strlst_append(l, ";");
-
-    su_strlst_append(l, m_features);
-  }
-
-  if (NH_PGET(nh, callee_caps)) {
-    sip_allow_t const *allow = NH_PGET(nh, allow);
-
-    if (allow) {
-      /* Skip ";" if this is first one */
-      su_strlst_append(l, ";methods=\"" + (su_strlst_len(l) == 0));
-      if (allow->k_items) {
-        size_t i;
-        for (i = 0; allow->k_items[i]; i++) {
-          su_strlst_append(l, allow->k_items[i]);
-          if (allow->k_items[i + 1])
-            su_strlst_append(l, ",");
-        }
+  if (!in_dialog) {
+    s = NH_PGET(nh, m_features);
+    if (s) 
+      s[0] == ';' ? "" : su_strlst_append(l, ";"), su_strlst_append(l, s);
+
+    if (NH_PGET(nh, callee_caps)) {
+      sip_allow_t const *allow = NH_PGET(nh, allow);
+
+      if (allow) {
+       su_strlst_append(l, ";methods=\"");
+       if (allow->k_items) {
+         size_t i;
+         for (i = 0; allow->k_items[i]; i++) {
+           su_strlst_append(l, allow->k_items[i]);
+           if (allow->k_items[i + 1])
+             su_strlst_append(l, ",");
+         }
+       }
+       su_strlst_append(l, "\"");
       }
-      su_strlst_append(l, "\"");
-    }
-
-    if (nh->nh_soa) {
-      char **media = soa_media_features(nh->nh_soa, 0, home);
 
-      while (*media) {
-        if (su_strlst_len(l))
-          su_strlst_append(l, ";");
-        su_strlst_append(l, *media++);
+      if (nh->nh_soa) {
+       char **media = soa_media_features(nh->nh_soa, 0, home);
+       
+       while (*media) {
+         if (su_strlst_len(l))
+           su_strlst_append(l, ";");
+         su_strlst_append(l, *media++);
+       }
       }
     }
   }
 
-  if (su_strlst_len(l))
-    retval = su_strlst_join(l, nh->nh_home, "");
-
+  m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), ""));
+  
   su_strlst_destroy(l);
-
-  return retval;
-}
-
-static int nua_stack_outbound_features(nua_handle_t *nh, outbound_t *ob)
-{
-  char *features;
-  int retval;
-
-  if (!nh)
-    return -1;
-  if (!ob)
-    return 0;
-
-  features = nua_handle_features(nh);
-  retval = outbound_set_features(ob, features);
-  su_free(nh->nh_home, features);
-
-  return retval;
+  
+  return m;
 }
index 3d3e994563a7588ff6da35c512ce28798b2da016..a134e0842ffa048640ef8bf22012b00be5bdbc24 100644 (file)
@@ -299,10 +299,7 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg,
 
     if (tags) {
       tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len);
-      void *b = t_end;
-#ifndef NDEBUG
-         void *end = (char *)b + xtra;
-#endif
+      void *b = t_end, *end = (char *)b + xtra;
 
       t = tl_dup(t, tags, &b); p = b;
       assert(t == t_end); assert(b == end); (void)end;
index 2713cfb41dba5a5ced34289941e1ee13b8261b06..867e4b42011f12496cbb71249c67c1a7fa7818b0 100644 (file)
@@ -117,7 +117,6 @@ struct outbound {
 
   char const *ob_instance;     /**< Our instance ID */
   int32_t ob_reg_id;           /**< Flow-id */
-  char const *ob_features;     /**< Feature parameters for rcontact */
   sip_contact_t *ob_rcontact;  /**< Our contact */
   sip_contact_t *ob_dcontact;  /**< Contact for dialogs */
   sip_contact_t *ob_previous;  /**< Stale contact */
@@ -327,20 +326,6 @@ int outbound_set_options(outbound_t *ob,
   return 0;
 }
 
-/** Set the feature string (added to the Contact header when registering). */
-int outbound_set_features(outbound_t *ob, char *features)
-{
-  char *old_features = (char *)ob->ob_features;
-  char *new_features = su_strdup(ob->ob_home, features);
-
-  if (features && !new_features)
-    return -1;
-
-  ob->ob_features = new_features;
-  su_free(ob->ob_home, old_features);
-  return 0;
-}
-
 /* ---------------------------------------------------------------------- */
 
 /** Obtain contacts for REGISTER */
@@ -698,21 +683,32 @@ static int create_keepalive_message(outbound_t *ob, sip_t const *regsip)
 {
   msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous;
   sip_t *osip = sip_object(msg);
-  sip_accept_contact_t *ac;
-
-  char const *p1 = ob->ob_instance;
-  char const *p2 = ob->ob_features;
+  sip_contact_t *m = ob->ob_rcontact;
 
   unsigned d = ob->ob_keepalive.interval;
 
   assert(regsip); assert(regsip->sip_request);
 
-  if (p1 || p2) {
-    ac = sip_accept_contact_format(msg_home(msg), "*;require;explicit;%s%s%s",
-                                  p1 ? p1 : "",
-                                  p2 && p2 ? ";" : "",
-                                  p2 ? p2 : "");
-    msg_header_insert(msg, NULL, (void *)ac);
+  if (m && m->m_params) {
+    sip_accept_contact_t *ac;
+    size_t i;
+    int features = 0;
+
+    ac = sip_accept_contact_make(msg_home(msg), "*;require;explicit");
+
+    for (i = 0; m->m_params[i]; i++) {
+      char const *s = m->m_params[i];
+      if (!sip_is_callerpref(s))
+       continue;
+      features++;
+      s = su_strdup(msg_home(msg), s);
+      msg_header_add_param(msg_home(msg), ac->cp_common, s);
+    }
+    
+    if (features)
+      msg_header_insert(msg, NULL, (void *)ac);
+    else
+      msg_header_free(msg_home(msg), (void *)ac);
   }
 
   if (0 >
@@ -1008,46 +1004,16 @@ int outbound_contacts_from_via(outbound_t *ob, sip_via_t const *via)
 
   v = v0; *v0 = *via; v0->v_next = NULL;
 
-  dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
+  dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1,
                                   NULL, v, v->v_protocol, NULL);
 
   if (ob->ob_instance && ob->ob_reg_id != 0)
     snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
 
-  rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
+  rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
                                   NULL, v, v->v_protocol, 
-                                  ob->ob_features ? ob->ob_features : "",
                                   ob->ob_instance, reg_id_param, NULL);
     
-#if 0
-  char *uri;
-
-  /* uri contains < > */
-  uri = sip_contact_string_from_via(NULL, via, NULL, v->v_protocol);
-
-  dcontact = sip_contact_make(home, uri);
-
-  if (ob->ob_instance) {
-    char reg_id[20];
-
-    if (ob->ob_instance && ob->ob_reg_id)
-      snprintf(reg_id, sizeof reg_id, ";reg-id=%u", ob->ob_reg_id);
-    else
-      strcpy(reg_id, "");
-
-    rcontact = sip_contact_format(home, "%s;%s%s%s%s",
-                                 uri, ob->ob_instance, reg_id,
-                                 ob->ob_features ? ";" : "",
-                                 ob->ob_features ? ob->ob_features : "");
-  }
-  else if (ob->ob_features)
-    rcontact = sip_contact_format(home, "%s;%s", uri, ob->ob_features);
-  else
-    rcontact = dcontact;
-
-  free(uri);
-#endif
-
   v = sip_via_dup(home, v);
 
   if (!rcontact || !dcontact || !v) {
@@ -1139,7 +1105,7 @@ int outbound_set_contact(outbound_t *ob,
     char const *tport = !v->v_next ? v->v_protocol : NULL; 
     char reg_id_param[20];
 
-    dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
+    dcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 1, 
                                     NULL, v, tport, NULL);
     if (!dcontact)
       return -1;
@@ -1147,9 +1113,8 @@ int outbound_set_contact(outbound_t *ob,
     if (ob->ob_instance && ob->ob_reg_id != 0)
       snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id);
 
-    rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home,
+    rcontact = ob->ob_oo->oo_contact(ob->ob_owner, home, 0,
                                     NULL, v, v->v_protocol, 
-                                    ob->ob_features ? ob->ob_features : "",
                                     ob->ob_instance, reg_id_param, NULL);
     if (!rcontact)
       return -1;
@@ -1195,6 +1160,11 @@ sip_contact_t const *outbound_dialog_contact(outbound_t const *ob)
     return ob->ob_dcontact;
 }
 
+sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob)
+{
+  return ob ? ob->ob_gruu : NULL;
+}
+
 /* ---------------------------------------------------------------------- */
 
 
index b86994686d5778e0440f484a8c0e30a35762e5c2..ef9d1d4cc345ff4419def539e16194309f6293bb 100644 (file)
@@ -70,8 +70,6 @@ int outbound_set_options(outbound_t *ob,
                         unsigned dgram_interval,
                         unsigned stream_interval);
 
-int outbound_set_features(outbound_t *ob, char *features);
-
 int outbound_get_contacts(outbound_t *ob, 
                          sip_contact_t **return_current_contact, 
                          sip_contact_t **return_previous_contact);
@@ -98,6 +96,8 @@ int outbound_set_contact(outbound_t *ob,
 
 sip_contact_t const *outbound_dialog_contact(outbound_t const *ob);
 
+sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob);
+
 int outbound_gruuize(outbound_t *ob, sip_t const *sip);
 
 void outbound_start_keepalive(outbound_t *ob,
@@ -118,6 +118,7 @@ struct outbound_owner_vtable
   int oo_size;
   sip_contact_t *(*oo_contact)(outbound_owner_t *,
                               su_home_t *home,
+                              int used_in_dialog,
                               char const *extra_username,
                               sip_via_t const *v,
                               char const *transport,
index 39b17a4e5788b74710d3ec665a107825a1fbd426..f643ae4e224ca4f7bbe26170357ba51274c77e00 100644 (file)
@@ -1074,7 +1074,7 @@ SOFIAPUBVAR tag_typedef_t nutag_registrar_ref;
  *
  * The outbound option string can specify how the NAT traversal is handled.
  * The option tokens are as follows:
- * - "gruuize": try to generate a GRUU
+ * - "gruuize": try to generate a GRUU contact from REGISTER response
  * - "outbound": use SIP outbound extension (off by default)
  * - "validate": validate registration behind a NAT by sending OPTIONS to self
  * - "natify": try to traverse NAT
@@ -1084,6 +1084,10 @@ SOFIAPUBVAR tag_typedef_t nutag_registrar_ref;
  * An option token with "no-" or "not-" prefix turns the option off. For
  * example, if you want to try to traverse NATs but not to use OPTIONS
  * keepalive, use NUTAG_OUTBOUND("natify no-options-keepalive").
+ * 
+ * An empty string can be passed to let the stack choose the
+ * default values for outbound usage (in the 1.12.5 release, the
+ * defaults are: "gruuize no-outbound validate use-port options-keepalive").
  *
  * @note
  * Options string is used so that no new tags need to be added when the
@@ -1207,7 +1211,7 @@ SOFIAPUBVAR tag_typedef_t nutag_outbound_set4_ref;
  *    nua_create()
  *
  * @par Parameter type
- *    msg_mclass_t *
+ *    msg_mclass_t const *
  *
  * @par Values
  *    Pointer to an extended SIP parser.
@@ -1243,6 +1247,9 @@ SOFIAPUBVAR tag_typedef_t nutag_auth;
 SOFIAPUBVAR tag_typedef_t nutag_auth_ref;
 
 /** Keepalive interval in milliseconds.
+ *
+ * This setting applies to OPTIONS/STUN keepalives. See documentation 
+ * for nua_register() for more detailed information.
  *
  * @par Used with
  *    nua_register()   \n
@@ -1268,6 +1275,8 @@ SOFIAPUBVAR tag_typedef_t nutag_keepalive;
 SOFIAPUBVAR tag_typedef_t nutag_keepalive_ref;
 
 /** Transport-level keepalive interval for streams.
+ *
+ * See documentation for nua_register() for more detailed information.
  *
  * @par Used with
  *    nua_register()   \n
index 35c1c159f7cedd4f4f17ee5a10cec3d2d52fe26d..36e51e861b8a8bfc5ae28015d05bb25bcc5efb4b 100644 (file)
@@ -478,6 +478,47 @@ int test_basic_call_2(struct context *ctx)
   TEST_1(nua_handle_has_active_call(b_call->nh));
   TEST_1(!nua_handle_has_call_on_hold(b_call->nh));
 
+  /* Send a NOTIFY from B to A */
+  if (print_headings)
+    printf("TEST NUA-3.2.2: send a NOTIFY within a dialog\n");
+
+  /* Make A to accept NOTIFY */
+  nua_set_params(a->nua, NUTAG_APPL_METHOD("NOTIFY"), TAG_END());
+  run_a_until(ctx, nua_r_set_params, until_final_response);
+
+  NOTIFY(b, b_call, b_call->nh,
+        NUTAG_NEWSUB(1),
+        SIPTAG_SUBJECT_STR("NUA-3.2.2"),
+        SIPTAG_EVENT_STR("message-summary"),
+        SIPTAG_CONTENT_TYPE_STR("application/simple-message-summary"),
+        SIPTAG_PAYLOAD_STR("Messages-Waiting: no"),
+        TAG_END());
+
+  run_ab_until(ctx, -1, accept_notify, -1, save_until_final_response);
+
+  /* Notifier events: nua_r_notify */
+  TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_notify);
+  TEST(e->data->e_status, 200);
+  TEST_1(tl_find(e->data->e_tags, nutag_substate));
+  TEST(tl_find(e->data->e_tags, nutag_substate)->t_value,
+       nua_substate_terminated);
+
+  /* watcher events: nua_i_notify */
+  TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_notify);
+  TEST_1(sip = sip_object(e->data->e_msg));
+  TEST_1(sip->sip_subscription_state);
+  TEST_S(sip->sip_subscription_state->ss_substate, "terminated");
+  TEST_1(tl_find(e->data->e_tags, nutag_substate));
+  TEST(tl_find(e->data->e_tags, nutag_substate)->t_value, 
+       nua_substate_terminated);
+  TEST_1(!e->next);
+
+  free_events_in_list(ctx, a->events);
+  free_events_in_list(ctx, b->events);
+
+  if (print_headings)
+    printf("TEST NUA-3.2.2: PASSED\n");
+
   INFO(b, b_call, b_call->nh, TAG_END());
   BYE(b, b_call, b_call->nh, TAG_END());
   INFO(b, b_call, b_call->nh, TAG_END());
index d764fb77d76e64b19348e63fcff39ee9a5189843..1a062a7729a267fb2a4c6e2a13ce0454dd650e1a 100644 (file)
@@ -92,6 +92,9 @@ static char const options_usage[] =
   "   --no-alarm        don't ask for guard ALARM\n"
   "   -p uri            specify uri of outbound proxy (implies --no-proxy)\n"
   "   --proxy-tests     run tests involving proxy, too\n"
+#if SU_HAVE_OSX_CF_API /* If compiled with CoreFoundation events */
+  "   --osx-runloop     use OSX CoreFoundation runloop instead of poll() loop\n"
+#endif
   "   -k                do not exit after first error\n"
   ;
 
index 305611a133d86d050d8cf546edb1e9cc7ee1a754..0ad5cb08e40d7a0872aec3c0f6e5ede4671c3869 100644 (file)
@@ -216,6 +216,8 @@ int until_terminated(CONDITION_PARAMS);
 int until_ready(CONDITION_PARAMS);
 int accept_call(CONDITION_PARAMS);
 
+int accept_notify(CONDITION_PARAMS);
+
 void a_callback(nua_event_t event,
                int status, char const *phrase,
                nua_t *nua, struct context *ctx,
index fb41bdd2a855b8e6b8277b1089dbeed203b76221..04563c0e834261670ae6a59425b43021d25859de 100644 (file)
@@ -133,6 +133,8 @@ int test_register_to_proxy(struct context *ctx)
           NUTAG_KEEPALIVE(1000),
           NUTAG_M_DISPLAY("A&A"),
           NUTAG_M_USERNAME("a"),
+          NUTAG_M_PARAMS("foo=bar"),
+          NUTAG_M_FEATURES("q=0.9"),
           SIPTAG_CSEQ(cseq),
           TAG_END());
   run_a_until(ctx, -1, save_until_final_response);
@@ -161,6 +163,8 @@ int test_register_to_proxy(struct context *ctx)
     /* VC does not dig \" with TEST_S() */
   TEST_S(sip->sip_contact->m_display, expect_m_display); }
   TEST_S(sip->sip_contact->m_url->url_user, "a");
+  TEST_1(strstr(sip->sip_contact->m_url->url_params, "foo=bar"));
+  TEST_S(sip->sip_contact->m_q, "0.9");
   TEST(sip->sip_cseq->cs_seq, 14);
 
   if (ctx->nat) {
@@ -222,8 +226,12 @@ int test_register_to_proxy(struct context *ctx)
   TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END()));
 
   REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to), 
+          NUTAG_OUTBOUND(NULL),
           NUTAG_M_DISPLAY("C"),
           NUTAG_M_USERNAME("c"),
+          NUTAG_M_PARAMS("c=1"),
+          NUTAG_M_FEATURES("q=0.987;expires=5"),
+          NUTAG_CALLEE_CAPS(1),
           SIPTAG_EXPIRES_STR("5"), /* Test 423 negotiation */
           TAG_END());
   run_abc_until(ctx, -1, save_events, -1, save_events, 
@@ -254,6 +262,9 @@ int test_register_to_proxy(struct context *ctx)
   TEST_1(sip->sip_contact);
   TEST_S(sip->sip_contact->m_display, "C");
   TEST_S(sip->sip_contact->m_url->url_user, "c");
+  TEST_1(strstr(sip->sip_contact->m_url->url_params, "c=1"));
+  TEST_S(sip->sip_contact->m_q, "0.987");
+  TEST_1(msg_header_find_param(sip->sip_contact->m_common, "methods="));
   TEST_1(!e->next);
   free_events_in_list(ctx, c->events);
 
@@ -688,6 +699,7 @@ int test_unregister(struct context *ctx)
   UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to), 
             NUTAG_M_DISPLAY("C"),
             NUTAG_M_USERNAME("c"),
+            NUTAG_M_PARAMS("c=1"),
             TAG_END());
   run_c_until(ctx, -1, save_until_final_response);
 
index 26125f24aea75a37393c4619bf9ab9ffaa8a40c4..25a9cea6ac0cfdfa3b2e9ca15c819c66a8766fcb 100644 (file)
@@ -899,7 +899,7 @@ sip_addr_make_url(su_home_t *home, msg_hclass_t *hc, url_string_t const *us)
   sip_header_t *h;
 
   n = url_xtra(us->us_url);
-  h = sip_header_alloc(home, sip_to_class, n);    
+  h = sip_header_alloc(home, hc, n);    
 
   if (h) {
     sip_addr_t *a = h->sh_to;
index eab35a7351e219a1cbaf522a5fa7ed945ca192a8..8905c6a507e91f209925e1b3c9f6f76b4d7ac9ee 100644 (file)
@@ -60,9 +60,9 @@ char const sip_parser_version[] = VERSION;
 char const sip_version_2_0[] = "SIP/2.0";
 
 /** Default message class */
-extern msg_mclass_t sip_mclass[];
+extern msg_mclass_t const sip_mclass[];
 
-msg_mclass_t *sip_default_mclass(void)
+msg_mclass_t const *sip_default_mclass(void)
 {
   return sip_mclass;
 }
index 70045d860936b6dbc2e5d5c6774f55416ea02d3b..b2d0b1af78ceae8564edaf5e2e5428f186909b2c 100644 (file)
@@ -58,7 +58,7 @@
 SOFIA_BEGIN_DECLS
 
 /** Return built-in SIP parser object. */
-SOFIAPUBFUN msg_mclass_t *sip_default_mclass(void);
+SOFIAPUBFUN msg_mclass_t const *sip_default_mclass(void);
 
 /** Check that sip_t is a SIP structure (not RTSP or HTTP). @HIDE */
 #define sip_is_sip(sip) ((sip) && (sip)->sip_ident == SIP_PROTOCOL_TAG)
index 8139330e98ba6426c563d23fbe0e236e83022526..3a973afc62dbc4479b45703772ced90df63b67b0 100644 (file)
@@ -65,7 +65,7 @@ int diff(const char *olds, const char *news, int *linep, int *pos)
   return *o != *n;
 }
 
-int test_msg_class(msg_mclass_t *mc)
+int test_msg_class(msg_mclass_t const *mc)
 {
   int i, j, N;
 
@@ -159,7 +159,7 @@ int main(int argc, char *argv[])
   int m, tcp;
   sip_t *sip;
   int exitcode = 0; 
-  msg_mclass_t *sip_mclass = sip_default_mclass();
+  msg_mclass_t const *sip_mclass = sip_default_mclass();
   msg_t *msg = msg_create(sip_mclass, MSG_FLG_EXTRACT_COPY);
   msg_iovec_t iovec[1];
 
index 58fe6d2e4538ad1d4e73decfce25e4d2037068cf..84d71851b8a20222ff68b95039f5f01e24a5848f 100644 (file)
@@ -412,7 +412,12 @@ int test_basic(void)
     TEST_1(sip_from_tag(home, f, "tag=jxahudsf") == 0);
     su_free(home, f);
 
+    TEST_1(f = sip_from_create(home, (void *)"<sip:joe@bar;tag=bar> (joe)"));
+    TEST_1(sip_is_from((sip_header_t*)f));
+    su_free(home, f);
+
     TEST_1(t = sip_to_create(home, (void *)"<sip:joe@bar;tag=bar> (joe)"));
+    TEST_1(sip_is_to((sip_header_t*)f));
     TEST_1(sip_to_tag(home, t, "tag=jxahudsf") == 0);
     TEST_S(t->a_tag, "jxahudsf");
     TEST(msg_header_replace_param(home, t->a_common, "tag=bar"), 1);
index 2741eef7c859d22508abf42cd42a6af221d5b5ee..5bcb4ffdbaebc0fe41a20fefd20b26726aed0827 100644 (file)
@@ -180,7 +180,7 @@ char *lastpart(char *path)
     return path;
 }
 
-msg_mclass_t *mclass = NULL;
+msg_mclass_t const *mclass = NULL;
 
 int validate_file(int fd, char const *name, context_t *ctx);
 int validate_dump(char *, off_t, context_t *ctx);
index 8798bd39162c0e09a207ab88056fc55f2c27d40b..26a1832aa0a830636795e5ae7130a5149a527d6e 100644 (file)
@@ -55,9 +55,11 @@ if netstat --ip >/dev/null 2>&1 ; then
     done
 fi
 
-# No named, no fun
-type -p named >/dev/null || {
-echo test_sresolv: there is no BIND named installed, skipping
+# No BIND 9, no fun
+{ type -p named >/dev/null &&
+  named -v | grep -q BIND.*9 
+} || {
+echo test_sresolv: there is no BIND 9 named in you path, skipping
 exit 77
 } 
 
index 0c369d278cb05bd34d8997f4b5d344ef83f47c50..efb8a06ca48f93644647efe23f06714961111024 100644 (file)
@@ -64,7 +64,6 @@ typedef unsigned _int32 uint32_t;
 #include <sofia-resolv/sres_async.h>
 #include <sofia-resolv/sres_record.h>
 
-#include <sofia-sip/su.h>
 #include <sofia-sip/su_alloc.h>
 
 #include <assert.h>
@@ -120,6 +119,84 @@ static void test_answer_multi(sres_context_t *ctx, sres_query_t *query,
 
 static int tstflags = 0;
 
+#if HAVE_WINSOCK2_H
+
+/* Posix send() */
+static inline 
+ssize_t sres_send(sres_socket_t s, void *b, size_t length, int flags)
+{
+  if (length > INT_MAX)
+    length = INT_MAX;
+  return (ssize_t)send(s, b, (int)length, flags);
+}
+
+static inline 
+ssize_t sres_sendto(sres_socket_t s, void *b, size_t length, int flags,
+                   struct sockaddr const *sa, socklen_t salen)
+{
+  if (length > INT_MAX)
+    length = INT_MAX;
+  return (ssize_t)sendto(s, b, (int)length, flags, (void *)sa, (int)salen);
+}
+
+/* Posix recvfrom() */
+static inline 
+ssize_t sres_recvfrom(sres_socket_t s, void *buffer, size_t length, int flags,
+                     struct sockaddr *from, socklen_t *fromlen)
+{
+  int retval, ilen;
+
+  if (fromlen)
+    ilen = *fromlen;
+
+  if (length > INT_MAX)
+    length = INT_MAX;
+
+  retval = recvfrom(s, buffer, (int)length, flags, 
+                   (void *)from, fromlen ? &ilen : NULL);
+
+  if (fromlen)
+    *fromlen = ilen;
+
+  return (ssize_t)retval;
+}
+
+static sres_socket_t sres_socket(int af, int socktype, int protocol)
+{
+  return socket(af, socktype, protocol);
+}
+
+static inline
+int sres_close(sres_socket_t s)
+{
+  return closesocket(s);
+}
+
+#if !defined(IPPROTO_IPV6)
+#if HAVE_SIN6
+#include <tpipv6.h>
+#else
+#if !defined(__MINGW32__)
+struct sockaddr_storage {
+    short ss_family;
+    char ss_pad[126];
+};
+#endif
+#endif
+#endif
+#else
+
+#define sres_send(s,b,len,flags) send((s),(b),(len),(flags))
+#define sres_sendto(s,b,len,flags,a,alen) \
+  sendto((s),(b),(len),(flags),(a),(alen))
+#define sres_recvfrom(s,b,len,flags,a,alen) \
+  recvfrom((s),(b),(len),(flags),(a),(alen))
+#define sres_close(s) close((s))
+#define SOCKET_ERROR   (-1)
+#define INVALID_SOCKET ((sres_socket_t)-1)
+#define sres_socket(x,y,z) socket((x),(y),(z))
+#endif
+
 #if 1
 
 #if HAVE_POLL && 0
@@ -145,7 +222,7 @@ static
 int test_socket(sres_context_t *ctx)
 {
   int af;
-  su_sockeet_t s1, s2, s3, s4;
+  sres_socket_t s1, s2, s3, s4;
   struct sockaddr_storage a[1];
   struct sockaddr_storage a1[1], a2[1], a3[1], a4[1];
   struct sockaddr_in *sin = (void *)a;
@@ -160,10 +237,10 @@ int test_socket(sres_context_t *ctx)
   af = AF_INET;
 
   for (;;) {
-    TEST_1((s1 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
-    TEST_1((s2 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
-    TEST_1((s3 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
-    TEST_1((s4 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
+    TEST_1((s1 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
+    TEST_1((s2 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
+    TEST_1((s3 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
+    TEST_1((s4 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
 
     TEST_1(setblocking(s1, 0) == 0);
     TEST_1(setblocking(s2, 0) == 0);
@@ -212,13 +289,13 @@ int test_socket(sres_context_t *ctx)
     TEST(connect(s2, sa4, a4len), 0);
     TEST(getsockname(s2, (struct sockaddr *)a2, &a2len), 0);
 
-    TEST(sendto(s1, "foo", 3, 0, sa4, a4len), 3);
-    TEST(recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3);
-    TEST(sendto(s4, "bar", 3, 0, sa, alen), 3);
-    TEST(recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1);
-    TEST(recvfrom(s1, buf, sizeof buf, 0, sa, &alen), 3);
+    TEST(sres_sendto(s1, "foo", 3, 0, sa4, a4len), 3);
+    TEST(sres_recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3);
+    TEST(sres_sendto(s4, "bar", 3, 0, sa, alen), 3);
+    TEST(sres_recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1);
+    TEST(sres_recvfrom(s1, buf, sizeof buf, 0, sa, &alen), 3);
 
-    su_close(s1), su_close(s2), su_close(s3), su_close(s4);
+    sres_close(s1), sres_close(s2), sres_close(s3), sres_close(s4);
 
     break;
   }
@@ -1428,7 +1505,7 @@ int sink_deinit(sres_context_t *ctx)
   if (ctx->sinkidx)
     su_root_deregister(ctx->root, ctx->sinkidx);
   ctx->sinkidx = 0;
-  su_close(ctx->sink), ctx->sink = INVALID_SOCKET;
+  sres_close(ctx->sink), ctx->sink = INVALID_SOCKET;
 
   END();
 }
@@ -1453,7 +1530,7 @@ int test_timeout(sres_context_t *ctx)
 
   result = sres_cached_answers(res, sres_type_a, domain);
 
-#if 0
+#if 0  /* Currently, we do not create error records */
   TEST_1(result); TEST_1(result[0] != NULL);
 
   rr_soa = result[0]->sr_soa;
@@ -1464,7 +1541,6 @@ int test_timeout(sres_context_t *ctx)
 
   sres_free_answers(res, result);
 #else
-  /* Currently, we do not create error records */
   TEST_1(result == NULL);
 #endif
 
@@ -1625,7 +1701,8 @@ int test_net(sres_context_t *ctx)
   struct sockaddr *sa = (void *)ss;
   socklen_t salen = sizeof ss;
   char *bin;
-  size_t i, n, binlen;
+  size_t i, binlen;
+  ssize_t n;
   char const *domain = "example.com";
   char query[512];
 
@@ -1647,14 +1724,14 @@ int test_net(sres_context_t *ctx)
       /* We got an error => make new query */
       TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
                                 sres_type_naptr, domain));
-      TEST_1((n = recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
+      TEST_1((n = sres_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
       memcpy(bin, query, 2); /* Copy ID */
     }
     if (i != 1)
       bin[i] ^= 0xff;
     else
       bin[3] ^= SRES_FORMAT_ERR; /* format error -> EDNS0 failure */
-    n = su_sendto(c, bin, binlen, 0, sa, salen);
+    n = sres_sendto(c, bin, binlen, 0, sa, salen);
     if (i != 1)
       bin[i] ^= 0xff;
     else
@@ -1675,10 +1752,10 @@ int test_net(sres_context_t *ctx)
       /* We got an error => make new query */
       TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
                                 sres_type_naptr, domain));
-      TEST_1((n = su_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
+      TEST_1((n = sres_recvfrom(c, query, sizeof query, 0, sa, &salen)) != -1);
       memcpy(bin, query, 2); /* Copy ID */
     }
-    n = su_sendto(c, bin, i, 0, sa, salen);
+    n = sres_sendto(c, bin, i, 0, sa, salen);
     if (n == -1)
       perror("sendto");
     while (!poll_sockets(ctx))
index bbab6db0f9b9a04ce8c67a3aeb69f37c8420e6a2..945b2a885f2240b0b3e980758865328d8c2dd295 100644 (file)
@@ -79,7 +79,7 @@ libsu_la_SOURCES = \
        su_time.c su_time0.c \
        su_wait.c su_root.c su_timer.c \
        su_port.c  su_port.h \
-       su_base_port.c su_pthread_port.c \
+       su_base_port.c su_pthread_port.c su_socket_port.c \
        su_poll_port.c su_epoll_port.c su_select_port.c \
        su_localinfo.c \
        su_os_nw.c \
@@ -94,6 +94,7 @@ EXTRA_libsu_la_SOURCES = \
                        inet_ntop.c inet_pton.c poll.c getopt.c \
                        su_tag_ref.c su_win32_port.c
 
+libsu_la_CFLAGS =      $(AM_CFLAGS) $(SOFIA_CFLAGS)
 libsu_la_LIBADD =      $(REPLACE_LIBADD)
 libsu_la_DEPENDENCIES = $(REPLACE_LIBADD)
 
index 35159ad1b288f7251d4776480b7964488b594922..dbaf935d6e7ad6a0310af62993f7812bec2f2905 100644 (file)
@@ -1,13 +1,20 @@
-/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002
-   Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+/* This file is part of the Sofia-SIP package.
+
+   Copyright (C) 2005 Nokia Corporation.
+
+   Contact: Pekka Pessi <pekka.pessi@nokia.com>
+
+   This file is originally from GNU C library.
 
-   The GNU C Library is free software; you can redistribute it and/or
+   Copyright (C) 1994,1996,1997,1998,1999,2001,2002
+   Free Software Foundation, Inc.
+   
+   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.
 
-   The GNU C Library is distributed in the hope that it will be useful,
+   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.
 
 #include "config.h"
 
-#if !HAVE_POLL && HAVE_SELECT && HAVE_POLL_PORT
+#if HAVE_SELECT
 
 #include "sofia-sip/su.h"
 
-
-//extern __typeof(poll) __libc_poll;
-
-#if 1
-
 #include <alloca.h>
 #include <string.h>
 
 #include "sofia-sip/su_wait.h"
 
-#ifndef __NFDBITS
-#define        NBBY            8                               /* bits in a byte */
-#define __NFDBITS      (sizeof(__int32_t) * NBBY)              /* bits per mask */
-#endif
-
+#undef NBBY
+#undef NFDBITS
+#undef FDSETSIZE
+#undef roundup
 
-#undef howmany
+#define        NBBY  8                                 /* bits in a byte */
+#define NFDBITS        (sizeof(long) * NBBY)           /* bits per mask */
 
-#ifndef howmany
-#define        howmany(x, y)   (((x)+((y)-1))/(y)) * sizeof(uint32_t)
-#endif
+#define FDSETSIZE(n) (((n) + NFDBITS - 1) / NFDBITS * (NFDBITS / NBBY))
+#define roundup(n, x) (((n) + (x) - 1) / (x) * (x))
 
-//libc_hidden_proto(memcpy)
-//libc_hidden_proto(memset)
-//libc_hidden_proto(getdtablesize)
-//libc_hidden_proto(select)
+/* Emulated poll() using select(). 
 
-/* uClinux 2.0 doesn't have poll, emulate it using select */
+This is used by su_wait().
 
-/* Poll the file descriptors described by the NFDS structures starting at
-   FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
-   an event to occur; if TIMEOUT is -1, block until an event occurs.
-   Returns the number of file descriptors with events, zero if timed out,
-   or -1 for errors.  */
+Poll the file descriptors described by the NFDS structures starting at
+FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
+an event to occur; if TIMEOUT is -1, block until an event occurs.
+Returns the number of file descriptors with events, zero if timed out,
+or -1 for errors.  */
 
 int poll(struct pollfd *fds, nfds_t nfds, int timeout)
 {
-    struct timeval tv;
-#if HAVE_ALLOCA_H
-    static int max_fd_size;
-    int bytes;
-    fd_set *rset, *wset, *xset;
-#else
-    fd_set rset[1], wset[1], xset[1];
-#endif
-    struct pollfd *f;
-    int ready;
-    int maxfd = 0;
+  struct timeval tv;
+  struct pollfd *f;
+  int ready;
+  int maxfd = 0;
 
 #if HAVE_ALLOCA_H
-    if (!max_fd_size)
-       max_fd_size = getdtablesize ();
+  static int max_fd_size;
+  int bytes;
+  fd_set *rset, *wset, *xset;
 
-    bytes = howmany (max_fd_size, __NFDBITS);
+  if (!max_fd_size)
+    max_fd_size = getdtablesize ();
 
-    rset = alloca (bytes);
-    wset = alloca (bytes);
-    xset = alloca (bytes);
+  bytes = FDSETSIZE (max_fd_size);
 
-    /* We can't call FD_ZERO, since FD_ZERO only works with sets
-       of exactly __FD_SETSIZE size.  */
-    memset (rset, 0, bytes);
-    memset (wset, 0, bytes);
-    memset (xset, 0, bytes);
+  rset = alloca (bytes);
+  wset = alloca (bytes);
+  xset = alloca (bytes);
+
+  /* We can't call FD_ZERO, since FD_ZERO only works with sets
+     of exactly __FD_SETSIZE size.  */
+  memset (rset, 0, bytes);
+  memset (wset, 0, bytes);
+  memset (xset, 0, bytes);
 #else
-    FD_ZERO(rset);
-    FD_ZERO(wset);
-    FD_ZERO(xset);
-#endif
+  fd_set rset[1], wset[1], xset[1];
 
+  FD_ZERO(rset);
+  FD_ZERO(wset);
+  FD_ZERO(xset);
+#endif
 
-    for (f = fds; f < &fds[nfds]; ++f)
+  for (f = fds; f < &fds[nfds]; ++f)
     {
-       f->revents = 0;
-       if (f->fd >= 0)
+      f->revents = 0;
+      if (f->fd >= 0)
        {
 #if HAVE_ALLOCA_H
-           if (f->fd >= max_fd_size)
+         if (f->fd >= max_fd_size)
            {
-               /* The user provides a file descriptor number which is higher
-                  than the maximum we got from the `getdtablesize' call.
-                  Maybe this is ok so enlarge the arrays.  */
-               fd_set *nrset, *nwset, *nxset;
-               int nbytes;
+             /* The user provides a file descriptor number which is higher
+                than the maximum we got from the `getdtablesize' call.
+                Maybe this is ok so enlarge the arrays.  */
+             fd_set *nrset, *nwset, *nxset;
+             int nbytes;
 
-               max_fd_size = roundup (f->fd, __NFDBITS);
-               nbytes = howmany (max_fd_size, __NFDBITS);
+             max_fd_size = roundup (f->fd, NFDBITS);
+             nbytes = FDSETSIZE (max_fd_size);
 
-               nrset = alloca (nbytes);
-               nwset = alloca (nbytes);
-               nxset = alloca (nbytes);
+             nrset = alloca (nbytes);
+             nwset = alloca (nbytes);
+             nxset = alloca (nbytes);
 
-               memset ((char *) nrset + bytes, 0, nbytes - bytes);
-               memset ((char *) nwset + bytes, 0, nbytes - bytes);
-               memset ((char *) nxset + bytes, 0, nbytes - bytes);
+             memset ((char *) nrset + bytes, 0, nbytes - bytes);
+             memset ((char *) nwset + bytes, 0, nbytes - bytes);
+             memset ((char *) nxset + bytes, 0, nbytes - bytes);
 
-               rset = memcpy (nrset, rset, bytes);
-               wset = memcpy (nwset, wset, bytes);
-               xset = memcpy (nxset, xset, bytes);
+             rset = memcpy (nrset, rset, bytes);
+             wset = memcpy (nwset, wset, bytes);
+             xset = memcpy (nxset, xset, bytes);
 
-               bytes = nbytes;
+             bytes = nbytes;
            }
 #else
-           if (f->fd >= FD_SETSIZE) {
-             errno = EBADF;
-             return -1;
-           }
+         if (f->fd >= FD_SETSIZE) {
+           errno = EBADF;
+           return -1;
+         }
 #endif /* HAVE_ALLOCA_H */
 
-           if (f->events & POLLIN)
-               FD_SET (f->fd, rset);
-           if (f->events & POLLOUT)
-               FD_SET (f->fd, wset);
-           if (f->events & POLLPRI)
-               FD_SET (f->fd, xset);
-           if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
-               maxfd = f->fd;
+         if (f->events & POLLIN)
+           FD_SET (f->fd, rset);
+         if (f->events & POLLOUT)
+           FD_SET (f->fd, wset);
+         if (f->events & POLLPRI)
+           FD_SET (f->fd, xset);
+         if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
+           maxfd = f->fd;
        }
     }
 
-    tv.tv_sec = timeout / 1000;
-    tv.tv_usec = (timeout % 1000) * 1000;
+  tv.tv_sec = timeout / 1000;
+  tv.tv_usec = (timeout % 1000) * 1000;
 
-    while (1)
+  while (1)
     {
-       ready = select (maxfd + 1, rset, wset, xset,
-               timeout == -1 ? NULL : &tv);
+      ready = select (maxfd + 1, rset, wset, xset,
+                     timeout == -1 ? NULL : &tv);
 
-       /* It might be that one or more of the file descriptors is invalid.
-          We now try to find and mark them and then try again.  */
-       if (ready == -1 && errno == EBADF)
+      /* It might be that one or more of the file descriptors is invalid.
+        We now try to find and mark them and then try again.  */
+      if (ready == -1 && errno == EBADF)
        {
-           struct timeval sngl_tv;
+         struct timeval sngl_tv;
 #if HAVE_ALLOCA_H
-           fd_set *sngl_rset = alloca (bytes);
-           fd_set *sngl_wset = alloca (bytes);
-           fd_set *sngl_xset = alloca (bytes);
-
-           /* Clear the original set.  */
-           memset (rset, 0, bytes);
-           memset (wset, 0, bytes);
-           memset (xset, 0, bytes);
+         fd_set *sngl_rset = alloca (bytes);
+         fd_set *sngl_wset = alloca (bytes);
+         fd_set *sngl_xset = alloca (bytes);
+
+         /* Clear the original set.  */
+         memset (rset, 0, bytes);
+         memset (wset, 0, bytes);
+         memset (xset, 0, bytes);
 #else
-           fd_set sngl_rset[1];
-           fd_set sngl_wset[1];
-           fd_set sngl_xset[1];
+         fd_set sngl_rset[1];
+         fd_set sngl_wset[1];
+         fd_set sngl_xset[1];
 
-           FD_ZERO(rset);
-           FD_ZERO(wset);
-           FD_ZERO(xset);
+         FD_ZERO(rset);
+         FD_ZERO(wset);
+         FD_ZERO(xset);
 #endif
 
-           /* This means we don't wait for input.  */
-           sngl_tv.tv_sec = 0;
-           sngl_tv.tv_usec = 0;
+         /* This means we don't wait for input.  */
+         sngl_tv.tv_sec = 0;
+         sngl_tv.tv_usec = 0;
 
-           maxfd = -1;
+         maxfd = -1;
 
-           /* Reset the return value.  */
-           ready = 0;
+         /* Reset the return value.  */
+         ready = 0;
 
-           for (f = fds; f < &fds[nfds]; ++f)
-               if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
-                       && (f->revents & POLLNVAL) == 0)
-               {
-                   int n;
+         for (f = fds; f < &fds[nfds]; ++f)
+           if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
+               && (f->revents & POLLNVAL) == 0)
+             {
+               int n;
 
 #if HAVE_ALLOCA_H
-                   memset (sngl_rset, 0, bytes);
-                   memset (sngl_wset, 0, bytes);
-                   memset (sngl_xset, 0, bytes);
+               memset (sngl_rset, 0, bytes);
+               memset (sngl_wset, 0, bytes);
+               memset (sngl_xset, 0, bytes);
 #else
-                   FD_ZERO(rset);
-                   FD_ZERO(wset);
-                   FD_ZERO(xset);
+               FD_ZERO(rset);
+               FD_ZERO(wset);
+               FD_ZERO(xset);
 #endif
 
+               if (f->events & POLLIN)
+                 FD_SET (f->fd, sngl_rset);
+               if (f->events & POLLOUT)
+                 FD_SET (f->fd, sngl_wset);
+               if (f->events & POLLPRI)
+                 FD_SET (f->fd, sngl_xset);
+
+               n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
+                           &sngl_tv);
+               if (n != -1)
+                 {
+                   /* This descriptor is ok.  */
                    if (f->events & POLLIN)
-                       FD_SET (f->fd, sngl_rset);
+                     FD_SET (f->fd, rset);
                    if (f->events & POLLOUT)
-                       FD_SET (f->fd, sngl_wset);
+                     FD_SET (f->fd, wset);
                    if (f->events & POLLPRI)
-                       FD_SET (f->fd, sngl_xset);
-
-                   n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
-                           &sngl_tv);
-                   if (n != -1)
-                   {
-                       /* This descriptor is ok.  */
-                       if (f->events & POLLIN)
-                           FD_SET (f->fd, rset);
-                       if (f->events & POLLOUT)
-                           FD_SET (f->fd, wset);
-                       if (f->events & POLLPRI)
-                           FD_SET (f->fd, xset);
-                       if (f->fd > maxfd)
-                           maxfd = f->fd;
-                       if (n > 0)
-                           /* Count it as being available.  */
-                           ++ready;
-                   }
-                   else if (errno == EBADF)
-                       f->revents |= POLLNVAL;
-               }
-           /* Try again.  */
-           continue;
+                     FD_SET (f->fd, xset);
+                   if (f->fd > maxfd)
+                     maxfd = f->fd;
+                   if (n > 0)
+                     /* Count it as being available.  */
+                     ++ready;
+                 }
+               else if (errno == EBADF)
+                 f->revents |= POLLNVAL;
+             }
+         /* Try again.  */
+         continue;
        }
 
-       break;
+      break;
     }
 
-    if (ready > 0) 
-       for (f = fds; f < &fds[nfds]; ++f)
-       {
-           if (f->fd >= 0)
-           {
-               if (FD_ISSET (f->fd, rset))
-                   f->revents |= POLLIN;
-               if (FD_ISSET (f->fd, wset))
-                   f->revents |= POLLOUT;
-               if (FD_ISSET (f->fd, xset))
-                   f->revents |= POLLPRI;
-           }
-       }
-
-    return ready;
+  if (ready > 0) 
+    for (f = fds; f < &fds[nfds]; ++f)
+      {
+       if (f->fd >= 0)
+         {
+           if (FD_ISSET (f->fd, rset))
+             f->revents |= POLLIN;
+           if (FD_ISSET (f->fd, wset))
+             f->revents |= POLLOUT;
+           if (FD_ISSET (f->fd, xset))
+             f->revents |= POLLPRI;
+         }
+      }
+
+  return ready;
 }
 
 #endif
-#endif
index a89e626dce21011ee399ba2453896a6764e56f38..d40b64941f3003d799f46b7b7f760e7b4f89325f 100644 (file)
@@ -2,18 +2,33 @@
 
 rc=0
 
+run=no
+
+for SU_PORT in select epoll poll ; do
+
+export SU_PORT
+
+grep -q -i '^#define have_'$SU_PORT ../../config.h ||
+continue
+
+run=yes
+
 if $VALGRIND ./test_su ; then
-    echo PASS: multithread test_su
+    echo PASS: multithread test_su with $SU_PORT
 else
-    echo FAIL: multithread test_su failed
+    echo FAIL: multithread test_su with $SU_PORT failed
     rc=1
 fi
 
 if $VALGRIND ./test_su -s ; then
-    echo PASS: singlethread test_su
+    echo PASS: singlethread test_su with $SU_PORT
 else
-    echo FAIL: singlethread test_su failed
+    echo FAIL: singlethread test_su with $SU_PORT failed
     rc=1
 fi
 
+done
+
+test $run = no && exit 77
+
 exit $rc
index ad2ad69e8808dd1a47d5abcf7aafd58c93d45385..b6b78f39ab761410f8cadf5740dae8bcf959f125 100644 (file)
@@ -512,6 +512,31 @@ SOFIAPUBFUN void su_clone_wait(su_root_t *root, su_clone_r clone);
 SOFIAPUBFUN int su_clone_pause(su_clone_r);
 SOFIAPUBFUN int su_clone_resume(su_clone_r);
 
+/* ---------------------------------------------------------------------- */
+/* Different su_root_t implementations */
+
+typedef su_port_t *su_port_create_f(void);
+typedef int su_clone_start_f(su_root_t *parent,
+                           su_clone_r return_clone,
+                           su_root_magic_t *magic,
+                           su_root_init_f init,
+                           su_root_deinit_f deinit);
+
+SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
+
+SOFIAPUBFUN su_port_create_f su_default_port_create;
+SOFIAPUBFUN su_port_create_f su_epoll_port_create;
+SOFIAPUBFUN su_port_create_f su_poll_port_create;
+SOFIAPUBFUN su_port_create_f su_wsaevent_port_create;
+SOFIAPUBFUN su_port_create_f su_select_port_create;
+
+SOFIAPUBFUN su_clone_start_f su_default_clone_start;
+SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
+SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
+SOFIAPUBFUN su_clone_start_f su_wsaevent_clone_start;
+SOFIAPUBFUN su_clone_start_f su_select_clone_start;
+
+
 SOFIA_END_DECLS
 
 #endif /* SU_WAIT_H */
index a3a128b4e11f9f393b512ea39db94e15aa27614d..35d8477a05cf5fc708d7cecb30764cca74fc1bb4 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>
  *
  */
 
 /**@ingroup su_wait
- * @CFILE su_poll_port.c
+ * @CFILE su_epoll_port.c
  *
- * Port implementation using poll()
+ * Port implementation using epoll(7)
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  * @author Kai Vehmanen <kai.vehmanen@nokia.com>
  *
- * @date Created: Tue Sep 14 15:51:04 1999 ppessi
+ * @date Created: Fri Jan 26 20:44:14 2007 ppessi
+ * @date Original: Tue Sep 14 15:51:04 1999 ppessi
  */
 
 #include "config.h"
 
+#define su_port_s su_epoll_port_s
+
+#include "su_port.h"
+
+#if HAVE_EPOLL
+
+#include "sofia-sip/su.h"
+#include "sofia-sip/su_alloc.h"
+
 #include <stdlib.h>
 #include <assert.h>
 #include <stdarg.h>
 #include <limits.h>
 #include <errno.h>
 
-#define su_port_s su_poll_port_s
-
-#include "sofia-sip/su.h"
-#include "su_port.h"
-#include "sofia-sip/su_alloc.h"
-
-#if HAVE_EPOLL
-
 #include <sys/epoll.h>
 
 #define POLL2EPOLL_NEEDED \
@@ -62,8 +64,8 @@
 
 /** Port based on epoll(). */
 
-struct su_poll_port_s {
-  su_pthread_port_t sup_base[1];
+struct su_epoll_port_s {
+  su_socket_port_t sup_base[1];
 
   /** epoll fd */
   int              sup_epoll;
@@ -88,7 +90,9 @@ struct su_poll_port_s {
   } **sup_indices;
 };
 
-static void su_epoll_port_decref(su_port_t *self, int blocking, char const *who);
+static void su_epoll_port_decref(su_port_t *self,
+                                int blocking,
+                                char const *who);
 static int su_epoll_port_register(su_port_t *self,
                                  su_root_t *root, 
                                  su_wait_t *wait, 
@@ -118,7 +122,7 @@ su_port_vtable_t const su_epoll_port_vtable[1] =
       su_base_port_incref,
       su_epoll_port_decref,
       su_base_port_gsource,
-      su_pthread_port_send,
+      su_socket_port_send,
       su_epoll_port_register,
       su_epoll_port_unregister,
       su_epoll_port_deregister,
@@ -159,7 +163,7 @@ static void su_epoll_port_deinit(void *arg)
 
   SU_DEBUG_9(("%s(%p) called\n", "su_epoll_port_deinit", (void* )self));
 
-  su_pthread_port_deinit(self);
+  su_socket_port_deinit(self->sup_base);
 
   close(self->sup_epoll), self->sup_epoll = -1;
 }
@@ -434,9 +438,9 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
   ev.data.u64 = (uint64_t)0;
   ev.data.u32 = (uint32_t)index;
 
-  if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, ser->ser_wait->fd, &ev) == -1) {
+  if (epoll_ctl(self->sup_epoll, EPOLL_CTL_MOD, socket, &ev) == -1) {
     SU_DEBUG_1(("su_port(%p): EPOLL_CTL_MOD(%u): %s\n", (void *)self, 
-               ser->ser_wait->fd, su_strerror(su_errno())));
+               socket, su_strerror(su_errno())));
     return -1;
   }
 
@@ -449,7 +453,7 @@ int su_epoll_port_eventmask(su_port_t *self, int index, int socket, int events)
  * multishot mode determines how the events are scheduled by port. If
  * multishot mode is enabled, port serves all the sockets that have received
  * network events. If it is disabled, only first socket event is served.
-p *
+ *
  * @param self      pointer to port object
  * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query)
  * 
@@ -547,7 +551,7 @@ su_port_t *su_epoll_port_create(void)
   self->sup_epoll = epoll;
   self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
 
-  if (su_pthread_port_init(self, su_epoll_port_vtable) < 0)
+  if (su_socket_port_init(self->sup_base, su_epoll_port_vtable) < 0)
     return su_home_unref(su_port_home(self)), NULL;
 
   return self;
@@ -562,22 +566,21 @@ int su_epoll_clone_start(su_root_t *parent,
   return su_pthreaded_port_start(su_epoll_port_create, 
                                 parent, return_clone, magic, init, deinit);
 }
+
 #else
 
 su_port_t *su_epoll_port_create(void)
 {
-  return su_poll_port_create();
+  return su_default_port_create();
 }
 
 int su_epoll_clone_start(su_root_t *parent,
-                       su_clone_r return_clone,
-                       su_root_magic_t *magic,
-                       su_root_init_f init,
-                       su_root_deinit_f deinit)
+                        su_clone_r return_clone,
+                        su_root_magic_t *magic,
+                        su_root_init_f init,
+                        su_root_deinit_f deinit)
 {
-  return su_pthreaded_port_start(su_poll_port_create, 
-                                parent, return_clone, magic, init, deinit);
+  return su_default_clone_start(parent, return_clone, magic, init, deinit);
 }
 
 #endif  /* HAVE_EPOLL */
-
index 19bdfc2eb3c78793838f3c04477674f88ffbe7d2..1a65f7bc1245600a2f0bd24c24c93f5f01e91212 100644 (file)
@@ -1199,7 +1199,7 @@ static
 int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
 {
   /* This is Windows XP code, for both IPv6 and IPv4. */
-  size_t iaa_size = 2048;
+  ULONG iaa_size = 2048;
   IP_ADAPTER_ADDRESSES *iaa0, *iaa;
   int error, loopback_seen = 0;
   int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 0;
@@ -1208,7 +1208,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
   int flags = GAA_FLAG_SKIP_MULTICAST;
   *rresult = NULL; next = rresult;
 
-  iaa0 = malloc(iaa_size);
+  iaa0 = malloc((size_t)iaa_size);
   if (!iaa0) {
     SU_DEBUG_1(("su_localinfo: memory exhausted\n"));
     error = ELI_MEMORY;
@@ -1229,7 +1229,7 @@ int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
     IP_ADAPTER_UNICAST_ADDRESS *ua;
     IP_ADAPTER_UNICAST_ADDRESS lua[1];
     int if_index = iaa->IfIndex;
-    int ifnamelen = 0;
+    size_t ifnamelen = 0;
     char ifname[16];
 
     for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {
index 20e578527dd9b3a8d88c0c1e744c860937ce76ac..5cbbfcba713046c369b6f25a6906b432f8c408df 100644 (file)
@@ -31,7 +31,7 @@
  * poll/select/WaitForMultipleObjects and message passing functionality.
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
- * @author Kai Vehmanen <kai.vehmanen@nokia.com>
+ * @author Martti Mela <martti.mela@nokia.com>
  *
  * @date Created: Tue Sep 14 15:51:04 1999 ppessi
  */
@@ -46,9 +46,8 @@
 #include <limits.h>
 #include <errno.h>
 
-#define SU_PORT_IMPLEMENTATION 1
+#define su_port_s su_osx_port_s 
 
-#include "sofia-sip/su.h"
 #include "su_port.h"
 #include "sofia-sip/su_osx_runloop.h"
 #include "sofia-sip/su_alloc.h"
 #define enter (void)0
 #endif
 
-
-#if SU_HAVE_PTHREADS
-/* Pthread implementation */
-#include <pthread.h>
-#define SU_HAVE_MBOX 1
-#else
-#define SU_HAVE_MBOX 0
-#endif
-
-#if HAVE_SOCKETPAIR
-#define MBOX_SEND  1
-#else
-#define MBOX_SEND  0
-#endif
-
 static su_port_t *su_osx_runloop_create(void) __attribute__((__malloc__));
 
 /* Callback for CFObserver and CFSocket */
-static
-void cf_observer_cb(CFRunLoopObserverRef observer
-                   CFRunLoopActivity activity, 
-                   void *info);
-static void su_port_osx_socket_cb(CFSocketRef s, 
+static void cf_observer_cb(CFRunLoopObserverRef observer, 
+                          CFRunLoopActivity activity
+                          void *info);
+
+static void su_osx_port_socket_cb(CFSocketRef s, 
                                  CFSocketCallBackType callbackType, 
                                  CFDataRef address, 
                                  const void *data, 
                                  void *info);
-static CFSocketCallBackType map_poll_event_to_cf_event(int events);
 
-static void su_port_osx_lock(su_port_t *self, char const *who);
-static void su_port_osx_unlock(su_port_t *self, char const *who);
-static void su_port_osx_incref(su_port_t *self, char const *who);
-static void su_port_osx_decref(su_port_t *self, int blocking, char const *who);
+static void su_osx_port_deinit(void *arg);
+
+static void su_osx_port_decref(su_port_t *self, int blocking, char const *who)
+{
+  (void)su_base_port_decref(self, blocking, who);
+}
+
+
+static CFSocketCallBackType map_poll_event_to_cf_event(int events);
 
-static int su_port_osx_send(su_port_t *self, su_msg_r rmsg);
+static int su_osx_port_send(su_port_t *self, su_msg_r rmsg);
 
-static int su_port_osx_register(su_port_t *self,
+static int su_osx_port_register(su_port_t *self,
                            su_root_t *root, 
                            su_wait_t *wait, 
                            su_wakeup_f callback,
                            su_wakeup_arg_t *arg,
                            int priority);
-static int su_port_osx_unregister(su_port_t *port,
+static int su_osx_port_unregister(su_port_t *port,
                              su_root_t *root, 
                              su_wait_t *wait,  
                              su_wakeup_f callback, 
                              su_wakeup_arg_t *arg);
 
-static int su_port_osx_deregister(su_port_t *self, int i);
-
-static int su_port_osx_unregister_all(su_port_t *self,
-                          su_root_t *root);
-
-static int su_port_osx_getmsgs(su_port_t *self);
-static
-int su_port_osx_eventmask(su_port_t *self, int index, int socket, int events);
-static
-void su_port_osx_run(su_port_t *self);
-static
-void su_port_osx_break(su_port_t *self);
-static
-su_duration_t su_port_osx_step(su_port_t *self, su_duration_t tout);
-
-#if 0
-unsigned su_port_query(su_port_t *, su_wait_t *, unsigned n_waits);
-void su_port_event(su_port_t *, su_wait_t *waitobj);
-#endif
-
-static
-int su_port_osx_own_thread(su_port_t const *port);
-
-static
-int su_port_osx_add_prepoll(su_port_t *port,
-                       su_root_t *root, 
-                       su_prepoll_f *, 
-                       su_prepoll_magic_t *);
+static int su_osx_port_deregister(su_port_t *self, int i);
 
-static
-int su_port_osx_remove_prepoll(su_port_t *port,
+static int su_osx_port_unregister_all(su_port_t *self,
                           su_root_t *root);
 
-static
-su_timer_t **su_port_osx_timers(su_port_t *port);
+static int su_osx_port_eventmask(su_port_t *, int , int, int );
+static void su_osx_port_run(su_port_t *self);
+static void su_osx_port_break(su_port_t *self);
+static su_duration_t su_osx_port_step(su_port_t *self, su_duration_t tout);
 
-static
-int su_port_osx_multishot(su_port_t *port, int multishot);
+static int su_osx_port_multishot(su_port_t *port, int multishot);
 
-static
-int su_port_osx_threadsafe(su_port_t *port);
+static int su_osx_port_wait_events(su_port_t *self, su_duration_t tout);
 
-static
-int su_port_osx_yield(su_port_t *port);
+static char const *su_osx_port_name(su_port_t const *self)
+{
+  return "CFRunLoop";
+}
 
-su_port_vtable_t const su_port_osx_vtable[1] =
+su_port_vtable_t const su_osx_port_vtable[1] =
   {{
-      /* su_vtable_size: */ sizeof su_port_osx_vtable,
-      su_port_osx_lock,
-      su_port_osx_unlock,
-      su_port_osx_incref,
-      su_port_osx_decref,
-      NULL /* su_port_osx_runloop */, /* XXX - was: gsource, */
-      su_port_osx_send,
-      su_port_osx_register,
-      su_port_osx_unregister,
-      su_port_osx_deregister,
-      su_port_osx_unregister_all,
-      su_port_osx_eventmask,
-      su_port_osx_run,
-      su_port_osx_break,
-      su_port_osx_step,
-      su_port_osx_own_thread,
-      su_port_osx_add_prepoll,
-      su_port_osx_remove_prepoll,
-      su_port_osx_timers,
-      su_port_osx_multishot,
-      su_port_osx_threadsafe,
-      su_port_osx_yield
+      /* su_vtable_size: */ sizeof su_osx_port_vtable,
+      su_pthread_port_lock,
+      su_pthread_port_unlock,
+      su_base_port_incref,
+      su_osx_port_decref,
+      su_base_port_gsource,
+      su_osx_port_send,
+      su_osx_port_register,
+      su_osx_port_unregister,
+      su_osx_port_deregister,
+      su_osx_port_unregister_all,
+      su_osx_port_eventmask,
+      su_osx_port_run,
+      su_osx_port_break,
+      su_osx_port_step,
+      su_pthread_port_own_thread,
+      su_base_port_add_prepoll,
+      su_base_port_remove_prepoll,
+      su_base_port_timers,
+      su_osx_port_multishot,
+      su_base_port_threadsafe,
+      su_base_port_yield,
+      su_osx_port_wait_events,
+      su_base_port_getmsgs,
+      su_base_port_getmsgs_from,
+      su_osx_port_name,
+      su_base_port_start_shared,
+      su_pthread_port_wait,
+      su_pthread_port_execute,
     }};
 
-static int su_port_osx_wait_events(su_port_t *self, su_duration_t tout);
-
-
-/* *
+/*
  * Port is a per-thread reactor.  
  *
  * Multiple root objects executed by single thread share a su_port_t object. 
  */
-struct su_port_s {
-  su_home_t        sup_home[1];
-
-  su_port_vtable_t const *sup_vtable;
-  
-  unsigned         sup_running;
-  unsigned         sup_source_fired;
+struct su_osx_port_s {
+  su_socket_port_t sup_socket[1];
 
+#define sup_pthread sup_socket->sup_base
+#define sup_base sup_socket->sup_base->sup_base
+#define sup_home sup_socket->sup_base->sup_base->sup_home
 
-#if SU_HAVE_PTHREADS
-  pthread_t        sup_tid;
-  pthread_mutex_t  sup_mutex[1];
-#if __CYGWIN__
-  pthread_mutex_t  sup_reflock[1];
-  int              sup_ref;
-#else
-  pthread_rwlock_t sup_ref[1];
-#endif
-#else
-  int              sup_ref;
-#endif
-
-#if SU_HAVE_MBOX
-  su_socket_t      sup_mbox[MBOX_SEND + 1];
-  su_wait_t        sup_mbox_wait;
-#endif
+  unsigned         sup_source_fired;
 
   CFRunLoopRef        sup_main_loop;
   CFRunLoopSourceRef *sup_sources;
   CFSocketRef        *sup_sockets;
+
+  CFRunLoopObserverRef sup_observer;
+  CFRunLoopObserverContext sup_observer_cntx[1];
+  /* Struct for CFSocket callbacks; contains current CFSource index */
+  struct osx_magic {
+    su_port_t *o_port;
+    int        o_current;
+    int        o_count;
+  } osx_magic[1];
   
   unsigned         sup_multishot; /**< Multishot operation? */
 
@@ -248,147 +205,10 @@ struct su_port_s {
   su_root_t      **sup_wait_roots; 
 
   su_wait_t       *sup_waits; 
-
-  /* Pre-poll callback */
-  su_prepoll_f    *sup_prepoll; 
-  su_prepoll_magic_t *sup_pp_magic;
-  su_root_t       *sup_pp_root;
-
-  /* Timer list */
-  su_timer_t      *sup_timers;
-
-  /* Message list - this is protected by lock  */
-  su_msg_t        *sup_head;
-  su_msg_t       **sup_tail;
-
-#if 0
-  int              sup_free_index;   /**< Number of first free index */
-  int             *sup_indices; /** Indices to registrations */
-
-  int             *sup_reverses; /** Reverse index */
-  su_wakeup_f     *sup_wait_cbs; 
-  su_wakeup_arg_t**sup_wait_args; 
-  su_root_t      **sup_wait_roots; 
-
-  su_wait_t       *sup_waits; 
-
-  /* Pre-poll callback */
-  su_prepoll_f    *sup_prepoll; 
-  su_prepoll_magic_t *sup_pp_magic;
-  su_root_t       *sup_pp_root;
-
-  /* Timer list */
-  su_timer_t      *sup_timers;
-
-  /* Message list - this is protected by lock  */
-  su_msg_t        *sup_head;
-  su_msg_t       **sup_tail;
-#endif
 };
 
 
-/* Struct for CFSocket callbacks; contains current CFSource index */
-typedef struct {
-  su_port_t *o_port;
-  int        o_current;
-  int        o_count;
-} osx_magic_t;
-
-
-#if SU_HAVE_PTHREADS
-#define SU_PORT_OSX_OWN_THREAD(p)   (pthread_equal((p)->sup_tid, pthread_self()))
-
-#if __CYGWIN__
-
-/* Debugging versions */
-#define SU_PORT_OSX_INITREF(p)      (pthread_mutex_init((p)->sup_reflock, NULL), printf("initref(%p)\n", (p)))
-#define SU_PORT_OSX_INCREF(p, f)    (pthread_mutex_lock(p->sup_reflock), p->sup_ref++, pthread_mutex_unlock(p->sup_reflock), printf("incref(%p) by %s\n", (p), f))
-#define SU_PORT_OSX_DECREF(p, f)    do {                                       \
-    pthread_mutex_lock(p->sup_reflock);        p->sup_ref--; pthread_mutex_unlock(p->sup_reflock); \
-    if ((p->sup_ref) == 0) {                   \
-      printf("decref(%p) to 0 by %s\n", (p), f); su_port_osx_destroy(p); }     \
-    else { printf("decref(%p) to %u by %s\n", (p), p->sup_ref, f); }  } while(0)
-
-#define SU_PORT_OSX_ZAPREF(p, f)    do { printf("zapref(%p) by %s\n", (p), f), \
-    pthread_mutex_lock(p->sup_reflock);        p->sup_ref--; pthread_mutex_unlock(p->sup_reflock); \
-  if ((p->sup_ref) != 0) { \
-    assert(!"SU_PORT_OSX_ZAPREF"); } \
-  su_port_osx_destroy(p); } while(0)
-
-#define SU_PORT_OSX_INITLOCK(p) \
-   (pthread_mutex_init((p)->sup_mutex, NULL), printf("init_lock(%p)\n", p))
-
-#define SU_PORT_OSX_LOCK(p, f)    \
-   (printf("%ld at %s locking(%p)...", pthread_self(), f, p), pthread_mutex_lock((p)->sup_mutex), printf(" ...%ld at %s locked(%p)...", pthread_self(), f, p))
-
-#define SU_PORT_OSX_UNLOCK(p, f)  \
-  (pthread_mutex_unlock((p)->sup_mutex), printf(" ...%ld at %s unlocked(%p)\n", pthread_self(), f, p))
-
-#elif 1
-#define SU_PORT_OSX_INITREF(p)      (pthread_rwlock_init(p->sup_ref, NULL))
-#define SU_PORT_OSX_INCREF(p, f)    (pthread_rwlock_rdlock(p->sup_ref))
-#define SU_PORT_OSX_DECREF(p, f)    do { pthread_rwlock_unlock(p->sup_ref); \
-  if (pthread_rwlock_trywrlock(p->sup_ref) == 0) su_port_osx_destroy(p); } while(0)
-
-#define SU_PORT_OSX_ZAPREF(p, f)    do { pthread_rwlock_unlock(p->sup_ref); \
-  if (pthread_rwlock_trywrlock(p->sup_ref) != 0) { \
-    assert(!"SU_PORT_OSX_ZAPREF"); pthread_rwlock_wrlock(p->sup_ref); } \
-  su_port_osx_destroy(p); } while(0)
-
-#define SU_PORT_OSX_INITLOCK(p)     (pthread_mutex_init((p)->sup_mutex, NULL))
-#define SU_PORT_OSX_LOCK(p, f)      (pthread_mutex_lock((p)->sup_mutex))
-#define SU_PORT_OSX_UNLOCK(p, f)    (pthread_mutex_unlock((p)->sup_mutex))
-
-#else
-
-/* Debugging versions */
-#define SU_PORT_OSX_INITREF(p)      (pthread_rwlock_init((p)->sup_ref, NULL), printf("initref(%p)\n", (p)))
-#define SU_PORT_OSX_INCREF(p, f)    (pthread_rwlock_rdlock(p->sup_ref), printf("incref(%p) by %s\n", (p), f))
-#define SU_PORT_OSX_DECREF(p, f)    do {                                       \
-    pthread_rwlock_unlock(p->sup_ref);                                 \
-    if (pthread_rwlock_trywrlock(p->sup_ref) == 0) {                   \
-      printf("decref(%p) to 0 by %s\n", (p), f); su_port_osx_destroy(p); }     \
-    else { printf("decref(%p) by %s\n", (p), f); }  } while(0)
-
-#define SU_PORT_OSX_ZAPREF(p, f)    do { printf("zapref(%p) by %s\n", (p), f), \
-  pthread_rwlock_unlock(p->sup_ref); \
-  if (pthread_rwlock_trywrlock(p->sup_ref) != 0) { \
-    assert(!"SU_PORT_OSX_ZAPREF"); pthread_rwlock_wrlock(p->sup_ref); } \
-  su_port_osx_destroy(p); } while(0)
-
-#define SU_PORT_OSX_INITLOCK(p) \
-   (pthread_mutex_init((p)->sup_mutex, NULL), printf("init_lock(%p)\n", p))
-
-#define SU_PORT_OSX_LOCK(p, f)    \
-   (printf("%ld at %s locking(%p)...", pthread_self(), f, p), pthread_mutex_lock((p)->sup_mutex), printf(" ...%ld at %s locked(%p)...", pthread_self(), f, p))
-
-#define SU_PORT_OSX_UNLOCK(p, f)  \
-  (pthread_mutex_unlock((p)->sup_mutex), printf(" ...%ld at %s unlocked(%p)\n", pthread_self(), f, p))
-
-#endif
-
-#else /* !SU_HAVE_PTHREADS */
-
-#define SU_PORT_OSX_OWN_THREAD(p)  1
-#define SU_PORT_OSX_INITLOCK(p)    (void)(p)
-#define SU_PORT_OSX_LOCK(p, f)      (void)(p)
-#define SU_PORT_OSX_UNLOCK(p, f)    (void)(p)
-#define SU_PORT_OSX_ZAPREF(p, f)    ((p)->sup_ref--)
-
-#define SU_PORT_OSX_INITREF(p)      ((p)->sup_ref = 1)
-#define SU_PORT_OSX_INCREF(p, f)    ((p)->sup_ref++)
-#define SU_PORT_OSX_DECREF(p, f) \
-do { if (--((p)->sup_ref) == 0) su_port_osx_destroy(p); } while (0);
-
-#endif
-
-#if SU_HAVE_MBOX
-static int su_port_osx_wakeup(su_root_magic_t *magic, 
-                         su_wait_t *w,
-                         su_wakeup_arg_t *arg);
-#endif
-
-static void su_port_osx_destroy(su_port_t *self);
+/* XXX - mela static void su_osx_port_destroy(su_port_t *self); */
 
 /** Create a reactor object.
  *
@@ -405,7 +225,6 @@ su_root_t *su_root_osx_runloop_create(su_root_magic_t *magic)
   return su_root_create_with_port(magic, su_osx_runloop_create());
 }
 
-
 void osx_enabler_cb(CFSocketRef s, 
                    CFSocketCallBackType type, 
                    CFDataRef address, 
@@ -413,35 +232,32 @@ void osx_enabler_cb(CFSocketRef s,
                    void *info)
 {
   CFRunLoopRef  rl;
-  osx_magic_t  *magic = (osx_magic_t *) info;
+  struct osx_magic  *magic = (struct osx_magic *) info;
   su_port_t    *self = magic->o_port;
   su_duration_t tout = 0;
   su_time_t     now = su_now();
   
   rl = CFRunLoopGetCurrent();
 
-  if (self->sup_running) {
+  if (self->sup_base->sup_running) {
     
-    if (self->sup_prepoll)
-      self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+    if (self->sup_base->sup_prepoll)
+      self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
     
-    if (self->sup_head)
-      su_port_osx_getmsgs(self);
+    if (self->sup_base->sup_head)
+      su_base_port_getmsgs(self);
     
-    if (self->sup_timers)
-      su_timer_expire(&self->sup_timers, &tout, now);
+    if (self->sup_base->sup_timers)
+      su_timer_expire(&self->sup_base->sup_timers, &tout, now);
   }
   
   CFRunLoopWakeUp(rl);
-  
 }
 
 
 /**@internal
  *
- * Allocates and initializes a message port. It creates a mailbox used to.
- * wake up the tasks waiting on the port if needed.  Currently, the
- * mailbox is simply an UDP socket connected to itself.
+ * Allocates and initializes a message port.
  *
  * @return
  *   If successful a pointer to the new message port is returned, otherwise
@@ -449,142 +265,59 @@ void osx_enabler_cb(CFSocketRef s,
  */
 su_port_t *su_osx_runloop_create(void)
 {
-  su_port_t *self;
-
-  SU_DEBUG_9(("su_osx_runloop_create() called\n"));
-
-  self = su_home_clone(NULL, sizeof(*self));
-
-  if (self) {
-#if SU_HAVE_MBOX
-    int af;
-    su_socket_t mb = INVALID_SOCKET;
-    char const *why;
-#endif
-    CFRunLoopObserverRef cf_observer; 
-    osx_magic_t *osx_magic = NULL;
-    CFRunLoopObserverContext cf_observer_cntx[1] = {{0, NULL, NULL,
-                                                    NULL, NULL}};
-
-    self->sup_vtable = su_port_osx_vtable;
-    
-    SU_PORT_OSX_INITREF(self);
-    SU_PORT_OSX_INITLOCK(self);
-    self->sup_tail = &self->sup_head;
-
-    self->sup_multishot = 0; /* XXX (SU_ENABLE_MULTISHOT_POLL) != 0; */
-
-#if SU_HAVE_PTHREADS
-    self->sup_tid = pthread_self();
-#endif
-  
-#if SU_HAVE_MBOX
-#if HAVE_SOCKETPAIR
-#if defined(AF_LOCAL)
-    af = AF_LOCAL;
-#else
-    af = AF_UNIX;
-#endif
-    if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) {
-      why = "su_port_osx_init: socketpair"; goto error;
-    }
-
-    mb = self->sup_mbox[0];
-    su_setblocking(self->sup_mbox[0], 0);
-    su_setblocking(self->sup_mbox[1], 0);
-#else
-    {
-      struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 };
-      socklen_t sinsize = sizeof sin;
-      struct sockaddr *sa = (struct sockaddr *)&sin;
+  su_port_t *self = su_home_new(sizeof *self);
 
-      af = PF_INET;
-
-      self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP);
-      if (mb == INVALID_SOCKET) {
-       why = "su_port_osx_init: socket"; goto error;
-      }
-  
-      sin.sin_family = AF_INET;
-      sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */
-      
-      /* Get a port for us */
-      if (bind(mb, sa, sizeof sin) == -1) {
-       why = "su_port_osx_init: bind"; goto error;
-      }
+  if (!self)
+    return self;
 
-      if (getsockname(mb, sa, &sinsize) == -1) {
-       why = "su_port_osx_init: getsockname"; goto error;
-      }
-    
-      if (connect(mb, sa, sinsize) == -1) {
-       why = "su_port_osx_init: connect"; goto error;
-      }
-    }
-#endif    
+  enter;
 
-    if (su_wait_create(&self->sup_mbox_wait, mb, SU_WAIT_IN) == -1) {
-      why = "su_port_osx_init: su_wait_create"; goto error;
-    }
+  if (su_home_destructor(su_port_home(self), su_osx_port_deinit) < 0)
+    return su_home_unref(su_port_home(self)), NULL;
 
-    if (su_port_osx_register(self, NULL, &self->sup_mbox_wait,
-                            su_port_osx_wakeup, 
-                            (su_wakeup_arg_t *)self->sup_mbox, 0)
-       == -1) {
-      why = "su_port_osx_create: su_port_osx_register"; goto error;
-    }
+  self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
 
-    osx_magic = calloc(1, sizeof(*osx_magic));
-    osx_magic->o_port = self;
-    cf_observer_cntx->info = osx_magic;
-    
-    cf_observer =
-      CFRunLoopObserverCreate(NULL, kCFRunLoopAfterWaiting | kCFRunLoopBeforeWaiting,
-                             TRUE, 0, cf_observer_cb, cf_observer_cntx);
+  if (su_socket_port_init(self->sup_base, su_osx_port_vtable) == 0) {
+    self->osx_magic->o_port = self;
+    self->sup_observer_cntx->info = self->osx_magic;
+    self->sup_observer =
+      CFRunLoopObserverCreate(NULL, 
+                             kCFRunLoopAfterWaiting | kCFRunLoopBeforeWaiting,
+                             TRUE, 0, cf_observer_cb, self->sup_observer_cntx);
     
     CFRunLoopAddObserver(CFRunLoopGetCurrent(),
-                        cf_observer,
+                        self->sup_observer,
                         kCFRunLoopDefaultMode);
-    
-    SU_DEBUG_9(("su_port_osx_create() returns %p\n", self));
-    
-    return self;
-    
-  error:
-    su_perror(why);
-    su_port_osx_destroy(self), self = NULL;
-#endif
   }
-  
-  SU_DEBUG_9(("su_port_osx_create() returns %p\n", self));
-  
+  else
+    return su_home_unref(su_port_home(self)), NULL;
+
   return self;
 }
 
-
 static
 void cf_observer_cb(CFRunLoopObserverRef observer, 
                    CFRunLoopActivity activity, 
                    void *info)
 {
   CFRunLoopRef  rl;
-  osx_magic_t  *magic = (osx_magic_t *) info;
+  struct osx_magic  *magic = (struct osx_magic *) info;
   su_port_t    *self = magic->o_port;
   su_duration_t tout = 0;
   su_time_t     now = su_now();
 
   rl = CFRunLoopGetCurrent();
 
-  if (self->sup_running) {
+  if (self->sup_base->sup_running) {
 
-    if (self->sup_prepoll)
-      self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+    if (self->sup_base->sup_prepoll)
+      self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
     
-    if (self->sup_head)
-      su_port_osx_getmsgs(self);
+    if (self->sup_base->sup_head)
+      su_port_getmsgs(self);
     
-    if (self->sup_timers)
-      su_timer_expire(&self->sup_timers, &tout, now);
+    if (self->sup_base->sup_timers)
+      su_timer_expire(&self->sup_base->sup_timers, &tout, now);
   } else
     SU_DEBUG_9(("cf_observer_cb(): PORT IS NOT RUNNING!\n"));
 
@@ -594,70 +327,13 @@ void cf_observer_cb(CFRunLoopObserverRef observer,
 }
 
 /** @internal Destroy a port. */
-void su_port_osx_destroy(su_port_t *self)
-{
-  assert(self);
-
-  SU_DEBUG_9(("su_port_osx_destroy() called\n"));
-
-#if SU_HAVE_MBOX
-  if (self->sup_mbox[0] != INVALID_SOCKET) {
-    su_port_osx_unregister(self, NULL, &self->sup_mbox_wait, NULL, 
-                      (su_wakeup_arg_t *)self->sup_mbox);
-    su_wait_destroy(&self->sup_mbox_wait);
-    su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET;
-#if HAVE_SOCKETPAIR
-    su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET;
-#endif
-    SU_DEBUG_9(("su_port_osx_destroy() close mailbox\n"));
-  }
-#endif
-  if (self->sup_sources) 
-    free(self->sup_sources), self->sup_sources = NULL;
-  if (self->sup_sockets) 
-    free(self->sup_sockets), self->sup_sockets = NULL;
-  if (self->sup_waits) 
-    free(self->sup_waits), self->sup_waits = NULL;
-  if (self->sup_wait_cbs)
-    free(self->sup_wait_cbs), self->sup_wait_cbs = NULL;
-  if (self->sup_wait_args)
-    free(self->sup_wait_args), self->sup_wait_args = NULL;
-  if (self->sup_wait_roots)
-    free(self->sup_wait_roots), self->sup_wait_roots = NULL;
-  if (self->sup_reverses)
-    free(self->sup_reverses), self->sup_reverses = NULL;
-  if (self->sup_indices)
-    free(self->sup_indices), self->sup_indices = NULL;
-
-  SU_DEBUG_9(("su_port_osx_destroy() freed registrations\n"));
-
-  su_home_zap(self->sup_home);
-
-  SU_DEBUG_9(("su_port_osx_destroy() returns\n"));
-
-}
-
-static void su_port_osx_lock(su_port_t *self, char const *who)
-{
-  SU_PORT_OSX_LOCK(self, who);
-}
-
-static void su_port_osx_unlock(su_port_t *self, char const *who)
+static void su_osx_port_deinit(void *arg)
 {
-  SU_PORT_OSX_UNLOCK(self, who);
-}
+  su_port_t *self = arg;
 
-static void su_port_osx_incref(su_port_t *self, char const *who)
-{
-  SU_PORT_OSX_INCREF(self, who);
-}
+  SU_DEBUG_9(("%s(%p) called\n", "su_osx_port_deinit", (void *)self));
 
-static void su_port_osx_decref(su_port_t *self, int blocking, char const *who)
-{
-  if (blocking)
-    SU_PORT_OSX_ZAPREF(self, who);
-  else
-    SU_PORT_OSX_DECREF(self, who);
+  su_socket_port_deinit(self->sup_base);
 }
 
 static
@@ -683,6 +359,7 @@ CFSocketCallBackType map_poll_event_to_cf_event(int events)
 }
 
 
+#if 0
 static
 int map_cf_event_to_poll_event(CFSocketCallBackType type)
 {
@@ -702,18 +379,18 @@ int map_cf_event_to_poll_event(CFSocketCallBackType type)
 
   return event;
 }
-
+#endif
 
 static
-void su_port_osx_socket_cb(CFSocketRef s, 
+void su_osx_port_socket_cb(CFSocketRef s, 
                           CFSocketCallBackType type, 
                           CFDataRef address, 
                           const void *data, 
                           void *info)
 {
-  osx_magic_t       *magic = (osx_magic_t *) info;
-  su_port_t         *self = magic->o_port;
-  int                curr = magic->o_current;
+  struct osx_magic *magic = (struct osx_magic *) info;
+  su_port_t        *self = magic->o_port;
+  int               curr = magic->o_current;
   su_duration_t tout = 0;
   
 #if SU_HAVE_POLL
@@ -733,13 +410,13 @@ void su_port_osx_socket_cb(CFSocketRef s,
                          &waits[n], 
                          self->sup_wait_args[n]);
     
-    if (self->sup_running) {
-      su_port_osx_getmsgs(self);
+    if (self->sup_base->sup_running) {
+      su_port_getmsgs(self);
       
-      if (self->sup_timers)
-       su_timer_expire(&self->sup_timers, &tout, su_now());
+      if (self->sup_base->sup_timers)
+       su_timer_expire(&self->sup_base->sup_timers, &tout, su_now());
 
-      if (self->sup_head)
+      if (self->sup_base->sup_head)
        tout = 0;
 
       /* CFRunLoopWakeUp(CFRunLoopGetCurrent()); */
@@ -752,37 +429,20 @@ void su_port_osx_socket_cb(CFSocketRef s,
   
 }
 
-#if SU_HAVE_MBOX
-/** @internal Message box wakeup function. */
-static int su_port_osx_wakeup(su_root_magic_t *magic, /* NULL */
-                             su_wait_t *w,
-                             su_wakeup_arg_t *arg)
-{
-  char buf[32];
-  su_socket_t s = *(su_socket_t *)arg;
-  su_wait_events(w, s);
-  recv(s, buf, sizeof(buf), 0);
-
-  /* CFRunLoopWakeUp(CFRunLoopGetCurrent()); */
-
-  return 0;
-}
-#endif
-
 /** @internal Send a message to the port. */
-int su_port_osx_send(su_port_t *self, su_msg_r rmsg)
+int su_osx_port_send(su_port_t *self, su_msg_r rmsg)
 {
   CFRunLoopRef rl;
 
   if (self) {
     int wakeup;
 
-    SU_PORT_OSX_LOCK(self, "su_port_osx_send");
+    //XXX - mela SU_OSX_PORT_LOCK(self, "su_osx_port_send");
     
-    wakeup = self->sup_head == NULL;
+    wakeup = self->sup_base->sup_head == NULL;
 
-    *self->sup_tail = rmsg[0]; rmsg[0] = NULL;
-    self->sup_tail = &(*self->sup_tail)->sum_next;
+    *self->sup_base->sup_tail = rmsg[0]; rmsg[0] = NULL;
+    self->sup_base->sup_tail = &(*self->sup_base->sup_tail)->sum_next;
 
 #if SU_HAVE_MBOX
     /* if (!pthread_equal(pthread_self(), self->sup_tid)) */
@@ -799,7 +459,7 @@ int su_port_osx_send(su_port_t *self, su_msg_r rmsg)
     }
 #endif
 
-    SU_PORT_OSX_UNLOCK(self, "su_port_osx_send");
+    //XXX - mela SU_OSX_PORT_UNLOCK(self, "su_osx_port_send");
 
     rl = CFRunLoopGetCurrent();
     CFRunLoopWakeUp(rl);
@@ -811,48 +471,6 @@ int su_port_osx_send(su_port_t *self, su_msg_r rmsg)
     return -1;
   }
 }
-
-/** @internal
- * Execute the messages in the incoming queue until the queue is empty..
- *
- * @param self - pointer to a port object
- *
- * @retval Number of messages sent
- */
-int su_port_osx_getmsgs(su_port_t *self)
-{
-  int n = 0;
-
-  if (self->sup_head) {
-    su_msg_f f;
-    su_msg_t *msg, *queue;
-
-    SU_PORT_OSX_LOCK(self, "su_port_getmsgs");
-
-    queue = self->sup_head;
-    self->sup_tail = &self->sup_head;
-    self->sup_head = NULL;
-
-    SU_PORT_OSX_UNLOCK(self, "su_port_osx_getmsgs");
-
-    for (msg = queue; msg; msg = queue) {
-      queue = msg->sum_next;
-      msg->sum_next = NULL;
-
-      f = msg->sum_func;
-      if (f) 
-       f(SU_ROOT_MAGIC(msg->sum_to->sut_root), &msg, msg->sum_data);
-      su_msg_delivery_report(&msg);
-      n++;
-    }
-
-    /* Check for wait events that may have been generated by messages */
-    su_port_osx_wait_events(self, 0);
-  }
-
-  return n;
-}
-
 static int o_count;
 
 /** @internal
@@ -873,9 +491,9 @@ static int o_count;
  *              (0 is normal, 1 important, 2 realtime)
  * 
  * @return
- *   The function @su_port_osx_register returns nonzero index of the wait object, 
+ *   The function @su_osx_port_register returns nonzero index of the wait object, 
  *   or -1 upon an error.  */
-int su_port_osx_register(su_port_t *self,
+int su_osx_port_register(su_port_t *self,
                         su_root_t *root, 
                         su_wait_t *wait, 
                         su_wakeup_f callback,
@@ -887,11 +505,11 @@ int su_port_osx_register(su_port_t *self,
   CFRunLoopSourceRef *sources, source;
   CFSocketRef cf_socket, *sockets;
   int events = 0;
-  osx_magic_t *osx_magic = NULL;
+  struct osx_magic *osx_magic = NULL;
   CFSocketContext cf_socket_cntx[1] = {{0, NULL, NULL, NULL, NULL}};
   CFOptionFlags flags = 0;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   n = self->sup_n_waits;
 
@@ -1015,7 +633,7 @@ int su_port_osx_register(su_port_t *self,
 
   cf_socket = CFSocketCreateWithNative(NULL,
                                       (CFSocketNativeHandle) su_wait_socket(wait),
-                                      events, su_port_osx_socket_cb, cf_socket_cntx);
+                                      events, su_osx_port_socket_cb, cf_socket_cntx);
 
   flags = CFSocketGetSocketFlags(cf_socket);
   flags &= ~kCFSocketCloseOnInvalidate;
@@ -1044,7 +662,7 @@ int su_port_osx_register(su_port_t *self,
 
 /** Deregister a su_wait_t object. */
 static
-int su_port_osx_deregister0(su_port_t *self, int i)
+int su_osx_port_deregister0(su_port_t *self, int i)
 {
   CFRunLoopRef rl;
   int n, N, *indices, *reverses;
@@ -1118,7 +736,7 @@ int su_port_osx_deregister0(su_port_t *self, int i)
 
 /** Unregister a su_wait_t object.
  *  
- *  The function su_port_osx_unregister() unregisters a su_wait_t object. The
+ *  The function su_osx_port_unregister() unregisters a su_wait_t object. The
  *  wait object, a callback function and a argument are removed from the
  *  port object.
  * 
@@ -1131,7 +749,7 @@ int su_port_osx_deregister0(su_port_t *self, int i)
  * 
  * @return Nonzero index of the wait object, or -1 upon an error.
  */
-int su_port_osx_unregister(su_port_t *self,
+int su_osx_port_unregister(su_port_t *self,
                       su_root_t *root, 
                       su_wait_t *wait, 
                       su_wakeup_f callback, /* XXX - ignored */
@@ -1140,13 +758,13 @@ int su_port_osx_unregister(su_port_t *self,
   int n, N;
 
   assert(self);
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   N = self->sup_n_waits;
 
   for (n = 0; n < N; n++) {
     if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
-      return su_port_osx_deregister0(self, self->sup_reverses[n]);
+      return su_osx_port_deregister0(self, self->sup_reverses[n]);
     }
   }
 
@@ -1157,7 +775,7 @@ int su_port_osx_unregister(su_port_t *self,
 
 /** Deregister a su_wait_t object.
  *  
- *  The function su_port_osx_deregister() deregisters a su_wait_t registrattion. 
+ *  The function su_osx_port_deregister() deregisters a su_wait_t registrattion. 
  *  The wait object, a callback function and a argument are removed from the
  *  port object.
  * 
@@ -1166,13 +784,13 @@ int su_port_osx_unregister(su_port_t *self,
  * 
  * @return Index of the wait object, or -1 upon an error.
  */
-int su_port_osx_deregister(su_port_t *self, int i)
+int su_osx_port_deregister(su_port_t *self, int i)
 {
   su_wait_t wait[1] = { SU_WAIT_INIT };
   int retval;
 
   assert(self);
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   if (i <= 0 || i > self->sup_size_waits)
     return su_seterrno(EBADF);
@@ -1180,7 +798,7 @@ int su_port_osx_deregister(su_port_t *self, int i)
   if (self->sup_indices[i] < 0)
     return su_seterrno(EBADF);
     
-  retval = su_port_osx_deregister0(self, i);
+  retval = su_osx_port_deregister0(self, i);
 
   su_wait_destroy(wait);
 
@@ -1191,7 +809,7 @@ int su_port_osx_deregister(su_port_t *self, int i)
 /** @internal
  * Unregister all su_wait_t objects.
  *
- * The function su_port_osx_unregister_all() unregisters all su_wait_t objects
+ * The function su_osx_port_unregister_all() unregisters all su_wait_t objects
  * and destroys all queued timers associated with given root object.
  * 
  * @param  self     - pointer to port object
@@ -1199,7 +817,7 @@ int su_port_osx_deregister(su_port_t *self, int i)
  * 
  * @return Number of wait objects removed.
  */
-int su_port_osx_unregister_all(su_port_t *self, 
+int su_osx_port_unregister_all(su_port_t *self, 
                           su_root_t *root)
 {
   int i, j, index, N;
@@ -1212,7 +830,7 @@ int su_port_osx_unregister_all(su_port_t *self,
   CFRunLoopSourceRef *sources;
   CFSocketRef        *sockets;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - assert(SU_OSX_PORT_OWN_THREAD(self));
 
   N          = self->sup_n_waits;
   indices    = self->sup_indices;
@@ -1286,7 +904,7 @@ int su_port_osx_unregister_all(su_port_t *self,
 
 /**Set mask for a registered event. @internal
  *
- * The function su_port_osx_eventmask() sets the mask describing events that can
+ * The function su_osx_port_eventmask() sets the mask describing events that can
  * signal the registered callback.
  *
  * @param port   pointer to port object
@@ -1297,12 +915,12 @@ int su_port_osx_unregister_all(su_port_t *self,
  * @retval 0 when successful,
  * @retval -1 upon an error.
  */
-int su_port_osx_eventmask(su_port_t *self, int index, int socket, int events)
+int su_osx_port_eventmask(su_port_t *self, int index, int socket, int events)
 {
   int n, ret;
 
   assert(self);
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   if (index <= 0 || index > self->sup_size_waits)
     return su_seterrno(EBADF);
@@ -1321,7 +939,7 @@ int su_port_osx_eventmask(su_port_t *self, int index, int socket, int events)
 /** @internal
  *
  *  Copies the su_wait_t objects from the port. The number of wait objects
- *  can be found out by calling su_port_osx_query() with @a n_waits as zero.
+ *  can be found out by calling su_osx_port_query() with @a n_waits as zero.
  * 
  * @note This function is called only by friends.
  *
@@ -1331,11 +949,11 @@ int su_port_osx_eventmask(su_port_t *self, int index, int socket, int events)
  *
  * @return Number of wait objects, or 0 upon an error.
  */
-unsigned su_port_osx_query(su_port_t *self, su_wait_t *waits, unsigned n_waits)
+unsigned su_osx_port_query(su_port_t *self, su_wait_t *waits, unsigned n_waits)
 {
   unsigned n;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   n = self->sup_n_waits;
 
@@ -1351,7 +969,7 @@ unsigned su_port_osx_query(su_port_t *self, su_wait_t *waits, unsigned n_waits)
 
 /** @internal Enable multishot mode.
  *
- * The function su_port_osx_multishot() enables, disables or queries the
+ * The function su_osx_port_multishot() enables, disables or queries the
  * multishot mode for the port. The multishot mode determines how the events
  * are scheduled by port. If multishot mode is enabled, port serves all the
  * sockets that have received network events. If it is disables, only first
@@ -1364,7 +982,7 @@ unsigned su_port_osx_query(su_port_t *self, su_wait_t *waits, unsigned n_waits)
  * @retval 1 multishot mode is enabled
  * @retval -1 an error occurred
  */
-int su_port_osx_multishot(su_port_t *self, int multishot)
+int su_osx_port_multishot(su_port_t *self, int multishot)
 {
   if (multishot < 0)
     return self->sup_multishot;
@@ -1374,12 +992,14 @@ int su_port_osx_multishot(su_port_t *self, int multishot)
     return (errno = EINVAL), -1;
 }
 
+#if 0
 /** @internal Enable threadsafe operation. */
 static
-int su_port_osx_threadsafe(su_port_t *port)
+int su_osx_port_threadsafe(su_port_t *port)
 {
   return su_home_threadsafe(port->sup_home);
 }
+#endif
 
 /** Prepare root to be run on OSX Run Loop.
  *
@@ -1399,23 +1019,23 @@ void su_root_osx_prepare_run(su_root_t *root)
   CFRunLoopRef rl;
   su_duration_t tout = 0;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   enter;
 
-  self->sup_running = 1;
+  self->sup_base->sup_running = 1;
   rl = CFRunLoopGetCurrent();
 
-  if (self->sup_prepoll)
-    self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+  if (self->sup_base->sup_prepoll)
+    self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
 
-  if (self->sup_head)
-    su_port_osx_getmsgs(self);
+  if (self->sup_base->sup_head)
+    su_port_getmsgs(self);
   
-  if (self->sup_timers)
-    su_timer_expire(&self->sup_timers, &tout, su_now());
+  if (self->sup_base->sup_timers)
+    su_timer_expire(&self->sup_base->sup_timers, &tout, su_now());
 
-  if (!self->sup_running)
+  if (!self->sup_base->sup_running)
     return;
 
   CFRetain(rl);
@@ -1426,45 +1046,45 @@ void su_root_osx_prepare_run(su_root_t *root)
 
 /** @internal Main loop.
  * 
- * The function @c su_port_osx_run() waits for wait objects and the timers
+ * The function @c su_osx_port_run() waits for wait objects and the timers
  * associated with the port object.  When any wait object is signaled or
  * timer is expired, it invokes the callbacks, and returns waiting.
  * 
- * The function @c su_port_osx_run() runs until @c su_port_osx_break() is called
+ * The function @c su_osx_port_run() runs until @c su_osx_port_break() is called
  * from a callback.
  * 
  * @param self     pointer to port object
  * 
  */
-void su_port_osx_run(su_port_t *self)
+void su_osx_port_run(su_port_t *self)
 {
   CFRunLoopRef rl;
   su_duration_t tout = 0;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   enter;
 
-  self->sup_running = 1;
+  self->sup_base->sup_running = 1;
   rl = CFRunLoopGetCurrent();
 
-  if (self->sup_prepoll)
-    self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+  if (self->sup_base->sup_prepoll)
+    self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
 
-  if (self->sup_head)
-    su_port_osx_getmsgs(self);
+  if (self->sup_base->sup_head)
+    su_port_getmsgs(self);
   
-  if (self->sup_timers)
-    su_timer_expire(&self->sup_timers, &tout, su_now());
+  if (self->sup_base->sup_timers)
+    su_timer_expire(&self->sup_base->sup_timers, &tout, su_now());
 
-  if (!self->sup_running)
+  if (!self->sup_base->sup_running)
     return;
 
   CFRetain(rl);
   self->sup_main_loop = rl;
 
   /* if there are messages do a quick wait */
-  if (self->sup_head)
+  if (self->sup_base->sup_head)
     tout = 0;
 
   CFRunLoopRun();
@@ -1475,70 +1095,70 @@ void su_port_osx_run(su_port_t *self)
 
 #if tuning
 /* This version can help tuning... */
-void su_port_osx_run_tune(su_port_t *self)
+void su_osx_port_run_tune(su_port_t *self)
 {
   int i;
   int timers = 0, messages = 0, events = 0;
   su_duration_t tout = 0, tout0;
   su_time_t started = su_now(), woken = started, bedtime = woken;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
-  for (self->sup_running = 1; self->sup_running;) {
+  for (self->sup_base->sup_running = 1; self->sup_base->sup_running;) {
     tout0 = tout, tout = 2000;
 
     timers = 0, messages = 0;
 
-    if (self->sup_prepoll)
-      self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+    if (self->sup_base->sup_prepoll)
+      self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
 
-    if (self->sup_head)
-      messages = su_port_osx_getmsgs(self);
+    if (self->sup_base->sup_head)
+      messages = su_port_getmsgs(self);
 
-    if (self->sup_timers)
-      timers = su_timer_expire(&self->sup_timers, &tout, su_now());
+    if (self->sup_base->sup_timers)
+      timers = su_timer_expire(&self->sup_base->sup_timers, &tout, su_now());
 
-    if (!self->sup_running)
+    if (!self->sup_base->sup_running)
       break;
 
-    if (self->sup_head)      /* if there are messages do a quick wait */
+    if (self->sup_base->sup_head)      /* if there are messages do a quick wait */
       tout = 0;
 
     bedtime = su_now();
 
-    events = su_port_osx_wait_events(self, tout);
+    events = su_osx_port_wait_events(self, tout);
 
     woken = su_now();
 
     if (messages || timers || events)
-      SU_DEBUG_1(("su_port_osx_run(%p): %.6f: %u messages %u timers %u "
+      SU_DEBUG_1(("su_osx_port_run(%p): %.6f: %u messages %u timers %u "
                  "events slept %.6f/%.3f\n",
                  self, su_time_diff(woken, started), messages, timers, events,
                  su_time_diff(woken, bedtime), tout0 * 1e-3));
 
-    if (!self->sup_running)
+    if (!self->sup_base->sup_running)
       break;
   }
 }
 #endif
 
 /** @internal
- * The function @c su_port_osx_break() is used to terminate execution of @c
- * su_port_osx_run(). It can be called from a callback function.
+ * The function @c su_osx_port_break() is used to terminate execution of @c
+ * su_osx_port_run(). It can be called from a callback function.
  * 
  * @param self     pointer to port
  * 
  */
-void su_port_osx_break(su_port_t *self)
+void su_osx_port_break(su_port_t *self)
 {
   if (self->sup_main_loop)
     CFRunLoopStop(self->sup_main_loop);
 
-  self->sup_running = 0; 
+  self->sup_base->sup_running = 0; 
 }
 
 /** @internal
- * The function @c su_port_osx_wait_events() is used to poll() for wait objects
+ * The function @c su_osx_port_wait_events() is used to poll() for wait objects
  *
  * @param self     pointer to port
  * @param tout     timeout in milliseconds
@@ -1546,7 +1166,7 @@ void su_port_osx_break(su_port_t *self)
  * @return number of events handled
  */
 static
-int su_port_osx_wait_events(su_port_t *self, su_duration_t tout)
+int su_osx_port_wait_events(su_port_t *self, su_duration_t tout)
 {
   int i, events = 0;
   su_wait_t *waits = self->sup_waits;
@@ -1591,21 +1211,6 @@ int su_port_osx_wait_events(su_port_t *self, su_duration_t tout)
   return events;
 }
 
-/** @internal 
- * Used to check wait events in callbacks that take lots of time
- *
- * This function does a timeout 0 poll() and runs wait objects.
- *
- * @param port     pointer to port
- *
- * @return number of events handled
- */
-static
-int su_port_osx_yield(su_port_t *port)
-{
-  return su_port_osx_wait_events(port, 0);
-}
-
 /** @internal Block until wait object is signaled or timeout.
  *
  * This function waits for wait objects and the timers associated with 
@@ -1622,14 +1227,14 @@ int su_port_osx_yield(su_port_t *port)
  *   Milliseconds to the next invocation of timer, or @c SU_WAIT_FOREVER if
  *   there are no active timers.
  */
-su_duration_t su_port_osx_step(su_port_t *self, su_duration_t tout)
+su_duration_t su_osx_port_step(su_port_t *self, su_duration_t tout)
 {
   CFRunLoopRef rl;
   su_time_t now = su_now();
   CFAbsoluteTime start;
   int ret, timeout = tout > INT32_MAX ? INT32_MAX : tout;
 
-  assert(SU_PORT_OSX_OWN_THREAD(self));
+  // XXX - mela assert(SU_OSX_PORT_OWN_THREAD(self));
 
   rl = CFRunLoopGetCurrent();
 
@@ -1641,17 +1246,17 @@ su_duration_t su_port_osx_step(su_port_t *self, su_duration_t tout)
   if (tout < timeout)
     timeout = tout;
 
-  if (self->sup_prepoll)
-    self->sup_prepoll(self->sup_pp_magic, self->sup_pp_root);
+  if (self->sup_base->sup_prepoll)
+    self->sup_base->sup_prepoll(self->sup_base->sup_pp_magic, self->sup_base->sup_pp_root);
 
-  if (self->sup_head)
-    su_port_osx_getmsgs(self);
+  if (self->sup_base->sup_head)
+    su_base_port_getmsgs(self);
 
-  if (self->sup_timers)
-    su_timer_expire(&self->sup_timers, &tout, now);
+  if (self->sup_base->sup_timers)
+    su_timer_expire(&self->sup_base->sup_timers, &tout, now);
 
   /* if there are messages do a quick wait */
-  if (self->sup_head)
+  if (self->sup_base->sup_head)
     tout = 0;
 
   start = CFAbsoluteTimeGetCurrent();
@@ -1667,112 +1272,22 @@ su_duration_t su_port_osx_step(su_port_t *self, su_duration_t tout)
       break;
     }
 
+#if 0
     /* Check how long to run this loop */
-    if (CFAbsoluteTimeGetCurrent() >= start + timeout / 1000)
+    if (CFAbsoluteTimeGetCurrent() >= start + timeout / 10000)
+#else
       break;
+#endif
   }
   
-  if (self->sup_head)
-    su_port_osx_getmsgs(self);
+  if (self->sup_base->sup_head)
+    su_base_port_getmsgs(self);
 
-  if (self->sup_timers)
-    su_timer_expire(&self->sup_timers, &tout, su_now());
+  if (self->sup_base->sup_timers)
+    su_timer_expire(&self->sup_base->sup_timers, &tout, su_now());
 
-  if (self->sup_head)
+  if (self->sup_base->sup_head)
     tout = 0;
 
   return tout;
 }
-
-
-/** @internal
- * Checks if the calling thread owns the port object.
- *
- * @param self pointer to a port object
- *
- * @retval true (nonzero) if the calling thread owns the port,
- * @retval false (zero) otherwise.
- */
-int su_port_osx_own_thread(su_port_t const *self)
-{
-  return self == NULL || SU_PORT_OSX_OWN_THREAD(self);
-}
-
-#if 0
-/** @internal
- *  Prints out the contents of the port.
- *
- * @param self pointer to a port
- * @param f    pointer to a file (if @c NULL, uses @c stdout).
- */
-void su_port_osx_dump(su_port_t const *self, FILE *f)
-{
-  int i;
-#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
-#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
-#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
-
-  if (f == NULL)
-    f = stdout;
-
-  fprintf(f, "su_port_osx_t at %p:\n", self);
-  fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
-#if SU_HAVE_PTHREADS
-  fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
-#endif
-#if SU_HAVE_MBOX
-  fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
-         IS_WAIT_IN(&self->sup_mbox_wait),
-         IS_WAIT_OUT(&self->sup_mbox_wait),
-         IS_WAIT_ACCEPT(&self->sup_mbox_wait));
-#endif
-  fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
-  for (i = 0; i < self->sup_n_waits; i++) {
-    
-  }
-}
-
-#endif
-
-/* =========================================================================
- * Pre-poll() callback
- */
-
-int su_port_osx_add_prepoll(su_port_t *port,
-                       su_root_t *root, 
-                       su_prepoll_f *callback, 
-                       su_prepoll_magic_t *magic)
-{
-  if (port->sup_prepoll)
-    return -1;
-
-  port->sup_prepoll = callback;
-  port->sup_pp_magic = magic;
-  port->sup_pp_root = root;
-
-  return 0;
-}
-
-int su_port_osx_remove_prepoll(su_port_t *port,
-                          su_root_t *root)
-{
-  if (port->sup_pp_root != root)
-    return -1;
-
-  port->sup_prepoll = NULL;
-  port->sup_pp_magic = NULL;
-  port->sup_pp_root = NULL;
-
-  return 0;
-}
-
-/* =========================================================================
- * Timers
- */
-
-static
-su_timer_t **su_port_osx_timers(su_port_t *self)
-{
-  return &self->sup_timers;
-}
-
index cc873f28d694651054359f996c6882799c75d106..1f18fe29260ea68dabf8c89381b799af4fd72c21 100644 (file)
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  * @author Kai Vehmanen <kai.vehmanen@nokia.com>
  *
- * @date Created: Tue Sep 14 15:51:04 1999 ppessi
+ * @date Create: Fri Jan 26 20:44:14 2007 ppessi
+ * @date Original: Tue Sep 14 15:51:04 1999 ppessi
  */
 
 #include "config.h"
 
-#if HAVE_POLL || HAVE_SELECT
+#define su_port_s su_poll_port_s
+
+#include "su_port.h"
+#include "sofia-sip/su_alloc.h"
+#include "sofia-sip/su.h"
+
+#if HAVE_POLL_PORT
 
 #include <stdlib.h>
 #include <assert.h>
 #include <limits.h>
 #include <errno.h>
 
-#define su_port_s su_poll_port_s
-
-#include "sofia-sip/su.h"
-#include "su_port.h"
-#include "sofia-sip/su_alloc.h"
-
 /** Port based on poll(). */
 
 struct su_poll_port_s {
-  su_pthread_port_t sup_base[1];
+  su_socket_port_t sup_base[1];
 
-#define sup_home sup_base->sup_base->sup_home
+#define sup_home sup_base->sup_base->sup_base->sup_home
 
   unsigned         sup_multishot; /**< Multishot operation? */
 
@@ -69,12 +70,7 @@ struct su_poll_port_s {
   int              sup_size_waits; /**< Size of allocated su_waits */
   int              sup_pri_offset; /**< Offset to prioritized waits */
 
-#if !SU_HAVE_WINSOCK
 #define INDEX_MAX (0x7fffffff)
-#else 
-  /* We use WSAWaitForMultipleEvents() */
-#define INDEX_MAX (64)
-#endif
 
   /** Indices from index returned by su_root_register() to tables below. 
    *
@@ -124,7 +120,7 @@ su_port_vtable_t const su_poll_port_vtable[1] =
       su_base_port_incref,
       su_poll_port_decref,
       su_base_port_gsource,
-      su_pthread_port_send,
+      su_socket_port_send,
       su_poll_port_register,
       su_poll_port_unregister,
       su_poll_port_deregister,
@@ -160,7 +156,7 @@ static void su_poll_port_deinit(void *arg)
 
   SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", (void *)self));
 
-  su_pthread_port_deinit(self);
+  su_socket_port_deinit(self->sup_base);
 }
 
 static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
@@ -516,8 +512,8 @@ int su_poll_port_unregister_all(su_port_t *self,
 
 /**Set mask for a registered event. @internal
  *
- * The function su_poll_port_eventmask() sets the mask describing events that can
- * signal the registered callback.
+ * The function su_poll_port_eventmask() sets the mask describing events
+ * that can signal the registered callback.
  *
  * @param port   pointer to port object
  * @param index  registration index
@@ -663,7 +659,7 @@ su_port_t *su_poll_port_create(void)
 
   self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
 
-  if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
+  if (su_socket_port_init(self->sup_base, su_poll_port_vtable) < 0)
     return su_home_unref(su_port_home(self)), NULL;
 
   return self;
@@ -675,8 +671,25 @@ int su_poll_clone_start(su_root_t *parent,
                        su_root_init_f init,
                        su_root_deinit_f deinit)
 {
-  return su_pthreaded_port_start(su_poll_port_create, 
+  return su_pthreaded_port_start(su_default_port_create, 
                                 parent, return_clone, magic, init, deinit);
 }
 
-#endif  /* HAVE_POLL || HAVE_SELECT */
+#else
+
+su_port_t *su_poll_port_create(void)
+{
+  return su_default_port_create();
+}
+
+int su_poll_clone_start(su_root_t *parent,
+                       su_clone_r return_clone,
+                       su_root_magic_t *magic,
+                       su_root_init_f init,
+                       su_root_deinit_f deinit)
+{
+  return su_default_clone_start(parent, return_clone, magic, init, deinit);
+}
+
+#endif  /* HAVE_POLL_PORT */
+
index a20891f1b71d4695167e9892d4afd82739758f87..c30e9d3d399cc06ea7aa2d0149e6de99ac77345e 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
-static su_port_create_f *preferred_su_port_create;
+/** Create the default su_port_t implementation. */
+su_port_t *su_default_port_create(void)
+{
+#if HAVE_EPOLL
+  return su_epoll_port_create();
+#elif HAVE_POLL_PORT
+  return su_poll_port_create();
+#elif HAVE_WIN32
+  return su_wsaevent_port_create();
+#elif HAVE_SELECT
+  return su_select_port_create();
+#else
+  return NULL;
+#endif
+}
+
+int su_default_clone_start(su_root_t *parent,
+                          su_clone_r return_clone,
+                          su_root_magic_t *magic,
+                          su_root_init_f init,
+                          su_root_deinit_f deinit)
+{
+#if HAVE_EPOLL
+  return su_epoll_clone_start(parent, return_clone, magic, init, deinit);;
+#elif HAVE_POLL_PORT
+  return su_poll_clone_start(parent, return_clone, magic, init, deinit);;
+#elif HAVE_WIN32
+  return su_wsaevent_clone_start(parent, return_clone, magic, init, deinit);;
+#elif HAVE_SELECT
+  return su_select_clone_start(parent, return_clone, magic, init, deinit);;
+#else
+  errno = ENOSYS;
+  return -1;
+#endif
+}
+
+static su_port_create_f *preferred_su_port_create = su_default_port_create;
 static su_clone_start_f *preferred_su_clone_start;
 
 /** Explicitly set the preferred su_port_t implementation.
@@ -69,45 +105,44 @@ void su_port_set_system_preferences(char const *name)
 
   if (name == NULL)
       ;
-#if HAVE_POLL_PORT
 #if HAVE_EPOLL
   else if (strcmp(name, "epoll") == 0) {
     create = su_epoll_port_create;
     start = su_epoll_clone_start;
   }
 #endif
+#if HAVE_POLL_PORT
   else if (strcmp(name, "poll") == 0) {
     create = su_poll_port_create;
     start = su_poll_clone_start;
   }
-#else
-  /* select port does not work yet */
-#error no poll!
 #endif
-#if HAVE_SELECT
+#if HAVE_WIN32
+  else if (strcasecmp(name, "wsaevent") == 0) {
+    create = su_wsaevent_port_create;
+    start = su_wsaevent_clone_start;
+  }
+#endif
+#if HAVE_SELECT && !HAVE_WIN32
   else if (strcmp(name, "select") == 0) {
     create = su_select_port_create;
     start = su_select_clone_start;
   }
 #endif
 
-#if HAVE_POLL_PORT
-#if HAVE_EPOLL
-  if (create == NULL) create = su_epoll_port_create;
-  if (start == NULL) start = su_epoll_clone_start;
-#else
-  if (create == NULL) create = su_poll_port_create;
-  if (start == NULL) start = su_poll_clone_start;
-#endif
-#else
-#if HAVE_SELECT
-  if (create == NULL) create = su_select_port_create;
-  if (start == NULL) start = su_select_clone_start;
-#endif
-#endif
+  if (create == NULL) 
+    create = su_default_port_create;
+
+  if (!preferred_su_port_create ||
+      preferred_su_port_create == su_default_port_create) 
+    preferred_su_port_create = create;
+
+  if (start == NULL)
+    start = su_default_clone_start;
 
-  if (preferred_su_port_create == NULL) preferred_su_port_create = create;
-  if (preferred_su_clone_start == NULL) preferred_su_clone_start = start;
+  if (!preferred_su_clone_start || 
+      preferred_su_clone_start == su_default_clone_start)
+    preferred_su_clone_start = start;
 }
 
 /** Create the preferred su_port_t implementation. */
@@ -116,10 +151,7 @@ su_port_t *su_port_create(void)
   if (preferred_su_port_create == NULL)
     su_port_set_system_preferences(getenv("SU_PORT"));
 
-  if (preferred_su_port_create)
-    return preferred_su_port_create();
-
-  return NULL;
+  return preferred_su_port_create();
 }
 
 /* ========================================================================
@@ -244,8 +276,6 @@ int su_clone_start(su_root_t *parent,
   if (parent == NULL || parent->sur_threading) {
     if (preferred_su_clone_start == NULL)
       su_port_set_system_preferences(getenv("SU_PORT"));
-    if (preferred_su_clone_start == NULL)
-      return -1;
     return preferred_su_clone_start(parent, return_clone, magic, init, deinit);
   }
 
index d650dbe5f173bdc995e34e2cace9843eafa1287e..29c1f5873162a4122e59b4e2297cf967d334a3d6 100644 (file)
@@ -152,26 +152,6 @@ SOFIAPUBFUN su_port_t *su_port_create(void)
 
 /* Extension from >= 1.12.5 */
 
-typedef su_port_t *su_port_create_f(void);
-typedef int su_clone_start_f(su_root_t *parent,
-                           su_clone_r return_clone,
-                           su_root_magic_t *magic,
-                           su_root_init_f init,
-                           su_root_deinit_f deinit);
-
-SOFIAPUBFUN void su_port_prefer(su_port_create_f *f, su_clone_start_f *);
-
-SOFIAPUBFUN su_port_t *su_epoll_port_create(void)
-     __attribute__((__malloc__));
-SOFIAPUBFUN su_port_t *su_poll_port_create(void)
-     __attribute__((__malloc__));
-SOFIAPUBFUN su_port_t *su_select_port_create(void)
-     __attribute__((__malloc__));
-
-SOFIAPUBFUN su_clone_start_f su_epoll_clone_start;
-SOFIAPUBFUN su_clone_start_f su_poll_clone_start;
-SOFIAPUBFUN su_clone_start_f su_select_clone_start;
-
 SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg);
 SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
                                                su_time_t now);
@@ -518,22 +498,18 @@ SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
 
 #include <pthread.h>
 
-#define SU_MBOX_SIZE 2
-
 /** Pthread port object */ 
 typedef struct su_pthread_port_s {
   su_base_port_t   sup_base[1];
   struct su_pthread_port_waiting_parent 
                   *sup_waiting_parent;
   pthread_t        sup_tid;
-  pthread_mutex_t  sup_runlock[1];
 #if 0
+  pthread_mutex_t  sup_runlock[1];
   pthread_cond_t   sup_resume[1];
   short            sup_paused; /**< True if thread is paused */
 #endif
   short            sup_thread; /**< True if thread is active */
-  short            sup_mbox_index;
-  su_socket_t      sup_mbox[SU_MBOX_SIZE];
 } su_pthread_port_t;
 
 /* Pthread methods */
@@ -546,9 +522,9 @@ SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who);
 
 SOFIAPUBFUN int su_pthread_port_own_thread(su_port_t const *self);
 
+#if 0                          /* not yet  */
 SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg);
 
-#if 0                          /* not yet  */
 SOFIAPUBFUN su_port_t *su_pthread_port_create(void);
 SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
                                             su_clone_r return_clone,
@@ -584,12 +560,27 @@ typedef su_base_port_t su_pthread_port_t;
 #define su_pthread_port_lock   su_base_port_lock
 #define su_pthread_port_unlock su_base_port_unlock
 #define su_pthread_port_own_thread su_base_port_own_thread
-#define su_pthread_port_send   su_base_port_send
 #define su_pthread_port_wait   su_base_port_wait
 #define su_pthread_port_execute  su_base_port_execute
 
 #endif
 
+/* ====================================================================== */
+/* Mailbox port using sockets */
+
+#define SU_MBOX_SIZE 2
+
+typedef struct su_socket_port_s {
+  su_pthread_port_t sup_base[1];
+  int               sup_mbox_index;
+  su_socket_t       sup_mbox[SU_MBOX_SIZE];
+} su_socket_port_t;
+
+SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *, 
+                                   su_port_vtable_t const *);
+SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self);
+SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg);
+
 SOFIA_END_DECLS
 
 #endif /* SU_PORT_H */
index 1d7bb256e3bd5f3a436874e707bc17840dade948..e5471ff857c07f0e37047d39ed3d94b2daed8558 100644 (file)
 #define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \
   (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0)
 
-#if HAVE_SOCKETPAIR
-#define SU_MBOX_SEND 1
-#else
-#define SU_MBOX_SEND 0
-#endif
-
-/** @internal Message box wakeup function. */
-static int su_mbox_port_wakeup(su_root_magic_t *magic, /* NULL */
-                              su_wait_t *w,
-                              su_wakeup_arg_t *arg)
-{
-  char buf[32];
-  su_socket_t socket = *(su_socket_t*)arg;
-  su_wait_events(w, socket);
-  recv(socket, buf, sizeof(buf), 0);
-  return 0;
-}
-
 /**@internal
  *
  * Initializes a message port. It creates a mailbox used to wake up the
@@ -90,93 +72,14 @@ int su_pthread_port_init(su_port_t *self, su_port_vtable_t const *vtable)
   SU_DEBUG_9(("su_pthread_port_init(%p, %p) called\n",
              (void *)self, (void *)vtable));
 
+  self->sup_tid = pthread_self();
+
   if (su_base_port_init(self, vtable) == 0 &&
       su_base_port_threadsafe(self) == 0) {
-    int af;
-    su_socket_t mb = INVALID_SOCKET;
-    su_wait_t wait[1] = { SU_WAIT_INIT };
-    char const *why;
-
-    self->sup_tid = pthread_self();
-
-#if 0
-    pthread_mutex_init(self->sup_runlock, NULL);
-    pthread_mutex_lock(self->sup_runlock);
-    pthread_cond_init(self->sup_resume, NULL);
-#endif
-
-#if HAVE_SOCKETPAIR
-#if defined(AF_LOCAL)
-    af = AF_LOCAL;
-#else
-    af = AF_UNIX;
-#endif
-    if (socketpair(af, SOCK_STREAM, 0, self->sup_mbox) == -1) {
-      why = "socketpair"; goto error;
-    }
-
-    mb = self->sup_mbox[0];
-    su_setblocking(self->sup_mbox[1], 0);
-
-#else
-    {
-      struct sockaddr_in sin = { sizeof(struct sockaddr_in), 0 };
-      socklen_t sinsize = sizeof sin;
-      struct sockaddr *sa = (struct sockaddr *)&sin;
-
-      af = PF_INET;
-
-      self->sup_mbox[0] = mb = su_socket(af, SOCK_DGRAM, IPPROTO_UDP);
-      if (mb == INVALID_SOCKET) {
-       why = "socket"; goto error;
-      }
-  
-      sin.sin_family = AF_INET;
-      sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* 127.1 */
-      
-      /* Get a port for us */
-      if (bind(mb, sa, sizeof sin) == -1) {
-       why = "bind"; goto error;
-      }
-
-      if (getsockname(mb, sa, &sinsize) == -1) {
-       why = "getsockname"; goto error;
-      }
-    
-      if (connect(mb, sa, sinsize) == -1) {
-       why = "connect"; goto error;
-      }
-    }
-#endif    
-
-    su_setblocking(mb, 0);
-
-    if (su_wait_create(wait, mb, SU_WAIT_IN) == -1) {
-      why = "su_wait_create";
-      goto error;
-    }
-
-    self->sup_mbox_index = su_port_register(self, NULL, wait, 
-                                           su_mbox_port_wakeup, 
-                                           (void *)self->sup_mbox, 0);
-
-    if (self->sup_mbox_index <= 0) {
-      why = "su_port_register";
-      su_wait_destroy(wait);
-      goto error;
-    }
-
-    SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", 0));
-
     return 0;
-
-  error:
-    su_log("%s: %s: %s\n", 
-          "su_pthread_port_init", why, su_strerror(su_errno()));
-    su_pthread_port_deinit(self);
   }
-
-  SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", -1));
+  else
+    su_base_port_deinit(self);
 
   return -1;
 }
@@ -187,17 +90,6 @@ void su_pthread_port_deinit(su_port_t *self)
 {
   assert(self);
 
-  if (self->sup_mbox_index > 0)
-    su_port_deregister(self, self->sup_mbox_index);
-  self->sup_mbox_index = 0;
-
-  if (self->sup_mbox[0] && self->sup_mbox[0] != INVALID_SOCKET)
-    su_close(self->sup_mbox[0]); self->sup_mbox[0] = INVALID_SOCKET;
-#if HAVE_SOCKETPAIR
-  if (self->sup_mbox[1] && self->sup_mbox[1] != INVALID_SOCKET)
-    su_close(self->sup_mbox[1]); self->sup_mbox[1] = INVALID_SOCKET;
-#endif
-
 #if 0
   pthread_mutex_destroy(self->sup_runlock);
   pthread_cond_destroy(self->sup_resume);
@@ -225,27 +117,6 @@ void su_pthread_port_unlock(su_port_t *self, char const *who)
                   (void *)pthread_self(), who, self));
 }
 
-/** @internal Send a message to the port. */
-int su_pthread_port_send(su_port_t *self, su_msg_r rmsg)
-{
-  int wakeup = su_base_port_send(self, rmsg);
-
-  if (wakeup < 0)
-    return -1;
-  if (wakeup == 0)
-    return 0;
-
-  assert(self->sup_mbox[SU_MBOX_SEND] != INVALID_SOCKET);
-
-  if (send(self->sup_mbox[SU_MBOX_SEND], "X", 1, 0) == -1) {
-#if HAVE_SOCKETPAIR
-    if (su_errno() != EWOULDBLOCK)
-#endif
-      su_perror("su_msg_send: send()");
-  }
-  return 0;
-}
-
 /** @internal
  * Checks if the calling thread owns the port object.
  *
index 2b7483544eb60afc5c9fd954b48a7f3ae5126866..807b5898989ff3c53a8bc8d0b563af23bd5ce0fd 100644 (file)
 /**@ingroup su_wait
  * @CFILE su_select_port.c
  *
- * Port implementation using select(). NOT IMPLEMENTED YET!
+ * Port implementation using select().
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  * @author Kai Vehmanen <kai.vehmanen@nokia.com>
  *
- * @date Created: Tue Sep 14 15:51:04 1999 ppessi
+ * @date Created: Fri Jan 26 17:56:34 2007 ppessi
  */
 
 #include "config.h"
 #include <limits.h>
 #include <errno.h>
 
+#if HAVE_WIN32
+#error winsock select() not supported yet
+#else
 #if HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #elif HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
 
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef __NFDBITS
+#define __NFDBITS (8 * sizeof (long int))
+#endif
+
+#undef FDSETSIZE
+/* Size of fd set in bytes */
+#define FDSETSIZE(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
+#endif
+
 /** Port based on select(). */
 
 struct su_select_port_s {
-  su_pthread_port_t sup_base[1];
+  su_socket_port_t sup_base[1];
 
+#define sup_home sup_base->sup_base->sup_base->sup_home
+
+  /** epoll fd */
+  int              sup_epoll;
   unsigned         sup_multishot; /**< Multishot operation? */
 
   unsigned         sup_registers; /** Counter incremented by 
                                      su_port_register() or 
                                      su_port_unregister()
                                   */
-
-  int              sup_n_waits; /**< Active su_wait_t in su_waits */
-  int              sup_size_waits; /**< Size of allocated su_waits */
-  int              sup_pri_offset; /**< Offset to prioritized waits */
-
-  /** Indices from index returned by su_root_register() to tables below. 
-   *
-   * Free elements are negative. Free elements form a list, value of free
-   * element is (0 - index of next free element).
-   *
-   * First element sup_indices[0] points to first free element. 
-   */
-  int             *sup_indices;
-
-  int             *sup_reverses; /** Reverse index */
-  su_wakeup_f     *sup_wait_cbs; 
-  su_wakeup_arg_t**sup_wait_args; 
-  su_root_t      **sup_wait_roots; 
-  su_wait_t       *sup_waits; 
+  int              sup_n_registrations;
+  int              sup_max_index; /**< Indexes are equal or smaller than this */
+  int              sup_size_indices; /**< Size of allocated index table */
+
+  /** Structure containing registration data */
+  struct su_select_register {
+    struct su_select_register *ser_next; /* Next in free list */
+    su_wakeup_f     ser_cb; 
+    su_wakeup_arg_t*ser_arg; 
+    su_root_t      *ser_root; 
+    int             ser_id; /** registration identifier */
+    su_wait_t       ser_wait[1];
+  } **sup_indices;
+
+  int               sup_maxfd, sup_allocfd;
+  
+  fd_set           *sup_readfds, *sup_readfds2;
+  fd_set           *sup_writefds, *sup_writefds2;
 };
 
-static void su_select_port_decref(su_port_t *, int blocking, char const *who);
-
+static void su_select_port_decref(su_port_t *self,
+                                int blocking,
+                                char const *who);
 static int su_select_port_register(su_port_t *self,
-                                su_root_t *root, 
-                                su_wait_t *wait, 
-                                su_wakeup_f callback,
-                                su_wakeup_arg_t *arg,
-                                int priority);
+                                 su_root_t *root, 
+                                 su_wait_t *wait, 
+                                 su_wakeup_f callback,
+                                 su_wakeup_arg_t *arg,
+                                 int priority);
 static int su_select_port_unregister(su_port_t *port,
-                                  su_root_t *root, 
-                                  su_wait_t *wait,     
-                                  su_wakeup_f callback, 
-                                  su_wakeup_arg_t *arg);
+                                   su_root_t *root, 
+                                   su_wait_t *wait,    
+                                   su_wakeup_f callback, 
+                                   su_wakeup_arg_t *arg);
 static int su_select_port_deregister(su_port_t *self, int i);
 static int su_select_port_unregister_all(su_port_t *self, su_root_t *root);
 static int su_select_port_eventmask(su_port_t *self, 
-                                   int index,
-                                   int socket,
-                                   int events);
+                                  int index,
+                                  int socket,
+                                  int events);
 static int su_select_port_multishot(su_port_t *self, int multishot);
 static int su_select_port_wait_events(su_port_t *self, su_duration_t tout);
 static char const *su_select_port_name(su_port_t const *self);
@@ -120,7 +139,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
       su_base_port_incref,
       su_select_port_decref,
       su_base_port_gsource,
-      su_pthread_port_send,
+      su_socket_port_send,
       su_select_port_register,
       su_select_port_unregister,
       su_select_port_deregister,
@@ -142,7 +161,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
       su_select_port_name,
       su_base_port_start_shared,
       su_pthread_port_wait,
-      su_pthread_port_execute
+      su_pthread_port_execute,
     }};
 
 static char const *su_select_port_name(su_port_t const *self)
@@ -150,39 +169,23 @@ static char const *su_select_port_name(su_port_t const *self)
   return "select";
 }
 
+static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
+{
+  (void)su_base_port_decref(self, blocking, who);
+}
+
 static void su_select_port_deinit(void *arg)
 {
   su_port_t *self = arg;
 
   SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self));
 
-  su_pthread_port_deinit(self);
-
-  if (self->sup_waits) 
-    free(self->sup_waits), self->sup_waits = NULL;
-  if (self->sup_wait_cbs)
-    free(self->sup_wait_cbs), self->sup_wait_cbs = NULL;
-  if (self->sup_wait_args)
-    free(self->sup_wait_args), self->sup_wait_args = NULL;
-  if (self->sup_wait_roots)
-    free(self->sup_wait_roots), self->sup_wait_roots = NULL;
-  if (self->sup_reverses)
-    free(self->sup_reverses), self->sup_reverses = NULL;
-  if (self->sup_indices)
-    free(self->sup_indices), self->sup_indices = NULL;
-
-  SU_DEBUG_9(("%s(%p) freed registrations\n",
-             "su_select_port_deinit", (void *)self));
-}
-
-static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
-{
-  su_base_port_decref(self, blocking, who);
+  su_socket_port_deinit(self->sup_base);
 }
 
 /** @internal
  *
- *  Register a @c su_wait_t object. The wait object, a callback function and
+ *  Register a #su_wait_t object. The wait object, a callback function and
  *  an argument pointer is stored in the port object.  The callback function
  *  will be called when the wait object is signaled.
  *
@@ -202,179 +205,154 @@ static void su_select_port_decref(su_port_t *self, int blocking, char const *who
  *   or -1 upon an error.
  */
 int su_select_port_register(su_port_t *self,
-                         su_root_t *root, 
-                         su_wait_t *wait, 
-                         su_wakeup_f callback,
-                         su_wakeup_arg_t *arg,
-                         int priority)
+                          su_root_t *root, 
+                          su_wait_t *wait, 
+                          su_wakeup_f callback,
+                          su_wakeup_arg_t *arg,
+                          int priority)
 {
   int i, j, n;
+  struct su_select_register *ser;
+  struct su_select_register **indices = self->sup_indices;
+  int allocfd = self->sup_allocfd;
+  fd_set *readfds = self->sup_readfds, *readfds2 = self->sup_readfds2;
+  fd_set *writefds = self->sup_writefds, *writefds2 = self->sup_writefds2;
 
   assert(su_port_own_thread(self));
 
-  n = self->sup_n_waits;
+  n = self->sup_size_indices;
 
   if (n >= SU_WAIT_MAX)
     return su_seterrno(ENOMEM);
 
-  if (n >= self->sup_size_waits) {
-    /* Reallocate size arrays */
-    int size;
-    int *indices;
-    int *reverses;
-    su_wait_t *waits;
-    su_wakeup_f *wait_cbs;
-    su_wakeup_arg_t **wait_args;
-    su_root_t **wait_tasks;
-
-    if (self->sup_size_waits == 0)
-      size = su_root_size_hint;
-    else 
-      size = 2 * self->sup_size_waits;
-
-    if (size < SU_WAIT_MIN)
-      size = SU_WAIT_MIN;
-
-    /* Too large */
-    if (-3 - size > 0)
-      return (errno = ENOMEM), -1;
-
-    indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices));
-    if (indices) {
-      self->sup_indices = indices;
+  self->sup_registers++;
 
-      if (self->sup_size_waits == 0)
-       indices[0] = -1;
+  if (wait->fd >= allocfd) 
+    allocfd += __NFDBITS;              /* long at a time */
 
-      for (i = self->sup_size_waits + 1; i <= size; i++)
-       indices[i] = -1 - i;
-    }
+  if (allocfd >= self->sup_allocfd) {
+    size_t bytes = FDSETSIZE(allocfd);
+    size_t bytes0 = FDSETSIZE(self->sup_allocfd);
+    /* (Re)allocate fd_sets  */
 
-    reverses = realloc(self->sup_reverses, size * sizeof(*waits));
-    if (reverses) {
-      for (i = self->sup_size_waits; i < size; i++)
-       reverses[i] = -1;
-      self->sup_reverses = reverses;
-    }
-      
-    waits = realloc(self->sup_waits, size * sizeof(*waits));
-    if (waits)
-      self->sup_waits = waits;
-
-    wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs));
-    if (wait_cbs)
-      self->sup_wait_cbs = wait_cbs;
-
-    wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args));
-    if (wait_args)
-      self->sup_wait_args = wait_args;
-
-    /* Add sup_wait_roots array, if needed */
-    wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks));
-    if (wait_tasks) 
-      self->sup_wait_roots = wait_tasks;
-
-    if (!(indices && 
-         reverses && waits && wait_cbs && wait_args && wait_tasks)) {
+    readfds = su_realloc(self->sup_home, readfds, bytes);
+    if (readfds) self->sup_readfds = readfds;
+    readfds2 = su_realloc(self->sup_home, readfds2, bytes);
+    if (readfds2) self->sup_readfds2 = readfds2;
+    if (!readfds || !readfds2)
       return -1;
-    }
 
-    self->sup_size_waits = size;
+    writefds = su_realloc(self->sup_home, writefds, bytes);
+    if (writefds) self->sup_writefds = writefds;
+    writefds2 = su_realloc(self->sup_home, writefds2, bytes);
+    if (writefds2) self->sup_writefds2 = writefds2;
+    if (!writefds || !writefds2)
+      return -1;
+
+    memset((char *)readfds + bytes0, 0, bytes - bytes0);
+    memset((char *)writefds + bytes0, 0, bytes - bytes0);
+
+    self->sup_allocfd = allocfd;
   }
 
-  i = -self->sup_indices[0]; assert(i <= self->sup_size_waits);
-
-  if (priority > 0) {
-    /* Insert */
-    for (n = self->sup_n_waits; n > 0; n--) {
-      j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1);
-      self->sup_indices[j] = n;
-      self->sup_reverses[n] = j;
-      self->sup_waits[n] = self->sup_waits[n-1];
-      self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1];
-      self->sup_wait_args[n] = self->sup_wait_args[n-1];
-      self->sup_wait_roots[n] = self->sup_wait_roots[n-1];     
+  ser = indices[0];
+
+  if (!ser) {
+    su_home_t *h = su_port_home(self);
+
+    i = self->sup_max_index, j = i == 0 ? 15 : i + 16;
+    
+    if (j >= self->sup_size_indices) {
+      /* Reallocate index table */
+      n = n < 1024 ? 2 * n : n + 1024;
+      indices = su_realloc(h, indices, n * sizeof(indices[0]));
+      if (!indices)
+       return -1;
+      self->sup_indices = indices;
+      self->sup_size_indices = n;
     }
 
-    self->sup_pri_offset++;
-  }
-  else {
-    /* Append - no need to move anything */
-    n = self->sup_n_waits;
+    /* Allocate registrations */
+    ser = su_zalloc(h, (j - i) * (sizeof *ser));
+    if (!ser)
+      return -1;
+
+    indices[0] = ser;
+
+    for (i++; i <= j; i++) {
+      ser->ser_id = i;
+      ser->ser_next = i < j ? ser + 1 : NULL;
+      indices[i] = ser++;
+    }
+
+    self->sup_max_index = j;
+
+    ser = indices[0];
   }
 
-  self->sup_n_waits++;
+  i = ser->ser_id;
 
-  self->sup_indices[0] = self->sup_indices[i];  /* Free index */
-  self->sup_indices[i] = n;
+  indices[0] = ser->ser_next;
+  
+  ser->ser_next = NULL;
+  *ser->ser_wait = *wait;
+  ser->ser_cb = callback;
+  ser->ser_arg = arg;
+  ser->ser_root = root;
 
-  self->sup_reverses[n] = i;
-  self->sup_waits[n] = *wait;
-  self->sup_wait_cbs[n] = callback;
-  self->sup_wait_args[n] = arg;
-  self->sup_wait_roots[n] = root;
+  if (wait->events & SU_WAIT_IN)
+    FD_SET(wait->fd, readfds);
+  if (wait->events & SU_WAIT_OUT)
+    FD_SET(wait->fd, writefds);
 
-  self->sup_registers++;
+  if (wait->fd >= self->sup_maxfd)
+    self->sup_maxfd = wait->fd + 1;
 
-  /* We return -1 or positive integer */
+  self->sup_n_registrations++;
 
-  return i;
+  return i;                    /* return index */
 }
 
-/** Deregister a su_wait_t object. */
-static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
+static void su_select_port_update_maxfd(su_port_t *self)
 {
-  int n, N, *indices, *reverses;
+  int i;
+  su_socket_t maxfd = 0;
 
-  indices = self->sup_indices;
-  reverses = self->sup_reverses;
+  for (i = 1; i <= self->sup_max_index; i++) {
+    if (!self->sup_indices[i]->ser_cb)
+      continue;
+    if (maxfd <= self->sup_indices[i]->ser_wait->fd)
+      maxfd = self->sup_indices[i]->ser_wait->fd + 1;
+  }
 
-  n = indices[i]; assert(n >= 0);
+  self->sup_maxfd = maxfd;
+}
 
-  if (destroy_wait)
-    su_wait_destroy(&self->sup_waits[n]);
-  
-  N = --self->sup_n_waits;
-  
-  if (n < self->sup_pri_offset) {
-    int j = --self->sup_pri_offset;
-    if (n != j) {
-      assert(reverses[j] > 0);
-      assert(indices[reverses[j]] == j);
-      indices[reverses[j]] = n;
-      reverses[n] = reverses[j];
-
-      self->sup_waits[n] = self->sup_waits[j];
-      self->sup_wait_cbs[n] = self->sup_wait_cbs[j];
-      self->sup_wait_args[n] = self->sup_wait_args[j];
-      self->sup_wait_roots[n] = self->sup_wait_roots[j];
-      n = j;
-    }
+/** Deregister a su_wait_t object. */
+static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
+{
+  struct su_select_register **indices = self->sup_indices;
+  struct su_select_register *ser;
+
+  ser = self->sup_indices[i];
+  if (ser == NULL || ser->ser_cb == NULL) {
+    su_seterrno(ENOENT);
+    return -1;
   }
 
-  if (n < N) {
-    assert(reverses[N] > 0);
-    assert(indices[reverses[N]] == N);
+  assert(ser->ser_id == i);
 
-    indices[reverses[N]] = n;
-    reverses[n] = reverses[N];
+  FD_CLR(ser->ser_wait->fd, self->sup_readfds);
+  FD_CLR(ser->ser_wait->fd, self->sup_writefds);
 
-    self->sup_waits[n] = self->sup_waits[N];
-    self->sup_wait_cbs[n] = self->sup_wait_cbs[N];
-    self->sup_wait_args[n] = self->sup_wait_args[N];
-    self->sup_wait_roots[n] = self->sup_wait_roots[N];
-    n = N;
-  }
+  if (ser->ser_wait->fd + 1 >= self->sup_maxfd)
+    self->sup_maxfd = 0;
 
-  reverses[n] = -1;
-  memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]);
-  self->sup_wait_cbs[n] = NULL;
-  self->sup_wait_args[n] = NULL;
-  self->sup_wait_roots[n] = NULL;
-  
-  indices[i] = indices[0];
-  indices[0] = -i;
+  memset(ser, 0, sizeof *ser);
+  ser->ser_id = i;
+  ser->ser_next = indices[0], indices[0] = ser;
 
+  self->sup_n_registrations--;
   self->sup_registers++;
 
   return i;
@@ -383,9 +361,9 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
 
 /** Unregister a su_wait_t object.
  *  
- *  The function su_select_port_unregister() unregisters a su_wait_t object. The
- *  wait object, a callback function and a argument are removed from the
- *  port object.
+ * The function su_select_port_unregister() unregisters a su_wait_t object. 
+ * The registration defined by the wait object, the callback function and
+ * the argument pointer are removed from the port object.
  * 
  * @param self     - pointer to port object
  * @param root     - pointer to root object
@@ -399,22 +377,27 @@ static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
  * @return Nonzero index of the wait object, or -1 upon an error.
  */
 int su_select_port_unregister(su_port_t *self,
-                           su_root_t *root, 
-                           su_wait_t *wait,    
-                           su_wakeup_f callback, /* XXX - ignored */
-                           su_wakeup_arg_t *arg)
+                            su_root_t *root, 
+                            su_wait_t *wait,   
+                            su_wakeup_f callback, /* XXX - ignored */
+                            su_wakeup_arg_t *arg)
 {
-  int n, N;
+  int i, I;
+
+  struct su_select_register *ser;
 
   assert(self);
   assert(su_port_own_thread(self));
 
-  N = self->sup_n_waits;
+  I = self->sup_max_index;
 
-  for (n = 0; n < N; n++) {
-    if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
-      return su_select_port_deregister0(self, self->sup_reverses[n], 0);
-    }
+  for (i = 1; i <= I; i++) {
+    ser = self->sup_indices[i];
+
+    if (ser->ser_cb &&
+       arg == ser->ser_arg &&
+       SU_WAIT_CMP(wait[0], ser->ser_wait[0]) == 0)
+      return su_select_port_deregister0(self, ser->ser_id, 0);
   }
 
   su_seterrno(ENOENT);
@@ -435,100 +418,56 @@ int su_select_port_unregister(su_port_t *self,
  */
 int su_select_port_deregister(su_port_t *self, int i)
 {
-  su_wait_t wait[1] = { SU_WAIT_INIT };
-  int retval;
-
-  assert(self);
-  assert(su_port_own_thread(self));
+  struct su_select_register *ser;
 
-  if (i <= 0 || i > self->sup_size_waits)
+  if (i <= 0 || i > self->sup_max_index)
     return su_seterrno(EBADF);
 
-  if (self->sup_indices[i] < 0)
+  ser = self->sup_indices[i];
+  if (!ser->ser_cb)
     return su_seterrno(EBADF);
-    
-  retval = su_select_port_deregister0(self, i, 1);
-
-  su_wait_destroy(wait);
 
-  return retval;
+  return su_select_port_deregister0(self, i, 1);
 }
 
 
 /** @internal
- * Unregister all su_wait_t objects.
+ * Unregister all su_wait_t objects of given su_root_t instance.
  *
- * The function su_select_port_unregister_all() unregisters all su_wait_t objects
- * and destroys all queued timers associated with given root object.
+ * The function su_select_port_unregister_all() unregisters all su_wait_t
+ * objects associated with given root object.
  * 
  * @param  self     - pointer to port object
  * @param  root     - pointer to root object
  * 
  * @return Number of wait objects removed.
  */
-int su_select_port_unregister_all(su_port_t *self, 
-                               su_root_t *root)
+int su_select_port_unregister_all(su_port_t *self, su_root_t *root)
 {
-  int i, j, index, N;
-  int             *indices, *reverses;
-  su_wait_t       *waits;
-  su_wakeup_f     *wait_cbs;
-  su_wakeup_arg_t**wait_args;
-  su_root_t      **wait_roots;
+  int i, I, n;
 
-  assert(su_port_own_thread(self));
+  struct su_select_register *ser;
 
-  N          = self->sup_n_waits;
-  indices    = self->sup_indices;
-  reverses   = self->sup_reverses;
-  waits      = self->sup_waits; 
-  wait_cbs   = self->sup_wait_cbs; 
-  wait_args  = self->sup_wait_args;
-  wait_roots = self->sup_wait_roots; 
-  
-  for (i = j = 0; i < N; i++) {
-    index = reverses[i]; assert(index > 0 && indices[index] == i);
+  assert(self); assert(root);
+  assert(su_port_own_thread(self));
 
-    if (wait_roots[i] == root) {
-      /* XXX - we should free all resources associated with this, too */
-      if (i < self->sup_pri_offset)
-       self->sup_pri_offset--;
+  I = self->sup_max_index;
 
-      indices[index] = indices[0];
-      indices[0] = -index;
+  for (i = 1, n = 0; i <= I; i++) {
+    ser = self->sup_indices[i];
+    if (ser->ser_root != root)
       continue;
-    }
-
-    if (i != j) {
-      indices[index] = j;
-      reverses[j]   = reverses[i];
-      waits[j]      = waits[i];
-      wait_cbs[j]   = wait_cbs[i];
-      wait_args[j]  = wait_args[i];
-      wait_roots[j] = wait_roots[i];
-    }
-    
-    j++;
-  }
-  
-  for (i = j; i < N; i++) {
-    reverses[i] = -1;
-    wait_cbs[i] = NULL;
-    wait_args[i] = NULL;
-    wait_roots[i] = NULL;
+    su_select_port_deregister0(self, ser->ser_id, 0);
+    n++;
   }
-  memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]);
-
-  self->sup_n_waits = j;
-  self->sup_registers++;
 
-  return N - j;
+  return n;
 }
 
 /**Set mask for a registered event. @internal
  *
- * The function su_select_port_eventmask() sets the mask describing events that can
- * signal the registered callback.
+ * The function su_select_port_eventmask() sets the mask describing events
+ * that can signal the registered callback.
  *
  * @param port   pointer to port object
  * @param index  registration index
@@ -538,19 +477,41 @@ int su_select_port_unregister_all(su_port_t *self,
  * @retval 0 when successful,
  * @retval -1 upon an error.
  */
-int su_select_port_eventmask(su_port_t *self, int index, int socket, int events)
+int su_select_port_eventmask(su_port_t *self,
+                            int index,
+                            int socket, int events)
 {
-  int n;
-  assert(self);
-  assert(su_port_own_thread(self));
+  struct su_select_register *ser;
+
+  if (index <= 0 || index > self->sup_max_index)
+    return su_seterrno(EBADF);
 
-  if (index <= 0 || index > self->sup_size_waits)
+  ser = self->sup_indices[index];
+  if (!ser->ser_cb)
     return su_seterrno(EBADF);
-  n = self->sup_indices[index];
-  if (n < 0)
+
+  if (self->sup_maxfd == 0)
+    su_select_port_update_maxfd(self);
+
+  if (socket >= self->sup_maxfd)
     return su_seterrno(EBADF);
 
-  return su_wait_mask(&self->sup_waits[n], socket, events);
+  if (su_wait_mask(ser->ser_wait, socket, events) < 0)
+    return -1;
+
+  assert(socket < self->sup_maxfd);
+  
+  if (events & SU_WAIT_IN)
+    FD_SET(socket, self->sup_readfds);
+  else
+    FD_CLR(socket, self->sup_readfds);
+
+  if (events & SU_WAIT_OUT)
+    FD_SET(socket, self->sup_writefds);
+  else
+    FD_CLR(socket, self->sup_writefds);
+
+  return 0;
 }
 
 /** @internal Enable multishot mode.
@@ -580,7 +541,7 @@ int su_select_port_multishot(su_port_t *self, int multishot)
 
 
 /** @internal
- * Wait (select()) for wait objects in port.
+ * Wait (poll()) for wait objects in port.
  *
  * @param self     pointer to port
  * @param tout     timeout in milliseconds
@@ -590,78 +551,107 @@ int su_select_port_multishot(su_port_t *self, int multishot)
 static
 int su_select_port_wait_events(su_port_t *self, su_duration_t tout)
 {
-  /* NOT IMPLEMENTED */
-  (void)su_select_port_deinit;
+  int j, n, events = 0;
+  unsigned version = self->sup_registers;
+  size_t bytes;
+  struct timeval tv;
+  fd_set *rset = NULL, *wset = NULL;
 
-  return -1;
-}
+  if (self->sup_maxfd == 0)
+    su_select_port_update_maxfd(self);
 
-#if 0
-/** @internal
- *  Prints out the contents of the port.
- *
- * @param self pointer to a port
- * @param f    pointer to a file (if @c NULL, uses @c stdout).
- */
-void su_port_dump(su_port_t const *self, FILE *f)
-{
-  int i;
-#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
-#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
-#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
-
-  if (f == NULL)
-    f = stdout;
-
-  fprintf(f, "su_port_t at %p:\n", self);
-  fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
-#if SU_HAVE_PTHREADS
-  fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
-  fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
-         IS_WAIT_IN(&self->sup_mbox_wait),
-         IS_WAIT_OUT(&self->sup_mbox_wait),
-         IS_WAIT_ACCEPT(&self->sup_mbox_wait));
-#endif
-  fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
-  for (i = 0; i < self->sup_n_waits; i++) {
-    
+  bytes = self->sup_maxfd ? FDSETSIZE(self->sup_maxfd - 1) : 0;
+
+  if (bytes) {
+    rset = memcpy(self->sup_readfds2, self->sup_readfds, bytes);
+    wset = memcpy(self->sup_writefds2, self->sup_writefds, bytes);
+  }  
+
+  tv.tv_sec = tout / 1000;
+  tv.tv_usec = (tout % 1000) * 1000;
+
+  n = select(self->sup_maxfd, rset, wset, NULL, &tv);
+
+  if (n <= 0) {
+    SU_DEBUG_0(("su_select_port_wait_events(%p): %s (%d)\n",
+               (void *)self, su_strerror(su_errno()), su_errno()));
+    return 0;
   }
-}
 
-#endif
+  for (j = 1; j < self->sup_max_index; j++) {
+    struct su_select_register *ser;
+    su_root_magic_t *magic;
+    int fd;
 
-/** Create a port using select().
+    ser = self->sup_indices[j];
+    if (!ser->ser_cb)
+      continue;
+
+    fd = ser->ser_wait->fd;
+    ser->ser_wait->revents = 0;
+
+    if (ser->ser_wait->events & SU_WAIT_IN)
+      if (FD_ISSET(fd, rset)) ser->ser_wait->revents |= SU_WAIT_IN, n--;
+    if (ser->ser_wait->events & SU_WAIT_OUT)
+      if (FD_ISSET(fd, wset)) ser->ser_wait->revents |= SU_WAIT_OUT, n--;
+
+    if (ser->ser_wait->revents) {
+      magic = ser->ser_root ? su_root_magic(ser->ser_root) : NULL;
+      ser->ser_cb(magic, ser->ser_wait, ser->ser_arg);
+      events++;
+      if (version != self->sup_registers)
+       /* Callback function used su_register()/su_deregister() */
+       return events;
+      if (!self->sup_multishot)
+       /* Callback function used su_register()/su_deregister() */
+       return events;
+    }
+
+    if (n == 0)
+      break;
+  }    
+
+  assert(n == 0);
+
+  return events;
+}
+
+/** Create a port using epoll() or poll().
  */
 su_port_t *su_select_port_create(void)
 {
-#if notyet
-  su_port_t *self = su_home_new(sizeof *self);
+  su_port_t *self;
 
+  self = su_home_new(sizeof *self);
   if (!self)
-    return self;
-
-  if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0)
-    return su_home_unref(su_port_home(self)), NULL;
+    return NULL;
+
+  if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0 ||
+      !(self->sup_indices = 
+       su_zalloc(su_port_home(self),
+                 (sizeof self->sup_indices[0]) * 
+                 (self->sup_size_indices = __NFDBITS)))) {
+    su_home_unref(su_port_home(self));
+    return NULL;
+  }
 
   self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
 
-  if (su_pthread_port_init(self, su_select_port_vtable) < 0)
+  if (su_socket_port_init(self->sup_base, su_select_port_vtable) < 0)
     return su_home_unref(su_port_home(self)), NULL;
 
   return self;
-#else
-  return NULL;
-#endif
 }
 
 int su_select_clone_start(su_root_t *parent,
-                         su_clone_r return_clone,
-                         su_root_magic_t *magic,
-                         su_root_init_f init,
-                         su_root_deinit_f deinit)
+                        su_clone_r return_clone,
+                        su_root_magic_t *magic,
+                        su_root_init_f init,
+                        su_root_deinit_f deinit)
 {
   return su_pthreaded_port_start(su_select_port_create, 
                                 parent, return_clone, magic, init, deinit);
 }
 
+
 #endif
index b74db94b7439c7221e8f0b7e800884def2413106..1cc4d8e51ba3702efa5a8ba52d3cffdf504efd18 100644 (file)
@@ -193,7 +193,10 @@ RBTREE_BODIES(static inline, timers, su_timer_t,
              IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR,
              CMP, INSERT, REMOVE);
 
-/** Set the timer. */
+/**@internal Set the timer. 
+ *
+ * @retval 0 when successful (always)
+ */
 static inline int
 su_timer_set0(su_timer_t **timers,
              su_timer_t *t,
@@ -212,7 +215,10 @@ su_timer_set0(su_timer_t **timers,
   return timers_append(timers, t);
 }
 
-/** Reset the timer. */
+/**@internal Reset the timer. 
+ *
+ * @retval 0 when successful (always)
+ */
 static inline int
 su_timer_reset0(su_timer_t **timers,
                su_timer_t *t)
@@ -229,6 +235,40 @@ su_timer_reset0(su_timer_t **timers,
   return 0;
 }
 
+/**@internal Validate timer @a t and return pointer to per-port timer tree.
+ * 
+ * @retval pointer to pointer to timer tree when successful
+ * @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_t **timers;
+
+  if (t == NULL) {
+    SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
+               "NULL argument"));
+    return NULL;
+  }
+
+  timers = su_task_timers(t->sut_task);
+
+  if (timers == NULL)
+    SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t,
+               "invalid timer"));
+
+  if (use_sut_duration && t->sut_duration == 0) {
+    assert(t->sut_duration > 0);
+    SU_DEBUG_1(("%s(%p): %s\n", caller, (void *)t, 
+               "timer without default duration"));
+    return NULL;
+  }
+
+  return timers;
+}
+
 
 /**Create a timer.
  *
@@ -291,23 +331,12 @@ int su_timer_set_interval(su_timer_t *t,
                          su_timer_arg_t *arg,
                          su_duration_t interval)
 {
-  char const *func = "su_timer_set_interval";
-  su_timer_t **timers;
-
-  if (t == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
-    return -1;
-  }
+  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_interval");
 
-  timers = su_task_timers(t->sut_task);
-  if (timers == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
+  if (t == NULL)
     return -1;
-  }
 
-  su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
-
-  return 0;
+  return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
 }
 
 /** Set the timer for the default interval.
@@ -326,19 +355,12 @@ int su_timer_set(su_timer_t *t,
                 su_timer_f wakeup,
                 su_timer_arg_t *arg)
 {
-  char const *func = "su_timer_set";
+  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set");
 
-  if (t == NULL)
+  if (timers == NULL)
     return -1;
 
-  assert(t->sut_duration > 0);
-  if (t->sut_duration == 0) {
-    SU_DEBUG_0(("%s(%p): %s\n", func, (void *)t,
-               "timer without default duration"));
-    return -1;
-  }
-
-  return su_timer_set_interval(t, wakeup, arg, t->sut_duration);
+  return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
 }
 
 /** Set timer at known time.
@@ -357,23 +379,12 @@ int su_timer_set_at(su_timer_t *t,
                    su_wakeup_arg_t *arg,
                    su_time_t when)
 {
-  char const *func = "su_timer_set_at";
-  su_timer_t **timers;
-
-  if (t == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
-    return -1;
-  }
+  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_at");
 
-  timers = su_task_timers(t->sut_task);
-  if (timers == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
+  if (timers == NULL)
     return -1;
-  }
 
-  su_timer_set0(timers, t, wakeup, arg, when, 0);
-
-  return 0;
+  return su_timer_set0(timers, t, wakeup, arg, when, 0);
 }
 
 /** Set the timer for regular intervals.
@@ -398,35 +409,17 @@ int su_timer_run(su_timer_t *t,
                 su_timer_f wakeup,
                 su_timer_arg_t *arg)
 {
-  char const *func = "su_timer_run";
-  su_timer_t **timers;
-  su_time_t now = su_now();
+  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_run");
+  su_time_t now;
 
-  if (t == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
+  if (timers == NULL)
     return -1;
-  }
-
-  assert(t->sut_duration > 0);
-  if (t->sut_duration == 0) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
-               "timer without default duration"));
-    return -1;
-  }
-
-  timers = su_task_timers(t->sut_task);
-  if (timers == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
-    return -1;
-  }
 
   t->sut_running = run_at_intervals;
-  t->sut_run = now;
+  t->sut_run = now = su_now();
   t->sut_woken = 0;
 
-  su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
-
-  return 0;
+  return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
 }
 
 /**Set the timer for regular intervals.
@@ -449,35 +442,17 @@ int su_timer_set_for_ever(su_timer_t *t,
                          su_timer_f wakeup,
                          su_timer_arg_t *arg)
 {
-  char const *func = "su_timer_set_for_ever";
-  su_timer_t **timers;
-  su_time_t now = su_now();
+  su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
+  su_time_t now;
 
-  if (t == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
-    return -1;
-  }
-
-  assert(t->sut_duration > 0);
-  if (t->sut_duration == 0) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t,
-               "timer without default duration"));
+  if (timers == NULL)
     return -1;
-  }
-
-  timers = su_task_timers(t->sut_task);
-  if (timers == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
-    return -1;
-  }
 
   t->sut_running = run_for_ever;
-  t->sut_run = now;
+  t->sut_run = now = su_now();
   t->sut_woken = 0;
 
-  su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
-
-  return 0;
+  return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
 }
 
 /**Reset the timer.
@@ -490,19 +465,12 @@ int su_timer_set_for_ever(su_timer_t *t,
  */
 int su_timer_reset(su_timer_t *t)
 {
-  char const *func = "su_timer_reset";
-  su_timer_t **timers;
+  su_timer_t **timers = su_timer_tree(t, 0, "su_timer_reset");
 
-  if (t == NULL) {
-    SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
+  if (timers == NULL)
     return -1;
-  }
 
-  timers = su_task_timers(t->sut_task);
-
-  su_timer_reset0(timers, t);
-
-  return 0;
+  return su_timer_reset0(timers, t);
 }
 
 /** @internal Check for expired timers in queue.
@@ -576,6 +544,7 @@ int su_timer_expire(su_timer_t ** const timers,
 }
 
 
+/** Calculate duration in milliseconds until next timer expires. */
 su_duration_t su_timer_next_expires(su_timer_t const * t, su_time_t now)
 {
   su_duration_t tout;
@@ -625,14 +594,13 @@ int su_timer_reset_all(su_timer_t **timers, su_task_r task)
 
 /** Get the root object owning the timer.
  *
- *   The function su_timer_root() return pointer to the root object owning the
- *   timer.
+ * Return pointer to the root object owning the timer.
  *
  * @param t pointer to the timer
  *
- * @return Pointer to the root object owning the timer.
+ * @return Pointer to the root object.
  */
 su_root_t *su_timer_root(su_timer_t const *t)
 {
-  return su_task_root(t->sut_task);
+  return t ? su_task_root(t->sut_task) : NULL;
 }
index ba201647f10d525e4a9b18a9cf3273f80b456b7b..02ff3f46c4d2d3de35904b6e809731e38ca5e8cb 100644 (file)
  */
 
 /**@ingroup su_wait
- * @CFILE su_poll_port.c
+ * @CFILE su_win32_port.c
  *
- * Port implementation using poll()
+ * Port implementation using WSAEVENTs
  *
  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  * @author Kai Vehmanen <kai.vehmanen@nokia.com>
  *
- * @date Created: Tue Sep 14 15:51:04 1999 ppessi
+ * @date Created: Mon Feb  5 20:29:21 2007 ppessi
+ * @date Original: Tue Sep 14 15:51:04 1999 ppessi
  */
 
 #include "config.h"
 
-#if HAVE_POLL || HAVE_WIN32
+#define su_port_s su_wsaevent_port_s
+
+#include "sofia-sip/su.h"
+#include "su_port.h"
+#include "sofia-sip/su_alloc.h"
 
 #include <stdlib.h>
 #include <assert.h>
 #include <limits.h>
 #include <errno.h>
 
-#define su_port_s su_poll_port_s
+/** Port based on su_wait() aka WSAWaitForMultipleEvents. */
 
-#include "sofia-sip/su.h"
-#include "su_port.h"
-#include "sofia-sip/su_alloc.h"
-
-/** Port based on poll(). */
+#define INDEX_MAX (64)
 
-struct su_poll_port_s {
-  su_pthread_port_t sup_base[1];
+struct su_wsaevent_port_s {
+  su_socket_port_t sup_base[1];
 
-#define sup_home sup_base->sup_base->sup_home
+#define sup_home sup_base->sup_base->sup_base->sup_home
 
   unsigned         sup_multishot; /**< Multishot operation? */
 
@@ -69,13 +70,6 @@ struct su_poll_port_s {
   int              sup_size_waits; /**< Size of allocated su_waits */
   int              sup_pri_offset; /**< Offset to prioritized waits */
 
-#if !SU_HAVE_WINSOCK
-#define INDEX_MAX (0x7fffffff)
-#else 
-  /* We use WSAWaitForMultipleEvents() */
-#define INDEX_MAX (64)
-#endif
-
   /** Indices from index returned by su_root_register() to tables below. 
    *
    * Free elements are negative. Free elements form a list, value of free
@@ -93,43 +87,43 @@ struct su_poll_port_s {
 
 };
 
-static void su_poll_port_decref(su_port_t *, int blocking, char const *who);
+static void su_wsevent_port_decref(su_port_t *, int blocking, char const *who);
 
-static int su_poll_port_register(su_port_t *self,
+static int su_wsevent_port_register(su_port_t *self,
                                 su_root_t *root, 
                                 su_wait_t *wait, 
                                 su_wakeup_f callback,
                                 su_wakeup_arg_t *arg,
                                 int priority);
-static int su_poll_port_unregister(su_port_t *port,
+static int su_wsevent_port_unregister(su_port_t *port,
                                   su_root_t *root, 
                                   su_wait_t *wait,     
                                   su_wakeup_f callback, 
                                   su_wakeup_arg_t *arg);
-static int su_poll_port_deregister(su_port_t *self, int i);
-static int su_poll_port_unregister_all(su_port_t *self, su_root_t *root);
-static int su_poll_port_eventmask(su_port_t *self, 
+static int su_wsevent_port_deregister(su_port_t *self, int i);
+static int su_wsevent_port_unregister_all(su_port_t *self, su_root_t *root);
+static int su_wsevent_port_eventmask(su_port_t *self, 
                                  int index,
                                  int socket,
                                  int events);
-static int su_poll_port_multishot(su_port_t *self, int multishot);
-static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout);
-static char const *su_poll_port_name(su_port_t const *self);
+static int su_wsevent_port_multishot(su_port_t *self, int multishot);
+static int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout);
+static char const *su_wsevent_port_name(su_port_t const *self);
 
-su_port_vtable_t const su_poll_port_vtable[1] =
+su_port_vtable_t const su_wsevent_port_vtable[1] =
   {{
-      /* su_vtable_size: */ sizeof su_poll_port_vtable,
+      /* su_vtable_size: */ sizeof su_wsevent_port_vtable,
       su_pthread_port_lock,
       su_pthread_port_unlock,
       su_base_port_incref,
-      su_poll_port_decref,
+      su_wsevent_port_decref,
       su_base_port_gsource,
-      su_pthread_port_send,
-      su_poll_port_register,
-      su_poll_port_unregister,
-      su_poll_port_deregister,
-      su_poll_port_unregister_all,
-      su_poll_port_eventmask,
+      su_socket_port_send,
+      su_wsevent_port_register,
+      su_wsevent_port_unregister,
+      su_wsevent_port_deregister,
+      su_wsevent_port_unregister_all,
+      su_wsevent_port_eventmask,
       su_base_port_run,
       su_base_port_break,
       su_base_port_step,
@@ -137,33 +131,33 @@ su_port_vtable_t const su_poll_port_vtable[1] =
       su_base_port_add_prepoll,
       su_base_port_remove_prepoll,
       su_base_port_timers,
-      su_poll_port_multishot,
+      su_wsevent_port_multishot,
       su_base_port_threadsafe,
       su_base_port_yield,
-      su_poll_port_wait_events,
+      su_wsevent_port_wait_events,
       su_base_port_getmsgs,
       su_base_port_getmsgs_from,
-      su_poll_port_name,
+      su_wsevent_port_name,
       su_base_port_start_shared,
       su_pthread_port_wait,
       su_pthread_port_execute,
     }};
 
-static char const *su_poll_port_name(su_port_t const *self)
+static char const *su_wsevent_port_name(su_port_t const *self)
 {
   return "poll";
 }
 
-static void su_poll_port_deinit(void *arg)
+static void su_wsevent_port_deinit(void *arg)
 {
   su_port_t *self = arg;
 
-  SU_DEBUG_9(("%s(%p) called\n", "su_poll_port_deinit", self));
+  SU_DEBUG_9(("%s(%p) called\n", "su_wsevent_port_deinit", self));
 
-  su_pthread_port_deinit(self);
+  su_socket_port_deinit(self->sup_base);
 }
 
-static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
+static void su_wsevent_port_decref(su_port_t *self, int blocking, char const *who)
 {
   su_base_port_decref(self, blocking, who);
 }
@@ -189,7 +183,7 @@ static void su_poll_port_decref(su_port_t *self, int blocking, char const *who)
  *   Positive index of the wait object, 
  *   or -1 upon an error.
  */
-int su_poll_port_register(su_port_t *self,
+int su_wsevent_port_register(su_port_t *self,
                          su_root_t *root, 
                          su_wait_t *wait, 
                          su_wakeup_f callback,
@@ -311,7 +305,7 @@ int su_poll_port_register(su_port_t *self,
 }
 
 /** Deregister a su_wait_t object. */
-static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
+static int su_wsevent_port_deregister0(su_port_t *self, int i, int destroy_wait)
 {
   int n, N, *indices, *reverses;
 
@@ -372,9 +366,8 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
 
 /** Unregister a su_wait_t object.
  *  
- *  The function su_poll_port_unregister() unregisters a su_wait_t object. The
- *  wait object, a callback function and a argument are removed from the
- *  port object.
+ * Unregisters a su_wait_t object. The wait object, a callback function and
+ * a argument are removed from the port object.
  * 
  * @param self     - pointer to port object
  * @param root     - pointer to root object
@@ -383,11 +376,11 @@ static int su_poll_port_deregister0(su_port_t *self, int i, int destroy_wait)
  * @param arg      - argument given to callback function when it is invoked 
  *                   (may be NULL)
  *
- * @deprecated Use su_poll_port_deregister() instead. 
+ * @deprecated Use su_wsevent_port_deregister() instead. 
  *
  * @return Nonzero index of the wait object, or -1 upon an error.
  */
-int su_poll_port_unregister(su_port_t *self,
+int su_wsevent_port_unregister(su_port_t *self,
                            su_root_t *root, 
                            su_wait_t *wait,    
                            su_wakeup_f callback, /* XXX - ignored */
@@ -402,7 +395,7 @@ int su_poll_port_unregister(su_port_t *self,
 
   for (n = 0; n < N; n++) {
     if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) {
-      return su_poll_port_deregister0(self, self->sup_reverses[n], 0);
+      return su_wsevent_port_deregister0(self, self->sup_reverses[n], 0);
     }
   }
 
@@ -422,7 +415,7 @@ int su_poll_port_unregister(su_port_t *self,
  * 
  * @return Index of the wait object, or -1 upon an error.
  */
-int su_poll_port_deregister(su_port_t *self, int i)
+int su_wsevent_port_deregister(su_port_t *self, int i)
 {
   su_wait_t wait[1] = { SU_WAIT_INIT };
   int retval;
@@ -436,7 +429,7 @@ int su_poll_port_deregister(su_port_t *self, int i)
   if (self->sup_indices[i] < 0)
     return su_seterrno(EBADF);
     
-  retval = su_poll_port_deregister0(self, i, 1);
+  retval = su_wsevent_port_deregister0(self, i, 1);
 
   su_wait_destroy(wait);
 
@@ -447,15 +440,15 @@ int su_poll_port_deregister(su_port_t *self, int i)
 /** @internal
  * Unregister all su_wait_t objects.
  *
- * The function su_poll_port_unregister_all() unregisters all su_wait_t objects
- * and destroys all queued timers associated with given root object.
+ * Unregisters all su_wait_t objects and destroys all queued timers
+ * associated with given root object.
  * 
  * @param  self     - pointer to port object
  * @param  root     - pointer to root object
  * 
  * @return Number of wait objects removed.
  */
-int su_poll_port_unregister_all(su_port_t *self, 
+int su_wsevent_port_unregister_all(su_port_t *self, 
                                su_root_t *root)
 {
   int i, j, index, N;
@@ -516,8 +509,7 @@ int su_poll_port_unregister_all(su_port_t *self,
 
 /**Set mask for a registered event. @internal
  *
- * The function su_poll_port_eventmask() sets the mask describing events that can
- * signal the registered callback.
+ * Sets the mask describing events that can signal the registered callback.
  *
  * @param port   pointer to port object
  * @param index  registration index
@@ -527,7 +519,7 @@ int su_poll_port_unregister_all(su_port_t *self,
  * @retval 0 when successful,
  * @retval -1 upon an error.
  */
-int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
+int su_wsevent_port_eventmask(su_port_t *self, int index, int socket, int events)
 {
   int n;
   assert(self);
@@ -557,7 +549,7 @@ int su_poll_port_eventmask(su_port_t *self, int index, int socket, int events)
  * @retval -1 an error occurred
  */
 static
-int su_poll_port_multishot(su_port_t *self, int multishot)
+int su_wsevent_port_multishot(su_port_t *self, int multishot)
 {
   if (multishot < 0)
     return self->sup_multishot;
@@ -577,7 +569,7 @@ int su_poll_port_multishot(su_port_t *self, int multishot)
  * @return number of events handled
  */
 static
-int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
+int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout)
 {
   int i, events = 0;
   su_wait_t *waits = self->sup_waits;
@@ -620,68 +612,32 @@ int su_poll_port_wait_events(su_port_t *self, su_duration_t tout)
   return events;
 }
 
-#if 0
-/** @internal
- *  Prints out the contents of the port.
- *
- * @param self pointer to a port
- * @param f    pointer to a file (if @c NULL, uses @c stdout).
- */
-void su_port_dump(su_port_t const *self, FILE *f)
-{
-  int i;
-#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
-#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
-#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
-
-  if (f == NULL)
-    f = stdout;
-
-  fprintf(f, "su_port_t at %p:\n", self);
-  fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
-#if SU_HAVE_PTHREADS
-  fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
-  fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
-         IS_WAIT_IN(&self->sup_mbox_wait),
-         IS_WAIT_OUT(&self->sup_mbox_wait),
-         IS_WAIT_ACCEPT(&self->sup_mbox_wait));
-#endif
-  fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
-  for (i = 0; i < self->sup_n_waits; i++) {
-    
-  }
-}
-
-#endif
-
-/** Create a port using epoll() or poll().
- */
-su_port_t *su_poll_port_create(void)
+/** Create a port using WSAEVENTs and WSAWaitForMultipleEvents. */
+su_port_t *su_wsaevent_port_create(void)
 {
   su_port_t *self = su_home_new(sizeof *self);
 
   if (!self)
     return self;
 
-  if (su_home_destructor(su_port_home(self), su_poll_port_deinit) < 0)
+  if (su_home_destructor(su_port_home(self), su_wsevent_port_deinit) < 0)
     return su_home_unref(su_port_home(self)), NULL;
 
   self->sup_multishot = SU_ENABLE_MULTISHOT_POLL;
 
-  if (su_pthread_port_init(self, su_poll_port_vtable) < 0)
+  if (su_socket_port_init(self->sup_base, su_wsevent_port_vtable) < 0)
     return su_home_unref(su_port_home(self)), NULL;
 
   return self;
 }
 
-int su_poll_clone_start(su_root_t *parent,
-                       su_clone_r return_clone,
-                       su_root_magic_t *magic,
-                       su_root_init_f init,
-                       su_root_deinit_f deinit)
+int su_wsaevent_clone_start(su_root_t *parent,
+                           su_clone_r return_clone,
+                           su_root_magic_t *magic,
+                           su_root_init_f init,
+                           su_root_deinit_f deinit)
 {
-  return su_pthreaded_port_start(su_poll_port_create, 
+  return su_pthreaded_port_start(su_wsaevent_port_create, 
                                 parent, return_clone, magic, init, deinit);
 }
 
-#endif  /* HAVE_POLL */
index f18331bf5805cb5c2c93816ee15efe69eb328987..b38d116754b4938b8b980e8c657fbbc05d79abd8 100644 (file)
@@ -100,7 +100,7 @@ int test_sockaddr(void)
   TEST(su_setblocking(s, 1), 0);
   TEST(su_close(s), 0);
 
-  su_freelocalinfo(res);
+  su_freelocalinfo(res), res = NULL;
 
 #if SU_HAVE_IN6
   hints->li_family = AF_INET6;
@@ -111,16 +111,17 @@ int test_sockaddr(void)
   for (li = res; li; li = li->li_next)
     TEST(li->li_family, AF_INET6);
 
-  su_freelocalinfo(res);
+  su_freelocalinfo(res), res = NULL;
 #endif
 
   hints->li_flags |= LI_NUMERIC;
   TEST(su_getlocalinfo(hints, &res), 0);
+  su_freelocalinfo(res), res = NULL;
 
-  hints->li_flags |= LI_NAMEREQD;
   res = NULL;
+  hints->li_flags |= LI_NAMEREQD;
   su_getlocalinfo(hints, &res);
-  su_freelocalinfo(res);
+  su_freelocalinfo(res), res = NULL;
 
   memset(a, 0, sizeof *a); 
   memset(b, 0, sizeof *b); 
@@ -161,7 +162,7 @@ int test_sockaddr(void)
 
 int test_sendrecv(void)
 {
-  int s, l, a;
+  su_socket_t s, l, a;
   int n;
   su_sockaddr_t su, csu;
   socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin;
@@ -260,6 +261,120 @@ int test_sendrecv(void)
   END();
 }
 
+#if HAVE_SELECT 
+
+#if HAVE_WIN32
+int test_select(void)
+{
+  return 0;
+}
+#else
+
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#elif HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifndef __NFDBITS
+#define __NFDBITS (8 * sizeof (long int))
+#endif
+
+#undef howmany
+/* Size of fd set in bytes. Sorry, octets. */
+#define howmany(n) (((n) + __NFDBITS - 1) / __NFDBITS * (__NFDBITS / 8))
+
+#define FD_ZERO_TO(maxfd, set) \
+  memset((set), 0, howmany(maxfd))
+
+/* Test assumptions in su_select_port implementation */
+int test_select(void)
+{
+  su_socket_t s;
+  su_sockaddr_t su;
+  socklen_t sulen = sizeof su.su_sin;
+  size_t bytes;
+  fd_set *rset, *wset;
+  struct timeval tv;
+
+  BEGIN();
+
+  s = su_socket(AF_INET, SOCK_DGRAM, 0); TEST_1(s != -1);
+
+  memset(&su, 0, sulen);
+  su.su_len = sulen;
+  su.su_family = AF_INET;
+  TEST(inet_pton(AF_INET, "127.0.0.1", &su.su_sin.sin_addr), 1);
+  TEST(bind(s, &su.su_sa, sulen), 0);
+  TEST(getsockname(s, &su.su_sa, &sulen), 0);
+  
+  tv.tv_sec = 0; tv.tv_usec = 1000;
+  TEST(select(0, NULL, NULL, NULL, &tv), 0);
+
+  bytes = howmany(s);
+  TEST_1(rset = malloc(bytes));
+  TEST_1(wset = malloc(bytes));
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); FD_SET(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, NULL, wset, NULL, &tv), 1);
+  TEST_1(FD_ISSET(s, wset));
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); 
+  FD_SET(s, rset); FD_SET(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, rset, wset, NULL, &tv), 1);
+  TEST_1(!FD_ISSET(s, rset));
+  TEST_1(FD_ISSET(s, wset));
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); 
+  FD_SET(s, rset); FD_SET(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, rset, NULL, NULL, &tv), 0);
+  TEST_1(!FD_ISSET(s, rset));
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); 
+  FD_SET(s, rset); FD_CLR(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, rset, wset, NULL, &tv), 0);
+  TEST_1(!FD_ISSET(s, rset));
+  TEST_1(!FD_ISSET(s, wset));
+
+  TEST(su_sendto(s, "foo", 3, 0, &su, sulen), 3);
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); 
+  FD_SET(s, rset); FD_CLR(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, rset, wset, NULL, &tv), 1);
+  TEST_1(FD_ISSET(s, rset));
+  TEST_1(!FD_ISSET(s, wset));
+
+  FD_ZERO_TO(s, rset); FD_ZERO_TO(s, wset); 
+  FD_SET(s, rset); FD_SET(s, wset);
+  tv.tv_sec = 0, tv.tv_usec = 1000;
+  TEST(select(s + 1, rset, wset, NULL, &tv), 2);
+  TEST_1(FD_ISSET(s, rset));
+  TEST_1(FD_ISSET(s, wset));
+
+  su_close(s);
+
+  free(wset);
+  free(rset);
+
+  END();
+}
+#endif
+
+#else
+int test_select(void)
+{
+  return 0;
+}
+#endif
+
 #include <sofia-sip/su_md5.h>
 
 int test_md5(void)
@@ -395,10 +510,10 @@ int main(int argc, char *argv[])
   
   retval |= test_sockaddr();
   retval |= test_sendrecv();
+  retval |= test_select();
   retval |= test_md5(); fflush(stdout);
 
   su_deinit();
 
   return retval;
 }
-
index 08152b9e2d92170f9585c820be6523584945a4ec..2e17193097a0fbf0dee2ba80022139c996ccd2fa 100644 (file)
@@ -533,10 +533,30 @@ void usage(void)
 
 int main(int argc, char *argv[])
 {
-  root_test_t rt[1] = {{{ SU_HOME_INIT(rt) }}};
+  root_test_t *rt, rt0[1] = {{{ SU_HOME_INIT(rt0) }}}, rt1[1];
   int retval = 0;
   int i;
 
+  struct {
+    su_port_create_f *create;
+    su_clone_start_f *start;
+    char const *preference;
+  } prefer[] =
+      {
+       { NULL, NULL, "default" },
+#if HAVE_POLL_PORT
+#if HAVE_EPOLL
+       { su_epoll_port_create, su_epoll_clone_start, "epoll", },
+#endif
+       { su_poll_port_create, su_poll_clone_start, "poll" },
+#endif
+#if HAVE_SELECT
+       { su_select_port_create, su_select_clone_start, "select" },
+#endif
+       { NULL, NULL }
+      };
+
+  rt = rt0;
   rt->rt_family = AF_INET;
 
   for (i = 1; argv[i]; i++) {
@@ -550,14 +570,23 @@ int main(int argc, char *argv[])
       usage();
   }
 
-  retval |= init_test(rt);
-  retval |= register_test(rt);
-  retval |= event_test(rt);
-  su_root_threading(rt->rt_root, 1);
-  retval |= clone_test(rt);
-  su_root_threading(rt->rt_root, 0);
-  retval |= clone_test(rt);
-  retval |= deinit_test(rt);
+  i = 0;
+
+  do {
+    rt = rt1, *rt = *rt0;
+    printf("%s: testing %s implementation\n",
+          name, prefer[i].preference);
+    su_port_prefer(prefer[i].create, prefer[i].start);
+
+    retval |= init_test(rt);
+    retval |= register_test(rt);
+    retval |= event_test(rt);
+    su_root_threading(rt->rt_root, 1);
+    retval |= clone_test(rt);
+    su_root_threading(rt->rt_root, 0);
+    retval |= clone_test(rt);
+    retval |= deinit_test(rt);
+  } while (prefer[++i].create);
 
   return retval;
 }
index f46bc6f19450d3e73b8ae0fcc650decf0f5221a9..402331f496625faee106024196c586f4615fa0d6 100644 (file)
@@ -1117,7 +1117,7 @@ int tport_get_params(tport_t const *self,
     || !tport_is_primary(self) || !tport_is_dgram(self);
 
   n = tl_tgets(ta_args(ta),
-              TPTAG_MTU(tpp->tpp_mtu),
+              TPTAG_MTU((usize_t)tpp->tpp_mtu),
               TPTAG_REUSE(self->tp_reusable),
               TPTAG_CONNECT(connect),
               TPTAG_QUEUESIZE(tpp->tpp_qsize),
@@ -1153,14 +1153,16 @@ int tport_set_params(tport_t *self,
   ta_list ta;
   int n;
   tport_params_t tpp[1], *tpp0;
-
+  
+  usize_t mtu;
   int connect, sdwn_error, reusable, stun_server;
-
+  
   if (self == NULL)
     return su_seterrno(EINVAL);
 
   memcpy(tpp, tpp0 = self->tp_params, sizeof *tpp);
 
+  mtu = tpp->tpp_mtu;
   connect = tpp->tpp_conn_orient;
   sdwn_error = tpp->tpp_sdwn_error;
   reusable = self->tp_reusable;
@@ -1169,7 +1171,7 @@ int tport_set_params(tport_t *self,
   ta_start(ta, tag, value);
 
   n = tl_gets(ta_args(ta),
-             TPTAG_MTU_REF(tpp->tpp_mtu),
+             TPTAG_MTU_REF(mtu),
              TAG_IF(!self->tp_queue, TPTAG_QUEUESIZE_REF(tpp->tpp_qsize)),
              TPTAG_IDLE_REF(tpp->tpp_idle),
              TPTAG_TIMEOUT_REF(tpp->tpp_timeout),
@@ -1202,6 +1204,9 @@ int tport_set_params(tport_t *self,
   if (tpp->tpp_qsize >= 1000)
     tpp->tpp_qsize = 1000;
 
+  if (mtu > UINT_MAX)
+    mtu = UINT_MAX;
+  tpp->tpp_mtu = (unsigned)mtu;
   /* Currently only primary UDP transport can *not* be connection oriented */ 
   tpp->tpp_conn_orient = connect; 
   tpp->tpp_sdwn_error = sdwn_error;
index c0b9f9ef0843eaa58ac7ad33d14b16f08adae980..8d10097d798196df588f56da38094b7e7503960d 100644 (file)
 #undef HAVE_INTTYPES_H
 
 /* Define to 1 if you have the <iphlpapi.h> header file. */
-// XXX: vehmanek-win32-fix:
+#if _MSC_VER > 1200 
+#define HAVE_IPHLPAPI_H 1
+#else
+// XXX: vehmanek-win32-fix for VC6
 #undef HAVE_IPHLPAPI_H
+#endif
 
 /* Define to 1 if you have IPV6_RECVERR in <netinet/in6.h> */
 #undef HAVE_IPV6_RECVERR
 #undef HAVE_POLL
 
 /* Define to 1 if you use poll in su_port. */
-#define HAVE_POLL_PORT 1
+#undef HAVE_POLL_PORT
 
 /* Define to 1 if you have /proc/net/if_inet6 control file */
 #undef HAVE_PROC_NET_IF_INET6
index e95673a7c4c21e21020ce530cd572b97457d4783..0f3cfe6853f9612dc9ccb0c49aa05c5b9025ec37 100644 (file)
@@ -57,6 +57,7 @@
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                                WarnAsError="true"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\su_socket_port.c"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c"\r
                                        >\r
index c0ee45fc164400498d681fd271d39241ea77066c..7b0cbf38c4b2a6b5ab91839928de7c4983ba942b 100644 (file)
@@ -63,6 +63,7 @@
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
@@ -77,7 +78,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib advapi32.lib"\r
+                               AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"\r
                                OutputFile=".\Debug/libsofia_sip_ua.dll"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
                                WarnAsError="true"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib"\r
+                               AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"\r
                                OutputFile=".\Release/libsofia_sip_ua.dll"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
                                                />\r
                                        </FileConfiguration>\r
                                </File>\r
+                               <File\r
+                                       RelativePath="..\..\libsofia-sip-ua\su\su_socket_port.c"\r
+                                       >\r
+                               </File>\r
                                <File\r
                                        RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c"\r
                                        >\r
index d58de10d9f15d40236c16dda2845b49069417af7..d686df4caa76ce389f054ab7914836575b1262a7 100644 (file)
@@ -62,6 +62,7 @@
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
                                DebugInformationFormat="4"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
                                WarnAsError="true"\r
                                SuppressStartupBanner="true"\r
                                Detect64BitPortabilityProblems="true"\r
+                               CompileAs="1"\r
                        />\r
                        <Tool\r
                                Name="VCManagedResourceCompilerTool"\r
index 4c6b680dd83d2d00c4910699edfc0000d7d9b074..51a4624f67a93c54236972f1a53b9a1592284237 100644 (file)
@@ -76,7 +76,7 @@
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib"\r
+                               AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"\r
                                OutputFile=".\Release/sip_options_static.exe"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="ws2_32.lib advapi32.lib"\r
+                               AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"\r
                                OutputFile=".\Debug/sip_options_static.exe"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r