sync back up again with sofia tree prior to their release

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4177 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris 2007-02-09 17:32:17 +00:00
parent f359f847f7
commit 666bd3bec3
55 changed files with 1807 additions and 2097 deletions

View File

@ -10,6 +10,8 @@ Contributors (in alphabetical order, surname first)
Chan, Tat <first.surname@nokia.com> Chan, Tat <first.surname@nokia.com>
Ciarkowski, Andrzej <wp-voigtkampff -at users -dot sourceforge -dot net> 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> Haataja, Mikko <first.surname@nokia.com>
Jacobs, Remeres <first.surname@nokia.com> Jacobs, Remeres <first.surname@nokia.com>
Jalava, Teemu <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> Whittaker, Colin <colinw -at occamnetworks -dot com>
Zabaluev, Mikhail <first.surname@nokia.com> Zabaluev, Mikhail <first.surname@nokia.com>
Note: for details on who did what, see the version control Note: for details on who did what, see the version control
system change history, and release notes for past releases at system change history, and release notes for past releases at
http://sofia-sip.sourceforge.net/relnotes/ http://sofia-sip.sourceforge.net/relnotes/

View File

@ -221,3 +221,31 @@ other special, indirect and consequential damages, even if author has
been advised of the possibility of such damages. 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.
----------------------------------------------------------------------------

View File

@ -5,21 +5,17 @@ Release notes for current version of Sofia-SIP
Changes since last release Changes since last release
-------------------------- --------------------------
<changes since last written in freshmeat.net "Changes:" style; Support for request queuing has been added to the high-level user-agent
and in less than 10 lines /> API. Various portability improvements have been made related to Linux,
Mac OS X, Windows and Solaris ports. SIP registrations have been
Bugs in blaa and foo have been fixed. The stack now supports modified to utilize persistent transport connections. The GObject
use of foobar... 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 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. New features in API are marked with Doxytag macro @NEW_1_12_5.
Experimental features are marked with Doxytag macro @EXP_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 - Added sip_is_allowed() function and k_bitmap field to the
sip_allow_t structure sip_allow_t structure
- Added sl_header_log implementation, updated its prototype - Added sl_header_log implementation, updated its prototype
- Added experimental SIP headers and related functions, - Added experimental SIP headers Suppress-Notify-If-Match and
enabled with ./configure option --enable-experimental Suppress-Body-If-Match and functions related to them,
enabled with ./configure option --enable-experimental
- Added SIP header Refer-Sub and related functions - Added SIP header Refer-Sub and related functions
- Added <sofia-sip/sip_extra.h> include file - Added <sofia-sip/sip_extra.h> include file
- Added auc_info() function (sofia-sip/auth_client.h) - 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 is now considered stable and will be API/ABI compatible with later
releases in the 1.12.x series. releases in the 1.12.x series.
- ABI has been modified and applications built against 1.12.4 and earlier - 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 - Added su_glib_prefer_gsource() which makes glib-based su_port_t
implementation the default choice when su_root_create() is called implementation the default choice when su_root_create() is called
Contributors to this release 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) - 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) - Michael Jerris (patch to url parsing # in sip/sips userpart)
- Colin Whittaker (TPTAG_TOS()) - Colin Whittaker (TPTAG_TOS())
- Roman Filonenko (TPTAG_LOG(), TPTAG_DUMP(), - Roman Filonenko (TPTAG_LOG(), TPTAG_DUMP(),
patch to query DNS-servers with IP-Helper on win32) 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. See the AUTHORS file in the distribution package.
Notes on new features 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 - nua now supports request queuing, for instance, an application can send
overlapping BYE and NOTIFY requests. The stack engine takes care of overlapping BYE and NOTIFY requests. The stack engine takes care of
sending the new request only after the previous one has been responded. 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 STUN and HTTP support. See 'docs/devel_platform_notes.txt' for some
additional notes to distributors. 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 Bugs fixed in this release
-------------------------- --------------------------
< notable bugs fixed in this release - Fixed su_from_create() returning a sip_to_t instance. Problem reported by
- check the sf.net bug tracker; see closed bugs, Ludovico Cavedon.
sorted by closing date - Partially fixed problem #1633969 with too frequent timer
- other bugs as fixed in CVS/darcs
/>
- **template**: #9499652 sf.net bug item title
- Fixed problem in dialog matching. Problem reported by Fabio Margarido. - Fixed problem in dialog matching. Problem reported by Fabio Margarido.
- Fixed #1624446 - su_wait_clone() (and nua_destroy()) blocking for ever if - Fixed #1624446 - su_wait_clone() (and nua_destroy()) blocking for ever if
the root object was created using su_glib the root object was created using su_glib

View File

@ -6,7 +6,8 @@ Changes since last release
-------------------------- --------------------------
<changes since last written in freshmeat.net "Changes:" style; <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 Bugs in blaa and foo have been fixed. The stack now supports
use of foobar... use of foobar...
@ -39,9 +40,11 @@ Contributors to this release
<list of people who contributed to _this_ release <list of people who contributed to _this_ release
- update as people's patches are added, or when you commit stuff - 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), - 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 - roughly sorted by number of patches accepted
/> />

View File

@ -11,14 +11,14 @@ dnl information on the package
dnl --------------------------- dnl ---------------------------
dnl update both the version for AC_INIT and the LIBSOFIA_SIP_UA_MAJOR_MINOR 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_CONFIG_SRCDIR([libsofia-sip-ua/sip/sofia-sip/sip.h])
AC_SUBST(VER_LIBSOFIA_SIP_UA_MAJOR_MINOR, [1.12]) AC_SUBST(VER_LIBSOFIA_SIP_UA_MAJOR_MINOR, [1.12])
dnl Includedir specific to this sofia version dnl Includedir specific to this sofia version
AC_SUBST(include_sofiadir, '${includedir}/sofia-sip-1.12') 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_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_SOVER, [0]) # CUR-AGE
AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_CUR, [3]) AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_CUR, [3])
AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_REV, [0]) AC_SUBST(LIBVER_SOFIA_SIP_UA_GLIB_REV, [0])

View 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> 2006-09-26 Kai Vehmanen <kai.vehmanen@nokia.com>
* libsofia-sip-ua interface v2 frozen (2:0:2) for the 1.12.2 release * libsofia-sip-ua interface v2 frozen (2:0:2) for the 1.12.2 release

View File

@ -61,9 +61,9 @@ char const http_version_1_0[] = "HTTP/1.0";
/** HTTP version 0.9 is an empty string. */ /** HTTP version 0.9 is an empty string. */
char const http_version_0_9[] = ""; 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; return http_mclass;
} }

View File

@ -95,7 +95,7 @@ SOFIAPUBVAR char const http_version_1_1[];
*/ */
/** HTTP parser description. */ /** HTTP parser description. */
SOFIAPUBFUN msg_mclass_t *http_default_mclass(void); SOFIAPUBFUN msg_mclass_t const *http_default_mclass(void);
/** Complete a HTTP request. */ /** Complete a HTTP request. */
SOFIAPUBFUN int http_request_complete(msg_t *msg); SOFIAPUBFUN int http_request_complete(msg_t *msg);

View File

@ -76,7 +76,7 @@ static int http_tag_test(void);
static int test_query_parser(void); static int test_query_parser(void);
static msg_t *read_message(char const string[]); static msg_t *read_message(char const string[]);
msg_mclass_t *test_mclass = NULL; msg_mclass_t const *test_mclass = NULL;
void usage(void) void usage(void)
{ {

View File

@ -890,7 +890,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
unsigned threadpool = agent->sa_tport_threadpool; unsigned threadpool = agent->sa_tport_threadpool;
char const *sigcomp = agent->sa_sigcomp_options; char const *sigcomp = agent->sa_sigcomp_options;
char const *algorithm = NONE; char const *algorithm = NONE;
msg_mclass_t *mclass = NONE; msg_mclass_t const *mclass = NONE;
sip_contact_t const *aliases = NONE; sip_contact_t const *aliases = NONE;
url_string_t const *proxy = NONE; url_string_t const *proxy = NONE;
tport_t *tport; tport_t *tport;
@ -4983,15 +4983,16 @@ static inline
nta_incoming_t *incoming_find(nta_agent_t const *agent, nta_incoming_t *incoming_find(nta_agent_t const *agent,
sip_t const *sip, sip_t const *sip,
sip_via_t const *v, sip_via_t const *v,
nta_incoming_t **merge, nta_incoming_t **return_merge,
nta_incoming_t **ack) nta_incoming_t **return_ack)
{ {
sip_cseq_t const *cseq = sip->sip_cseq; sip_cseq_t const *cseq = sip->sip_cseq;
sip_call_id_t const *i = sip->sip_call_id; sip_call_id_t const *i = sip->sip_call_id;
sip_to_t const *to = sip->sip_to; sip_to_t const *to = sip->sip_to;
sip_from_t const *from = sip->sip_from; sip_from_t const *from = sip->sip_from;
sip_request_t *rq = sip->sip_request; 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; incoming_htable_t const *iht = agent->sa_incoming;
hash_value_t hash = NTA_HASH(i, cseq->cs_seq); 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; continue;
if (str0casecmp(irq->irq_from->a_tag, from->a_tag)) if (str0casecmp(irq->irq_from->a_tag, from->a_tag))
continue; 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 (is_uas_ack) {
if (!addr_match(irq->irq_to, to)) if (!addr_match(irq->irq_to, to))
continue; 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)) else if (str0casecmp(irq->irq_to->a_tag, to->a_tag))
continue; 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)) if (!is_uas_ack && url_cmp(irq->irq_rq->rq_url, rq->rq_url))
continue; continue;
@ -5041,18 +5056,18 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
if (irq->irq_method == rq->rq_method) if (irq->irq_method == rq->rq_method)
break; /* found */ break; /* found */
if (ack && rq->rq_method == sip_method_cancel) if (return_ack && rq->rq_method == sip_method_cancel)
*ack = irq; *return_ack = irq;
else if (ack && rq->rq_method == sip_method_ack && else if (return_ack && rq->rq_method == sip_method_ack &&
irq->irq_method == sip_method_invite) irq->irq_method == sip_method_invite)
*ack = irq; *return_ack = irq;
} }
if (irq) if (irq)
return irq; return irq;
/* Check PRACKed requests */ /* 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; sip_rack_t const *rack = sip->sip_rack;
hash = NTA_HASH(i, rack->ra_cseq); hash = NTA_HASH(i, rack->ra_cseq);
@ -5072,7 +5087,7 @@ nta_incoming_t *incoming_find(nta_agent_t const *agent,
continue; continue;
if (!irq->irq_from->a_tag != !from->a_tag) if (!irq->irq_from->a_tag != !from->a_tag)
continue; continue;
*ack = irq; *return_ack = irq;
return NULL; return NULL;
} }

View File

@ -108,7 +108,7 @@ struct nta_agent_s
uint32_t sa_nw_updates; /* Shall we enable network detector? */ uint32_t sa_nw_updates; /* Shall we enable network detector? */
uint32_t sa_flags; /**< Message flags */ uint32_t sa_flags; /**< Message flags */
msg_mclass_t *sa_mclass; msg_mclass_t const *sa_mclass;
sip_contact_t *sa_contact; sip_contact_t *sa_contact;
sip_via_t *sa_vias; /**< @Via headers for all transports */ sip_via_t *sa_vias; /**< @Via headers for all transports */

View File

@ -110,38 +110,38 @@ tag_typedef_t ntatag_rseq = UINTTAG_TYPEDEF(rseq);
/* Status */ /* Status */
tag_typedef_t ntatag_s_irq_hash = UINTTAG_TYPEDEF(s_irq_hash); tag_typedef_t ntatag_s_irq_hash = USIZETAG_TYPEDEF(s_irq_hash);
tag_typedef_t ntatag_s_orq_hash = UINTTAG_TYPEDEF(s_orq_hash); tag_typedef_t ntatag_s_orq_hash = USIZETAG_TYPEDEF(s_orq_hash);
tag_typedef_t ntatag_s_leg_hash = UINTTAG_TYPEDEF(s_leg_hash); tag_typedef_t ntatag_s_leg_hash = USIZETAG_TYPEDEF(s_leg_hash);
tag_typedef_t ntatag_s_irq_hash_used = UINTTAG_TYPEDEF(s_irq_hash_used); tag_typedef_t ntatag_s_irq_hash_used = USIZETAG_TYPEDEF(s_irq_hash_used);
tag_typedef_t ntatag_s_orq_hash_used = UINTTAG_TYPEDEF(s_orq_hash_used); tag_typedef_t ntatag_s_orq_hash_used = USIZETAG_TYPEDEF(s_orq_hash_used);
tag_typedef_t ntatag_s_leg_hash_used = UINTTAG_TYPEDEF(s_leg_hash_used); tag_typedef_t ntatag_s_leg_hash_used = USIZETAG_TYPEDEF(s_leg_hash_used);
tag_typedef_t ntatag_s_recv_msg = UINTTAG_TYPEDEF(s_recv_msg); tag_typedef_t ntatag_s_recv_msg = USIZETAG_TYPEDEF(s_recv_msg);
tag_typedef_t ntatag_s_recv_request = UINTTAG_TYPEDEF(s_recv_request); tag_typedef_t ntatag_s_recv_request = USIZETAG_TYPEDEF(s_recv_request);
tag_typedef_t ntatag_s_recv_response = UINTTAG_TYPEDEF(s_recv_response); tag_typedef_t ntatag_s_recv_response = USIZETAG_TYPEDEF(s_recv_response);
tag_typedef_t ntatag_s_bad_message = UINTTAG_TYPEDEF(s_bad_message); tag_typedef_t ntatag_s_bad_message = USIZETAG_TYPEDEF(s_bad_message);
tag_typedef_t ntatag_s_bad_request = UINTTAG_TYPEDEF(s_bad_request); tag_typedef_t ntatag_s_bad_request = USIZETAG_TYPEDEF(s_bad_request);
tag_typedef_t ntatag_s_bad_response = UINTTAG_TYPEDEF(s_bad_response); tag_typedef_t ntatag_s_bad_response = USIZETAG_TYPEDEF(s_bad_response);
tag_typedef_t ntatag_s_drop_request = UINTTAG_TYPEDEF(s_drop_request); tag_typedef_t ntatag_s_drop_request = USIZETAG_TYPEDEF(s_drop_request);
tag_typedef_t ntatag_s_drop_response = UINTTAG_TYPEDEF(s_drop_response); tag_typedef_t ntatag_s_drop_response = USIZETAG_TYPEDEF(s_drop_response);
tag_typedef_t ntatag_s_client_tr = UINTTAG_TYPEDEF(s_client_tr); tag_typedef_t ntatag_s_client_tr = USIZETAG_TYPEDEF(s_client_tr);
tag_typedef_t ntatag_s_server_tr = UINTTAG_TYPEDEF(s_server_tr); tag_typedef_t ntatag_s_server_tr = USIZETAG_TYPEDEF(s_server_tr);
tag_typedef_t ntatag_s_dialog_tr = UINTTAG_TYPEDEF(s_dialog_tr); tag_typedef_t ntatag_s_dialog_tr = USIZETAG_TYPEDEF(s_dialog_tr);
tag_typedef_t ntatag_s_acked_tr = UINTTAG_TYPEDEF(s_acked_tr); tag_typedef_t ntatag_s_acked_tr = USIZETAG_TYPEDEF(s_acked_tr);
tag_typedef_t ntatag_s_canceled_tr = UINTTAG_TYPEDEF(s_canceled_tr); tag_typedef_t ntatag_s_canceled_tr = USIZETAG_TYPEDEF(s_canceled_tr);
tag_typedef_t ntatag_s_trless_request = UINTTAG_TYPEDEF(s_trless_request); tag_typedef_t ntatag_s_trless_request = USIZETAG_TYPEDEF(s_trless_request);
tag_typedef_t ntatag_s_trless_to_tr = UINTTAG_TYPEDEF(s_trless_to_tr); tag_typedef_t ntatag_s_trless_to_tr = USIZETAG_TYPEDEF(s_trless_to_tr);
tag_typedef_t ntatag_s_trless_response = UINTTAG_TYPEDEF(s_trless_response); tag_typedef_t ntatag_s_trless_response = USIZETAG_TYPEDEF(s_trless_response);
tag_typedef_t ntatag_s_trless_200 = UINTTAG_TYPEDEF(s_trless_200); tag_typedef_t ntatag_s_trless_200 = USIZETAG_TYPEDEF(s_trless_200);
tag_typedef_t ntatag_s_merged_request = UINTTAG_TYPEDEF(s_merged_request); tag_typedef_t ntatag_s_merged_request = USIZETAG_TYPEDEF(s_merged_request);
tag_typedef_t ntatag_s_sent_msg = UINTTAG_TYPEDEF(s_sent_msg); tag_typedef_t ntatag_s_sent_msg = USIZETAG_TYPEDEF(s_sent_msg);
tag_typedef_t ntatag_s_sent_request = UINTTAG_TYPEDEF(s_sent_request); tag_typedef_t ntatag_s_sent_request = USIZETAG_TYPEDEF(s_sent_request);
tag_typedef_t ntatag_s_sent_response = UINTTAG_TYPEDEF(s_sent_response); tag_typedef_t ntatag_s_sent_response = USIZETAG_TYPEDEF(s_sent_response);
tag_typedef_t ntatag_s_retry_request = UINTTAG_TYPEDEF(s_retry_request); tag_typedef_t ntatag_s_retry_request = USIZETAG_TYPEDEF(s_retry_request);
tag_typedef_t ntatag_s_retry_response = UINTTAG_TYPEDEF(s_retry_response); tag_typedef_t ntatag_s_retry_response = USIZETAG_TYPEDEF(s_retry_response);
tag_typedef_t ntatag_s_recv_retry = UINTTAG_TYPEDEF(s_recv_retry); tag_typedef_t ntatag_s_recv_retry = USIZETAG_TYPEDEF(s_recv_retry);
tag_typedef_t ntatag_s_tout_request = UINTTAG_TYPEDEF(s_tout_request); tag_typedef_t ntatag_s_tout_request = USIZETAG_TYPEDEF(s_tout_request);
tag_typedef_t ntatag_s_tout_response = UINTTAG_TYPEDEF(s_tout_response); tag_typedef_t ntatag_s_tout_response = USIZETAG_TYPEDEF(s_tout_response);
/* Internal */ /* Internal */
tag_typedef_t ntatag_delay_sending = BOOLTAG_TYPEDEF(delay_sending); tag_typedef_t ntatag_delay_sending = BOOLTAG_TYPEDEF(delay_sending);

View File

@ -59,10 +59,10 @@ NTA_DLL extern tag_typedef_t ntatag_any;
NTA_DLL extern tag_typedef_t ntatag_mclass; NTA_DLL extern tag_typedef_t ntatag_mclass;
/** Message class used by NTA. @HI */ /** 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; 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; NTA_DLL extern tag_typedef_t ntatag_bad_req_mask;
/** Mask for bad request messages. /** 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)) ntatag_s_leg_hash_used_ref, tag_usize_vr(&(x))
NTA_DLL extern tag_typedef_t ntatag_s_recv_msg; 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; 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; 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; NTA_DLL extern tag_typedef_t ntatag_s_recv_request_ref;
#define NTATAG_S_RECV_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_recv_response_ref;
#define NTATAG_S_RECV_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_bad_message_ref;
#define NTATAG_S_BAD_MESSAGE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_bad_request_ref;
#define NTATAG_S_BAD_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_bad_response_ref;
#define NTATAG_S_BAD_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_drop_request_ref;
#define NTATAG_S_DROP_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_drop_response_ref;
#define NTATAG_S_DROP_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_client_tr_ref;
#define NTATAG_S_CLIENT_TR_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_server_tr_ref;
#define NTATAG_S_SERVER_TR_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_dialog_tr_ref;
#define NTATAG_S_DIALOG_TR_REF(x)\ #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; 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; 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; 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; NTA_DLL extern tag_typedef_t ntatag_s_canceled_tr_ref;
#define NTATAG_S_CANCELED_TR_REF(x) \ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_trless_request_ref;
#define NTATAG_S_TRLESS_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_trless_to_tr_ref;
#define NTATAG_S_TRLESS_TO_TR_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_trless_response_ref;
#define NTATAG_S_TRLESS_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_trless_200_ref;
#define NTATAG_S_TRLESS_200_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_merged_request_ref;
#define NTATAG_S_MERGED_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_sent_msg_ref;
#define NTATAG_S_SENT_MSG_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_sent_request_ref;
#define NTATAG_S_SENT_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_sent_response_ref;
#define NTATAG_S_SENT_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_retry_request_ref;
#define NTATAG_S_RETRY_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_retry_response_ref;
#define NTATAG_S_RETRY_RESPONSE_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_recv_retry_ref;
#define NTATAG_S_RECV_RETRY_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_tout_request_ref;
#define NTATAG_S_TOUT_REQUEST_REF(x)\ #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; 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; NTA_DLL extern tag_typedef_t ntatag_s_tout_response_ref;
#define NTATAG_S_TOUT_RESPONSE_REF(x)\ #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 SOFIA_END_DECLS

View File

@ -559,18 +559,18 @@ int api_test_stats(agent_t *ag)
nta_agent_t *nta; nta_agent_t *nta;
uint32_t irq_hash = -1, orq_hash = -1, leg_hash = -1; usize_t irq_hash = -1, orq_hash = -1, leg_hash = -1;
uint32_t recv_msg = -1, sent_msg = -1; usize_t recv_msg = -1, sent_msg = -1;
uint32_t recv_request = -1, recv_response = -1; usize_t recv_request = -1, recv_response = -1;
uint32_t bad_message = -1, bad_request = -1, bad_response = -1; usize_t bad_message = -1, bad_request = -1, bad_response = -1;
uint32_t drop_request = -1, drop_response = -1; usize_t drop_request = -1, drop_response = -1;
uint32_t client_tr = -1, server_tr = -1, dialog_tr = -1; usize_t client_tr = -1, server_tr = -1, dialog_tr = -1;
uint32_t acked_tr = -1, canceled_tr = -1; usize_t acked_tr = -1, canceled_tr = -1;
uint32_t trless_request = -1, trless_to_tr = -1, trless_response = -1; usize_t trless_request = -1, trless_to_tr = -1, trless_response = -1;
uint32_t trless_200 = -1, merged_request = -1; usize_t trless_200 = -1, merged_request = -1;
uint32_t sent_request = -1, sent_response = -1; usize_t sent_request = -1, sent_response = -1;
uint32_t retry_request = -1, retry_response = -1, recv_retry = -1; usize_t retry_request = -1, retry_response = -1, recv_retry = -1;
uint32_t tout_request = -1, tout_response = -1; usize_t tout_request = -1, tout_response = -1;
TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*", TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*",
NULL, NULL, TAG_END())); NULL, NULL, TAG_END()));
@ -1301,10 +1301,10 @@ int main(int argc, char *argv[])
} }
if (o_attach) { if (o_attach) {
char line[10]; char *response, line[10];
printf("nua_test: pid %lu\n", (unsigned long)getpid()); printf("nua_test: pid %lu\n", (unsigned long)getpid());
printf("<Press RETURN to continue>\n"); printf("<Press RETURN to continue>\n");
fgets(line, sizeof line, stdin); response = fgets(line, sizeof line, stdin);
} }
#if HAVE_ALARM #if HAVE_ALARM
else if (o_alarm) { else if (o_alarm) {

View File

@ -704,7 +704,7 @@ server_t *server_create(url_t const *url,
tag_type_t tag, tag_value_t value, ...) tag_type_t tag, tag_value_t value, ...)
{ {
server_t *srv; server_t *srv;
msg_mclass_t *mclass = NULL; msg_mclass_t const *mclass = NULL;
tp_name_t tpn[1] = {{ NULL }}; tp_name_t tpn[1] = {{ NULL }};
su_root_t *root = NULL; su_root_t *root = NULL;
http_server_t const *server = NULL; http_server_t const *server = NULL;

View File

@ -378,11 +378,9 @@ void nua_dialog_usage_remove_at(nua_owner_t *own,
su_free(own, du); 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) { if (ds->ds_usage == NULL) {
nta_leg_destroy(ds->ds_leg), ds->ds_leg = NULL; nua_dialog_remove(own, ds, NULL);
su_free(own, (void *)ds->ds_remote_tag), ds->ds_remote_tag = NULL;
ds->ds_route = 0;
ds->ds_has_events = 0; ds->ds_has_events = 0;
ds->ds_terminated = 0; ds->ds_terminated = 0;
return; return;

View File

@ -119,8 +119,11 @@ struct register_usage {
nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */ 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_from_t *nr_aor; /**< AoR for this registration, NULL if none */
sip_contact_t *nr_contact; /**< Our Contact */ sip_contact_t *nr_contact; /**< Our Contact */
sip_contact_t nr_dcontact[1]; /**< Contact in dialog */
sip_via_t *nr_via; /**< Corresponding Via headers */ sip_via_t *nr_via; /**< Corresponding Via headers */
unsigned long nr_min_expires; /**< Value from 423 negotiation */
/** Status of registration */ /** Status of registration */
unsigned nr_ready:1; unsigned nr_ready:1;
/** Kind of registration. /** Kind of registration.
@ -222,14 +225,13 @@ static void nua_register_usage_peer_info(nua_dialog_usage_t *du,
/* Interface towards outbound_t */ /* Interface towards outbound_t */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home, su_home_t *home,
int in_dialog,
char const *extra_username, char const *extra_username,
sip_via_t const *v, sip_via_t const *v,
char const *transport, char const *transport,
char const *m_param, 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 *, static int nua_stack_outbound_refresh(nua_handle_t *,
outbound_t *ob); outbound_t *ob);
@ -431,6 +433,11 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
* the desired transport-layer keepalive interval for stream-based * the desired transport-layer keepalive interval for stream-based
* transports like TLS and TCP. * 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, * @sa #nua_r_register, nua_unregister(), #nua_r_unregister,
* #nua_i_register, * #nua_i_register,
* @RFC3261 section 10, * @RFC3261 section 10,
@ -659,7 +666,6 @@ static int nua_register_client_init(nua_client_request_t *cr,
NH_PISSET(nh, keepalive_stream) NH_PISSET(nh, keepalive_stream)
? NH_PGET(nh, keepalive_stream) ? NH_PGET(nh, keepalive_stream)
: NH_PGET(nh, keepalive)); : NH_PGET(nh, keepalive));
nua_stack_outbound_features(nh, ob);
if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0) if (outbound_set_contact(ob, sip->sip_contact, nr->nr_via, unreg) < 0)
return nua_client_return(cr, 900, "Cannot set outbound contact", msg); 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_handle_t *nh = cr->cr_owner;
nua_dialog_usage_t *du = cr->cr_usage; nua_dialog_usage_t *du = cr->cr_usage;
nua_registration_t *nr; 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; int unreg;
(void)nh; (void)nh;
@ -698,48 +705,58 @@ int nua_register_client_request(nua_client_request_t *cr,
if (m == NULL) if (m == NULL)
nua_client_terminating(cr); 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; unreg = cr->cr_terminating;
if (du) { nr = nua_dialog_usage_private(du);
nr = nua_dialog_usage_private(du);
if (nr) {
if (nr->nr_ob) { if (nr->nr_ob) {
outbound_stop_keepalive(nr->nr_ob); outbound_stop_keepalive(nr->nr_ob);
outbound_start_registering(nr->nr_ob); outbound_start_registering(nr->nr_ob);
} }
if (nr->nr_by_stack) { 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); 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, 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")), TAG_IF(unreg, SIPTAG_EXPIRES_STR("0")),
#if 0 #if 0
TAG_IF(unreg, NTATAG_SIGCOMP_CLOSE(1)), 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? */; /* 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 */ /* Check for status-specific reasons to retry */
if (nua_base_client_check_restart(cr, status, phrase, sip)) if (nua_base_client_check_restart(cr, status, phrase, sip))
return 1; return 1;
@ -1262,11 +1284,8 @@ int nua_registration_from_via(nua_registration_t **list,
v2[1].v_next = NULL; v2[1].v_next = NULL;
#if 1 contact = nua_handle_contact_by_via(nh, home, 0, NULL, v2, protocol, NULL);
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
v = sip_via_dup(home, v2); v = sip_via_dup(home, v2);
if (!contact || !v) { 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_ready = 1, nr->nr_default = 1, nr->nr_public = public;
nr->nr_secure = contact->m_url->url_type == url_sips; nr->nr_secure = contact->m_url->url_type == url_sips;
nr->nr_contact = contact; nr->nr_contact = contact;
*nr->nr_dcontact = *contact, nr->nr_dcontact->m_params = NULL;
nr->nr_via = v; nr->nr_via = v;
nr->nr_ip4 = host_is_ip4_address(contact->m_url->url_host); 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); 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 m;
} }
return nr->nr_contact; if (nr->nr_contact)
return nr->nr_dcontact;
else
return NULL;
} }
/** Return initial route. */ /** 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) sip_contact_t const *nua_stack_get_contact(nua_registration_t const *nr)
{ {
nr = nua_registration_by_aor(nr, NULL, NULL, 1); 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 */ /** 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; return -1;
if (add_contact) { 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); if (nr->nr_by_stack && nr->nr_ob) {
char const *m_username = NH_PGET(nh, m_username); m = outbound_dialog_gruu(nr->nr_ob);
char const *m_params = NH_PGET(nh, m_params);
url_t const *u = m->m_url; 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) if (!m)
return -1; 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_params = NULL;
m = sip_contact_format(msg_home(msg), m = sip_contact_format(msg_home(msg),
"%s<%s:%s%s%s%s%s%s%s%s%s>", "%s<%s:%s%s%s%s%s%s%s%s%s>",
m_display ? m_display : m_display ? m_display : "",
m->m_display ? m->m_display : "",
u->url_scheme, u->url_scheme,
m_username ? m_username : "", m_username ? m_username : "",
m_username ? "@" : "", m_username ? "@" : "",
@ -1648,7 +1699,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
if (nr0 && nr0->nr_via) { if (nr0 && nr0->nr_via) {
char const *tport = nr0->nr_via->v_next ? NULL : nr0->nr_via->v_protocol; 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); NULL, nr0->nr_via, tport, NULL);
} }
} }
@ -1657,6 +1708,7 @@ int nua_registration_set_contact(nua_handle_t *nh,
return -1; return -1;
nr->nr_contact = m; 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_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_ip6 = !nr->nr_ip4 && host_is_ip6_reference(m->m_url->url_host);
nr->nr_by_stack = !application_contact; 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. */ /** @internal Generate a @Contact header. */
sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh, sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
su_home_t *home, su_home_t *home,
int in_dialog,
char const *extra_username, char const *extra_username,
sip_via_t const *v, sip_via_t const *v,
char const *transport, 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); su_strlst_append(l, ";comp="), su_strlst_append(l, comp);
s = NH_PGET(nh, m_params); s = NH_PGET(nh, m_params);
if (s) 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, ">"); su_strlst_append(l, ">");
va_start(va, m_param); va_start(va, m_param);
@ -1882,81 +1935,42 @@ sip_contact_t *nua_handle_contact_by_via(nua_handle_t *nh,
va_end(va); va_end(va);
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, "\"");
}
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++);
}
}
}
}
m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), "")); m = sip_contact_make(home, su_strlst_join(l, su_strlst_home(l), ""));
su_strlst_destroy(l); su_strlst_destroy(l);
return m; 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, ",");
}
}
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 (su_strlst_len(l))
retval = su_strlst_join(l, nh->nh_home, "");
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;
}

