Sync to current darcs tree:
Mon Sep 17 14:50:04 EDT 2007 Pekka.Pessi@nokia.com * sofia-sip/sip_util.h: updated documentation Mon Sep 17 14:50:18 EDT 2007 Pekka.Pessi@nokia.com * sofia-sip/tport_tag.h: updated documentation Mon Sep 17 14:50:28 EDT 2007 Pekka.Pessi@nokia.com * soa_tag.c: updated documentation Wed Sep 19 12:50:01 EDT 2007 Pekka.Pessi@nokia.com * msg: updated documentation Wed Sep 19 13:29:50 EDT 2007 Pekka.Pessi@nokia.com * url: updated documentation Wed Sep 19 13:32:14 EDT 2007 Pekka.Pessi@nokia.com * nth: updated documentation Wed Sep 19 13:32:27 EDT 2007 Pekka.Pessi@nokia.com * nea: updated documentation Wed Sep 19 13:33:36 EDT 2007 Pekka.Pessi@nokia.com * http: updated documentation Wed Sep 19 13:36:58 EDT 2007 Pekka.Pessi@nokia.com * bnf: updated documentation Wed Sep 19 13:38:58 EDT 2007 Pekka.Pessi@nokia.com * nua: updated nua_stack_init_handle() prototype Wed Sep 19 18:45:56 EDT 2007 Pekka.Pessi@nokia.com * sip: added sip_name_addr_xtra(), sip_name_addr_dup() Wed Sep 19 19:00:19 EDT 2007 Pekka.Pessi@nokia.com * sip_basic.c: cleaned old crud Thu Sep 20 13:34:04 EDT 2007 Pekka.Pessi@nokia.com * iptsec: updated documentation Thu Sep 20 13:36:22 EDT 2007 Pekka.Pessi@nokia.com * tport: updated documentation Thu Sep 20 13:36:56 EDT 2007 Pekka.Pessi@nokia.com * su: updated documentation Removed internal files from doxygen-generated documentation. Thu Sep 20 13:38:29 EDT 2007 Pekka.Pessi@nokia.com * soa: fixed documentation Thu Sep 20 13:39:56 EDT 2007 Pekka.Pessi@nokia.com * sdp: updated documentation Thu Sep 20 13:40:16 EDT 2007 Pekka.Pessi@nokia.com * ipt: updated documentation Thu Sep 20 14:24:20 EDT 2007 Pekka.Pessi@nokia.com * nta: updated documentation Thu Sep 20 14:41:04 EDT 2007 Pekka.Pessi@nokia.com * nua: updated documentation Updated tag documentation. Moved doxygen doc entries from sofia-sip/nua_tag.h to nua_tag.c. Removed internal datatypes and files from the generated documents. Wed Sep 19 13:34:20 EDT 2007 Pekka.Pessi@nokia.com * docs: updated the generation of documentation. Updated links to header files. Thu Sep 20 08:45:32 EDT 2007 Pekka.Pessi@nokia.com * sip/Makefile.am: added tags to <sofia-sip/sip_extra.h> Added check for extra tags in torture_sip.c. Thu Sep 20 14:45:22 EDT 2007 Pekka.Pessi@nokia.com * stun: updated documentation Wed Jul 4 18:55:20 EDT 2007 Pekka.Pessi@nokia.com * torture_heap.c: added tests for ##sort() and su_smoothsort() Wed Jul 4 18:56:59 EDT 2007 Pekka.Pessi@nokia.com * Makefile.am: added smoothsort.c Fri Jul 13 12:38:44 EDT 2007 Pekka.Pessi@nokia.com * sofia-sip/heap.h: heap_remove() now set()s index to 0 on removed item Mon Jul 23 11:14:22 EDT 2007 Pekka.Pessi@nokia.com * sofia-sip/heap.h: fixed bug in heap##remove() If left kid was in heap but right was not, left kid was ignored. Wed Jul 4 18:51:08 EDT 2007 Pekka.Pessi@nokia.com * smoothsort.c: added Wed Jul 4 18:51:34 EDT 2007 Pekka.Pessi@nokia.com * heap.h: using su_smoothsort() Fri Jul 6 10:20:27 EDT 2007 Pekka.Pessi@nokia.com * smoothsort.c: added Wed Sep 19 17:40:30 EDT 2007 Pekka.Pessi@nokia.com * msg_parser.awk: generate two parser tables, default and extended Wed Sep 19 18:39:45 EDT 2007 Pekka.Pessi@nokia.com * msg_parser.awk: just generate list of extra headers Allocate extended parser dynamically. Wed Sep 19 18:59:59 EDT 2007 Pekka.Pessi@nokia.com * sip: added Remote-Party-ID, P-Asserted-Identity, P-Preferred-Identity Added functions sip_update_default_mclass() and sip_extend_mclass() for handling the extended parser. Note that Reply-To and Alert-Info are only available with the extended parser. Wed Sep 19 19:05:44 EDT 2007 Pekka.Pessi@nokia.com * RELEASE: updated Thu Sep 20 13:38:59 EDT 2007 Pekka.Pessi@nokia.com * sip: updated documentation Thu Sep 20 14:17:28 EDT 2007 Pekka.Pessi@nokia.com * docs/conformance.docs: updated Mon Oct 1 10:11:14 EDT 2007 Pekka.Pessi@nokia.com * tport_tag.c: re-enabled tptag_trusted Thu Oct 4 09:21:07 EDT 2007 Pekka.Pessi@nokia.com * su_osx_runloop.c: moved virtual function table after struct definition Preparing for su_port_vtable_t refactoring. Thu Oct 4 10:22:03 EDT 2007 Pekka.Pessi@nokia.com * su_source.c: refactored initialization/deinitialization Fri Oct 5 04:58:18 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * sip_extra.c: fixed prototypes with isize_t Fri Oct 5 04:58:45 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * test_nta_api.c: removed warnings about signedness Fri Oct 5 04:59:02 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * test_nua_params.c: removed warnings about constness Fri Oct 5 07:20:26 EDT 2007 Pekka Pessi <first.lastname@nokia.com> * su_port.h, su_root.c: cleaned argument checking The su_root_*() and su_port_*() functions now check their arguments once and do not assert() with NULL arguments. The sur_task->sut_port should always be valid while su_root_t is alive. Fri Oct 5 07:22:09 EDT 2007 Pekka Pessi <first.lastname@nokia.com> * su: added su_root_obtain(), su_root_release() and su_root_has_thread() When root is created with su_root_create() or cloned with su_clone_start(), the resulting root is obtained by the calling or created thread, respectively. The root can be released with su_root_release() and another thread can obtain it. The function su_root_has_thread() can be used to check if a thread has obtained or released the root. Implementation upgraded the su_port_own_thread() method as su_port_thread(). Fri Oct 5 07:28:10 EDT 2007 Pekka Pessi <first.lastname@nokia.com> * su_port.h: removed su_port_threadsafe() and su_port_yield() methods su_port_wait_events() replaces su_port_yield(). Fri Oct 5 13:26:04 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * msg_parser.awk: not extending header structure unless needed. Removed gawk-ish /* comments */. Fri Oct 5 14:32:25 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * run_test_su: removed GNUisms Fri Oct 5 14:32:47 EDT 2007 Pekka Pessi <Pekka.Pessi@nokia.com> * Makefile.am: removed implicit check target test_urlmap Fri Oct 5 14:22:32 EDT 2007 Pekka Pessi <first.lastname@nokia.com> * torture_sresolv.c: use CLOCK_REALTIME if no CLOCK_PROCESS_CPUTIME_ID available Casting timespec tv_sec to unsigned long. Fri Oct * nua_s added handling nua_prack() Thanks to Fabio Margarido for the patch. Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com * test_nua: added test for sf.net bug #1803686 Mon Oct 8 08:15:23 EDT 2007 Pekka.Pessi@nokia.com * RELEASE: updated. Mon Oct 8 09:30:36 EDT 2007 Pekka.Pessi@nokia.com * nua_stack: added handling nua_prack() Thanks to Fabio Margarido for the patch. Mon Oct 8 10:24:35 EDT 2007 Pekka.Pessi@nokia.com * test_nua: added test for sf.net bug #1803686 Mon Oct 8 10:26:31 EDT 2007 Pekka.Pessi@nokia.com * nua: added test for nua_prack() (sf.net bug #1804248) Avoid sending nua_i_state after nua_prack() if no SDP O/A is happening, too. Mon Oct 8 10:32:04 EDT 2007 Mikhail Zabaluev <mikhail.zabaluev@nokia.com> * su_source.c: don t leak the wait arrays Mon Oct 8 10:37:11 EDT 2007 Pekka.Pessi@nokia.com * RELEASE: updated Wed Oct 10 11:55:21 EDT 2007 Pekka.Pessi@nokia.com * sip_parser.c: silenced warning about extra const in sip_extend_mclass() Wed Oct 10 11:57:08 EDT 2007 Pekka.Pessi@nokia.com * nta_tag.c: updated tag documentation Wed Oct 10 13:16:40 EDT 2007 Pekka.Pessi@nokia.com * nua: fix logging crash if outbound used with application contact Silenced warnings. Wed Oct 10 13:30:45 EDT 2007 Pekka.Pessi@nokia.com * msg_parser.awk: removed extra "const" Wed Oct 10 13:31:45 EDT 2007 Pekka.Pessi@nokia.com * Makefile.am's: fixed distclean of documentation git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@5840 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
24ff890bbb
commit
5e81b98eba
|
@ -4,42 +4,73 @@ Release notes for current version of Sofia-SIP
|
|||
|
||||
Changes since last release
|
||||
--------------------------
|
||||
|
||||
<changes since last written in freshmeat.net "Changes:" style;
|
||||
and in less than 10 lines, 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...
|
||||
The stacksupports specifying the outbound proxy by a set of Route
|
||||
headers as recommended by RFC3261. It also supports CR-LF-based keepalives
|
||||
on TCP connections.
|
||||
|
||||
Bugs in call state machines, URI and SDP handling has been fixed.
|
||||
|
||||
|
||||
API/ABI changes and versioning
|
||||
------------------------------
|
||||
|
||||
<see previous release notes at
|
||||
http://sofia-sip.sourceforge.net/relnotes/ for examples ;
|
||||
- should include all changes to public headers, and
|
||||
other important information to developers;
|
||||
- and should be updated _continuously_! />
|
||||
|
||||
New features in API are marked with Doxytag macro @VERSION_1_12_7.
|
||||
New features in API are marked with Doxytag macro @VERSION_1_12_7 or
|
||||
@NEW_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
|
||||
work against an older library. The ABI has been tested with the nua module
|
||||
unit test (test_nua) built against original 1.12.0 release.
|
||||
|
||||
libsofia-sip-ua/nua:
|
||||
- Added tag NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR()
|
||||
|
||||
libsofia-sip-ua/nta:
|
||||
- Added nta_incoming_received()
|
||||
- Added accessor function nta_outgoing_branch()
|
||||
- Added tag NTATAG_TIMER_C()
|
||||
- Deprecated nta_msg_ackbye()
|
||||
|
||||
libsofia-sip-ua/iptsec:
|
||||
- Added tag AUTHTAG_MAX_NCOUNT()
|
||||
|
||||
libsofia-sip-ua/sip:
|
||||
- Added SIPEXTHDRTAG_TYPEDEF() macro and tag class sipexthdrtag_class[]
|
||||
- Added SIP headers Alert-Info and Reply-To. Remote-Party-ID,
|
||||
P-Asserted-Identity, P-Preferred-Identity
|
||||
- Added sip_update_default_mclass() and sip_extend_mclass()
|
||||
- Added macros SIP_HAVE_XXXX for extra headers, e.g., SIP_HAVE_ALERT_INFO().
|
||||
|
||||
libsofia-sip-ua/soa:
|
||||
- Added tags SOATAG_ORDERED_USER() and SOATAG_REUSE_REJECTED()
|
||||
|
||||
libsofia-sip-ua/tport:
|
||||
- Updated transport timers
|
||||
- Added TPTAG_KEEPALIVE(), TPTAG_PINGPONG(), TPTAG_PONG2PING()
|
||||
- Added tport_is_clear_to_send(), tport_has_queued()
|
||||
- Updated timer handling
|
||||
- Added abstract type su_timer_queue_t (typedef'd to SU_TIMER_QUEUE_T)
|
||||
- Updated su_task_timers() and su_timer_expire() prototypes
|
||||
|
||||
libsofia-sip-ua/stun:
|
||||
- Removed extra system headers from <sofia-sip/stun_common.h>
|
||||
|
||||
libsofia-sip-ua/su:
|
||||
- Added su_nanotime_t and functions su_nanotime()/su_monotime()
|
||||
- Added function su_getsocktype()
|
||||
- Added heap template in <sofia-sip/heap.h>
|
||||
- Added configure option --disable-tag-cast and macro SU_INLINE_TAG_CAST
|
||||
- Added global variable su_socket_blocking. If it is set to true,
|
||||
sockets are created as blocking.
|
||||
- Added access point selection functionality for Open C / Symbian
|
||||
- Added functions su_root_release(), su_root_obtain() and
|
||||
su_root_has_thread(). A thread can release a su_root_t and another one can
|
||||
obtain it.
|
||||
|
||||
libsofia-sip-ua-glib:
|
||||
- No ABI/API changes, compatible with 1.12.0. Note, libsofia-sip-ua-glib
|
||||
interface is not considered stable and may change in a future 1.12.x
|
||||
|
@ -48,28 +79,21 @@ libsofia-sip-ua-glib:
|
|||
Contributors to this release
|
||||
----------------------------
|
||||
|
||||
<list of people who contributed to _this_ release
|
||||
- update as people's patches are added, or when you commit stuff
|
||||
- current development team members (see AUTHORS) may be omitted,
|
||||
or listed at the end of the contribur list (depending on the scope
|
||||
of the work done since the last release)
|
||||
- name of the contributor should be enough (email addresses in AUTHORS),
|
||||
plus a _brief_ description of what was contributed
|
||||
- roughly sorted by number of patches accepted
|
||||
/>
|
||||
|
||||
- Mikhail Zabaluev (bug fixes)
|
||||
- Fabio Margarido (bug fixes)
|
||||
- Martti Mela (Open C port and extra functionality, bug fixes)
|
||||
- Kai Vehmanen (fixes to win32 VC6/2005 project files)
|
||||
- Pekka Pessi (everything else)
|
||||
|
||||
See the AUTHORS file in the distribution package.
|
||||
|
||||
Notes on new features
|
||||
---------------------
|
||||
|
||||
<information about major new features
|
||||
- new/changed/removed functionality
|
||||
- links to further documentation
|
||||
- section may be omitted for minor releases
|
||||
/>
|
||||
The route to the outbound proxy can now be specified as an explicit route
|
||||
set.
|
||||
|
||||
The TCP transport can use CR-LF keepalive and CR-LF PING-PONG messages.
|
||||
|
||||
IPv6 support can now be disabled in VC6/VC2005 builds, by
|
||||
setting SU_HAVE_IN6 to zero `win32/sofia-sip/su_configure.h'.
|
||||
|
@ -78,14 +102,53 @@ 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.
|
||||
|
||||
New SIP headers are not available by default. Application must enable them
|
||||
with sip_update_default_mclass() and sip_extend_mclass().
|
||||
|
||||
Bugs fixed in this release
|
||||
--------------------------
|
||||
|
||||
< notable bugs fixed in this release
|
||||
- check the sf.net bug tracker; see closed bugs,
|
||||
sorted by closing date
|
||||
- other bugs as fixed in CVS/darcs
|
||||
/>
|
||||
|
||||
- Fixed #1472682 sf.net bug: ACK does not find INVITE when
|
||||
To URI has been changed.
|
||||
- Fixed sf.net bug #1804248: nua_prack() now works.
|
||||
Thanks to Fabio Margarido for sending the patch.
|
||||
- Fixed sf.net bug 1803686: nua_destroy() can now be called from inside
|
||||
nua event callback.
|
||||
Thanks to Mikhail Zabaluev for reporting the problem.
|
||||
- SIP Content-Length structure was casted to one with 64-bit integer instead
|
||||
of 32-bit, so message body was not parsed on 64-bit big-endian platform.
|
||||
Thanks to Martin Drasar for hunting down the bug.
|
||||
- Authentication scheme token was compared as case-sensitive on client side.
|
||||
Thanks to Russell McConnachie for reporting this problem.
|
||||
- Fixed sf.net bug #1706629: in-dialog requests not routed according to the
|
||||
dialog route. Problem was because the outbound proxy was not handles as
|
||||
RECOMMENDED by RFC 3261. The new tag NUTAG_INITIAL_ROUTE() allows correct
|
||||
handling of requests.
|
||||
- Fixed problems in nua state engines (call setup failing if some messages
|
||||
were re-ordered or crashing when they were lost)
|
||||
Thanks to Michail Jerris, Anthony Minessale, and others in Freeswitch
|
||||
project for hunting down these bugs and reporting them
|
||||
- When nua generates Contact URI, the user-specified URI parameters are now
|
||||
overriden by actual transport parameters (e.g., transport=tcp)
|
||||
Thanks to Mikhail Zabaluev for submitting the patch.
|
||||
- Fixed sf.net bug #1750691: used to send ACK&BYE when extra 200 OK is
|
||||
received and the 200 OK did not match any client transaction.
|
||||
Thanks to Mikhail Zabaluev for reporting the problem.
|
||||
- Fixed problem of un-escaping reserved characters in URIs
|
||||
Thanks to Jan van den Bosch, Fabio Margarido and Mikhail Zabaluev for
|
||||
reporting the problem.
|
||||
- Fixed missing links in doxygen-generated documentation
|
||||
Thanks to Jerry Richards for reporting this problem.
|
||||
- Fixed timing problem with CANCELed INVITE transactions.
|
||||
Thanks to Fabio Margarido for reporting this problem.
|
||||
- Fixed sf.net bug #1771243: tport_check_trunc() does not block anymore
|
||||
Thanks to Erland Lwin for reporting the problem
|
||||
- Fixed sf.net bug #1733323: extra tag arguments were used by
|
||||
nta_outgoing_tcancel().
|
||||
Thanks to Fabio Margarido for reporting this problem.
|
||||
- Fixed sf.net bug #1747149: sdp_session_cmp() ignored some m= lines
|
||||
(e.g., new SDP in re-INVITE was sometimes ignored)
|
||||
Thanks to Mikhail Zabaluev for reporting the problem.
|
||||
- Fixed sf.net bug #1726034: crash in msg_as_string() with too large messages
|
||||
- Fixed sf.net bug #1472682: ACK did not find INVITE server transaction when
|
||||
the To URI had been changed.
|
||||
- Do not block when making a TCP connect()ion in tport.
|
||||
Thanks to Mikhail Zabaluev for submitting the patch.
|
||||
|
|
|
@ -51,3 +51,8 @@ include $(top_srcdir)/rules/lcov.am
|
|||
endif
|
||||
|
||||
.PHONY = $(PHONY)
|
||||
|
||||
CLEANFILES = docs/*.doxytags
|
||||
|
||||
distclean-local:
|
||||
-rm -rf docs/html
|
||||
|
|
|
@ -88,6 +88,9 @@ GSourceFuncs su_source_funcs[1] = {{
|
|||
NULL
|
||||
}};
|
||||
|
||||
static int su_source_port_init(su_port_t *self, su_port_vtable_t const *vtable);
|
||||
static void su_source_port_deinit(su_port_t *self);
|
||||
|
||||
static void su_source_lock(su_port_t *self, char const *who);
|
||||
static void su_source_unlock(su_port_t *self, char const *who);
|
||||
static void su_source_incref(su_port_t *self, char const *who);
|
||||
|
@ -115,7 +118,7 @@ static int su_source_eventmask(su_port_t *self,
|
|||
static void su_source_run(su_port_t *self);
|
||||
static void su_source_break(su_port_t *self);
|
||||
static su_duration_t su_source_step(su_port_t *self, su_duration_t tout);
|
||||
static int su_source_own_thread(su_port_t const *port);
|
||||
static int su_source_thread(su_port_t *self, enum su_port_thread_op op);
|
||||
static int su_source_add_prepoll(su_port_t *port,
|
||||
su_root_t *root,
|
||||
su_prepoll_f *,
|
||||
|
@ -147,13 +150,11 @@ su_port_vtable_t const su_source_port_vtable[1] =
|
|||
su_source_run,
|
||||
su_source_break,
|
||||
su_source_step,
|
||||
su_source_own_thread,
|
||||
su_source_thread,
|
||||
su_source_add_prepoll,
|
||||
su_source_remove_prepoll,
|
||||
su_base_port_timers,
|
||||
su_source_multishot,
|
||||
su_base_port_threadsafe,
|
||||
/*su_source_yield*/ NULL,
|
||||
/*su_source_wait_events*/ NULL,
|
||||
su_base_port_getmsgs,
|
||||
su_base_port_getmsgs_from,
|
||||
|
@ -177,6 +178,8 @@ struct su_source_s {
|
|||
su_base_port_t sup_base[1];
|
||||
|
||||
GThread *sup_tid;
|
||||
GStaticMutex sup_obtained[1];
|
||||
|
||||
GStaticMutex sup_mutex[1];
|
||||
|
||||
GSource *sup_source; /**< Backpointer to source */
|
||||
|
@ -258,37 +261,51 @@ GSource *su_glib_root_gsource(su_root_t *root)
|
|||
/*=============== Private function definitions ===============*/
|
||||
|
||||
/** Initialize source port */
|
||||
int su_source_port_init(su_port_t *self,
|
||||
GSource *gs,
|
||||
su_port_vtable_t const *vtable)
|
||||
static int su_source_port_init(su_port_t *self,
|
||||
su_port_vtable_t const *vtable)
|
||||
{
|
||||
if (su_base_port_init(self, vtable) < 0)
|
||||
return -1;
|
||||
GSource *gs = (GSource *)((char *)self - offsetof(SuSource, ss_port));
|
||||
|
||||
self->sup_source = gs;
|
||||
self->sup_tid = g_thread_self();
|
||||
|
||||
g_static_mutex_init(self->sup_obtained);
|
||||
|
||||
g_static_mutex_init(self->sup_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
return su_base_port_init(self, vtable);
|
||||
}
|
||||
|
||||
|
||||
static void su_source_port_deinit(su_port_t *self)
|
||||
{
|
||||
su_base_port_deinit(self);
|
||||
|
||||
g_static_mutex_free(self->sup_mutex);
|
||||
g_static_mutex_free(self->sup_obtained);
|
||||
|
||||
if (self->sup_indices)
|
||||
free (self->sup_indices), self->sup_indices = NULL;
|
||||
if (self->sup_waits)
|
||||
free (self->sup_waits), self->sup_waits = NULL;
|
||||
if (self->sup_wait_cbs)
|
||||
free (self->sup_wait_cbs), self->sup_wait_cbs = NULL;
|
||||
if (self->sup_wait_args)
|
||||
free (self->sup_wait_args), self->sup_wait_args = NULL;
|
||||
if (self->sup_wait_roots)
|
||||
free (self->sup_wait_roots), self->sup_wait_roots = NULL;
|
||||
|
||||
su_home_deinit(self->sup_base->sup_home);
|
||||
}
|
||||
|
||||
|
||||
/** @internal Destroy a port. */
|
||||
static
|
||||
void su_source_finalize(GSource *gs)
|
||||
{
|
||||
SuSource *ss = (SuSource *)gs;
|
||||
su_port_t *self = ss->ss_port;
|
||||
|
||||
assert(gs);
|
||||
|
||||
SU_DEBUG_9(("su_source_finalize() called\n"));
|
||||
|
||||
g_static_mutex_free(self->sup_mutex);
|
||||
|
||||
su_base_port_deinit(self);
|
||||
|
||||
su_home_deinit(self->sup_base->sup_home);
|
||||
su_source_port_deinit(ss->ss_port);
|
||||
}
|
||||
|
||||
void su_source_port_lock(su_port_t *self, char const *who)
|
||||
|
@ -330,16 +347,46 @@ int su_source_send(su_port_t *self, su_msg_r rmsg)
|
|||
}
|
||||
|
||||
/** @internal
|
||||
* Checks if the calling thread owns the port object.
|
||||
*
|
||||
* Change or query ownership of the port object.
|
||||
*
|
||||
* @param self pointer to a port object
|
||||
* @param op operation
|
||||
*
|
||||
* @retval true (nonzero) if the calling thread owns the port,
|
||||
* @retval false (zero) otherwise.
|
||||
* @ERRORS
|
||||
* @ERROR EALREADY port already has an owner (or has no owner)
|
||||
*/
|
||||
int su_source_own_thread(su_port_t const *self)
|
||||
static int su_source_thread(su_port_t *self, enum su_port_thread_op op)
|
||||
{
|
||||
return self == NULL || SU_SOURCE_OWN_THREAD(self);
|
||||
GThread *me = g_thread_self();
|
||||
|
||||
switch (op) {
|
||||
|
||||
case su_port_thread_op_is_obtained:
|
||||
if (self->sup_tid == me)
|
||||
return 2;
|
||||
else if (self->sup_tid)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
case su_port_thread_op_release:
|
||||
if (self->sup_tid != me)
|
||||
return errno = EALREADY, -1;
|
||||
self->sup_tid = NULL;
|
||||
g_static_mutex_unlock(self->sup_obtained);
|
||||
return 0;
|
||||
|
||||
case su_port_thread_op_obtain:
|
||||
if (su_home_threadsafe(su_port_home(self)) == -1)
|
||||
return -1;
|
||||
g_static_mutex_lock(self->sup_obtained);
|
||||
self->sup_tid = me;
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return errno = ENOSYS, -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Registering and unregistering ------------------------------------- */
|
||||
|
@ -1044,7 +1091,7 @@ static su_port_t *su_source_port_create(void)
|
|||
|
||||
if (ss) {
|
||||
self = ss->ss_port;
|
||||
if (su_source_port_init(self, ss->ss_source, su_source_port_vtable) < 0)
|
||||
if (su_source_port_init(self, su_source_port_vtable) < 0)
|
||||
g_source_unref(ss->ss_source), self = NULL;
|
||||
} else {
|
||||
su_perror("su_source_port_create(): g_source_new");
|
||||
|
|
|
@ -6,8 +6,10 @@
|
|||
*
|
||||
* The Sofia @b bnf module contains macros and functions for parsing
|
||||
* text-based formats, for example, for SIP. The interface is described in
|
||||
* <bnf.h>, the <bnf.c> contains a #_bnf_table table used to classify
|
||||
* characters.
|
||||
* <sofia-sip/bnf.h>.
|
||||
*
|
||||
* The interface used for validating hostnames and IP addresses is in
|
||||
* <sofia-sip/hostdomain.h>.
|
||||
*
|
||||
* @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
|
|
|
@ -28,7 +28,7 @@ ALIASES = \
|
|||
"TAG=\par \n" \
|
||||
"EVENTS=\par Events:\n" \
|
||||
"RESPONSES=\par Related Response Codes:\n" \
|
||||
"CFILE=\file" \
|
||||
"CFILE=\internal \file" \
|
||||
"IFILE=\file" \
|
||||
"HI=\hideinitializer " \
|
||||
"HIDE=\hideinitializer " \
|
||||
|
|
|
@ -23,6 +23,7 @@ COLLABORATION_GRAPH = YES
|
|||
GROUP_GRAPHS = NO
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
|
|
|
@ -7,6 +7,7 @@ INPUT = @srcdir@/mainpage.docs @srcdir@/docguide.docs @srcdir@/conformanc
|
|||
|
||||
@INCLUDE_PATH = . @srcdir@
|
||||
@INCLUDE = ../docs/Doxyfile.conf
|
||||
@INCLUDE = ../sip/sip.doxyaliases
|
||||
|
||||
GENERATE_TAGFILE = docs.doxytags
|
||||
|
||||
|
@ -28,4 +29,6 @@ TAGFILES += nea.doxytags=nea
|
|||
TAGFILES += nua.doxytags=nua
|
||||
TAGFILES += features.doxytags=features
|
||||
|
||||
|
||||
|
||||
EXAMPLE_PATH = @srcdir@/../sip
|
||||
|
|
|
@ -40,7 +40,10 @@ Doxyfile.rfc:
|
|||
from=700 to=4800 \
|
||||
/dev/null > $@
|
||||
|
||||
CLEANFILES = Doxyfile.rfc
|
||||
CLEANFILES = Doxyfile.rfc *.doxytags
|
||||
|
||||
distclean-local:
|
||||
-rm -rf html
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Sofia specific rules
|
||||
|
|
|
@ -20,32 +20,37 @@ below.
|
|||
<a href="#3313">RFC 3313</a> <br>
|
||||
<a href="#3323">RFC 3323</a> <br>
|
||||
<a href="#3326">RFC 3326</a> <br>
|
||||
</td><td>
|
||||
<a href="#3325">RFC 3325</a> <br>
|
||||
<a href="#3327">RFC 3327</a> <br>
|
||||
</td><td>
|
||||
<a href="#3329">RFC 3329</a> <br>
|
||||
<a href="#3361">RFC 3361</a> <br>
|
||||
<a href="#3420">RFC 3420</a> <br>
|
||||
<a href="#3428">RFC 3428</a> <br>
|
||||
<a href="#3486">RFC 3486</a> <br>
|
||||
<a href="#3515">RFC 3515</a> <br>
|
||||
<a href="#3581">RFC 3581</a> <br>
|
||||
<a href="#3608">RFC 3608</a> <br>
|
||||
<a href="#3680">RFC 3680</a> <br>
|
||||
<a href="#3824">RFC 3824</a> <br>
|
||||
</td><td>
|
||||
<a href="#3840">RFC 3840</a> <br>
|
||||
<a href="#3841">RFC 3841</a> <br>
|
||||
<a href="#3842">RFC 3842</a> <br>
|
||||
</td><td>
|
||||
<a href="#3856">RFC 3856</a> <br>
|
||||
<a href="#3857">RFC 3857</a> <br>
|
||||
<a href="#3858">RFC 3858</a> <br>
|
||||
<a href="#3859">RFC 3859</a> <br>
|
||||
<a href="#3860">RFC 3860</a> <br>
|
||||
<a href="#3891">RFC 3891</a> <br>
|
||||
<a href="#3892">RFC 3892</a> <br>
|
||||
<a href="#3903">RFC 3903</a> <br>
|
||||
<a href="#4028">RFC 4028</a> <br>
|
||||
<a href="#4168">RFC 4168</a> <br>
|
||||
<a href="#4320">RFC 4320</a> <br>
|
||||
<a href="#4566">RFC 4566</a> <br>
|
||||
<a href="#4488">RFC 4488</a> <br>
|
||||
</td><td>
|
||||
<a href="#4566">RFC 4566</a> <br>
|
||||
<a href="#2327">RFC 2327</a> <br>
|
||||
<a href="#3264">RFC 3264</a> <br>
|
||||
<a href="#3266">RFC 3266</a> <br>
|
||||
|
@ -53,6 +58,7 @@ below.
|
|||
<a href="#3388">RFC 3388</a> <br>
|
||||
<a href="#3407">RFC 3407</a> <br>
|
||||
<a href="#3524">RFC 3524</a> <br>
|
||||
<a href="#3551">RFC 3551</a> <br>
|
||||
<a href="#3556">RFC 3556</a> <br>
|
||||
<a href="#3605">RFC 3605</a> <br>
|
||||
<a href="#3890">RFC 3890</a> <br>
|
||||
|
@ -98,7 +104,7 @@ below.
|
|||
</td>
|
||||
<td>
|
||||
The supported @RFC3261 methods are: @b REGISTER, @b OPTIONS, @b
|
||||
INVITE, @b ACK, @b CANCEL, @b BYE, as well as methods
|
||||
INVITE, @b ACK, @b CANCEL, @b BYE, as well as extension methods
|
||||
<a href="#2976"><b>INFO</b></a>,
|
||||
<a href="#3262"><b>PRACK</b></a>,
|
||||
<a href="#3265"><b>SUBSCRIBE</b></a>,
|
||||
|
@ -116,7 +122,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_alert_info "Alert-Info" (extension in @VERSION_1_12_7),
|
||||
@ref sip_allow "Allow",
|
||||
@ref sip_authentication_info "Authentication-Info",
|
||||
@ref sip_authorization "Authorization",
|
||||
|
@ -138,12 +144,18 @@ below.
|
|||
@ref sip_min_expires "Min-Expires",
|
||||
@ref sip_mime_version "MIME-Version",
|
||||
@ref sip_organization "Organization",
|
||||
@ref sip_p_asserted_identity "P-Asserted-Identity"
|
||||
(extension in @VERSION_1_12_7),
|
||||
@ref sip_p_preferred_identity "P-Preferred-Identity"
|
||||
(extension in @VERSION_1_12_7),
|
||||
@ref sip_priority "Priority",
|
||||
@ref sip_proxy_authenticate "Proxy-Authenticate",
|
||||
@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_refer_sub "Refer-Sub" (@VERSION_1_12_5),
|
||||
@ref sip_remote_party_id "Remote-Party-ID" (extension in @VERSION_1_12_7),
|
||||
@ref sip_reply_to "Reply-To" (extension in @VERSION_1_12_7),
|
||||
@ref sip_require "Require",
|
||||
@ref sip_retry_after "Retry-After",
|
||||
@ref sip_route "Route",
|
||||
|
@ -167,7 +179,7 @@ below.
|
|||
<td>
|
||||
- Automatic escaping of reserved characters has not been
|
||||
implemented.
|
||||
- Using NUL (zero byte) in doublequoted strings has not been implemented
|
||||
- Using NUL (zero byte) in double-quoted strings has not been implemented
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -196,7 +208,7 @@ below.
|
|||
Only one SIP message is accepted per UDP message, as per @RFC3261.
|
||||
</td>
|
||||
<td>
|
||||
There is experimental support for SCTP, too.
|
||||
There is <a href="#4168">experimental support for SCTP</a>, too.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -212,8 +224,12 @@ below.
|
|||
User-Agent and Proxy modes.
|
||||
|
||||
Default values for SIP timers are those specified by @RFC3261. The
|
||||
defaults for T1, T1x64, T2 and T4 can be changed via
|
||||
values for T1, T1x64, T2 and T4 can be changed via
|
||||
configuration tags defined in <sofia-sip/nta_tag.h>.
|
||||
|
||||
The SIP timer C is implemented from @VERSION_1_12_7. Also, its value
|
||||
can be changed via configuration tag NTATAG_TIMER_C() defined in
|
||||
<sofia-sip/nta_tag.h>.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
@ -462,10 +478,13 @@ below.
|
|||
@RFC3325: Asserted Identity
|
||||
</th>
|
||||
<td>
|
||||
Sofia-SIP provides <a href="#3261.19">generic support</a> for
|
||||
extension headers and parameters. P-Asserted-Identity and
|
||||
P-Preferred-Identity are supported as supported as @ref
|
||||
sip_unknown "extension headers".
|
||||
Sofia-SIP supports
|
||||
@ref sip_p_asserted_identity "P-Asserted-Identity" and
|
||||
@ref sip_p_preferred_identity "P-Preferred-Identity" headers
|
||||
(generating, parsing and syntax checking). Also the non-standard
|
||||
header @ref sip_remote_party_id "Remote-Party-ID" is supported.
|
||||
|
||||
@NEW_1_12_7.
|
||||
</td>
|
||||
<td>
|
||||
Not implemented:
|
||||
|
@ -733,10 +752,11 @@ below.
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<a name="3856"></a>
|
||||
<a name="3856"></a><a name="3859"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
@RFC3856: Presence
|
||||
@RFC3856: Presence <br />
|
||||
@RFC3859: Common Profile for Presence
|
||||
</th>
|
||||
<td>
|
||||
Sofia-SIP supports <a href="#3265">generic SIP event support</a> for
|
||||
|
@ -778,7 +798,22 @@ below.
|
|||
- Including correct @ref sip_event "Event" and
|
||||
@ref sip_accept "Accept" headers in the request (if needed)
|
||||
- Processing notifications for winfo events:
|
||||
- Processing watcherxinfo XML documents
|
||||
- Processing watcherinfo XML documents
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<a name="3860"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
@RFC3860: Common Profile for IM
|
||||
</th>
|
||||
<td>
|
||||
Sofia-SIP supports handling of any URI type. Sofia-SIP parses "im:"
|
||||
URIs.
|
||||
</td>
|
||||
<td>
|
||||
Application must take care of:
|
||||
- resolving the "im:" URI
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -834,7 +869,7 @@ below.
|
|||
<td>
|
||||
Application must take care of:
|
||||
- Including correct @ref sip_event "Event" in the request
|
||||
- Permanently storing SIP-ETag
|
||||
- Permanently storing @SIPETag
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -864,6 +899,26 @@ below.
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<a name="4168"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
@RFC4168: SCTP as Transport for SIP
|
||||
</th>
|
||||
<td>
|
||||
The transport=sctp URI parameter is supported. The SCTP transport
|
||||
protocol is supported as experimental. It is enabled with
|
||||
configure script argument --enable-sctp.
|
||||
|
||||
The framing of SIP messages over SCTP is not specified clearly in
|
||||
@RFC4168. It is possible to send SIP messages smaller than 64K over
|
||||
SCTP.
|
||||
</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<a name="4320"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
|
@ -886,6 +941,28 @@ below.
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<a name="4488"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
@RFC4488: Suppression of REFER Implicit Subscription
|
||||
</th>
|
||||
<td>
|
||||
Sofia-SIP supports @ref sip_refer_sub "Refer-Sub" header
|
||||
(generating, parsing and syntax checking).
|
||||
|
||||
The implicit subscription is suppressed by @nua, if the @ReferSub:
|
||||
true header is included in the REFER
|
||||
request (@ref nua_refer "on server side") or
|
||||
response (@ref nua_i_refer "on client side").
|
||||
|
||||
@NEW_1_12_5
|
||||
</td>
|
||||
<td>
|
||||
The REFER client application must include SIPTAG_REFER_SUB_STR("true")
|
||||
in the nua_refer() tags.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table border=1 cellpadding=4 cellspacing=0>
|
||||
|
@ -922,7 +999,7 @@ below.
|
|||
"a=inactive", @ref sdp_rtpmap_s "a=rtpmap", and "a=fmtp" are parsed.
|
||||
|
||||
The implementation partially implements @RFC4566. Note that
|
||||
definiton of 'token' was updated in @RFC4566 and the parser has not
|
||||
definition of 'token' was updated in @RFC4566 and the parser has not
|
||||
been updated yet.
|
||||
</td>
|
||||
<td>
|
||||
|
@ -1023,6 +1100,23 @@ below.
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<a name="3551"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
@RFC3551: RTP/AVP
|
||||
</th>
|
||||
<td>
|
||||
Sofia-SIP recognizes the RTP payload types for well-known audio and
|
||||
video codecs defined in @RFC3551.
|
||||
</td>
|
||||
<td>
|
||||
Application must take care of:
|
||||
- Audio or video processing
|
||||
- Generating a=rtpmap or a=fmtp lines when needed
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<a name="3556"></a>
|
||||
<tr valign=top>
|
||||
<th align="left">
|
||||
|
|
|
@ -260,7 +260,7 @@ C 99 standard defines the following fixed length data types:
|
|||
- int8_t
|
||||
- uint8_t
|
||||
|
||||
To use these data types you must include the <su_types.h> header, which
|
||||
To use these data types you must include the <sofia-sip/su_types.h> header, which
|
||||
takes care of including correct file. If @b su includes are not available,
|
||||
you must include the following code segment to each file where you plan to
|
||||
use them:
|
||||
|
@ -298,7 +298,7 @@ network byte order to host byte order.
|
|||
The ntohs() function converts the unsigned short integer netshort
|
||||
from network byte order to host byte order.
|
||||
|
||||
You need to include <netinet/in.h> or <su.h> to use these functions.
|
||||
You need to include <netinet/in.h> or <sofia-sip/su.h> to use these functions.
|
||||
|
||||
@subsection port_struct Packing structures
|
||||
|
||||
|
@ -467,7 +467,7 @@ reference. This simplifies application logic because application code does
|
|||
not need to keep track of the allocated memory and free every allocated block
|
||||
separately.
|
||||
|
||||
See documentation of <su_alloc.h> and @ref su_alloc "memory managment tutorial"
|
||||
See documentation of <sofia-sip/su_alloc.h> and @ref su_alloc "memory managment tutorial"
|
||||
for more information of memory management services.
|
||||
|
||||
@subsection contextdata Memory management of context data
|
||||
|
@ -532,7 +532,7 @@ controlled by upper level memory management.
|
|||
|
||||
@section testing Testing Your Code
|
||||
|
||||
See <tstdef.h> for example of how to write module tests with macros provided
|
||||
See <sofia-sip/tstdef.h> for example of how to write module tests with macros provided
|
||||
by Sofia.
|
||||
|
||||
Here are some ideas of what you should test:
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* @section http_overview Overview
|
||||
*
|
||||
* Each HTTP header has a structure defined for it in <http.h>. All the
|
||||
* Each HTTP header has a structure defined for it in <sofia-sip/http.h>. All the
|
||||
* variables, objects and functions related to a particular HTTP header are
|
||||
* 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
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file http_tag.c HTTP Tag classes
|
||||
/**@internal @file http_tag.c HTTP Tag classes
|
||||
*
|
||||
* This file is autogenerated from <http_tag.c.in>.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
PROJECT_NAME = "ipt"
|
||||
OUTPUT_DIRECTORY = ../docs/html/ips
|
||||
OUTPUT_DIRECTORY = ../docs/html/ipt
|
||||
|
||||
INPUT = @srcdir@/ipt.docs @srcdir@/sofia-sip @srcdir@ .
|
||||
INPUT = @srcdir@/ipt.docs
|
||||
INPUT += @srcdir@/sofia-sip/base64.h @srcdir@/base64.c
|
||||
INPUT += @srcdir@/sofia-sip/token64.h @srcdir@/token64.c
|
||||
|
||||
@INCLUDE_PATH = . @srcdir@
|
||||
@INCLUDE = ../docs/Doxyfile.conf
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
* @section ipt_overview Overview
|
||||
*
|
||||
* This module contain some routines useful for IPT applications, like
|
||||
* - <sofia-sip/base64.h> BASE64 encoding/decoding,
|
||||
* - <sofia-sip/token64.h> encoding/decoding binary as SIP/HTTP token,
|
||||
* - <sofia-sip/base64.h> BASE64 encoding/decoding, and
|
||||
* - <sofia-sip/token64.h> encoding/decoding binary as SIP/HTTP token.
|
||||
*/
|
||||
|
|
|
@ -57,7 +57,7 @@ SOFIAPUBFUN isize_t base64_e(char buf[], isize_t bsiz, void *data, isize_t dsiz)
|
|||
/** Calculate size of n bytes encoded in base64 */
|
||||
#define BASE64_SIZE(n) ((((n) + 2) / 3) * 4)
|
||||
|
||||
/** Calculate size of n bytes encoded in base64 sans trailing =. @NEW_1_12_5 */
|
||||
/** Calculate size of n bytes encoded in base64 sans trailing =. @NEW_1_12_5. */
|
||||
#define BASE64_MINSIZE(n) ((n * 4 + 2) / 3)
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@CFILE token64.c
|
||||
/**@internal @file token64.c
|
||||
*
|
||||
* Token encoding.
|
||||
*
|
||||
|
@ -41,7 +41,7 @@
|
|||
static const char code[65] =
|
||||
"0123456789-abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
/** Encode data as an http token.
|
||||
/** Encode data as a SIP/HTTP token.
|
||||
*
|
||||
* @note
|
||||
* A token is case-independent, so this is really not a good idea.
|
||||
|
|
|
@ -20,7 +20,7 @@ TAGFILES += ../docs/nta.doxytags=../nta
|
|||
|
||||
GENERATE_TAGFILE = ../docs/iptsec.doxytags
|
||||
|
||||
ALIASES +=
|
||||
ALIASES += "iptsec=@ref index \"iptsec\""
|
||||
|
||||
PREDEFINED += SOFIA_EXTEND_AUTH_CLIENT=1
|
||||
|
||||
|
|
|
@ -205,15 +205,17 @@ int ca_challenge(auth_client_t *ca,
|
|||
* processed.
|
||||
*
|
||||
* @bug
|
||||
* The result can be quite unexpected if there are more than one
|
||||
* authenticator with the given type (specified by @a crcl). In principle,
|
||||
* SIP allows more than one challenge for a single request.
|
||||
* In principle, SIP allows more than one challenge for a single request.
|
||||
* For example, there can be multiple proxies that each challenge the
|
||||
* client. The result of storing authentication info can be quite unexpected
|
||||
* if there are more than one authenticator with the given type (specified
|
||||
* by @a credential_class).
|
||||
*
|
||||
* @retval number of challenges to updated
|
||||
* @retval 0 when there was no challenge to update
|
||||
* @retval -1 upon an error
|
||||
*
|
||||
* @NEW_1_12_5
|
||||
* @NEW_1_12_5.
|
||||
*/
|
||||
int auc_info(auth_client_t **auc_list,
|
||||
msg_auth_info_t const *info,
|
||||
|
@ -525,7 +527,7 @@ int ca_clear_credentials(auth_client_t *ca)
|
|||
* @retval 1 when authorization can proceed
|
||||
* @retval 0 when there is not enough credentials
|
||||
*
|
||||
* @NEW_1_12_5
|
||||
* @NEW_1_12_5.
|
||||
*/
|
||||
int auc_has_authorization(auth_client_t **auc_list)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file auth_module_http.c
|
||||
* @brief Authenticate HTTP request
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file auth_module_sip.c
|
||||
* @brief Authenticate SIP request
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file auth_plugin.c
|
||||
* @brief Plugin interface for authentication verification modules.
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file iptsec_debug.c
|
||||
/**@internal @file iptsec_debug.c
|
||||
* @brief Debug log for IPTSEC module.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
@ -36,25 +36,34 @@
|
|||
|
||||
#include "iptsec_debug.h"
|
||||
|
||||
/**@var IPTSEC_DEBUG
|
||||
#if DOXYGEN_ONLY
|
||||
/** @defgroup iptsec_env Environment Variables Used by iptsec Module
|
||||
*
|
||||
* Environment variable determining the debug log level for @b iptsec
|
||||
* @brief Environment variables used by @iptsec module are listed here.
|
||||
*
|
||||
* The #IPTSEC_DEBUG variable sets the debug level.
|
||||
*/
|
||||
|
||||
/**@ingroup iptsec_env
|
||||
*
|
||||
* Environment variable determining the debug log level for @iptsec
|
||||
* module.
|
||||
*
|
||||
* The IPTSEC_DEBUG environment variable is used to determine the debug
|
||||
* logging level for @b iptsec module. The default level is 3.
|
||||
* logging level for @iptsec module. The default level is 3.
|
||||
*
|
||||
* @sa <sofia-sip/su_debug.h>, iptsec_log, SOFIA_DEBUG
|
||||
* @sa <sofia-sip/su_debug.h>, #iptsec_log, #SOFIA_DEBUG
|
||||
*/
|
||||
extern char const IPTSEC_DEBUG[];
|
||||
extern IPTSEC_DEBUG;
|
||||
#endif
|
||||
|
||||
#ifndef SU_DEBUG
|
||||
#define SU_DEBUG 3
|
||||
#endif
|
||||
|
||||
/**Debug log for @b iptsec module.
|
||||
/** Common log for client and server components.
|
||||
*
|
||||
* The iptsec_log is the log object used by @b iptsec module. The level of
|
||||
* The iptsec_log is the log object used by @iptsec module. The level of
|
||||
* #iptsec_log is set using #IPTSEC_DEBUG environment variable.
|
||||
*/
|
||||
su_log_t iptsec_log[] = { SU_LOG_INIT("iptsec", "IPTSEC_DEBUG", SU_DEBUG) };
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
/** Defined when <iptsec_debug.h> has been included. */
|
||||
#define IPTSEC_DEBUG_H
|
||||
|
||||
/**@file iptsec_debug.h
|
||||
/**@internal
|
||||
* @file iptsec_debug.h
|
||||
* @brief Debug log for IPTSEC module.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
@ -38,7 +39,7 @@
|
|||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/** Common log for application and srvlib components. */
|
||||
/** Common log for client and server components. */
|
||||
SOFIAPUBVAR su_log_t iptsec_log[];
|
||||
|
||||
SOFIA_END_DECLS
|
||||
|
|
|
@ -91,12 +91,12 @@ struct auth_client_plugin
|
|||
int (*auc_info)(auth_client_t *ca, msg_auth_info_t const *ai);
|
||||
|
||||
#if SOFIA_EXTEND_AUTH_CLIENT
|
||||
/** Clear credentials (user/pass). @NEW_1_12_6 */
|
||||
/** Clear credentials (user/pass). @NEW_1_12_6. */
|
||||
int (*auc_clear)(auth_client_t *ca);
|
||||
#endif
|
||||
};
|
||||
|
||||
/** Check if authentication client has been extended. @NEW_1_12_6 */
|
||||
/** Check if authentication client has been extended. @NEW_1_12_6. */
|
||||
#define AUTH_CLIENT_IS_EXTENDED(ca) \
|
||||
((ca)->ca_auc->auc_plugin_size > \
|
||||
(int)offsetof(auth_client_plugin_t, auc_clear) \
|
||||
|
|
|
@ -7,6 +7,8 @@ INPUT = @srcdir@/msg.docs @srcdir@/sofia-sip sofia-sip @srcdir@ .
|
|||
@INCLUDE = ../docs/Doxyfile.conf
|
||||
@INCLUDE = ../sip/sip.doxyaliases
|
||||
|
||||
EXCLUDE_PATTERNS += msg_test*.h msg_test*.c
|
||||
|
||||
TAGFILES += ../docs/ipt.doxytags=../ipt \
|
||||
../docs/su.doxytags=../su \
|
||||
../docs/sip.doxytags=../sip \
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file msg.c Message object implementation.
|
||||
/**@internal @file msg.c Message object implementation.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
|
|
|
@ -142,7 +142,7 @@ separator and the message body are all in their own fragment structure. The
|
|||
fragments form a dual-linked list known as @e fragment @e chain as shown in
|
||||
the above figure. The memory buffers for the message, the fragment chain,
|
||||
and a whole lot of other stuff is held by the generic message type, #msg_t,
|
||||
defined in <msg.h>. The internal structure of #msg_t is known only within @b
|
||||
defined in <sofia-sip/msg.h>. The internal structure of #msg_t is known only within @b
|
||||
msg module and it is opaque to other modules.
|
||||
|
||||
The @b msg parser engine also drives the reverse process, invoking the
|
||||
|
@ -262,7 +262,7 @@ header members that are also found in the beginning of a header
|
|||
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.
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@ingroup msg_parser
|
||||
/**@internal
|
||||
* @ingroup msg_parser
|
||||
* @file msg_generic.c
|
||||
* @brief Functions for generic headers
|
||||
*
|
||||
|
|
|
@ -67,36 +67,6 @@ size_t memcspn(const void *mem, size_t memlen,
|
|||
/** Protocol version of MIME */
|
||||
char const msg_mime_version_1_0[] = "MIME/1.0";
|
||||
|
||||
/* Internally used version of msg_header_t */
|
||||
union msg_mime_u
|
||||
{
|
||||
msg_common_t sh_common[1];
|
||||
struct {
|
||||
msg_common_t shn_common;
|
||||
msg_header_t *shn_next;
|
||||
} sh_header_next[1];
|
||||
|
||||
msg_multipart_t sh_multipart[1];
|
||||
|
||||
msg_accept_t sh_accept[1];
|
||||
msg_accept_any_t sh_accept_any[1];
|
||||
msg_accept_charset_t sh_accept_charset[1];
|
||||
msg_accept_encoding_t sh_accept_encoding[1];
|
||||
msg_accept_language_t sh_accept_language[1];
|
||||
msg_content_disposition_t sh_content_disposition[1];
|
||||
msg_content_encoding_t sh_content_encoding[1];
|
||||
msg_content_id_t sh_content_id[1];
|
||||
msg_content_language_t sh_content_language[1];
|
||||
msg_content_length_t sh_content_length[1];
|
||||
msg_content_location_t sh_content_location[1];
|
||||
msg_content_type_t sh_content_type[1];
|
||||
msg_mime_version_t sh_mime_version[1];
|
||||
msg_warning_t sh_warning[1];
|
||||
msg_unknown_t sh_unknown[1];
|
||||
msg_separator_t sh_separator[1];
|
||||
msg_payload_t sh_payload[1];
|
||||
};
|
||||
|
||||
#include <sofia-sip/msg_parser.h>
|
||||
#include <sofia-sip/msg_mime_protos.h>
|
||||
|
||||
|
|
|
@ -54,25 +54,26 @@ BEGIN {
|
|||
split("", NAMES);
|
||||
split("", Comments);
|
||||
split("", COMMENTS);
|
||||
split("", experimental);
|
||||
|
||||
# indexed by the C name of the header
|
||||
split("", Since); # Non-NUL if extra
|
||||
split("", Extra); # Offset in extra headers
|
||||
|
||||
total = 0;
|
||||
ordinary = 0;
|
||||
basic = 0;
|
||||
extra = 0;
|
||||
without_experimental = 0;
|
||||
|
||||
template="";
|
||||
template1="";
|
||||
template2="";
|
||||
template3="";
|
||||
prefix="";
|
||||
tprefix="";
|
||||
extra=0;
|
||||
failed=0;
|
||||
success=0;
|
||||
|
||||
extra_struct = "msg_pub_extra";
|
||||
|
||||
ERRNO="error";
|
||||
}
|
||||
|
||||
|
@ -159,7 +160,6 @@ function protos (name, comment, hash, since)
|
|||
symbols[name] = comment;
|
||||
if (since) {
|
||||
Since[name] = since;
|
||||
Extra[name] = extra++;
|
||||
}
|
||||
|
||||
expr = (without_experimental > 0 && do_hash);
|
||||
|
@ -210,7 +210,7 @@ function replace (p, hash, name, NAME, comment, Comment, COMMENT, since)
|
|||
|
||||
#
|
||||
# Repeat each line in the footer containing the magic replacement
|
||||
# pattern with a instance of all headers
|
||||
# pattern with an instance of all headers
|
||||
#
|
||||
function process_footer (text)
|
||||
{
|
||||
|
@ -368,9 +368,14 @@ function templates ()
|
|||
}
|
||||
|
||||
/^#### EXTRA HEADER LIST STARTS HERE ####$/ { HLIST=1; templates(); }
|
||||
HLIST && /^#### DEFAULT HEADER LIST ENDS HERE ####$/ { basic=total; }
|
||||
HLIST && /^#### EXPERIMENTAL HEADER LIST STARTS HERE ####$/ {
|
||||
without_experimental=total; }
|
||||
HLIST && /^[a-z]/ { protos($1, $0, 0, $2); headers[total++] = $1; }
|
||||
without_experimental = total; }
|
||||
|
||||
HLIST && /^[a-z]/ { protos($1, $0, 0, $2);
|
||||
headers[total++] = $1;
|
||||
Extra[$1] = extra++;
|
||||
}
|
||||
/^#### EXTRA HEADER LIST ENDS HERE ####$/ { HLIST=0; }
|
||||
|
||||
/^ *\/\* === Headers start here \*\// { in_header_list=1; templates(); }
|
||||
|
@ -396,15 +401,117 @@ in_header_list && /^ (sip|rtsp|http|msg|mp)_[a-z_0-9]+_t/ {
|
|||
if (!NO_MIDDLE)
|
||||
protos(n, $0, 0);
|
||||
|
||||
headers[total++] = n;
|
||||
headers[total] = n; total++; ordinary++;
|
||||
}
|
||||
|
||||
function print_parser_table(struct, scope, name, N, N_EXPERIMENTAL)
|
||||
{
|
||||
if (PT) {
|
||||
if (N > ordinary) {
|
||||
printf("/* Ordinary %u, extra %u, experimental %u */\n",
|
||||
ordinary, N - ordinary, N_EXPERIMENTAL - N) > PT;
|
||||
printf("struct %s {\n", struct) > PT;
|
||||
printf(" %s_t base;\n", module) > PT;
|
||||
printf(" msg_header_t *extra[%u];\n", N - ordinary) > PT;
|
||||
if (N != N_EXPERIMENTAL) {
|
||||
print "#if SU_HAVE_EXPERIMENTAL" > PT;
|
||||
printf(" msg_header_t *extra[%u];\n", N_EXPERIMENTAL - N) > PT;
|
||||
print "#endif" > PT;
|
||||
}
|
||||
printf("};\n\n") > PT;
|
||||
}
|
||||
|
||||
printf("%s\n", scope) > PT;
|
||||
printf("msg_mclass_t const %s[1] = \n{{\n", name) > PT;
|
||||
printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT;
|
||||
printf(" %s_HCLASS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" {{ 0 }},\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
printf(" %s_VERSION_CURRENT,\n", toupper(module)) > PT;
|
||||
printf(" %s_PROTOCOL_TAG,\n", toupper(module)) > PT;
|
||||
printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT;
|
||||
printf(" %s_PARSER_FLAGS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" 0,\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
if (N > ordinary) {
|
||||
printf(" sizeof (struct %s),\n", struct) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" sizeof (%s_t),\n", module) > PT;
|
||||
}
|
||||
printf(" %s_extract_body,\n", module) > PT;
|
||||
|
||||
len = split("request status separator payload unknown error", unnamed, " ");
|
||||
|
||||
for (i = 1; i <= len; i++) {
|
||||
printf(" {{ %s_%s_class, msg_offsetof(%s_t, %s_%s) }},\n",
|
||||
tprefix, unnamed[i], module, prefix, unnamed[i]) > PT;
|
||||
}
|
||||
if (multipart) {
|
||||
printf(" {{ %s_class, msg_offsetof(%s_t, %s_multipart) }},\n",
|
||||
multipart, module, prefix) > PT;
|
||||
} else {
|
||||
printf(" {{ NULL, 0 }},\n") > PT;
|
||||
}
|
||||
if (MC_SHORT_SIZE) {
|
||||
printf(" %s_short_forms, \n", module) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" NULL, \n") > PT;
|
||||
}
|
||||
printf(" %d, \n", MC_HASH_SIZE) > PT;
|
||||
if (N != N_EXPERIMENTAL) {
|
||||
print "#if SU_HAVE_EXPERIMENTAL" > PT;
|
||||
printf(" %d,\n", N_EXPERIMENTAL) > PT;
|
||||
print "#else" > PT;
|
||||
}
|
||||
printf(" %d,\n", N) > PT;
|
||||
if (N != N_EXPERIMENTAL) {
|
||||
print "#endif" > PT;
|
||||
}
|
||||
|
||||
printf(" {\n") > PT;
|
||||
|
||||
for (j = 0; j < MC_HASH_SIZE; j++) {
|
||||
c = (j + 1 == MC_HASH_SIZE) ? "" : ",";
|
||||
if (j in header_hash) {
|
||||
n = header_hash[j];
|
||||
i = index_hash[j];
|
||||
|
||||
flags = header_flags[n]; if (flags) flags = ",\n " flags;
|
||||
|
||||
if (i >= N) {
|
||||
print "#if SU_HAVE_EXPERIMENTAL" > PT;
|
||||
}
|
||||
|
||||
if (i >= ordinary) {
|
||||
printf(" { %s_%s_class,\n" \
|
||||
" msg_offsetof(struct %s, extra[%u])%s }%s\n",
|
||||
tprefix, n, struct, Extra[n], flags, c) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" { %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
tprefix, n, module, prefix, n, flags, c) > PT;
|
||||
}
|
||||
|
||||
if (i >= N) {
|
||||
printf("#else\n { NULL, 0 }%s\n#endif\n", c) > PT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf(" { NULL, 0 }%s\n", c) > PT;
|
||||
}
|
||||
}
|
||||
printf(" }\n}};\n\n") > PT;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (failed) { exit };
|
||||
|
||||
if (without_experimental == 0)
|
||||
without_experimental = total;
|
||||
|
||||
if (!NO_LAST) {
|
||||
protos("unknown", "/**< Unknown headers */", -3);
|
||||
protos("error", "/**< Erroneous headers */", -4);
|
||||
|
@ -429,8 +536,6 @@ END {
|
|||
getline footer < TEMPLATE;
|
||||
RS=RS0;
|
||||
|
||||
module_struct = module "_t";
|
||||
|
||||
sub(/.*[\/]/, "", TEMPLATE);
|
||||
gsub(/#AUTO#/, auto, header);
|
||||
gsub(/#DATE#/, "@date Generated: " date, header);
|
||||
|
@ -451,9 +556,9 @@ END {
|
|||
n = shorts[i];
|
||||
flags = header_flags[n]; if (flags) flags = ",\n " flags;
|
||||
|
||||
printf(" { /* %s */ %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
substr(lower_case, i, 1),
|
||||
tprefix, n, module, prefix, n, flags, c) \
|
||||
printf(" { /* %s */ %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
substr(lower_case, i, 1),
|
||||
tprefix, n, module, prefix, n, flags, c) \
|
||||
> PT;
|
||||
}
|
||||
else {
|
||||
|
@ -466,67 +571,13 @@ END {
|
|||
|
||||
# printf("extern msg_hclass_t msg_multipart_class[];\n\n") > PT;
|
||||
|
||||
if (extra > 0) {
|
||||
printf("struct %s {\n", extra_struct) > PT;
|
||||
printf(" %s base;\n", module_struct) > PT;
|
||||
if (total - without_experimental < extra) {
|
||||
printf(" msg_header_t *extra[%u];\n",
|
||||
extra - (total - without_experimental)) > PT;
|
||||
}
|
||||
if (total - without_experimental > 0) {
|
||||
print "#if SU_HAVE_EXPERIMENTAL" > PT;
|
||||
printf(" msg_header_t *experimental[%u];\n",
|
||||
total - without_experimental) > PT;
|
||||
print "#endif" > PT;
|
||||
}
|
||||
printf("};\n\n") > PT;
|
||||
module_struct = "struct " extra_struct;
|
||||
}
|
||||
if (basic == 0) basic = total;
|
||||
if (without_experimental == 0) without_experimental = total;
|
||||
|
||||
printf("msg_mclass_t const %s_mclass[1] = \n{{\n", module) > PT;
|
||||
printf("# if defined (%s_HCLASS)\n", toupper(module)) > PT;
|
||||
printf(" %s_HCLASS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" {{ 0 }},\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
printf(" %s_VERSION_CURRENT,\n", toupper(module)) > PT;
|
||||
printf(" %s_PROTOCOL_TAG,\n", toupper(module)) > PT;
|
||||
printf("#if defined (%s_PARSER_FLAGS)\n", toupper(module)) > PT;
|
||||
printf(" %s_PARSER_FLAGS,\n", toupper(module)) > PT;
|
||||
printf("#else\n") > PT;
|
||||
printf(" 0,\n") > PT;
|
||||
printf("#endif\n") > PT;
|
||||
printf(" sizeof (%s),\n", module_struct) > PT;
|
||||
printf(" %s_extract_body,\n", module) > PT;
|
||||
split("", header_hash);
|
||||
split("", index_hash);
|
||||
|
||||
len = split("request status separator payload unknown error", unnamed, " ");
|
||||
|
||||
for (i = 1; i <= len; i++) {
|
||||
printf(" {{ %s_%s_class, msg_offsetof(%s_t, %s_%s) }},\n",
|
||||
tprefix, unnamed[i], module, prefix, unnamed[i]) > PT;
|
||||
}
|
||||
if (multipart) {
|
||||
printf(" {{ %s_class, msg_offsetof(%s_t, %s_multipart) }},\n",
|
||||
multipart, module, prefix) > PT;
|
||||
} else {
|
||||
printf(" {{ NULL, 0 }},\n") > PT;
|
||||
}
|
||||
if (MC_SHORT_SIZE) {
|
||||
printf(" %s_short_forms, \n", module) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" NULL, \n") > PT;
|
||||
}
|
||||
printf(" %d, \n", MC_HASH_SIZE) > PT;
|
||||
printf ("#if SU_HAVE_EXPERIMENTAL\n" \
|
||||
" %d,\n" \
|
||||
"#else\n" \
|
||||
" %d,\n" \
|
||||
"#endif\n", \
|
||||
total, without_experimental) > PT;
|
||||
printf(" {\n") > PT;
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
for (i = 0; i < basic; i++) {
|
||||
n = headers[i];
|
||||
h = hashed[n];
|
||||
|
||||
|
@ -542,38 +593,67 @@ END {
|
|||
}
|
||||
|
||||
header_hash[j] = n;
|
||||
experimental2[j] = (i >= without_experimental);
|
||||
index_hash[j] = i;
|
||||
}
|
||||
|
||||
for (i = 0; i < MC_HASH_SIZE; i++) {
|
||||
c = (i + 1 == MC_HASH_SIZE) ? "" : ",";
|
||||
if (i in header_hash) {
|
||||
n = header_hash[i];
|
||||
flags = header_flags[n]; if (flags) flags = ",\n " flags;
|
||||
m = module "_mclass";
|
||||
s = "_d_" module "_t";
|
||||
|
||||
if (experimental2[i]) {
|
||||
# Add basic headers
|
||||
if (ordinary == basic) {
|
||||
print_parser_table(s, "", m, basic, basic);
|
||||
}
|
||||
else if (basic < without_experimental) {
|
||||
print_parser_table(s, "", m, basic, basic);
|
||||
}
|
||||
else {
|
||||
print_parser_table(s, "", m, without_experimental, basic);
|
||||
}
|
||||
|
||||
if (0) {
|
||||
|
||||
# Hash extra headers
|
||||
for (i = basic; i < total; i++) {
|
||||
n = headers[i];
|
||||
h = hashed[n];
|
||||
|
||||
if (h < 0)
|
||||
continue;
|
||||
|
||||
j = h % MC_HASH_SIZE; if (j == -0) j = 0;
|
||||
|
||||
for (; j in header_hash;) {
|
||||
if (++j == MC_HASH_SIZE) {
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
header_hash[j] = n;
|
||||
index_hash[j] = i;
|
||||
}
|
||||
|
||||
if (basic < total) {
|
||||
m = module "_ext_mclass";
|
||||
s = "_e_" module "_s";
|
||||
print_parser_table(s, "static", m, without_experimental, total);
|
||||
}
|
||||
|
||||
printf("msg_mclass_t const * %s_extended_mclass = %s;\n\n", module, m) > PT;
|
||||
|
||||
}
|
||||
|
||||
if (basic < total) {
|
||||
printf("msg_hclass_t * const %s_extensions[] = {\n", module) > PT;
|
||||
for (i = basic; i < total; i++) {
|
||||
if (i == without_experimental) {
|
||||
print "#if SU_HAVE_EXPERIMENTAL" > PT;
|
||||
}
|
||||
|
||||
if (Since[n]) {
|
||||
printf(" { %s_%s_class,\n" \
|
||||
" msg_offsetof(struct %s, extra[%u])%s }%s\n",
|
||||
tprefix, n, extra_struct, Extra[n], flags, c) > PT;
|
||||
}
|
||||
else {
|
||||
printf(" { %s_%s_class, msg_offsetof(%s_t, %s_%s)%s }%s\n",
|
||||
tprefix, n, module, prefix, n, flags, c) > PT;
|
||||
}
|
||||
|
||||
if (experimental2[i]) {
|
||||
printf("#else\n { NULL, 0 }%s\n#endif\n", c) > PT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf(" { NULL, 0 }%s\n", c) > PT;
|
||||
}
|
||||
printf(" %s_%s_class,\n", module, headers[i]) > PT;
|
||||
}
|
||||
if (total != without_experimental)
|
||||
print "#endif" > PT;
|
||||
print " NULL\n};\n\n" > PT;
|
||||
}
|
||||
printf(" }\n}};\n\n") > PT;
|
||||
}
|
||||
|
||||
exit success;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file nea_event.c
|
||||
* @brief Default MIME type for certain events.
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file nea_server.c
|
||||
/**@internal @file nea_server.c
|
||||
* @brief Nokia Event API - event notifier implementation.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
@ -65,7 +65,7 @@
|
|||
/** Number of primary views (with different MIME type or content) */
|
||||
#define NEA_VIEW_MAX (8)
|
||||
|
||||
/** Server object, created for every notifier.
|
||||
/** @internal Server object, created for every notifier.
|
||||
*/
|
||||
struct nea_server_s {
|
||||
su_home_t nes_home[1];
|
||||
|
@ -112,7 +112,7 @@ struct nea_server_s {
|
|||
};
|
||||
|
||||
|
||||
/** Supported events and their subscribers */
|
||||
/** @internal Supported events and their subscribers */
|
||||
struct nea_event_s {
|
||||
nea_event_t *ev_next;
|
||||
nea_event_t **ev_prev;
|
||||
|
@ -141,7 +141,7 @@ struct nea_event_s {
|
|||
|
||||
typedef struct nea_event_queue_s nea_event_queue_t;
|
||||
|
||||
/** Object representing particular view of event */
|
||||
/** @internal Object representing particular view of event */
|
||||
struct nea_event_view_s
|
||||
{
|
||||
nea_event_view_t *evv_next;
|
||||
|
@ -156,7 +156,7 @@ struct nea_event_view_s
|
|||
unsigned evv_reliable:1; /**< Keep all notifications */
|
||||
unsigned:0;
|
||||
|
||||
/** Queued notification */
|
||||
/** @internal Queued notification */
|
||||
struct nea_event_queue_s
|
||||
{
|
||||
nea_event_queue_t *evq_next;
|
||||
|
@ -173,7 +173,7 @@ struct nea_event_view_s
|
|||
#define evv_payload evv_head->evq_payload
|
||||
|
||||
|
||||
/** Subscription object
|
||||
/** @internal Subscription object.
|
||||
*/
|
||||
struct nea_sub_s {
|
||||
nea_sub_t *s_next;
|
||||
|
|
|
@ -4538,7 +4538,7 @@ nta_incoming_t *incoming_create(nta_agent_t *agent,
|
|||
irq->irq_home = home = msg_home(msg_ref_create(msg));
|
||||
irq->irq_agent = agent;
|
||||
|
||||
irq->irq_received = agent_now(agent);
|
||||
irq->irq_received = agent_now(agent); /* Timestamp originally from tport */
|
||||
|
||||
irq->irq_method = method;
|
||||
irq->irq_rq = sip_request_copy(home, sip->sip_request);
|
||||
|
@ -5129,7 +5129,12 @@ nta_incoming_magic_t *nta_incoming_magic(nta_incoming_t *irq,
|
|||
return irq && irq->irq_callback == callback ? irq->irq_magic : NULL;
|
||||
}
|
||||
|
||||
/** When received */
|
||||
/** When received.
|
||||
*
|
||||
* Return timestamp from the reception of the initial request.
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
sip_time_t nta_incoming_received(nta_incoming_t *irq,
|
||||
su_nanotime_t *return_nano)
|
||||
{
|
||||
|
@ -6768,7 +6773,7 @@ unsigned nta_outgoing_delay(nta_outgoing_t const *orq)
|
|||
return orq != NULL && orq != NONE ? orq->orq_delay : UINT_MAX;
|
||||
}
|
||||
|
||||
/** Get the branch parameter. @NEW_1_12_7 */
|
||||
/** 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
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
/** Defined when <nta_internal.h> has been included. */
|
||||
#define NTA_INTERNAL_H
|
||||
|
||||
/**@IFILE nta_internal.h
|
||||
/**@internal @file nta_internal.h
|
||||
*
|
||||
* @brief Internals of NTA objects.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,8 +22,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file portbind.c
|
||||
* @brief bind a socket to an UDP/TCP port and return the port number
|
||||
/**@internal @file portbind.c
|
||||
* @brief Bind a socket to an UDP/TCP port and return the port number
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*
|
||||
|
|
|
@ -63,25 +63,25 @@ typedef struct nta_incoming_s nta_incoming_t;
|
|||
#ifndef NTA_AGENT_MAGIC_T
|
||||
/** Default type of application context for NTA agents.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nta.h>. */
|
||||
* <sofia-sip/nta.h>. */
|
||||
#define NTA_AGENT_MAGIC_T struct nta_agent_magic_s
|
||||
#endif
|
||||
#ifndef NTA_LEG_MAGIC_T
|
||||
/** Default type of application context for NTA call legs.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nta.h>. */
|
||||
* <sofia-sip/nta.h>. */
|
||||
#define NTA_LEG_MAGIC_T struct nta_leg_magic_s
|
||||
#endif
|
||||
#ifndef NTA_OUTGOING_MAGIC_T
|
||||
/** Default type of application context for outgoing NTA requests.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nta.h>. */
|
||||
* <sofia-sip/nta.h>. */
|
||||
#define NTA_OUTGOING_MAGIC_T struct nta_outgoing_magic_s
|
||||
#endif
|
||||
#ifndef NTA_INCOMING_MAGIC_T
|
||||
/** Default type of application context for incoming NTA requests.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nta.h>. */
|
||||
* <sofia-sip/nta.h>. */
|
||||
#define NTA_INCOMING_MAGIC_T struct nta_incoming_magic_s
|
||||
#endif
|
||||
|
||||
|
@ -439,13 +439,13 @@ SOFIAPUBFUN int nta_outgoing_setrseq(nta_outgoing_t *orq, uint32_t rseq);
|
|||
typedef struct nta_reliable_s nta_reliable_t;
|
||||
|
||||
#ifndef NTA_RELIABLE_MAGIC_T
|
||||
/** Default type of application context for reliable NTA responses.
|
||||
/** Default type of application context for reliable preliminary responses.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nta.h>. */
|
||||
* <sofia-sip/nta.h>. */
|
||||
#define NTA_RELIABLE_MAGIC_T struct nta_reliable_magic_s
|
||||
#endif
|
||||
|
||||
/** Application context for reliable NTA requests */
|
||||
/** Application context for reliable preliminary responses. */
|
||||
typedef NTA_RELIABLE_MAGIC_T nta_reliable_magic_t;
|
||||
|
||||
typedef int nta_prack_f(nta_reliable_magic_t *rmagic,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -534,11 +534,11 @@ int api_test_params(agent_t *ag)
|
|||
TEST_1(default_proxy == NULL);
|
||||
TEST_1(smime == NULL);
|
||||
|
||||
TEST_1(blacklist != -1);
|
||||
TEST_1(blacklist != (unsigned)-1);
|
||||
TEST(debug_drop_prob, 0);
|
||||
TEST_1(max_forwards >= 20);
|
||||
TEST_1(maxsize >= 65536);
|
||||
TEST_1(preload != -1);
|
||||
TEST_1(preload != (unsigned)-1);
|
||||
TEST_1(progress <= 60 * 1000);
|
||||
TEST(sip_t1, NTA_SIP_T1);
|
||||
TEST(sip_t2, NTA_SIP_T2);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file nth_server.c
|
||||
/**@internal @file nth_server.c
|
||||
* @brief HTTP server.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
|
@ -50,7 +50,7 @@ typedef struct nth_request_s nth_request_t;
|
|||
#ifndef NTH_CLIENT_MAGIC_T
|
||||
/** Default type of application context for client NTH requests.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nth.h>. */
|
||||
* <sofia-sip/nth.h>. */
|
||||
#define NTH_CLIENT_MAGIC_T struct nth_client_magic_s
|
||||
#endif
|
||||
|
||||
|
@ -60,7 +60,7 @@ typedef NTH_CLIENT_MAGIC_T nth_client_magic_t;
|
|||
#ifndef NTH_SITE_MAGIC_T
|
||||
/** Default type of application context for NTH servers.
|
||||
* Application may define this to appropriate type before including
|
||||
* <nth.h>. */
|
||||
* <sofia-sip/nth.h>. */
|
||||
#define NTH_SITE_MAGIC_T struct nth_site_magic_s
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ ALIASES += NUA_EVENT="@var nua_event_e::"
|
|||
ALIASES += END_NUA_EVENT="@par "
|
||||
|
||||
ALIASES += \
|
||||
NUA_HPARAM_CALLS="nua_invite(), nua_respond(), nua_ack(), nua_prack(), nua_update(), nua_info(), nua_bye(), nua_options(), nua_message(), nua_register(), nua_publish(), nua_refer(),nua_subscribe(), nua_notify(), nua_refer(), nua_notifier()"
|
||||
NUA_HPARAM_CALLS="nua_method(), nua_respond(), nua_invite(), nua_ack(), nua_cancel(), nua_prack(), nua_update(), nua_info(), nua_bye(), nua_options(), nua_message(), nua_register(), nua_unregister(), nua_publish(), nua_refer(), nua_subscribe(), nua_unsubscribe(), nua_notify(), nua_notifier()"
|
||||
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file nua.c High-Level User Agent Library - "nua" Implementation.
|
||||
/**@internal @file nua.c High-Level User Agent Library - "nua" Implementation.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
* @author Kai Vehmanen <Kai.Vehmanen@nokia.com>
|
||||
|
@ -93,19 +93,28 @@ su_log_t nua_log[] = { SU_LOG_INIT("nua", "NUA_DEBUG", SU_DEBUG) };
|
|||
* @param magic Pointer to callback context
|
||||
* @param tag, value, ... List of tagged parameters
|
||||
*
|
||||
* @retval !=NULL a pointer to a @nua stack object \n
|
||||
* @retval !=NULL a pointer to a @nua stack object
|
||||
* @retval NULL upon an error
|
||||
*
|
||||
* @par Related tags:
|
||||
* NUTAG_PROXY() \n
|
||||
* NUTAG_URL() \n
|
||||
* NUTAG_SIPS_URL() \n
|
||||
* NUTAG_SIP_PARSER() \n
|
||||
* NUTAG_CERTIFICATE_DIR() \n
|
||||
* 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
|
||||
* - NUTAG_PROXY(), giving the URI of the outbound proxy
|
||||
* (but see also NUTAG_INITIAL_ROUTE()).
|
||||
* - NUTAG_URL() (and NUTAG_SIPS_URL(), listing URIs describing
|
||||
* transports)
|
||||
* - NUTAG_CERTIFICATE_DIR(), specifying the location of the
|
||||
* root and client/server certificate files
|
||||
* - NUTAG_SIP_PARSER(), providing customized parser used to
|
||||
* parse received SIP messages
|
||||
* - All parameter tags, listed with nua_set_params()
|
||||
* - All NTATAG_* are passed to NTA documented in <sofia-sip/nta_tag.h>:
|
||||
* see NTATAG_EXTRA_100(),
|
||||
* - All tport tags are passed to tport.
|
||||
* They are documented in <sofia-sip/tport_tag.h>
|
||||
* - All SOATAG_* are passed to the default SOA (media session) object which
|
||||
* is created by nua_create() unless NUTAG_MEDIA_ENABLE(0) is included in
|
||||
* the tag list
|
||||
* - STUN tags STUNTAG_DOMAIN(), STUNTAG_SERVER().
|
||||
* STUN is deprecated, however.
|
||||
*
|
||||
* @note
|
||||
* From the @VERSION_1_12_2 all the nua_set_params() tags are processed.
|
||||
|
@ -186,6 +195,13 @@ void nua_shutdown(nua_t *nua)
|
|||
nua_signal(nua, NULL, NULL, 1, nua_r_shutdown, 0, NULL, TAG_END());
|
||||
}
|
||||
|
||||
/** @internal Linked stack frames from nua event callback */
|
||||
struct nua_event_frame_s {
|
||||
nua_event_frame_t *nf_next;
|
||||
nua_t *nf_nua;
|
||||
nua_saved_event_t nf_saved[1];
|
||||
};
|
||||
|
||||
/** Destroy the @nua stack.
|
||||
*
|
||||
* Before calling nua_destroy() the application
|
||||
|
@ -211,6 +227,8 @@ void nua_destroy(nua_t *nua)
|
|||
enter;
|
||||
|
||||
if (nua) {
|
||||
nua_event_frame_t *nf;
|
||||
|
||||
if (!nua->nua_shutdown_final) {
|
||||
SU_DEBUG_0(("nua_destroy(%p): FATAL: nua_shutdown not completed\n",
|
||||
(void *)nua));
|
||||
|
@ -218,6 +236,13 @@ void nua_destroy(nua_t *nua)
|
|||
return;
|
||||
}
|
||||
|
||||
nua->nua_callback = NULL;
|
||||
|
||||
for (nf = nua->nua_current; nf; nf = nf->nf_next) {
|
||||
nf->nf_nua = NULL;
|
||||
}
|
||||
nua->nua_current = NULL;
|
||||
|
||||
su_task_deinit(nua->nua_server);
|
||||
su_task_deinit(nua->nua_client);
|
||||
|
||||
|
@ -975,9 +1000,10 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e)
|
|||
{
|
||||
nua_t *nua;
|
||||
nua_handle_t *nh = e->e_nh;
|
||||
|
||||
enter;
|
||||
|
||||
e->e_nh = NULL;
|
||||
|
||||
if (nh) {
|
||||
if (!nh->nh_ref_by_user && nh->nh_valid) {
|
||||
nh->nh_ref_by_user = 1;
|
||||
|
@ -1004,40 +1030,40 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e)
|
|||
|
||||
nua = nh->nh_nua; assert(nua);
|
||||
|
||||
if (e->e_event == nua_r_shutdown && e->e_status >= 200)
|
||||
nua->nua_shutdown_final = 1;
|
||||
|
||||
if (!nua->nua_callback)
|
||||
return;
|
||||
|
||||
if (NH_IS_DEFAULT(nh))
|
||||
nh = NULL;
|
||||
|
||||
su_msg_save(nua->nua_current, sumsg);
|
||||
if (e->e_event == nua_r_shutdown && e->e_status >= 200)
|
||||
nua->nua_shutdown_final = 1;
|
||||
|
||||
e->e_nh = NULL;
|
||||
if (nua->nua_callback) {
|
||||
nua_event_frame_t frame[1];
|
||||
|
||||
su_msg_remove_refs(sumsg); /* Remove references to tasks */
|
||||
su_msg_save(frame->nf_saved, sumsg);
|
||||
frame->nf_nua = nua;
|
||||
frame->nf_next = nua->nua_current, nua->nua_current = frame;
|
||||
|
||||
nua->nua_callback(e->e_event, e->e_status, e->e_phrase,
|
||||
nua, nua->nua_magic,
|
||||
nh, nh ? nh->nh_magic : NULL,
|
||||
e->e_msg ? sip_object(e->e_msg) : NULL,
|
||||
e->e_tags);
|
||||
nua->nua_callback(e->e_event, e->e_status, e->e_phrase,
|
||||
nua, nua->nua_magic,
|
||||
nh, nh ? nh->nh_magic : NULL,
|
||||
e->e_msg ? sip_object(e->e_msg) : NULL,
|
||||
e->e_tags);
|
||||
|
||||
if (nh && !NH_IS_DEFAULT(nh) && nua_handle_unref(nh)) {
|
||||
su_msg_destroy(frame->nf_saved);
|
||||
|
||||
if (frame->nf_nua == NULL)
|
||||
return;
|
||||
nua->nua_current = frame->nf_next;
|
||||
}
|
||||
|
||||
if (nh && nua_handle_unref(nh)) {
|
||||
#if HAVE_NUA_HANDLE_DEBUG
|
||||
SU_DEBUG_0(("nua(%p): freed by application\n", (void *)nh));
|
||||
#else
|
||||
SU_DEBUG_9(("nua(%p): freed by application\n", (void *)nh));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!su_msg_is_non_null(nua->nua_current))
|
||||
return;
|
||||
|
||||
if (e->e_msg)
|
||||
msg_destroy(e->e_msg), e->e_msg = NULL;
|
||||
|
||||
su_msg_destroy(nua->nua_current);
|
||||
}
|
||||
|
||||
/** Get current request message. @NEW_1_12_4.
|
||||
|
@ -1048,7 +1074,9 @@ void nua_event(nua_t *root_magic, su_msg_r sumsg, event_t *e)
|
|||
*/
|
||||
msg_t *nua_current_request(nua_t const *nua)
|
||||
{
|
||||
return nua && nua->nua_current ? su_msg_data(nua->nua_current)->e_msg : NULL;
|
||||
if (nua && nua->nua_current && su_msg_is_non_null(nua->nua_current->nf_saved))
|
||||
return su_msg_data(nua->nua_current->nf_saved)->e_msg;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Get request message from saved nua event. @NEW_1_12_4.
|
||||
|
@ -1066,14 +1094,15 @@ msg_t *nua_saved_event_request(nua_saved_event_t const *saved)
|
|||
*/
|
||||
int nua_save_event(nua_t *nua, nua_saved_event_t return_saved[1])
|
||||
{
|
||||
if (nua && return_saved) {
|
||||
su_msg_save(return_saved, nua->nua_current);
|
||||
if (su_msg_is_non_null(return_saved)) {
|
||||
/* Remove references to tasks */
|
||||
su_msg_remove_refs(return_saved);
|
||||
return 1;
|
||||
if (return_saved) {
|
||||
if (nua && nua->nua_current) {
|
||||
su_msg_save(return_saved, nua->nua_current->nf_saved);
|
||||
return su_msg_is_non_null(return_saved);
|
||||
}
|
||||
else
|
||||
*return_saved = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ char const *nua_generate_instance_identifier(su_home_t *home)
|
|||
*
|
||||
* @sa nua_respond(), #nua_event_e, #nua_event_t, nua_event_name()
|
||||
*
|
||||
* @NEW_1_12_6
|
||||
* @NEW_1_12_6.
|
||||
*/
|
||||
int nua_event_is_incoming_request(nua_event_t event)
|
||||
{
|
||||
|
|
|
@ -80,7 +80,7 @@ typedef struct {
|
|||
|
||||
} nua_server_methods_t;
|
||||
|
||||
/** Server side transaction */
|
||||
/* Server side transaction */
|
||||
struct nua_server_request {
|
||||
struct nua_server_request *sr_next, **sr_prev;
|
||||
|
||||
|
@ -147,7 +147,7 @@ int sr_status(nua_server_request_t *sr, int status, char const *phrase)
|
|||
return (void)(sr->sr_phrase = phrase), (sr->sr_status = status);
|
||||
}
|
||||
|
||||
/** Methods for client request */
|
||||
/* Methods for client request. @internal */
|
||||
typedef struct {
|
||||
sip_method_t crm_method;
|
||||
char const *crm_method_name;
|
||||
|
@ -367,7 +367,7 @@ struct nua_dialog_state
|
|||
} ds_remote_ua[1];
|
||||
};
|
||||
|
||||
/** Virtual function pointer table for dialog usage. */
|
||||
/* Virtual function pointer table for dialog usage. */
|
||||
typedef struct {
|
||||
unsigned usage_size, usage_class_size;
|
||||
int (*usage_add)(nua_owner_t *,
|
||||
|
@ -387,7 +387,7 @@ typedef struct {
|
|||
} nua_usage_class;
|
||||
|
||||
|
||||
/** Base structure for dialog usage. */
|
||||
/* Base structure for dialog usage. */
|
||||
struct nua_dialog_usage {
|
||||
nua_dialog_usage_t *du_next;
|
||||
nua_usage_class const *du_class;
|
||||
|
|
|
@ -79,7 +79,7 @@ nua_stack_notifier(nua_t *nua, nua_handle_t *nh, nua_event_t e, tagi_t const *ta
|
|||
int status = 900;
|
||||
char const *phrase = nua_internal_error;
|
||||
|
||||
nua_stack_init_handle(nua, nh, TAG_NEXT(tags));
|
||||
nua_stack_init_handle(nua, nh, tags);
|
||||
|
||||
tl_gets(tags,
|
||||
NUTAG_URL_REF(url),
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* @date Created: Wed Mar 8 11:38:18 EET 2006 ppessi
|
||||
*/
|
||||
|
||||
/** NUA preferences.
|
||||
/**@internal @brief NUA preferences.
|
||||
*
|
||||
* This structure contains values for various preferences and a separate
|
||||
* bitmap (nhp_set) for each preference. Preferences are set using
|
||||
|
|
|
@ -116,7 +116,7 @@ static int nua_register_usage_shutdown(nua_handle_t *,
|
|||
nua_dialog_state_t *,
|
||||
nua_dialog_usage_t *);
|
||||
|
||||
/** REGISTER usage, aka nua_registration_t */
|
||||
/** @internal @brief REGISTER usage, aka nua_registration_t. */
|
||||
struct register_usage {
|
||||
nua_registration_t *nr_next, **nr_prev, **nr_list; /* Doubly linked list and its head */
|
||||
sip_from_t *nr_aor; /**< AoR for this registration, NULL if none */
|
||||
|
@ -293,7 +293,7 @@ outbound_owner_vtable nua_stack_outbound_callbacks = {
|
|||
* @par Related tags:
|
||||
* NUTAG_REGISTRAR(), NUTAG_INSTANCE(), NUTAG_OUTBOUND(),
|
||||
* NUTAG_KEEPALIVE(), NUTAG_KEEPALIVE_STREAM(), NUTAG_M_USERNAME(),
|
||||
* NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES(),
|
||||
* NUTAG_M_DISPLAY(), NUTAG_M_PARAMS(), NUTAG_M_FEATURES()
|
||||
*
|
||||
* @par Events:
|
||||
* #nua_r_register, #nua_i_outbound
|
||||
|
|
|
@ -57,9 +57,15 @@
|
|||
* Incoming REGISTER request.
|
||||
*
|
||||
* In order to receive #nua_i_register events, the application must enable
|
||||
* the REGISTER method with NUTAG_ALLOW() tag.
|
||||
* the REGISTER method with NUTAG_ALLOW() tag, e.g.,
|
||||
* @verbatim
|
||||
* nua_set_params(nua;
|
||||
* NUTAG_APPL_METHOD("REGISTER"),
|
||||
* NUTAG_ALLOW("REGISTER"),
|
||||
* TAG_END());
|
||||
* @endverbatim
|
||||
*
|
||||
* The nua_response() call responding to a REGISTER request must have
|
||||
* The nua_response() call responding to a REGISTER request must include
|
||||
* NUTAG_WITH() (or NUTAG_WITH_THIS()/NUTAG_WITH_SAVED()) tag. Note that
|
||||
* a successful response to REGISTER @b MUST include the @Contact header
|
||||
* bound to the the AoR URI (in @To header).
|
||||
|
|
|
@ -137,7 +137,7 @@ sip_response_terminates_dialog().
|
|||
/* ---------------------------------------------------------------------- */
|
||||
/* Session event usage */
|
||||
|
||||
/** Session-related state */
|
||||
/** @internal @brief Session-related state. */
|
||||
typedef struct nua_session_usage
|
||||
{
|
||||
enum nua_callstate ss_state; /**< Session status (enum nua_callstate) */
|
||||
|
@ -1591,7 +1591,11 @@ static int nua_prack_client_request(nua_client_request_t *cr,
|
|||
else if (answer_sent)
|
||||
ss->ss_oa_sent = Answer;
|
||||
|
||||
if (!cr->cr_restarting) /* Restart logic calls nua_prack_client_report */
|
||||
if (cr->cr_restarting)
|
||||
/* Restart logic calls nua_prack_client_report */;
|
||||
else if (!cr->cr_auto && (!offer_sent || !answer_sent))
|
||||
/* Suppose application know it called nua_prack() */;
|
||||
else
|
||||
signal_call_state_change(nh, ss, status, phrase, ss->ss_state);
|
||||
}
|
||||
|
||||
|
|
|
@ -414,6 +414,9 @@ void nua_stack_signal(nua_t *nua, su_msg_r msg, nua_event_data_t *e)
|
|||
case nua_r_info:
|
||||
error = nua_stack_info(nua, nh, event, tags);
|
||||
break;
|
||||
case nua_r_prack:
|
||||
error = nua_stack_prack(nua, nh, event, tags);
|
||||
break;
|
||||
case nua_r_update:
|
||||
error = nua_stack_update(nua, nh, event, tags);
|
||||
break;
|
||||
|
@ -754,10 +757,8 @@ void nh_destroy(nua_t *nua, nua_handle_t *nh)
|
|||
* @retval -1 upon an error
|
||||
* @retval 0 when successful
|
||||
*/
|
||||
int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
|
||||
tag_type_t tag, tag_value_t value, ...)
|
||||
int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags)
|
||||
{
|
||||
ta_list ta;
|
||||
int retval = 0;
|
||||
|
||||
if (nh == NULL)
|
||||
|
@ -765,13 +766,9 @@ int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
|
|||
|
||||
assert(nh != nua->nua_dhandle);
|
||||
|
||||
ta_start(ta, tag, value);
|
||||
|
||||
if (nua_stack_set_params(nua, nh, nua_i_error, ta_args(ta)) < 0)
|
||||
if (nua_stack_set_params(nua, nh, nua_i_error, tags) < 0)
|
||||
retval = -1;
|
||||
|
||||
ta_end(ta);
|
||||
|
||||
if (retval || nh->nh_init) /* Already initialized? */
|
||||
return retval;
|
||||
|
||||
|
@ -814,7 +811,7 @@ nua_handle_t *nua_stack_incoming_handle(nua_t *nua,
|
|||
SIPTAG_FROM(from), /* Remote AoR */
|
||||
TAG_END());
|
||||
|
||||
if (nua_stack_init_handle(nh->nh_nua, nh, TAG_END()) < 0)
|
||||
if (nua_stack_init_handle(nh->nh_nua, nh, NULL) < 0)
|
||||
nh_destroy(nua, nh), nh = NULL;
|
||||
|
||||
if (nh && create_dialog) {
|
||||
|
@ -1672,7 +1669,9 @@ int nua_base_server_report(nua_server_request_t *sr, tagi_t const *tags)
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** @class nua_client_request
|
||||
/**@internal
|
||||
*
|
||||
* @class nua_client_request
|
||||
*
|
||||
* Each handle has a queue of client-side requests; if a request is pending,
|
||||
* a new request from API is added to the queue. After the request is
|
||||
|
@ -1944,7 +1943,7 @@ int nua_client_init_request(nua_client_request_t *cr)
|
|||
cr->cr_offer_recv = 0, cr->cr_answer_sent = 0;
|
||||
cr->cr_terminated = 0, cr->cr_graceful = 0;
|
||||
|
||||
nua_stack_init_handle(nua, nh, TAG_NEXT(cr->cr_tags));
|
||||
nua_stack_init_handle(nua, nh, cr->cr_tags);
|
||||
|
||||
if (cr->cr_method == sip_method_cancel) {
|
||||
if (cr->cr_methods->crm_init) {
|
||||
|
|
|
@ -129,7 +129,7 @@ su_inline int nua_handle_unref_by(nua_handle_t *nh, char const *by)
|
|||
|
||||
#endif
|
||||
|
||||
/** NUA handle.
|
||||
/** @internal @brief NUA handle.
|
||||
*
|
||||
*/
|
||||
struct nua_handle_s
|
||||
|
@ -197,6 +197,8 @@ int nh_is_special(nua_handle_t *nh)
|
|||
return nh == NULL || nh->nh_special;
|
||||
}
|
||||
|
||||
typedef struct nua_event_frame_s nua_event_frame_t;
|
||||
|
||||
extern char const nua_internal_error[];
|
||||
|
||||
#define NUA_INTERNAL_ERROR 900, nua_internal_error
|
||||
|
@ -214,7 +216,7 @@ struct nua_s {
|
|||
nua_callback_f nua_callback;
|
||||
nua_magic_t *nua_magic;
|
||||
|
||||
nua_saved_event_t nua_current[1];
|
||||
nua_event_frame_t *nua_current;
|
||||
nua_saved_event_t nua_signal[1];
|
||||
|
||||
/* Engine state flags */
|
||||
|
@ -307,7 +309,8 @@ nua_stack_signal_handler
|
|||
nua_stack_set_params, nua_stack_get_params,
|
||||
nua_stack_register,
|
||||
nua_stack_invite, nua_stack_ack, nua_stack_cancel,
|
||||
nua_stack_bye, nua_stack_info, nua_stack_update,
|
||||
nua_stack_bye, nua_stack_info, nua_stack_update,
|
||||
nua_stack_prack,
|
||||
nua_stack_options, nua_stack_publish, nua_stack_message,
|
||||
nua_stack_subscribe, nua_stack_notify, nua_stack_refer,
|
||||
nua_stack_method;
|
||||
|
@ -336,8 +339,7 @@ nua_handle_t *nua_stack_incoming_handle(nua_t *nua,
|
|||
sip_t const *sip,
|
||||
int create_dialog);
|
||||
|
||||
int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh,
|
||||
tag_type_t tag, tag_value_t value, ...);
|
||||
int nua_stack_init_handle(nua_t *nua, nua_handle_t *nh, tagi_t const *tags);
|
||||
|
||||
enum nh_kind {
|
||||
nh_has_nothing,
|
||||
|
|
|
@ -737,7 +737,10 @@ int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags)
|
|||
* #nua_i_notify
|
||||
*
|
||||
* @sa #nua_r_refer, NUTAG_SUBSTATE(), NUTAG_REFER_EVENT(),#nua_i_refer,
|
||||
* @RFC3515, @ReferTo, @RFC3892, @ReferredBy
|
||||
* @RFC3515, @ReferTo, SIPTAG_REFER_TO(), SIPTAG_REFER_TO_STR(),
|
||||
* @RFC3892, @ReferredBy, SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR(),
|
||||
* @RFC3891, @Replaces, SIPTAG_REPLACES(), SIPTAG_REPLACES_STR(),
|
||||
* @RFC4488, @ReferSub, SIPTAG_REFER_SUB(), SIPTAG_REFER_SUB_STR()
|
||||
*/
|
||||
|
||||
/**@NUA_EVENT nua_r_refer
|
||||
|
@ -758,7 +761,7 @@ int nua_notify_server_report(nua_server_request_t *sr, tagi_t const *tags)
|
|||
* NUTAG_SUBSTATE()
|
||||
*
|
||||
* @sa nua_refer(), NUTAG_SUBSTATE(), #nua_i_refer,
|
||||
* @RFC3515, @ReferTo, @RFC3892, @ReferredBy
|
||||
* @RFC3515, @RFC4488, @ReferSub
|
||||
*
|
||||
* @END_NUA_EVENT
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -863,11 +863,20 @@ static int response_to_keepalive_options(outbound_t *ob,
|
|||
loglevel = 1; /* XXX ... for now */
|
||||
|
||||
if (loglevel >= SU_LOG->log_level) {
|
||||
su_llog(SU_LOG, loglevel,
|
||||
"outbound(%p): %s <" URL_PRINT_FORMAT ">\n",
|
||||
(void *)ob->ob_owner,
|
||||
failed ? "FAILED to validate" : "validated",
|
||||
URL_PRINT_ARGS(ob->ob_rcontact->m_url));
|
||||
sip_contact_t const *m = ob->ob_rcontact;
|
||||
|
||||
if (m)
|
||||
su_llog(SU_LOG, loglevel,
|
||||
"outbound(%p): %s <" URL_PRINT_FORMAT ">\n",
|
||||
(void *)ob->ob_owner,
|
||||
failed ? "FAILED to validate" : "validated",
|
||||
URL_PRINT_ARGS(m->m_url));
|
||||
else
|
||||
su_llog(SU_LOG, loglevel,
|
||||
"outbound(%p): %s registration\n",
|
||||
(void *)ob->ob_owner,
|
||||
failed ? "FAILED to validate" : "validated");
|
||||
|
||||
if (failed)
|
||||
su_llog(SU_LOG, loglevel, "outbound(%p): FAILED with %u %s\n",
|
||||
(void *)ob->ob_owner, status, phrase);
|
||||
|
@ -1101,6 +1110,8 @@ int outbound_set_contact(outbound_t *ob,
|
|||
previous = ob->ob_rcontact;
|
||||
}
|
||||
else if (application_contact) {
|
||||
rcontact = sip_contact_dup(home, application_contact);
|
||||
|
||||
if (!ob->ob_rcontact ||
|
||||
url_cmp_all(ob->ob_rcontact->m_url, application_contact->m_url)) {
|
||||
contact_uri_changed = 1;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -550,6 +550,7 @@ int ringing_pracked(CONDITION_PARAMS)
|
|||
}
|
||||
|
||||
int respond_483_to_prack(CONDITION_PARAMS);
|
||||
static int prack_100rel(CONDITION_PARAMS);
|
||||
|
||||
int test_183rel(struct context *ctx)
|
||||
{
|
||||
|
@ -681,13 +682,14 @@ int test_183rel(struct context *ctx)
|
|||
if (print_headings)
|
||||
printf("TEST NUA-10.2.2: graceful termination because PRACK fails\n");
|
||||
|
||||
nua_set_hparams(a_call->nh, NUTAG_APPL_METHOD("PRACK"), TAG_END());
|
||||
nua_set_hparams(b_call->nh, NUTAG_APPL_METHOD("PRACK"),
|
||||
NUTAG_AUTOANSWER(0), TAG_END());
|
||||
run_b_until(ctx, nua_r_set_params, NULL);
|
||||
run_ab_until(ctx, nua_r_set_params, NULL, nua_r_set_params, NULL);
|
||||
|
||||
INVITE(a, a_call, a_call->nh, TAG_END());
|
||||
|
||||
run_ab_until(ctx, -1, until_terminated, -1, respond_483_to_prack);
|
||||
run_ab_until(ctx, -1, prack_100rel, -1, respond_483_to_prack);
|
||||
|
||||
/* Client transitions:
|
||||
INIT -(C1)-> CALLING: nua_invite(), nua_i_state
|
||||
|
@ -790,6 +792,29 @@ int test_183rel(struct context *ctx)
|
|||
END();
|
||||
}
|
||||
|
||||
static int prack_100rel(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_r_invite && 100 < status && status < 200 &&
|
||||
sip_has_feature(sip->sip_require, "100rel")) {
|
||||
sip_rack_t rack[1];
|
||||
|
||||
sip_rack_init(rack);
|
||||
rack->ra_response = sip->sip_rseq->rs_response;
|
||||
rack->ra_cseq = sip->sip_cseq->cs_seq;
|
||||
rack->ra_method = sip->sip_cseq->cs_method;
|
||||
rack->ra_method_name = sip->sip_cseq->cs_method_name;
|
||||
|
||||
nua_prack(nh, SIPTAG_RACK(rack), TAG_END());
|
||||
}
|
||||
|
||||
return event == nua_i_state && callstate(tags) == nua_callstate_terminated;
|
||||
}
|
||||
|
||||
int respond_483_to_prack(CONDITION_PARAMS)
|
||||
{
|
||||
if (!(check_handle(ep, call, nh, SIP_500_INTERNAL_SERVER_ERROR)))
|
||||
|
|
|
@ -338,6 +338,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
retval |= test_nua_params(ctx); SINGLE_FAILURE_CHECK();
|
||||
|
||||
retval |= test_nua_destroy(ctx); SINGLE_FAILURE_CHECK();
|
||||
|
||||
retval |= test_nua_init(ctx, o_iproxy, o_proxy, o_inat,
|
||||
TESTNATTAG_SYMMETRIC(o_inat_symmetric),
|
||||
TESTNATTAG_LOGGING(o_inat_logging),
|
||||
|
|
|
@ -327,6 +327,7 @@ int test_nua_init(struct context *ctx,
|
|||
int test_deinit(struct context *ctx);
|
||||
|
||||
int test_nua_api_errors(struct context *ctx);
|
||||
int test_nua_destroy(struct context *ctx);
|
||||
int test_stack_errors(struct context *ctx);
|
||||
int test_tag_filter(void);
|
||||
int test_nua_params(struct context *ctx);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include "test_nua.h"
|
||||
#include "sofia-sip/tport_tag.h"
|
||||
|
||||
#if HAVE_FUNC
|
||||
#elif HAVE_FUNCTION
|
||||
|
@ -71,9 +72,9 @@ int test_nua_api_errors(struct context *ctx)
|
|||
TEST(status, 200); TEST_S(phrase, sip_200_OK);
|
||||
|
||||
su_log_init(nua_log);
|
||||
level = nua_log->log_level;
|
||||
if (!(tstflags & tst_verbatim))
|
||||
su_log_set_level(nua_log, 0); /* Log at level 0 by default */
|
||||
level = nua_log->log_level;
|
||||
|
||||
TEST_1(!nua_create(NULL, NULL, NULL, TAG_END()));
|
||||
TEST_VOID(nua_shutdown(NULL));
|
||||
|
@ -142,6 +143,61 @@ int test_nua_api_errors(struct context *ctx)
|
|||
|
||||
/* ======================================================================== */
|
||||
|
||||
void destroy_callback(nua_event_t event,
|
||||
int status, char const *phrase,
|
||||
nua_t *nua, struct context *ctx,
|
||||
nua_handle_t *nh, struct call *call,
|
||||
sip_t const *sip,
|
||||
tagi_t tags[])
|
||||
{
|
||||
if (status >= 200) {
|
||||
nua_destroy(ctx->a.nua), ctx->a.nua = NULL;
|
||||
su_root_break(ctx->root);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test different nua_destroy() corner cases */
|
||||
int test_nua_destroy(struct context *ctx)
|
||||
{
|
||||
BEGIN();
|
||||
|
||||
struct endpoint *a = &ctx->a;
|
||||
|
||||
TEST_1(ctx->root = su_root_create(NULL));
|
||||
|
||||
#if 0
|
||||
a->nua = nua_create(ctx->root, destroy_callback, ctx,
|
||||
NUTAG_URL("sip:0.0.0.0:*"),
|
||||
TAG_IF(ctx->a.logging, TPTAG_LOG(1)),
|
||||
TAG_END());
|
||||
TEST_1(a->nua);
|
||||
|
||||
nua_get_params(a->nua, TAG_ANY(), TAG_END());
|
||||
|
||||
su_root_run(ctx->root);
|
||||
|
||||
TEST_1(a->nua == NULL);
|
||||
#endif
|
||||
|
||||
a->nua = nua_create(ctx->root, destroy_callback, ctx,
|
||||
NUTAG_URL("sip:0.0.0.0:*"),
|
||||
TAG_IF(ctx->a.logging, TPTAG_LOG(1)),
|
||||
TAG_END());
|
||||
TEST_1(a->nua);
|
||||
|
||||
nua_shutdown(a->nua);
|
||||
|
||||
su_root_run(ctx->root);
|
||||
|
||||
TEST_1(a->nua == NULL);
|
||||
|
||||
su_root_destroy(ctx->root), ctx->root = NULL;
|
||||
|
||||
END();
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
int test_stack_errors(struct context *ctx)
|
||||
{
|
||||
BEGIN();
|
||||
|
|
|
@ -299,7 +299,7 @@ int test_nua_params(struct context *ctx)
|
|||
sip_organization_t const *organization = NONE;
|
||||
char const *organization_str = "NONE";
|
||||
|
||||
sip_route_t *initial_route = NONE;
|
||||
sip_route_t const *initial_route = NONE;
|
||||
char const *initial_route_str = NONE;
|
||||
|
||||
char const *outbound = "NONE";
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file sdp_tag.c
|
||||
* @brief SDP Tags
|
||||
*
|
||||
|
|
|
@ -230,7 +230,7 @@ typedef enum
|
|||
sdp_media_control, /**< Additional conference control */
|
||||
sdp_media_message, /**< Messaging sessions*/
|
||||
sdp_media_image, /**< Image browsing sessions for JPIP, and T.38 */
|
||||
sdp_media_red /**< Redundancy. @NEW_1_12_4 */
|
||||
sdp_media_red /**< Redundancy. @NEW_1_12_4. */
|
||||
} sdp_media_e;
|
||||
|
||||
/** Media transport protocol. */
|
||||
|
@ -241,7 +241,7 @@ typedef enum
|
|||
sdp_proto_udp = 17, /**< Plain UDP */
|
||||
sdp_proto_rtp = 256, /**< RTP/AVP */
|
||||
sdp_proto_srtp = 257, /**< RTP/SAVP */
|
||||
sdp_proto_udptl = 258, /**< UDPTL. @NEW_1_12_4 */
|
||||
sdp_proto_udptl = 258, /**< UDPTL. @NEW_1_12_4. */
|
||||
sdp_proto_tls = 511, /**< TLS over TCP */
|
||||
sdp_proto_any = 512 /**< * wildcard */
|
||||
} sdp_proto_e;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
Description of Adding a SIP Header to Sofia SIP
|
||||
===============================================
|
||||
Adding a SIP Header to Sofia SIP
|
||||
================================
|
||||
|
||||
by Pekka Pessi (2002-08-16, updated 2006-10-03)
|
||||
by Pekka Pessi (2002-08-16, last updated 2007-09-19)
|
||||
|
||||
There are three ways to extend the Sofia SIP parser, including a standard
|
||||
header in sip_t structure, including a standard header in extra headers or
|
||||
putting the extension headers into a separate library.
|
||||
|
||||
Probalem with extending #sip_t is that it breaks binary compatibility.
|
||||
There are two recommended ways to extend the Sofia SIP parser, including a
|
||||
standard header in extra headers or putting the extension headers into a
|
||||
separate library.
|
||||
|
||||
In the text below, we use "Example" header as our example with following
|
||||
ABNF:
|
||||
|
@ -18,30 +16,18 @@ ABNF:
|
|||
IF YOUR HEADER IS A STANDARD ONE
|
||||
--------------------------------
|
||||
|
||||
* In <sip.h>, add:
|
||||
* In <sofia-sip/sip_extra.h>, add:
|
||||
|
||||
- Add typedef to the header structure.
|
||||
|
||||
The typedefs to ordinary headers are in more or less alphabetic
|
||||
order after typedef of sip_unknown_t. You should add a typedef line
|
||||
like this:
|
||||
You should add a typedef line like this:
|
||||
|
||||
typedef struct sip_example_s sip_example_t;
|
||||
|
||||
Note that the typedefs are documented together with the
|
||||
implementation in the .c file.
|
||||
|
||||
- Add field to the sip_t structure (struct sip_s)
|
||||
- Remember to add a comment containing the header name
|
||||
after field for benefit of the AWK script autmatically generating
|
||||
boilerplate functions and macros:
|
||||
sip_example_t *sip_example; /**< Example */
|
||||
- The AWK script msg_parser.awk automatically creates the default
|
||||
prototypes and tags for the newly created header when the entry in
|
||||
sip_t structure is formatted like to the example above.
|
||||
It will complain about mismatches between header name and field name.
|
||||
|
||||
* Add the actual header structure:
|
||||
- Add the actual header structure:
|
||||
|
||||
The header structure would look like below. The first field MUST be a
|
||||
sip_common_t structure, second field MUST be a pointer to next header
|
||||
|
@ -61,6 +47,21 @@ IF YOUR HEADER IS A STANDARD ONE
|
|||
unsigned long ex_value; /**< Value of example. */
|
||||
};
|
||||
|
||||
* Add entry to sip_extra_headers.txt:
|
||||
- In this case:
|
||||
example @NEW_2_0 /* Example header */
|
||||
- The first is the base C name used for functions and types related to
|
||||
the type. The AWK script msg_parser.awk automatically creates the
|
||||
default prototypes and tags for the newly created header. It will
|
||||
complain about mismatches between header name and the base name.
|
||||
|
||||
- If the entry is before #### DEFAULT HEADER LIST ENDS HERE ####
|
||||
the new header is added to the default parser
|
||||
- If after, the new header is added only to the extended parser.
|
||||
|
||||
- The extended parser will be used after call to
|
||||
sip_update_default_mclass(NULL)
|
||||
|
||||
* Write parsing tests for your new headers in torture_sip.c:
|
||||
|
||||
Add all relevant parsing/processing cases you can think of
|
||||
|
@ -86,8 +87,10 @@ IF YOUR HEADER IS A STANDARD ONE
|
|||
* Run "make check" after you are ready. Really.
|
||||
|
||||
|
||||
IF YOUR HEADERS ARE NON-STANDARD
|
||||
--------------------------------
|
||||
IF YOUR HEADERS ARE COMPLETELY NON-STANDARD
|
||||
-------------------------------------------
|
||||
|
||||
* Add a separate library package for them
|
||||
|
||||
- There is an example package sofia-sip-2543.tar.gz, available from
|
||||
sofia-sip.sourceforge.net
|
||||
|
@ -147,6 +150,3 @@ struct sip_example_dummy_structure {
|
|||
|
||||
#endif /** !defined(SIP_EXAMPLE_H) */
|
||||
--->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -148,4 +148,5 @@ sofia-sip/sip_extra.h: ${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA}
|
|||
PACKAGE_VERSION="${PACKAGE_VERSION}" \
|
||||
TEMPLATE1=${srcdir}/sofia-sip/sip_hclasses.h.in \
|
||||
TEMPLATE2=${srcdir}/sofia-sip/sip_protos.h.in \
|
||||
TEMPLATE3=${srcdir}/sofia-sip/sip_tag.h.in \
|
||||
TEMPLATE=${srcdir}/sofia-sip/sip_extra.h.in ${EXTRA}
|
||||
|
|
|
@ -69,4 +69,6 @@ ALIASES += \
|
|||
"ReplyTo=@ref sip_reply_to \"Reply-To\"" \
|
||||
"SuppressBodyIfMatch=@ref sip_suppress_body_if_match \"Suppress-Body-If-Match\"" \
|
||||
"SuppressNotifyIfMatch=@ref sip_suppress_notify_if_match \"Suppress-Notify-If-Match\"" \
|
||||
|
||||
"RemotePartyID=@ref sip_remote_party_id \"Remote-Party-ID\"" \
|
||||
"PAssertedIdentity=@ref sip_p_asserted_identity \"P-Asserted-Identity\"" \
|
||||
"PPreferredIdentity=@ref sip_p_preferred_identity \"P-Preferred-Identity\"" \
|
||||
|
|
|
@ -123,7 +123,7 @@ SIP_HEADER_CLASS(request, NULL, "", rq_common, single_critical, request);
|
|||
/**Parse @ref sip_request "request line" from a a SIP message. */
|
||||
issize_t sip_request_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
sip_request_t *rq = h->sh_request;
|
||||
sip_request_t *rq = (sip_request_t *)h;
|
||||
char *uri, *version;
|
||||
|
||||
if (msg_firstline_d(s, &uri, &version) < 0 || !uri || !version ||
|
||||
|
@ -138,7 +138,7 @@ issize_t sip_request_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|||
/**Encode @ref sip_request "request line" of a a SIP message. */
|
||||
issize_t sip_request_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
sip_request_t const *rq = h->sh_request;
|
||||
sip_request_t const *rq = (sip_request_t *)h;
|
||||
|
||||
return snprintf(b, bsiz, "%s " URL_FORMAT_STRING " %s" CRLF,
|
||||
rq->rq_method_name,
|
||||
|
@ -148,7 +148,7 @@ issize_t sip_request_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|||
|
||||
isize_t sip_request_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_request_t const *rq = h->sh_request;
|
||||
sip_request_t const *rq = (sip_request_t *)h;
|
||||
|
||||
offset += url_xtra(rq->rq_url);
|
||||
if (!rq->rq_method)
|
||||
|
@ -162,8 +162,8 @@ isize_t sip_request_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
char *sip_request_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_request_t *rq = dst->sh_request;
|
||||
sip_request_t const *o = src->sh_request;
|
||||
sip_request_t *rq = (sip_request_t *)dst;
|
||||
sip_request_t const *o = (sip_request_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
URL_DUP(b, end, rq->rq_url, o->rq_url);
|
||||
|
@ -224,7 +224,7 @@ sip_request_t *sip_request_create(su_home_t *home,
|
|||
|
||||
xtra = url_xtra(uri->us_url) + (method ? 0 : strlen(name) + 1);
|
||||
|
||||
rq = sip_header_alloc(home, sip_request_class, xtra)->sh_request;
|
||||
rq = (sip_request_t *)sip_header_alloc(home, sip_request_class, xtra);
|
||||
|
||||
if (rq) {
|
||||
char *b = (char *)(rq + 1), *end = b + xtra;
|
||||
|
@ -298,7 +298,7 @@ SIP_HEADER_CLASS(status, NULL, "", st_common, single_critical, status);
|
|||
/** Parse status line */
|
||||
issize_t sip_status_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
sip_status_t *st = h->sh_status;
|
||||
sip_status_t *st = (sip_status_t *)h;
|
||||
char *status, *phrase;
|
||||
unsigned long code;
|
||||
|
||||
|
@ -315,25 +315,26 @@ issize_t sip_status_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|||
|
||||
issize_t sip_status_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
sip_status_t const *st = (sip_status_t *)h;
|
||||
int status;
|
||||
|
||||
assert(sip_is_status(h));
|
||||
|
||||
status = h->sh_status->st_status;
|
||||
status = st->st_status;
|
||||
|
||||
if (status > 999 || status < 100)
|
||||
status = 0;
|
||||
|
||||
return snprintf(b, bsiz, "%s %03u %s" CRLF,
|
||||
h->sh_status->st_version,
|
||||
st->st_version,
|
||||
status,
|
||||
h->sh_status->st_phrase);
|
||||
st->st_phrase);
|
||||
}
|
||||
|
||||
/** Extra size of a #sip_status_t object. */
|
||||
isize_t sip_status_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_status_t const *st = h->sh_status;
|
||||
sip_status_t const *st = (sip_status_t *)h;
|
||||
offset += sip_version_xtra(st->st_version);
|
||||
offset += MSG_STRING_SIZE(st->st_phrase);
|
||||
return offset;
|
||||
|
@ -343,8 +344,8 @@ isize_t sip_status_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
char *sip_status_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_status_t *st = dst->sh_status;
|
||||
sip_status_t const *o = src->sh_status;
|
||||
sip_status_t *st = (sip_status_t *)dst;
|
||||
sip_status_t const *o = (sip_status_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
sip_version_dup(&b, &st->st_version, o->st_version);
|
||||
|
@ -386,7 +387,7 @@ sip_status_t *sip_status_create(su_home_t *home,
|
|||
if (phrase == NULL && (phrase = sip_status_phrase(status)) == NULL)
|
||||
phrase = "";
|
||||
|
||||
if ((st = sip_header_alloc(home, sip_status_class, 0)->sh_status)) {
|
||||
if ((st = (sip_status_t *)sip_header_alloc(home, sip_status_class, 0))) {
|
||||
st->st_status = status;
|
||||
st->st_phrase = phrase;
|
||||
st->st_version = version ? version : SIP_VERSION_CURRENT;
|
||||
|
@ -452,7 +453,7 @@ sip_payload_t *sip_payload_create(su_home_t *home, void const *data, isize_t len
|
|||
{
|
||||
msg_hclass_t *hc = sip_payload_class;
|
||||
sip_header_t *h = sip_header_alloc(home, hc, len + 1);
|
||||
sip_payload_t *pl = h->sh_payload;
|
||||
sip_payload_t *pl = (sip_payload_t *)h;
|
||||
|
||||
if (pl) {
|
||||
char *b = sip_header_data(h);
|
||||
|
@ -512,8 +513,8 @@ SIP_HEADER_CLASS(separator, NULL, "", sep_common, single, any);
|
|||
*/
|
||||
sip_separator_t *sip_separator_create(su_home_t *home)
|
||||
{
|
||||
sip_separator_t *sep =
|
||||
sip_header_alloc(home, sip_separator_class, 0)->sh_separator;
|
||||
sip_separator_t *sep = (sip_separator_t *)
|
||||
sip_header_alloc(home, sip_separator_class, 0);
|
||||
|
||||
if (sep)
|
||||
strcpy(sep->sep_data, CRLF);
|
||||
|
@ -764,7 +765,7 @@ issize_t sip_name_addr_e(char b[], isize_t bsiz,
|
|||
int flags,
|
||||
char const *display,
|
||||
int brackets, url_t const url[],
|
||||
msg_param_t const params[],
|
||||
msg_param_t const params[],
|
||||
char const *comment)
|
||||
{
|
||||
int const compact = MSG_IS_COMPACT(flags);
|
||||
|
@ -801,6 +802,63 @@ issize_t sip_name_addr_e(char b[], isize_t bsiz,
|
|||
return b - b0;
|
||||
}
|
||||
|
||||
/** Calculate the extra size needed to duplicate a name-addr-params construct.
|
||||
*
|
||||
* @param display display name (may be NULL)
|
||||
* @param addr pointer to URL structure
|
||||
* @param params pointer to parameter list (may be NULL)
|
||||
* @param offset base offset
|
||||
*
|
||||
* @retval Size of duplicated name-addr-params construct, including base offset.
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
isize_t sip_name_addr_xtra(char const *display, url_t const *addr,
|
||||
msg_param_t const params[],
|
||||
isize_t offset)
|
||||
{
|
||||
SIP_PARAMS_SIZE(offset, params);
|
||||
offset += SIP_STRING_SIZE(display);
|
||||
offset += url_xtra(addr);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**Duplicate a name-addr-params construct.
|
||||
*
|
||||
* @param d_display value-result parameter for copied @e name (may be NULL)
|
||||
* @param display display name (may be NULL)
|
||||
* @param d_addr value-result parameter for copied @e address
|
||||
* @param addr pointer to URL address structure
|
||||
* @param d_params value-result parameter for copied parameters (may be NULL)
|
||||
* @param params pointer to parameter list (may be NULL)
|
||||
* @param b pointer to memory pool
|
||||
* @param xtra size of the memory pool
|
||||
*
|
||||
* @retval End of the memory area used.
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
char *sip_name_addr_dup(char const **d_display, char const *display,
|
||||
url_t *d_addr, url_t const *addr,
|
||||
msg_param_t const **d_params, msg_param_t const params[],
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
char *end = b + xtra;
|
||||
|
||||
if (d_params)
|
||||
b = msg_params_dup(d_params, params, b, xtra);
|
||||
|
||||
URL_DUP(b, end, d_addr, addr);
|
||||
|
||||
if (d_display)
|
||||
MSG_STRING_DUP(b, *d_display, display);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/** Parse @To or @From headers */
|
||||
static issize_t sip_addr_d(su_home_t *home,
|
||||
sip_header_t *h,
|
||||
|
@ -851,10 +909,11 @@ isize_t sip_addr_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
{
|
||||
sip_addr_t const *a = (sip_addr_t const *)h;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, a->a_params);
|
||||
offset += MSG_STRING_SIZE(a->a_display);
|
||||
offset += url_xtra(a->a_url);
|
||||
|
||||
return sip_name_addr_xtra(a->a_display,
|
||||
a->a_url,
|
||||
a->a_params,
|
||||
offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
@ -866,15 +925,11 @@ static char *sip_addr_dup_one(sip_header_t *dst, sip_header_t const *src,
|
|||
{
|
||||
sip_addr_t *a = (sip_addr_t *)dst;
|
||||
sip_addr_t const *o = (sip_addr_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&a->a_params, o->a_params, b, xtra);
|
||||
MSG_STRING_DUP(b, a->a_display, o->a_display);
|
||||
URL_DUP(b, end, a->a_url, o->a_url);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
return sip_name_addr_dup(&a->a_display, o->a_display,
|
||||
a->a_url, o->a_url,
|
||||
&a->a_params, o->a_params,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
/** Update parameters in sip_addr_t object */
|
||||
|
@ -905,7 +960,7 @@ sip_addr_make_url(su_home_t *home, msg_hclass_t *hc, url_string_t const *us)
|
|||
h = sip_header_alloc(home, hc, n);
|
||||
|
||||
if (h) {
|
||||
sip_addr_t *a = h->sh_to;
|
||||
sip_addr_t *a = (sip_to_t *)h;
|
||||
char *s2 = sip_header_data(h);
|
||||
|
||||
if ((size_t)url_dup(s2, n, a->a_url, us->us_url) == n)
|
||||
|
@ -997,7 +1052,7 @@ issize_t sip_call_id_d(su_home_t *home,
|
|||
char *s,
|
||||
isize_t slen)
|
||||
{
|
||||
sip_call_id_t *i = h->sh_call_id;
|
||||
sip_call_id_t *i = (sip_call_id_t *)h;
|
||||
|
||||
i->i_id = s; /* XXX - why not sip_word_at_word_d(&s); */
|
||||
i->i_hash = msg_hash_string(s);
|
||||
|
@ -1008,10 +1063,11 @@ issize_t sip_call_id_d(su_home_t *home,
|
|||
|
||||
issize_t sip_call_id_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
size_t n = strlen(h->sh_call_id->i_id);
|
||||
sip_call_id_t const *i = (sip_call_id_t *)h;
|
||||
size_t n = strlen(i->i_id);
|
||||
|
||||
if (bsiz > n)
|
||||
strcpy(b, h->sh_call_id->i_id);
|
||||
strcpy(b, i->i_id);
|
||||
|
||||
return (issize_t)n;
|
||||
}
|
||||
|
@ -1019,7 +1075,7 @@ issize_t sip_call_id_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|||
/** Extra size of a #sip_call_id_t object. */
|
||||
isize_t sip_call_id_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_call_id_t const *i = h->sh_call_id;
|
||||
sip_call_id_t const *i = (sip_call_id_t *)h;
|
||||
return offset + MSG_STRING_SIZE(i->i_id);
|
||||
}
|
||||
|
||||
|
@ -1038,8 +1094,8 @@ isize_t sip_call_id_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
char *sip_call_id_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_call_id_t *i = dst->sh_call_id;
|
||||
sip_call_id_t const *o = src->sh_call_id;
|
||||
sip_call_id_t *i = (sip_call_id_t *)dst;
|
||||
sip_call_id_t const *o = (sip_call_id_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
MSG_STRING_DUP(b, i->i_id, o->i_id);
|
||||
|
@ -1072,7 +1128,7 @@ sip_call_id_t *sip_call_id_create(su_home_t *home, char const *domain)
|
|||
sip_call_id_t *i;
|
||||
size_t xtra = su_guid_strlen + 1 + (domain ? strlen(domain) + 1 : 0);
|
||||
|
||||
i = sip_header_alloc(home, sip_call_id_class, xtra)->sh_call_id;
|
||||
i = (sip_call_id_t *)sip_header_alloc(home, sip_call_id_class, xtra);
|
||||
|
||||
if (i) {
|
||||
char *b;
|
||||
|
@ -1149,7 +1205,7 @@ issize_t sip_cseq_d(su_home_t *home,
|
|||
char *s,
|
||||
isize_t slen)
|
||||
{
|
||||
sip_cseq_t *cs = h->sh_cseq;
|
||||
sip_cseq_t *cs = (sip_cseq_t *)h;
|
||||
|
||||
if (msg_uint32_d(&s, &cs->cs_seq) < 0)
|
||||
return -1;
|
||||
|
@ -1165,17 +1221,16 @@ issize_t sip_cseq_d(su_home_t *home,
|
|||
|
||||
issize_t sip_cseq_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
sip_cseq_t const *cs = (sip_cseq_t *)h;
|
||||
|
||||
assert(sip_is_cseq(h));
|
||||
|
||||
return snprintf(b, bsiz,
|
||||
"%u %s",
|
||||
h->sh_cseq->cs_seq,
|
||||
h->sh_cseq->cs_method_name);
|
||||
return snprintf(b, bsiz, "%u %s", cs->cs_seq, cs->cs_method_name);
|
||||
}
|
||||
|
||||
isize_t sip_cseq_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_cseq_t const *cs = h->sh_cseq;
|
||||
sip_cseq_t const *cs = (sip_cseq_t *)h;
|
||||
if (!cs->cs_method)
|
||||
return offset + MSG_STRING_SIZE(cs->cs_method_name);
|
||||
else
|
||||
|
@ -1185,8 +1240,8 @@ isize_t sip_cseq_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
char *sip_cseq_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_cseq_t *cs = dst->sh_cseq;
|
||||
sip_cseq_t const *o = src->sh_cseq;
|
||||
sip_cseq_t *cs = (sip_cseq_t *)dst;
|
||||
sip_cseq_t const *o = (sip_cseq_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
if (!(cs->cs_method = o->cs_method))
|
||||
|
@ -1241,7 +1296,7 @@ sip_cseq_t *sip_cseq_create(su_home_t *home,
|
|||
|
||||
xtra = (method ? 0 : (strlen(method_name) + 1));
|
||||
|
||||
cs = sip_header_alloc(home, sip_cseq_class, xtra)->sh_cseq;
|
||||
cs = (sip_cseq_t *)sip_header_alloc(home, sip_cseq_class, xtra);
|
||||
|
||||
if (cs) {
|
||||
cs->cs_seq = seq;
|
||||
|
@ -1355,7 +1410,7 @@ issize_t sip_contact_d(su_home_t *home,
|
|||
|
||||
issize_t sip_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
sip_contact_t const *m = h->sh_contact;
|
||||
sip_contact_t const *m = (sip_contact_t *)h;
|
||||
int always_lt_gt = MSG_IS_CANONIC(flags) && m->m_url->url_type != url_any;
|
||||
|
||||
assert(sip_is_contact(h));
|
||||
|
@ -1369,30 +1424,26 @@ issize_t sip_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|||
|
||||
isize_t sip_contact_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_contact_t const *m = h->sh_contact;
|
||||
sip_contact_t const *m = (sip_contact_t *)h;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, m->m_params);
|
||||
offset += MSG_STRING_SIZE(m->m_display);
|
||||
offset += url_xtra(m->m_url);
|
||||
offset += MSG_STRING_SIZE(m->m_comment);
|
||||
|
||||
return offset;
|
||||
return sip_name_addr_xtra(m->m_display,
|
||||
m->m_url,
|
||||
m->m_params,
|
||||
offset)
|
||||
+ MSG_STRING_SIZE(m->m_comment);
|
||||
}
|
||||
|
||||
char *sip_contact_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
char *end = b + xtra;
|
||||
sip_contact_t *m = dst->sh_contact;
|
||||
sip_contact_t const *o = src->sh_contact;
|
||||
sip_contact_t *m = (sip_contact_t *)dst;
|
||||
sip_contact_t const *o = (sip_contact_t *)src;
|
||||
|
||||
b = msg_params_dup(&m->m_params, o->m_params, b, xtra);
|
||||
MSG_STRING_DUP(b, m->m_display, o->m_display);
|
||||
URL_DUP(b, end, m->m_url, o->m_url);
|
||||
b = sip_name_addr_dup(&m->m_display, o->m_display,
|
||||
m->m_url, o->m_url,
|
||||
&m->m_params, o->m_params,
|
||||
b, xtra);
|
||||
MSG_STRING_DUP(b, m->m_comment, o->m_comment);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
@ -1515,8 +1566,8 @@ issize_t sip_content_length_e(char b[], isize_t bsiz, sip_header_t const *h, int
|
|||
*/
|
||||
sip_content_length_t *sip_content_length_create(su_home_t *home, uint32_t n)
|
||||
{
|
||||
sip_content_length_t *l =
|
||||
sip_header_alloc(home, sip_content_length_class, 0)->sh_content_length;
|
||||
sip_content_length_t *l = (sip_content_length_t *)
|
||||
sip_header_alloc(home, sip_content_length_class, 0);
|
||||
|
||||
if (l)
|
||||
l->l_length = n;
|
||||
|
@ -1570,7 +1621,7 @@ SIP_HEADER_CLASS(date, "Date", "", d_common, single, any);
|
|||
|
||||
issize_t sip_date_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
sip_date_t *date = h->sh_date;
|
||||
sip_date_t *date = (sip_date_t *)h;
|
||||
|
||||
if (msg_date_d((char const **)&s, &date->d_time) < 0 || *s)
|
||||
return -1;
|
||||
|
@ -1580,7 +1631,7 @@ issize_t sip_date_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|||
|
||||
issize_t sip_date_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
||||
{
|
||||
sip_date_t const *date = h->sh_date;
|
||||
sip_date_t const *date = (sip_date_t *)h;
|
||||
|
||||
return msg_date_e(b, bsiz, date->d_time);
|
||||
}
|
||||
|
@ -1601,15 +1652,15 @@ issize_t sip_date_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
*/
|
||||
sip_date_t *sip_date_create(su_home_t *home, sip_time_t date)
|
||||
{
|
||||
sip_header_t *h = sip_header_alloc(home, sip_date_class, 0);
|
||||
sip_date_t *d = (sip_date_t *)sip_header_alloc(home, sip_date_class, 0);
|
||||
|
||||
if (h) {
|
||||
if (d) {
|
||||
if (date == 0)
|
||||
date = sip_now();
|
||||
h->sh_date->d_time = date;
|
||||
d->d_time = date;
|
||||
}
|
||||
|
||||
return h->sh_date;
|
||||
return d;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
@ -1651,7 +1702,7 @@ SIP_HEADER_CLASS(expires, "Expires", "", ex_common, single, any);
|
|||
|
||||
issize_t sip_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
sip_expires_t *expires = h->sh_expires;
|
||||
sip_expires_t *expires = (sip_expires_t *)h;
|
||||
|
||||
if (msg_date_delta_d((char const **)&s,
|
||||
&expires->ex_date,
|
||||
|
@ -1663,7 +1714,7 @@ issize_t sip_expires_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|||
|
||||
issize_t sip_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
||||
{
|
||||
sip_expires_t const *expires = h->sh_expires;
|
||||
sip_expires_t const *expires = (sip_expires_t *)h;
|
||||
|
||||
if (expires->ex_date)
|
||||
return msg_date_e(b, bsiz, expires->ex_date + expires->ex_delta);
|
||||
|
@ -1685,12 +1736,13 @@ issize_t sip_expires_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
*/
|
||||
sip_expires_t *sip_expires_create(su_home_t *home, sip_time_t delta)
|
||||
{
|
||||
sip_header_t *h = sip_header_alloc(home, sip_expires_class, 0);
|
||||
sip_expires_t *ex = (sip_expires_t *)
|
||||
sip_header_alloc(home, sip_expires_class, 0);
|
||||
|
||||
if (h)
|
||||
h->sh_expires->ex_delta = delta;
|
||||
if (ex)
|
||||
ex->ex_delta = delta;
|
||||
|
||||
return h->sh_expires;
|
||||
return ex;
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
@ -1955,7 +2007,7 @@ SIP_HEADER_CLASS(retry_after, "Retry-After", "", af_params, single,
|
|||
|
||||
issize_t sip_retry_after_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
||||
{
|
||||
sip_retry_after_t *af = h->sh_retry_after;
|
||||
sip_retry_after_t *af = (sip_retry_after_t *)h;
|
||||
|
||||
if ((msg_delta_d((char const **)&s, &af->af_delta) < 0) ||
|
||||
(*s == '(' && msg_comment_d(&s, &af->af_comment) == -1) ||
|
||||
|
@ -1974,7 +2026,7 @@ issize_t sip_retry_after_d(su_home_t *home, sip_header_t *h, char *s, isize_t sl
|
|||
|
||||
issize_t sip_retry_after_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
||||
{
|
||||
sip_retry_after_t const *af = h->sh_retry_after;
|
||||
sip_retry_after_t const *af = (sip_retry_after_t *)h;
|
||||
int const compact = MSG_IS_COMPACT(f);
|
||||
char *b0 = b, *end = b + bsiz;
|
||||
|
||||
|
@ -2000,7 +2052,7 @@ issize_t sip_retry_after_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
|
||||
isize_t sip_retry_after_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_retry_after_t const *af = h->sh_retry_after;
|
||||
sip_retry_after_t const *af = (sip_retry_after_t *)h;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, af->af_params);
|
||||
offset += MSG_STRING_SIZE(af->af_comment);
|
||||
|
@ -2013,8 +2065,8 @@ char *sip_retry_after_dup_one(sip_header_t *dst,
|
|||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
sip_retry_after_t *af = dst->sh_retry_after;
|
||||
sip_retry_after_t const *o = src->sh_retry_after;
|
||||
sip_retry_after_t *af = (sip_retry_after_t *)dst;
|
||||
sip_retry_after_t const *o = (sip_retry_after_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&af->af_params, o->af_params, b, xtra);
|
||||
|
@ -2072,7 +2124,7 @@ issize_t sip_any_route_d(su_home_t *home,
|
|||
|
||||
issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
sip_route_t const *r = h->sh_route;
|
||||
sip_route_t const *r = (sip_route_t *)h;
|
||||
|
||||
return sip_name_addr_e(b, bsiz, flags,
|
||||
r->r_display, 1, r->r_url, r->r_params, NULL);
|
||||
|
@ -2080,30 +2132,23 @@ issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flag
|
|||
|
||||
isize_t sip_any_route_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_route_t const *r = h->sh_route;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, r->r_params);
|
||||
offset += MSG_STRING_SIZE(r->r_display);
|
||||
offset += url_xtra(r->r_url);
|
||||
|
||||
return offset;
|
||||
sip_route_t const *r = (sip_route_t *)h;
|
||||
return sip_name_addr_xtra(r->r_display,
|
||||
r->r_url,
|
||||
r->r_params,
|
||||
offset);
|
||||
}
|
||||
|
||||
char *sip_any_route_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b,
|
||||
isize_t xtra)
|
||||
{
|
||||
sip_route_t *r = dst->sh_route;
|
||||
sip_route_t const *o = src->sh_route;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&r->r_params, o->r_params, b, xtra);
|
||||
MSG_STRING_DUP(b, r->r_display, o->r_display);
|
||||
URL_DUP(b, end, r->r_url, o->r_url);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
sip_route_t *r = (sip_route_t *)dst;
|
||||
sip_route_t const *o = (sip_route_t *)src;
|
||||
return sip_name_addr_dup(&r->r_display, o->r_display,
|
||||
r->r_url, o->r_url,
|
||||
&r->r_params, o->r_params,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
#define sip_any_route_update NULL
|
||||
|
@ -2149,7 +2194,7 @@ sip_route_t *sip_any_route_create(su_home_t *home,
|
|||
xtra = n_url + n_params + n_addr + (n_params || n_addr);
|
||||
|
||||
h = sip_header_alloc(home, hc, xtra);
|
||||
if ((rr = h->sh_record_route)) {
|
||||
if ((rr = (sip_record_route_t *)h)) {
|
||||
b = sip_header_data(h);
|
||||
n = url_dup(b, n_url, rr->r_url, url);
|
||||
assert(n == n_url);
|
||||
|
@ -2519,7 +2564,7 @@ issize_t sip_via_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
|
|||
issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
||||
{
|
||||
char *b0 = b, *end = b + bsiz;
|
||||
sip_via_t const *v = h->sh_via;
|
||||
sip_via_t const *v = (sip_via_t *)h;
|
||||
|
||||
assert(sip_is_via(h));
|
||||
|
||||
|
@ -2548,7 +2593,7 @@ issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
|
|||
|
||||
isize_t sip_via_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_via_t const *v = h->sh_via;
|
||||
sip_via_t const *v = (sip_via_t *)h;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, v->v_params);
|
||||
offset += sip_transport_xtra(v->v_protocol);
|
||||
|
@ -2563,8 +2608,8 @@ isize_t sip_via_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
char *sip_via_dup_one(sip_header_t *dst, sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_via_t *v = dst->sh_via;
|
||||
sip_via_t const *o = src->sh_via;
|
||||
sip_via_t *v = (sip_via_t *)dst;
|
||||
sip_via_t const *o = (sip_via_t *)src;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&v->v_params, o->v_params, b, xtra);
|
||||
|
@ -2679,7 +2724,7 @@ sip_via_t *sip_via_create(su_home_t *home,
|
|||
via->v_host = host;
|
||||
via->v_port = port;
|
||||
|
||||
v = msg_header_dup_as(home, sip_via_class, (sip_header_t *)via)->sh_via;
|
||||
v = (sip_via_t *)msg_header_dup_as(home, sip_via_class, (sip_header_t *)via);
|
||||
|
||||
if (v) {
|
||||
char const *param;
|
||||
|
|
|
@ -219,7 +219,9 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
*
|
||||
* The parsed Alert-Info header is stored in #sip_alert_info_t structure.
|
||||
*
|
||||
* @NEW_1_12_7
|
||||
* @NEW_1_12_7. In order to use @b Alert-Info header,
|
||||
* initialize the SIP parser with, e.g.,
|
||||
* sip_update_default_mclass(sip_extend_mclass(NULL))
|
||||
*/
|
||||
|
||||
/**@ingroup sip_alert_info
|
||||
|
@ -239,7 +241,7 @@ issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
* };
|
||||
* @endcode
|
||||
*
|
||||
* @NEW_1_12_7
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
|
||||
msg_hclass_t sip_alert_info_class[] =
|
||||
|
@ -276,6 +278,12 @@ issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
|
|||
* @endcode
|
||||
*
|
||||
* The parsed Reply-To header is stored in #sip_reply_to_t structure.
|
||||
*
|
||||
* @sa sip_update_default_mclass()
|
||||
*
|
||||
* @NEW_1_12_7. In order to use @b Reply-To header,
|
||||
* initialize the SIP parser with, e.g.,
|
||||
* sip_update_default_mclass(sip_extend_mclass(NULL)).
|
||||
*/
|
||||
|
||||
/**@ingroup sip_reply_to
|
||||
|
@ -336,11 +344,10 @@ 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;
|
||||
return sip_name_addr_xtra(rplyto->rplyto_display,
|
||||
rplyto->rplyto_url,
|
||||
rplyto->rplyto_params,
|
||||
offset);
|
||||
}
|
||||
|
||||
/**@internal Duplicate one sip_reply_to_t object. */
|
||||
|
@ -349,15 +356,11 @@ static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
|
|||
{
|
||||
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;
|
||||
return sip_name_addr_dup(&rplyto->rplyto_display, o->rplyto_display,
|
||||
rplyto->rplyto_url, o->rplyto_url,
|
||||
&rplyto->rplyto_params, o->rplyto_params,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
@ -889,10 +892,10 @@ isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
|
|||
{
|
||||
sip_call_info_t const *ci = h->sh_call_info;
|
||||
|
||||
MSG_PARAMS_SIZE(offset, ci->ci_params);
|
||||
offset += url_xtra(ci->ci_url);
|
||||
|
||||
return offset;
|
||||
return sip_name_addr_xtra(NULL,
|
||||
ci->ci_url,
|
||||
ci->ci_params,
|
||||
offset);
|
||||
}
|
||||
|
||||
char *sip_info_dup_one(sip_header_t *dst,
|
||||
|
@ -902,14 +905,11 @@ char *sip_info_dup_one(sip_header_t *dst,
|
|||
{
|
||||
sip_call_info_t *ci = dst->sh_call_info;
|
||||
sip_call_info_t const *o = src->sh_call_info;
|
||||
char *end = b + xtra;
|
||||
|
||||
b = msg_params_dup(&ci->ci_params, o->ci_params, b, xtra);
|
||||
URL_DUP(b, end, ci->ci_url, o->ci_url);
|
||||
|
||||
assert(b <= end);
|
||||
|
||||
return b;
|
||||
return sip_name_addr_dup(NULL, NULL,
|
||||
ci->ci_url, o->ci_url,
|
||||
&ci->ci_params, o->ci_params,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
/* ====================================================================== */
|
||||
|
@ -1047,3 +1047,319 @@ issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz,
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SIP_HAVE_REMOTE_PARTY_ID
|
||||
|
||||
/**@SIP_HEADER sip_remote_party_id Remote-Party-ID Header
|
||||
*
|
||||
* The syntax of the Remote-Party-ID header is described as follows:
|
||||
* @code
|
||||
* Remote-Party-ID = "Remote-Party-ID" HCOLON rpid *(COMMA rpid)
|
||||
*
|
||||
* rpid = [display-name] LAQUOT addr-spec RAQUOT
|
||||
* *(SEMI rpi-token)
|
||||
*
|
||||
* rpi-token = rpi-screen / rpi-pty-type /
|
||||
* rpi-id-type / rpi-privacy / other-rpi-token
|
||||
*
|
||||
* rpi-screen = "screen" EQUAL ("no" / "yes")
|
||||
*
|
||||
* rpi-pty-type = "party" EQUAL ("calling" / "called" / token)
|
||||
*
|
||||
* rpi-id-type = "id-type" EQUAL ("subscriber" / "user" /
|
||||
* "term" / token)
|
||||
*
|
||||
* rpi-privacy = "privacy" EQUAL
|
||||
* ( rpi-priv-element
|
||||
* / (LDQUOT rpi-priv-element
|
||||
* *(COMMA rpi-priv-element) RDQUOT) )
|
||||
*
|
||||
* rpi-priv-element = ("full" / "name" / "uri" / "off" / token)
|
||||
* ["-" ( "network" / token )]
|
||||
*
|
||||
* other-rpi-token = ["-"] token [EQUAL (token / quoted-string)]
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @sa sip_update_default_mclass(), draft-ietf-sip-privacy-04.txt, @RFC3325
|
||||
*
|
||||
* @NEW_1_12_7. In order to use @b Remote-Party-ID header,
|
||||
* initialize the SIP parser with, e.g.,
|
||||
* sip_update_default_mclass(sip_extend_mclass(NULL)).
|
||||
*/
|
||||
|
||||
/**@ingroup sip_remote_party_id
|
||||
* @typedef typedef struct sip_remote_party_id_s sip_remote_party_id_t;
|
||||
*
|
||||
* The structure #sip_remote_party_id_t contains representation of SIP
|
||||
* @RemotePartyID header.
|
||||
*
|
||||
* The #sip_remote_party_id_t is defined as follows:
|
||||
* @code
|
||||
* typedef struct sip_remote_party_id_s {
|
||||
* sip_common_t rpid_common[1]; // Common fragment info
|
||||
* sip_remote_party_id_t *rpid_next; // Link to next
|
||||
* char const *rpid_display; // Display name
|
||||
* url_t rpid_url[1]; // URL
|
||||
* sip_param_t const *rpid_params; // Parameters
|
||||
* // Shortcuts to screen, party, id-type and privacy parameters
|
||||
* char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy;
|
||||
* } sip_remote_party_id_t;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
extern msg_xtra_f sip_remote_party_id_dup_xtra;
|
||||
extern msg_dup_f sip_remote_party_id_dup_one;
|
||||
|
||||
static msg_update_f sip_remote_party_id_update;
|
||||
|
||||
msg_hclass_t sip_remote_party_id_class[] =
|
||||
SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "",
|
||||
rpid_params, append, remote_party_id);
|
||||
|
||||
issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h,
|
||||
char *s, isize_t slen)
|
||||
{
|
||||
sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
|
||||
|
||||
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
|
||||
*s = '\0', s += span_lws(s + 1) + 1;
|
||||
|
||||
if (sip_name_addr_d(home, &s,
|
||||
&rpid->rpid_display,
|
||||
rpid->rpid_url,
|
||||
&rpid->rpid_params, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
return msg_parse_next_field(home, h, s, slen);
|
||||
}
|
||||
|
||||
issize_t sip_remote_party_id_e(char b[], isize_t bsiz,
|
||||
sip_header_t const *h, int f)
|
||||
{
|
||||
sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
|
||||
|
||||
return sip_name_addr_e(b, bsiz, f,
|
||||
rpid->rpid_display, 1,
|
||||
rpid->rpid_url,
|
||||
rpid->rpid_params,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/** Calculate size of extra data required for duplicating one
|
||||
* sip_remote_party_id_t header.
|
||||
*/
|
||||
isize_t sip_remote_party_id_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
|
||||
return sip_name_addr_xtra(rpid->rpid_display,
|
||||
rpid->rpid_url,
|
||||
rpid->rpid_params,
|
||||
offset);
|
||||
}
|
||||
|
||||
/** Duplicate one sip_remote_party_id_t object */
|
||||
char *sip_remote_party_id_dup_one(sip_header_t *dst,
|
||||
sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)dst;
|
||||
sip_remote_party_id_t const *o = (sip_remote_party_id_t const *)src;
|
||||
|
||||
return sip_name_addr_dup(&rpid->rpid_display, o->rpid_display,
|
||||
rpid->rpid_url, o->rpid_url,
|
||||
&rpid->rpid_params, o->rpid_params,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
static int sip_remote_party_id_update(msg_common_t *h,
|
||||
char const *name, isize_t namelen,
|
||||
char const *value)
|
||||
{
|
||||
sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
|
||||
|
||||
if (name == NULL) {
|
||||
rpid->rpid_screen = NULL;
|
||||
rpid->rpid_party = NULL;
|
||||
rpid->rpid_id_type = NULL;
|
||||
rpid->rpid_privacy = NULL;
|
||||
}
|
||||
|
||||
#define MATCH(s) (namelen == strlen(#s) && !strncasecmp(name, #s, strlen(#s)))
|
||||
|
||||
else if (MATCH(screen))
|
||||
rpid->rpid_screen = value;
|
||||
else if (MATCH(party))
|
||||
rpid->rpid_party = value;
|
||||
else if (MATCH(id-type))
|
||||
rpid->rpid_id_type = value;
|
||||
else if (MATCH(privacy))
|
||||
rpid->rpid_privacy = value;
|
||||
|
||||
#undef MATCH
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SIP_HAVE_P_ASSERTED_IDENTITY
|
||||
|
||||
/**@SIP_HEADER sip_p_asserted_identity P-Asserted-Identity Header
|
||||
*
|
||||
* The P-Asserted-Identity header is used used among trusted SIP entities
|
||||
* (typically intermediaries) to carry the identity of the user sending a
|
||||
* SIP message as it was verified by authentication. It is "defined" in
|
||||
* @RFC3325 section 9.1 as follows:
|
||||
*
|
||||
* @code
|
||||
* PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
|
||||
* *(COMMA PAssertedID-value)
|
||||
* PAssertedID-value = name-addr / addr-spec
|
||||
* @endcode
|
||||
*
|
||||
* @sa @RFC3325, @PPreferredIdentity
|
||||
*
|
||||
* @NEW_1_12_7. In order to use @b P-Asserted-Identity header,
|
||||
* initialize the SIP parser with, e.g.,
|
||||
* sip_update_default_mclass(sip_extend_mclass(NULL)).
|
||||
*/
|
||||
|
||||
/**@ingroup sip_p_asserted_identity
|
||||
* @typedef typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t;
|
||||
*
|
||||
* The structure #sip_p_asserted_identity_t contains representation of SIP
|
||||
* @PAssertedIdentity header.
|
||||
*
|
||||
* The #sip_p_asserted_identity_t is defined as follows:
|
||||
* @code
|
||||
* typedef struct sip_p_asserted_identity_s {
|
||||
* sip_common_t paid_common[1]; // Common fragment info
|
||||
* sip_p_asserted_identity_t *paid_next; // Link to next
|
||||
* char const *paid_display; // Display name
|
||||
* url_t paid_url[1]; // URL
|
||||
* } sip_p_asserted_identity_t;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
static msg_xtra_f sip_p_asserted_identity_dup_xtra;
|
||||
static msg_dup_f sip_p_asserted_identity_dup_one;
|
||||
|
||||
#define sip_p_asserted_identity_update NULL
|
||||
|
||||
msg_hclass_t sip_p_asserted_identity_class[] =
|
||||
SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "",
|
||||
paid_common, append, p_asserted_identity);
|
||||
|
||||
issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h,
|
||||
char *s, isize_t slen)
|
||||
{
|
||||
sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)h;
|
||||
|
||||
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
|
||||
*s = '\0', s += span_lws(s + 1) + 1;
|
||||
|
||||
if (sip_name_addr_d(home, &s,
|
||||
&paid->paid_display,
|
||||
paid->paid_url,
|
||||
NULL, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
return msg_parse_next_field(home, h, s, slen);
|
||||
}
|
||||
|
||||
issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz,
|
||||
sip_header_t const *h, int f)
|
||||
{
|
||||
sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
|
||||
|
||||
return sip_name_addr_e(b, bsiz, f,
|
||||
paid->paid_display, MSG_IS_CANONIC(f),
|
||||
paid->paid_url,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
isize_t sip_p_asserted_identity_dup_xtra(sip_header_t const *h, isize_t offset)
|
||||
{
|
||||
sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
|
||||
|
||||
return sip_name_addr_xtra(paid->paid_display,
|
||||
paid->paid_url,
|
||||
NULL,
|
||||
offset);
|
||||
}
|
||||
|
||||
/** Duplicate one sip_p_asserted_identity_t object */
|
||||
char *sip_p_asserted_identity_dup_one(sip_header_t *dst,
|
||||
sip_header_t const *src,
|
||||
char *b, isize_t xtra)
|
||||
{
|
||||
sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)dst;
|
||||
sip_p_asserted_identity_t const *o = (sip_p_asserted_identity_t *)src;
|
||||
|
||||
return sip_name_addr_dup(&paid->paid_display, o->paid_display,
|
||||
paid->paid_url, o->paid_url,
|
||||
NULL, NULL,
|
||||
b, xtra);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if SIP_HAVE_P_PREFERRED_IDENTITY
|
||||
|
||||
/**@SIP_HEADER sip_p_preferred_identity P-Preferred-Identity Header
|
||||
*
|
||||
* The P-Preferred-Identity header is used used among trusted SIP entities
|
||||
* (typically intermediaries) to carry the identity of the user sending a
|
||||
* SIP message as it was verified by authentication. It is "defined" in
|
||||
* @RFC3325 section 9.1 as follows:
|
||||
*
|
||||
* @code
|
||||
* PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
|
||||
* *(COMMA PPreferredID-value)
|
||||
* PPreferredID-value = name-addr / addr-spec
|
||||
* @endcode
|
||||
*
|
||||
* @sa @RFC3325, @PAssertedIdentity
|
||||
*
|
||||
* @NEW_1_12_7. In order to use @b P-Preferred-Identity header,
|
||||
* initialize the SIP parser with, e.g.,
|
||||
* sip_update_default_mclass(sip_extend_mclass(NULL)).
|
||||
*/
|
||||
|
||||
/**@ingroup sip_p_preferred_identity
|
||||
* @typedef typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t;
|
||||
*
|
||||
* The structure #sip_p_preferred_identity_t contains representation of SIP
|
||||
* @PPreferredIdentity header.
|
||||
*
|
||||
* The #sip_p_preferred_identity_t is defined as follows:
|
||||
* @code
|
||||
* typedef struct sip_p_preferred_identity_s {
|
||||
* sip_common_t ppid_common[1]; // Common fragment info
|
||||
* sip_p_preferred_identity_t *ppid_next; // Link to next
|
||||
* char const *ppid_display; // Display name
|
||||
* url_t ppid_url[1]; // URL
|
||||
* } sip_p_preferred_identity_t;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
|
||||
msg_hclass_t sip_p_preferred_identity_class[] =
|
||||
SIP_HEADER_CLASS(p_preferred_identity, "P-Preferred-Identity", "",
|
||||
ppid_common, append, p_asserted_identity);
|
||||
|
||||
issize_t sip_p_preferred_identity_d(su_home_t *home, sip_header_t *h,
|
||||
char *s, isize_t slen)
|
||||
{
|
||||
return sip_p_asserted_identity_d(home, h, s, slen);
|
||||
}
|
||||
|
||||
issize_t sip_p_preferred_identity_e(char b[], isize_t bsiz,
|
||||
sip_header_t const *h, int f)
|
||||
{
|
||||
return sip_p_asserted_identity_e(b, bsiz, h, f);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#
|
||||
# This file specifies extra SIP headers not included in sip_t structure
|
||||
#
|
||||
# The parsed headers are accessed with function (or macro) like sip_refer_sub()
|
||||
# e.g., sip_refer_sub_t *rsub = sip_refer_sub(sip);
|
||||
#
|
||||
# The line format is:
|
||||
# C-name @SINCE sip_t-like-comment
|
||||
#
|
||||
|
@ -9,8 +12,19 @@
|
|||
#### EXTRA HEADER LIST STARTS HERE ####
|
||||
|
||||
refer_sub @NEW_1_12_5 /**< Refer-Sub header */
|
||||
|
||||
#### DEFAULT HEADER LIST ENDS HERE ####
|
||||
|
||||
#
|
||||
# These headers are added to the extended parser, installed
|
||||
# as default with sip_update_default_mclass(NULL)
|
||||
#
|
||||
|
||||
alert_info @NEW_1_12_7 /**< Alert-Info header */
|
||||
reply_to @NEW_1_12_7 /**< Reply-To header */
|
||||
remote_party_id @NEW_1_12_7 /**< Remote-Party-ID header */
|
||||
p_asserted_identity @NEW_1_12_7 /**<P-Asserted-Identity*/
|
||||
p_preferred_identity @NEW_1_12_7 /**<P-Preferred-Identity*/
|
||||
|
||||
#### EXPERIMENTAL HEADER LIST STARTS HERE ####
|
||||
|
||||
|
|
|
@ -60,11 +60,84 @@ char const sip_parser_version[] = VERSION;
|
|||
char const sip_version_2_0[] = "SIP/2.0";
|
||||
|
||||
/** Default message class */
|
||||
extern msg_mclass_t const sip_mclass[];
|
||||
extern msg_mclass_t sip_mclass[];
|
||||
|
||||
static msg_mclass_t const *_default = sip_mclass;
|
||||
|
||||
/** Return a built-in SIP parser object. */
|
||||
msg_mclass_t const *sip_default_mclass(void)
|
||||
{
|
||||
return sip_mclass;
|
||||
return _default;
|
||||
}
|
||||
|
||||
/** Update the default SIP parser.
|
||||
*
|
||||
* Use the extended SIP parser as default one.
|
||||
*
|
||||
* If the applications want to use headers added after @VERSION_1_12_5,
|
||||
* they should call this function before doing any other initialization, e.g.,
|
||||
* @code
|
||||
* su_init();
|
||||
* if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) {
|
||||
* su_deinit();
|
||||
* exit(2);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* The default parser is not extended because it may break the old
|
||||
* applications looking for extension headers from sip_unknown list.
|
||||
*
|
||||
* @retval 0 when successful
|
||||
* @retval -1 upon an error
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
int sip_update_default_mclass(msg_mclass_t const *mclass)
|
||||
{
|
||||
if (mclass == NULL)
|
||||
return -1;
|
||||
_default = mclass;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Extend SIP parser class with extension headers.
|
||||
*
|
||||
* Extend given SIP parser class with extension headers. If the given parser
|
||||
* class is the default one or NULL, make a clone of it before extending it.
|
||||
*
|
||||
* @param input pointer to a SIP message class (may be NULL)
|
||||
*
|
||||
* @return Pointer to extended mclass, or NULL upon an error.
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
msg_mclass_t *sip_extend_mclass(msg_mclass_t *input)
|
||||
{
|
||||
msg_mclass_t *mclass;
|
||||
|
||||
if (input == NULL || input == _default)
|
||||
mclass = msg_mclass_clone(_default, 0, 0);
|
||||
else
|
||||
mclass = input;
|
||||
|
||||
if (mclass) {
|
||||
extern msg_hclass_t * const sip_extensions[];
|
||||
int i;
|
||||
|
||||
for (i = 0; sip_extensions[i]; i++) {
|
||||
msg_hclass_t *hclass = sip_extensions[i];
|
||||
if (mclass->mc_unknown != msg_find_hclass(mclass, hclass->hc_name, NULL))
|
||||
continue;
|
||||
|
||||
if (msg_mclass_insert_header(mclass, hclass, 0) < 0) {
|
||||
if (input != mclass)
|
||||
free(mclass);
|
||||
return mclass = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mclass;
|
||||
}
|
||||
|
||||
/** Extract the SIP message body, including separator line.
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
*/
|
||||
|
||||
#ifndef SIP_H
|
||||
#include <sip.h>
|
||||
#include <sofia-sip/sip.h>
|
||||
#endif
|
||||
|
||||
/**@ingroup sip_also
|
||||
|
|
|
@ -543,12 +543,12 @@ sip_contact_t *sip_contact_immunize(su_home_t *home, sip_contact_t const *m)
|
|||
*
|
||||
* @retval -1 if the contact is rejected
|
||||
* @retval 1000 if contact is immune to caller preferences
|
||||
* @retval 0..1000 reflecting @RFC3481 score in 0.000 - 1.000.
|
||||
* @retval 0..1000 reflecting @RFC3841 score in 0.000 - 1.000.
|
||||
*
|
||||
* @sa sip_q_value(),
|
||||
* sip_contact_accept(), sip_contact_reject(), sip_contact_is_immune(),
|
||||
* sip_contact_immunize(), sip_is_callerpref(), sip_prefs_matching(),
|
||||
* @RFC3481, @AcceptContact, @RejectContact, @Contact
|
||||
* @RFC3841, @AcceptContact, @RejectContact, @Contact
|
||||
*/
|
||||
int sip_contact_score(sip_contact_t const *m,
|
||||
sip_accept_contact_t const *ac,
|
||||
|
|
|
@ -1421,3 +1421,4 @@ int sip_response_terminates_dialog(int response_code,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ typedef msg_time_t sip_time_t;
|
|||
/** Latest time that can be expressed with #sip_time_t. @HIDE */
|
||||
#define SIP_TIME_MAX ((sip_time_t)MSG_TIME_MAX)
|
||||
|
||||
/** SIP message object. */
|
||||
/** Structure for accessing parsed SIP headers. */
|
||||
typedef struct sip_s sip_t;
|
||||
|
||||
/** Any SIP header - union of all possible SIP headers. */
|
||||
|
@ -409,7 +409,7 @@ struct sip_accept_s
|
|||
/**@ingroup sip_allow
|
||||
* @brief Structure for @Allow header field.
|
||||
*
|
||||
* @NEW_1_12_5 (before used struct msg_list_s with @Allow).
|
||||
* @NEW_1_12_5. (Before used struct msg_list_s with @Allow).
|
||||
*/
|
||||
struct sip_allow_s
|
||||
{
|
||||
|
@ -417,7 +417,7 @@ struct sip_allow_s
|
|||
msg_list_t *k_next; /**< Link to next */
|
||||
msg_param_t *k_items; /**< List of allowed items */
|
||||
uint32_t k_bitmap; /**< Bitmap of allowed methods.
|
||||
@NEW_1_12_5 */
|
||||
@NEW_1_12_5. */
|
||||
};
|
||||
|
||||
/**@ingroup sip_authentication_info
|
||||
|
@ -573,7 +573,7 @@ struct sip_min_expires_s
|
|||
};
|
||||
|
||||
/**@ingroup sip_rack
|
||||
* @brief Structure for @b Rack header.
|
||||
* @brief Structure for @RAck header.
|
||||
*/
|
||||
struct sip_rack_s
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/**@file sofia-sip/sip_extra.h.in
|
||||
`/**@file sofia-sip/sip_extra.h.in
|
||||
* -*- C -*-
|
||||
* Template for <sofia-sip/sip_extra.h>.
|
||||
*
|
||||
|
@ -117,6 +117,55 @@ struct sip_suppress_notify_if_match_s
|
|||
char const *snim_tag; /**< Entity-tag */
|
||||
};
|
||||
|
||||
typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t;
|
||||
|
||||
/**@ingroup sip_p_asserted_identity
|
||||
* @brief Structure for @PAssertedIdentity header.
|
||||
*/
|
||||
struct sip_p_asserted_identity_s
|
||||
{
|
||||
sip_common_t paid_common[1];/**< Common fragment info */
|
||||
sip_p_asserted_identity_t
|
||||
*paid_next; /**< Link to next identity */
|
||||
char const *paid_display; /**< Display name */
|
||||
url_t paid_url[1]; /**< SIP, SIPS or TEL URL */
|
||||
};
|
||||
|
||||
typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t;
|
||||
|
||||
/**@ingroup sip_p_preferred_identity
|
||||
* @brief Structure for @PPreferredIdentity header.
|
||||
*/
|
||||
struct sip_p_preferred_identity_s
|
||||
{
|
||||
sip_common_t ppid_common[1];/**< Common fragment info */
|
||||
sip_p_preferred_identity_t
|
||||
*ppid_next; /**< Link to next identity */
|
||||
char const *ppid_display; /**< Display name */
|
||||
url_t ppid_url[1]; /**< SIP, SIPS or TEL URL */
|
||||
};
|
||||
|
||||
|
||||
int sip_p_initialize_remote_party_id_headers(msg_mclass_t *mclass);
|
||||
|
||||
typedef struct sip_remote_party_id_s sip_remote_party_id_t;
|
||||
|
||||
/**@ingroup sip_remote_party_id
|
||||
* @brief Structure for @RemotePartyID header.
|
||||
*/
|
||||
struct sip_remote_party_id_s
|
||||
{
|
||||
sip_common_t rpid_common[1];/**< Common fragment info */
|
||||
sip_remote_party_id_t
|
||||
*rpid_next; /**< Link to next identity */
|
||||
char const *rpid_display; /**< Display name */
|
||||
url_t rpid_url[1]; /**< URL */
|
||||
sip_param_t const *rpid_params; /**< Parameters */
|
||||
/** Shortcuts to screen, party, id-type and privacy parameters */
|
||||
char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Defined as 1 if the @ref sip_#xxxxxx# "#xxxxxxx_xxxxxxx#" is supported */
|
||||
#define SIP_HAVE_#XXXXXX# 1
|
||||
|
|
|
@ -57,13 +57,16 @@
|
|||
|
||||
SOFIA_BEGIN_DECLS
|
||||
|
||||
/** Return built-in SIP parser object. */
|
||||
/** Return a built-in SIP parser object. */
|
||||
SOFIAPUBFUN msg_mclass_t const *sip_default_mclass(void);
|
||||
|
||||
/** Check that sip_t is a SIP structure (not RTSP or HTTP). @HIDE */
|
||||
SOFIAPUBFUN int sip_update_default_mclass(msg_mclass_t const *mclass);
|
||||
SOFIAPUBFUN msg_mclass_t *sip_extend_mclass(msg_mclass_t *input);
|
||||
|
||||
/** Check that sip_t is a SIP header structure (not MIME or HTTP). @HIDE */
|
||||
#define sip_is_sip(sip) ((sip) && (sip)->sip_ident == SIP_PROTOCOL_TAG)
|
||||
|
||||
/** Initializer for a SIP header object. @HIDE */
|
||||
/** Initializer for a SIP header structure. @HIDE */
|
||||
#define SIP_HDR_INIT(name) {{{ 0, 0, sip_##name##_class }}}
|
||||
|
||||
/** Initialize a SIP header structure. @HIDE */
|
||||
|
@ -349,7 +352,7 @@ int sip_has_feature(msg_list_t const *supported, char const *feature);
|
|||
SOFIAPUBFUN int sip_is_allowed(sip_allow_t const *allow,
|
||||
sip_method_t method, char const *name);
|
||||
|
||||
/** Check if the well-known method is listed in @Allow header. @NEW_1_12_6 */
|
||||
/** Check if the well-known method is listed in @Allow header. @NEW_1_12_6. */
|
||||
#define SIP_IS_ALLOWED(allow, method) \
|
||||
(sip_method_unknown < (method) && (method) < 32 && \
|
||||
(allow) && ((allow)->k_bitmap & (1 << (method))) != 0)
|
||||
|
@ -447,7 +450,7 @@ enum sip_bad_mask {
|
|||
|
||||
/** Bit marking essential headers for PUBLISH servers and clients.
|
||||
*
|
||||
* @SIPEtag, and @SIPIfMatch.
|
||||
* @SIPETag, and @SIPIfMatch.
|
||||
*
|
||||
* @sa @RFC3903.
|
||||
*/
|
||||
|
|
|
@ -137,6 +137,17 @@ SOFIAPUBFUN issize_t sip_name_addr_e(char b[], isize_t bsiz,
|
|||
msg_param_t const params[],
|
||||
char const *comment);
|
||||
|
||||
SOFIAPUBFUN isize_t sip_name_addr_xtra(char const *display, url_t const *addr,
|
||||
msg_param_t const params[],
|
||||
isize_t offset);
|
||||
|
||||
SOFIAPUBFUN char *sip_name_addr_dup(char const **d_display, char const *display,
|
||||
url_t *d_addr, url_t const *addr,
|
||||
msg_param_t const **d_params,
|
||||
msg_param_t const params[],
|
||||
char *b, isize_t xtra);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* 3) Compatibility macros and functions
|
||||
*/
|
||||
|
|
|
@ -153,7 +153,7 @@ siptag_header_vr(sip_header_t const **vp)
|
|||
* Macro is used to include a tag item containing an unknown extension
|
||||
* header in the tag list, e.g.,
|
||||
* @code
|
||||
* SIPTAG_HEADER_STR("Remote-Party-ID: +358718008000")
|
||||
* SIPTAG_HEADER_STR("P-Alternative-URL: <+358718008000>")
|
||||
* @endcode
|
||||
*
|
||||
* It is also possible to include multiple headers at once
|
||||
|
|
|
@ -138,7 +138,7 @@ union sip_pref
|
|||
usize_t spl_length;
|
||||
} sp_literal;
|
||||
|
||||
/** String (tag="<foo>"). */
|
||||
/** String (tag="<foo>"). */ /* (tag="<foo>") */
|
||||
struct sp_string {
|
||||
enum sp_type sps_type;
|
||||
char const *sps_value;
|
||||
|
|
|
@ -74,6 +74,135 @@ msg_mclass_t *test_mclass = NULL;
|
|||
|
||||
static msg_t *read_message(int flags, char const string[]);
|
||||
|
||||
static int test_identity(void)
|
||||
{
|
||||
su_home_t *home;
|
||||
sip_p_asserted_identity_t *paid;
|
||||
sip_p_preferred_identity_t *ppid;
|
||||
|
||||
msg_t *msg;
|
||||
sip_t *sip;
|
||||
|
||||
BEGIN();
|
||||
|
||||
msg_href_t const *href;
|
||||
msg_mclass_t const *def0, *def1, *ext;
|
||||
|
||||
def0 = sip_default_mclass();
|
||||
|
||||
/* Check that Refer-Sub has been added to our parser */
|
||||
TEST_1(href = msg_find_hclass(def0, "Refer-Sub", NULL));
|
||||
TEST_P(href->hr_class, sip_refer_sub_class);
|
||||
/* Check that Reply-To is not there */
|
||||
TEST_P(msg_find_hclass(def0, "Reply-To", NULL), def0->mc_unknown);
|
||||
|
||||
TEST_1(ext = sip_extend_mclass(NULL));
|
||||
/* Update default parser */
|
||||
TEST_1(sip_update_default_mclass(ext) == 0);
|
||||
def1 = sip_default_mclass();
|
||||
TEST_1(def0 != def1);
|
||||
TEST_1(ext == def1);
|
||||
|
||||
TEST_1(href = msg_find_hclass(def1, "Reply-To", NULL));
|
||||
TEST_P(href->hr_class, sip_reply_to_class);
|
||||
|
||||
TEST_1(test_mclass = msg_mclass_clone(def0, 0, 0));
|
||||
|
||||
msg = read_message(MSG_DO_EXTRACT_COPY,
|
||||
"BYE sip:foo@bar SIP/2.0\r\n"
|
||||
"To: <sip:foo@bar>;tag=deadbeef\r\n"
|
||||
"From: <sip:bar@foo>;\r\n"
|
||||
"Call-ID: 0ha0isndaksdj@10.1.2.3\r\n"
|
||||
"CSeq: 8 SUBSCRIBE\r\n"
|
||||
"Via: SIP/2.0/UDP 135.180.130.133\r\n"
|
||||
"P-Asserted-Identity: <sip:test@test.domain.com>\r\n"
|
||||
"P-Preferred-Identity: <sip:test@test.domain.com>, <tel:+358708008000>\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n");
|
||||
|
||||
sip = sip_object(msg);
|
||||
|
||||
TEST_1(!sip_p_asserted_identity(sip));
|
||||
TEST_1(!sip_p_preferred_identity(sip));
|
||||
|
||||
msg_destroy(msg);
|
||||
|
||||
TEST_1(msg_mclass_insert_header(test_mclass,
|
||||
sip_p_asserted_identity_class, 0) > 0);
|
||||
TEST_1(msg_mclass_insert_header(test_mclass,
|
||||
sip_p_preferred_identity_class, 0) > 0);
|
||||
|
||||
msg = read_message(MSG_DO_EXTRACT_COPY,
|
||||
"BYE sip:foo@bar SIP/2.0\r\n"
|
||||
"To: <sip:foo@bar>;tag=deadbeef\r\n"
|
||||
"From: <sip:bar@foo>;\r\n"
|
||||
"Call-ID: 0ha0isndaksdj@10.1.2.3\r\n"
|
||||
"CSeq: 8 SUBSCRIBE\r\n"
|
||||
"Via: SIP/2.0/UDP 135.180.130.133\r\n"
|
||||
"P-Asserted-Identity: <sip:test@test.domain.com>\r\n"
|
||||
"P-Preferred-Identity: <sip:test@test.domain.com>, <tel:+358708008000>\r\n"
|
||||
"Content-Length: 0\r\n"
|
||||
"\r\n");
|
||||
|
||||
sip = sip_object(msg);
|
||||
|
||||
TEST_1(home = msg_home(msg));
|
||||
|
||||
TEST_1((paid = sip_p_asserted_identity_make(home, "sip:joe@example.com")));
|
||||
TEST_1((paid = sip_p_asserted_identity_make
|
||||
(home, "Jaska <sip:joe@example.com>, Helmi <tel:+3587808000>")));
|
||||
TEST_1(paid->paid_next);
|
||||
TEST_1((ppid = sip_p_preferred_identity_make(home, "sip:joe@example.com")));
|
||||
TEST_1((ppid = sip_p_preferred_identity_make
|
||||
(home, "Jaska <sip:joe@example.com>, Helmi <tel:+3587808000>")));
|
||||
|
||||
msg_destroy(msg);
|
||||
|
||||
/* Now with extensions */
|
||||
TEST_1(test_mclass = msg_mclass_clone(def1, 0, 0));
|
||||
|
||||
{
|
||||
su_home_t *home = su_home_clone(NULL, sizeof *home);
|
||||
|
||||
char *s;
|
||||
char const canonic[] =
|
||||
"\"Jaska Jokunen\" <sip:jaska.jokunen@example.com>;"
|
||||
"screen=yes;party=called;id-type=user;privacy=\"name,uri-network\"";
|
||||
char const canonic2[] =
|
||||
"Jaska Jokunen <sip:jaska.jokunen@example.com>;"
|
||||
"screen=yes;party=called;id-type=user;privacy=\"name,uri-network\"";
|
||||
|
||||
sip_remote_party_id_t *rpid, *d;
|
||||
|
||||
TEST_1(rpid = sip_remote_party_id_make(home, canonic));
|
||||
TEST_S(rpid->rpid_display, "\"Jaska Jokunen\"");
|
||||
TEST_S(rpid->rpid_url->url_user, "jaska.jokunen");
|
||||
TEST_S(rpid->rpid_params[0], "screen=yes");
|
||||
TEST_S(rpid->rpid_screen, "yes");
|
||||
TEST_S(rpid->rpid_party, "called");
|
||||
TEST_S(rpid->rpid_id_type, "user");
|
||||
TEST_S(rpid->rpid_privacy, "\"name,uri-network\"");
|
||||
TEST_1(s = sip_header_as_string(home, (void*)rpid));
|
||||
TEST_S(s, canonic);
|
||||
TEST_1(d = sip_remote_party_id_dup(home, rpid));
|
||||
TEST_S(d->rpid_display, rpid->rpid_display);
|
||||
TEST_S(d->rpid_params[0], rpid->rpid_params[0]);
|
||||
|
||||
TEST_1(rpid = sip_remote_party_id_make(home, canonic2));
|
||||
TEST_S(rpid->rpid_display, "Jaska Jokunen");
|
||||
TEST_1(s = sip_header_as_string(home, (void*)rpid));
|
||||
TEST_S(s, canonic2);
|
||||
TEST_1(d = sip_remote_party_id_dup(home, rpid));
|
||||
TEST_S(d->rpid_display, rpid->rpid_display);
|
||||
|
||||
su_home_check(home);
|
||||
|
||||
su_home_zap(home);
|
||||
}
|
||||
|
||||
END();
|
||||
}
|
||||
|
||||
int test_url_headers(void)
|
||||
{
|
||||
BEGIN();
|
||||
|
@ -84,16 +213,20 @@ int test_url_headers(void)
|
|||
sip_from_t const *f;
|
||||
sip_accept_t const *ac;
|
||||
sip_payload_t const *body;
|
||||
sip_refer_sub_t rs[1];
|
||||
|
||||
TEST_1(home = su_home_new(sizeof *home));
|
||||
|
||||
sip_refer_sub_init(rs)->rs_value = "false";
|
||||
|
||||
s = sip_headers_as_url_query
|
||||
(home,
|
||||
SIPTAG_SUBJECT_STR(";"),
|
||||
SIPTAG_SUBJECT_STR("kuik"),
|
||||
SIPTAG_REFER_SUB(rs),
|
||||
TAG_END());
|
||||
|
||||
TEST_1(s);
|
||||
TEST_S(s, "subject=;");
|
||||
TEST_S(s, "subject=kuik&refer-sub=false");
|
||||
|
||||
s = sip_headers_as_url_query
|
||||
(home,
|
||||
|
@ -2189,7 +2322,7 @@ int test_refer(void)
|
|||
|
||||
TEST_1(home = su_home_create());
|
||||
|
||||
/* Check that Refer-Sub has already been added to our parser */
|
||||
/* Check that Refer-Sub has now been added to our parser */
|
||||
TEST_1(msg_mclass_insert_with_mask(test_mclass, sip_refer_sub_class,
|
||||
0, 0) == -1);
|
||||
|
||||
|
@ -3334,9 +3467,13 @@ int main(int argc, char *argv[])
|
|||
tstflags |= tst_verbatim;
|
||||
#endif
|
||||
|
||||
if (!test_mclass)
|
||||
retval |= test_identity(); fflush(stdout);
|
||||
|
||||
if (test_mclass == NULL)
|
||||
test_mclass = msg_mclass_clone(sip_default_mclass(), 0, 0);
|
||||
|
||||
retval |= parser_test(); fflush(stdout);
|
||||
|
||||
retval |= test_url_headers(); fflush(stdout);
|
||||
retval |= test_manipulation(); fflush(stdout);
|
||||
retval |= test_methods(); fflush(stdout);
|
||||
|
@ -3348,7 +3485,7 @@ int main(int argc, char *argv[])
|
|||
retval |= tag_test(); fflush(stdout);
|
||||
retval |= parser_tag_test(); fflush(stdout);
|
||||
retval |= response_phrase_test(); fflush(stdout);
|
||||
retval |= parser_test(); fflush(stdout);
|
||||
|
||||
retval |= sip_header_test(); fflush(stdout);
|
||||
retval |= test_bad_packet(); fflush(stdout);
|
||||
retval |= test_sip_list_header(); fflush(stdout);
|
||||
|
|
|
@ -22,9 +22,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@IFILE validator.c
|
||||
/**@internal @IFILE validator.c
|
||||
*
|
||||
* SIP parser tester. This uses output
|
||||
* SIP parser tester. This uses output from tport dump where messages are
|
||||
* separated with Control-K ('\v') from each other.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>.
|
||||
*
|
||||
|
|
|
@ -824,7 +824,7 @@ int soa_get_warning(soa_session_t *ss, char const **return_text)
|
|||
* nua_options(), #nua_i_options
|
||||
*/
|
||||
int soa_get_capability_sdp(soa_session_t const *ss,
|
||||
sdp_session_t const **return_sdp,
|
||||
struct sdp_session_s const **return_sdp,
|
||||
char const **return_sdp_str,
|
||||
isize_t *return_len)
|
||||
{
|
||||
|
@ -874,7 +874,7 @@ int soa_get_capability_sdp(soa_session_t const *ss,
|
|||
* nua_options(), #nua_i_options
|
||||
*/
|
||||
int soa_set_capability_sdp(soa_session_t *ss,
|
||||
sdp_session_t const *sdp,
|
||||
struct sdp_session_s const *sdp,
|
||||
char const *str, issize_t len)
|
||||
{
|
||||
SU_DEBUG_9(("soa_set_capability_sdp(%s::%p, %p, %p, "MOD_ZD") called\n",
|
||||
|
@ -956,7 +956,7 @@ soa_base_set_capability_sdp(soa_session_t *ss,
|
|||
* soa_get_capability_sdp()
|
||||
*/
|
||||
int soa_get_user_sdp(soa_session_t const *ss,
|
||||
sdp_session_t const **return_sdp,
|
||||
struct sdp_session_s const **return_sdp,
|
||||
char const **return_sdp_str,
|
||||
isize_t *return_len)
|
||||
{
|
||||
|
@ -1032,7 +1032,7 @@ int soa_get_user_version(soa_session_t const *ss)
|
|||
* soa_set_remote_sdp()
|
||||
*/
|
||||
int soa_set_user_sdp(soa_session_t *ss,
|
||||
sdp_session_t const *sdp,
|
||||
struct sdp_session_s const *sdp,
|
||||
char const *str, issize_t len)
|
||||
{
|
||||
SU_DEBUG_9(("soa_set_user_sdp(%s::%p, %p, %p, "MOD_ZD") called\n",
|
||||
|
@ -1073,7 +1073,7 @@ int soa_base_set_user_sdp(soa_session_t *ss,
|
|||
* soa_get_local_sdp(), soa_get_user_sdp(), soa_get_capability_sdp().
|
||||
*/
|
||||
int soa_get_remote_sdp(soa_session_t const *ss,
|
||||
sdp_session_t const **return_sdp,
|
||||
struct sdp_session_s const **return_sdp,
|
||||
char const **return_sdp_str,
|
||||
isize_t *return_len)
|
||||
{
|
||||
|
@ -1151,7 +1151,7 @@ int soa_get_remote_version(soa_session_t const *ss)
|
|||
* soa_set_user_sdp(), soa_set_capability_sdp().
|
||||
*/
|
||||
int soa_set_remote_sdp(soa_session_t *ss,
|
||||
sdp_session_t const *sdp,
|
||||
struct sdp_session_s const *sdp,
|
||||
char const *str, issize_t len)
|
||||
{
|
||||
SU_DEBUG_9(("soa_set_remote_sdp(%s::%p, %p, %p, "MOD_ZD") called\n",
|
||||
|
@ -1245,7 +1245,7 @@ int soa_has_received_sdp(soa_session_t const *ss)
|
|||
* soa_get_user_sdp(), soa_get_remote_sdp(), soa_get_capability_sdp().
|
||||
*/
|
||||
int soa_get_local_sdp(soa_session_t const *ss,
|
||||
sdp_session_t const **return_sdp,
|
||||
struct sdp_session_s const **return_sdp,
|
||||
char const **return_sdp_str,
|
||||
isize_t *return_len)
|
||||
{
|
||||
|
@ -1412,7 +1412,7 @@ int soa_generate_offer(soa_session_t *ss,
|
|||
if (ss == NULL)
|
||||
return su_seterrno(EFAULT), -1;
|
||||
|
||||
/** @ERROR An operation is already in progress */
|
||||
/** @ERROR EALREADY An operation is already in progress */
|
||||
if (ss->ss_in_progress)
|
||||
return su_seterrno(EALREADY), -1;
|
||||
|
||||
|
@ -1500,7 +1500,7 @@ int soa_generate_answer(soa_session_t *ss,
|
|||
if (ss == NULL)
|
||||
return su_seterrno(EFAULT), -1;
|
||||
|
||||
/** @ERROR An operation is already in progress. */
|
||||
/** @ERROR EALREADY An operation is already in progress. */
|
||||
if (ss->ss_in_progress)
|
||||
return su_seterrno(EALREADY), -1;
|
||||
|
||||
|
@ -1580,7 +1580,7 @@ int soa_process_answer(soa_session_t *ss,
|
|||
if (ss == NULL)
|
||||
return su_seterrno(EFAULT), -1;
|
||||
|
||||
/** @ERROR An operation is already in progress. */
|
||||
/** @ERROR EALREADY An operation is already in progress. */
|
||||
if (ss->ss_in_progress)
|
||||
return su_seterrno(EALREADY), -1;
|
||||
|
||||
|
@ -1661,7 +1661,7 @@ int soa_process_reject(soa_session_t *ss,
|
|||
if (ss == NULL)
|
||||
return su_seterrno(EFAULT), -1;
|
||||
|
||||
/** @ERROR An operation is already in progress. */
|
||||
/** @ERROR EALREADY An operation is already in progress. */
|
||||
if (ss->ss_in_progress)
|
||||
return su_seterrno(EALREADY), -1;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@section soa_meta Module Information
|
||||
|
||||
The Sofia SIP @b soa module consists of an asynchronous SDP Offer/Answer engine
|
||||
library. The interface to library is defined in <soa.h>.
|
||||
library. The interface to library is defined in <sofia-sip/soa.h>.
|
||||
|
||||
@CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
||||
|
|
|
@ -631,6 +631,8 @@ tag_typedef_t soatag_hold = STRTAG_TYPEDEF(hold);
|
|||
* Corresponding tag taking a reference parameter is SOATAG_RTP_SELECT_REF().
|
||||
*
|
||||
* @sa @RFC3264 section 8.3.3, T.38
|
||||
*
|
||||
* @NEW_1_12_7.
|
||||
*/
|
||||
tag_typedef_t soatag_ordered_user = BOOLTAG_TYPEDEF(ordered_user);
|
||||
|
||||
|
|
|
@ -30,14 +30,14 @@
|
|||
# Author(s): Pekka Pessi <Pekka.Pessi@nokia.com>.
|
||||
#
|
||||
|
||||
s=${0%/*}
|
||||
|
||||
test x$s = x$0 && s=`pwd`
|
||||
s=`dirname $0`
|
||||
test x$s = x. && s=`pwd`
|
||||
|
||||
PATH=/usr/sbin:/usr/local/sbin:/sbin:$PATH
|
||||
export PATH
|
||||
|
||||
# Test for support for IPv6 on Linux. This probably fails on everything else.
|
||||
ipv6='sysctl net.ipv6.conf.default.mtu >& /dev/null'
|
||||
ipv6='sysctl net.ipv6.conf.default.mtu >/dev/null 2>&1'
|
||||
# Bind not working with IPv6 on RHEL 4:
|
||||
# client.c:1325: unexpected error: failed to get request's destination: failure
|
||||
#ipv6=false
|
||||
|
@ -46,18 +46,18 @@ port=`expr $$ % \( 65536 - 1024 \) + 1024`
|
|||
|
||||
# Try to find a free port
|
||||
if netstat --ip >/dev/null 2>&1 ; then
|
||||
while netstat --ip -n -a | fgrep -q ":$port "
|
||||
while netstat --ip -n -a | fgrep ":$port " > /dev/null
|
||||
do
|
||||
port=$(($port + 1))
|
||||
if [$port = 65536] ; then
|
||||
port=`expr $port + 1`
|
||||
if test $port = 65536 ; then
|
||||
port=1024
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# No BIND 9, no fun
|
||||
{ type -p named >/dev/null &&
|
||||
named -v | grep -q BIND.*9
|
||||
{ type named >/dev/null &&
|
||||
named -v | grep BIND.*9 > /dev/null
|
||||
} || {
|
||||
echo test_sresolv: there is no BIND 9 named in you path, skipping
|
||||
exit 77
|
||||
|
@ -66,10 +66,10 @@ exit 77
|
|||
if eval $ipv6
|
||||
then
|
||||
# Figure out nice IPv6 address for us
|
||||
ns=$(ip addr ls | awk '
|
||||
ns=`ip addr ls | awk '
|
||||
/^[0-9]:/ { up = ($3 ~ /UP/) && ($3 !~ /LOOPBACK/); }
|
||||
/inet6 fe80::/ { next; } # no link-local
|
||||
up && $1 ~ /inet6/ { sub(/\/.*$/, "", $2); print $2; exit 0; }')
|
||||
up && $1 ~ /inet6/ { sub(/\/.*$/, "", $2); print $2; exit 0; }'`
|
||||
|
||||
# Nothing found, use localnode ::1
|
||||
if test -z "$ns"; then ns=::1 ; fi
|
||||
|
@ -113,9 +113,11 @@ search example.com
|
|||
port $port
|
||||
EOF
|
||||
|
||||
absolute=`cd $s; pwd`
|
||||
|
||||
cat > $t/named.conf <<EOF
|
||||
options {
|
||||
directory "$(cd $s; pwd)";
|
||||
directory "$absolute";
|
||||
pid-file "$t/named.pid";
|
||||
notify no;
|
||||
$listen4
|
||||
|
@ -164,16 +166,16 @@ done
|
|||
|
||||
test -r $t/named.pid || {
|
||||
echo $0: cannot start named >&2 ;
|
||||
if fgrep -q -i -e SELINUX=enforcing /etc/selinux/config 2>&/dev/null ; then
|
||||
if fgrep -i -e SELINUX=enforcing /etc/selinux/config >/dev/null 2>&1 ; then
|
||||
echo $0: perhaps you have to disable SELinux protection for named
|
||||
fi
|
||||
exit 77
|
||||
}
|
||||
|
||||
function kill_named
|
||||
kill_named ()
|
||||
{
|
||||
kill `cat $t/named.pid`
|
||||
rm $t/named.conf $t/resolv.conf $t/error.conf $t/named.pid
|
||||
rm $t/named.conf $t/resolv.conf $t/error.conf $t/named.pid 2>/dev/null
|
||||
rmdir $t
|
||||
}
|
||||
trap kill_named EXIT
|
||||
|
|
|
@ -224,6 +224,10 @@ int test_api_errors(void)
|
|||
|
||||
extern void sres_cache_clean(sres_cache_t *cache, time_t now);
|
||||
|
||||
#ifndef CLOCK_PROCESS_CPUTIME_ID
|
||||
#define CLOCK_PROCESS_CPUTIME_ID CLOCK_REALTIME
|
||||
#endif
|
||||
|
||||
static
|
||||
int test_cache(void)
|
||||
{
|
||||
|
@ -282,7 +286,7 @@ int test_cache(void)
|
|||
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);
|
||||
N, (long unsigned)t2.tv_sec, t2.tv_nsec);
|
||||
}
|
||||
|
||||
for (i = 0, N; i < N; i++)
|
||||
|
@ -299,7 +303,7 @@ int test_cache(void)
|
|||
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);
|
||||
N, (long unsigned)t2.tv_sec, t2.tv_nsec);
|
||||
}
|
||||
|
||||
for (i = 0, N; i < N; i++)
|
||||
|
@ -321,7 +325,7 @@ int test_cache(void)
|
|||
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);
|
||||
N, (long unsigned)t2.tv_sec, t2.tv_nsec);
|
||||
}
|
||||
|
||||
for (i = 0, N; i < N; i++)
|
||||
|
@ -339,7 +343,7 @@ int test_cache(void)
|
|||
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);
|
||||
N, (long unsigned)t2.tv_sec, t2.tv_nsec);
|
||||
}
|
||||
|
||||
for (i = 0, N; i < N; i++) {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file lookup_stun_server.c
|
||||
* @brief Test app for STUN DNS-SRV lookups.
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file stun.c STUN client module
|
||||
*
|
||||
* See RFC 3489/3489bis for further information.
|
||||
|
|
|
@ -14,9 +14,9 @@ client library.
|
|||
@section stun_contents Contents of stun Module
|
||||
|
||||
The stun module contains the public header files as follows:
|
||||
- <stun.h> the public API of the module
|
||||
- <stun_common.h> low-level functions for parsing and encoding STUN messages
|
||||
- <stun_tag.h> defines the su tags used by stun
|
||||
- <sofia-sip/stun.h> the public API of the module
|
||||
- <sofia-sip/stun_common.h> low-level functions for parsing and encoding STUN messages
|
||||
- <sofia-sip/stun_tag.h> defines the su tags used by stun
|
||||
|
||||
@section stun_usage Using Sofia STUN Library
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file stun_common.c
|
||||
* @brief
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file stun_dns.c
|
||||
* @brief Functins to discover STUN server address using DNS-SRV.
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
/**@internal
|
||||
* @file stun_mini.c
|
||||
* @brief Minimal stun server
|
||||
*
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@CFILE stun_tag.c Tags and tag lists for Offer/Answer Engine
|
||||
/**@internal @CFILE stun_tag.c Tags and tag lists for Offer/Answer Engine
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
* @author Martti Mela <Martti.Mela@nokia.com>
|
||||
|
|
|
@ -73,7 +73,7 @@ libsu_la_SOURCES = \
|
|||
su_os_nw.c \
|
||||
su_taglist.c su_tag.c su_tag_io.c \
|
||||
su_log.c su_global_log.c su_default_log.c su_module_debug.h \
|
||||
su_md5.c su_uniqueid.c su_bm.c string0.c $(OSXSOURCES)
|
||||
su_md5.c su_uniqueid.c su_bm.c smoothsort.c string0.c $(OSXSOURCES)
|
||||
|
||||
|
||||
EXTRA_libsu_la_SOURCES = \
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/**@file smoothsort.c
|
||||
* @brief Smoothsort implementation
|
||||
*
|
||||
* Smoothsort is a in-place sorting algorithm with performance of O(NlogN)
|
||||
* in worst case and O(n) in best case.
|
||||
*
|
||||
* @sa <a href="http://www.enterag.ch/hartwig/order/smoothsort.pdf">
|
||||
* "Smoothsort, an alternative for sorting in-situ", E.D. Dijkstra, EWD796a</a>,
|
||||
* <http://www.enterag.ch/hartwig/order/smoothsort.pdf>.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/** Description of current stretch */
|
||||
typedef struct {
|
||||
size_t b, c; /**< Leonardo numbers */
|
||||
unsigned longlong p; /**< Concatenation codification */
|
||||
} stretch;
|
||||
|
||||
/** Description of array */
|
||||
typedef struct
|
||||
{
|
||||
void *m;
|
||||
int (*less)(void *m, size_t a, size_t b);
|
||||
void (*swap)(void *m, size_t a, size_t b);
|
||||
} array;
|
||||
|
||||
static inline size_t stretch_up(stretch s[1])
|
||||
{
|
||||
size_t next;
|
||||
|
||||
s->p >>= 1;
|
||||
|
||||
next = s->b + s->c + 1, s->c = s->b, s->b = next;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
static inline size_t stretch_down(stretch s[1], unsigned bit)
|
||||
{
|
||||
size_t next;
|
||||
|
||||
s->p <<= 1, s->p |= bit;
|
||||
|
||||
next = s->c, s->c = s->b - s->c - 1, s->b = next;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
#if DEBUG_SMOOTHSORT
|
||||
static char const *binary(unsigned long long p)
|
||||
{
|
||||
static char binary[65];
|
||||
int i;
|
||||
|
||||
if (p == 0)
|
||||
return "0";
|
||||
|
||||
binary[64] = 0;
|
||||
|
||||
for (i = 64; p; p >>= 1)
|
||||
binary[--i] = "01"[p & 1];
|
||||
|
||||
return binary + i;
|
||||
}
|
||||
#else
|
||||
#define DEBUG(x) ((void)0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sift the root of the stretch.
|
||||
*
|
||||
* The low values are sifted up (towards index 0) from root.
|
||||
*
|
||||
* @param array description of array to sort
|
||||
* @param r root of the stretch
|
||||
* @param s description of current stretch
|
||||
*/
|
||||
static void sift(array const *array, size_t r, stretch s)
|
||||
{
|
||||
while (s.b >= 3) {
|
||||
size_t r2 = r - s.b + s.c;
|
||||
|
||||
if (!array->less(array->m, r - 1, r2)) {
|
||||
r2 = r - 1;
|
||||
stretch_down(&s, 0);
|
||||
}
|
||||
|
||||
if (array->less(array->m, r2, r))
|
||||
break;
|
||||
|
||||
DEBUG(("\tswap(%p @%zu <=> @%zu)\n", array, r, r2));
|
||||
|
||||
array->swap(array->m, r, r2); r = r2;
|
||||
|
||||
stretch_down(&s, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Trinkle the roots of the given stretches
|
||||
*
|
||||
* @param array description of array to sort
|
||||
* @param r root of the stretch
|
||||
* @param s description of stretches to concatenate
|
||||
*/
|
||||
static void trinkle(array const *array, size_t r, stretch s)
|
||||
{
|
||||
DEBUG(("trinkle(%p, %zu, (%u, %s))\n", array, r, s.b, binary(s.p)));
|
||||
|
||||
while (s.p != 0) {
|
||||
size_t r2, r3;
|
||||
|
||||
while ((s.p & 1) == 0)
|
||||
stretch_up(&s);
|
||||
|
||||
if (s.p == 1)
|
||||
break;
|
||||
|
||||
r3 = r - s.b;
|
||||
|
||||
if (array->less(array->m, r3, r))
|
||||
break;
|
||||
|
||||
s.p--;
|
||||
|
||||
if (s.b < 3) {
|
||||
DEBUG(("\tswap(%p @%zu <=> @%zu b=%u)\n", array, r, r3, s.b));
|
||||
array->swap(array->m, r, r3); r = r3;
|
||||
continue;
|
||||
}
|
||||
|
||||
r2 = r - s.b + s.c;
|
||||
|
||||
if (array->less(array->m, r2, r - 1)) {
|
||||
r2 = r - 1;
|
||||
stretch_down(&s, 0);
|
||||
}
|
||||
|
||||
if (array->less(array->m, r2, r3)) {
|
||||
DEBUG(("swap(%p [%zu]=[%zu])\n", array, r, r3));
|
||||
array->swap(array->m, r, r3); r = r3;
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(("\tswap(%p @%zu <=> @%zu b=%u)\n", array, r, r2, s.b));
|
||||
array->swap(array->m, r, r2); r = r2;
|
||||
stretch_down(&s, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
sift(array, r, s);
|
||||
}
|
||||
|
||||
/** Trinkles the stretches when the adjacent stretches are already trusty.
|
||||
*
|
||||
* @param array description of array to sort
|
||||
* @param r root of the stretch
|
||||
* @param stretch description of stretches to trinkle
|
||||
*/
|
||||
static void semitrinkle(array const *array, size_t r, stretch s)
|
||||
{
|
||||
size_t r1 = r - s.c;
|
||||
|
||||
DEBUG(("semitrinkle(%p, %zu, (%u, %s))\n", array, r, s.b, binary(s.p)));
|
||||
|
||||
if (array->less(array->m, r, r1)) {
|
||||
DEBUG(("\tswap(%p @%zu <=> @%zu b=%u)\n", array, r, r1, s.b));
|
||||
array->swap(array->m, r, r1);
|
||||
trinkle(array, r1, s);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sort array using smoothsort.
|
||||
*
|
||||
* Sort @a N elements from array @a base starting with index @a r with smoothsort.
|
||||
*
|
||||
* @param base pointer to array
|
||||
* @param r lowest index to sort
|
||||
* @param N number of elements to sort
|
||||
* @param less comparison function returning nonzero if m[a] < m[b]
|
||||
* @param swap swapper function exchanging elements m[a] and m[b]
|
||||
*/
|
||||
void su_smoothsort(void *base, size_t r, size_t N,
|
||||
int (*less)(void *m, size_t a, size_t b),
|
||||
void (*swap)(void *m, size_t a, size_t b))
|
||||
{
|
||||
stretch s = { 1, 1, 1 };
|
||||
size_t q;
|
||||
|
||||
array const array[1] = {{ base, less, swap }};
|
||||
|
||||
assert(less && swap);
|
||||
|
||||
if (base == NULL || N <= 1 || less == NULL || swap == NULL)
|
||||
return;
|
||||
|
||||
DEBUG(("\nsmoothsort(%p, %zu)\n", array, nmemb));
|
||||
|
||||
for (q = 1; q != N; q++, r++, s.p++) {
|
||||
DEBUG(("loop0 q=%zu, b=%u, p=%s \n", q, s.b, binary(s.p)));
|
||||
|
||||
if ((s.p & 7) == 3) {
|
||||
sift(array, r, s), stretch_up(&s), stretch_up(&s);
|
||||
}
|
||||
else /* if ((s.p & 3) == 1) */ { assert((s.p & 3) == 1);
|
||||
if (q + s.c < N)
|
||||
sift(array, r, s);
|
||||
else
|
||||
trinkle(array, r, s);
|
||||
|
||||
while (stretch_down(&s, 0) > 1)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
trinkle(array, r, s);
|
||||
|
||||
for (; q > 1; q--) {
|
||||
s.p--;
|
||||
|
||||
DEBUG(("loop1 q=%zu: b=%u p=%s\n", q, s.b, binary(s.p)));
|
||||
|
||||
if (s.b <= 1) {
|
||||
while ((s.p & 1) == 0)
|
||||
stretch_up(&s);
|
||||
--r;
|
||||
}
|
||||
else /* if b >= 3 */ {
|
||||
if (s.p) semitrinkle(array, r - (s.b - s.c), s);
|
||||
stretch_down(&s, 1);
|
||||
semitrinkle(array, --r, s);
|
||||
stretch_down(&s, 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file memccpy.c
|
||||
/**@internal @file memccpy.c
|
||||
* @brief The memccpy() replacement function.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file memcspn.c
|
||||
/**@internal @file memcspn.c
|
||||
* @brief The memcspn() replacement function.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file memmem.c
|
||||
/**@internal @file memmem.c
|
||||
*
|
||||
* @brief Backup implementation of memmem()
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/**@file memspn.c
|
||||
/**@internal @file memspn.c
|
||||
*
|
||||
* The memspn() replacement function.
|
||||
*
|
||||
* @author Pekka Pessi <Pekka.Pessi@nokia.com>
|
||||
|
|
|
@ -8,7 +8,7 @@ for SU_PORT in select kqueue devpoll epoll poll ; do
|
|||
|
||||
export SU_PORT
|
||||
|
||||
egrep -q -i '^#define have_(sys_)?'$SU_PORT ../../config.h ||
|
||||
egrep -i '^#define have_(sys_)?'$SU_PORT ../../config.h >/dev/null ||
|
||||
continue
|
||||
|
||||
run=yes
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue