2006-12-21 06:30:28 +00:00
|
|
|
/* -*- text -*- */
|
|
|
|
|
|
|
|
/**@MODULEPAGE "msg" - Message Parser Module
|
|
|
|
|
|
|
|
@section msg_meta Module Meta Information
|
|
|
|
|
|
|
|
This module contains parser and functions for manipulating messages and
|
|
|
|
headers for text-based protocols like SIP, HTTP or RTSP. It also
|
|
|
|
provides parsing of MIME headers and MIME multipart messages common to
|
|
|
|
these protocols.
|
|
|
|
|
|
|
|
@CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
|
|
|
|
|
|
@STATUS @SofiaSIP Core library
|
|
|
|
|
|
|
|
@LICENSE LGPL
|
|
|
|
|
|
|
|
@par Contributor(s):
|
|
|
|
- Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
|
|
|
|
|
|
@section msg_contents Contents of msg Module
|
|
|
|
|
|
|
|
The msg module contains the public header files as follows:
|
|
|
|
- <sofia-sip/msg.h> base message interfaces
|
|
|
|
- <sofia-sip/msg_types.h> message and header struct definitions and typedefs
|
|
|
|
- <sofia-sip/msg_protos.h> prototypes of header-specific functions for generic headers
|
|
|
|
- <sofia-sip/msg_header.h> function prototypes and macros for manipulating message
|
|
|
|
headers
|
|
|
|
- <sofia-sip/msg_addr.h> functions for accessing network addresses and I/O vectors
|
|
|
|
associated with the message
|
|
|
|
- <sofia-sip/msg_date.h> types and functions for handling dates and times
|
|
|
|
- <sofia-sip/msg_mime.h> types, function prototypes and macros for MIME headers
|
|
|
|
and @ref msg_multipart "multipart messages"
|
|
|
|
- <sofia-sip/msg_mime_protos.h> prototypes of MIME-header-specific functions
|
|
|
|
|
|
|
|
In addition to this interface, the @ref msg_parser "parser documentation"
|
|
|
|
contains description of the functionality required when an existing parser
|
|
|
|
is extended by a new header or a parser is created for a completely new
|
|
|
|
protocol. It is possible to add new headers to the parser or extend the
|
|
|
|
definition of existing ones. The header files used for constructing these
|
|
|
|
parsers are as follows:
|
|
|
|
- <sofia-sip/msg_parser.h> parsing functions, macros
|
|
|
|
- <sofia-sip/msg_mclass.h> message factory object definition
|
|
|
|
- <sofia-sip/msg_mclass_hash.h> hashing of header names
|
|
|
|
|
|
|
|
@section msg_overview Parsers, Messages and Headers
|
|
|
|
|
|
|
|
The Sofia @b msg module contains interface to the text-based parsers for
|
|
|
|
RFC822-like message, the header and message objects. Currently, there
|
|
|
|
are three parsers defined: SIP, HTTP, and MIME.
|
|
|
|
|
|
|
|
The C structure corresponding to each header is defined either in a
|
|
|
|
<sofia-sip/msg_types.h> or in a protocol-specific header file. These
|
|
|
|
protocol-specific header files include <sofia-sip/sip.h>, <sofia-sip/http.h>, and
|
|
|
|
<sofia-sip/msg_mime.h>. For each header, there is defined a @em header @em class
|
|
|
|
structure, some standard functions, and tags for including them in tag
|
|
|
|
lists.
|
|
|
|
|
|
|
|
As a convention, all the identifiers for SIP headers start with prefix @c
|
|
|
|
sip and all the macros with @c SIP. Same thing holds for HTTP, too: it
|
|
|
|
uses prefix @c http. However, the MIME headers
|
|
|
|
and the functions related to them are defined within the @b msg module and
|
|
|
|
they use prefix @c msg. If a SIP or HTTP header uses a structure
|
|
|
|
defined in <sofia-sip/msg_types.h>, there is a typedef suitable for the particular
|
|
|
|
protocol, for example @b Accept header is defined multiple times:
|
|
|
|
|
|
|
|
@code
|
|
|
|
typedef struct msg_accept_s sip_accept_t;
|
|
|
|
typedef struct msg_accept_s http_accept_t;
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
For header @e X of protocol @e NS, there are types, functions, macros and
|
|
|
|
header class as follows:
|
|
|
|
|
|
|
|
- @c ns_X_t is the structure used to store parsed header,
|
|
|
|
- @c ns_hclass_t @c ns_X_class[] contains the @em header @em class
|
|
|
|
for header X,
|
|
|
|
- @c NS_X_INIT() initializes a static instance of @c ns_X_t,
|
|
|
|
- @c ns_X_init() initializes a dynamic instance of @c ns_X_t,
|
|
|
|
- @c ns_is_X() tests if header object is instance of header X,
|
|
|
|
- @c ns_X_make() creates a header X object by decoding given string,
|
|
|
|
- @c ns_X_format() creates a header X object by decoding given
|
|
|
|
@c printf() list,
|
|
|
|
- @c ns_X_dup() duplicates (deeply copies) the header X,
|
|
|
|
- @c ns_X_copy() copies the header X,
|
|
|
|
- @c NSTAG_X() is used include instance of @c ns_X_t in a tag list, and
|
|
|
|
- @c NSTAG_X_STR() is used to include string containing value header
|
|
|
|
in a tag list.
|
|
|
|
|
|
|
|
The declarations of header tags and the prototypes for these functions can
|
|
|
|
be imported separately from the type definitions, for instance, the tags
|
|
|
|
related to SIP headers are declared in the include file
|
|
|
|
<sofia-sip/sip_tag.h>, and the header-specific functions in
|
|
|
|
<sofia-sip/sip_header.h>.
|
|
|
|
|
|
|
|
@section parser_intro Parsing Text Messages
|
|
|
|
|
|
|
|
Sofia text parser follows @em recursive-descent principle. In other words,
|
|
|
|
it is a program that descends the syntax tree top-down recursively.
|
|
|
|
(All syntax trees have root at top and they grow downwards.)
|
|
|
|
|
|
|
|
In the case of SIP, HTTP and other similar protocols, such a parser is very
|
|
|
|
efficient. The parser can choose between different forms based on each
|
|
|
|
token, as the protocol syntax is carefully designed so that it requires only
|
|
|
|
minimal scan-ahead. It is also easy to extend a recursive-descent parser via
|
|
|
|
a standard API, unlike, for instance, a LALR parser generated by @em Bison.
|
|
|
|
|
|
|
|
The abstract message module @b msg contains a high-level parser engine that
|
|
|
|
drives the parsing process and invokes the protocol-specific parser for each
|
|
|
|
header. As there is no low-layer framing between the RFC822-style messages,
|
|
|
|
the parser considers any received data, be it a UDP datagram or a TCP
|
|
|
|
stream, as a @em byte @em stream. The protocol-specific parsers controls how
|
|
|
|
a byte stream is split into separate messages or if it consists of a single
|
|
|
|
message only.
|
|
|
|
|
|
|
|
The parser engine works by separating stream into fragments, then passing
|
|
|
|
the fragment to a suitable parser. A fragment is a piece of message that is
|
|
|
|
parsed during a single step: the first line, each header, the empty line
|
|
|
|
between headers and message body, the message body. (In case of HTTP, the
|
|
|
|
message body can consists of multiple fragments known as chunks.)
|
|
|
|
|
|
|
|
The parser starts by separating the first line (e.g., request or status
|
|
|
|
line) from the byte stream, then passing the line to the suitable parser.
|
|
|
|
After first line comes the message headers. The parser continues parsing
|
|
|
|
process by extracting headers, each on their own line, from the stream and
|
|
|
|
passing contents of each header to its parser. The message structure is
|
|
|
|
populated based on the parsing results. When an empty line - indicating end
|
|
|
|
of headers - is encountered, the control is passed to the protocol-specific
|
|
|
|
parser. Protocol-specific functions take care of extracting the possible
|
|
|
|
message body from the byte stream.
|
|
|
|
|
|
|
|
After parsing process is completed, it can be given to the upper layers
|
|
|
|
(typically a protocol state machine). The parser continues processing the
|
|
|
|
stream and feeding the messages to protocol engine until the end of the
|
|
|
|
stream is reached.
|
|
|
|
|
|
|
|
@image html sip-parser.gif Separating byte stream to messages
|
|
|
|
@image latex sip-parser.eps Separating byte stream to messages
|
|
|
|
|
|
|
|
When the parsing process has completed, the first line, each header,
|
|
|
|
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,
|
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
2007-10-11 14:16:59 +00:00
|
|
|
defined in <sofia-sip/msg.h>. The internal structure of #msg_t is known only within @b
|
2006-12-21 06:30:28 +00:00
|
|
|
msg module and it is opaque to other modules.
|
|
|
|
|
|
|
|
The @b msg parser engine also drives the reverse process, invoking the
|
|
|
|
encoding method of each fragment so that the whole outgoing message can be
|
|
|
|
encoded properly.
|
|
|
|
|
|
|
|
@section msg_header_struct Message Header as a C struct
|
|
|
|
|
|
|
|
Just separating headers from each other and from the message body is not
|
|
|
|
usually enough. When a header contains structured data, the header contents
|
|
|
|
should be converted to a form that is convenient to use from C programs. For
|
|
|
|
that purpose, the message parser needs a parsing function specific to each
|
|
|
|
individual header. This parsing function divides the contents of the header
|
|
|
|
into semantically meaningful segments and stores the result in the structure
|
|
|
|
specific to each header.
|
|
|
|
|
|
|
|
The parser engine passes the fragment contents to the parsing function after
|
|
|
|
it has separated the fragment from the rest of the message. The parser
|
|
|
|
engine selects correct @e header @e class either by implication (in case of
|
|
|
|
first line), or it searches for the header class from the hash table using
|
|
|
|
the header name as the hash key. The @e header @e class contains a pointer
|
|
|
|
to the parsing function. The parser has also special header classes for
|
|
|
|
headers with errors and @e unknown headers, header with a name that is not
|
|
|
|
regocnized by the parser.
|
|
|
|
|
|
|
|
For instance, the Accept header has following syntax:
|
|
|
|
@code
|
|
|
|
Accept = "Accept" ":" #( media-range [ accept-params ] )
|
|
|
|
|
|
|
|
media-range = ( "*" "/" "*"
|
|
|
|
| ( type "/" "*" )
|
|
|
|
| ( type "/" subtype ) ) *( ";" parameter )
|
|
|
|
|
|
|
|
accept-params = ";" "q" "=" qvalue *( accept-extension )
|
|
|
|
|
|
|
|
accept-extension = ";" token [ "=" ( token | quoted-string ) ]
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
When an Accept header is parsed, the header parser function (msg_accept_d())
|
|
|
|
separates the @e type, @e subtype, and each parameter in the list to
|
|
|
|
strings. The parsing result is assigned to a #msg_accept_t structure, which is
|
|
|
|
defined as follows:
|
|
|
|
|
|
|
|
@code
|
|
|
|
typedef struct msg_accept_s
|
|
|
|
{
|
|
|
|
msg_common_t ac_common[1]; //< Common fragment info
|
|
|
|
msg_accept_t *ac_next; //< Pointer to next Accept header
|
|
|
|
char const *ac_type; //< Pointer to type/subtype
|
|
|
|
char const *ac_subtype; //< Points after first slash in type
|
|
|
|
msg_param_t const *ac_params; //< List of parameters
|
|
|
|
msg_param_t ac_q; //< Value of q parameter
|
|
|
|
}
|
|
|
|
msg_accept_t;
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
The string containing the @e type is put into the @c ac_type field, the @e
|
|
|
|
subtype after slash in the can be found in the @c ac_subtype field, and the
|
|
|
|
list of @e accept-params (together with media-specific-parameters) is put in
|
|
|
|
the @c ac_params array. If there is a @e q parameter present, a pointer to
|
|
|
|
the @c qvalue is assigned to @c ac_q field.
|
|
|
|
|
|
|
|
In the beginning of the header structure there are two boilerplate members.
|
|
|
|
The @c ac_common[1] contains information common to all message fragments.
|
|
|
|
The @c ac_next is a pointer to next header field with the same name, in case
|
|
|
|
a message contains multiple @b Accept headers or multiple comma-separated
|
|
|
|
header fields are located in a single line.
|
|
|
|
|
|
|
|
@section msg_object_example Representing a Message as a C struct
|
|
|
|
|
|
|
|
It is not enough to represent a message as a list of headers following each
|
|
|
|
other. The programmer also needs a convenient way to access certain headers
|
|
|
|
at the message level, for example, accessing directly the @b Accept header
|
|
|
|
instead of going through all headers and examining their name. The
|
|
|
|
structured view to the message is provided via a message-specific C struct.
|
|
|
|
In general, its type is msg_pub_t (it provides public view to message). The
|
|
|
|
protocol-specific type is #sip_t, #http_t or #msg_multipart_t for
|
|
|
|
SIP, HTTP and MIME, respectively.
|
|
|
|
|
|
|
|
So, a single message is represented by two objects, first object (#msg_t) is
|
|
|
|
private to the @b msg module and opaque by an application programmer, second
|
|
|
|
(#sip_t, #http_t or #msg_multipart_t) is a public protocol-specific
|
|
|
|
structure accessible by all.
|
|
|
|
|
|
|
|
@note The application programmer can obtain a pointer to the
|
|
|
|
protocol-specific structure from an #msg_t object using msg_public()
|
|
|
|
function. The msg_public() takes a protocol tag, a well-known identifier, as
|
|
|
|
its argument. The SIP, HTTP and MIME already define a wrapper around
|
|
|
|
msg_public(), for example, a #sip_t structure can be obtained with
|
|
|
|
sip_object() function (or macro).
|
|
|
|
|
|
|
|
As an example, the #sip_t structure is defined as follows:
|
|
|
|
@code
|
|
|
|
typedef struct sip_s {
|
|
|
|
msg_common_t sip_common[1]; // Used with recursive inclusion
|
|
|
|
msg_pub_t *sip_next; // Ditto
|
|
|
|
void *sip_user; // Application data
|
|
|
|
unsigned sip_size; // Size of the structure with
|
|
|
|
// extension headers
|
|
|
|
int sip_flags; // Parser flags
|
|
|
|
|
|
|
|
sip_error_t *sip_error; // Erroneous headers
|
|
|
|
|
|
|
|
sip_request_t *sip_request; // Request line
|
|
|
|
sip_status_t *sip_status; // Status line
|
|
|
|
|
|
|
|
sip_via_t *sip_via; // Via (v)
|
|
|
|
sip_route_t *sip_route; // Route
|
|
|
|
sip_record_route_t *sip_record_route; // Record-Route
|
|
|
|
sip_max_forwards_t *sip_max_forwards; // Max-Forwards
|
|
|
|
...
|
|
|
|
} sip_t;
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
As you can see above, the public #sip_t structure contains the common
|
|
|
|
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
|
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
2007-10-11 14:16:59 +00:00
|
|
|
parsing and printing process. They are documented in the <sofia-sip/msg.h>. These
|
2006-12-21 06:30:28 +00:00
|
|
|
boilerplate members are followed by the pointers to various message
|
|
|
|
elements and headers.
|
|
|
|
|
|
|
|
@section msg_parsing_example Result of Parsing Process
|
|
|
|
|
|
|
|
Let us now show how a simple message is parsed and presented to the
|
|
|
|
applications. As an exampe, we choose a SIP request message with method BYE,
|
|
|
|
including only the mandatory fields:
|
|
|
|
@code
|
|
|
|
BYE sip:joe@example.com SIP/2.0
|
|
|
|
Via: SIP/2.0/UDP sip.example.edu;branch=d7f2e89c.74a72681
|
|
|
|
Via: SIP/2.0/UDP pc104.example.edu:1030;maddr=110.213.33.19
|
|
|
|
From: Bobby Brown <sip:bb@example.edu>;tag=77241a86
|
|
|
|
To: Joe User <sip:joe@example.com>;tag=7c6276c1
|
|
|
|
Call-ID: 4c4e911b@pc104.example.edu
|
|
|
|
CSeq: 2
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
The figure below shows the layout of the BYE message above after parsing:
|
|
|
|
|
|
|
|
@image html sip-parser2.gif BYE message and its representation in C
|
|
|
|
@image latex sip-parser2.eps BYE message and its representation in C
|
|
|
|
|
|
|
|
The leftmost box represents the message of type #msg_t. Next box from
|
|
|
|
the left reprents the #sip_t structure, which contains pointers to a
|
|
|
|
header objects. The next column contains the header objects. There is
|
|
|
|
one header object for each message fragment. The rightmost box represents
|
|
|
|
the I/O buffer used when the message was received. Note that the I/O
|
|
|
|
buffer may be non-continous and composed of many separate memory areas.
|
|
|
|
|
|
|
|
The message object has link to the public message structure (@a
|
|
|
|
m_object), to the dual-linked fragment chain (@a m_frags) and to the I/O
|
|
|
|
buffer (@a m_buffer). The public message structure contains pointers to
|
|
|
|
the headers according to their type. If there are multiple headers of
|
|
|
|
the same type (like there are two Via headers in the above message), the
|
|
|
|
headers are put into a single-linked list.
|
|
|
|
|
|
|
|
Each fragment has pointers to successing and preceding fragment. It also
|
|
|
|
contains pointer to the corresponding data within the I/O buffer and its
|
|
|
|
length.
|
|
|
|
|
|
|
|
The main purpose of the fragment chain is to preserve the original order
|
|
|
|
of the headers. If there were an third Via header after CSeq in the
|
|
|
|
message, the fragment representing it would be after the CSeq header in
|
|
|
|
the fragment chain but after second Via in the header list.
|
|
|
|
|
|
|
|
@section msg_parsing_memory Example: Parsing a Complete Message
|
|
|
|
|
|
|
|
The following code fragment is an example of parsing a complete message. The
|
|
|
|
parsing process is more hairy when there is stream to be parsed.
|
|
|
|
|
|
|
|
@code
|
|
|
|
msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len)
|
|
|
|
{
|
|
|
|
msg_t *msg;
|
|
|
|
int m;
|
|
|
|
msg_iovec_t iovec[2] = {{ 0 }};
|
|
|
|
|
|
|
|
msg = msg_create(mclass, 0);
|
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
m = msg_recv_iovec(msg, iovec, 2, n, 1);
|
|
|
|
if (m < 0) {
|
|
|
|
msg_destroy(msg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
assert(m <= 2);
|
|
|
|
assert(iovec[0].mv_len + iovec[1].mv_len == n);
|
|
|
|
|
|
|
|
memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len);
|
|
|
|
if (m == 2)
|
|
|
|
memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len);
|
|
|
|
|
|
|
|
msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1);
|
|
|
|
|
|
|
|
m = msg_extract(msg);
|
|
|
|
assert(m != 0);
|
|
|
|
if (m < 0) {
|
|
|
|
msg_destroy(msg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
Let's go through this simple function, step by step. First, we get the @a
|
|
|
|
data pointer and its size in bytes, @a len. We first initialize an I/O
|
|
|
|
vector used to represent message with the parser.
|
|
|
|
|
|
|
|
@code
|
|
|
|
msg_t *parse_memory(msg_mclass_t const *mclass, char const data[], int len)
|
|
|
|
{
|
|
|
|
msg_t *msg;
|
|
|
|
int m;
|
|
|
|
msg_iovec_t iovec[2] = {{ 0 }};
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
The message class @a mclass (a parser driver object, #msg_mclass_t) is used
|
|
|
|
to represent a particular protocol-specific parser instance. When a message
|
|
|
|
object is created, it is given as an argument to msg_create() function:
|
|
|
|
|
|
|
|
@code
|
|
|
|
msg = msg_create(mclass, 0);
|
|
|
|
if (!msg)
|
|
|
|
return NULL;
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
Next we obtain a memory buffer for data with msg_recv_iovec(). The memory
|
|
|
|
buffer is usually a single continous memory area, but in some cases it may
|
|
|
|
consist of two distinct areas. Therefore the @a iovec is used here to pass
|
|
|
|
the buffers around. The @a iovec is also very handly as it can be directly
|
|
|
|
passed to various system I/O calls.
|
|
|
|
|
|
|
|
@code
|
|
|
|
m = msg_recv_iovec(msg, iovec, 2, n, 1);
|
|
|
|
if (m < 0) {
|
|
|
|
msg_destroy(msg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
These assumptions hold always true when you call msg_recv_iovec() first
|
|
|
|
time with a complete message:
|
|
|
|
|
|
|
|
@code
|
|
|
|
assert(m >= 1 && m <= 2);
|
|
|
|
assert(iovec[0].mv_len + iovec[1].mv_len == n);
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
Next, we copy the data to the I/O vector and commit the copied data to the
|
|
|
|
message. Earlier with msg_recv_iovec() we allocated buffer space for data,
|
|
|
|
now calling msg_recv_commit() indicates that valid data has been copied to
|
|
|
|
the buffer. The last parameter to msg_recv_commit() indicates that the end
|
|
|
|
of stream is encountered and no more data is to be expected.
|
|
|
|
|
|
|
|
@code
|
|
|
|
memcpy(iovec[0].mv_base, data, n = iovec[0].mv_len);
|
|
|
|
if (m == 2)
|
|
|
|
memcpy(iovec[1].mv_base + n, data + n, iovec[1].mv_len);
|
|
|
|
|
|
|
|
msg_recv_commit(msg, iovec[0].mv_len + iovec[1].mv_len, 1);
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
We call msg_extract() next; it takes care of parsing the message. A fatal
|
|
|
|
parsing error is indicated by returning -1. If the message is incomplete,
|
|
|
|
msg_extract() returns 0. When a complete message has been parsed, a positive
|
|
|
|
value is returned. We know that a message cannot be incomplete, as a call to
|
|
|
|
msg_recv_commit() indicated to the parser that the end-of-stream has been
|
|
|
|
encountered.
|
|
|
|
|
|
|
|
@code
|
|
|
|
m = msg_extract(msg);
|
|
|
|
assert(m != 0);
|
|
|
|
if (m < 0) {
|
|
|
|
msg_destroy(msg);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@class msg_s msg.h
|
|
|
|
*
|
|
|
|
* @brief Message object.
|
|
|
|
*
|
|
|
|
* The message object is used by Sofia parsers for SIP and HTTP
|
|
|
|
* protocols. The message object has an abstract, protocol-independent
|
|
|
|
* inteface type #msg_t, and a separate public protocol-specific interface
|
|
|
|
* #msg_pub_t (which is typedef'ed to #sip_t or #http_t depending
|
|
|
|
* on the protocol).
|
|
|
|
*
|
|
|
|
* The main interface to abstract messages is defined in <sofia-sip/msg.h>. The
|
|
|
|
* network I/O interface used by transport protocols is defined in
|
|
|
|
* <sofia-sip/msg_addr.h>. The protocol-specific parser table, also known as message
|
|
|
|
* class, is defined in <sofia-sip/msg_mclass.h>. (The message class is used as a
|
|
|
|
* factory object when a message object is created with msg_create()).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@typedef typedef struct msg_s msg_t;
|
|
|
|
*
|
|
|
|
* Message object.
|
|
|
|
*
|
|
|
|
* The @a msg_t is the type of a message object used by Sofia signaling
|
|
|
|
* protocols and parsers. Its contents are not directly accessible.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**@typedef typedef struct msg_common_s msg_common_t;
|
|
|
|
*
|
|
|
|
* Common part of header.
|
|
|
|
*
|
|
|
|
* The @a msg_common_t is the base type of a message headers used by
|
|
|
|
* protocol parsers. Instead of #msg_common_t, most interfaces use
|
|
|
|
* #msg_header_t, which is supposed to be a union of all possible headers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup msg_parser Parser Building Blocks
|
|
|
|
*
|
|
|
|
* This submodule contains the functions and types for building a
|
|
|
|
* protocol-specific parser.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup msg_headers Headers
|
|
|
|
*
|
|
|
|
* This submodule contains the functions and types for handling message
|
|
|
|
* headers and other elements.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup msg_mime MIME Headers
|
|
|
|
*
|
|
|
|
* This submodule contains the header classes, functions and types for
|
|
|
|
* handling MIME headers (@RFC2045) and MIME multipart (@RFC2046) processing.
|
|
|
|
*
|
|
|
|
* The MIME headers implemented are as follows:
|
|
|
|
* - @ref msg_accept "@b Accept header"
|
|
|
|
* - @ref msg_accept_charset "@b Accept-Charser header"
|
|
|
|
* - @ref msg_accept_encoding "@b Accept-Encoding header"
|
|
|
|
* - @ref msg_accept_language "@b Accept-Language header"
|
|
|
|
* - @ref msg_content_disposition "@b Content-Disposition header"
|
|
|
|
* - @ref msg_content_encoding "@b Content-Encoding header"
|
|
|
|
* - @ref msg_content_id "@b Content-ID header"
|
|
|
|
* - @ref msg_content_location "@b Content-Location header"
|
|
|
|
* - @ref msg_content_language "@b Content-Language header"
|
|
|
|
* - @ref msg_content_md5 "@b Content-MD5 header"
|
|
|
|
* - @ref msg_content_transfer_encoding "@b Content-Transfer-Encoding header"
|
|
|
|
* - @ref msg_mime_version "@b MIME-Version header"
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup test_msg Testing Parser
|
|
|
|
*
|
|
|
|
* This submodule contains the functions and types for building a
|
|
|
|
* parser objects for testing purposes.
|
|
|
|
*/
|