View File

@ -299,10 +299,7 @@ int nua_stack_event(nua_t *nua, nua_handle_t *nh, msg_t *msg,
if (tags) { if (tags) {
tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len); tagi_t *t = e->e_tags, *t_end = (tagi_t *)((char *)t + len);
void *b = t_end; void *b = t_end, *end = (char *)b + xtra;
#ifndef NDEBUG
void *end = (char *)b + xtra;
#endif
t = tl_dup(t, tags, &b); p = b; t = tl_dup(t, tags, &b); p = b;
assert(t == t_end); assert(b == end); (void)end; assert(t == t_end); assert(b == end); (void)end;

View File

@ -117,7 +117,6 @@ struct outbound {
char const *ob_instance; /**< Our instance ID */ char const *ob_instance; /**< Our instance ID */
int32_t ob_reg_id; /**< Flow-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_rcontact; /**< Our contact */
sip_contact_t *ob_dcontact; /**< Contact for dialogs */ sip_contact_t *ob_dcontact; /**< Contact for dialogs */
sip_contact_t *ob_previous; /**< Stale contact */ sip_contact_t *ob_previous; /**< Stale contact */
@ -327,20 +326,6 @@ int outbound_set_options(outbound_t *ob,
return 0; 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 */ /** 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; msg_t *msg = nta_msg_create(ob->ob_nta, MSG_FLG_COMPACT), *previous;
sip_t *osip = sip_object(msg); sip_t *osip = sip_object(msg);
sip_accept_contact_t *ac; sip_contact_t *m = ob->ob_rcontact;
char const *p1 = ob->ob_instance;
char const *p2 = ob->ob_features;
unsigned d = ob->ob_keepalive.interval; unsigned d = ob->ob_keepalive.interval;
assert(regsip); assert(regsip->sip_request); assert(regsip); assert(regsip->sip_request);
if (p1 || p2) { if (m && m->m_params) {
ac = sip_accept_contact_format(msg_home(msg), "*;require;explicit;%s%s%s", sip_accept_contact_t *ac;
p1 ? p1 : "", size_t i;
p2 && p2 ? ";" : "", int features = 0;
p2 ? p2 : "");
msg_header_insert(msg, NULL, (void *)ac); 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 > 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; 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); NULL, v, v->v_protocol, NULL);
if (ob->ob_instance && ob->ob_reg_id != 0) if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id); 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, NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL); 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); v = sip_via_dup(home, v);
if (!rcontact || !dcontact || !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 const *tport = !v->v_next ? v->v_protocol : NULL;
char reg_id_param[20]; 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); NULL, v, tport, NULL);
if (!dcontact) if (!dcontact)
return -1; return -1;
@ -1147,9 +1113,8 @@ int outbound_set_contact(outbound_t *ob,
if (ob->ob_instance && ob->ob_reg_id != 0) if (ob->ob_instance && ob->ob_reg_id != 0)
snprintf(reg_id_param, sizeof reg_id_param, ";reg-id=%u", ob->ob_reg_id); 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, NULL, v, v->v_protocol,
ob->ob_features ? ob->ob_features : "",
ob->ob_instance, reg_id_param, NULL); ob->ob_instance, reg_id_param, NULL);
if (!rcontact) if (!rcontact)
return -1; return -1;
@ -1195,6 +1160,11 @@ sip_contact_t const *outbound_dialog_contact(outbound_t const *ob)
return ob->ob_dcontact; return ob->ob_dcontact;
} }
sip_contact_t const *outbound_dialog_gruu(outbound_t const *ob)
{
return ob ? ob->ob_gruu : NULL;
}
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */

View File

@ -70,8 +70,6 @@ int outbound_set_options(outbound_t *ob,
unsigned dgram_interval, unsigned dgram_interval,
unsigned stream_interval); unsigned stream_interval);
int outbound_set_features(outbound_t *ob, char *features);
int outbound_get_contacts(outbound_t *ob, int outbound_get_contacts(outbound_t *ob,
sip_contact_t **return_current_contact, sip_contact_t **return_current_contact,
sip_contact_t **return_previous_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_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); int outbound_gruuize(outbound_t *ob, sip_t const *sip);
void outbound_start_keepalive(outbound_t *ob, void outbound_start_keepalive(outbound_t *ob,
@ -118,6 +118,7 @@ struct outbound_owner_vtable
int oo_size; int oo_size;
sip_contact_t *(*oo_contact)(outbound_owner_t *, sip_contact_t *(*oo_contact)(outbound_owner_t *,
su_home_t *home, su_home_t *home,
int used_in_dialog,
char const *extra_username, char const *extra_username,
sip_via_t const *v, sip_via_t const *v,
char const *transport, char const *transport,

View 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 outbound option string can specify how the NAT traversal is handled.
* The option tokens are as follows: * 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) * - "outbound": use SIP outbound extension (off by default)
* - "validate": validate registration behind a NAT by sending OPTIONS to self * - "validate": validate registration behind a NAT by sending OPTIONS to self
* - "natify": try to traverse NAT * - "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 * 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 * example, if you want to try to traverse NATs but not to use OPTIONS
* keepalive, use NUTAG_OUTBOUND("natify no-options-keepalive"). * 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 * @note
* Options string is used so that no new tags need to be added when the * 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() * nua_create()
* *
* @par Parameter type * @par Parameter type
* msg_mclass_t * * msg_mclass_t const *
* *
* @par Values * @par Values
* Pointer to an extended SIP parser. * Pointer to an extended SIP parser.
@ -1243,6 +1247,9 @@ SOFIAPUBVAR tag_typedef_t nutag_auth;
SOFIAPUBVAR tag_typedef_t nutag_auth_ref; SOFIAPUBVAR tag_typedef_t nutag_auth_ref;
/** Keepalive interval in milliseconds. /** Keepalive interval in milliseconds.
*
* This setting applies to OPTIONS/STUN keepalives. See documentation
* for nua_register() for more detailed information.
* *
* @par Used with * @par Used with
* nua_register() \n * nua_register() \n
@ -1268,6 +1275,8 @@ SOFIAPUBVAR tag_typedef_t nutag_keepalive;
SOFIAPUBVAR tag_typedef_t nutag_keepalive_ref; SOFIAPUBVAR tag_typedef_t nutag_keepalive_ref;
/** Transport-level keepalive interval for streams. /** Transport-level keepalive interval for streams.
*
* See documentation for nua_register() for more detailed information.
* *
* @par Used with * @par Used with
* nua_register() \n * nua_register() \n

View 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_active_call(b_call->nh));
TEST_1(!nua_handle_has_call_on_hold(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()); INFO(b, b_call, b_call->nh, TAG_END());
BYE(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()); INFO(b, b_call, b_call->nh, TAG_END());

View File

@ -92,6 +92,9 @@ static char const options_usage[] =
" --no-alarm don't ask for guard ALARM\n" " --no-alarm don't ask for guard ALARM\n"
" -p uri specify uri of outbound proxy (implies --no-proxy)\n" " -p uri specify uri of outbound proxy (implies --no-proxy)\n"
" --proxy-tests run tests involving proxy, too\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" " -k do not exit after first error\n"
; ;

View File

@ -216,6 +216,8 @@ int until_terminated(CONDITION_PARAMS);
int until_ready(CONDITION_PARAMS); int until_ready(CONDITION_PARAMS);
int accept_call(CONDITION_PARAMS); int accept_call(CONDITION_PARAMS);
int accept_notify(CONDITION_PARAMS);
void a_callback(nua_event_t event, void a_callback(nua_event_t event,
int status, char const *phrase, int status, char const *phrase,
nua_t *nua, struct context *ctx, nua_t *nua, struct context *ctx,

View File

@ -133,6 +133,8 @@ int test_register_to_proxy(struct context *ctx)
NUTAG_KEEPALIVE(1000), NUTAG_KEEPALIVE(1000),
NUTAG_M_DISPLAY("A&A"), NUTAG_M_DISPLAY("A&A"),
NUTAG_M_USERNAME("a"), NUTAG_M_USERNAME("a"),
NUTAG_M_PARAMS("foo=bar"),
NUTAG_M_FEATURES("q=0.9"),
SIPTAG_CSEQ(cseq), SIPTAG_CSEQ(cseq),
TAG_END()); TAG_END());
run_a_until(ctx, -1, save_until_final_response); 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() */ /* VC does not dig \" with TEST_S() */
TEST_S(sip->sip_contact->m_display, expect_m_display); } TEST_S(sip->sip_contact->m_display, expect_m_display); }
TEST_S(sip->sip_contact->m_url->url_user, "a"); 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); TEST(sip->sip_cseq->cs_seq, 14);
if (ctx->nat) { 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())); TEST_1(c_reg->nh = nua_handle(c->nua, c_reg, TAG_END()));
REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to), REGISTER(c, c_reg, c_reg->nh, SIPTAG_TO(c->to),
NUTAG_OUTBOUND(NULL),
NUTAG_M_DISPLAY("C"), NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("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 */ SIPTAG_EXPIRES_STR("5"), /* Test 423 negotiation */
TAG_END()); TAG_END());
run_abc_until(ctx, -1, save_events, -1, save_events, 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_1(sip->sip_contact);
TEST_S(sip->sip_contact->m_display, "C"); TEST_S(sip->sip_contact->m_display, "C");
TEST_S(sip->sip_contact->m_url->url_user, "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); TEST_1(!e->next);
free_events_in_list(ctx, c->events); 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), UNREGISTER(c, c->call, c->call->nh, SIPTAG_TO(c->to),
NUTAG_M_DISPLAY("C"), NUTAG_M_DISPLAY("C"),
NUTAG_M_USERNAME("c"), NUTAG_M_USERNAME("c"),
NUTAG_M_PARAMS("c=1"),
TAG_END()); TAG_END());
run_c_until(ctx, -1, save_until_final_response); run_c_until(ctx, -1, save_until_final_response);

View 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; sip_header_t *h;
n = url_xtra(us->us_url); n = url_xtra(us->us_url);
h = sip_header_alloc(home, sip_to_class, n); h = sip_header_alloc(home, hc, n);
if (h) { if (h) {
sip_addr_t *a = h->sh_to; sip_addr_t *a = h->sh_to;

View File

@ -60,9 +60,9 @@ char const sip_parser_version[] = VERSION;
char const sip_version_2_0[] = "SIP/2.0"; char const sip_version_2_0[] = "SIP/2.0";
/** Default message class */ /** 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; return sip_mclass;
} }

View File

@ -58,7 +58,7 @@
SOFIA_BEGIN_DECLS SOFIA_BEGIN_DECLS
/** Return built-in SIP parser object. */ /** 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 */ /** 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) #define sip_is_sip(sip) ((sip) && (sip)->sip_ident == SIP_PROTOCOL_TAG)

View File

@ -65,7 +65,7 @@ int diff(const char *olds, const char *news, int *linep, int *pos)
return *o != *n; return *o != *n;
} }
int test_msg_class(msg_mclass_t *mc) int test_msg_class(msg_mclass_t const *mc)
{ {
int i, j, N; int i, j, N;
@ -159,7 +159,7 @@ int main(int argc, char *argv[])
int m, tcp; int m, tcp;
sip_t *sip; sip_t *sip;
int exitcode = 0; 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_t *msg = msg_create(sip_mclass, MSG_FLG_EXTRACT_COPY);
msg_iovec_t iovec[1]; msg_iovec_t iovec[1];

View File

@ -412,7 +412,12 @@ int test_basic(void)
TEST_1(sip_from_tag(home, f, "tag=jxahudsf") == 0); TEST_1(sip_from_tag(home, f, "tag=jxahudsf") == 0);
su_free(home, f); 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(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_1(sip_to_tag(home, t, "tag=jxahudsf") == 0);
TEST_S(t->a_tag, "jxahudsf"); TEST_S(t->a_tag, "jxahudsf");
TEST(msg_header_replace_param(home, t->a_common, "tag=bar"), 1); TEST(msg_header_replace_param(home, t->a_common, "tag=bar"), 1);

View File

@ -180,7 +180,7 @@ char *lastpart(char *path)
return 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_file(int fd, char const *name, context_t *ctx);
int validate_dump(char *, off_t, context_t *ctx); int validate_dump(char *, off_t, context_t *ctx);

View File

@ -55,9 +55,11 @@ if netstat --ip >/dev/null 2>&1 ; then
done done
fi fi
# No named, no fun # No BIND 9, no fun
type -p named >/dev/null || { { type -p named >/dev/null &&
echo test_sresolv: there is no BIND named installed, skipping named -v | grep -q BIND.*9
} || {
echo test_sresolv: there is no BIND 9 named in you path, skipping
exit 77 exit 77
} }

View File

@ -64,7 +64,6 @@ typedef unsigned _int32 uint32_t;
#include <sofia-resolv/sres_async.h> #include <sofia-resolv/sres_async.h>
#include <sofia-resolv/sres_record.h> #include <sofia-resolv/sres_record.h>
#include <sofia-sip/su.h>
#include <sofia-sip/su_alloc.h> #include <sofia-sip/su_alloc.h>
#include <assert.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; 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 1
#if HAVE_POLL && 0 #if HAVE_POLL && 0
@ -145,7 +222,7 @@ static
int test_socket(sres_context_t *ctx) int test_socket(sres_context_t *ctx)
{ {
int af; int af;
su_sockeet_t s1, s2, s3, s4; sres_socket_t s1, s2, s3, s4;
struct sockaddr_storage a[1]; struct sockaddr_storage a[1];
struct sockaddr_storage a1[1], a2[1], a3[1], a4[1]; struct sockaddr_storage a1[1], a2[1], a3[1], a4[1];
struct sockaddr_in *sin = (void *)a; struct sockaddr_in *sin = (void *)a;
@ -160,10 +237,10 @@ int test_socket(sres_context_t *ctx)
af = AF_INET; af = AF_INET;
for (;;) { for (;;) {
TEST_1((s1 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET); TEST_1((s1 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s2 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET); TEST_1((s2 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s3 = su_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET); TEST_1((s3 = sres_socket(af, SOCK_DGRAM, 0)) != INVALID_SOCKET);
TEST_1((s4 = su_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(s1, 0) == 0);
TEST_1(setblocking(s2, 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(connect(s2, sa4, a4len), 0);
TEST(getsockname(s2, (struct sockaddr *)a2, &a2len), 0); TEST(getsockname(s2, (struct sockaddr *)a2, &a2len), 0);
TEST(sendto(s1, "foo", 3, 0, sa4, a4len), 3); TEST(sres_sendto(s1, "foo", 3, 0, sa4, a4len), 3);
TEST(recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3); TEST(sres_recvfrom(s4, buf, sizeof buf, 0, sa, &alen), 3);
TEST(sendto(s4, "bar", 3, 0, sa, alen), 3); TEST(sres_sendto(s4, "bar", 3, 0, sa, alen), 3);
TEST(recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1); TEST(sres_recvfrom(s2, buf, sizeof buf, 0, sa, &alen), -1);
TEST(recvfrom(s1, buf, sizeof buf, 0, sa, &alen), 3); 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; break;
} }
@ -1428,7 +1505,7 @@ int sink_deinit(sres_context_t *ctx)
if (ctx->sinkidx) if (ctx->sinkidx)
su_root_deregister(ctx->root, ctx->sinkidx); su_root_deregister(ctx->root, ctx->sinkidx);
ctx->sinkidx = 0; ctx->sinkidx = 0;
su_close(ctx->sink), ctx->sink = INVALID_SOCKET; sres_close(ctx->sink), ctx->sink = INVALID_SOCKET;
END(); END();
} }
@ -1453,7 +1530,7 @@ int test_timeout(sres_context_t *ctx)
result = sres_cached_answers(res, sres_type_a, domain); 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); TEST_1(result); TEST_1(result[0] != NULL);
rr_soa = result[0]->sr_soa; rr_soa = result[0]->sr_soa;
@ -1464,7 +1541,6 @@ int test_timeout(sres_context_t *ctx)
sres_free_answers(res, result); sres_free_answers(res, result);
#else #else
/* Currently, we do not create error records */
TEST_1(result == NULL); TEST_1(result == NULL);
#endif #endif
@ -1625,7 +1701,8 @@ int test_net(sres_context_t *ctx)
struct sockaddr *sa = (void *)ss; struct sockaddr *sa = (void *)ss;
socklen_t salen = sizeof ss; socklen_t salen = sizeof ss;
char *bin; char *bin;
size_t i, n, binlen; size_t i, binlen;
ssize_t n;
char const *domain = "example.com"; char const *domain = "example.com";
char query[512]; char query[512];
@ -1647,14 +1724,14 @@ int test_net(sres_context_t *ctx)
/* We got an error => make new query */ /* We got an error => make new query */
TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */ TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
sres_type_naptr, domain)); 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 */ memcpy(bin, query, 2); /* Copy ID */
} }
if (i != 1) if (i != 1)
bin[i] ^= 0xff; bin[i] ^= 0xff;
else else
bin[3] ^= SRES_FORMAT_ERR; /* format error -> EDNS0 failure */ 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) if (i != 1)
bin[i] ^= 0xff; bin[i] ^= 0xff;
else else
@ -1675,10 +1752,10 @@ int test_net(sres_context_t *ctx)
/* We got an error => make new query */ /* We got an error => make new query */
TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */ TEST_1(q = sres_query(res, test_answer, ctx, /* Send query */
sres_type_naptr, domain)); 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 */ 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) if (n == -1)
perror("sendto"); perror("sendto");
while (!poll_sockets(ctx)) while (!poll_sockets(ctx))

