mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-04 19:31:56 +00:00
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:
+14
-2
@@ -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 19 and 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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[];
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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[];
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 },
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user