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