View File

@ -79,7 +79,7 @@ libsu_la_SOURCES = \
su_time.c su_time0.c \ su_time.c su_time0.c \
su_wait.c su_root.c su_timer.c \ su_wait.c su_root.c su_timer.c \
su_port.c su_port.h \ 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_poll_port.c su_epoll_port.c su_select_port.c \
su_localinfo.c \ su_localinfo.c \
su_os_nw.c \ su_os_nw.c \
@ -94,6 +94,7 @@ EXTRA_libsu_la_SOURCES = \
inet_ntop.c inet_pton.c poll.c getopt.c \ inet_ntop.c inet_pton.c poll.c getopt.c \
su_tag_ref.c su_win32_port.c su_tag_ref.c su_win32_port.c
libsu_la_CFLAGS = $(AM_CFLAGS) $(SOFIA_CFLAGS)
libsu_la_LIBADD = $(REPLACE_LIBADD) libsu_la_LIBADD = $(REPLACE_LIBADD)
libsu_la_DEPENDENCIES = $(REPLACE_LIBADD) libsu_la_DEPENDENCIES = $(REPLACE_LIBADD)

View File

@ -1,13 +1,20 @@
/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002 /* This file is part of the Sofia-SIP package.
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 Copyright (C) 2005 Nokia Corporation.
Contact: Pekka Pessi <pekka.pessi@nokia.com>
This file is originally from GNU C library.
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 modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. 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 but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
@ -19,237 +26,225 @@
#include "config.h" #include "config.h"
#if !HAVE_POLL && HAVE_SELECT && HAVE_POLL_PORT #if HAVE_SELECT
#include "sofia-sip/su.h" #include "sofia-sip/su.h"
//extern __typeof(poll) __libc_poll;
#if 1
#include <alloca.h> #include <alloca.h>
#include <string.h> #include <string.h>
#include "sofia-sip/su_wait.h" #include "sofia-sip/su_wait.h"
#ifndef __NFDBITS #undef NBBY
#define NBBY 8 /* bits in a byte */ #undef NFDBITS
#define __NFDBITS (sizeof(__int32_t) * NBBY) /* bits per mask */ #undef FDSETSIZE
#endif #undef roundup
#define NBBY 8 /* bits in a byte */
#define NFDBITS (sizeof(long) * NBBY) /* bits per mask */
#undef howmany #define FDSETSIZE(n) (((n) + NFDBITS - 1) / NFDBITS * (NFDBITS / NBBY))
#define roundup(n, x) (((n) + (x) - 1) / (x) * (x))
#ifndef howmany /* Emulated poll() using select().
#define howmany(x, y) (((x)+((y)-1))/(y)) * sizeof(uint32_t)
#endif
//libc_hidden_proto(memcpy) This is used by su_wait().
//libc_hidden_proto(memset)
//libc_hidden_proto(getdtablesize)
//libc_hidden_proto(select)
/* uClinux 2.0 doesn't have poll, emulate it using select */ Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
/* Poll the file descriptors described by the NFDS structures starting at an event to occur; if TIMEOUT is -1, block until an event occurs.
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for Returns the number of file descriptors with events, zero if timed out,
an event to occur; if TIMEOUT is -1, block until an event occurs. or -1 for errors. */
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) int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{ {
struct timeval tv; struct timeval tv;
#if HAVE_ALLOCA_H struct pollfd *f;
static int max_fd_size; int ready;
int bytes; int maxfd = 0;
fd_set *rset, *wset, *xset;
#else
fd_set rset[1], wset[1], xset[1];
#endif
struct pollfd *f;
int ready;
int maxfd = 0;
#if HAVE_ALLOCA_H #if HAVE_ALLOCA_H
if (!max_fd_size) static int max_fd_size;
max_fd_size = getdtablesize (); int bytes;
fd_set *rset, *wset, *xset;
bytes = howmany (max_fd_size, __NFDBITS); if (!max_fd_size)
max_fd_size = getdtablesize ();
rset = alloca (bytes); bytes = FDSETSIZE (max_fd_size);
wset = alloca (bytes);
xset = alloca (bytes);
/* We can't call FD_ZERO, since FD_ZERO only works with sets rset = alloca (bytes);
of exactly __FD_SETSIZE size. */ wset = alloca (bytes);
memset (rset, 0, bytes); xset = alloca (bytes);
memset (wset, 0, bytes);
memset (xset, 0, 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 #else
FD_ZERO(rset); fd_set rset[1], wset[1], xset[1];
FD_ZERO(wset);
FD_ZERO(xset); FD_ZERO(rset);
FD_ZERO(wset);
FD_ZERO(xset);
#endif #endif
for (f = fds; f < &fds[nfds]; ++f)
for (f = fds; f < &fds[nfds]; ++f)
{ {
f->revents = 0; f->revents = 0;
if (f->fd >= 0) if (f->fd >= 0)
{ {
#if HAVE_ALLOCA_H #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 /* The user provides a file descriptor number which is higher
than the maximum we got from the `getdtablesize' call. than the maximum we got from the `getdtablesize' call.
Maybe this is ok so enlarge the arrays. */ Maybe this is ok so enlarge the arrays. */
fd_set *nrset, *nwset, *nxset; fd_set *nrset, *nwset, *nxset;
int nbytes; int nbytes;
max_fd_size = roundup (f->fd, __NFDBITS); max_fd_size = roundup (f->fd, NFDBITS);
nbytes = howmany (max_fd_size, __NFDBITS); nbytes = FDSETSIZE (max_fd_size);
nrset = alloca (nbytes); nrset = alloca (nbytes);
nwset = alloca (nbytes); nwset = alloca (nbytes);
nxset = alloca (nbytes); nxset = alloca (nbytes);
memset ((char *) nrset + bytes, 0, nbytes - bytes); memset ((char *) nrset + bytes, 0, nbytes - bytes);
memset ((char *) nwset + bytes, 0, nbytes - bytes); memset ((char *) nwset + bytes, 0, nbytes - bytes);
memset ((char *) nxset + bytes, 0, nbytes - bytes); memset ((char *) nxset + bytes, 0, nbytes - bytes);
rset = memcpy (nrset, rset, bytes); rset = memcpy (nrset, rset, bytes);
wset = memcpy (nwset, wset, bytes); wset = memcpy (nwset, wset, bytes);
xset = memcpy (nxset, xset, bytes); xset = memcpy (nxset, xset, bytes);
bytes = nbytes; bytes = nbytes;
} }
#else #else
if (f->fd >= FD_SETSIZE) { if (f->fd >= FD_SETSIZE) {
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
#endif /* HAVE_ALLOCA_H */ #endif /* HAVE_ALLOCA_H */
if (f->events & POLLIN) if (f->events & POLLIN)
FD_SET (f->fd, rset); FD_SET (f->fd, rset);
if (f->events & POLLOUT) if (f->events & POLLOUT)
FD_SET (f->fd, wset); FD_SET (f->fd, wset);
if (f->events & POLLPRI) if (f->events & POLLPRI)
FD_SET (f->fd, xset); FD_SET (f->fd, xset);
if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
maxfd = f->fd; maxfd = f->fd;
} }
} }
tv.tv_sec = timeout / 1000; tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000; tv.tv_usec = (timeout % 1000) * 1000;
while (1) while (1)
{ {
ready = select (maxfd + 1, rset, wset, xset, ready = select (maxfd + 1, rset, wset, xset,
timeout == -1 ? NULL : &tv); timeout == -1 ? NULL : &tv);
/* It might be that one or more of the file descriptors is invalid. /* 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. */ We now try to find and mark them and then try again. */
if (ready == -1 && errno == EBADF) if (ready == -1 && errno == EBADF)
{ {
struct timeval sngl_tv; struct timeval sngl_tv;
#if HAVE_ALLOCA_H #if HAVE_ALLOCA_H
fd_set *sngl_rset = alloca (bytes); fd_set *sngl_rset = alloca (bytes);
fd_set *sngl_wset = alloca (bytes); fd_set *sngl_wset = alloca (bytes);
fd_set *sngl_xset = alloca (bytes); fd_set *sngl_xset = alloca (bytes);
/* Clear the original set. */ /* Clear the original set. */
memset (rset, 0, bytes); memset (rset, 0, bytes);
memset (wset, 0, bytes); memset (wset, 0, bytes);
memset (xset, 0, bytes); memset (xset, 0, bytes);
#else #else
fd_set sngl_rset[1]; fd_set sngl_rset[1];
fd_set sngl_wset[1]; fd_set sngl_wset[1];
fd_set sngl_xset[1]; fd_set sngl_xset[1];
FD_ZERO(rset); FD_ZERO(rset);
FD_ZERO(wset); FD_ZERO(wset);
FD_ZERO(xset); FD_ZERO(xset);
#endif #endif
/* This means we don't wait for input. */ /* This means we don't wait for input. */
sngl_tv.tv_sec = 0; sngl_tv.tv_sec = 0;
sngl_tv.tv_usec = 0; sngl_tv.tv_usec = 0;
maxfd = -1; maxfd = -1;
/* Reset the return value. */ /* Reset the return value. */
ready = 0; ready = 0;
for (f = fds; f < &fds[nfds]; ++f) for (f = fds; f < &fds[nfds]; ++f)
if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI))
&& (f->revents & POLLNVAL) == 0) && (f->revents & POLLNVAL) == 0)
{ {
int n; int n;
#if HAVE_ALLOCA_H #if HAVE_ALLOCA_H
memset (sngl_rset, 0, bytes); memset (sngl_rset, 0, bytes);
memset (sngl_wset, 0, bytes); memset (sngl_wset, 0, bytes);
memset (sngl_xset, 0, bytes); memset (sngl_xset, 0, bytes);
#else #else
FD_ZERO(rset); FD_ZERO(rset);
FD_ZERO(wset); FD_ZERO(wset);
FD_ZERO(xset); FD_ZERO(xset);
#endif #endif
if (f->events & POLLIN) if (f->events & POLLIN)
FD_SET (f->fd, sngl_rset); FD_SET (f->fd, sngl_rset);
if (f->events & POLLOUT) if (f->events & POLLOUT)
FD_SET (f->fd, sngl_wset); FD_SET (f->fd, sngl_wset);
if (f->events & POLLPRI) if (f->events & POLLPRI)
FD_SET (f->fd, sngl_xset); FD_SET (f->fd, sngl_xset);
n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset,
&sngl_tv); &sngl_tv);
if (n != -1) if (n != -1)
{ {
/* This descriptor is ok. */ /* This descriptor is ok. */
if (f->events & POLLIN) if (f->events & POLLIN)
FD_SET (f->fd, rset); FD_SET (f->fd, rset);
if (f->events & POLLOUT) if (f->events & POLLOUT)
FD_SET (f->fd, wset); FD_SET (f->fd, wset);
if (f->events & POLLPRI) if (f->events & POLLPRI)
FD_SET (f->fd, xset); FD_SET (f->fd, xset);
if (f->fd > maxfd) if (f->fd > maxfd)
maxfd = f->fd; maxfd = f->fd;
if (n > 0) if (n > 0)
/* Count it as being available. */ /* Count it as being available. */
++ready; ++ready;
} }
else if (errno == EBADF) else if (errno == EBADF)
f->revents |= POLLNVAL; f->revents |= POLLNVAL;
} }
/* Try again. */ /* Try again. */
continue; continue;
} }
break; break;
} }
if (ready > 0) if (ready > 0)
for (f = fds; f < &fds[nfds]; ++f) for (f = fds; f < &fds[nfds]; ++f)
{ {
if (f->fd >= 0) if (f->fd >= 0)
{ {
if (FD_ISSET (f->fd, rset)) if (FD_ISSET (f->fd, rset))
f->revents |= POLLIN; f->revents |= POLLIN;
if (FD_ISSET (f->fd, wset)) if (FD_ISSET (f->fd, wset))
f->revents |= POLLOUT; f->revents |= POLLOUT;
if (FD_ISSET (f->fd, xset)) if (FD_ISSET (f->fd, xset))
f->revents |= POLLPRI; f->revents |= POLLPRI;
} }
} }
return ready; return ready;
} }
#endif #endif
#endif

