sync with latest sofia tree.

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5574 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris
2007-08-06 19:24:10 +00:00
parent 7e81dbe5b0
commit 19561a8411
154 changed files with 6238 additions and 2474 deletions
+14 -2
View File
@@ -9,6 +9,9 @@ Changes since last release
and in less than 10 lines, written in 3rd person English, with
complete sentences />
The stack now compiles and runs on Symbian SDK with Open C support
enabled.
Bugs in blaa and foo have been fixed. The stack now supports
use of foobar...
@@ -24,10 +27,13 @@ API/ABI changes and versioning
New features in API are marked with Doxytag macro @VERSION_1_12_7.
libsofia-sip-ua:
- Added access point selection functionality for Open C / Symbian
- Removed extra system headers from <sofia-sip/stun_common.h>
- Added global variable su_socket_blocking. If it is set to true,
sockets are created as blocking.
- Added accessor function nta_outgoing_branch()
- Added SIP headers Alert-Info and Reply-To.
- Added macros SIP_HAVE_XXXX for extra headers, e.g., SIP_HAVE_ALERT_INFO().
- **template**: Added foobar() function (sofia-sip/foobar.h).
- This release is ABI/API compatible with applications linked against
any 1.12.x release. However, applications built against this release won't
@@ -52,7 +58,7 @@ Contributors to this release
- roughly sorted by number of patches accepted
/>
- **template**: First Surname (patch to nua/soa/msg)
- Kai Vehmanen (fixes to win32 VC6/2005 project files)
See the AUTHORS file in the distribution package.
@@ -65,6 +71,13 @@ Notes on new features
- section may be omitted for minor releases
/>
IPv6 support can now be disabled in VC6/VC2005 builds, by
setting SU_HAVE_IN6 to zero `win32/sofia-sip/su_configure.h'.
Symbian Open C build and packaging (SIS) files for libsofia-sip-ua,
libsofia-sip-ua-glib and for several test apps have been added under
sofia-sip/open_c.
Bugs fixed in this release
--------------------------
@@ -74,6 +87,5 @@ Bugs fixed in this release
- other bugs as fixed in CVS/darcs
/>
- **template**: #9499652 sf.net bug item title
- Fixed #1472682 sf.net bug: ACK does not find INVITE when
To URI has been changed.
@@ -36,12 +36,15 @@
*
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <glib.h>
#if HAVE_OPEN_C
#include <glib/gthread.h>
#include <glib_global.h>
#endif
#define SU_PORT_IMPLEMENTATION 1
#define SU_MSG_ARG_T union { char anoymous[4]; }
@@ -32,9 +32,7 @@
* @date Created: Thu Mar 18 19:40:51 1999 pessi
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
@@ -52,6 +50,7 @@ struct pinger;
#include "sofia-sip/su_wait.h"
#include "sofia-sip/su_log.h"
#include <glib/gthread.h>
#include "sofia-sip/su_glib.h"
struct pinger {
@@ -373,11 +372,13 @@ init_ping(struct pinger *p, su_msg_r msg, su_sockaddr_t *arg)
}
}
#if HAVE_SIGNAL
static
RETSIGTYPE term(int n)
{
exit(1);
}
#endif
void
time_test(void)
@@ -433,6 +434,10 @@ int main(int argc, char *argv[])
char *argv0 = argv[0];
#if HAVE_OPEN_C
dup2(1, 2);
#endif
while (argv[1]) {
if (strcmp(argv[1], "-v") == 0) {
opt_verbatim = 1;
@@ -457,7 +462,15 @@ int main(int argc, char *argv[])
}
}
#if HAVE_OPEN_C
opt_verbatim = 1;
opt_singlethread = 1;
su_log_soft_set_level(su_log_default, 9);
#endif
#if HAVE_SIGNAL
signal(SIGTERM, term);
#endif
su_init(); atexit(su_deinit);
@@ -509,9 +522,15 @@ int main(int argc, char *argv[])
printf("%s exiting\n", argv0);
#ifndef HAVE_WIN32
#if HAVE_SIGNAL
if (sleeppid)
kill(sleeppid, SIGTERM);
#endif
#endif
#if HAVE_OPEN_C
sleep(7);
#endif
return 0;
}
@@ -320,13 +320,14 @@ int host_test(void)
TEST(host_has_domain_invalid("valid."), 0);
TEST(host_has_domain_invalid("1-.invalid."), 0);
/* Invalid IP4 addresses (extra leading zeros) */
/* Invalid IP4 address (extra leading zeros) */
TEST_1(!host_cmp("127.0.0.1", "127.0.0.01"));
TEST_1(!host_cmp("[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
/* Invalid reference (extra leading zeros) */
TEST_1(host_cmp("[0ffff:0ffff:0ffff:0ffff:0ffff:0ffff:255.255.255.255]",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
#if SU_HAVE_IN6
TEST_1(!host_cmp("[ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
TEST_1(!host_cmp("::1", "::001"));
TEST_1(!host_cmp("[::1]", "::1"));
TEST_1(!host_cmp("[::1]", "::0.0.0.1"));
@@ -334,6 +335,7 @@ int host_test(void)
TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1"));
TEST_1(!host_cmp("::ffff:127.0.0.1", "::ffff:7f00:1"));
TEST_1(!host_cmp("[::ffff:127.0.0.1]", "[::7f00:1]"));
#endif
TEST_1(host_cmp("::", "0.0.0.0"));
TEST_1(host_cmp("::1", "0.0.0.1"));
@@ -49,4 +49,7 @@ ALIASES = \
"VERSION_1_12_6=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>" \
"NEW_1_12_6=@since New in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>" \
"EXP_1_12_6=@since Experimental in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.6.txt\">1.12.6</a>, available if --enable-experimental configuration option is given" \
"VERSION_1_12_7=<a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>" \
"NEW_1_12_7=@since New in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>" \
"EXP_1_12_7=@since Experimental in <a href=\"http://sofia-sip.sf.net/relnotes/relnotes-sofia-sip-1.12.7.txt\">1.12.7</a>, available if --enable-experimental configuration option is given" \
@@ -66,9 +66,9 @@ below.
<th>Notes</td>
</tr>
<a name="3261"></a>
<tr valign=top>
<th align="left">
<a name="3261"></a>
@RFC3261: Basic SIP Protocol
</th>
<td>
@@ -90,9 +90,9 @@ below.
</td>
</tr>
<a name="3261.19"></a> <a name="3261.20"></a>
<tr valign=top>
<th align="left">
<a name="3261.19"></a> <a name="3261.20"></a>
@RFC3261 Sections&nbsp;19&nbsp;and&nbsp;20:<br>
Syntax and encoding
</td>
@@ -116,6 +116,7 @@ below.
@ref sip_accept "Accept",
@ref sip_accept_encoding "Accept-Encoding",
@ref sip_accept_language "Accept-Language",
@ref sip_alert_info "Alert-Info" (@VERSION_1_12_7),
@ref sip_allow "Allow",
@ref sip_authentication_info "Authentication-Info",
@ref sip_authorization "Authorization",
@@ -142,6 +143,7 @@ below.
@ref sip_proxy_authorization "Proxy-Authorization",
@ref sip_proxy_require "Proxy-Require",
@ref sip_record_route "Record-Route",
@ref sip_reply_to "Reply-To" (@VERSION_1_12_7),
@ref sip_require "Require",
@ref sip_retry_after "Retry-After",
@ref sip_route "Route",
@@ -163,18 +165,15 @@ below.
parsers.
</td>
<td>
- Unsupported headers:
Alert-Info,
Reply-To
- Automatic escaping of reserved characters has not been
implemented.
- Using NUL (zero byte) in doublequoted strings has not been implemented
</td>
</tr>
<a name="3261.18"></a>
<tr valign=top>
<th align="left">
<a name="3261.18"></a>
@RFC3261 Section 18:<br>
UDP and TCP transports
</th>
@@ -201,9 +200,9 @@ below.
</td>
</tr>
<a name="3261.17"></a>
<tr valign=top>
<th align="left">
<a name="3261.17"></a>
@RFC3261 Section 17:<br> Transactions
</th>
<td>
@@ -214,7 +213,7 @@ below.
Default values for SIP timers are those specified by @RFC3261. The
defaults for T1, T1x64, T2 and T4 can be changed via
configuration tags defined in <nta_tag.h>.
configuration tags defined in <sofia-sip/nta_tag.h>.
</td>
<td>
&nbsp;
@@ -222,9 +221,9 @@ below.
</tr>
<a name="3261.26"></a>
<tr valign=top>
<th align="left">
<a name="3261.26"></a>
@RFC3261 Section 26:<br> Security
</th>
<td>
@@ -234,19 +233,19 @@ below.
</td>
<td>
Missing:
- TLS certificate checking
- Authorizing connections with TLS certificates
- S/MIME
</td>
</tr>
<a name="2617"></a>
<tr valign=top>
<th align="left">
<a name="2617"></a>
@RFC2617: HTTP Digest Authentication
</th>
<td>
Sofia-SIP an authentication client and server modules implementing
HTTP Digest authentication.
Sofia-SIP includes authentication client and server modules
implementing HTTP Digest authentication.
HTTP Digest is a simple challenge-response authentication
scheme defined in @RFC2617 based on the UA sending a checksum
@@ -283,9 +282,9 @@ below.
</td>
</tr>
<a name="3262"></a>
<tr valign=top>
<th align="left">
<a name="3262"></a>
@RFC3262: PRACK and 100rel
</th>
<td>
@@ -305,9 +304,9 @@ below.
</td>
</tr>
<a name="3263"></a>
<tr valign=top>
<th align="left">
<a name="3263"></a>
@RFC3263: Locating SIP Servers
</th>
<td>
@@ -320,9 +319,9 @@ below.
</td>
</tr>
<a name="3265"></a>
<tr valign=top>
<th align="left">
<a name="3265"></a>
@RFC3265: SIP Event Notifications
</th>
<td>
@@ -347,9 +346,9 @@ below.
</td>
</tr>
<a name="2806"></a>
<tr valign=top>
<th align="left">
<a name="2806"></a>
@RFC2806: tel URI
</th>
<td>
@@ -362,9 +361,9 @@ below.
</td>
</tr>
<a name="2976"></a>
<tr valign=top>
<th align="left">
<a name="2976"></a>
@RFC2976: INFO
</th>
<td>
@@ -377,9 +376,9 @@ below.
</tr>
<a name="3311"></a>
<tr valign=top>
<th align="left">
<a name="3311"></a>
@RFC3311: UPDATE
</th>
<td>
@@ -396,9 +395,9 @@ below.
</tr>
<a name="3313"></a>
<tr valign=top>
<th align="left">
<a name="3313"></a>
@RFC3313: Media Authentication
</th>
<td>
@@ -413,9 +412,9 @@ below.
</tr>
<a name="3323"></a>
<tr valign=top>
<th align="left">
<a name="3323"></a>
@RFC3323: Privacy
</th>
<td>
@@ -441,9 +440,9 @@ below.
</tr>
<a name="3326"></a>
<tr valign=top>
<th align="left">
<a name="3326"></a>
@RFC3326: Reason
</th>
<td>
@@ -457,9 +456,9 @@ below.
</tr>
<a name="3325"></a>
<tr valign=top>
<th align="left">
<a name="3325"></a>
@RFC3325: Asserted Identity
</th>
<td>
@@ -476,9 +475,9 @@ below.
</td>
</tr>
<a name="3327"></a>
<tr valign=top>
<th align="left">
<a name="3327"></a>
@RFC3327: Path
</th>
<td>
@@ -493,9 +492,9 @@ below.
</td>
</tr>
<a name="3329"></a>
<tr valign=top>
<th align="left">
<a name="3329"></a>
@RFC3329:
Security Agreement
</th>
@@ -517,9 +516,9 @@ below.
</td>
</tr>
<a name="3361"></a>
<tr valign=top>
<th align="left">
<a name="3361"></a>
@RFC3361: DHCPv4 option for locating SIP servers.
</th>
<td>
@@ -532,9 +531,9 @@ below.
</td>
</tr>
<a name="3420"></a>
<tr valign=top>
<th align="left">
<a name="3420"></a>
@RFC3420: message/sipfrag
</th>
<td>
@@ -547,9 +546,9 @@ below.
</td>
</tr>
<a name="3428"></a>
<tr valign=top>
<th align="left">
<a name="3428"></a>
@RFC3428: MESSAGE
</th>
<td>
@@ -560,9 +559,9 @@ below.
</td>
</tr>
<a name="3486"></a>
<tr valign=top>
<th align="left">
<a name="3486"></a>
@RFC3486: Compressing SIP
</th>
<td>
@@ -575,9 +574,9 @@ below.
</td>
</tr>
<a name="3515"></a>
<tr valign=top>
<th align="left">
<a name="3515"></a>
@RFC3515: REFER
</th>
<td>
@@ -600,9 +599,9 @@ below.
</td>
</tr>
<a name="3608"></a>
<tr valign=top>
<th align="left">
<a name="3608"></a>
@RFC3608: Service-Route
</th>
<td>
@@ -619,9 +618,9 @@ below.
</td>
</tr>
<a name="3680"></a>
<tr valign=top>
<th align="left">
<a name="3680"></a>
@RFC3680: "reg" event
</th>
<td>
@@ -643,9 +642,9 @@ below.
</td>
</tr>
<a name="3824"></a>
<tr valign=top>
<th align="left">
<a name="3824"></a>
@RFC3824: ENUM
</th>
<td>
@@ -659,9 +658,9 @@ below.
</td>
</tr>
<a name="3840"></a>
<tr valign=top>
<th align="left">
<a name="3840"></a>
@RFC3840: Callee Capabilities
</th>
<td>
@@ -681,9 +680,9 @@ below.
</tr>
<a name="3841"></a>
<tr valign=top>
<th align="left">
<a name="3841"></a>
@RFC3841: Caller Preferences
</th>
<td>
@@ -712,9 +711,9 @@ below.
</td>
</tr>
<a name="3842"></a>
<tr valign=top>
<th align="left">
<a name="3842"></a>
@RFC3842: Message waiting event
</th>
<td>
@@ -734,9 +733,9 @@ below.
</td>
</tr>
<a name="3856"></a>
<tr valign=top>
<th align="left">
<a name="3856"></a>
@RFC3856: Presence
</th>
<td>
@@ -760,9 +759,9 @@ below.
</td>
</tr>
<a name="3857"></a> <a name="3858"></a>
<tr valign=top>
<th align="left">
<a name="3857"></a> <a name="3858"></a>
@RFC3857: "winfo" event template package<br>
@RFC3858: winfo format
</th>
@@ -783,9 +782,9 @@ below.
</td>
</tr>
<a name="3891"></a>
<tr valign=top>
<th align="left">
<a name="3891"></a>
@RFC3891: Replaces
</th>
<td>
@@ -799,9 +798,9 @@ below.
</td>
</tr>
<a name="3892"></a>
<tr valign=top>
<th align="left">
<a name="3892"></a>
@RFC3892: Referred-By
</th>
<td>
@@ -819,9 +818,9 @@ below.
</td>
</tr>
<a name="3903"></a>
<tr valign=top>
<th align="left">
<a name="3903"></a>
@RFC3903: PUBLISH
</th>
<td>
@@ -839,9 +838,9 @@ below.
</td>
</tr>
<a name="4028"></a>
<tr valign=top>
<th align="left">
<a name="4028"></a>
@RFC4028: Session Timers
</th>
<td>
@@ -865,9 +864,9 @@ below.
</td>
</tr>
<a name="4320"></a>
<tr valign=top>
<th align="left">
<a name="4320"></a>
@RFC4320: Actions Addressing Identified Issues with SIP's Non-INVITE Transaction
</th>
<td>
@@ -896,10 +895,12 @@ below.
<th>Notes</td>
</tr>
<a name="4566"></a>
<a name="2327"></a>
<a name="3266"></a>
<tr valign=top>
<th align="left" align="left">
<a name="2327"></a>
@RFC2327: SDP (Session Description Protocol)
@RFC4566: SDP: Session Description Protocol
</th>
<td>
Generic support (generating, parsing and syntax checking) for SDP.
@@ -920,17 +921,20 @@ below.
The attributes "a=sendrecv", "a=sendonly", "a=recvonly",
"a=inactive", @ref sdp_rtpmap_s "a=rtpmap", and "a=fmtp" are parsed.
The implementation tries to follow draft-ietf-mmusic-sdp-new-25,
draft Internet Standard for SDP in progress.
The implementation partially implements @RFC4566. Note that
definiton of 'token' was updated in @RFC4566 and the parser has not
been updated yet.
</td>
<td>
- see also <a href="#4566">RFC 4566</a>
@RFC4566 obsoletes
- @RFC2327: SDP (Session Description Protocol)
- @RFC3266: IP6 in SDP
</td>
</tr>
<a name="3264"></a>
<tr valign=top>
<th align="left">
<a name="3264"></a>
@RFC3264: SDP Offer/Answer Negotiation
</th>
<td>
@@ -942,22 +946,9 @@ below.
</td>
</tr>
<a name="3312"></a>
<tr valign=top>
<th align="left">
<a name="3266"></a>
@RFC3266: IP6 in SDP
</th>
<td>
Representation of IP6 addresses within SDP message.
</td>
<td>
- see also <a href="#4566">RFC 4566</a>
</td>
</tr>
<tr valign=top>
<th align="left">
<a name="3312"></a>
@RFC3312: Preconditions
</th>
<td>
@@ -978,9 +969,9 @@ below.
</td>
</tr>
<a name="3388"></a>
<tr valign=top>
<th align="left">
<a name="3388"></a>
@RFC3388: Grouping of Media Lines
</th>
<td>
@@ -998,9 +989,9 @@ below.
</tr>
<a name="3407"></a>
<tr valign=top>
<th align="left">
<a name="3407"></a>
@RFC3407: Capability Declaration
</th>
<td>
@@ -1016,9 +1007,9 @@ below.
</tr>
<a name="3524"></a>
<tr valign=top>
<th align="left">
<a name="3524"></a>
@RFC3524: SRF
</th>
<td>
@@ -1032,9 +1023,9 @@ below.
</td>
</tr>
<a name="3556"></a>
<tr valign=top>
<th align="left">
<a name="3556"></a>
@RFC3556: Bandwidth
</th>
<td>
@@ -1048,9 +1039,9 @@ below.
</td>
</tr>
<a name="3605"></a>
<tr valign=top>
<th align="left">
<a name="3605"></a>
@RFC3605: RTCP attribute
</th>
<td>
@@ -1064,9 +1055,9 @@ below.
</td>
</tr>
<a name="3890"></a>
<tr valign=top>
<th align="left">
<a name="3890"></a>
@RFC3890: TIAS
</th>
<td>
@@ -1080,9 +1071,16 @@ below.
</td>
</tr>
</table>
*/
/* Overflow:
<a name="4566"></a>
<tr valign=top>
<th align="left">
<a name="4566"></a>
@RFC4566: SDP: Session Description Protocol
</th>
<td>
@@ -1093,15 +1091,10 @@ below.
</td>
</tr>
</table>
*/
/* Overflow:
<a name="3320"></a>
<tr valign=top>
<th align="left">
<a name="3320"></a>
@RFC3320: SigComp
</th>
<td>
@@ -1116,9 +1109,9 @@ below.
</td>
</tr>
<a name="3321"></a>
<tr valign=top>
<th align="left">
<a name="3321"></a>
@RFC3321: SigComp Extended operations
</th>
<td>
@@ -1132,9 +1125,9 @@ below.
</td>
</tr>
<a name="3325"></a>
<tr valign=top>
<th align="left">
<a name="3325"></a>
@RFC3325: Asserted Identity
</th>
<td>
@@ -1147,9 +1140,9 @@ below.
</td>
</tr>
<a name="3485"></a>
<tr valign=top>
<th align="left">
<a name="3485"></a>
@RFC3485: SIP/SDP Dictionary
</th>
<td>
@@ -1166,9 +1159,9 @@ below.
- Implicitly registered user identities
<a name="3959"></a>
<tr valign=top>
<th align="left">
<a name="3959"></a>
@RFC3959: early-session
</th>
<td>
@@ -35,7 +35,7 @@
#include <stddef.h>
#include <sofia-sip/su_configure.h>
#include <tport_tls.h>
#include "tport_tls.h"
#include "sofia-sip/sofia_features.h"
/** The name and version of software package providing Sofia-SIP-UA library.
@@ -20,7 +20,7 @@
* documented in a <a href="modules.html">submodule</a> for the header. In
* addition to the header structure, there is defined a @em header @em class
* structure and some standard functions for each header in the
* <http_header.h> include file. For header @c X, there are types,
* <sofia-sip/http_header.h> include file. For header @c X, there are types,
* functions, macros and header class as follows:
*
* - @c http_X_t is the structure used to store parsed header,
@@ -140,7 +140,7 @@ char *http_request_dup_one(http_header_t *dst, http_header_t const *src,
*
* Note that version string is not copied; it @b MUST remain constant during
* lifetime of the @c http_request_t object. You can use constants
* http_version_1_1 or http_version_1_0 declared in <http_header.h>.
* http_version_1_1 or http_version_1_0 declared in <sofia-sip/http_header.h>.
*/
http_request_t *http_request_create(su_home_t *home,
http_method_t method, char const *name,
@@ -112,6 +112,10 @@ int main(int argc, char *argv[])
usage(1);
}
#if HAVE_OPEN_C
tstflags |= tst_verbatim;
#endif
if (!test_mclass)
test_mclass = http_default_mclass();
@@ -125,6 +129,10 @@ int main(int argc, char *argv[])
retval |= http_chunk_test(); fflush(stdout);
retval |= test_query_parser(); fflush(stdout);
#if HAVE_OPEN_C
sleep(5);
#endif
return retval;
}
@@ -23,14 +23,14 @@ TESTS = torture_base64
# Rules for building the targets
nobase_include_sofia_HEADERS = \
sofia-sip/rc4.h \
sofia-sip/base64.h \
sofia-sip/token64.h \
sofia-sip/token64.h \
sofia-sip/uniqueid.h
libipt_la_SOURCES = base64.c token64.c
EXTRA_DIST = sofia-sip/utf8.h \
sofia-sip/rc4.h \
utf8internal.h \
utf8.c ucs2.c ucs4.c rc4.c \
utf8test.c
+2 -5
View File
@@ -15,9 +15,6 @@
* @section ipt_overview Overview
*
* This module contain some routines useful for IPT applications, like
* - base64.h BASE64 encoding/decoding,
* - token64.h encoding/decoding binary as SIP/HTTP token,
* - utf8.h UTF8 encoding/decoding,
* - sha1.h SHA1 hash routines, and
* - rc4.h arcfour random number generator.
* - <sofia-sip/base64.h> BASE64 encoding/decoding,
* - <sofia-sip/token64.h> encoding/decoding binary as SIP/HTTP token,
*/
@@ -133,6 +133,7 @@ int auth_init_default(auth_mod_t *am,
char const *realm = NULL, *opaque = NULL, *db = NULL, *allows = NULL;
char const *qop = NULL, *algorithm = NULL;
unsigned expires = 60 * 60, next_expires = 5 * 60;
unsigned max_ncount = 0;
unsigned blacklist = 5;
int forbidden = 0;
int anonymous = 0;
@@ -152,6 +153,7 @@ int auth_init_default(auth_mod_t *am,
AUTHTAG_ALGORITHM_REF(algorithm),
AUTHTAG_EXPIRES_REF(expires),
AUTHTAG_NEXT_EXPIRES_REF(next_expires),
AUTHTAG_MAX_NCOUNT_REF(max_ncount),
AUTHTAG_BLACKLIST_REF(blacklist),
AUTHTAG_FORBIDDEN_REF(forbidden),
AUTHTAG_ANONYMOUS_REF(anonymous),
@@ -172,6 +174,7 @@ int auth_init_default(auth_mod_t *am,
msg_commalist_d(am->am_home, &s, &am->am_allow, NULL);
am->am_expires = expires;
am->am_next_exp = next_expires;
am->am_max_ncount = max_ncount;
am->am_blacklist = blacklist;
am->am_forbidden = forbidden;
am->am_anonymous = anonymous;
@@ -1437,6 +1440,16 @@ int auth_validate_digest_nonce(auth_mod_t *am,
as->as_stale = 1;
}
if (am->am_max_ncount && ar->ar_nc) {
unsigned long nc = strtoul(ar->ar_nc, NULL, 10);
if (nc == 0 || nc > am->am_max_ncount) {
SU_DEBUG_5(("auth_method_digest: nonce used %s times, max %u\n",
ar->ar_nc, am->am_max_ncount));
as->as_stale = 1;
}
}
/* We should also check cnonce, nc... */
return 0;
@@ -64,7 +64,7 @@ tag_typedef_t authtag_module = PTRTAG_TYPEDEF(module);
* authentication module, like "Digest" or "Basic", or an plugin module,
* like "SGMF+Digest".
*
* @sa See <auth_plugin.h> for plugin interface.
* @sa See <sofia-sip/auth_plugin.h> for plugin interface.
*/
tag_typedef_t authtag_method = STRTAG_TYPEDEF(method);
@@ -150,6 +150,17 @@ tag_typedef_t authtag_expires = UINTTAG_TYPEDEF(expires);
*/
tag_typedef_t authtag_next_expires = UINTTAG_TYPEDEF(next_expires);
/**@def AUTHTAG_MAX_NCOUNT()
*
* Max nonce count value.
*
* The tag AUTHTAG_MAX_NCOUNT() specifies the maximum number of times a
* nonce should be used.
*
* @todo Count actual usages and don't trust "nc" parameter only.
*/
tag_typedef_t authtag_max_ncount = UINTTAG_TYPEDEF(max_ncount);
/**@def AUTHTAG_BLACKLIST()
*
* Blacklist time.
@@ -19,11 +19,10 @@
*
* @section auth_module Server Verifying Authentication
*
* The file <auth_module.h> defines the interface used by a server verifying
* the authentication from client. After the server has created an @ref
* auth_mod_t "authentication module", the usual authentication operation is
* simple enough:
* The file <sofia-sip/auth_module.h> defines the interface used by a server
* verifying the authentication from client. After the server has created an
* @ref auth_mod_t "authentication module", the usual authentication
* operation is simple enough:
* -# server initializes an #auth_status_t structure with information from
* the request
* -# server calls auth_mod_method()
@@ -42,8 +41,8 @@
*
* When the server creates the authentication module with auth_mod_create(),
* it can specify numerous parameters affecting the authentication protocol
* and algorithms. The parameter tags are defined in <auth_module.h>. The
* most important parameters include:
* and algorithms. The parameter tags are defined in
* <sofia-sip/auth_module.h>. The most important parameters include:
*
* - AUTHTAG_METHOD(),
* - AUTHTAG_ALGORITHM(),
@@ -52,7 +51,7 @@
*
* @section auth_client Client Authenticating User
*
* The file <auth_client.h> defines the interface used by a client
* The file <sofia-sip/auth_client.h> defines the interface used by a client
* authenticating a user with a server. Because there may be multiple
* servers or proxies requiring authentication, the client-side
* authentication information is represented using a list of #auth_client_t
@@ -44,7 +44,7 @@
* The IPTSEC_DEBUG environment variable is used to determine the debug
* logging level for @b iptsec module. The default level is 3.
*
* @sa <su_debug.h>, iptsec_log, SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, iptsec_log, SOFIA_DEBUG
*/
extern char const IPTSEC_DEBUG[];
@@ -322,6 +322,13 @@ SOFIAPUBVAR tag_typedef_t authtag_next_expires;
authtag_next_expires_ref, tag_uint_vr((&x))
SOFIAPUBVAR tag_typedef_t authtag_next_expires_ref;
/** Maximum nonce count allowed. */
#define AUTHTAG_MAX_NCOUNT(x) authtag_max_ncount, tag_uint_v((x))
SOFIAPUBVAR tag_typedef_t authtag_max_ncount;
#define AUTHTAG_MAX_NCOUNT_REF(x) authtag_max_ncount_ref, tag_uint_vr((&x))
SOFIAPUBVAR tag_typedef_t authtag_max_ncount_ref;
/** Extra delay when responding if provided invalid credentials or nonce. */
#define AUTHTAG_BLACKLIST(x) authtag_blacklist, tag_uint_v((x))
SOFIAPUBVAR tag_typedef_t authtag_blacklist;
@@ -343,13 +350,6 @@ SOFIAPUBVAR tag_typedef_t authtag_anonymous;
#define AUTHTAG_ANONYMOUS_REF(x) authtag_anonymous_ref, tag_bool_vr((&x))
SOFIAPUBVAR tag_typedef_t authtag_anonymous_ref;
/** Fake authentication procedure - do not check result. */
#define AUTHTAG_FAKE(x) authtag_fake, tag_bool_v((x))
SOFIAPUBVAR tag_typedef_t authtag_fake;
#define AUTHTAG_FAKE_REF(x) authtag_fake_ref, tag_bool_vr((&x))
SOFIAPUBVAR tag_typedef_t authtag_fake_ref;
/** HSS client structure. */
#define AUTHTAG_HSS(x) authtag_hss, tag_ptr_v((x))
SOFIAPUBVAR tag_typedef_t authtag_hss;
@@ -164,6 +164,8 @@ struct auth_mod_t
su_md5_t am_hmac_ipad; /**< MD5 with inner pad */
su_md5_t am_hmac_opad; /**< MD5 with outer pad */
unsigned am_max_ncount:1; /**< If nonzero, challenge with new nonce after ncount */
};
SOFIAPUBFUN
@@ -92,11 +92,9 @@ char const name[] = "test_auth_digest";
unsigned offset;
void su_time(su_time_t *tv)
void offset_time(su_time_t *tv)
{
tv->tv_sec = time(NULL) + offset +
/* Seconds from 1.1.1900 to 1.1.1970 */ 2208988800UL ;
tv->tv_usec = 555555;
tv->tv_sec += offset;
}
int test_digest()
@@ -896,6 +894,7 @@ int test_digest_client()
AUTHTAG_QOP("auth,auth-int"),
AUTHTAG_FORBIDDEN(1),
AUTHTAG_ANONYMOUS(1),
AUTHTAG_MAX_NCOUNT(1),
TAG_END()));
reinit_as(as);
@@ -942,6 +941,36 @@ int test_digest_client()
TEST(as->as_status, 401);
TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
TEST_S(msg_params_find(au->au_params, "stale="), "true");
TEST(auc_challenge(&aucs, home, (msg_auth_t *)as->as_response,
sip_authorization_class), 1);
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
(url_t *)"sip:surf3@ims3.so.noklab.net",
sip->sip_payload), 1);
TEST_1(sip->sip_authorization);
TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
"00000001");
reinit_as(as);
auth_mod_check_client(am, as, sip->sip_authorization, ach);
TEST(as->as_status, 0);
/* Test nonce count check */
msg_header_remove(m2, (void *)sip, (void *)sip->sip_authorization);
TEST(auc_authorization(&aucs, m2, (msg_pub_t*)sip, rq->rq_method_name,
(url_t *)"sip:surf3@ims3.so.noklab.net",
sip->sip_payload), 1);
TEST_1(sip->sip_authorization);
TEST_S(msg_header_find_param(sip->sip_authorization->au_common, "nc="),
"00000002");
reinit_as(as);
auth_mod_check_client(am, as, sip->sip_authorization, ach);
TEST(as->as_status, 401);
TEST_1(au = (void *)as->as_response); TEST_1(au->au_params);
TEST_S(msg_params_find(au->au_params, "stale="), "true");
aucs = NULL;
/* Test anonymous operation */
@@ -1210,6 +1239,9 @@ int main(int argc, char *argv[])
{
int retval = 0;
int i;
extern void (*_su_time)(su_time_t *tv);
_su_time = offset_time;
argv0 = argv[0];
@@ -42,10 +42,10 @@
#define TAG_NAMESPACE "tst"
#include <test_class.h>
#include "test_class.h"
#include <sofia-sip/msg_parser.h>
#include <sofia-sip/msg_mclass.h>
#include <test_protos.h>
#include "test_protos.h"
#include <sofia-sip/msg_addr.h>
extern msg_mclass_t const msg_test_mclass[1];
@@ -47,8 +47,8 @@
#include <stddef.h>
#include <string.h>
#include <test_class.h>
#include <test_protos.h>
#include "test_class.h"
#include "test_protos.h"
#include <sofia-sip/msg_mime_protos.h>
#include <sofia-sip/msg_mclass.h>
+1 -1
View File
@@ -6,7 +6,7 @@
*
* Sofia Event API provides an interface to different events used in SIP
* presence and conferencing. Interface used both in client and server sides
* is presented in <nea.h>.
* is presented in <sofia-sip/nea.h>.
*
* @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
*
@@ -67,7 +67,7 @@
* The NEA_DEBUG environment variable is used to determine the debug
* logging level for @b nea module. The default level is 3.
*
* @sa <su_debug.h>, nea_log, SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, nea_log, SOFIA_DEBUG
*/
extern char const NEA_DEBUG[];
@@ -14,6 +14,7 @@ TAGFILES += ../docs/msg.doxytags=../msg
TAGFILES += ../docs/sip.doxytags=../sip
TAGFILES += ../docs/sresolv.doxytags=../sresolv
TAGFILES += ../docs/tport.doxytags=../tport
TAGFILES += ../docs/nua.doxytags=../nua
GENERATE_TAGFILE = ../docs/nta.doxytags
+357 -139
View File
@@ -282,7 +282,7 @@ union sm_arg_u {
* The NTA_DEBUG environment variable is used to determine the default
* debug logging level. The normal level is 3.
*
* @sa <su_debug.h>, #su_log_global, #SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, #su_log_global, #SOFIA_DEBUG
*/
#ifdef DOXYGEN
extern char const NTA_DEBUG[]; /* dummy declaration for Doxygen */
@@ -336,13 +336,36 @@ su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG) };
* @param contact_url URL that agent uses to bind the server sockets
* @param callback pointer to callback function
* @param magic pointer to user data
* @param tag,value,... other arguments
* @param tag,value,... tagged arguments
*
* @note It is possible to provide -1 as @a contact_url.
* @TAGS
* NTATAG_ALIASES(),
* NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
* NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
* NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
* NTATAG_EXTRA_100(),
* NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
* NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(),
* NTATAG_REL100(),
* NTATAG_SERVER_RPORT(),
* NTATAG_SIPFLAGS(),
* NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
* NTATAG_STATELESS(),
* NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
* NTATAG_TIMER_C(),
* NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
* NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
*
* @note The value from following tags are stored, but they currently do nothing:
* NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
*
* @note It is possible to provide @c (url_string_t*)-1 as @a contact_url.
* In that case, no server sockets are bound.
*
* @retval handle to the agent when successful,
* @retval NULL upon an error.
*
* @sa NUTAG_
*/
nta_agent_t *nta_agent_create(su_root_t *root,
url_string_t const *contact_url,
@@ -359,6 +382,8 @@ nta_agent_t *nta_agent_create(su_root_t *root,
ta_start(ta, tag, value);
if ((agent = su_home_new(sizeof(*agent)))) {
unsigned timer_c;
agent->sa_root = root;
agent->sa_callback = callback;
agent->sa_magic = magic;
@@ -366,13 +391,20 @@ nta_agent_t *nta_agent_create(su_root_t *root,
agent->sa_maxsize = 2 * 1024 * 1024; /* 2 MB */
agent->sa_bad_req_mask =
(unsigned) ~(sip_mask_response | sip_mask_proxy);
/*
* Bit-wise not of these - what is left is suitable for UAs with
* 100rel, timer, events, publish
*/
(unsigned) ~(sip_mask_response | sip_mask_proxy | sip_mask_registrar |
sip_mask_pref | sip_mask_privacy);
agent->sa_bad_resp_mask =
(unsigned) ~(sip_mask_request | sip_mask_proxy);
(unsigned) ~(sip_mask_request | sip_mask_proxy | sip_mask_registrar |
sip_mask_pref | sip_mask_privacy);
agent->sa_t1 = NTA_SIP_T1;
agent->sa_t2 = NTA_SIP_T2;
agent->sa_t4 = NTA_SIP_T4;
agent->sa_t1x64 = 64 * NTA_SIP_T1;
agent->sa_timer_c = 185 * 1000;
agent->sa_drop_prob = 0;
agent->sa_is_a_uas = 0;
agent->sa_progress = 60 * 1000;
@@ -421,7 +453,9 @@ nta_agent_t *nta_agent_create(su_root_t *root,
outgoing_queue_init(agent->sa_out.terminated, 0);
/* Special queues (states) for outgoing INVITE transactions */
outgoing_queue_init(agent->sa_out.inv_calling, agent->sa_t1x64); /* B */
outgoing_queue_init(agent->sa_out.inv_proceeding, 0);
timer_c = (agent->sa_use_timer_c || !agent->sa_is_a_uas)
? agent->sa_timer_c : 0;
outgoing_queue_init(agent->sa_out.inv_proceeding, timer_c); /* C */
outgoing_queue_init(agent->sa_out.inv_completed, 32000); /* Timer D */
if (leg_htable_resize(agent->sa_home, agent->sa_dialogs, 0) < 0 ||
@@ -841,17 +875,25 @@ void agent_kill_terminator(nta_agent_t *agent)
* 0 selects the default value.
*
* @TAGS
* NTATAG_ALIASES(), NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(),
* NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_DEBUG_DROP_PROB(),
* NTATAG_DEFAULT_PROXY(), NTATAG_EXTRA_100(), NTATAG_MAXSIZE(),
* NTATAG_MAX_FORWARDS(),
* NTATAG_UDP_MTU(), NTATAG_MERGE_482(), NTATAG_PASS_100(),
* NTATAG_PRELOAD(), NTATAG_REL100(), NTATAG_RPORT(), NTATAG_SERVER_RPORT(),
* NTATAG_TCP_RPORT(),
* NTATAG_SIPFLAGS(), NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(),
* NTATAG_SIP_T4(), NTATAG_SMIME(), NTATAG_STATELESS(), NTATAG_TAG_3261(),
* NTATAG_TIMEOUT_408(), NTATAG_PASS_408(), NTATAG_UA(), NTATAG_USER_VIA(),
* and NTATAG_USE_TIMESTAMP().
* NTATAG_ALIASES(),
* NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
* NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
* NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
* NTATAG_EXTRA_100(),
* NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
* NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(),
* NTATAG_REL100(),
* NTATAG_SERVER_RPORT(),
* NTATAG_SIPFLAGS(),
* NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
* NTATAG_STATELESS(),
* NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
* NTATAG_TIMER_C(),
* NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
* NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
*
* @note The value from following tags are stored, but they currently do nothing:
* NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
*/
int nta_agent_set_params(nta_agent_t *agent,
tag_type_t tag, tag_value_t value, ...)
@@ -875,7 +917,7 @@ int nta_agent_set_params(nta_agent_t *agent,
static
int agent_set_params(nta_agent_t *agent, tagi_t *tags)
{
int n, m;
int n, nC, m;
unsigned bad_req_mask = agent->sa_bad_req_mask;
unsigned bad_resp_mask = agent->sa_bad_resp_mask;
usize_t maxsize = agent->sa_maxsize;
@@ -885,6 +927,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
unsigned sip_t2 = agent->sa_t2;
unsigned sip_t4 = agent->sa_t4;
unsigned sip_t1x64 = agent->sa_t1x64;
unsigned timer_c = agent->sa_timer_c;
unsigned blacklist = agent->sa_blacklist;
int ua = agent->sa_is_a_uas;
unsigned progress = agent->sa_progress;
@@ -919,50 +962,54 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
su_home_t *home = agent->sa_home;
n = tl_gets(tags,
NTATAG_MCLASS_REF(mclass),
NTATAG_ALIASES_REF(aliases),
NTATAG_BAD_REQ_MASK_REF(bad_req_mask),
NTATAG_BAD_RESP_MASK_REF(bad_resp_mask),
NTATAG_ALIASES_REF(aliases),
NTATAG_UA_REF(ua),
NTATAG_STATELESS_REF(stateless),
NTATAG_BLACKLIST_REF(blacklist),
NTATAG_CANCEL_2543_REF(cancel_2543),
NTATAG_CANCEL_487_REF(cancel_487),
NTATAG_DEBUG_DROP_PROB_REF(drop_prob),
NTATAG_DEFAULT_PROXY_REF(proxy),
NTATAG_EXTRA_100_REF(extra_100),
NTATAG_MAXSIZE_REF(maxsize),
NTATAG_MAX_FORWARDS_REF(max_forwards),
NTATAG_UDP_MTU_REF(udp_mtu),
NTATAG_MCLASS_REF(mclass),
NTATAG_MERGE_482_REF(merge_482),
NTATAG_PASS_100_REF(pass_100),
NTATAG_PASS_408_REF(pass_408),
NTATAG_PRELOAD_REF(preload),
NTATAG_PROGRESS_REF(progress),
NTATAG_REL100_REF(invite_100rel),
NTATAG_RPORT_REF(rport),
NTATAG_SERVER_RPORT_REF(server_rport),
NTATAG_SIGCOMP_ALGORITHM_REF(algorithm),
NTATAG_SIGCOMP_OPTIONS_REF(sigcomp),
NTATAG_SIPFLAGS_REF(flags),
NTATAG_SIP_T1X64_REF(sip_t1x64),
NTATAG_SIP_T1_REF(sip_t1),
NTATAG_SIP_T2_REF(sip_t2),
NTATAG_SIP_T4_REF(sip_t4),
NTATAG_SIP_T1X64_REF(sip_t1x64),
NTATAG_PROGRESS_REF(progress),
NTATAG_BLACKLIST_REF(blacklist),
NTATAG_DEBUG_DROP_PROB_REF(drop_prob),
NTATAG_USER_VIA_REF(user_via),
NTATAG_EXTRA_100_REF(extra_100),
NTATAG_PASS_100_REF(pass_100),
NTATAG_TIMEOUT_408_REF(timeout_408),
NTATAG_PASS_408_REF(pass_408),
NTATAG_MERGE_482_REF(merge_482),
NTATAG_DEFAULT_PROXY_REF(proxy),
NTATAG_CANCEL_2543_REF(cancel_2543),
NTATAG_CANCEL_487_REF(cancel_487),
NTATAG_REL100_REF(invite_100rel),
NTATAG_USE_TIMESTAMP_REF(use_timestamp),
NTATAG_USE_NAPTR_REF(use_naptr),
NTATAG_USE_SRV_REF(use_srv),
#if HAVE_SOFIA_SMIME
NTATAG_SMIME_REF(smime),
#endif
NTATAG_SIPFLAGS_REF(flags),
NTATAG_RPORT_REF(rport),
NTATAG_SERVER_RPORT_REF(server_rport),
NTATAG_STATELESS_REF(stateless),
NTATAG_TCP_RPORT_REF(tcp_rport),
NTATAG_PRELOAD_REF(preload),
NTATAG_TIMEOUT_408_REF(timeout_408),
NTATAG_UA_REF(ua),
NTATAG_UDP_MTU_REF(udp_mtu),
NTATAG_USER_VIA_REF(user_via),
NTATAG_USE_NAPTR_REF(use_naptr),
NTATAG_USE_SRV_REF(use_srv),
NTATAG_USE_TIMESTAMP_REF(use_timestamp),
#ifdef TPTAG_THRPSIZE
/* If threadpool is enabled, start a separate "reaper thread" */
TPTAG_THRPSIZE_REF(threadpool),
#endif
NTATAG_SIGCOMP_OPTIONS_REF(sigcomp),
NTATAG_SIGCOMP_ALGORITHM_REF(algorithm),
TAG_END());
nC = tl_gets(tags,
NTATAG_TIMER_C_REF(timer_c),
TAG_END());
n += nC;
if (mclass != NONE)
agent->sa_mclass = mclass ? mclass : sip_default_mclass();
@@ -972,7 +1019,7 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
m = tport_set_params(tport, TAG_NEXT(tags));
}
if (n == 0 || m == -1)
if (m == -1)
return m;
n += m;
@@ -1065,6 +1112,14 @@ int agent_set_params(nta_agent_t *agent, tagi_t *tags)
outgoing_queue_adjust(agent, agent->sa_out.inv_calling, sip_t1x64);
}
agent->sa_t1x64 = sip_t1x64;
if (nC == 1) {
agent->sa_use_timer_c = 1;
if (timer_c == 0)
timer_c = 185 * 1000;
agent->sa_timer_c = timer_c;
outgoing_queue_adjust(agent, agent->sa_out.inv_proceeding, timer_c);
}
agent->sa_blacklist = blacklist;
if (progress == 0)
@@ -1123,16 +1178,25 @@ void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu)
* INVITE transactions, or how the @Via headers are generated.
*
* @TAGS
* NTATAG_ALIASES_REF(), NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
* NTATAG_CONTACT_REF(), NTATAG_DEBUG_DROP_PROB_REF(),
* NTATAG_DEFAULT_PROXY_REF(), NTATAG_EXTRA_100_REF(), NTATAG_MAXSIZE_REF(),
* NTATAG_MAX_FORWARDS_REF(),
* NTATAG_MERGE_482_REF(), NTATAG_PASS_100_REF(), NTATAG_PRELOAD_REF(),
* NTATAG_REL100_REF(), NTATAG_RPORT_REF(), NTATAG_SIPFLAGS_REF(),
* NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T1_REF(), NTATAG_SIP_T2_REF(),
* NTATAG_ALIASES_REF(), NTATAG_BLACKLIST_REF(),
* NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
* NTATAG_CLIENT_RPORT_REF(), NTATAG_CONTACT_REF(),
* NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(),
* NTATAG_EXTRA_100_REF(),
* NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(),
* NTATAG_MERGE_482_REF(),
* NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(),
* NTATAG_PROGRESS_REF(),
* NTATAG_REL100_REF(),
* NTATAG_SERVER_RPORT_REF(),
* NTATAG_SIGCOMP_ALGORITHM_REF(), NTATAG_SIGCOMP_OPTIONS_REF(),
* NTATAG_SIPFLAGS_REF(),
* NTATAG_SIP_T1_REF(), NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T2_REF(),
* NTATAG_SIP_T4_REF(), NTATAG_SMIME_REF(), NTATAG_STATELESS_REF(),
* NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_PASS_408_REF(),
* NTATAG_UA_REF(), NTATAG_USER_VIA_REF(), and NTATAG_USE_TIMESTAMP_REF().
* NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_TIMER_C_REF(),
* NTATAG_UA_REF(), NTATAG_UDP_MTU_REF(), NTATAG_USER_VIA_REF(),
* NTATAG_USE_NAPTR_REF(), NTATAG_USE_SRV_REF(),
* and NTATAG_USE_TIMESTAMP_REF().
*
*/
int nta_agent_get_params(nta_agent_t *agent,
@@ -1145,12 +1209,11 @@ int nta_agent_get_params(nta_agent_t *agent,
ta_start(ta, tag, value);
n = agent_get_params(agent, ta_args(ta));
ta_end(ta);
} else {
su_seterrno(EINVAL);
n = -1;
return n;
}
return n;
su_seterrno(EINVAL);
return -1;
}
/** Get NTA parameters */
@@ -1159,46 +1222,49 @@ int agent_get_params(nta_agent_t *agent, tagi_t *tags)
{
return
tl_tgets(tags,
NTATAG_MCLASS(agent->sa_mclass),
NTATAG_CONTACT(agent->sa_contact),
NTATAG_ALIASES(agent->sa_aliases),
NTATAG_UA(agent->sa_is_a_uas),
NTATAG_STATELESS(agent->sa_is_stateless),
NTATAG_MAXSIZE(agent->sa_maxsize),
NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count),
NTATAG_UDP_MTU(agent->sa_udp_mtu),
NTATAG_SIP_T1(agent->sa_t1),
NTATAG_SIP_T2(agent->sa_t2),
NTATAG_SIP_T4(agent->sa_t4),
NTATAG_SIP_T1X64(agent->sa_t1x64),
NTATAG_BLACKLIST(agent->sa_blacklist),
NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob),
NTATAG_USER_VIA(agent->sa_user_via),
NTATAG_EXTRA_100(agent->sa_extra_100),
NTATAG_PASS_100(agent->sa_pass_100),
NTATAG_TIMEOUT_408(agent->sa_timeout_408),
NTATAG_PASS_408(agent->sa_pass_408),
NTATAG_MERGE_482(agent->sa_merge_482),
NTATAG_DEFAULT_PROXY(agent->sa_default_proxy),
NTATAG_CANCEL_2543(agent->sa_cancel_2543),
NTATAG_CANCEL_487(agent->sa_cancel_487),
NTATAG_TAG_3261(1),
NTATAG_CLIENT_RPORT(agent->sa_rport),
NTATAG_CONTACT(agent->sa_contact),
NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob),
NTATAG_DEFAULT_PROXY(agent->sa_default_proxy),
NTATAG_EXTRA_100(agent->sa_extra_100),
NTATAG_MAXSIZE(agent->sa_maxsize),
NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count),
NTATAG_MCLASS(agent->sa_mclass),
NTATAG_MERGE_482(agent->sa_merge_482),
NTATAG_PASS_100(agent->sa_pass_100),
NTATAG_PASS_408(agent->sa_pass_408),
NTATAG_PRELOAD(agent->sa_preload),
NTATAG_PROGRESS(agent->sa_progress),
NTATAG_REL100(agent->sa_invite_100rel),
NTATAG_USE_TIMESTAMP(agent->sa_timestamp),
NTATAG_USE_NAPTR(agent->sa_use_naptr),
NTATAG_USE_SRV(agent->sa_use_srv),
NTATAG_SERVER_RPORT(agent->sa_server_rport),
NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm),
NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ?
agent->sa_sigcomp_options :
"sip"),
NTATAG_SIPFLAGS(agent->sa_flags),
NTATAG_SIP_T1(agent->sa_t1),
NTATAG_SIP_T1X64(agent->sa_t1x64),
NTATAG_SIP_T2(agent->sa_t2),
NTATAG_SIP_T4(agent->sa_t4),
#if HAVE_SOFIA_SMIME
NTATAG_SMIME(agent->sa_smime),
#else
NTATAG_SMIME(NULL),
#endif
NTATAG_SIPFLAGS(agent->sa_flags),
NTATAG_RPORT(agent->sa_rport),
NTATAG_PRELOAD(agent->sa_preload),
NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm),
NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ?
agent->sa_sigcomp_options :
"sip"),
NTATAG_STATELESS(agent->sa_is_stateless),
NTATAG_TAG_3261(1),
NTATAG_TIMEOUT_408(agent->sa_timeout_408),
NTATAG_TIMER_C(agent->sa_timer_c),
NTATAG_UA(agent->sa_is_a_uas),
NTATAG_UDP_MTU(agent->sa_udp_mtu),
NTATAG_USER_VIA(agent->sa_user_via),
NTATAG_USE_NAPTR(agent->sa_use_naptr),
NTATAG_USE_SRV(agent->sa_use_srv),
NTATAG_USE_TIMESTAMP(agent->sa_timestamp),
TAG_END());
}
@@ -1207,8 +1273,38 @@ int agent_get_params(nta_agent_t *agent, tagi_t *tags)
* The nta_agent_get_stats() function retrieves the stack statistics.
*
* @TAGS
* @TAG NTATAG_S_*
*
* NTATAG_S_ACKED_TR_REF(),
* NTATAG_S_BAD_MESSAGE_REF(),
* NTATAG_S_BAD_REQUEST_REF(),
* NTATAG_S_BAD_RESPONSE_REF(),
* NTATAG_S_CANCELED_TR_REF(),
* NTATAG_S_CLIENT_TR_REF(),
* NTATAG_S_DIALOG_TR_REF(),
* NTATAG_S_DROP_REQUEST_REF(),
* NTATAG_S_DROP_RESPONSE_REF(),
* NTATAG_S_IRQ_HASH_REF(),
* NTATAG_S_IRQ_HASH_USED_REF(),
* NTATAG_S_LEG_HASH_REF(),
* NTATAG_S_LEG_HASH_USED_REF(),
* NTATAG_S_MERGED_REQUEST_REF(),
* NTATAG_S_ORQ_HASH_REF(),
* NTATAG_S_ORQ_HASH_USED_REF(),
* NTATAG_S_RECV_MSG_REF(),
* NTATAG_S_RECV_REQUEST_REF(),
* NTATAG_S_RECV_RESPONSE_REF(),
* NTATAG_S_RECV_RETRY_REF(),
* NTATAG_S_RETRY_REQUEST_REF(),
* NTATAG_S_RETRY_RESPONSE_REF(),
* NTATAG_S_SENT_MSG_REF(),
* NTATAG_S_SENT_REQUEST_REF(),
* NTATAG_S_SENT_RESPONSE_REF(),
* NTATAG_S_SERVER_TR_REF(),
* NTATAG_S_TOUT_REQUEST_REF(),
* NTATAG_S_TOUT_RESPONSE_REF(),
* NTATAG_S_TRLESS_200_REF(),
* NTATAG_S_TRLESS_REQUEST_REF(),
* NTATAG_S_TRLESS_RESPONSE_REF(), and
* NTATAG_S_TRLESS_TO_TR_REF(),
*/
int nta_agent_get_stats(nta_agent_t *agent,
tag_type_t tag, tag_value_t value, ...)
@@ -1622,7 +1718,6 @@ int agent_create_master_transport(nta_agent_t *self, tagi_t *tags)
tport_tcreate(self, nta_agent_class, self->sa_root,
TPTAG_SDWN_ERROR(0),
TPTAG_IDLE(1800000),
TPTAG_DEBUG_DROP(self->sa_drop_prob),
TAG_NEXT(tags));
if (!self->sa_tports)
@@ -2119,6 +2214,16 @@ void agent_recv_request(nta_agent_t *agent,
URL_PRINT_ARGS(sip->sip_request->rq_url),
sip->sip_request->rq_version, cseq));
if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
SU_DEBUG_5(("nta: %s (%u) is %s\n",
method_name, cseq, "dropped simulating packet loss"));
agent->sa_stats->as_drop_request++;
msg_destroy(msg);
return;
}
}
stream = tport_is_stream(tport);
/* Try to use compression on reverse direction if @Via has comp=sigcomp */
@@ -2304,8 +2409,9 @@ void agent_recv_request(nta_agent_t *agent,
}
else {
agent->sa_stats->as_trless_request++;
SU_DEBUG_5(("nta: %s (%u) no place to go: %d %s\n",
method_name, cseq, SIP_501_NOT_IMPLEMENTED));
SU_DEBUG_5(("nta: %s (%u) %s\n",
method_name, cseq,
"not processed by application: returning 501"));
if (method != sip_method_ack)
nta_msg_treply(agent, msg, SIP_501_NOT_IMPLEMENTED,
NTATAG_TPORT(tport),
@@ -2493,6 +2599,16 @@ void agent_recv_response(nta_agent_t *agent,
SU_DEBUG_5(("nta: received %03d %s for %s (%u)\n",
status, phrase, method, cseq));
if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
SU_DEBUG_5(("nta: %03d %s %s\n",
status, phrase, "dropped simulating packet loss"));
agent->sa_stats->as_drop_response++;
msg_destroy(msg);
return;
}
}
if (agent->sa_bad_resp_mask)
errors = msg_extract_errors(msg) & agent->sa_bad_resp_mask;
else
@@ -2505,7 +2621,10 @@ void agent_recv_response(nta_agent_t *agent,
agent->sa_stats->as_bad_response++;
agent->sa_stats->as_bad_message++;
SU_DEBUG_5(("nta: %03d %s failed sanity check\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase,
errors
? "has fatal syntax errors"
: "failed sanity check"));
for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_next) {
if (h->sh_class->hc_name) {
@@ -2532,7 +2651,7 @@ void agent_recv_response(nta_agent_t *agent,
/* Drop response messages to ACK */
agent->sa_stats->as_bad_response++;
agent->sa_stats->as_bad_message++;
SU_DEBUG_5(("nta: %03d %s is response to ACK\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is response to ACK"));
msg_destroy(msg);
return;
}
@@ -2540,7 +2659,8 @@ void agent_recv_response(nta_agent_t *agent,
/* XXX - should check if msg should be discarded based on via? */
if ((orq = outgoing_find(agent, msg, sip, sip->sip_via))) {
SU_DEBUG_5(("nta: %03d %s going to a transaction\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n",
status, phrase, "is going to a transaction"));
if (outgoing_recv(orq, status, msg, sip) == 0)
return;
}
@@ -2548,12 +2668,13 @@ void agent_recv_response(nta_agent_t *agent,
agent->sa_stats->as_trless_response++;
if ((orq = agent->sa_default_outgoing)) {
SU_DEBUG_5(("nta: %03d %s to the default transaction\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase,
"to the default transaction"));
outgoing_default_recv(orq, status, msg, sip);
return;
}
else if (agent->sa_callback) {
SU_DEBUG_5(("nta: %03d %s to message callback\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "to message callback"));
/*
* Store message and transport to hook for the duration of the callback
* so that the transport can be obtained by nta_transport().
@@ -2569,13 +2690,15 @@ void agent_recv_response(nta_agent_t *agent,
&& sip->sip_via && !sip->sip_via->v_next
&& agent_has_via(agent, sip->sip_via)) {
agent->sa_stats->as_trless_200++;
/* Orphan 200 Ok to INVITE. ACK and BYE it */
SU_DEBUG_5(("nta: %03d %s must be ACK&BYE\n", status, phrase));
if (nta_msg_ackbye(agent, msg) != -1)
return;
if (agent->sa_is_a_uas) {
/* Orphan 200 Ok to INVITE. ACK and BYE it */
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is ACK&BYE"));
if (nta_msg_ackbye(agent, msg) != -1)
return;
}
}
SU_DEBUG_5(("nta: %03d %s was discarded\n", status, phrase));
SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "was discarded"));
msg_destroy(msg);
}
@@ -2817,6 +2940,7 @@ int nta_msg_mreply(nta_agent_t *agent,
NTATAG_TPORT_REF(tport),
NTATAG_INCOMPLETE_REF(incomplete),
TPTAG_COMPARTMENT_REF(cc),
/* XXX - should also check ntatag_sigcomp_close() */
TAG_END());
if (reply == NULL) {
@@ -3340,6 +3464,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
nta_leg_t *leg;
su_home_t *home;
url_t *url;
char const *what = NULL;
if (agent == NULL)
return su_seterrno(EINVAL), NULL;
@@ -3423,32 +3548,35 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
leg->leg_url = url;
if (from && from != NONE && leg->leg_local == NULL) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate local address\n"));
what = "cannot duplicate local address";
goto err;
}
else if (to && to != NONE && leg->leg_remote == NULL) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate remote address\n"));
what = "cannot duplicate remote address";
goto err;
}
else if (route && route != NONE && leg->leg_route == NULL) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate route\n"));
what = "cannot duplicate route";
goto err;
}
else if (contact && contact != NONE && leg->leg_target == NULL) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate target\n"));
what = "cannot duplicate target";
goto err;
}
else if (url_string && leg->leg_url == NULL) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot duplicate local destination\n"));
what = "cannot duplicate local destination";
goto err;
}
if (!no_dialog) {
if (!leg->leg_local || !leg->leg_remote) {
/* To and/or From header missing */
SU_DEBUG_3(("nta_leg_tcreate(): missing%s%s header\n",
!leg->leg_remote ? " To" : "",
!leg->leg_local ? " From" : ""));
if (leg->leg_remote)
what = "Missing local dialog address";
else if (leg->leg_local)
what = "Missing remote dialog address";
else
what = "Missing dialog addresses";
goto err;
}
@@ -3462,7 +3590,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
leg->leg_id = sip_call_id_create(home, NULL);
if (!leg->leg_id) {
SU_DEBUG_3(("nta_leg_tcreate(): cannot create Call-ID\n"));
what = "cannot create Call-ID";
goto err;
}
@@ -3498,7 +3626,7 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
else {
/* This is "default leg" without a destination URL. */
if (agent->sa_default_leg) {
SU_DEBUG_1(("leg_create(): tried to create second default leg\n"));
SU_DEBUG_1(("%s(): %s\n", "nta_leg_tcreate", "tried to create second default leg"));
su_seterrno(EEXIST);
goto err;
}
@@ -3515,11 +3643,14 @@ nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
leg_insert(agent, leg);
SU_DEBUG_9(("nta_leg_create(%p)\n", (void *)leg));
SU_DEBUG_9(("%s(%p)\n", "nta_leg_tcreate", (void *)leg));
return leg;
err:
if (what)
SU_DEBUG_9(("%s(): %s\n", "nta_leg_tcreate", what));
su_home_zap(leg->leg_home);
return NULL;
@@ -4478,7 +4609,7 @@ nta_incoming_t *incoming_create(nta_agent_t *agent,
}
else {
queue = agent->sa_in.proceeding;
/* draft-sparks-sip-nit-actions-03:
/* RFC 4320 (nit-actions-03):
Blacklisting on a late response occurs even over reliable transports.
Thus, if an element processing a request received over a reliable
@@ -5661,7 +5792,7 @@ int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
irq->irq_method != sip_method_invite &&
!agent->sa_pass_408 &&
!irq->irq_default) {
/* draft-sparks-sip-nit-actions-03 Action 2:
/* RFC 4320 nit-actions-03 Action 2:
A transaction-stateful SIP element MUST NOT send a response with
Status-Code of 408 to a non-INVITE request. As a consequence, an
@@ -6199,6 +6330,9 @@ static size_t outgoing_timer_dk(outgoing_queue_t *q,
static size_t outgoing_timer_bf(outgoing_queue_t *q,
char const *timer,
su_duration_t now);
static size_t outgoing_timer_c(outgoing_queue_t *q,
char const *timer,
su_duration_t now);
static void outgoing_ack(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);
static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *,
@@ -6303,7 +6437,7 @@ nta_outgoing_t *nta_outgoing_default(nta_agent_t *agent,
* NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
* NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
* NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
* SIP tags from <sip_tag.h> can be used to manipulate the request message.
* SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message.
* SIP tags after SIPTAG_END() are ignored, however.
*/
nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg,
@@ -6385,13 +6519,13 @@ nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg,
* transaction is freed before returning from the function.
*
* @sa
* nta_outgoing_tcreate(), nnta_outgoing_tcancel(), nta_outgoing_destroy().
* nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
*
* @TAGS
* NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
* NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
* NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
* SIP tags from <sip_tag.h> can be used to manipulate the request message.
* SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message.
* SIP tags after SIPTAG_END() are ignored, however.
*/
nta_outgoing_t *nta_outgoing_mcreate(nta_agent_t *agent,
@@ -6611,7 +6745,7 @@ unsigned nta_outgoing_delay(nta_outgoing_t const *orq)
return orq != NULL && orq != NONE ? orq->orq_delay : UINT_MAX;
}
/** Get the branch parameter. */
/** Get the branch parameter. @NEW_1_12_7 */
char const *nta_outgoing_branch(nta_outgoing_t const *orq)
{
return orq != NULL && orq != NONE && orq->orq_branch
@@ -6713,6 +6847,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
char const *scheme = NULL;
char const *port = NULL;
int invalid, resolved, stateless = 0, user_via = agent->sa_user_via;
int invite_100rel = agent->sa_invite_100rel;
tagi_t const *t;
tport_t const *override_tport = NULL;
@@ -6777,6 +6913,9 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
else if (ntatag_tport == tt) {
override_tport = (tport_t *)t->t_value;
}
else if (ntatag_rel100 == tt) {
invite_100rel = t->t_value != 0;
}
}
orq->orq_agent = agent;
@@ -6798,6 +6937,8 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent,
orq->orq_delay = UINT_MAX;
orq->orq_stateless = stateless != 0;
orq->orq_user_via = user_via != 0 && sip->sip_via;
orq->orq_100rel = invite_100rel;
if (cc)
orq->orq_cc = nta_compartment_ref(cc);
@@ -7332,17 +7473,18 @@ int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq,
supported[i = 0] = NULL;
if (orq->orq_method == sip_method_invite) {
int add_100rel = agent->sa_invite_100rel;
int require_100rel = sip_has_feature(sip->sip_require, "100rel");
tl_gets(tags,
NTATAG_REL100_REF(add_100rel),
TAG_END());
if (add_100rel && !require_100rel &&
!sip_has_feature(sip->sip_supported, "100rel"))
supported[i++] = "100rel";
orq->orq_must_100rel = require_100rel;
if (require_100rel) {
orq->orq_must_100rel = 1;
orq->orq_100rel = 1;
}
else if (sip_has_feature(sip->sip_supported, "100rel")) {
orq->orq_100rel = 1;
}
else if (orq->orq_100rel) {
supported[i++] = "100rel";
}
}
if (i) {
@@ -7404,7 +7546,8 @@ outgoing_queue_adjust(nta_agent_t *sa,
latest = set_timeout(sa, queue->q_timeout = timeout);
for (orq = queue->q_head; orq; orq = orq->orq_next) {
if (orq->orq_timeout - latest > 0)
if (orq->orq_timeout == 0 ||
orq->orq_timeout - latest > 0)
orq->orq_timeout = latest;
}
}
@@ -7659,6 +7802,7 @@ su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next)
sa->sa_out.inv_calling->q_length;
size_t completed = sa->sa_out.completed->q_length +
sa->sa_out.inv_completed->q_length;
outgoing_queue_t *proceeding = sa->sa_out.inv_proceeding;
outgoing_queue_init(sa->sa_out.free = rq, 0);
@@ -7712,9 +7856,12 @@ su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next)
timeout
= outgoing_timer_bf(sa->sa_out.inv_calling, "B", now)
+ outgoing_timer_c(proceeding, "C", now)
+ outgoing_timer_bf(sa->sa_out.trying, "F", now);
next = NEXT_TIMEOUT(next, sa->sa_out.inv_calling->q_head, orq_timeout, now);
if (proceeding->q_timeout)
next = NEXT_TIMEOUT(next, proceeding->q_head, orq_timeout, now);
next = NEXT_TIMEOUT(next, sa->sa_out.trying->q_head, orq_timeout, now);
destroyed = outgoing_mass_destroy(sa, rq);
@@ -7791,6 +7938,38 @@ size_t outgoing_timer_bf(outgoing_queue_t *q,
return timeout;
}
/** Handle timer C */
static
size_t outgoing_timer_c(outgoing_queue_t *q,
char const *timer,
su_duration_t now)
{
nta_outgoing_t *orq;
size_t timeout = 0;
if (q->q_timeout == 0)
return 0;
while ((orq = q->q_head)) {
if (orq->orq_timeout - now > 0 || timeout >= timer_max_timeout)
break;
timeout++;
SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n",
timer, "CANCEL and timeout",
orq->orq_method_name, orq->orq_cseq->cs_seq));
nta_outgoing_tcancel(orq, NULL, NULL, TAG_NULL());
outgoing_timeout(orq, now);
assert(q->q_head != orq);
}
return timeout;
}
/** @internal Signal transaction timeout to the application. */
void outgoing_timeout(nta_outgoing_t *orq, su_duration_t now)
{
@@ -8074,6 +8253,13 @@ int outgoing_recv(nta_outgoing_t *orq,
orq->orq_status = status;
outgoing_queue(sa->sa_out.inv_proceeding, orq);
}
else if (orq->orq_queue == sa->sa_out.inv_proceeding) {
orq->orq_status = status;
if (sa->sa_out.inv_proceeding->q_timeout) {
outgoing_remove(orq);
outgoing_queue(sa->sa_out.inv_proceeding, orq);
}
}
/* Handle 100rel */
if (sip && sip->sip_rseq)
@@ -8092,6 +8278,10 @@ int outgoing_recv(nta_outgoing_t *orq,
return 0;
if (sip && sa->sa_is_a_uas) {
/*
* We silently discard duplicate final responses to INVITE below
* with outgoing_duplicate()
*/
su_home_t *home = msg_home(orq->orq_request);
orq->orq_tag = su_strdup(home, sip->sip_to->a_tag);
}
@@ -8119,6 +8309,10 @@ int outgoing_recv(nta_outgoing_t *orq,
assert(orq_status < 200); (void)orq_status;
if (status < 200) {
/* @RFC3261 17.1.2.1:
* retransmissions continue for unreliable transports,
* but at an interval of T2
*/
if (!orq->orq_reliable)
outgoing_set_timer(orq, sa->sa_t2);
}
@@ -8324,6 +8518,33 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
if (!sip)
return NULL;
if (tags) {
sip_add_tl(msg, sip, TAG_NEXT(tags));
/* Bug sf.net # 173323:
* Ensure that request-URI, topmost Via, From, To, Call-ID, CSeq,
* Max-Forward, Route, Accept-Contact, Reject-Contact and
* Request-Disposition are copied from original request
*/
if (sip->sip_from)
sip_header_remove(msg, sip, (void *)sip->sip_from);
if (sip->sip_to)
sip_header_remove(msg, sip, (void *)sip->sip_to);
if (sip->sip_call_id)
sip_header_remove(msg, sip, (void *)sip->sip_call_id);
while (sip->sip_route)
sip_header_remove(msg, sip, (void *)sip->sip_route);
while (sip->sip_accept_contact)
sip_header_remove(msg, sip, (void *)sip->sip_accept_contact);
while (sip->sip_reject_contact)
sip_header_remove(msg, sip, (void *)sip->sip_reject_contact);
if (sip->sip_request_disposition)
sip_header_remove(msg, sip, (void *)sip->sip_request_disposition);
while (sip->sip_via)
sip_header_remove(msg, sip, (void *)sip->sip_via);
if (sip->sip_max_forwards)
sip_header_remove(msg, sip, (void *)sip->sip_max_forwards);
}
sip->sip_request =
sip_request_create(home, m, mname, (url_string_t *)orq->orq_url, NULL);
@@ -8335,6 +8556,7 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
sip_add_dup(msg, sip, (sip_header_t *)old->sip_accept_contact);
sip_add_dup(msg, sip, (sip_header_t *)old->sip_reject_contact);
sip_add_dup(msg, sip, (sip_header_t *)old->sip_request_disposition);
sip_add_dup(msg, sip, (sip_header_t *)old->sip_max_forwards);
if (old->sip_via) {
/* Add only the topmost Via header */
@@ -8344,12 +8566,6 @@ msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
sip->sip_cseq = sip_cseq_create(home, old->sip_cseq->cs_seq, m, mname);
if (tags)
sip_add_tl(msg, sip, TAG_NEXT(tags));
if (!sip->sip_max_forwards)
sip_add_dup(msg, sip, (sip_header_t *)orq->orq_agent->sa_max_forwards);
if (sip->sip_request &&
sip->sip_to &&
sip->sip_from &&
@@ -8418,7 +8634,9 @@ int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
/* Create response message, if needed */
if (!orq->orq_stateless &&
!(orq->orq_callback == outgoing_default_cb) &&
!(status == 408 && !orq->orq_agent->sa_timeout_408)) {
!(status == 408 &&
orq->orq_method != sip_method_invite &&
!orq->orq_agent->sa_timeout_408)) {
char const *to_tag;
msg = nta_msg_create(agent, NTA_INTERNAL_MSG);
+3 -2
View File
@@ -24,8 +24,9 @@
* (#nta_incoming_t).
*
* NTA also uses SIP message objects #msg_t and #sip_t for handling
* messages, as defined in <msg.h> and <sip.h>, respectively. The various
* SIP headers are also defined in <sip.h>.
* messages, as defined in <sofia-sip/msg.h> and <sofia-sip/sip.h>,
* respectively. The various SIP headers are also defined in
* <sofia-sip/sip.h>.
*
* @section nta_agent_t Creating an NTA Agent
*
@@ -160,10 +160,13 @@ struct nta_agent_s
/** Progress timer - interval between provisional responses sent */
unsigned sa_progress;
/** SIP timer C - interval between provisional responses receivedxs */
unsigned sa_timer_c;
/** Blacklisting period */
unsigned sa_blacklist;
/** NTA is used to test packet drop */
/** NTA is used to test packet drop */
unsigned sa_drop_prob : 10;
/** NTA is acting as an User Agent server */
unsigned sa_is_a_uas : 1;
@@ -226,6 +229,9 @@ struct nta_agent_s
/** Set when executing timer */
unsigned sa_in_timer:1;
/** Set if application has set value for timer C */
unsigned sa_use_timer_c:1;
unsigned :0;
@@ -307,7 +313,7 @@ struct nta_agent_s
/* Special queues (states) for outgoing INVITE transactions */
outgoing_queue_t inv_calling[1]; /* Timer B/A */
outgoing_queue_t inv_proceeding[1];
outgoing_queue_t inv_proceeding[1]; /* Timer C */
outgoing_queue_t inv_completed[1]; /* Timer D */
/* Temporary queue for transactions waiting to be freed */
@@ -517,6 +523,7 @@ struct nta_outgoing_s
unsigned orq_sigcomp_zap:1; /**< Reset SigComp after completing */
unsigned orq_must_100rel : 1;
unsigned orq_timestamp : 1; /**< Insert @Timestamp header. */
unsigned orq_100rel:1; /**< Support 100rel */
unsigned : 0; /* pad */
#if HAVE_SOFIA_SRESOLV
@@ -76,6 +76,7 @@ tag_typedef_t ntatag_sip_t1x64 = UINTTAG_TYPEDEF(sip_t1x64);
tag_typedef_t ntatag_sip_t2 = UINTTAG_TYPEDEF(sip_t2);
tag_typedef_t ntatag_sip_t4 = UINTTAG_TYPEDEF(sip_t4);
tag_typedef_t ntatag_progress = UINTTAG_TYPEDEF(progress);
tag_typedef_t ntatag_timer_c = UINTTAG_TYPEDEF(timer_c);
tag_typedef_t ntatag_blacklist = UINTTAG_TYPEDEF(blacklist);
tag_typedef_t ntatag_debug_drop_prob = UINTTAG_TYPEDEF(debug_drop_prob);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -453,84 +453,129 @@ int api_test_params(agent_t *ag)
sip_contact_t const *aliases = (void *)-1;
msg_mclass_t *mclass = (void *)-1;
sip_contact_t *contact = (void *)-1;
url_string_t const *default_proxy = (void *)-1;
void *smime = (void *)-1;
unsigned blacklist = -1;
unsigned debug_drop_prob = -1;
unsigned max_forwards = -1;
unsigned maxsize = -1;
unsigned preload = -1;
unsigned progress = -1;
unsigned sip_t1 = -1;
unsigned sip_t2 = -1;
unsigned sip_t4 = -1;
unsigned debug_drop_prob = -1;
int ua = -1;
int user_via = -1;
int extra_100 = -1;
int pass_100 = -1;
int timeout_408 = -1;
int pass_408 = -1;
int merge_482 = -1;
unsigned sip_t4 = -1;
unsigned timer_c = -1;
unsigned udp_mtu = -1;
int cancel_2543 = -1;
int cancel_487 = -1;
int client_rport = -1;
int extra_100 = -1;
int merge_482 = -1;
int pass_100 = -1;
int pass_408 = -1;
int rel100 = -1;
int use_timestamp = -1;
int server_rport = -1;
int stateless = -1;
int tag_3261 = -1;
int timeout_408 = -1;
int ua = -1;
int use_naptr = -1;
int use_srv = -1;
unsigned preload = (unsigned)-1;
int use_timestamp = -1;
int user_via = -1;
char const *s = NONE;
TEST_1(nta = nta_agent_create(ag->ag_root, (url_string_t *)"sip:*:*",
NULL, NULL, TAG_END()));
TEST(nta_agent_get_params(nta,
NTATAG_MCLASS_REF(mclass),
NTATAG_ALIASES_REF(aliases),
NTATAG_BLACKLIST_REF(blacklist),
NTATAG_CANCEL_2543_REF(cancel_2543),
NTATAG_CANCEL_487_REF(cancel_487),
NTATAG_CLIENT_RPORT_REF(client_rport),
NTATAG_CONTACT_REF(contact),
NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob),
NTATAG_DEFAULT_PROXY_REF(default_proxy),
NTATAG_EXTRA_100_REF(extra_100),
NTATAG_MAXSIZE_REF(maxsize),
NTATAG_MAX_FORWARDS_REF(max_forwards),
NTATAG_MCLASS_REF(mclass),
NTATAG_MERGE_482_REF(merge_482),
NTATAG_PASS_100_REF(pass_100),
NTATAG_PASS_408_REF(pass_408),
NTATAG_PRELOAD_REF(preload),
NTATAG_PROGRESS_REF(progress),
NTATAG_REL100_REF(rel100),
NTATAG_SERVER_RPORT_REF(server_rport),
NTATAG_SIP_T1_REF(sip_t1),
NTATAG_SIP_T2_REF(sip_t2),
NTATAG_SIP_T4_REF(sip_t4),
NTATAG_DEBUG_DROP_PROB_REF(debug_drop_prob),
NTATAG_UA_REF(ua),
NTATAG_USER_VIA_REF(user_via),
NTATAG_EXTRA_100_REF(extra_100),
NTATAG_PASS_100_REF(pass_100),
NTATAG_SMIME_REF(smime),
NTATAG_STATELESS_REF(stateless),
NTATAG_TAG_3261_REF(tag_3261),
NTATAG_TIMEOUT_408_REF(timeout_408),
NTATAG_PASS_408_REF(pass_408),
NTATAG_MERGE_482_REF(merge_482),
NTATAG_CANCEL_2543_REF(cancel_2543),
NTATAG_CANCEL_487_REF(cancel_487),
NTATAG_REL100_REF(rel100),
NTATAG_USE_TIMESTAMP_REF(use_timestamp),
NTATAG_TIMER_C_REF(timer_c),
NTATAG_UA_REF(ua),
NTATAG_UDP_MTU_REF(udp_mtu),
NTATAG_USER_VIA_REF(user_via),
NTATAG_USE_NAPTR_REF(use_naptr),
NTATAG_USE_SRV_REF(use_srv),
NTATAG_USE_TIMESTAMP_REF(use_timestamp),
TAG_END()),
/* Number of parameters */ 19);
/* Number of parameters */ 33);
TEST_P(mclass, sip_default_mclass());
TEST_P(aliases, NULL);
TEST_1(contact != (void *)-1 && contact != NULL);
TEST_1(default_proxy == NULL);
TEST_1(smime == NULL);
TEST_1(blacklist != -1);
TEST(debug_drop_prob, 0);
TEST_1(max_forwards >= 20);
TEST_1(maxsize >= 65536);
TEST_1(preload != -1);
TEST_1(progress <= 60 * 1000);
TEST(sip_t1, NTA_SIP_T1);
TEST(sip_t2, NTA_SIP_T2);
TEST(sip_t4, NTA_SIP_T4);
TEST(debug_drop_prob, 0);
TEST(ua, 0);
TEST(user_via, 0);
TEST(extra_100, 0);
TEST(pass_100, 0);
TEST(timeout_408, 1);
TEST(pass_408, 0);
TEST(merge_482, 0);
TEST(cancel_2543, 0);
TEST(cancel_487, 1);
TEST(rel100, 0);
TEST(use_timestamp, 0);
TEST(use_naptr, 1);
TEST(use_srv, 1);
TEST_1(timer_c > 180 * 1000);
TEST(udp_mtu, 1300);
TEST_1(cancel_2543 != -1);
TEST_1(cancel_487 != -1);
TEST_1(client_rport != -1);
TEST_1(extra_100 != -1);
TEST_1(merge_482 != -1);
TEST_1(pass_100 != -1);
TEST_1(pass_408 != -1);
TEST_1(rel100 != -1);
TEST_1(server_rport != -1);
TEST_1(stateless == 0);
TEST_1(timeout_408 != -1);
TEST_1(ua == 0);
TEST_1(use_naptr != -1);
TEST_1(use_srv != -1);
TEST_1(use_timestamp != -1);
TEST_1(user_via == 0);
TEST(nta_agent_set_params(NULL,
NTATAG_PRELOAD(2048),
TAG_END()), -1);
NTATAG_PRELOAD(2048),
TAG_END()), -1);
TEST(nta_agent_get_params(NULL,
NTATAG_PRELOAD_REF(preload),
TAG_END()), -1);
NTATAG_PRELOAD_REF(preload),
TAG_END()), -1);
TEST(nta_agent_set_params(nta,
NTATAG_PRELOAD(2048),
TAG_END()), 1);
NTATAG_PRELOAD(2048),
TAG_END()), 1);
TEST(nta_agent_get_params(nta,
NTATAG_PRELOAD_REF(preload),
TAG_END()), 1);
NTATAG_PRELOAD_REF(preload),
TAG_END()), 1);
TEST(preload, 2048);
TEST(nta_agent_set_params(nta,
+2 -2
View File
@@ -6,8 +6,8 @@
*
* NTH provides interface to simple HTTP transaction engines for both HTTP
* servers and clients. The transaction interface for both client and server
* is available through <nth.h>, tags controlling the options in
* <nth_tag.h>.
* is available through <sofia-sip/nth.h>, tags controlling the options in
* <sofia-sip/nth_tag.h>.
*
* @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
*
@@ -174,7 +174,7 @@ struct nth_client_s {
* The NTH_DEBUG environment variable is used to determine the debug
* logging level for @b nth module. The default level is 1.
*
* @sa <su_debug.h>, nth_client_log, #SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, nth_client_log, #SOFIA_DEBUG
*/
extern char const NTH_DEBUG[];
@@ -172,7 +172,7 @@ struct nth_request_s
* The NTH_DEBUG environment variable is used to determine the debug
* logging level for @b nth module. The default level is 1.
*
* @sa <su_debug.h>, nth_server_log, SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, nth_server_log, SOFIA_DEBUG
*/
extern char const NTH_DEBUG[];
+41 -10
View File
@@ -101,11 +101,11 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
* NUTAG_URL() \n
* NUTAG_SIPS_URL() \n
* NUTAG_SIP_PARSER() \n
* NUTAG_UICC() \n
* NUTAG_CERTIFICATE_DIR() \n
* and all tags listed in nua_set_params(), \n
* and all relevant NTATAG_* are passed to NTA \n
* and all tport tags listed in <sofia-sip/tport_tag.h>
* all tags listed in nua_set_params(), \n
* all NTATAG_* are passed to NTA listed in <sofia-sip/nta_tag.h> \n
* all tport tags listed in <sofia-sip/tport_tag.h> \n
* STUNTAG_DOMAIN(), STUNTAG_SERVER() \n
*
* @note
* From the @VERSION_1_12_2 all the nua_set_params() tags are processed.
@@ -119,7 +119,7 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
* @par Events:
* none
*
* @sa nua_shutdown(), nua_destroy(), nua_handle()
* @sa nua_shutdown(), nua_destroy(), nua_handle(), nta_agent_create().
*/
nua_t *nua_create(su_root_t *root,
nua_callback_f callback,
@@ -1040,19 +1040,30 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e)
su_msg_destroy(nua->nua_current);
}
/** Get current request message. @NEW_1_12_4. */
/** Get current request message. @NEW_1_12_4.
*
* @note A response message is returned when processing response message.
*
* @sa #nua_event_e, nua_respond(), NUTAG_WITH_CURRENT()
*/
msg_t *nua_current_request(nua_t const *nua)
{
return nua && nua->nua_current ? su_msg_data(nua->nua_current)->e_msg : NULL;
}
/** Get request message from saved nua event. @NEW_1_12_4. */
/** Get request message from saved nua event. @NEW_1_12_4.
*
* @sa nua_save_event(), nua_respond(), NUTAG_WITH_SAVED(),
*/
msg_t *nua_saved_event_request(nua_saved_event_t const *saved)
{
return saved && saved[0] ? su_msg_data(saved)->e_msg : NULL;
}
/** Save nua event and its arguments */
/** Save nua event and its arguments.
*
* @sa #nua_event_e, nua_event_data() nua_saved_event_request(), nua_destroy_event()
*/
int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
{
if (nua && return_saved) {
@@ -1066,13 +1077,19 @@ int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
return 0;
}
/** Get event data */
/** Get event data.
*
* @sa #nua_event_e, nua_event_save(), nua_saved_event_request(), nua_destroy_event().
*/
nua_event_data_t const *nua_event_data(nua_saved_event_t const saved[1])
{
return saved ? su_msg_data(saved) : NULL;
}
/** Destroy saved event */
/** Destroy saved event.
*
* @sa #nua_event_e, nua_event_save(), nua_event_data(), nua_saved_event_request().
*/
void nua_destroy_event(nua_saved_event_t saved[1])
{
if (su_msg_is_non_null(saved)) {
@@ -1136,7 +1153,14 @@ sip_replaces_t *nua_handle_make_replaces(nua_handle_t *nh,
int early_only)
{
if (nh && nh->nh_valid && nh->nh_nua) {
#if HAVE_OPEN_C
struct nua_stack_handle_make_replaces_args a = { NULL, NULL, NULL, 0 };
a.nh = nh;
a.home = home;
a.early_only = early_only;
#else
struct nua_stack_handle_make_replaces_args a = { NULL, nh, home, early_only };
#endif
if (su_task_execute(nh->nh_nua->nua_server,
nua_stack_handle_make_replaces_call, (void *)&a,
@@ -1176,7 +1200,14 @@ static int nua_stack_handle_by_replaces_call(void *arg)
nua_handle_t *nua_handle_by_replaces(nua_t *nua, sip_replaces_t const *r)
{
if (nua) {
#if HAVE_OPEN_C
struct nua_stack_handle_by_replaces_args a;
a.retval = NULL;
a.nua = nua;
a.r = r;
#else
struct nua_stack_handle_by_replaces_args a = { NULL, nua, r };
#endif
if (su_task_execute(nua->nua_server,
nua_stack_handle_by_replaces_call, (void *)&a,
+17 -15
View File
@@ -26,18 +26,18 @@ The NUA API gives the high-level application programmer transparent and
full control to the SIP protocol engine below it. NUA provides the call
semantics on top of existing transaction semantics found in
<a href="../nta/index.html"><b>nta</b></a> module.
API makes it possible to create different kind of User Agents,
With NUA it is possible to create different kind of SIP User Agents,
like terminals, gateways or MCUs.
The @b nua engine hides many low-level signaling and media management
aspects from the application programmer. It is possible to use different
kind of media interfaces - even remote ones - in a fully transparent way.
The application and the protocol engine within User Agent library can be
run in separate threads. Communications from the protocol engine is
conveyed through a callback function. The callback function is called
within context of the application, so the application must provide
appropriate handle to a #su_root_t object.
The application and the protocol engine within User Agent library can be run
in separate threads. The protocol engine communicates with the application
using @ref nua_event_e "events", delivered to the application with a a
callback function. The callback function is called within the thread context
of the application, represented with a #su_root_t object.
@section nua_concepts_user Sofia Concepts for NUA User
@@ -74,14 +74,14 @@ the main event loop of the task. Through the root object the task code
can access its context information (magic) and thread-synchronization
features like wait objects, timers, and messages.
An application using NUA services must create a root object and the
callback routine to handle events. The root object is created with
su_root_create() function and the callback routine is registered with
An application using NUA services must create a root object and the callback
routine to handle @ref nua_event_e "NUA events". The root object is created
with su_root_create() function and the callback routine is registered with
nua_create() function.
Root object has type #su_root_t.
See documentation of <su_wait.h> and <su_root.c> for more information
See documentation of <sofia-sip/su_wait.h> and <su_root.c> for more information
of root object.
See section #nua_event_e for more information of the callback function.
@@ -109,8 +109,8 @@ separately.
An application using NUA services can use the memory management services
provided by the SU library but it is not mandatory.
See documentation of <su_alloc.h> for more information of memory management
services.
See documentation of <sofia-sip/su_alloc.h> for more information of memory
management services.
@subsection nua_tags Tags
@@ -169,14 +169,14 @@ An application using NUA services must use tagged arguments for passing the
parameters to functions. See nua_invite() for discussion on how a SIP
message is constructed from the tags.
See documentation of <su_tag.h> for more information of tags and the
See documentation of <sofia-sip/su_tag.h> for more information of tags and the
module-specific documentation of each Sofia module for information of
tags specific for that module.
@subsection nua_debugandlogging Debugging and Logging
The modules of Sofia stack contain configurable debugging and logging
functionality based on the services defined in <su_log.h>. The debugging
functionality based on the services defined in <sofia-sip/su_log.h>. The debugging
and logging details (for example level of details on output and output
file name) can be configured by environment variables, directives in
configuration files and compilation directives in the source files.
@@ -201,7 +201,7 @@ The defined debug output levels are:
An application using NUA services can also use the debugging and
logging services provided by the Sofia stack but it is not mandatory.
See documentation of <su_log.h> for more information of debugging and
See documentation of <sofia-sip/su_log.h> for more information of debugging and
logging services.
@section nua_concepts NUA Concepts
@@ -2089,6 +2089,8 @@ NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side.
* #nua_r_unregister \n
* #nua_r_unsubscribe \n
* #nua_r_update
*
* @sa nua_event_is_incoming_request(), nua_event_name()
*/
/** @NUA_EVENT nua_i_chat
@@ -235,7 +235,7 @@ char const *nua_generate_instance_identifier(su_home_t *home)
* ...
* @endcode
*
* @sa #nua_event_t, nua_respond()
* @sa nua_respond(), #nua_event_e, #nua_event_t, nua_event_name()
*
* @NEW_1_12_6
*/
@@ -260,7 +260,10 @@ int nua_event_is_incoming_request(nua_event_t event)
}
}
/** Get name for a NUA event. */
/** Get name for a NUA event.
*
* @sa #nua_event_e, #nua_event_t, nua_callstate_name(), nua_substate_name()
*/
char const *nua_event_name(nua_event_t event)
{
switch (event) {
@@ -329,7 +332,10 @@ char const *nua_event_name(nua_event_t event)
}
}
/** Return name of call state */
/** Return name of call state.
*
* @sa enum #nua_callstate, nua_event_name(), nua_substate_name()
*/
char const *nua_callstate_name(enum nua_callstate state)
{
switch (state) {
@@ -348,7 +354,10 @@ char const *nua_callstate_name(enum nua_callstate state)
}
}
/** Return name of subscription state. @NEW_1_12_5. */
/** Return name of subscription state. @NEW_1_12_5.
*
* @sa enum #nua_substate, nua_event_name(), nua_callstate_name()
*/
char const *nua_substate_name(enum nua_substate substate)
{
switch (substate) {
@@ -63,7 +63,7 @@
* NUTAG_METHOD() \n
* NUTAG_URL() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_method
@@ -64,7 +64,7 @@
* @par Related Tags:
* NUTAG_URL() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_message
@@ -366,7 +366,7 @@ int nua_subscribe_server_report(nua_server_request_t *sr, tagi_t const *tags)
* @par Related Tags:
* NUTAG_SUBSTATE() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_notify
@@ -58,7 +58,7 @@
* nothing
*
* @par Related Tags:
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_options
@@ -1088,6 +1088,11 @@ static int nua_handle_param_filter(tagi_t const *f, tagi_t const *t);
/** Save taglist to a handle */
int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
{
#if HAVE_OPEN_C
/* Nice. An old symbian compiler */
tagi_t tagfilter[2];
tagi_t paramfilter[2];
#else
tagi_t const tagfilter[] = {
{ TAG_FILTER(nua_handle_tags_filter) },
{ TAG_NULL() }
@@ -1096,6 +1101,7 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
{ TAG_FILTER(nua_handle_param_filter) },
{ TAG_NULL() }
};
#endif
/* Initialization parameters */
url_string_t const *url = NULL;
@@ -1112,6 +1118,18 @@ int nua_handle_save_tags(nua_handle_t *nh, tagi_t *tags)
int error;
#if HAVE_OPEN_C
tagfilter[0].t_tag = tag_filter;
tagfilter[0].t_value = tag_filter_v(nua_handle_tags_filter);
tagfilter[1].t_tag = (tag_type_t)0;
tagfilter[1].t_value = (tag_value_t)0;
paramfilter[0].t_tag = tag_filter;
paramfilter[0].t_value = tag_filter_v(nua_handle_param_filter);
paramfilter[1].t_tag = (tag_type_t)0;
paramfilter[1].t_value = (tag_value_t)0;
#endif
for (t = tags; t; t = tl_next(t)) {
if (t->t_tag == NULL)
break;
@@ -138,7 +138,7 @@ void nua_publish_usage_remove(nua_handle_t *nh,
* @par Related Tags:
* NUTAG_URL() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_publish
@@ -196,7 +196,7 @@ void nua_unpublish(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
* SIPTAG_IF_MATCH(), SIPTAG_IF_MATCH_STR() \n
* SIPTAG_EVENT(), SIPTAG_EVENT_STR() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Other header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
*
* @par Events:
* #nua_r_unpublish
@@ -48,7 +48,7 @@
#include <sofia-sip/sip_util.h>
#include <sofia-sip/sip_status.h>
#define NTA_UPDATE_MAGIC_T struct nua_handle_s
#define NTA_UPDATE_MAGIC_T struct nua_s
#include "nua_stack.h"
@@ -516,7 +516,7 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
*
* @par Related tags:
* NUTAG_REGISTRAR() \n
* Tags in <sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
* Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
*
* @par Events:
* #nua_r_unregister
@@ -999,7 +999,7 @@ static int nua_invite_client_report(nua_client_request_t *cr,
* nothing
*
* @par Related Tags:
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_i_media_error \n
@@ -1217,7 +1217,7 @@ static int nua_invite_client_deinit(nua_client_request_t *cr)
* nothing
*
* @par Related Tags:
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_cancel, #nua_i_state (#nua_i_active, #nua_i_terminated)
@@ -2714,7 +2714,7 @@ nh_referral_respond(nua_handle_t *nh, int status, char const *phrase)
* nothing
*
* @par Related Tags:
* Tags in <sip_tag.h>.
* Header tags defined in <sofia-sip/sip_tag.h>.
*
* @par Events:
* #nua_r_info
+14 -6
View File
@@ -781,10 +781,6 @@ int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
if (nua_stack_set_params(nua, nh, nua_i_error, ta_args(ta)) < 0)
retval = -1;
if (!retval && nh->nh_soa)
if (soa_set_params(nh->nh_soa, ta_tags(ta)) < 0)
retval = -1;
ta_end(ta);
if (retval || nh->nh_init) /* Already initialized? */
@@ -1338,7 +1334,7 @@ void nua_server_request_destroy(nua_server_request_t *sr)
* SOATAG_AF() \n
* SOATAG_HOLD() \n
* Tags used with nua_set_hparams() \n
* Tags in <sip_tag.h>.
* Header tags defined in <sofia-sip/sip_tag.h>.
*
* @par Events:
* #nua_i_state \n
@@ -1445,13 +1441,25 @@ int nua_server_respond(nua_server_request_t *sr, tagi_t const *tags)
nua_handle_t *nh = sr->sr_owner;
sip_method_t method = sr->sr_method;
struct { msg_t *msg; sip_t *sip; } next = { NULL, NULL };
tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }};
int retval;
#if HAVE_OPEN_C
/* Nice. And old arm symbian compiler; see below. */
tagi_t next_tags[2];
#else
tagi_t next_tags[2] = {{ SIPTAG_END() }, { TAG_NEXT(tags) }};
#endif
msg_t *msg = sr->sr_response.msg;
sip_t *sip = sr->sr_response.sip;
sip_contact_t *m = sr->sr_request.sip->sip_contact;
#if HAVE_OPEN_C
next_tags[0].t_tag = siptag_end;
next_tags[0].t_value = (tag_value_t)0;
next_tags[1].t_tag = tag_next;
next_tags[1].t_value = (tag_value_t)(tags);
#endif
if (sr->sr_response.msg == NULL) {
assert(sr->sr_status == 500);
goto internal_error;
@@ -62,7 +62,7 @@
#ifndef NUA_DIALOG_H
#define NUA_OWNER_T struct nua_handle_s
#include <nua_dialog.h>
#include "nua_dialog.h"
#endif
SOFIA_BEGIN_DECLS
@@ -72,7 +72,7 @@ SOFIA_BEGIN_DECLS
#endif
#ifndef NUA_PARAMS_H
#include <nua_params.h>
#include "nua_params.h"
#endif
typedef struct event_s event_t;
@@ -138,7 +138,7 @@ void nua_subscribe_usage_remove(nua_handle_t *nh,
*
* @par Related Tags:
* NUTAG_URL()
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_subscribe \n
@@ -164,7 +164,7 @@ void nua_subscribe_usage_remove(nua_handle_t *nh,
*
* @par Related Tags:
* SIPTAG_EVENT() or SIPTAG_EVENT_STR() \n
* Tags in <sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
* Header tags defined in <sofia-sip/sip_tag.h> except SIPTAG_EXPIRES() or SIPTAG_EXPIRES_STR()
*
* @par Events:
* #nua_r_unsubscribe
@@ -401,9 +401,10 @@ static int nua_subscribe_client_response(nua_client_request_t *cr,
/* let nua_base_client_tresponse to remove usage */
cr->cr_terminated = 1;
}
return nua_base_client_tresponse(cr, status, phrase, sip,
NUTAG_SUBSTATE(substate),
SIPTAG_EVENT(du ? du->du_event : NULL),
TAG_END());
}
@@ -727,7 +728,7 @@ int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags)
* @par Related Tags:
* NUTAG_URL() \n
* Tags of nua_set_hparams() \n
* Tags in <sip_tag.h>
* Header tags defined in <sofia-sip/sip_tag.h>
*
* @par Events:
* #nua_r_refer \n
@@ -852,6 +853,7 @@ static int nua_refer_client_request(nua_client_request_t *cr,
nua_stack_tevent(nh->nh_nua, nh, NULL,
cr->cr_event, SIP_100_TRYING,
NUTAG_REFER_EVENT(event),
SIPTAG_EVENT(event),
TAG_END());
su_free(nh->nh_home, event);
}
@@ -885,5 +887,6 @@ static int nua_refer_client_response(nua_client_request_t *cr,
return nua_base_client_tresponse(cr, status, phrase, sip,
NUTAG_SUBSTATE(substate),
SIPTAG_EVENT(du ? du->du_event : NULL),
TAG_END());
}
@@ -36,7 +36,7 @@
#define NTA_OUTGOING_MAGIC_T struct outbound
#include <outbound.h>
#include "outbound.h"
#include <sofia-sip/hostdomain.h>
#include <sofia-sip/sip.h>
@@ -172,6 +172,7 @@ typedef struct event_s {
/** NUA module version */
SOFIAPUBVAR char const nua_version[];
/** Typedef of NUA event callback. */
typedef void (*nua_callback_f)(nua_event_t event,
int status, char const *phrase,
nua_t *nua, nua_magic_t *magic,
@@ -349,9 +350,10 @@ SOFIAPUBFUN void nua_respond(nua_handle_t *nh,
/** Check if event can be responded with nua_respond() */
SOFIAPUBFUN int nua_event_is_incoming_request(nua_event_t e);
/** Cast a #nua_handle_t pointer to a #su_home_t. */
#define nua_handle_home(nh) ((su_home_t *)(nh))
/** Generate an instance identifier */
/** Generate an instance identifier. */
SOFIAPUBFUN char const *nua_generate_instance_identifier(su_home_t *);
#ifndef NUA_SAVED_EVENT_T
@@ -1105,6 +1105,256 @@ int test_basic_call_5(struct context *ctx)
END();
}
/* ======================================================================== */
/* Call with media upgrade:
A B
|-------INVITE------>|
| with audio only |
|<----100 Trying-----|
| |
|<----180 Ringing----|
| |
|<------200 OK-------|
|--------ACK-------->|
| |
|<------INVITE-------|
| with video |
|-----100 Trying---->|
| |
|-------200 OK------>|
| with video |
|<-------ACK---------|
| |
|<-------BYE---------|
|-------200 OK------>|
| |
Client transitions:
INIT -(C1)-> CALLING -(C2a)-> PROCEEDING -(C3+C4)-> READY
Server transitions:
INIT -(S1)-> RECEIVED -(S2a)-> EARLY -(S3b)-> COMPLETED -(S4)-> READY
B sends BYE:
READY -(T2)-> TERMINATING -(T3)-> TERMINATED
A receives BYE:
READY -(T1)-> TERMINATED
See @page nua_call_model in nua.docs for more information
*/
int accept_upgrade(CONDITION_PARAMS);
int test_video_call_1(struct context *ctx)
{
BEGIN();
struct endpoint *a = &ctx->a, *b = &ctx->b;
struct call *a_call = a->call, *b_call = b->call;
struct event *e;
sip_t *sip;
sdp_session_t *b_sdp;
sdp_media_t *m, b_video[1];
sdp_rtpmap_t *rm, b_h261[1];
sip_time_t se, min_se;
if (print_headings)
printf("TEST NUA-3.6: Basic call\n");
/* Disable session timer from proxy */
test_proxy_get_session_timer(ctx->p, &se, &min_se);
test_proxy_set_session_timer(ctx->p, 0, 0);
a_call->sdp = "m=audio 5008 RTP/AVP 8";
b_call->sdp = "m=audio 5010 RTP/AVP 0 8";
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
TEST_1(!nua_handle_has_active_call(a_call->nh));
TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
INVITE(a, a_call, a_call->nh,
TAG_IF(!ctx->proxy_tests, NUTAG_URL(b->contact->m_url)),
SOATAG_USER_SDP_STR(a_call->sdp),
NUTAG_AUTOANSWER(0),
TAG_END());
run_ab_until(ctx, -1, until_ready, -1, accept_call_with_early_sdp);
TEST_1(nua_handle_has_active_call(a_call->nh));
TEST_1(!nua_handle_has_call_on_hold(a_call->nh));
TEST_1(nua_handle_has_active_call(b_call->nh));
TEST_1(!nua_handle_has_call_on_hold(b_call->nh));
/* Client transitions:
INIT -(C1)-> CALLING: nua_invite(), nua_i_state
CALLING -(C2)-> PROCEEDING: nua_r_invite, nua_i_state
PROCEEDING -(C3+C4)-> READY: nua_r_invite, nua_i_state
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(is_offer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 180);
TEST_1(sip = sip_object(e->data->e_msg));
TEST_1(sip->sip_payload);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_proceeding); /* PROCEEDING */
TEST_1(is_answer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
/*
Server transitions:
INIT -(S1)-> RECEIVED: nua_i_invite, nua_i_state
RECEIVED -(S2a)-> EARLY: nua_respond(), nua_i_state
EARLY -(S3b)-> COMPLETED: nua_respond(), nua_i_state
COMPLETED -(S4)-> READY: nua_i_ack, nua_i_state
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_early); /* EARLY */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(tl_find(e->data->e_tags, soatag_local_sdp));
TEST_1(b_sdp = sdp_session_dup(nua_handle_home(a_call->nh),
(sdp_session_t *)
tl_find(e->data->e_tags, soatag_local_sdp)
->t_value));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
a_call->sdp =
"m=audio 5008 RTP/AVP 8\n"
"m=video 5014 RTP/AVP 34 31\n";
m = memset(b_video, 0, sizeof b_video);
m->m_size = sizeof *m;
m->m_session = b_sdp;
m->m_type = sdp_media_video, m->m_type_name = "video";
m->m_port = 5016;
m->m_proto = sdp_proto_rtp; m->m_proto_name = "RTP/AVP";
m->m_rtpmaps = memset(rm = b_h261, 0, sizeof b_h261);
rm->rm_size = sizeof *rm;
rm->rm_pt = 31; rm->rm_encoding = "h261"; rm->rm_rate = 90000;
b_sdp->sdp_media->m_next = m;
INVITE(b, b_call, b_call->nh,
SOATAG_USER_SDP(b_sdp),
TAG_END());
run_ab_until(ctx, -1, accept_upgrade, -1, until_ready);
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_calling); /* CALLING */
TEST_1(tl_find(e->data->e_tags, soatag_local_sdp_str));
TEST_1(strstr((char *)
tl_find(e->data->e_tags, soatag_local_sdp_str)->t_value,
"m=video"));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_r_invite);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST_1(is_answer_recv(e->data->e_tags));
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_invite);
TEST(e->data->e_status, 100);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_received); /* RECEIVED */
TEST_1(is_offer_recv(e->data->e_tags));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_completed); /* COMPLETED */
TEST_1(is_answer_sent(e->data->e_tags));
TEST_1(tl_find(e->data->e_tags, soatag_local_sdp_str));
TEST_1(strstr((char *)
tl_find(e->data->e_tags, soatag_local_sdp_str)->t_value,
"m=video"));
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_ack);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_ready); /* READY */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
BYE(b, b_call, b_call->nh, TAG_END());
run_ab_until(ctx, -1, until_terminated, -1, until_terminated);
/* B transitions:
READY --(T2)--> TERMINATING: nua_bye()
TERMINATING --(T3)--> TERMINATED: nua_r_bye, nua_i_state
*/
TEST_1(e = b->events->head); TEST_E(e->data->e_event, nua_r_bye);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, b->events);
TEST_1(!nua_handle_has_active_call(b_call->nh));
/* A transitions:
READY -(T1)-> TERMINATED: nua_i_bye, nua_i_state
*/
TEST_1(e = a->events->head); TEST_E(e->data->e_event, nua_i_bye);
TEST(e->data->e_status, 200);
TEST_1(e = e->next); TEST_E(e->data->e_event, nua_i_state);
TEST(callstate(e->data->e_tags), nua_callstate_terminated); /* TERMINATED */
TEST_1(!e->next);
free_events_in_list(ctx, a->events);
TEST_1(!nua_handle_has_active_call(a_call->nh));
nua_handle_destroy(a_call->nh), a_call->nh = NULL;
nua_handle_destroy(b_call->nh), b_call->nh = NULL;
test_proxy_set_session_timer(ctx->p, se, min_se);
if (print_headings)
printf("TEST NUA-3.6: PASSED\n");
END();
}
int accept_upgrade(CONDITION_PARAMS)
{
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
return 0;
save_event_in_list(ctx, event, ep, call);
if (event == nua_i_invite && status < 200) {
RESPOND(ep, call, nh, SIP_200_OK,
TAG_IF(call->sdp, SOATAG_USER_SDP_STR(call->sdp)),
TAG_END());
return 0;
}
switch (callstate(tags)) {
case nua_callstate_ready:
return 1;
case nua_callstate_terminated:
if (call)
nua_handle_destroy(call->nh), call->nh = NULL;
return 1;
default:
return 0;
}
}
int test_basic_call(struct context *ctx)
{
@@ -1114,5 +1364,6 @@ int test_basic_call(struct context *ctx)
|| test_basic_call_3(ctx)
|| test_basic_call_4(ctx)
|| test_basic_call_5(ctx)
|| test_video_call_1(ctx)
;
}
@@ -97,7 +97,10 @@ int cancel_when_calling(CONDITION_PARAMS)
switch (callstate(tags)) {
case nua_callstate_calling:
CANCEL(ep, call, nh, TAG_END());
CANCEL(ep, call, nh,
/* sf.net bug #173323 */
SIPTAG_CALL_ID_STR("non-existing-call-id"),
TAG_END());
return 0;
case nua_callstate_terminated:
return 1;
+27 -21
View File
@@ -72,6 +72,7 @@ int test_nua_init(struct context *ctx,
char const *appl_method = NULL;
url_t const *p_uri, *a_uri, *b_uri; /* Proxy URI */
char const *a_bind, *a_bind2;
int err = -1;
url_t b_proxy[1];
a_bind = a_bind2 = "sip:0.0.0.0:*";
@@ -235,13 +236,15 @@ int test_nua_init(struct context *ctx,
nua_get_params(ctx->a.nua, TAG_ANY(), TAG_END());
run_a_until(ctx, nua_r_get_params, save_until_final_response);
TEST_1(e = ctx->a.specials->head);
TEST(tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END()), 5); TEST_1(m);
err = tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END());
TEST(err, 5);
TEST_1(m);
TEST_1(ctx->a.contact = sip_contact_dup(ctx->home, m));
TEST_1(ctx->a.to = sip_to_dup(ctx->home, sipaddress));
TEST_1(ctx->a.allow = sip_allow_dup(ctx->home, allow));
@@ -280,13 +283,14 @@ int test_nua_init(struct context *ctx,
nua_get_params(ctx->b.nua, TAG_ANY(), TAG_END());
run_b_until(ctx, nua_r_get_params, save_until_final_response);
TEST_1(e = ctx->b.specials->head);
TEST(tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END()), 5); TEST_1(m);
err = tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END());
TEST(err, 5); TEST_1(m);
TEST_1(ctx->b.contact = sip_contact_dup(ctx->home, m));
TEST_1(ctx->b.to = sip_to_dup(ctx->home, sipaddress));
@@ -317,13 +321,15 @@ int test_nua_init(struct context *ctx,
nua_get_params(ctx->c.nua, TAG_ANY(), TAG_END());
run_c_until(ctx, nua_r_get_params, save_until_final_response);
TEST_1(e = ctx->c.specials->head);
TEST(tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END()), 5); TEST_1(m);
err = tl_gets(e->data->e_tags,
NTATAG_CONTACT_REF(m),
SIPTAG_FROM_REF(sipaddress),
SIPTAG_ALLOW_REF(allow),
NUTAG_APPL_METHOD_REF(appl_method),
SIPTAG_SUPPORTED_REF(supported),
TAG_END());
TEST(err, 5); TEST_1(m);
TEST_1(ctx->c.contact = sip_contact_dup(ctx->home, m));
TEST_1(ctx->c.to = sip_to_dup(ctx->home, sipaddress));
TEST_1(ctx->c.allow = sip_allow_dup(ctx->home, allow));
@@ -79,7 +79,7 @@ STORAGE void PREFIX ##_remove(T *node) \
} \
extern int LIST_DUMMY_VARIABLE
#include <test_nat.h>
#include "test_nat.h"
struct nat {
su_home_t home[1];
@@ -117,6 +117,10 @@ int main(int argc, char *argv[])
struct context ctx[1] = {{{ SU_HOME_INIT(ctx) }}};
#if HAVE_OPEN_C
dup2(1, 2);
#endif
if (getenv("EXPENSIVE_CHECKS"))
o_expensive = 1;
@@ -272,6 +276,25 @@ int main(int argc, char *argv[])
}
#endif
#if HAVE_OPEN_C
tstflags |= tst_verbatim;
level = 9;
o_inat = 1; /* No NATs */
ctx->threading = 1;
ctx->quit_on_single_failure = 1;
su_log_soft_set_level(nua_log, level);
su_log_soft_set_level(soa_log, level);
su_log_soft_set_level(su_log_default, level);
su_log_soft_set_level(nea_log, level);
su_log_soft_set_level(nta_log, level);
su_log_soft_set_level(tport_log, level);
setenv("SU_DEBUG", "9", 1);
setenv("NUA_DEBUG", "9", 1);
setenv("NTA_DEBUG", "9", 1);
setenv("TPORT_DEBUG", "9", 1);
o_events_a = o_events_b = 1;
#endif
su_init();
if (!(TSTFLAGS & tst_verbatim)) {
@@ -279,6 +302,7 @@ int main(int argc, char *argv[])
level = 1;
su_log_soft_set_level(nua_log, level);
su_log_soft_set_level(soa_log, level);
su_log_soft_set_level(su_log_default, level);
su_log_soft_set_level(nea_log, level);
su_log_soft_set_level(nta_log, level);
su_log_soft_set_level(tport_log, level);
@@ -288,16 +312,28 @@ int main(int argc, char *argv[])
|| o_events_a || o_events_b || o_events_c)
print_headings = 1;
#if !HAVE_OPEN_C
#define SINGLE_FAILURE_CHECK() \
do { fflush(stdout); \
if (retval && ctx->quit_on_single_failure) { \
su_deinit(); return retval; } \
} while(0)
#else
#define SINGLE_FAILURE_CHECK() \
do { fflush(stdout); \
if (retval && ctx->quit_on_single_failure) { \
su_deinit(); sleep(10); return retval; } \
} while(0)
#endif
ctx->a.printer = o_events_init ? print_event : NULL;
sleep(2);
retval |= test_nua_api_errors(ctx); SINGLE_FAILURE_CHECK();
retval |= test_tag_filter(); SINGLE_FAILURE_CHECK();
retval |= test_nua_params(ctx); SINGLE_FAILURE_CHECK();
retval |= test_nua_init(ctx, o_iproxy, o_proxy, o_inat,
@@ -351,5 +387,9 @@ int main(int argc, char *argv[])
su_deinit();
#if HAVE_OPEN_C
sleep(7);
#endif
return retval;
}
@@ -49,13 +49,14 @@ struct call;
#include <sofia-sip/su_log.h>
#include <sofia-sip/su_tagarg.h>
#include <sofia-sip/su_tag_io.h>
#include <sofia-sip/nua_tag.h>
#if __APPLE_CC__
#include <sofia-sip/su_osx_runloop.h>
#endif
#include <test_proxy.h>
#include <test_nat.h>
#include "test_proxy.h"
#include "test_nat.h"
#include <sofia-sip/auth_module.h>
#include <stddef.h>
@@ -179,7 +179,8 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.2: BYE without INVITE\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END());
TEST_1(a_call->nh);
BYE(a, a_call, a_call->nh, TAG_END());
@@ -203,7 +204,8 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.3: unregister without register\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(a->to), TAG_END()));
a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(a->to), TAG_END());
TEST_1(a_call->nh);
UNREGISTER(a, a_call, a_call->nh, TAG_END());
@@ -227,7 +229,8 @@ int test_stack_errors(struct context *ctx)
if (print_headings)
printf("TEST NUA-1.2.4: unpublish without publish\n");
TEST_1(a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END()));
a_call->nh = nua_handle(a->nua, a_call, SIPTAG_TO(b->to), TAG_END());
TEST_1(a_call->nh);
UNPUBLISH(a, a_call, a_call->nh, TAG_END());
@@ -83,7 +83,7 @@ STORAGE void PREFIX ##_remove(T *node) \
} \
extern int LIST_DUMMY_VARIABLE
#include <test_proxy.h>
#include "test_proxy.h"
struct proxy {
su_home_t home[1];
+1 -1
View File
@@ -1180,7 +1180,7 @@ int sdp_session_cmp(sdp_session_t const *a, sdp_session_t const *b)
return rv;
for (am = a->sdp_media, bm = b->sdp_media;
am || bb;
am || bm;
am = am->m_next, bm = bm->m_next)
if ((rv = sdp_media_cmp(am, bm)))
return rv;
+5 -5
View File
@@ -15,7 +15,7 @@
*
* @section sip_overview Overview
*
* The structure of each header is defined in @b <sip.h>. In addition to the
* The structure of each header is defined in @b <sofia-sip/sip.h>. In addition to the
* header structure, there is defined a @em header @em class structure and
* some standard functions for each header in the include file @b
* <sofia-sip/sip_header.h>. For header @c X, there are types, functions,
@@ -68,7 +68,7 @@
* structure. The fragments form a dual-linked list known as @e fragment @e
* chain as shown in the above figure. The buffers for the message, the
* fragment chain, and a whole other stuff is held by the generic message
* type, #msg_t, defined in <msg.h>. The internal structure of #msg_t is
* type, #msg_t, defined in <sofia-sip/msg.h>. The internal structure of #msg_t is
* known only within @b msg module and it is hidden from other modules.
*
* The abstract message module @b msg also drives the reverse process,
@@ -168,7 +168,7 @@
* structure. The @e sip_size indicates the size of the structure - the
* application can extend the parser and #sip_t structure beyond the
* original size. The @e sip_flags contains various flags used during the
* parsing and printing process. They are documented in the <msg.h>. These
* parsing and printing process. They are documented in the <sofia-sip/msg.h>. These
* boilerplate members are followed by the pointers to various message
* elements and headers.
*
@@ -572,14 +572,14 @@ int sip_X_e(char buf[], int bsiz, sip_header_t const *h, int flags);
/**@defgroup sip_status_codes SIP Status Codes and Reason Phrases
*
* The macros and variables for the standard SIP status codes and reason
* phrases are defined in <sip_status.h>.
* phrases are defined in <sofia-sip/sip_status.h>.
*/
/**@defgroup sip_tag SIP Tags
*
* SIP headers in tag item lists and tagged argument lists.
*
* The include file <sip_tag.h> defines tags and tag items for including SIP
* The include file <sofia-sip/sip_tag.h> defines tags and tag items for including SIP
* headers in tag item lists or tagged argument lists. For each header,
* there is a tag for pointer to header object and an another tag for string
* containing header value. For example, @From header has tags
@@ -1,5 +1,5 @@
#
# nta has a bad_mask specifying which headers cause nta to automatically
# nta has an error mask specifying which headers cause nta to automatically
# return 400 Bad Message if a critical header or pseudoheader in a request
# has a parsing error.
#
@@ -7,13 +7,18 @@
#
# See <sip_parser.h> for definition of mask values.
#
# The mask can be set when header is added with
# msg_mclass_insert_header_flags().
# The error flags for a particular header can be set when header is added
# with msg_mclass_insert_header_flags().
#
# The flags of existing headers can be modified, if a copy of message class
# is first made with msg_mclass_clone().
#
#
# When updating this file, please update
# NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation, too.
#
#
# Headers that must be valid for all requests
#
@@ -53,7 +58,7 @@ Path = sip_mask_registrar
#
Supported = sip_mask_ua | sip_mask_proxy | sip_mask_registrar
Contact = sip_mask_ua | sip_mask_proxy | sip_mask_registrar
Require = sip_mask_ua | sip_mask_registrar
Require = sip_mask_ua | sip_mask_registrar | sip_mask_timer
Record-Route = sip_mask_ua | sip_mask_proxy
Expires = sip_mask_registrar | sip_mask_events
@@ -802,10 +802,10 @@ issize_t sip_name_addr_e(char b[], isize_t bsiz,
}
/** Parse @To or @From headers */
issize_t sip_addr_d(su_home_t *home,
sip_header_t *h,
char *s,
isize_t slen)
static issize_t sip_addr_d(su_home_t *home,
sip_header_t *h,
char *s,
isize_t slen)
{
sip_addr_t *a = (sip_addr_t *)h;
char const *comment = NULL;
+158 -2
View File
@@ -202,6 +202,163 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
NULL, 1, ei->ei_url, ei->ei_params, NULL);
}
/* ====================================================================== */
/**@SIP_HEADER sip_alert_info Alert-Info Header
*
* When present in an INVITE request, the Alert-Info header field
* specifies an alternative ring tone to the UAS. When present in a 180
* (Ringing) response, the Alert-Info header field specifies an
* alternative ringback tone to the UAC. A typical usage is for a proxy
* to insert this header field to provide a distinctive ring feature.
*
* @code
* Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
* alert-param = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
* @endcode
*
* The parsed Alert-Info header is stored in #sip_alert_info_t structure.
*
* @NEW_1_12_7
*/
/**@ingroup sip_alert_info
* @typedef struct sip_alert_info_s sip_alert_info_t;
*
* The structure #sip_alert_info_t contains representation of an
* @AlertInfo header.
*
* The #sip_alert_info_t is defined as follows:
* @code
* struct sip_alert_info_s
* {
* sip_common_t ai_common[1]; // Common fragment info
* sip_alert_info_t *ai_next; // Link to next @AlertInfo
* url_t ai_url[1]; // URI to alert info
* msg_param_t const *ai_params; // List of optional parameters
* };
* @endcode
*
* @NEW_1_12_7
*/
msg_hclass_t sip_alert_info_class[] =
SIP_HEADER_CLASS(alert_info, "Alert-Info", "",
ai_params, append, info);
issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
return sip_info_d(home, h, s, slen);
}
issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
{
sip_alert_info_t *ai = (sip_alert_info_t *)h;
return sip_name_addr_e(b, bsiz, f, NULL, 1, ai->ai_url, ai->ai_params, NULL);
}
/* ====================================================================== */
/**@SIP_HEADER sip_reply_to Reply-To Header
*
* The @b Reply-To header field contains a logical return URI that may be
* different from the @From header field. For example, the URI MAY be used to
* return missed calls or unestablished sessions. If the user wished to
* remain anonymous, the header field SHOULD either be omitted from the
* request or populated in such a way that does not reveal any private
* information. Its syntax is defined in @RFC3261 as follows:
*
* @code
* Reply-To = "Reply-To" HCOLON rplyto-spec
* rplyto-spec = ( name-addr / addr-spec )
* *( SEMI rplyto-param )
* rplyto-param = generic-param
* @endcode
*
* The parsed Reply-To header is stored in #sip_reply_to_t structure.
*/
/**@ingroup sip_reply_to
* @typedef struct msg_list_s sip_reply_to_t;
*
* The structure #sip_reply_to_t contains representation of SIP
* @ReplyTo header.
*
* The #sip_reply_to_t is defined as follows:
* @code
* struct sip_reply_to_s
* {
* sip_common_t rplyto_common[1]; // Common fragment info
* sip_error_t *rplyto_next; // Dummy link to next header
* char const *rplyto_display; // Display name
* url_t rplyto_url[1]; // Return URI
* msg_param_t const *rplyto_params; // List of optional parameters
* };
* @endcode
*/
static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset);
static char *sip_reply_to_dup_one(sip_header_t *dst,
sip_header_t const *src,
char *b,
isize_t xtra);
#define sip_reply_to_update NULL
msg_hclass_t sip_reply_to_class[] =
SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to);
issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
return sip_name_addr_d(home,
&s,
&rplyto->rplyto_display,
rplyto->rplyto_url,
&rplyto->rplyto_params,
NULL);
}
issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
{
sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
return sip_name_addr_e(b, bsiz,
flags,
rplyto->rplyto_display,
MSG_IS_CANONIC(flags), rplyto->rplyto_url,
rplyto->rplyto_params,
NULL);
}
static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset)
{
sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h;
MSG_PARAMS_SIZE(offset, rplyto->rplyto_params);
offset += MSG_STRING_SIZE(rplyto->rplyto_display);
offset += url_xtra(rplyto->rplyto_url);
return offset;
}
/**@internal Duplicate one sip_reply_to_t object. */
static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
char *b, isize_t xtra)
{
sip_reply_to_t *rplyto = (sip_reply_to_t *)dst;
sip_reply_to_t const *o = (sip_reply_to_t *)src;
char *end = b + xtra;
b = msg_params_dup(&rplyto->rplyto_params, o->rplyto_params, b, xtra);
MSG_STRING_DUP(b, rplyto->rplyto_display, o->rplyto_display);
URL_DUP(b, end, rplyto->rplyto_url, o->rplyto_url);
assert(b <= end);
return b;
}
/* ====================================================================== */
@@ -231,7 +388,7 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
* msg_common_t k_common[1]; // Common fragment info
* msg_list_t *k_next; // Link to next header
* msg_param_t *k_items; // List of call ids
* } sip_allow_events_t;
* } sip_in_reply_to_t;
* @endcode
*/
@@ -249,7 +406,6 @@ issize_t sip_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
return msg_list_e(b, bsiz, h, f);
}
/* ====================================================================== */
/**@SIP_HEADER sip_organization Organization Header
@@ -9,6 +9,8 @@
#### EXTRA HEADER LIST STARTS HERE ####
refer_sub @NEW_1_12_5 /**< Refer-Sub header */
alert_info @NEW_1_12_7 /**< Alert-Info header */
reply_to @NEW_1_12_7 /**< Reply-To header */
#### EXPERIMENTAL HEADER LIST STARTS HERE ####
@@ -66,6 +66,33 @@ struct sip_refer_sub_s
msg_param_t const *rs_params; /**< List of extension parameters */
};
typedef struct sip_alert_info_s sip_alert_info_t;
/**@ingroup sip_alert_info
* @brief Structure for @AlertInfo header.
*/
struct sip_alert_info_s
{
sip_common_t ai_common[1]; /**< Common fragment info */
sip_alert_info_t *ai_next; /**< Link to next @AlertInfo */
url_t ai_url[1]; /**< URI to alert info */
msg_param_t const *ai_params; /**< List of optional parameters */
};
typedef struct sip_reply_to_s sip_reply_to_t;
/**@ingroup sip_reply_to
* @brief Structure for @ReplyTo header.
*/
struct sip_reply_to_s
{
sip_common_t rplyto_common[1]; /**< Common fragment info */
sip_error_t *rplyto_next; /**< Dummy link to next header */
char const *rplyto_display; /**< Display name */
url_t rplyto_url[1]; /**< Return URI */
msg_param_t const *rplyto_params; /**< List of optional parameters */
};
typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t;
/**@ingroup sip_suppress_body_if_match
@@ -91,6 +118,8 @@ struct sip_suppress_notify_if_match_s
};
/** Defined as 1 if the @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" is supported */
#define SIP_HAVE_#XXXXXX# 1
SOFIA_END_DECLS
@@ -354,21 +354,109 @@ SOFIAPUBFUN int sip_is_allowed(sip_allow_t const *allow,
(sip_method_unknown < (method) && (method) < 32 && \
(allow) && ((allow)->k_bitmap & (1 << (method))) != 0)
/* ---------------------------------------------------------------------------
* Bitmasks for header classifications
/**
* Bitmasks for header classifications.
*
* If parsing of a particular header fails, the error bits in #msg_t are
* updated. The error bits can be obtained via msg_extract_errors() after
* parsing. The header-specific bits are stored along with the
* @ref msg_hclass_t "header class" in the #msg_href_t structure, found in
* the parser tables of the #msg_mclass_t object.
*
* @sa NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(),
* #msg_mclass_t, struct #msg_mclass_s, msg_mclass_clone(),
* msg_mclass_insert_with_mask(),
* #msg_href_t, struct #msg_href_s, msg_mclass_insert().
*/
enum {
sip_mask_request = 1,
sip_mask_response = 2,
sip_mask_ua = 4,
sip_mask_proxy = 8,
sip_mask_registrar = 16,
sip_mask_100rel = 32,
sip_mask_events = 64,
sip_mask_timer = 128,
sip_mask_privacy = 256,
sip_mask_pref = 512,
sip_mask_publish = 1024
enum sip_bad_mask {
/** Bit marking essential headers in a request message.
*
* @ref sip_request \"request line\"", @From, @To, @CSeq, @CallID,
* @ContentLength, @Via
*/
sip_mask_request = (1 << 0),
/** Bit marking essential headers in a response message.
*
* @ref sip_status \"status line\"", @From, @To, @CSeq, @CallID,
* @ContentLength, @Via
*/
sip_mask_response = (1 << 1),
/** Bit marking essential headers for User-Agent.
*
* @ContentType, @ContentDisposition, @ContentEncoding, @Supported,
* @Contact, @Require, and @RecordRoute.
*/
sip_mask_ua = (1 << 2),
/** Bit marking essential headers for proxy server.
*
* @Route, @MaxForwards, @ProxyRequire, @ProxyAuthorization, @Supported,
* @Contact, and @RecordRoute.
*/
sip_mask_proxy = (1 << 3),
/** Bit marking essential headers for registrar server.
*
* @MinExpires, @Authorization, @Path, @Supported, @Contact, @Require, and
* @Expires.
*
*/
sip_mask_registrar = (1 << 4),
/** Bit marking essential headers for 100rel extension.
*
* @RAck and @RSeq.
*
* @sa @RFC3262.
*/
sip_mask_100rel = (1 << 5),
/** Bit marking essential headers for SIP events.
*
* @Event, @Expires, and @SubscriptionState.
*
* @sa @RFC3265.
*/
sip_mask_events = (1 << 6),
/** Bit marking essential headers for session timer extension.
*
* @SessionExpires, and @MinSE.
*
* @RFC4028
*/
sip_mask_timer = (1 << 7),
/** Bit marking essential headers for privacy extension.
*
* @Privacy.
*
* @sa @RFC3323
*/
sip_mask_privacy = (1 << 8),
/** Bit marking essential headers for caller preference extension.
*
* @RequestDisposition, @AcceptContact, and @RejectContact.
*
* @sa @RFC3841.
*/
sip_mask_pref = (1 << 9),
/** Bit marking essential headers for PUBLISH servers and clients.
*
* @SIPEtag, and @SIPIfMatch.
*
* @sa @RFC3903.
*/
sip_mask_publish = (1 << 10)
/* NOTE:
* When adding bits, please update nta_agent_create() and
* NTATAG_BAD_RESP_MASK()/NTATAG_BAD_REQ_MASK() documentation.
*/
};
/* ------------------------------------------------------------------------- */
@@ -694,6 +694,40 @@ int test_basic(void)
su_free(home, ci0);
}
{
sip_alert_info_t *ai, *ai0;
TEST_1(ai = sip_alert_info_make(home, "<http://www.nokia.com/ringtone.mp3>;x-format=mp3"));
TEST_1(ai0 = sip_alert_info_dup(home, ai));
TEST(msg_header_remove_param(ai->ai_common, "x-format"), 1);
TEST(msg_header_remove_param(ai0->ai_common, "x-format"), 1);
su_free(home, ai);
su_free(home, ai0);
}
{
sip_reply_to_t *rplyto, *rplyto0;
TEST_1(rplyto = sip_reply_to_make(home, "sip:joe@bar"));
TEST_1(msg_header_add_param(home, (msg_common_t *)rplyto, "x-extra=extra") == 0);
while (rplyto->rplyto_params && rplyto->rplyto_params[0])
msg_header_remove_param(rplyto->rplyto_common, rplyto->rplyto_params[0]);
su_free(home, rplyto);
TEST_1(!sip_reply_to_make(home, (void *)"sip:joe@[baa"));
TEST_1(rplyto = sip_reply_to_make(home, (void *)"sip:joe@bar"));
su_free(home, rplyto);
TEST_1(rplyto = sip_reply_to_make(home, (void *)"Joe <sip:joe@bar;user=ip>;x-extra=extra"));
TEST_1(rplyto0 = sip_reply_to_dup(home, rplyto));
su_free(home, rplyto);
su_free(home, rplyto0);
}
su_home_check(home);
su_home_zap(home);
@@ -891,6 +925,8 @@ static int test_encoding(void)
"Warning: 399 presence.bar:5060 \"Unimplemented filter\"\r\n"
"RSeq: 421414\r\n"
"Refer-To: <sip:hsdf@cdwf.xcfw.com?Subject=test&Organization=Bar>\r\n"
"Alert-Info: <http://alert.example.org/test.mp3>\r\n"
"Reply-To: Bob <sip:bob@example.com>\r\n"
"WWW-Authenticate: Digest realm=\"foo\"\r\n"
"Proxy-Authenticate: Digest realm=\"foo\"\r\n"
"Security-Server: tls;q=0.2\r\n"
@@ -1555,6 +1591,10 @@ static int parser_test(void)
TEST_SIZE(sip_error_info_class->hc_params,
offsetof(sip_error_info_t, ei_params));
TEST_SIZE(sip_alert_info_class->hc_params,
offsetof(sip_alert_info_t, ai_params));
TEST_SIZE(sip_reply_to_class->hc_params,
offsetof(sip_reply_to_t, rplyto_params));
TEST_SIZE(sip_warning_class->hc_params, 0);
TEST_SIZE(sip_mime_version_class->hc_params, 0);
+1 -1
View File
@@ -122,7 +122,7 @@ static int soa_set_sdp(soa_session_t *ss,
* The SOA_DEBUG environment variable is used to determine the default
* debug logging level. The normal level is 3.
*
* @sa <su_debug.h>, su_log_global, SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, su_log_global, SOFIA_DEBUG
*/
extern char const SOA_DEBUG[];
@@ -41,6 +41,8 @@
#endif
#include <sofia-sip/soa.h>
#include <sofia-sip/soa_tag.h>
#include <sofia-sip/su_tag_class.h>
#include <sofia-sip/sdp_tag.h>
@@ -1423,6 +1423,10 @@ int main(int argc, char *argv[])
usage(1);
}
#if HAVE_OPEN_C
tstflags |= tst_verbatim;
#endif
if (o_attach) {
char line[10];
printf("%s: pid %u\n", name, getpid());
@@ -1462,5 +1466,9 @@ int main(int argc, char *argv[])
su_deinit();
#if HAVE_OPEN_C
sleep(5);
#endif
return retval;
}
@@ -17,11 +17,9 @@ INCLUDES = -I$(srcdir)/../url -I../url \
noinst_LTLIBRARIES = libsresolv.la
check_PROGRAMS = test_sresolv
check_PROGRAMS = torture_sresolv test_sresolv
TESTS = run_test_sresolv
TESTS_ENVIRONMENT = $(SHELL)
TESTS = torture_sresolv run_test_sresolv
CLEANFILES = resolv.conf error.conf named.conf.tmp \
.test_sresolv.api.conf.?????? \
@@ -60,7 +60,7 @@ typedef union sres_record sres_record_t;
enum {
/** Cache cleanup interval in seconds. */
SRES_CACHE_TIMER_INTERVAL = 30,
SRES_CACHE_TIMER_INTERVAL = 5,
#define SRES_CACHE_TIMER_INTERVAL (SRES_CACHE_TIMER_INTERVAL)
};
@@ -557,7 +557,7 @@ static int m_get_domain(char *d, int n, sres_message_t *m, uint16_t offset);
* The SRESOLV_DEBUG environment variable is used to determine the debug
* logging level for @b sresolv module. The default level is 3.
*
* @sa <su_debug.h>, sresolv_log, SOFIA_DEBUG
* @sa <sofia-sip/su_debug.h>, sresolv_log, SOFIA_DEBUG
*/
#ifdef DOXYGEN
extern char const SRESOLV_DEBUG[]; /* dummy declaration for Doxygen */
@@ -65,6 +65,7 @@ typedef unsigned _int32 uint32_t;
#include <sofia-sip/su_alloc.h>
#include <sofia-sip/su_strlst.h>
#include <sofia-sip/htable.h>
#include <sofia-sip/heap.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -86,19 +87,28 @@ typedef struct sres_rr_hash_entry_s sres_rr_hash_entry_t;
HTABLE_DECLARE_WITH(sres_htable, ht, sres_rr_hash_entry_t, unsigned, size_t);
typedef HEAP_TYPE sres_heap_t;
HEAP_DECLARE(static inline, sres_heap_t, sres_heap_, sres_rr_hash_entry_t *);
struct sres_rr_hash_entry_s {
unsigned int rr_hash_key;
time_t rr_received;
sres_record_t *rr;
size_t rr_heap_index;
time_t rr_expires;
unsigned int rr_hash_key;
};
#define SRES_HENTRY_HASH(e) ((e)->rr_hash_key)
/* ---------------------------------------------------------------------- */
/* Heap */
struct sres_cache
{
su_home_t cache_home[1];
time_t cache_cleaned;
sres_htable_t cache_hash[1];
sres_heap_t cache_heap;
};
#define sr_refcount sr_record->r_refcount
@@ -109,7 +119,6 @@ struct sres_cache
#define sr_class sr_record->r_class
#define sr_ttl sr_record->r_ttl
#define sr_rdlen sr_record->r_rdlen
#define sr_rdata sr_generic->g_data
/* ---------------------------------------------------------------------- */
/* Internal prototypes */
@@ -126,7 +135,6 @@ static unsigned sres_hash_key(const char *string);
HTABLE_PROTOS_WITH(sres_htable, ht, sres_rr_hash_entry_t, unsigned, size_t);
/* ---------------------------------------------------------------------- */
/* Public functions */
@@ -140,7 +148,8 @@ sres_cache_t *sres_cache_new(int n)
if (cache) {
su_home_threadsafe(cache->cache_home);
if (sres_htable_resize(cache->cache_home, cache->cache_hash, n) < 0)
if (sres_htable_resize(cache->cache_home, cache->cache_hash, n) < 0 ||
sres_heap_resize(cache->cache_home, &cache->cache_heap, 0) < 0)
su_home_unref(cache->cache_home), cache = NULL;
}
@@ -197,7 +206,7 @@ int sres_cache_get(sres_cache_t *cache,
rr = (*rr_iter)->rr;
if (rr != NULL &&
(uint32_t)(now - (*rr_iter)->rr_received) <= rr->sr_ttl &&
now <= (*rr_iter)->rr_expires &&
(type == sres_qtype_any || rr->sr_type == type) &&
rr->sr_name != NULL &&
strcasecmp(rr->sr_name, domain) == 0)
@@ -224,7 +233,7 @@ int sres_cache_get(sres_cache_t *cache,
rr = (*rr_iter)->rr;
if (rr != NULL &&
(uint32_t)(now - (*rr_iter)->rr_received) <= rr->sr_ttl &&
now <= (*rr_iter)->rr_expires &&
(type == sres_qtype_any || rr->sr_type == type) &&
rr->sr_name != NULL &&
strcasecmp(rr->sr_name, domain) == 0) {
@@ -278,13 +287,13 @@ sres_cache_alloc_record(sres_cache_t *cache,
}
/** Free a record that has not been stored. */
void sres_cache_free_record(sres_cache_t *cache, void *rr)
void sres_cache_free_record(sres_cache_t *cache, void *_sr)
{
sres_record_t *sr = rr;
sres_record_t *sr = _sr;
if (sr) {
assert(sr->sr_refcount == 0);
su_free(cache->cache_home, rr);
su_free(cache->cache_home, sr);
}
}
@@ -306,6 +315,12 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
if (sres_htable_is_full(cache->cache_hash))
sres_htable_resize(cache->cache_home, cache->cache_hash, 0);
if (sres_heap_is_full(cache->cache_heap))
if (sres_heap_resize(cache->cache_home, &cache->cache_heap, 0) < 0) {
UNLOCK(cache);
return;
}
for (rr_iter = sres_htable_hash(cache->cache_hash, hash);
(rr_hash_entry = *rr_iter);
rr_iter = sres_htable_next(cache->cache_hash, rr_iter)) {
@@ -327,10 +342,12 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
continue;
/* There was an old entry in the cache.. Zap it, replace this with it */
rr_hash_entry->rr_received = now;
sres_heap_remove(cache->cache_heap, rr_hash_entry->rr_heap_index);
rr_hash_entry->rr_expires = now + rr->sr_ttl;
rr_hash_entry->rr = rr;
rr->sr_refcount++;
sres_heap_add(cache->cache_heap, rr_hash_entry);
_sres_cache_free_one(cache, or);
UNLOCK(cache);
@@ -339,16 +356,19 @@ sres_cache_store(sres_cache_t *cache, sres_record_t *rr, time_t now)
}
rr_hash_entry = su_zalloc(cache->cache_home, sizeof(*rr_hash_entry));
if (rr_hash_entry) {
rr_hash_entry->rr_hash_key = hash;
rr_hash_entry->rr_received = now;
rr_hash_entry->rr_expires = now + rr->sr_ttl;
rr_hash_entry->rr = rr;
rr->sr_refcount++;
sres_heap_add(cache->cache_heap, rr_hash_entry);
cache->cache_hash->ht_used++;
*rr_iter = rr_hash_entry;
}
*rr_iter = rr_hash_entry;
UNLOCK(cache);
}
@@ -417,6 +437,7 @@ sres_hash_key(const char *string)
return result;
}
/** Remove entries from cache. */
void sres_cache_clean(sres_cache_t *cache, time_t now)
{
size_t i;
@@ -424,27 +445,56 @@ void sres_cache_clean(sres_cache_t *cache, time_t now)
if (now < cache->cache_cleaned + SRES_CACHE_TIMER_INTERVAL)
return;
if (!LOCK(cache))
return;
/* Clean cache from old entries */
cache->cache_cleaned = now;
for (i = 0; i < cache->cache_hash->ht_size; i++) {
sres_rr_hash_entry_t *e;
for (;;) {
if (!LOCK(cache))
return;
cache->cache_cleaned = now;
for (i = 0; i < 100; i++) {
sres_rr_hash_entry_t *e = sres_heap_get(cache->cache_heap, 1);
if (e == NULL || e->rr_expires >= now) {
UNLOCK(cache);
return;
}
while ((e = cache->cache_hash->ht_table[i]) != NULL) {
if ((uint32_t)(now - e->rr_received) <= e->rr->sr_ttl)
break;
sres_heap_remove(cache->cache_heap, 1);
sres_htable_remove(cache->cache_hash, e);
_sres_cache_free_one(cache, e->rr);
su_free(cache->cache_home, e);
}
}
UNLOCK(cache);
UNLOCK(cache);
}
}
HTABLE_BODIES_WITH(sres_htable, ht, sres_rr_hash_entry_t, SRES_HENTRY_HASH,
unsigned, size_t);
static inline
int sres_heap_earlier_entry(sres_rr_hash_entry_t const *a,
sres_rr_hash_entry_t const *b)
{
return a->rr_expires < b->rr_expires;
}
static inline
void sres_heap_set_entry(sres_rr_hash_entry_t **heap,
size_t index,
sres_rr_hash_entry_t *entry)
{
entry->rr_heap_index = index;
heap[index] = entry;
}
HEAP_BODIES(static inline,
sres_heap_t,
sres_heap_,
sres_rr_hash_entry_t *,
sres_heap_earlier_entry,
sres_heap_set_entry,
su_realloc,
NULL);
@@ -1152,7 +1152,7 @@ int test_cache(sres_context_t *ctx)
#if HAVE_SIN6
sres_query(res, test_answer_multi, ctx,
sres_type_aaaa, "mgw02.example.com");
sres_type_aaaa, "mgw02.example.com");
inet_pton(AF_INET6,
"3ffe:1200:3012:c000:0a08:20ff:fe7d:e7ac",
@@ -1161,7 +1161,7 @@ int test_cache(sres_context_t *ctx)
sin6.sin6_family = AF_INET6;
query = sres_query_sockaddr(res, test_answer_multi, ctx,
sres_qtype_any, (struct sockaddr *)&sin6);
sres_qtype_any, (struct sockaddr *)&sin6);
TEST_1(query != NULL);
#endif
@@ -1770,97 +1770,6 @@ int test_net(sres_context_t *ctx)
END();
}
/* Test API function argument validation */
static
int test_api_errors(sres_context_t *noctx)
{
sres_context_t ctx[1];
sres_resolver_t *res;
int s, fd;
int sockets[20];
struct sockaddr sa[1] = {{ 0 }};
char *template = NULL;
FILE *f;
BEGIN();
memset(ctx, 0, sizeof ctx);
template = su_sprintf(ctx->home, ".test_sresolv_api.conf.XXXXXX");
TEST_1(template);
TEST_1(res = sres_resolver_new(NULL));
TEST(su_home_threadsafe((su_home_t *)res), 0);
TEST_VOID(sres_resolver_unref(res));
#ifndef _WIN32
fd = mkstemp(template); TEST_1(fd != -1);
#else
fd = open(template, O_WRONLY); TEST_1(fd != -1);
#endif
f = fdopen(fd, "w"); TEST_1(f);
fprintf(f, "domain example.com\n");
fclose(f);
/* Test also LOCALDOMAIN handling */
putenv("LOCALDOMAIN=localdomain");
TEST_1(res = sres_resolver_new(template));
TEST(su_home_threadsafe((su_home_t *)res), 0);
unlink(template);
s = sockets[0];
TEST_P(sres_resolver_ref(NULL), NULL);
TEST(errno, EFAULT);
sres_resolver_unref(NULL);
TEST_P(sres_resolver_set_userdata(NULL, NULL), NULL);
TEST(errno, EFAULT);
TEST_P(sres_resolver_get_userdata(NULL), NULL);
TEST_P(sres_resolver_get_userdata(res), NULL);
TEST_P(sres_resolver_set_userdata(res, sa), NULL);
TEST_P(sres_resolver_get_userdata(res), sa);
TEST_P(sres_resolver_set_userdata(res, NULL), sa);
TEST_P(sres_resolver_get_userdata(res), NULL);
errno = 0;
TEST_P(sres_query(NULL, test_answer, ctx, sres_type_a, "com"), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_query(res, test_answer, ctx, sres_type_a, NULL), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_query_sockaddr(res, test_answer, ctx,
sres_qtype_any, sa), NULL);
TEST(errno, EAFNOSUPPORT); errno = 0;
TEST_P(sres_cached_answers(NULL, sres_qtype_any, "example.com"), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_cached_answers(res, sres_qtype_any, NULL), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_cached_answers(res, sres_qtype_any, name2048), NULL);
TEST(errno, ENAMETOOLONG); errno = 0;
TEST_P(sres_cached_answers_sockaddr(res, sres_qtype_any, sa), NULL);
TEST(errno, EAFNOSUPPORT); errno = 0;
sres_free_answer(res, NULL);
sres_free_answers(res, NULL);
sres_sort_answers(res, NULL);
sres_free_answer(NULL, NULL);
sres_free_answers(NULL, NULL);
sres_sort_answers(NULL, NULL);
sres_resolver_unref(res);
END();
}
static
int test_init(sres_context_t *ctx, char const *conf_file)
{
@@ -2087,8 +1996,6 @@ int main(int argc, char **argv)
}
}
error |= test_api_errors(ctx);
return error;
}
@@ -0,0 +1,440 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2006 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@internal
*
* @CFILE torture_sresolv.c Torture tests for Sofia resolver.
*
* @author Mikko Haataja
* @author Pekka Pessi <Pekka.Pessi@nokia.com>.
*/
#include "config.h"
#if HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#else
#if defined(_WIN32)
typedef unsigned _int8 uint8_t;
typedef unsigned _int16 uint16_t;
typedef unsigned _int32 uint32_t;
#endif
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
#if HAVE_NETINET_IN_H
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#if HAVE_WINSOCK2_H
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <sofia-resolv/sres.h>
#include <sofia-resolv/sres_async.h>
#include <sofia-resolv/sres_record.h>
#include <sofia-resolv/sres_cache.h>
#include <sofia-sip/su_alloc.h>
#include <time.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#if HAVE_ALARM
#include <signal.h>
#endif
#define TSTFLAGS tstflags
int tstflags, o_timing;
#include <sofia-sip/tstdef.h>
char const name[] = "torture_sresolv";
struct sres_context_s
{
su_home_t home[1];
};
static void test_answer(sres_context_t *ctx,
sres_query_t *q,
sres_record_t **answer)
{
}
static char name2048[2049] =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
"gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg"
"hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh";
/* Test API function argument validation */
static
int test_api_errors(void)
{
sres_context_t ctx[1];
sres_resolver_t *res;
int s, fd;
int sockets[20];
struct sockaddr sa[1] = {{ 0 }};
char *template = NULL;
FILE *f;
BEGIN();
memset(ctx, 0, sizeof ctx);
template = su_sprintf(ctx->home, ".torture_sresolv_api.conf.XXXXXX");
TEST_1(template);
TEST_1(res = sres_resolver_new(NULL));
TEST(su_home_threadsafe((su_home_t *)res), 0);
TEST_VOID(sres_resolver_unref(res));
#ifndef _WIN32
fd = mkstemp(template); TEST_1(fd != -1);
#else
fd = open(template, O_WRONLY); TEST_1(fd != -1);
#endif
f = fdopen(fd, "w"); TEST_1(f);
fprintf(f, "domain example.com\n");
fclose(f);
/* Test also LOCALDOMAIN handling */
putenv("LOCALDOMAIN=localdomain");
TEST_1(res = sres_resolver_new(template));
TEST(su_home_threadsafe((su_home_t *)res), 0);
unlink(template);
s = sockets[0];
TEST_P(sres_resolver_ref(NULL), NULL);
TEST(errno, EFAULT);
sres_resolver_unref(NULL);
TEST_P(sres_resolver_set_userdata(NULL, NULL), NULL);
TEST(errno, EFAULT);
TEST_P(sres_resolver_get_userdata(NULL), NULL);
TEST_P(sres_resolver_get_userdata(res), NULL);
TEST_P(sres_resolver_set_userdata(res, sa), NULL);
TEST_P(sres_resolver_get_userdata(res), sa);
TEST_P(sres_resolver_set_userdata(res, NULL), sa);
TEST_P(sres_resolver_get_userdata(res), NULL);
errno = 0;
TEST_P(sres_query(NULL, test_answer, ctx, sres_type_a, "com"), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_query(res, test_answer, ctx, sres_type_a, NULL), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_query_sockaddr(res, test_answer, ctx,
sres_qtype_any, sa), NULL);
TEST(errno, EAFNOSUPPORT); errno = 0;
TEST_P(sres_cached_answers(NULL, sres_qtype_any, "example.com"), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_cached_answers(res, sres_qtype_any, NULL), NULL);
TEST(errno, EFAULT); errno = 0;
TEST_P(sres_cached_answers(res, sres_qtype_any, name2048), NULL);
TEST(errno, ENAMETOOLONG); errno = 0;
TEST_P(sres_cached_answers_sockaddr(res, sres_qtype_any, sa), NULL);
TEST(errno, EAFNOSUPPORT); errno = 0;
sres_free_answer(res, NULL);
sres_free_answers(res, NULL);
sres_sort_answers(res, NULL);
sres_free_answer(NULL, NULL);
sres_free_answers(NULL, NULL);
sres_sort_answers(NULL, NULL);
sres_resolver_unref(res);
END();
}
extern void sres_cache_clean(sres_cache_t *cache, time_t now);
static
int test_cache(void)
{
BEGIN();
sres_a_record_t *a, a0[1], **all;
char host[128];
sres_cache_t *cache;
time_t now, base;
struct timespec t0, t1, t2;
size_t i, N, N1 = 1000, N3 = 1000000;
time(&base);
cache = sres_cache_new(N1);
TEST_1(cache);
all = calloc(N3, sizeof *all); if (!all) perror("calloc"), exit(2);
memset(a0, 0, sizeof a0);
a0->a_record->r_refcount = 1;
a0->a_record->r_size = sizeof *a;
a0->a_record->r_type = sres_type_a;
a0->a_record->r_class = sres_class_in;
a0->a_record->r_ttl = 3600;
a0->a_record->r_rdlen = sizeof a->a_addr;
a0->a_record->r_parsed = 1;
for (i = 0, N = N3; i < N; i++) {
a0->a_record->r_name = host;
snprintf(host, sizeof host, "%u.example.com.", (unsigned)i);
a = (sres_a_record_t *)
sres_cache_alloc_record(cache, (sres_record_t *)a0, 0);
if (!a)
perror("sres_cache_alloc_record"), exit(2);
all[i] = a, a->a_record->r_refcount = 1;
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
for (i = 0, N = N3; i < N; i++) {
now = base + (3600 * i + N / 2) / N;
a->a_record->r_ttl = 60 + (i * 60) % 3600;
sres_cache_store(cache, (sres_record_t *)all[i], now);
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
if (o_timing) {
t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
if (t1.tv_nsec < t0.tv_nsec)
t2.tv_sec--, t2.tv_nsec += 1000000000;
printf("sres_cache: stored %u entries: %lu.%09lu sec\n",
N, t2.tv_sec, t2.tv_nsec);
}
for (i = 0, N; i < N; i++)
TEST(all[i]->a_record->r_refcount, 2);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
for (now = base; now <= base + 3660; now += 30)
sres_cache_clean(cache, now + 3600);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
if (o_timing) {
t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
if (t1.tv_nsec < t0.tv_nsec)
t2.tv_sec--, t2.tv_nsec += 1000000000;
printf("sres_cache: cleaned %u entries: %lu.%09lu sec\n",
N, t2.tv_sec, t2.tv_nsec);
}
for (i = 0, N; i < N; i++)
TEST(all[i]->a_record->r_refcount, 1);
base += 24 * 3600;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
for (i = 0, N; i < N; i++) {
now = base + (3600 * i + N / 2) / N;
a->a_record->r_ttl = 60 + (i * 60) % 3600;
sres_cache_store(cache, (sres_record_t *)all[i], now);
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
if (o_timing) {
t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
if (t1.tv_nsec < t0.tv_nsec)
t2.tv_sec--, t2.tv_nsec += 1000000000;
printf("sres_cache: stored %u entries: %lu.%09lu sec\n",
N, t2.tv_sec, t2.tv_nsec);
}
for (i = 0, N; i < N; i++)
TEST(all[i]->a_record->r_refcount, 2);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t0);
for (now = base; now <= base + 3660; now += 1)
sres_cache_clean(cache, now + 3600);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t1);
if (o_timing) {
t2.tv_sec = t1.tv_sec - t0.tv_sec, t2.tv_nsec = t1.tv_nsec - t0.tv_nsec;
if (t1.tv_nsec < t0.tv_nsec)
t2.tv_sec--, t2.tv_nsec += 1000000000;
printf("sres_cache: cleaned %u entries: %lu.%09lu sec\n",
N, t2.tv_sec, t2.tv_nsec);
}
for (i = 0, N; i < N; i++) {
TEST(all[i]->a_record->r_refcount, 1);
sres_cache_free_one(cache, (sres_record_t *)all[i]);
}
sres_cache_unref(cache);
free(all);
END();
}
#if HAVE_ALARM
static RETSIGTYPE sig_alarm(int s)
{
fprintf(stderr, "%s: FAIL! test timeout!\n", name);
exit(1);
}
#endif
void usage(int exitcode)
{
fprintf(stderr,
"usage: %s OPTIONS [-]\n"
"\twhere OPTIONS are\n"
"\t -v be verbose\n"
"\t -a abort on error\n"
"\t -t show timing\n"
"\r --no-alarm disable timeout\n"
"\t -llevel set debugging level\n",
name);
exit(exitcode);
}
#include <sofia-sip/su_log.h>
extern su_log_t sresolv_log[];
int main(int argc, char **argv)
{
int i;
int error = 0;
int o_alarm = 1;
for (i = 1; argv[i]; i++) {
if (argv[i][0] != '-')
break;
else if (strcmp(argv[i], "-") == 0) {
i++; break;
}
else if (strcmp(argv[i], "-v") == 0)
tstflags |= tst_verbatim;
else if (strcmp(argv[i], "-a") == 0)
tstflags |= tst_abort;
else if (strcmp(argv[i], "-t") == 0)
o_timing = 1;
else if (strcmp(argv[i], "--no-alarm") == 0) {
o_alarm = 0;
}
else if (strncmp(argv[i], "-l", 2) == 0) {
int level = 3;
char *rest = NULL;
if (argv[i][2])
level = strtol(argv[i] + 2, &rest, 10);
else if (argv[i + 1])
level = strtol(argv[i + 1], &rest, 10), i++;
else
level = 3, rest = "";
if (rest == NULL || *rest)
usage(1);
su_log_set_level(sresolv_log, level);
}
else
usage(1);
}
#if HAVE_ALARM
if (o_alarm) {
alarm(60);
signal(SIGALRM, sig_alarm);
}
#endif
if (!(TSTFLAGS & tst_verbatim)) {
su_log_soft_set_level(sresolv_log, 0);
}
error |= test_api_errors();
error |= test_cache();
return error;
}
@@ -36,6 +36,7 @@
#define TAG_NAMESPACE "stun"
#include <sofia-sip/su_tag_class.h>
#include <sofia-sip/stun_tag.h>
/**@def STUNTAG_ANY()
*
@@ -159,7 +160,7 @@ tag_typedef_t stuntag_register_events = BOOLTAG_TYPEDEF(register_events);
* int (stun_action_t)
*
* @par Values
* See types for stun_action_t in stun.h
* See types for stun_action_t in <sofia-sip/stun.h>
*
* Corresponding tag taking reference parameter is STUNTAG_ACTION_REF()
*/
@@ -8,6 +8,7 @@ INPUT = @srcdir@/su.docs @srcdir@/sofia-sip sofia-sip @srcdir@ .
TAGFILES += ../docs/msg.doxytags=../msg
TAGFILES += ../docs/sip.doxytags=../sip
TAGFILES += ../docs/utils.doxytags=../utils
TAGFILES += ../docs/docs.doxytags=..
GENERATE_TAGFILE = ../docs/su.doxytags
+16 -18
View File
@@ -16,23 +16,9 @@ noinst_LTLIBRARIES = libsu.la
bin_PROGRAMS = addrinfo localinfo
if COREFOUNDATION
OSXSOURCES = \
su_osx_runloop.c
OSXHEADERS = \
sofia-sip/su_osx_runloop.h
OSXPROGS = \
torture_su_root_osx test_su_osx
OSXTESTS = \
torture_su_root_osx run_test_su_osx
else
OSXSOURCES =
OSXHEADERS =
endif
check_PROGRAMS = torture_su torture_su_port \
torture_su_alloc torture_su_time torture_su_tag \
test_htable torture_rbtree \
test_htable torture_rbtree torture_heap \
test_memmem torture_su_bm \
torture_su_root torture_su_timer \
test_su su_proxy test_poll $(OSXPROGS)
@@ -42,7 +28,7 @@ check_PROGRAMS = torture_su torture_su_port \
TESTS = torture_su torture_su_port \
torture_su_alloc torture_su_time torture_su_tag \
test_htable torture_rbtree \
test_htable torture_rbtree torture_heap \
test_memmem torture_su_bm \
torture_su_root torture_su_timer \
run_addrinfo run_localinfo run_test_su \
@@ -63,8 +49,8 @@ nobase_include_sofia_HEADERS = \
sofia-sip/su_tag_class.h sofia-sip/su_tagarg.h \
sofia-sip/su_tag_io.h sofia-sip/su_tag_inline.h \
sofia-sip/htable.h sofia-sip/htable2.h \
sofia-sip/rbtree.h sofia-sip/su_debug.h \
sofia-sip/su_log.h \
sofia-sip/rbtree.h sofia-sip/heap.h \
sofia-sip/su_debug.h sofia-sip/su_log.h \
sofia-sip/su_config.h sofia-sip/su_md5.h \
sofia-sip/su_uniqueid.h sofia-sip/su_bm.h \
sofia-sip/tstdef.h sofia-sip/su_os_nw.h \
@@ -122,3 +108,15 @@ AUTOMAKE_OPTIONS = foreign
# Sofia specific rules
include $(top_srcdir)/rules/sofia.am
# ----------------------------------------------------------------------
# OS X stuff
if COREFOUNDATION
OSXSOURCES = su_osx_runloop.c
OSXHEADERS = sofia-sip/su_osx_runloop.h
OSXPROGS = torture_su_root_osx test_su_osx
OSXTESTS = torture_su_root_osx run_test_su_osx
endif
EXTRA_DIST += su_osx_runloop.c sofia-sip/su_osx_runloop.h
@@ -0,0 +1,315 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef SOFIA_SIP_HEAP_H
/** Defined when <sofia-sip/heap.h> has been included. */
#define SOFIA_SIP_HEAP_H
/**@file sofia-sip/heap.h
*
* Heap template implemented with dynamic array.
*
* This file contain template macros implementing @a heap in C. The @a heap
* keeps its element in a known order and it can be used to implement, for
* example, a prioritye queue or an ordered queue.
*
* The ordering within the heap is defined as follows:
* - indexing starts from 1
* - for each element with index @a [i] in the heap there are two descendant
* elements with indices @a [2*i] and @a [2*i+1],
* - the heap guarantees that the descendant elements are never smaller than
* their parent element.
* Therefore it follows that there is no element smaller than element at
* index [1] in the rest of the heap.
*
* Adding and removing elements to the heap is an @a O(logN)
* operation.
*
* The heap array is resizeable, and it usually contain pointers to the
* actual entries. The template macros define two functions used to add and
* remove entries to the heap. The @a add() function takes the element to be
* added as its argument, the @a remove() function the index of the element
* to be removed. The template defines also a predicate used to check if the
* heap is full, and a function used to resize the heap.
*
* The heap user must define four primitives:
* - less than comparison
* - array setter
* - heap array allocator
* - empty element
*
* Please note that in order to remove an entry in the heap, the application
* must know its index in the heap array.
*
* The heap struct is declared with macro HEAP_DECLARE(). The prototypes for
* heap functions are instantiated with macro HEAP_PROTOS(). The
* implementation is instantiated with macro HEAP_BODIES().
*
* Example code can be found from <su/torture_heap.c> and
* <sresolv/sres_cache.c>.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>.
* @NEW_1_12_7.
*/
/** Minimum size of heap */
#define HEAP_MIN_SIZE 31
/** Declare heap structure type.
*
* The macro #HEAP_TYPE contains declaration of the heap structure.
*
* @showinitializer
*/
#define HEAP_TYPE struct { void *private; }
/** Prototypes for heap.
*
* The macro HEAP_PROTOS() expands to the prototypes of heap functions:
* - prefix ## resize(argument, in_out_heap, size)
* - prefix ## free(argument, in_heap)
* - prefix ## is_full(heap)
* - prefix ## size(heap)
* - prefix ## used(heap)
* - prefix ## add(heap, entry)
* - prefix ## remove(heap, index)
* - prefix ## get(heap, index)
*
* @param scope scope of functions
* @param heaptype type of heap
* @param prefix function prefix
* @param type type of entries
*
* The declared functions will have scope @a scope (for example, @c static
* or @c static inline). The declared function names will have prefix @a
* prefix. The heap structure has type @a heaptype. The heap element type is
* @a entrytype.
*
* @showinitializer
*/
#define HEAP_DECLARE(scope, heaptype, prefix, type) \
scope int prefix##resize(void *, heaptype *, size_t); \
scope int prefix##free(void *, heaptype *); \
scope int prefix##is_full(heaptype const); \
scope size_t prefix##size(heaptype const); \
scope size_t prefix##used(heaptype const); \
scope int prefix##add(heaptype, type); \
scope type prefix##remove(heaptype, size_t); \
scope type prefix##get(heaptype, size_t)
/**Heap implementation.
*
* The macro HEAP_BODIES() expands to the bodies of heap functions:
* - prefix ## resize(argument, heap, size)
* - prefix ## free(argument, in_heap)
* - prefix ## is_full(heap)
* - prefix ## size(heap)
* - prefix ## used(heap)
* - prefix ## add(heap, entry)
* - prefix ## remove(heap, index)
* - prefix ## get(heap, index)
*
* @param scope scope of functions
* @param prefix function prefix for heap
* @param type type of heaped elements
* @param less function or macro comparing two entries
* @param set function or macro assigning entry to array
* @param alloc function allocating or freeing memory
* @param null empty element (returned when index is invalid)
*
* Functions have scope @a scope, e.g., @c static @c inline.
* The heap structure has type @a type.
* The function names start with @a prefix, the field names start
* with @a pr. The entry type is @a entrytype.
* The function (or macro) @a less compares two entries in heap. It gets two
* arguments and it returns true if its left argument is less than its right
* argument.
* The function (or macro) @a set stores an entry in heap array. It gets
* three arguments, first is heap array, second index to the array and third
* the element to store at the given index.
*
* The function (or macro) @a halloc re-allocates the heap array. It
* receives three arguments, first is the first @a argument given to @a
* resize(), second the pointer to existing heap and third is the number of
* bytes in the heap.
*/
#define HEAP_BODIES(scope, heaptype, prefix, type, less, set, alloc, null) \
scope int prefix##resize(void *realloc_arg, heaptype h[1], size_t new_size) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[2]; }; \
struct prefix##priv *_priv; \
size_t _offset = \
(offsetof(struct prefix##priv, _heap[1]) - 1) / sizeof (type); \
size_t _min_size = 32 - _offset; \
size_t _bytes; \
size_t _used = 0; \
\
_priv = *(void **)h; \
\
if (_priv) { \
if (new_size == 0) \
new_size = 2 * _priv->_size + _offset + 1; \
_used = _priv->_used; \
if (new_size < _used) \
new_size = _used; \
} \
\
if (new_size < _min_size) \
new_size = _min_size; \
\
_bytes = (_offset + 1 + new_size) * sizeof (type); \
\
(void)realloc_arg; /* avoid warning */ \
_priv = alloc(realloc_arg, *(struct prefix##priv **)h, _bytes); \
if (!_priv) \
return -1; \
\
*(struct prefix##priv **)h = _priv; \
_priv->_size = new_size; \
_priv->_used = _used; \
\
return 0; \
} \
\
/** Free heap. */ \
scope int prefix##free(void *realloc_arg, heaptype h[1]) \
{ \
(void)realloc_arg; \
*(void **)h = alloc(realloc_arg, *(void **)h, 0); \
return 0; \
} \
\
/** Check if heap is full */ \
scope int prefix##is_full(heaptype h) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
\
return _priv == NULL || _priv->_used >= _priv->_size; \
} \
\
/** Add an element to the heap */ \
scope int prefix##add(heaptype h, type e) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
type *heap = _priv->_heap - 1; \
size_t i, parent; \
\
if (_priv == NULL || _priv->_used >= _priv->_size) \
return -1; \
\
for (i = ++_priv->_used; i > 1; i = parent) { \
parent = i / 2; \
if (!less(e, heap[parent])) \
break; \
set(heap, i, heap[parent]); \
} \
\
set(heap, i, e); \
\
return 0; \
} \
\
/** Remove element from heap */ \
scope type prefix##remove(heaptype h, size_t index) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
type *heap = _priv->_heap - 1; \
type retval; \
type e; \
\
size_t top, left, right, move; \
\
move = _priv->_used; \
\
if (index - 1 >= _priv->_used) \
return (null); \
\
move = _priv->_used--; \
retval = heap[top = index]; \
\
for (;;) { \
left = 2 * top; \
right = 2 * top + 1; \
\
if (right >= move) \
break; \
if (less(heap[right], heap[left])) \
top = right; \
else \
top = left; \
set(heap, index, heap[top]); \
index = top; \
} \
\
if (index == move) \
return retval; \
\
e = heap[move]; \
for (; index > 1; index = top) { \
top = index / 2; \
if (!less(e, heap[top])) \
break; \
set(heap, index, heap[top]); \
} \
\
set(heap, index, e); \
\
return retval; \
} \
\
scope \
type prefix##get(heaptype h, size_t index) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
\
if (--index >= _priv->_used) \
return (null); \
\
return _priv->_heap[index]; \
} \
\
scope \
size_t prefix##size(heaptype const h) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
return _priv ? _priv->_size : 0; \
} \
\
scope \
size_t prefix##used(heaptype const h) \
{ \
struct prefix##priv { size_t _size, _used; type _heap[1];}; \
struct prefix##priv *_priv = *(void **)&h; \
return _priv ? _priv->_used : 0; \
} \
extern int const prefix##dummy_heap
#endif /** !defined(SOFIA_SIP_HEAP_H) */
@@ -1,7 +1,7 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
* Copyright (C) 2005,2006,2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
@@ -66,15 +66,14 @@
#if SU_HAVE_WINSOCK /* Windows includes */
# include <winsock2.h>
# include <ws2tcpip.h>
# if defined(IPPROTO_IPV6)
/* IPv6 defined in ws2tcpip.h */
# elif SU_HAVE_IN6
# include <tpipv6.h> /* From "IPv6 Tech Preview" */
# else
# error Winsock with IPv6 support required
# if SU_HAVE_IN6
# if defined(IPPROTO_IPV6)
/* case 1: IPv6 defined in winsock2.h/ws2tcpip.h */
# else
/* case 2: try to use "IPv6 Tech Preview" */
# include <tpipv6.h>
# endif
# endif
#endif
SOFIA_BEGIN_DECLS
@@ -95,6 +94,9 @@ enum {
/** Return code for an unsuccessful call */
su_failure = -1
};
#if SYMBIAN && !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL (0)
#endif
#elif SU_HAVE_WINSOCK
enum {
su_success = 0,
@@ -274,7 +276,9 @@ SOFIAPUBFUN int su_close(su_socket_t s);
/** Control socket. */
SOFIAPUBFUN int su_ioctl(su_socket_t s, int request, ...);
/** Checks if the @a errcode indicates that the socket call failed because
/**Check for in-progress error codes.
*
* Checks if the @a errcode indicates that the socket call failed because
* it would have blocked.
*
* Defined as macro with POSIX sockets.
@@ -36,7 +36,7 @@
*/
#ifndef SU_CONFIGURE_H
#include "sofia-sip/su_configure.h"
#include <sofia-sip/su_configure.h>
#endif
#if defined(__GNUC__)
@@ -1,7 +1,7 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
* Copyright (C) 2005,2006,2007 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
@@ -73,7 +73,7 @@ enum {
*/
typedef uint64_t su_ntp_t;
/** Represent NTP consttant */
/** Represent NTP constant */
#define SU_NTP_C(x) SU_U64_C(x)
#define SU_TIME_CMP(t1, t2) su_time_cmp(t1, t2)
@@ -81,6 +81,13 @@ typedef uint64_t su_ntp_t;
/** Seconds from 1.1.1900 to 1.1.1970. @NEW_1_12_4 */
#define SU_TIME_EPOCH 2208988800UL
typedef uint64_t su_nanotime_t;
#define SU_E9 (1000000000U)
SOFIAPUBFUN su_nanotime_t su_nanotime(su_nanotime_t *return_time);
SOFIAPUBFUN su_nanotime_t su_monotime(su_nanotime_t *return_time);
SOFIAPUBFUN su_time_t su_now(void);
SOFIAPUBFUN void su_time(su_time_t *tv);
SOFIAPUBFUN long su_time_cmp(su_time_t const t1, su_time_t const t2);
@@ -34,7 +34,7 @@
*/
#ifndef SU_CONFIG_H
#include "sofia-sip/su_config.h"
#include <sofia-sip/su_config.h>
#endif
#if SU_HAVE_STDINT
@@ -341,6 +341,12 @@ typedef void (*su_timer_f)(su_root_magic_t *magic,
su_timer_t *t,
su_timer_arg_t *arg);
#ifndef SU_TIMER_QUEUE_T
#define SU_TIMER_QUEUE_T su_timer_t *
#endif
typedef SU_TIMER_QUEUE_T su_timer_queue_t;
/* ---------------------------------------------------------------------- */
/* Tasks */
@@ -487,7 +493,7 @@ SOFIAPUBFUN int su_timer_reset(su_timer_t *);
SOFIAPUBFUN su_root_t *su_timer_root(su_timer_t const *);
SOFIAPUBFUN int su_timer_expire(su_timer_t ** const,
SOFIAPUBFUN int su_timer_expire(su_timer_queue_t * const,
su_duration_t *tout,
su_time_t now);
@@ -505,7 +511,7 @@ SOFIAPUBFUN int su_task_cmp(su_task_r const, su_task_r const);
SOFIAPUBFUN int su_task_is_running(su_task_r const);
SOFIAPUBFUN su_root_t *su_task_root(su_task_r const self);
SOFIAPUBFUN su_timer_t **su_task_timers(su_task_r const self);
SOFIAPUBFUN su_timer_queue_t *su_task_timers(su_task_r const self);
SOFIAPUBFUN int su_task_execute(su_task_r const task,
int (*function)(void *), void *arg,
+180 -8
View File
@@ -32,9 +32,13 @@
#include "config.h"
#include "sofia-sip/su.h"
#include "sofia-sip/su_log.h"
#include "sofia-sip/su_alloc.h"
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#include <sofia-sip/su.h>
#include <sofia-sip/su_log.h>
#include <sofia-sip/su_alloc.h>
#include <stdio.h>
#include <string.h>
@@ -53,38 +57,194 @@
int su_socket_close_on_exec = 0;
int su_socket_blocking = 0;
/** Create an endpoint for communication. */
#if HAVE_OPEN_C && HAVE_NET_IF_H
#include <net/if.h>
#endif
#if SU_HAVE_BSDSOCK && HAVE_OPEN_C
char su_global_ap_name[IFNAMSIZ];
extern int su_get_local_ip_addr(su_sockaddr_t *su);
#endif
/** Create a socket endpoint for communication.
*
* @param af addressing family
* @param socktype socket type
* @param proto protocol number specific to the addressing family
*
* The newly created socket is nonblocking unless global variable
* su_socket_blocking is set to true.
*
* Also, the newly created socket is closed on exec() if global variable
* su_socket_close_on_exec is set to true. Note that a multithreaded program
* can fork() and exec() before the close-on-exec flag is set.
*
* @return A valid socket descriptor or INVALID_SOCKET (-1) upon an error.
*/
su_socket_t su_socket(int af, int socktype, int proto)
{
#if HAVE_OPEN_C
struct ifconf ifc;
int numifs = 64;
char *buffer;
struct ifreq ifr;
int const su_xtra = 0;
#endif
su_socket_t s = socket(af, socktype, proto);
#if SU_HAVE_BSDSOCK
if (s != INVALID_SOCKET) {
#if SU_HAVE_BSDSOCK
if (su_socket_close_on_exec)
fcntl(s, F_SETFD, FD_CLOEXEC); /* Close on exec */
#endif
if (!su_socket_blocking) /* All sockets are born blocking */
su_setblocking(s, 0);
}
#if HAVE_OPEN_C
/* Use AP we have raised up */
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, (char const *) su_global_ap_name, IFNAMSIZ);
/* Assign socket to an already active access point (interface) */
ioctl(s, SIOCSIFNAME, &ifr);
ioctl(s, SIOCIFSTART, &ifr);
#endif
return s;
}
#if SU_HAVE_BSDSOCK
#if HAVE_OPEN_C
#include <errno.h>
su_sockaddr_t su_ap[1];
int ifindex;
void *aConnection;
extern void *su_localinfo_ap_set(su_sockaddr_t *su, int *index);
extern int su_localinfo_ap_deinit(void *aconn);
#define NUMIFS 64
int su_localinfo_ap_name_to_index(int ap_index)
{
struct ifconf ifc;
struct ifreq *ifr, *ifr_next;
int error = EFAULT;
char *buffer, buf[NUMIFS * sizeof(struct ifreq)];
su_socket_t s;
s= socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return -1;
ifc.ifc_len = NUMIFS * sizeof (struct ifreq);
memset(buf, 0, ifc.ifc_len);
ifc.ifc_buf = buf;
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
return error;
}
buffer = ifc.ifc_buf + ifc.ifc_len;
for (ifr = ifc.ifc_req;
(void *)ifr < (void *)buffer;
ifr = ifr_next) {
struct ifreq ifreq[1];
int scope, if_index, flags = 0, gni_flags = 0;
char *if_name;
su_sockaddr_t su2[1];
#if SA_LEN
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_addr))
ifr_next = (struct ifreq *)
(ifr->ifr_addr.sa_len + (char *)(&ifr->ifr_addr));
else
#else
ifr_next = ifr + 1;
#endif
if_name = ifr->ifr_name;
#if defined(SIOCGIFINDEX)
ifreq[0] = *ifr;
if (ioctl(s, SIOCGIFINDEX, ifreq) < 0) {
return -1;
}
#if HAVE_IFR_INDEX
if_index = ifreq->ifr_index;
#elif HAVE_IFR_IFINDEX
if_index = ifreq->ifr_ifindex;
#else
#error Unknown index field in struct ifreq
#endif
if (ap_index == if_index)
{
strncpy(su_global_ap_name, (const char *) if_name, sizeof(su_global_ap_name));
error = 0;
};
#else
#error su_localinfo() cannot map interface name to number
#endif
}
close(s);
return error;
}
#endif
#if SU_HAVE_BSDSOCK || DOCUMENTATION_ONLY
/** Initialize socket implementation.
*
* Before using any sofia-sip-ua functions, the application should call
* su_init() in order to initialize run-time environment including sockets.
* This function may prepare plugins if there are any.
*
* @par POSIX Implementation
* The su_init() initializes debugging logs and ignores the SIGPIPE signal.
*
* @par Windows Implementation
* The function su_init() initializes Winsock2 library on Windows.
*
* @par Symbian Implementation
* The function su_init() prompts user to select an access point (interface
* towards Internet) and uses the activated access point for the socket
* operations.
*/
int su_init(void)
{
#if HAVE_OPEN_C
char apname[60];
su_socket_t s;
#endif
su_home_threadsafe(NULL);
#if HAVE_SIGPIPE
signal(SIGPIPE, SIG_IGN); /* we want to get EPIPE instead */
#endif
#if HAVE_OPEN_C
/* This code takes care of enabling an access point (interface) */
aConnection = su_localinfo_ap_set(su_ap, &ifindex);
su_localinfo_ap_name_to_index(ifindex);
#endif
su_log_init(su_log_default);
su_log_init(su_log_global);
return 0;
}
/** Deinitialize socket implementation. */
void su_deinit(void)
{
#if HAVE_OPEN_C
su_localinfo_ap_deinit(aConnection);
#endif
}
/** Close an socket descriptor. */
@@ -133,7 +293,7 @@ void su_deinit(void)
WSACleanup();
}
/** Close an socket descriptor. */
/** Close a socket descriptor. */
int su_close(su_socket_t s)
{
return closesocket(s);
@@ -196,6 +356,14 @@ issize_t su_getmsgsize(su_socket_t s)
return -1;
return (issize_t)n;
}
#elif HAVE_OPEN_C
issize_t su_getmsgsize(su_socket_t s)
{
int n = -1;
if (su_ioctl(s, E32IONREAD, &n) == -1)
return -1;
return (issize_t)n;
}
#else
issize_t su_getmsgsize(su_socket_t s)
{
@@ -222,8 +390,9 @@ struct in_addr6 const *su_in6addr_loopback(void)
}
#endif
#if SU_HAVE_WINSOCK
#if SU_HAVE_WINSOCK || DOCUMENTATION_ONLY
/** Call send() with POSIX-compatible signature */
ssize_t su_send(su_socket_t s, void *buffer, size_t length, int flags)
{
if (length > INT_MAX)
@@ -231,6 +400,7 @@ ssize_t su_send(su_socket_t s, void *buffer, size_t length, int flags)
return (ssize_t)send(s, buffer, (int)length, flags);
}
/** Call sendto() with POSIX-compatible signature */
ssize_t su_sendto(su_socket_t s, void *buffer, size_t length, int flags,
su_sockaddr_t const *to, socklen_t tolen)
{
@@ -240,6 +410,7 @@ ssize_t su_sendto(su_socket_t s, void *buffer, size_t length, int flags,
&to->su_sa, (int) tolen);
}
/** Call recv() with POSIX-compatible signature */
ssize_t su_recv(su_socket_t s, void *buffer, size_t length, int flags)
{
if (length > INT_MAX)
@@ -248,6 +419,7 @@ ssize_t su_recv(su_socket_t s, void *buffer, size_t length, int flags)
return (ssize_t)recv(s, buffer, (int)length, flags);
}
/** Call recvfrom() with POSIX-compatible signature */
ssize_t su_recvfrom(su_socket_t s, void *buffer, size_t length, int flags,
su_sockaddr_t *from, socklen_t *fromlen)
{
File diff suppressed because it is too large Load Diff
@@ -47,6 +47,10 @@
#include <stdlib.h>
#include <ctype.h>
#ifndef EAI_NODATA
#define EAI_NODATA 7
#endif
/*
* "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
*
@@ -477,7 +477,7 @@ int su_base_port_remove_prepoll(su_port_t *self,
* Timers
*/
su_timer_t **su_base_port_timers(su_port_t *self)
su_timer_queue_t *su_base_port_timers(su_port_t *self)
{
return &self->sup_timers;
}
@@ -53,7 +53,7 @@ static void default_logger(void *stream, char const *fmt, va_list ap)
* The SOFIA_DEBUG environment variable is used to determine the default
* debug logging level. The normal level is 3.
*
* @sa <su_debug.h>, su_log_global
* @sa <sofia-sip/su_debug.h>, su_log_global
*/
extern char const SOFIA_DEBUG[];
@@ -45,7 +45,7 @@
* The SU_DEBUG environment variable is used to determine the debug logging
* level for @b su module. The default level is 3.
*
* @sa <su_debug.h>, su_log_global
* @sa <sofia-sip/su_debug.h>, su_log_global
*/
extern char const SU_DEBUG[];
+155 -64
View File
@@ -28,20 +28,21 @@
* Obtain list of local addresses.
*
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
* @author Martti Mela <Martti.Mela@nokia.com>
*
* @date Created: Wed Oct 4 14:09:29 EET 2000 ppessi
*/
#include "config.h"
#include "sofia-sip/su.h"
#include "sofia-sip/su_localinfo.h"
#include "su_module_debug.h"
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#include <sofia-sip/su.h>
#include <sofia-sip/su_localinfo.h>
#include "su_module_debug.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -409,9 +410,14 @@ int su_sockaddr_scope(su_sockaddr_t const *su, socklen_t sulen)
return 0;
}
#if HAVE_OPEN_C
extern int su_get_local_ip_addr(su_sockaddr_t *su);
#endif
#if USE_LOCALINFO0
#elif HAVE_IFCONF
#if __APPLE_CC__
/** Build a list of local IPv4 addresses and append it to *rresult. */
static
int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
@@ -434,6 +440,10 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
char *buffer;
struct ifreq *ifr, *ifr_next;
su_sockaddr_t *sa;
socklen_t salen = sizeof(*sa);
int scope = 0, gni_flags = 0;
s = su_socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",
@@ -441,70 +451,105 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
return ELI_SYSTEM;
}
#if defined(__APPLE_CC__)
{
su_sockaddr_t *sa;
socklen_t salen = sizeof(*sa);
int scope = 0, gni_flags = 0;
li = calloc(1, sizeof(su_localinfo_t));
sa = calloc(1, sizeof(su_sockaddr_t));
li = calloc(1, sizeof(su_localinfo_t));
sa = calloc(1, sizeof(su_sockaddr_t));
error = getsockname(s, (struct sockaddr *) sa, &salen);
if (error < 0 && errno == SOCKET_ERROR) {
SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
su_strerror(su_errno())));
}
error = bind(s, (struct sockaddr *) sa, salen);
if (error < 0) {
SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
su_strerror(su_errno())));
goto err;
}
su_close(s);
scope = li_scope4(sa->su_sin.sin_addr.s_addr);
if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
gni_flags = NI_NUMERICHOST;
if (su_xtra) {
/* Map IPv4 address to IPv6 address */
memset(sa, 0, sizeof(*sa));
sa->su_family = AF_INET6;
((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff);
}
li->li_family = sa->su_family;
li->li_scope = scope;
li->li_index = 0;
li->li_addrlen = su_sockaddr_size(sa);
li->li_addr = sa;
if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
goto err;
if (canonname) {
if (strchr(canonname, ':') ||
strspn(canonname, "0123456789.") == strlen(canonname))
li->li_flags |= LI_NUMERIC;
}
else
li->li_flags = 0;
li->li_canonname = canonname;
canonname = NULL;
*rresult = li;
return 0;
error = getsockname(s, (struct sockaddr *) sa, &salen);
if (error < 0 && errno == SOCKET_ERROR) {
SU_DEBUG_1(("%s: getsockname() failed: %s\n", __func__,
su_strerror(su_errno())));
}
error = bind(s, (struct sockaddr *) sa, salen);
if (error < 0) {
SU_DEBUG_1(("%s: bind() failed: %s\n", __func__,
su_strerror(su_errno())));
goto err;
}
su_close(s);
scope = li_scope4(sa->su_sin.sin_addr.s_addr);
if (scope == LI_SCOPE_HOST || scope == LI_SCOPE_LINK)
gni_flags = NI_NUMERICHOST;
if (su_xtra) {
/* Map IPv4 address to IPv6 address */
memset(sa, 0, sizeof(*sa));
sa->su_family = AF_INET6;
((int32_t*)&sa->su_sin6.sin6_addr)[3] = sa->su_sin.sin_addr.s_addr;
((int32_t*)&sa->su_sin6.sin6_addr)[2] = htonl(0xffff);
}
li->li_family = sa->su_family;
li->li_scope = scope;
li->li_index = 0;
li->li_addrlen = su_sockaddr_size(sa);
li->li_addr = sa;
if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
goto err;
if (canonname) {
if (strchr(canonname, ':') ||
strspn(canonname, "0123456789.") == strlen(canonname))
li->li_flags |= LI_NUMERIC;
}
else
li->li_flags = 0;
li->li_canonname = canonname;
canonname = NULL;
*rresult = li;
return 0;
err:
if (canonname) free(canonname);
if (li_first) free(li_first);
su_freelocalinfo(tbf);
su_close(s);
return error;
}
#else /* !__APPLE_CC__ */
/** Build a list of local IPv4 addresses and append it to *rresult. */
static
int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
{
su_localinfo_t *tbf = NULL, **lli = &tbf;
su_localinfo_t *li = NULL, *li_first = NULL;
su_sockaddr_t *su;
int error = ELI_NOADDRESS;
char *canonname = NULL;
su_socket_t s;
#if SU_HAVE_IN6
int su_xtra = (hints->li_flags & LI_V4MAPPED) ? sizeof(*su) : 0;
#else
int const su_xtra = 0;
#endif
struct ifconf ifc;
int numifs;
char *buffer;
struct ifreq *ifr, *ifr_next;
#if HAVE_OPEN_C
su_sockaddr_t *sa;
socklen_t salen = sizeof(*sa);
#endif
s = su_socket(AF_INET, SOCK_DGRAM, 0);
if (s == -1) {
SU_DEBUG_1(("su_localinfo: su_socket failed: %s\n",
su_strerror(su_errno())));
return ELI_SYSTEM;
}
# if HAVE_IFNUM
/* Get the list of known IP address from the kernel */
@@ -539,16 +584,25 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
error = ELI_MEMORY;
goto err;
}
li_first = (su_localinfo_t *)buffer;
memset(li_first, 0, sizeof(su_localinfo_t) + su_xtra);
ifc.ifc_buf = buffer + sizeof(su_localinfo_t) + su_xtra;
#if HAVE_OPEN_C
if (ioctl(s, SIOCGIFACTIVECONF, (char *)&ifc) < 0) {
SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",
su_strerror(su_errno())));
error = ELI_SYSTEM;
goto err;
}
#else
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
SU_DEBUG_1(("su_localinfo: SIOCGIFCONF failed: %s\n",
su_strerror(su_errno())));
error = ELI_SYSTEM;
goto err;
}
#endif
buffer = ifc.ifc_buf + ifc.ifc_len;
@@ -594,6 +648,42 @@ int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
SU_DEBUG_9(("su_localinfo: if %s with index %d\n", if_name, if_index));
#if HAVE_OPEN_C
su_close(s);
li = calloc(1, sizeof(su_localinfo_t));
sa = calloc(1, sizeof(su_sockaddr_t));
if (su_get_local_ip_addr(sa) < 0)
goto err;
li->li_family = sa->su_family;
li->li_scope = LI_SCOPE_GLOBAL /* scope */;
li->li_index = if_index;
li->li_addrlen = su_sockaddr_size(sa);
li->li_addr = sa;
if ((error = li_name(hints, gni_flags, sa, &canonname)) < 0)
goto err;
if (canonname) {
if (strchr(canonname, ':') ||
strspn(canonname, "0123456789.") == strlen(canonname))
li->li_flags |= LI_NUMERIC;
}
else
li->li_flags = 0;
li->li_canonname = canonname;
canonname = NULL;
*rresult = li;
return 0;
#endif
#if defined(SIOCGIFFLAGS)
ifreq[0] = *ifr;
if (ioctl(s, SIOCGIFFLAGS, ifreq) < 0) {
@@ -703,6 +793,7 @@ err:
return error;
}
#endif /* __APPLE_CC__ */
#else
static
int localinfo4(su_localinfo_t const *hints, su_localinfo_t **rresult)
@@ -246,6 +246,10 @@ void su_log_soft_set_level(su_log_t *log, unsigned level)
} else {
log->log_level = level;
log->log_init = 2;
if (explicitly_initialized == not_initialized)
explicitly_initialized = getenv("SHOW_DEBUG_LEVELS");
if (explicitly_initialized)
su_llog(log, 0, "%s: soft set log to level %u\n",
log->log_name, log->log_level);
@@ -0,0 +1,147 @@
/*
* This file is part of the Sofia-SIP package
*
* Copyright (C) 2005 Nokia Corporation.
*
* Contact: Pekka Pessi <pekka.pessi@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
/**@ingroup su_open_c_localinfo.cpp
*
* @CFILE su_open_c_localinfo.cpp
* Functionality for choosing an access point for sockets on Symbian.
*
* @author Martti Mela <Martti.Mela@nokia.com>
* @date Created: Fri May 18 14:31:41 2007 mela
*
*/
#include "config.h"
#include <unistd.h>
#include <in_sock.h>
#include <es_sock.h>
#include <e32base.h>
#include <s32mem.h>
#include <s32strm.h>
#include <commdbconnpref.h>
#include <sofia-sip/su.h>
su_sockaddr_t sa_global[1];
/* Copy IP address for the sockaddr structure.
*
* @param su pointer to allocated su_sockaddr_t structure
*
* @return 0 if successful.
*/
extern "C" int su_get_local_ip_addr(su_sockaddr_t *su)
{
su->su_sin.sin_addr.s_addr = sa_global->su_sin.sin_addr.s_addr;
su->su_family = sa_global->su_family;
su->su_len = sa_global->su_len;
return 0;
}
/* Set up the access point for the stack. Code adapted from Forum Nokia,
* http://wiki.forum.nokia.com/index.php/LocalDeviceIpAddress.
*
* @param su su_sockaddr_t structure
* @param ifindex pointer to interface index
*
* @return Connection object
*/
extern "C" void *su_localinfo_ap_set(su_sockaddr_t *su, int *ifindex)
{
TCommDbConnPref iPref;
RSocketServ aSocketServ;
RSocket sock;
/* Get the IAP id of the underlying interface of this RConnection */
TUint32 iapId;
iPref.SetDirection(ECommDbConnectionDirectionOutgoing);
iPref.SetDialogPreference(ECommDbDialogPrefPrompt);
iPref.SetBearerSet(KCommDbBearerUnknown /*PSD*/);
aSocketServ = RSocketServ();
aSocketServ.Connect();
RConnection *aConnection = new RConnection();
aConnection->Open(aSocketServ);
aConnection->Start(iPref);
User::LeaveIfError(sock.Open(aSocketServ, KAfInet, KSockStream,
KProtocolInetTcp));
User::LeaveIfError(aConnection->GetIntSetting(_L("IAP\\Id"), iapId));
/* Get IP information from the socket */
TSoInetInterfaceInfo ifinfo;
TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
TSoInetIfQuery ifquery;
TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
/* To find out which interfaces are using our current IAP, we
* must enumerate and go through all of them and make a query
* by name for each. */
User::LeaveIfError(sock.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl));
while(sock.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
ifquery.iName = ifinfo.iName;
TInt err = sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
/* IAP ID is index 1 of iZone */
if(err == KErrNone && ifquery.iZone[1] == iapId) {
/* We have found an interface using the IAP we are interested in. */
if(ifinfo.iAddress.Address() > 0) {
/* found a IPv4 address */
su->su_sin.sin_addr.s_addr = htonl(ifinfo.iAddress.Address());
sa_global->su_sin.sin_addr.s_addr = su->su_sin.sin_addr.s_addr;
sa_global->su_family = su->su_family = AF_INET;
sa_global->su_len = su->su_len = 28;
*ifindex = iapId;
return (void *) aConnection;
}
}
else if(err != KErrNone)
break;
}
sock.Close();
}
/* Deinitialize the access point in use.
*
* @param aconn Pointer to connection object
*
* @return 0 if successful.
*/
extern "C" int su_localinfo_ap_deinit(void *aconn)
{
RConnection *aConnection = (RConnection *) aconn;
aConnection->Stop();
aConnection->Close();
delete aConnection;
return 0;
}
+2 -2
View File
@@ -123,7 +123,7 @@ typedef struct su_port_vtable {
int (*su_port_remove_prepoll)(su_port_t *port,
su_root_t *root);
su_timer_t **(*su_port_timers)(su_port_t *port);
su_timer_queue_t *(*su_port_timers)(su_port_t *port);
int (*su_port_multishot)(su_port_t *port, int multishot);
@@ -443,7 +443,7 @@ typedef struct su_base_port_s {
su_msg_t *sup_head, **sup_tail;
/* Timer list */
su_timer_t *sup_timers;
su_timer_queue_t sup_timers;
unsigned sup_running; /**< In su_root_run() loop? */
} su_base_port_t;
@@ -459,8 +459,10 @@ int su_pthread_port_execute(su_task_r const task,
struct su_pthread_port_execute frame = {
{ PTHREAD_MUTEX_INITIALIZER },
{ _ENeedsNormalInit, NULL },
function, arg, 0
NULL, NULL, 0
};
frame.function = function;
frame.arg = arg;
#else
struct su_pthread_port_execute frame = {
{ PTHREAD_MUTEX_INITIALIZER },
+2 -2
View File
@@ -313,7 +313,7 @@ int su_task_detach(su_task_r self)
* @return A timer list of the task. If there are no timers, it returns
* NULL.
*/
su_timer_t **su_task_timers(su_task_r const task)
su_timer_queue_t *su_task_timers(su_task_r const task)
{
return task ? su_port_timers(task->sut_port) : NULL;
}
@@ -901,7 +901,7 @@ int su_msg_report(su_msg_r msg,
* @retval -1 otherwise.
*/
int su_msg_reply(su_msg_r reply, su_msg_r const msg,
int su_msg_reply(su_msg_r reply, su_msg_cr msg,
su_msg_f wakeup, isize_t size)
{
su_msg_r msg0;
@@ -66,7 +66,7 @@ unsigned longlong strtoull(const char *, char **, int);
*
* Object-oriented tag routines for Sofia utility library.
*
* The <su_tag.h> defines a interface to object-oriented tag list routines.
* The <sofia-sip/su_tag.h> defines a interface to object-oriented tag list routines.
* A tag list is a linear list (array) of tag items, tagi_t structures,
* terminated by a TAG_END() item. Each tag item has a label, tag, (@c
* t_tag) and a value (@c t_value). The tag is a pointer (tag_type_t) to a
@@ -112,7 +112,7 @@ unsigned longlong strtoull(const char *, char **, int);
* - TAG_NEXT() - contains a pointer to the next tag list.
*
* The tag type structures are declared as tag_typedef_t. They can be
* defined by the macros found in <su_tag_class.h>. See nta_tag.c or
* defined by the macros found in <sofia-sip/su_tag_class.h>. See nta_tag.c or
* su_tag_test.c for an example.
*
*/
+29 -19
View File
@@ -61,7 +61,7 @@
* OS-independent timing functions and types for the @b su library.
*
* The @b su library provides three different time formats with different
* ranges and epochs in the file @b su_time.h:
* ranges and epochs in <sofia-sip/su_time.h>:
*
* - #su_time_t, second and microsecond as 32-bit values since 1900,
* - #su_duration_t, milliseconds between two times, and
@@ -209,6 +209,8 @@ const su_t64_t su_res64 = (su_t64_t)1000000UL;
(su_res64 * (su_t64_t)(tv).tv_sec + (su_t64_t)(tv).tv_usec)
#define SU_DUR_TO_T64(d) (1000 * (int64_t)(d))
#define E9 (1000000000)
/** Get NTP timestamp.
*
* The function su_ntp_now() returns the current NTP timestamp. NTP
@@ -219,22 +221,36 @@ const su_t64_t su_res64 = (su_t64_t)1000000UL;
*/
su_ntp_t su_ntp_now(void)
{
su_time_t t;
uint32_t sec, usec;
su_nanotime_t now;
su_time(&t);
su_nanotime(&now);
sec = t.tv_sec;
usec = t.tv_usec;
if (sizeof(long) == sizeof(now)) {
return ((now / E9) << 32) | ((((now % E9) << 32) + E9/2) / E9);
}
else {
su_nanotime_t usec;
int nsec;
unsigned rem;
/*
* Multiply usec by 4294.967296 (ie. 2**32 / 1E6)
*
* Utilize fact that 4294.967296 == 4295 - 511 / 15625
*/
usec = 4295 * usec - (511 * usec + 7812) / 15625;
usec = now / 1000;
nsec = now % 1000;
/*
* Multiply usec by 4294.967296 (ie. 2**32 / 1E6)
*
* Utilize fact that 4294.967296 == 4295 - 511 / 15625
*/
now = 4295 * usec - 511 * usec / 15625;
rem = (511U * usec) % 15625U;
return ((su_ntp_t)sec << 32) + (su_ntp_t)usec;
/* Multiply nsec by 4.294967296 */
nsec = 4295 * 125 * nsec - (511 * nsec) / 125;
nsec -= 8 * rem; /* usec rounding */
nsec = (nsec + (nsec < 0 ? -62499 : +62499)) / 125000;
return now + nsec;
}
}
/** Get NTP seconds.
@@ -263,7 +279,6 @@ uint32_t su_ntp_hi(su_ntp_t ntp)
return (uint32_t) (ntp >> 32) & 0xffffffffLU;
}
su_ntp_t su_ntp_hilo(uint32_t hi, uint32_t lo)
{
return ((((su_ntp_t)hi) << 32)) | lo;
@@ -464,8 +479,3 @@ uint64_t su_nanocounter(void)
}
#endif /* WIN32 */

Some files were not shown because too many files have changed in this diff Show More