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