View File

@ -2,18 +2,33 @@
rc=0 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 if $VALGRIND ./test_su ; then
echo PASS: multithread test_su echo PASS: multithread test_su with $SU_PORT
else else
echo FAIL: multithread test_su failed echo FAIL: multithread test_su with $SU_PORT failed
rc=1 rc=1
fi fi
if $VALGRIND ./test_su -s ; then if $VALGRIND ./test_su -s ; then
echo PASS: singlethread test_su echo PASS: singlethread test_su with $SU_PORT
else else
echo FAIL: singlethread test_su failed echo FAIL: singlethread test_su with $SU_PORT failed
rc=1 rc=1
fi fi
done
test $run = no && exit 77
exit $rc exit $rc

View 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_pause(su_clone_r);
SOFIAPUBFUN int su_clone_resume(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 SOFIA_END_DECLS
#endif /* SU_WAIT_H */ #endif /* SU_WAIT_H */

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Sofia-SIP package * 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> * Contact: Pekka Pessi <pekka.pessi@nokia.com>
* *
@ -23,18 +23,28 @@
*/ */
/**@ingroup su_wait /**@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 Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@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" #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 <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdarg.h> #include <stdarg.h>
@ -43,14 +53,6 @@
#include <limits.h> #include <limits.h>
#include <errno.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> #include <sys/epoll.h>
#define POLL2EPOLL_NEEDED \ #define POLL2EPOLL_NEEDED \
@ -62,8 +64,8 @@
/** Port based on epoll(). */ /** Port based on epoll(). */
struct su_poll_port_s { struct su_epoll_port_s {
su_pthread_port_t sup_base[1]; su_socket_port_t sup_base[1];
/** epoll fd */ /** epoll fd */
int sup_epoll; int sup_epoll;
@ -88,7 +90,9 @@ struct su_poll_port_s {
} **sup_indices; } **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, static int su_epoll_port_register(su_port_t *self,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
@ -118,7 +122,7 @@ su_port_vtable_t const su_epoll_port_vtable[1] =
su_base_port_incref, su_base_port_incref,
su_epoll_port_decref, su_epoll_port_decref,
su_base_port_gsource, su_base_port_gsource,
su_pthread_port_send, su_socket_port_send,
su_epoll_port_register, su_epoll_port_register,
su_epoll_port_unregister, su_epoll_port_unregister,
su_epoll_port_deregister, 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_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; 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.u64 = (uint64_t)0;
ev.data.u32 = (uint32_t)index; 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, 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; 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 determines how the events are scheduled by port. If
* multishot mode is enabled, port serves all the sockets that have received * multishot mode is enabled, port serves all the sockets that have received
* network events. If it is disabled, only first socket event is served. * network events. If it is disabled, only first socket event is served.
p * *
* @param self pointer to port object * @param self pointer to port object
* @param multishot multishot mode (0 => disables, 1 => enables, -1 => query) * @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_epoll = epoll;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; 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 su_home_unref(su_port_home(self)), NULL;
return self; return self;
@ -562,22 +566,21 @@ int su_epoll_clone_start(su_root_t *parent,
return su_pthreaded_port_start(su_epoll_port_create, return su_pthreaded_port_start(su_epoll_port_create,
parent, return_clone, magic, init, deinit); parent, return_clone, magic, init, deinit);
} }
#else #else
su_port_t *su_epoll_port_create(void) 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, int su_epoll_clone_start(su_root_t *parent,
su_clone_r return_clone, su_clone_r return_clone,
su_root_magic_t *magic, su_root_magic_t *magic,
su_root_init_f init, su_root_init_f init,
su_root_deinit_f deinit) su_root_deinit_f deinit)
{ {
return su_pthreaded_port_start(su_poll_port_create, return su_default_clone_start(parent, return_clone, magic, init, deinit);
parent, return_clone, magic, init, deinit);
} }
#endif /* HAVE_EPOLL */ #endif /* HAVE_EPOLL */

View File

@ -1199,7 +1199,7 @@ static
int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult) int win_localinfo(su_localinfo_t const hints[1], su_localinfo_t **rresult)
{ {
/* This is Windows XP code, for both IPv6 and IPv4. */ /* This is Windows XP code, for both IPv6 and IPv4. */
size_t iaa_size = 2048; ULONG iaa_size = 2048;
IP_ADAPTER_ADDRESSES *iaa0, *iaa; IP_ADAPTER_ADDRESSES *iaa0, *iaa;
int error, loopback_seen = 0; int error, loopback_seen = 0;
int v4_mapped = (hints->li_flags & LI_V4MAPPED) != 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; int flags = GAA_FLAG_SKIP_MULTICAST;
*rresult = NULL; next = rresult; *rresult = NULL; next = rresult;
iaa0 = malloc(iaa_size); iaa0 = malloc((size_t)iaa_size);
if (!iaa0) { if (!iaa0) {
SU_DEBUG_1(("su_localinfo: memory exhausted\n")); SU_DEBUG_1(("su_localinfo: memory exhausted\n"));
error = ELI_MEMORY; 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 *ua;
IP_ADAPTER_UNICAST_ADDRESS lua[1]; IP_ADAPTER_UNICAST_ADDRESS lua[1];
int if_index = iaa->IfIndex; int if_index = iaa->IfIndex;
int ifnamelen = 0; size_t ifnamelen = 0;
char ifname[16]; char ifname[16];
for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) { for (ua = iaa->FirstUnicastAddress; ;ua = ua->Next) {

File diff suppressed because it is too large Load Diff

View File

@ -30,12 +30,19 @@
* @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@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" #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 <stdlib.h>
#include <assert.h> #include <assert.h>
@ -45,18 +52,12 @@
#include <limits.h> #include <limits.h>
#include <errno.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(). */ /** Port based on poll(). */
struct su_poll_port_s { 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? */ 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_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized waits */ int sup_pri_offset; /**< Offset to prioritized waits */
#if !SU_HAVE_WINSOCK
#define INDEX_MAX (0x7fffffff) #define INDEX_MAX (0x7fffffff)
#else
/* We use WSAWaitForMultipleEvents() */
#define INDEX_MAX (64)
#endif
/** Indices from index returned by su_root_register() to tables below. /** 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_base_port_incref,
su_poll_port_decref, su_poll_port_decref,
su_base_port_gsource, su_base_port_gsource,
su_pthread_port_send, su_socket_port_send,
su_poll_port_register, su_poll_port_register,
su_poll_port_unregister, su_poll_port_unregister,
su_poll_port_deregister, 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_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) 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 /**Set mask for a registered event. @internal
* *
* The function su_poll_port_eventmask() sets the mask describing events that can * The function su_poll_port_eventmask() sets the mask describing events
* signal the registered callback. * that can signal the registered callback.
* *
* @param port pointer to port object * @param port pointer to port object
* @param index registration index * @param index registration index
@ -663,7 +659,7 @@ su_port_t *su_poll_port_create(void)
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; 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 su_home_unref(su_port_home(self)), NULL;
return self; return self;
@ -675,8 +671,25 @@ int su_poll_clone_start(su_root_t *parent,
su_root_init_f init, su_root_init_f init,
su_root_deinit_f deinit) 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); 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 */

View File

@ -48,7 +48,43 @@
#include <string.h> #include <string.h>
#include <stdlib.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; static su_clone_start_f *preferred_su_clone_start;
/** Explicitly set the preferred su_port_t implementation. /** 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 (name == NULL)
; ;
#if HAVE_POLL_PORT
#if HAVE_EPOLL #if HAVE_EPOLL
else if (strcmp(name, "epoll") == 0) { else if (strcmp(name, "epoll") == 0) {
create = su_epoll_port_create; create = su_epoll_port_create;
start = su_epoll_clone_start; start = su_epoll_clone_start;
} }
#endif #endif
#if HAVE_POLL_PORT
else if (strcmp(name, "poll") == 0) { else if (strcmp(name, "poll") == 0) {
create = su_poll_port_create; create = su_poll_port_create;
start = su_poll_clone_start; start = su_poll_clone_start;
} }
#else
/* select port does not work yet */
#error no poll!
#endif #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) { else if (strcmp(name, "select") == 0) {
create = su_select_port_create; create = su_select_port_create;
start = su_select_clone_start; start = su_select_clone_start;
} }
#endif #endif
#if HAVE_POLL_PORT if (create == NULL)
#if HAVE_EPOLL create = su_default_port_create;
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 (preferred_su_port_create == NULL) preferred_su_port_create = create; if (!preferred_su_port_create ||
if (preferred_su_clone_start == NULL) preferred_su_clone_start = start; preferred_su_port_create == su_default_port_create)
preferred_su_port_create = create;
if (start == NULL)
start = su_default_clone_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. */ /** Create the preferred su_port_t implementation. */
@ -116,10 +151,7 @@ su_port_t *su_port_create(void)
if (preferred_su_port_create == NULL) if (preferred_su_port_create == NULL)
su_port_set_system_preferences(getenv("SU_PORT")); su_port_set_system_preferences(getenv("SU_PORT"));
if (preferred_su_port_create) return preferred_su_port_create();
return preferred_su_port_create();
return NULL;
} }
/* ======================================================================== /* ========================================================================
@ -244,8 +276,6 @@ int su_clone_start(su_root_t *parent,
if (parent == NULL || parent->sur_threading) { if (parent == NULL || parent->sur_threading) {
if (preferred_su_clone_start == NULL) if (preferred_su_clone_start == NULL)
su_port_set_system_preferences(getenv("SU_PORT")); 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); return preferred_su_clone_start(parent, return_clone, magic, init, deinit);
} }

View File

@ -152,26 +152,6 @@ SOFIAPUBFUN su_port_t *su_port_create(void)
/* Extension from >= 1.12.5 */ /* 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 void su_msg_delivery_report(su_msg_r msg);
SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t, SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_t const * t,
su_time_t now); su_time_t now);
@ -518,22 +498,18 @@ SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone);
#include <pthread.h> #include <pthread.h>
#define SU_MBOX_SIZE 2
/** Pthread port object */ /** Pthread port object */
typedef struct su_pthread_port_s { typedef struct su_pthread_port_s {
su_base_port_t sup_base[1]; su_base_port_t sup_base[1];
struct su_pthread_port_waiting_parent struct su_pthread_port_waiting_parent
*sup_waiting_parent; *sup_waiting_parent;
pthread_t sup_tid; pthread_t sup_tid;
pthread_mutex_t sup_runlock[1];
#if 0 #if 0
pthread_mutex_t sup_runlock[1];
pthread_cond_t sup_resume[1]; pthread_cond_t sup_resume[1];
short sup_paused; /**< True if thread is paused */ short sup_paused; /**< True if thread is paused */
#endif #endif
short sup_thread; /**< True if thread is active */ short sup_thread; /**< True if thread is active */
short sup_mbox_index;
su_socket_t sup_mbox[SU_MBOX_SIZE];
} su_pthread_port_t; } su_pthread_port_t;
/* Pthread methods */ /* 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); 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); 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_create(void);
SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent, SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent,
su_clone_r return_clone, 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_lock su_base_port_lock
#define su_pthread_port_unlock su_base_port_unlock #define su_pthread_port_unlock su_base_port_unlock
#define su_pthread_port_own_thread su_base_port_own_thread #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_wait su_base_port_wait
#define su_pthread_port_execute su_base_port_execute #define su_pthread_port_execute su_base_port_execute
#endif #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 SOFIA_END_DECLS
#endif /* SU_PORT_H */ #endif /* SU_PORT_H */

View File

@ -61,24 +61,6 @@
#define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \ #define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \
(s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0) (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0)
#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 /**@internal
* *
* Initializes a message port. It creates a mailbox used to wake up the * 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", SU_DEBUG_9(("su_pthread_port_init(%p, %p) called\n",
(void *)self, (void *)vtable)); (void *)self, (void *)vtable));
self->sup_tid = pthread_self();
if (su_base_port_init(self, vtable) == 0 && if (su_base_port_init(self, vtable) == 0 &&
su_base_port_threadsafe(self) == 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; return 0;
error:
su_log("%s: %s: %s\n",
"su_pthread_port_init", why, su_strerror(su_errno()));
su_pthread_port_deinit(self);
} }
else
SU_DEBUG_9(("%s() returns %d\n", "su_pthread_port_init", -1)); su_base_port_deinit(self);
return -1; return -1;
} }
@ -187,17 +90,6 @@ void su_pthread_port_deinit(su_port_t *self)
{ {
assert(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 #if 0
pthread_mutex_destroy(self->sup_runlock); pthread_mutex_destroy(self->sup_runlock);
pthread_cond_destroy(self->sup_resume); 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)); (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 /** @internal
* Checks if the calling thread owns the port object. * Checks if the calling thread owns the port object.
* *

View File

@ -25,12 +25,12 @@
/**@ingroup su_wait /**@ingroup su_wait
* @CFILE su_select_port.c * @CFILE su_select_port.c
* *
* Port implementation using select(). NOT IMPLEMENTED YET! * Port implementation using select().
* *
* @author Pekka Pessi <Pekka.Pessi@nokia.com> * @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@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 "config.h"
@ -51,63 +51,82 @@
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#if HAVE_WIN32
#error winsock select() not supported yet
#else
#if HAVE_SYS_SELECT_H #if HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
#elif HAVE_SYS_TIME_H #elif HAVE_SYS_TIME_H
#include <sys/time.h> #include <sys/time.h>
#endif #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(). */ /** Port based on select(). */
struct su_select_port_s { 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_multishot; /**< Multishot operation? */
unsigned sup_registers; /** Counter incremented by unsigned sup_registers; /** Counter incremented by
su_port_register() or su_port_register() or
su_port_unregister() su_port_unregister()
*/ */
int sup_n_registrations;
int sup_max_index; /**< Indexes are equal or smaller than this */
int sup_size_indices; /**< Size of allocated index table */
int sup_n_waits; /**< Active su_wait_t in su_waits */ /** Structure containing registration data */
int sup_size_waits; /**< Size of allocated su_waits */ struct su_select_register {
int sup_pri_offset; /**< Offset to prioritized waits */ 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;
/** Indices from index returned by su_root_register() to tables below. int sup_maxfd, sup_allocfd;
*
* Free elements are negative. Free elements form a list, value of free fd_set *sup_readfds, *sup_readfds2;
* element is (0 - index of next free element). fd_set *sup_writefds, *sup_writefds2;
*
* First element sup_indices[0] points to first free element.
*/
int *sup_indices;
int *sup_reverses; /** Reverse index */
su_wakeup_f *sup_wait_cbs;
su_wakeup_arg_t**sup_wait_args;
su_root_t **sup_wait_roots;
su_wait_t *sup_waits;
}; };
static void su_select_port_decref(su_port_t *, int blocking, char const *who); static void su_select_port_decref(su_port_t *self,
int blocking,
char const *who);
static int su_select_port_register(su_port_t *self, static int su_select_port_register(su_port_t *self,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
su_wakeup_arg_t *arg, su_wakeup_arg_t *arg,
int priority); int priority);
static int su_select_port_unregister(su_port_t *port, static int su_select_port_unregister(su_port_t *port,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
su_wakeup_arg_t *arg); su_wakeup_arg_t *arg);
static int su_select_port_deregister(su_port_t *self, int i); 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_unregister_all(su_port_t *self, su_root_t *root);
static int su_select_port_eventmask(su_port_t *self, static int su_select_port_eventmask(su_port_t *self,
int index, int index,
int socket, int socket,
int events); int events);
static int su_select_port_multishot(su_port_t *self, int multishot); 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 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); 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_base_port_incref,
su_select_port_decref, su_select_port_decref,
su_base_port_gsource, su_base_port_gsource,
su_pthread_port_send, su_socket_port_send,
su_select_port_register, su_select_port_register,
su_select_port_unregister, su_select_port_unregister,
su_select_port_deregister, su_select_port_deregister,
@ -142,7 +161,7 @@ su_port_vtable_t const su_select_port_vtable[1] =
su_select_port_name, su_select_port_name,
su_base_port_start_shared, su_base_port_start_shared,
su_pthread_port_wait, su_pthread_port_wait,
su_pthread_port_execute su_pthread_port_execute,
}}; }};
static char const *su_select_port_name(su_port_t const *self) 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"; 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) static void su_select_port_deinit(void *arg)
{ {
su_port_t *self = arg; su_port_t *self = arg;
SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self)); SU_DEBUG_9(("%s(%p) called\n", "su_select_port_deinit", (void *)self));
su_pthread_port_deinit(self); su_socket_port_deinit(self->sup_base);
if (self->sup_waits)
free(self->sup_waits), self->sup_waits = NULL;
if (self->sup_wait_cbs)
free(self->sup_wait_cbs), self->sup_wait_cbs = NULL;
if (self->sup_wait_args)
free(self->sup_wait_args), self->sup_wait_args = NULL;
if (self->sup_wait_roots)
free(self->sup_wait_roots), self->sup_wait_roots = NULL;
if (self->sup_reverses)
free(self->sup_reverses), self->sup_reverses = NULL;
if (self->sup_indices)
free(self->sup_indices), self->sup_indices = NULL;
SU_DEBUG_9(("%s(%p) freed registrations\n",
"su_select_port_deinit", (void *)self));
}
static void su_select_port_decref(su_port_t *self, int blocking, char const *who)
{
su_base_port_decref(self, blocking, who);
} }
/** @internal /** @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 * an argument pointer is stored in the port object. The callback function
* will be called when the wait object is signaled. * 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. * or -1 upon an error.
*/ */
int su_select_port_register(su_port_t *self, int su_select_port_register(su_port_t *self,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
su_wakeup_arg_t *arg, su_wakeup_arg_t *arg,
int priority) int priority)
{ {
int i, j, n; 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)); assert(su_port_own_thread(self));
n = self->sup_n_waits; n = self->sup_size_indices;
if (n >= SU_WAIT_MAX) if (n >= SU_WAIT_MAX)
return su_seterrno(ENOMEM); return su_seterrno(ENOMEM);
if (n >= self->sup_size_waits) {
/* Reallocate size arrays */
int size;
int *indices;
int *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t **wait_args;
su_root_t **wait_tasks;
if (self->sup_size_waits == 0)
size = su_root_size_hint;
else
size = 2 * self->sup_size_waits;
if (size < SU_WAIT_MIN)
size = SU_WAIT_MIN;
/* Too large */
if (-3 - size > 0)
return (errno = ENOMEM), -1;
indices = realloc(self->sup_indices, (size + 1) * sizeof(*indices));
if (indices) {
self->sup_indices = indices;
if (self->sup_size_waits == 0)
indices[0] = -1;
for (i = self->sup_size_waits + 1; i <= size; i++)
indices[i] = -1 - i;
}
reverses = realloc(self->sup_reverses, size * sizeof(*waits));
if (reverses) {
for (i = self->sup_size_waits; i < size; i++)
reverses[i] = -1;
self->sup_reverses = reverses;
}
waits = realloc(self->sup_waits, size * sizeof(*waits));
if (waits)
self->sup_waits = waits;
wait_cbs = realloc(self->sup_wait_cbs, size * sizeof(*wait_cbs));
if (wait_cbs)
self->sup_wait_cbs = wait_cbs;
wait_args = realloc(self->sup_wait_args, size * sizeof(*wait_args));
if (wait_args)
self->sup_wait_args = wait_args;
/* Add sup_wait_roots array, if needed */
wait_tasks = realloc(self->sup_wait_roots, size * sizeof(*wait_tasks));
if (wait_tasks)
self->sup_wait_roots = wait_tasks;
if (!(indices &&
reverses && waits && wait_cbs && wait_args && wait_tasks)) {
return -1;
}
self->sup_size_waits = size;
}
i = -self->sup_indices[0]; assert(i <= self->sup_size_waits);
if (priority > 0) {
/* Insert */
for (n = self->sup_n_waits; n > 0; n--) {
j = self->sup_reverses[n-1]; assert(self->sup_indices[j] == n - 1);
self->sup_indices[j] = n;
self->sup_reverses[n] = j;
self->sup_waits[n] = self->sup_waits[n-1];
self->sup_wait_cbs[n] = self->sup_wait_cbs[n-1];
self->sup_wait_args[n] = self->sup_wait_args[n-1];
self->sup_wait_roots[n] = self->sup_wait_roots[n-1];
}
self->sup_pri_offset++;
}
else {
/* Append - no need to move anything */
n = self->sup_n_waits;
}
self->sup_n_waits++;
self->sup_indices[0] = self->sup_indices[i]; /* Free index */
self->sup_indices[i] = n;
self->sup_reverses[n] = i;
self->sup_waits[n] = *wait;
self->sup_wait_cbs[n] = callback;
self->sup_wait_args[n] = arg;
self->sup_wait_roots[n] = root;
self->sup_registers++; self->sup_registers++;
/* We return -1 or positive integer */ if (wait->fd >= allocfd)
allocfd += __NFDBITS; /* long at a time */
return i; if (allocfd >= self->sup_allocfd) {
size_t bytes = FDSETSIZE(allocfd);
size_t bytes0 = FDSETSIZE(self->sup_allocfd);
/* (Re)allocate fd_sets */
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;
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;
}
ser = indices[0];
if (!ser) {
su_home_t *h = su_port_home(self);
i = self->sup_max_index, j = i == 0 ? 15 : i + 16;
if (j >= self->sup_size_indices) {
/* Reallocate index table */
n = n < 1024 ? 2 * n : n + 1024;
indices = su_realloc(h, indices, n * sizeof(indices[0]));
if (!indices)
return -1;
self->sup_indices = indices;
self->sup_size_indices = n;
}
/* Allocate registrations */
ser = su_zalloc(h, (j - i) * (sizeof *ser));
if (!ser)
return -1;
indices[0] = ser;
for (i++; i <= j; i++) {
ser->ser_id = i;
ser->ser_next = i < j ? ser + 1 : NULL;
indices[i] = ser++;
}
self->sup_max_index = j;
ser = indices[0];
}
i = ser->ser_id;
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;
if (wait->events & SU_WAIT_IN)
FD_SET(wait->fd, readfds);
if (wait->events & SU_WAIT_OUT)
FD_SET(wait->fd, writefds);
if (wait->fd >= self->sup_maxfd)
self->sup_maxfd = wait->fd + 1;
self->sup_n_registrations++;
return i; /* return index */
}
static void su_select_port_update_maxfd(su_port_t *self)
{
int i;
su_socket_t maxfd = 0;
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;
}
self->sup_maxfd = maxfd;
} }
/** Deregister a su_wait_t object. */ /** Deregister a su_wait_t object. */
static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait) static int su_select_port_deregister0(su_port_t *self, int i, int destroy_wait)
{ {
int n, N, *indices, *reverses; struct su_select_register **indices = self->sup_indices;
struct su_select_register *ser;
indices = self->sup_indices; ser = self->sup_indices[i];
reverses = self->sup_reverses; if (ser == NULL || ser->ser_cb == NULL) {
su_seterrno(ENOENT);
n = indices[i]; assert(n >= 0); return -1;
if (destroy_wait)
su_wait_destroy(&self->sup_waits[n]);
N = --self->sup_n_waits;
if (n < self->sup_pri_offset) {
int j = --self->sup_pri_offset;
if (n != j) {
assert(reverses[j] > 0);
assert(indices[reverses[j]] == j);
indices[reverses[j]] = n;
reverses[n] = reverses[j];
self->sup_waits[n] = self->sup_waits[j];
self->sup_wait_cbs[n] = self->sup_wait_cbs[j];
self->sup_wait_args[n] = self->sup_wait_args[j];
self->sup_wait_roots[n] = self->sup_wait_roots[j];
n = j;
}
} }
if (n < N) { assert(ser->ser_id == i);
assert(reverses[N] > 0);
assert(indices[reverses[N]] == N);
indices[reverses[N]] = n; FD_CLR(ser->ser_wait->fd, self->sup_readfds);
reverses[n] = reverses[N]; FD_CLR(ser->ser_wait->fd, self->sup_writefds);
self->sup_waits[n] = self->sup_waits[N]; if (ser->ser_wait->fd + 1 >= self->sup_maxfd)
self->sup_wait_cbs[n] = self->sup_wait_cbs[N]; self->sup_maxfd = 0;
self->sup_wait_args[n] = self->sup_wait_args[N];
self->sup_wait_roots[n] = self->sup_wait_roots[N];
n = N;
}
reverses[n] = -1; memset(ser, 0, sizeof *ser);
memset(&self->sup_waits[n], 0, sizeof self->sup_waits[n]); ser->ser_id = i;
self->sup_wait_cbs[n] = NULL; ser->ser_next = indices[0], indices[0] = ser;
self->sup_wait_args[n] = NULL;
self->sup_wait_roots[n] = NULL;
indices[i] = indices[0];
indices[0] = -i;
self->sup_n_registrations--;
self->sup_registers++; self->sup_registers++;
return i; 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. /** Unregister a su_wait_t object.
* *
* The function su_select_port_unregister() unregisters a su_wait_t object. The * The function su_select_port_unregister() unregisters a su_wait_t object.
* wait object, a callback function and a argument are removed from the * The registration defined by the wait object, the callback function and
* port object. * the argument pointer are removed from the port object.
* *
* @param self - pointer to port object * @param self - pointer to port object
* @param root - pointer to root 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. * @return Nonzero index of the wait object, or -1 upon an error.
*/ */
int su_select_port_unregister(su_port_t *self, int su_select_port_unregister(su_port_t *self,
su_root_t *root, su_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */ su_wakeup_f callback, /* XXX - ignored */
su_wakeup_arg_t *arg) su_wakeup_arg_t *arg)
{ {
int n, N; int i, I;
struct su_select_register *ser;
assert(self); assert(self);
assert(su_port_own_thread(self)); assert(su_port_own_thread(self));
N = self->sup_n_waits; I = self->sup_max_index;
for (n = 0; n < N; n++) { for (i = 1; i <= I; i++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { ser = self->sup_indices[i];
return su_select_port_deregister0(self, self->sup_reverses[n], 0);
} 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); 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) int su_select_port_deregister(su_port_t *self, int i)
{ {
su_wait_t wait[1] = { SU_WAIT_INIT }; struct su_select_register *ser;
int retval;
assert(self); if (i <= 0 || i > self->sup_max_index)
assert(su_port_own_thread(self));
if (i <= 0 || i > self->sup_size_waits)
return su_seterrno(EBADF); return su_seterrno(EBADF);
if (self->sup_indices[i] < 0) ser = self->sup_indices[i];
if (!ser->ser_cb)
return su_seterrno(EBADF); return su_seterrno(EBADF);
retval = su_select_port_deregister0(self, i, 1);
su_wait_destroy(wait); return su_select_port_deregister0(self, i, 1);
return retval;
} }
/** @internal /** @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 * The function su_select_port_unregister_all() unregisters all su_wait_t
* and destroys all queued timers associated with given root object. * objects associated with given root object.
* *
* @param self - pointer to port object * @param self - pointer to port object
* @param root - pointer to root object * @param root - pointer to root object
* *
* @return Number of wait objects removed. * @return Number of wait objects removed.
*/ */
int su_select_port_unregister_all(su_port_t *self, int su_select_port_unregister_all(su_port_t *self, su_root_t *root)
su_root_t *root)
{ {
int i, j, index, N; int i, I, n;
int *indices, *reverses;
su_wait_t *waits;
su_wakeup_f *wait_cbs;
su_wakeup_arg_t**wait_args;
su_root_t **wait_roots;
struct su_select_register *ser;
assert(self); assert(root);
assert(su_port_own_thread(self)); assert(su_port_own_thread(self));
N = self->sup_n_waits; I = self->sup_max_index;
indices = self->sup_indices;
reverses = self->sup_reverses;
waits = self->sup_waits;
wait_cbs = self->sup_wait_cbs;
wait_args = self->sup_wait_args;
wait_roots = self->sup_wait_roots;
for (i = j = 0; i < N; i++) {
index = reverses[i]; assert(index > 0 && indices[index] == i);
if (wait_roots[i] == root) { for (i = 1, n = 0; i <= I; i++) {
/* XXX - we should free all resources associated with this, too */ ser = self->sup_indices[i];
if (i < self->sup_pri_offset) if (ser->ser_root != root)
self->sup_pri_offset--;
indices[index] = indices[0];
indices[0] = -index;
continue; continue;
} su_select_port_deregister0(self, ser->ser_id, 0);
n++;
if (i != j) {
indices[index] = j;
reverses[j] = reverses[i];
waits[j] = waits[i];
wait_cbs[j] = wait_cbs[i];
wait_args[j] = wait_args[i];
wait_roots[j] = wait_roots[i];
}
j++;
} }
for (i = j; i < N; i++) {
reverses[i] = -1;
wait_cbs[i] = NULL;
wait_args[i] = NULL;
wait_roots[i] = NULL;
}
memset(&waits[j], 0, (char *)&waits[N] - (char *)&waits[j]);
self->sup_n_waits = j; return n;
self->sup_registers++;
return N - j;
} }
/**Set mask for a registered event. @internal /**Set mask for a registered event. @internal
* *
* The function su_select_port_eventmask() sets the mask describing events that can * The function su_select_port_eventmask() sets the mask describing events
* signal the registered callback. * that can signal the registered callback.
* *
* @param port pointer to port object * @param port pointer to port object
* @param index registration index * @param index registration index
@ -538,19 +477,41 @@ int su_select_port_unregister_all(su_port_t *self,
* @retval 0 when successful, * @retval 0 when successful,
* @retval -1 upon an error. * @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; struct su_select_register *ser;
assert(self);
assert(su_port_own_thread(self));
if (index <= 0 || index > self->sup_size_waits) if (index <= 0 || index > self->sup_max_index)
return su_seterrno(EBADF);
n = self->sup_indices[index];
if (n < 0)
return su_seterrno(EBADF); return su_seterrno(EBADF);
return su_wait_mask(&self->sup_waits[n], socket, events); ser = self->sup_indices[index];
if (!ser->ser_cb)
return su_seterrno(EBADF);
if (self->sup_maxfd == 0)
su_select_port_update_maxfd(self);
if (socket >= self->sup_maxfd)
return su_seterrno(EBADF);
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. /** @internal Enable multishot mode.
@ -580,7 +541,7 @@ int su_select_port_multishot(su_port_t *self, int multishot)
/** @internal /** @internal
* Wait (select()) for wait objects in port. * Wait (poll()) for wait objects in port.
* *
* @param self pointer to port * @param self pointer to port
* @param tout timeout in milliseconds * @param tout timeout in milliseconds
@ -590,78 +551,107 @@ int su_select_port_multishot(su_port_t *self, int multishot)
static static
int su_select_port_wait_events(su_port_t *self, su_duration_t tout) int su_select_port_wait_events(su_port_t *self, su_duration_t tout)
{ {
/* NOT IMPLEMENTED */ int j, n, events = 0;
(void)su_select_port_deinit; 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 bytes = self->sup_maxfd ? FDSETSIZE(self->sup_maxfd - 1) : 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) if (bytes) {
f = stdout; rset = memcpy(self->sup_readfds2, self->sup_readfds, bytes);
wset = memcpy(self->sup_writefds2, self->sup_writefds, bytes);
}
fprintf(f, "su_port_t at %p:\n", self); tv.tv_sec = tout / 1000;
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not "); tv.tv_usec = (tout % 1000) * 1000;
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid); n = select(self->sup_maxfd, rset, wset, NULL, &tv);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait), if (n <= 0) {
IS_WAIT_OUT(&self->sup_mbox_wait), SU_DEBUG_0(("su_select_port_wait_events(%p): %s (%d)\n",
IS_WAIT_ACCEPT(&self->sup_mbox_wait)); (void *)self, su_strerror(su_errno()), su_errno()));
#endif return 0;
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
} }
for (j = 1; j < self->sup_max_index; j++) {
struct su_select_register *ser;
su_root_magic_t *magic;
int fd;
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;
} }
#endif /** Create a port using epoll() or poll().
/** Create a port using select().
*/ */
su_port_t *su_select_port_create(void) su_port_t *su_select_port_create(void)
{ {
#if notyet su_port_t *self;
su_port_t *self = su_home_new(sizeof *self);
self = su_home_new(sizeof *self);
if (!self) if (!self)
return self; return NULL;
if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0) if (su_home_destructor(su_port_home(self), su_select_port_deinit) < 0 ||
return su_home_unref(su_port_home(self)), NULL; !(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; 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 su_home_unref(su_port_home(self)), NULL;
return self; return self;
#else
return NULL;
#endif
} }
int su_select_clone_start(su_root_t *parent, int su_select_clone_start(su_root_t *parent,
su_clone_r return_clone, su_clone_r return_clone,
su_root_magic_t *magic, su_root_magic_t *magic,
su_root_init_f init, su_root_init_f init,
su_root_deinit_f deinit) su_root_deinit_f deinit)
{ {
return su_pthreaded_port_start(su_select_port_create, return su_pthreaded_port_start(su_select_port_create,
parent, return_clone, magic, init, deinit); parent, return_clone, magic, init, deinit);
} }
#endif #endif

View File

@ -193,7 +193,10 @@ RBTREE_BODIES(static inline, timers, su_timer_t,
IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR, IS_RED, SET_RED, IS_BLACK, SET_BLACK, COPY_COLOR,
CMP, INSERT, REMOVE); CMP, INSERT, REMOVE);
/** Set the timer. */ /**@internal Set the timer.
*
* @retval 0 when successful (always)
*/
static inline int static inline int
su_timer_set0(su_timer_t **timers, su_timer_set0(su_timer_t **timers,
su_timer_t *t, su_timer_t *t,
@ -212,7 +215,10 @@ su_timer_set0(su_timer_t **timers,
return timers_append(timers, t); return timers_append(timers, t);
} }
/** Reset the timer. */ /**@internal Reset the timer.
*
* @retval 0 when successful (always)
*/
static inline int static inline int
su_timer_reset0(su_timer_t **timers, su_timer_reset0(su_timer_t **timers,
su_timer_t *t) su_timer_t *t)
@ -229,6 +235,40 @@ su_timer_reset0(su_timer_t **timers,
return 0; 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. /**Create a timer.
* *
@ -291,23 +331,12 @@ int su_timer_set_interval(su_timer_t *t,
su_timer_arg_t *arg, su_timer_arg_t *arg,
su_duration_t interval) su_duration_t interval)
{ {
char const *func = "su_timer_set_interval"; su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_interval");
su_timer_t **timers;
if (t == NULL) { if (t == NULL)
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
return -1; return -1;
}
timers = su_task_timers(t->sut_task); return su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, su_now(), interval);
return 0;
} }
/** Set the timer for the default 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_f wakeup,
su_timer_arg_t *arg) 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; return -1;
assert(t->sut_duration > 0); return su_timer_set0(timers, t, wakeup, arg, su_now(), t->sut_duration);
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);
} }
/** Set timer at known time. /** Set timer at known time.
@ -357,23 +379,12 @@ int su_timer_set_at(su_timer_t *t,
su_wakeup_arg_t *arg, su_wakeup_arg_t *arg,
su_time_t when) su_time_t when)
{ {
char const *func = "su_timer_set_at"; su_timer_t **timers = su_timer_tree(t, 0, "su_timer_set_at");
su_timer_t **timers;
if (t == NULL) { if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
return -1; return -1;
}
timers = su_task_timers(t->sut_task); return su_timer_set0(timers, t, wakeup, arg, when, 0);
if (timers == NULL) {
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "invalid timer"));
return -1;
}
su_timer_set0(timers, t, wakeup, arg, when, 0);
return 0;
} }
/** Set the timer for regular intervals. /** Set the timer for regular intervals.
@ -398,35 +409,17 @@ int su_timer_run(su_timer_t *t,
su_timer_f wakeup, su_timer_f wakeup,
su_timer_arg_t *arg) su_timer_arg_t *arg)
{ {
char const *func = "su_timer_run"; su_timer_t **timers = su_timer_tree(t, 1, "su_timer_run");
su_timer_t **timers; su_time_t now;
su_time_t now = su_now();
if (t == NULL) { if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
return -1; 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_running = run_at_intervals;
t->sut_run = now; t->sut_run = now = su_now();
t->sut_woken = 0; t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration); return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
} }
/**Set the timer for regular intervals. /**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_f wakeup,
su_timer_arg_t *arg) su_timer_arg_t *arg)
{ {
char const *func = "su_timer_set_for_ever"; su_timer_t **timers = su_timer_tree(t, 1, "su_timer_set_for_ever");
su_timer_t **timers; su_time_t now;
su_time_t now = su_now();
if (t == NULL) { if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
return -1; 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_for_ever; t->sut_running = run_for_ever;
t->sut_run = now; t->sut_run = now = su_now();
t->sut_woken = 0; t->sut_woken = 0;
su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration); return su_timer_set0(timers, t, wakeup, arg, now, t->sut_duration);
return 0;
} }
/**Reset the timer. /**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) int su_timer_reset(su_timer_t *t)
{ {
char const *func = "su_timer_reset"; su_timer_t **timers = su_timer_tree(t, 0, "su_timer_reset");
su_timer_t **timers;
if (t == NULL) { if (timers == NULL)
SU_DEBUG_1(("%s(%p): %s\n", func, (void *)t, "NULL argument"));
return -1; return -1;
}
timers = su_task_timers(t->sut_task); return su_timer_reset0(timers, t);
su_timer_reset0(timers, t);
return 0;
} }
/** @internal Check for expired timers in queue. /** @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 su_timer_next_expires(su_timer_t const * t, su_time_t now)
{ {
su_duration_t tout; 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. /** Get the root object owning the timer.
* *
* The function su_timer_root() return pointer to the root object owning the * Return pointer to the root object owning the timer.
* timer.
* *
* @param t pointer to 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) 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;
} }

View File

@ -23,19 +23,24 @@
*/ */
/**@ingroup su_wait /**@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 Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Kai Vehmanen <kai.vehmanen@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" #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 <stdlib.h>
#include <assert.h> #include <assert.h>
@ -45,18 +50,14 @@
#include <limits.h> #include <limits.h>
#include <errno.h> #include <errno.h>
#define su_port_s su_poll_port_s /** Port based on su_wait() aka WSAWaitForMultipleEvents. */
#include "sofia-sip/su.h" #define INDEX_MAX (64)
#include "su_port.h"
#include "sofia-sip/su_alloc.h"
/** Port based on poll(). */ struct su_wsaevent_port_s {
su_socket_port_t sup_base[1];
struct su_poll_port_s { #define sup_home sup_base->sup_base->sup_base->sup_home
su_pthread_port_t sup_base[1];
#define sup_home sup_base->sup_base->sup_home
unsigned sup_multishot; /**< Multishot operation? */ 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_size_waits; /**< Size of allocated su_waits */
int sup_pri_offset; /**< Offset to prioritized 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. /** Indices from index returned by su_root_register() to tables below.
* *
* Free elements are negative. Free elements form a list, value of free * 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_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
su_wakeup_arg_t *arg, su_wakeup_arg_t *arg,
int priority); 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_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
su_wakeup_arg_t *arg); su_wakeup_arg_t *arg);
static int su_poll_port_deregister(su_port_t *self, int i); static int su_wsevent_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_wsevent_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_eventmask(su_port_t *self,
int index, int index,
int socket, int socket,
int events); int events);
static int su_poll_port_multishot(su_port_t *self, int multishot); static int su_wsevent_port_multishot(su_port_t *self, int multishot);
static int su_poll_port_wait_events(su_port_t *self, su_duration_t tout); static int su_wsevent_port_wait_events(su_port_t *self, su_duration_t tout);
static char const *su_poll_port_name(su_port_t const *self); 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_lock,
su_pthread_port_unlock, su_pthread_port_unlock,
su_base_port_incref, su_base_port_incref,
su_poll_port_decref, su_wsevent_port_decref,
su_base_port_gsource, su_base_port_gsource,
su_pthread_port_send, su_socket_port_send,
su_poll_port_register, su_wsevent_port_register,
su_poll_port_unregister, su_wsevent_port_unregister,
su_poll_port_deregister, su_wsevent_port_deregister,
su_poll_port_unregister_all, su_wsevent_port_unregister_all,
su_poll_port_eventmask, su_wsevent_port_eventmask,
su_base_port_run, su_base_port_run,
su_base_port_break, su_base_port_break,
su_base_port_step, 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_add_prepoll,
su_base_port_remove_prepoll, su_base_port_remove_prepoll,
su_base_port_timers, su_base_port_timers,
su_poll_port_multishot, su_wsevent_port_multishot,
su_base_port_threadsafe, su_base_port_threadsafe,
su_base_port_yield, su_base_port_yield,
su_poll_port_wait_events, su_wsevent_port_wait_events,
su_base_port_getmsgs, su_base_port_getmsgs,
su_base_port_getmsgs_from, su_base_port_getmsgs_from,
su_poll_port_name, su_wsevent_port_name,
su_base_port_start_shared, su_base_port_start_shared,
su_pthread_port_wait, su_pthread_port_wait,
su_pthread_port_execute, 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"; return "poll";
} }
static void su_poll_port_deinit(void *arg) static void su_wsevent_port_deinit(void *arg)
{ {
su_port_t *self = 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); 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, * Positive index of the wait object,
* or -1 upon an error. * 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_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, su_wakeup_f callback,
@ -311,7 +305,7 @@ int su_poll_port_register(su_port_t *self,
} }
/** Deregister a su_wait_t object. */ /** 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; 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. /** Unregister a su_wait_t object.
* *
* The function su_poll_port_unregister() unregisters a su_wait_t object. The * Unregisters a su_wait_t object. The wait object, a callback function and
* wait object, a callback function and a argument are removed from the * a argument are removed from the port object.
* port object.
* *
* @param self - pointer to port object * @param self - pointer to port object
* @param root - pointer to root 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 * @param arg - argument given to callback function when it is invoked
* (may be NULL) * (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. * @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_root_t *root,
su_wait_t *wait, su_wait_t *wait,
su_wakeup_f callback, /* XXX - ignored */ 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++) { for (n = 0; n < N; n++) {
if (SU_WAIT_CMP(wait[0], self->sup_waits[n]) == 0) { 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. * @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 }; su_wait_t wait[1] = { SU_WAIT_INIT };
int retval; int retval;
@ -436,7 +429,7 @@ int su_poll_port_deregister(su_port_t *self, int i)
if (self->sup_indices[i] < 0) if (self->sup_indices[i] < 0)
return su_seterrno(EBADF); return su_seterrno(EBADF);
retval = su_poll_port_deregister0(self, i, 1); retval = su_wsevent_port_deregister0(self, i, 1);
su_wait_destroy(wait); su_wait_destroy(wait);
@ -447,15 +440,15 @@ int su_poll_port_deregister(su_port_t *self, int i)
/** @internal /** @internal
* Unregister all su_wait_t objects. * Unregister all su_wait_t objects.
* *
* The function su_poll_port_unregister_all() unregisters all su_wait_t objects * Unregisters all su_wait_t objects and destroys all queued timers
* and destroys all queued timers associated with given root object. * associated with given root object.
* *
* @param self - pointer to port object * @param self - pointer to port object
* @param root - pointer to root object * @param root - pointer to root object
* *
* @return Number of wait objects removed. * @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) su_root_t *root)
{ {
int i, j, index, N; 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 /**Set mask for a registered event. @internal
* *
* The function su_poll_port_eventmask() sets the mask describing events that can * Sets the mask describing events that can signal the registered callback.
* signal the registered callback.
* *
* @param port pointer to port object * @param port pointer to port object
* @param index registration index * @param index registration index
@ -527,7 +519,7 @@ int su_poll_port_unregister_all(su_port_t *self,
* @retval 0 when successful, * @retval 0 when successful,
* @retval -1 upon an error. * @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; int n;
assert(self); 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 * @retval -1 an error occurred
*/ */
static 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) if (multishot < 0)
return self->sup_multishot; return self->sup_multishot;
@ -577,7 +569,7 @@ int su_poll_port_multishot(su_port_t *self, int multishot)
* @return number of events handled * @return number of events handled
*/ */
static 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; int i, events = 0;
su_wait_t *waits = self->sup_waits; 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; return events;
} }
#if 0 /** Create a port using WSAEVENTs and WSAWaitForMultipleEvents. */
/** @internal su_port_t *su_wsaevent_port_create(void)
* Prints out the contents of the port.
*
* @param self pointer to a port
* @param f pointer to a file (if @c NULL, uses @c stdout).
*/
void su_port_dump(su_port_t const *self, FILE *f)
{
int i;
#define IS_WAIT_IN(x) (((x)->events & SU_WAIT_IN) ? "IN" : "")
#define IS_WAIT_OUT(x) (((x)->events & SU_WAIT_OUT) ? "OUT" : "")
#define IS_WAIT_ACCEPT(x) (((x)->events & SU_WAIT_ACCEPT) ? "ACCEPT" : "")
if (f == NULL)
f = stdout;
fprintf(f, "su_port_t at %p:\n", self);
fprintf(f, "\tport is%s running\n", self->sup_running ? "" : "not ");
#if SU_HAVE_PTHREADS
fprintf(f, "\tport tid %p\n", (void *)self->sup_tid);
fprintf(f, "\tport mbox %d (%s%s%s)\n", self->sup_mbox[0],
IS_WAIT_IN(&self->sup_mbox_wait),
IS_WAIT_OUT(&self->sup_mbox_wait),
IS_WAIT_ACCEPT(&self->sup_mbox_wait));
#endif
fprintf(f, "\t%d wait objects\n", self->sup_n_waits);
for (i = 0; i < self->sup_n_waits; i++) {
}
}
#endif
/** Create a port using epoll() or poll().
*/
su_port_t *su_poll_port_create(void)
{ {
su_port_t *self = su_home_new(sizeof *self); su_port_t *self = su_home_new(sizeof *self);
if (!self) if (!self)
return 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; return su_home_unref(su_port_home(self)), NULL;
self->sup_multishot = SU_ENABLE_MULTISHOT_POLL; 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 su_home_unref(su_port_home(self)), NULL;
return self; return self;
} }
int su_poll_clone_start(su_root_t *parent, int su_wsaevent_clone_start(su_root_t *parent,
su_clone_r return_clone, su_clone_r return_clone,
su_root_magic_t *magic, su_root_magic_t *magic,
su_root_init_f init, su_root_init_f init,
su_root_deinit_f deinit) 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); parent, return_clone, magic, init, deinit);
} }
#endif /* HAVE_POLL */

View File

@ -100,7 +100,7 @@ int test_sockaddr(void)
TEST(su_setblocking(s, 1), 0); TEST(su_setblocking(s, 1), 0);
TEST(su_close(s), 0); TEST(su_close(s), 0);
su_freelocalinfo(res); su_freelocalinfo(res), res = NULL;
#if SU_HAVE_IN6 #if SU_HAVE_IN6
hints->li_family = AF_INET6; hints->li_family = AF_INET6;
@ -111,16 +111,17 @@ int test_sockaddr(void)
for (li = res; li; li = li->li_next) for (li = res; li; li = li->li_next)
TEST(li->li_family, AF_INET6); TEST(li->li_family, AF_INET6);
su_freelocalinfo(res); su_freelocalinfo(res), res = NULL;
#endif #endif
hints->li_flags |= LI_NUMERIC; hints->li_flags |= LI_NUMERIC;
TEST(su_getlocalinfo(hints, &res), 0); TEST(su_getlocalinfo(hints, &res), 0);
su_freelocalinfo(res), res = NULL;
hints->li_flags |= LI_NAMEREQD;
res = NULL; res = NULL;
hints->li_flags |= LI_NAMEREQD;
su_getlocalinfo(hints, &res); su_getlocalinfo(hints, &res);
su_freelocalinfo(res); su_freelocalinfo(res), res = NULL;
memset(a, 0, sizeof *a); memset(a, 0, sizeof *a);
memset(b, 0, sizeof *b); memset(b, 0, sizeof *b);
@ -161,7 +162,7 @@ int test_sockaddr(void)
int test_sendrecv(void) int test_sendrecv(void)
{ {
int s, l, a; su_socket_t s, l, a;
int n; int n;
su_sockaddr_t su, csu; su_sockaddr_t su, csu;
socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin; socklen_t sulen = sizeof su.su_sin, csulen = sizeof csu.su_sin;
@ -260,6 +261,120 @@ int test_sendrecv(void)
END(); 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> #include <sofia-sip/su_md5.h>
int test_md5(void) int test_md5(void)
@ -395,10 +510,10 @@ int main(int argc, char *argv[])
retval |= test_sockaddr(); retval |= test_sockaddr();
retval |= test_sendrecv(); retval |= test_sendrecv();
retval |= test_select();
retval |= test_md5(); fflush(stdout); retval |= test_md5(); fflush(stdout);
su_deinit(); su_deinit();
return retval; return retval;
} }

View File

@ -533,10 +533,30 @@ void usage(void)
int main(int argc, char *argv[]) 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 retval = 0;
int i; 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; rt->rt_family = AF_INET;
for (i = 1; argv[i]; i++) { for (i = 1; argv[i]; i++) {
@ -550,14 +570,23 @@ int main(int argc, char *argv[])
usage(); usage();
} }
retval |= init_test(rt); i = 0;
retval |= register_test(rt);
retval |= event_test(rt); do {
su_root_threading(rt->rt_root, 1); rt = rt1, *rt = *rt0;
retval |= clone_test(rt); printf("%s: testing %s implementation\n",
su_root_threading(rt->rt_root, 0); name, prefer[i].preference);
retval |= clone_test(rt); su_port_prefer(prefer[i].create, prefer[i].start);
retval |= deinit_test(rt);
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; return retval;
} }

View File

@ -1117,7 +1117,7 @@ int tport_get_params(tport_t const *self,
|| !tport_is_primary(self) || !tport_is_dgram(self); || !tport_is_primary(self) || !tport_is_dgram(self);
n = tl_tgets(ta_args(ta), n = tl_tgets(ta_args(ta),
TPTAG_MTU(tpp->tpp_mtu), TPTAG_MTU((usize_t)tpp->tpp_mtu),
TPTAG_REUSE(self->tp_reusable), TPTAG_REUSE(self->tp_reusable),
TPTAG_CONNECT(connect), TPTAG_CONNECT(connect),
TPTAG_QUEUESIZE(tpp->tpp_qsize), TPTAG_QUEUESIZE(tpp->tpp_qsize),
@ -1153,14 +1153,16 @@ int tport_set_params(tport_t *self,
ta_list ta; ta_list ta;
int n; int n;
tport_params_t tpp[1], *tpp0; tport_params_t tpp[1], *tpp0;
usize_t mtu;
int connect, sdwn_error, reusable, stun_server; int connect, sdwn_error, reusable, stun_server;
if (self == NULL) if (self == NULL)
return su_seterrno(EINVAL); return su_seterrno(EINVAL);
memcpy(tpp, tpp0 = self->tp_params, sizeof *tpp); memcpy(tpp, tpp0 = self->tp_params, sizeof *tpp);
mtu = tpp->tpp_mtu;
connect = tpp->tpp_conn_orient; connect = tpp->tpp_conn_orient;
sdwn_error = tpp->tpp_sdwn_error; sdwn_error = tpp->tpp_sdwn_error;
reusable = self->tp_reusable; reusable = self->tp_reusable;
@ -1169,7 +1171,7 @@ int tport_set_params(tport_t *self,
ta_start(ta, tag, value); ta_start(ta, tag, value);
n = tl_gets(ta_args(ta), 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)), TAG_IF(!self->tp_queue, TPTAG_QUEUESIZE_REF(tpp->tpp_qsize)),
TPTAG_IDLE_REF(tpp->tpp_idle), TPTAG_IDLE_REF(tpp->tpp_idle),
TPTAG_TIMEOUT_REF(tpp->tpp_timeout), TPTAG_TIMEOUT_REF(tpp->tpp_timeout),
@ -1202,6 +1204,9 @@ int tport_set_params(tport_t *self,
if (tpp->tpp_qsize >= 1000) if (tpp->tpp_qsize >= 1000)
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 */ /* Currently only primary UDP transport can *not* be connection oriented */
tpp->tpp_conn_orient = connect; tpp->tpp_conn_orient = connect;
tpp->tpp_sdwn_error = sdwn_error; tpp->tpp_sdwn_error = sdwn_error;

View File

@ -151,8 +151,12 @@
#undef HAVE_INTTYPES_H #undef HAVE_INTTYPES_H
/* Define to 1 if you have the <iphlpapi.h> header file. */ /* 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 #undef HAVE_IPHLPAPI_H
#endif
/* Define to 1 if you have IPV6_RECVERR in <netinet/in6.h> */ /* Define to 1 if you have IPV6_RECVERR in <netinet/in6.h> */
#undef HAVE_IPV6_RECVERR #undef HAVE_IPV6_RECVERR
@ -224,7 +228,7 @@
#undef HAVE_POLL #undef HAVE_POLL
/* Define to 1 if you use poll in su_port. */ /* 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 */ /* Define to 1 if you have /proc/net/if_inet6 control file */
#undef HAVE_PROC_NET_IF_INET6 #undef HAVE_PROC_NET_IF_INET6

View File

@ -57,6 +57,7 @@
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
DebugInformationFormat="4" DebugInformationFormat="4"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -135,6 +136,7 @@
WarnAsError="true" WarnAsError="true"
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -542,6 +544,10 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\libsofia-sip-ua\su\su_socket_port.c"
>
</File>
<File <File
RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c" RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c"
> >

View File

@ -63,6 +63,7 @@
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
DebugInformationFormat="4" DebugInformationFormat="4"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -77,7 +78,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib advapi32.lib" AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"
OutputFile=".\Debug/libsofia_sip_ua.dll" OutputFile=".\Debug/libsofia_sip_ua.dll"
LinkIncremental="2" LinkIncremental="2"
SuppressStartupBanner="true" SuppressStartupBanner="true"
@ -164,6 +165,7 @@
WarnAsError="true" WarnAsError="true"
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -178,7 +180,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib" AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"
OutputFile=".\Release/libsofia_sip_ua.dll" OutputFile=".\Release/libsofia_sip_ua.dll"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="true" SuppressStartupBanner="true"
@ -585,6 +587,10 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\libsofia-sip-ua\su\su_socket_port.c"
>
</File>
<File <File
RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c" RelativePath="..\..\libsofia-sip-ua\su\su_sprintf.c"
> >

View File

@ -62,6 +62,7 @@
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
DebugInformationFormat="4" DebugInformationFormat="4"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"
@ -160,6 +161,7 @@
WarnAsError="true" WarnAsError="true"
SuppressStartupBanner="true" SuppressStartupBanner="true"
Detect64BitPortabilityProblems="true" Detect64BitPortabilityProblems="true"
CompileAs="1"
/> />
<Tool <Tool
Name="VCManagedResourceCompilerTool" Name="VCManagedResourceCompilerTool"

View File

@ -76,7 +76,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib" AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"
OutputFile=".\Release/sip_options_static.exe" OutputFile=".\Release/sip_options_static.exe"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="true" SuppressStartupBanner="true"
@ -173,7 +173,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="ws2_32.lib advapi32.lib" AdditionalDependencies="ws2_32.lib advapi32.lib iphlpapi.lib"
OutputFile=".\Debug/sip_options_static.exe" OutputFile=".\Debug/sip_options_static.exe"
LinkIncremental="2" LinkIncremental="2"
SuppressStartupBanner="true" SuppressStartupBanner="true"