609 lines
23 KiB
C
609 lines
23 KiB
C
/* -*- c -*- */
|
|
|
|
/**@MODULEPAGE "sip" - SIP Parser Module
|
|
*
|
|
* @section sip_meta Module Meta Information
|
|
*
|
|
* The Sofia @b sip module contains interface to the SIP parser and the
|
|
* header and message objects.
|
|
*
|
|
* @CONTACT Pekka Pessi <Pekka.Pessi@nokia.com>
|
|
*
|
|
* @STATUS @SofiaSIP Core library
|
|
*
|
|
* @LICENSE LGPL
|
|
*
|
|
* @section sip_overview Overview
|
|
*
|
|
* The structure of each header is defined in @b <sip.h>. In addition to the
|
|
* header structure, there is defined a @em header @em class structure and
|
|
* some standard functions for each header in the include file @b
|
|
* <sofia-sip/sip_header.h>. For header @c X, there are types, functions,
|
|
* macros and header class declared in <sofia-sip/sip_protos.h> and
|
|
* <sofia-sip/sip_hclass.h>. See @ref sip_header_x for detailed description
|
|
* of these header-specific boilerplate declarations.
|
|
*
|
|
* In addition to this interface, the @ref sip_parser "SIP parser documentation"
|
|
* contains description of the functionality required when a parser is
|
|
* extended by a new header. It is possible to add new headers to the SIP
|
|
* parser or extend the definition of existing ones.
|
|
*
|
|
* @section sip_parser_intro Parsing SIP Messages
|
|
*
|
|
* Sofia SIP parser follows @em recursive-descent principle. In other words,
|
|
* it is a program that descends the SIP syntax tree top-down recursively.
|
|
* (All syntax trees have root at top and they grow downwards.)
|
|
*
|
|
* In the case of SIP such a parser is very efficient. The parser can choose
|
|
* between different forms based on each token, as SIP 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 SIP parser for each
|
|
* header. As there are no framing between SIP messages, the parser
|
|
* considers any received data, be it a UDP datagram or a TCP stream, as a
|
|
* @em message @em stream, which may consist of one or more SIP messages.
|
|
* The parser works by first separating stream into fragments, then building
|
|
* a complete message based on parsing result. After a message is completed,
|
|
* it can be given to the message stream customer (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.
|
|
*
|
|
* For each message, the parser starts by separating the first fragment,
|
|
* which is either a request or status line. After the first line has been
|
|
* processed, the parser engine continues by separating the headers
|
|
* one-by-one from the message. After the parser encounters an empty line
|
|
* separating the headers and the message body (payload), it invokes a
|
|
* function parsing the separator and payload fragment(s). When the message
|
|
* is complete, the parser can hand the message over to the protocol engine.
|
|
* Then it is ready to start again with first fragment of the next message.
|
|
*
|
|
* @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 request or status line, each
|
|
* header, separator and the payload 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 buffers for the message, the
|
|
* fragment chain, and a whole other stuff is held by the generic message
|
|
* type, #msg_t, defined in <msg.h>. The internal structure of #msg_t is
|
|
* known only within @b msg module and it is hidden from other modules.
|
|
*
|
|
* The abstract message module @b msg also drives the reverse process,
|
|
* invoking the encoding method of each fragment so that the whole outgoing
|
|
* SIP message is encoded properly.
|
|
*
|
|
* @section sip_header_struct SIP 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 special function
|
|
* for each individual header. The header-specific parsing function divides
|
|
* the contents of the header into semantically meaningful segments and
|
|
* stores the result in a header-specific structure.
|
|
*
|
|
* The parser passes the fragment contents to a parsing function immediately
|
|
* after it has separated a fragment from the message. The parsing function
|
|
* is defined by the @e header @e class. The header class is either
|
|
* determined by the fragment position (first line, separator line or
|
|
* payload), or it is found from the hash table using the header name as
|
|
* key. There is also a special header class for @e unknown headers, headers
|
|
* with a name that is not regocnized by the parser.
|
|
*
|
|
* For instance, the @From header has following syntax:
|
|
*
|
|
* @code
|
|
* from = ("From" | "f") ":"
|
|
* ( name-addr | addr-spec ) *( ";" addr-params )
|
|
* name-addr = [ display-name ] "<" addr-spec ">"
|
|
* addr-spec = SIP-URL | URI
|
|
* display-name = *token | quoted-string
|
|
* addr-params = *( tag-param | generic-param )
|
|
* tag-param = "tag" "=" ( token | quoted-string )
|
|
* @endcode
|
|
*
|
|
* When a @From header is parsed, the header parser function sip_from_d()
|
|
* separates the @e display-name, @e addr-spec and each parameter in the @e
|
|
* addr-params list. The parsing result is assigned to a #sip_from_t
|
|
* structure, which is defined as follows:
|
|
*
|
|
* @code
|
|
* typedef struct sip_addr_s {
|
|
* sip_common_t a_common[1];
|
|
* sip_unknown_t *a_next;
|
|
* char const *a_display;
|
|
* url_t a_url[1];
|
|
* sip_param_t const *a_params;
|
|
* char const *a_tag;
|
|
* } sip_from_t;
|
|
* @endcode
|
|
*
|
|
* The string containing the @e display-name is put into the @c a_display
|
|
* field, the URL contents can be found in the @c a_url field, and the list
|
|
* of @e addr-params parameters is put in the @c a_params array. If there
|
|
* is a @e tag-param present, a pointer to the parameter value is assigned
|
|
* to @c a_tag field.
|
|
*
|
|
* @section sip_msg_struct SIP Message as a C struct
|
|
*
|
|
* It is not enough to represent a SIP message as a collection of headers
|
|
* following each other. The programmer also needs a convenient way to
|
|
* access certain headers at the SIP message level, for example, accessing
|
|
* directly the @From header instead of going through all headers and
|
|
* examining their name. The structured view to the SIP message is provided
|
|
* via a C struct with type #sip_t.
|
|
*
|
|
* In other words, a single message is represented by two types, first type
|
|
* (#msg_t) is private to the msg module and inaccessable by an application
|
|
* programmer, second (#sip_t) is a public structure containing the parsed
|
|
* headers.
|
|
*
|
|
* 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;
|
|
* int sip_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; // @RecordRoute
|
|
* sip_max_forwards_t *sip_max_forwards; // @MaxForwards
|
|
* ...
|
|
* } 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
|
|
* parsing and printing process. They are documented in the <msg.h>. These
|
|
* boilerplate members are followed by the pointers to various message
|
|
* elements and headers.
|
|
*
|
|
* @note Within the @b msg module, the public structure is known as
|
|
* #msg_pub_t. The application programmer can cast a #msg_t pointer to
|
|
* #sip_t with sip_object() function (or macro).
|
|
*
|
|
*
|
|
* @section sip_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 BYE message with only the
|
|
* mandatory fields included:
|
|
* @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 header 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 the second @Via in the header list.
|
|
*
|
|
*/
|
|
|
|
/**@defgroup sip_headers SIP Headers
|
|
*
|
|
* SIP headers and other SIP message elements.
|
|
*
|
|
* For each SIP header recognized by the SIP module, there is a header
|
|
* structure containing the parsed value. The header structure name is
|
|
* generated from the header name by lowercasing the name, replacing the
|
|
* non-alphanumeric characters (usually just minus "-") with underscore "_"
|
|
* characters, and then adding prefix @c sip_ and suffix @c _t. For
|
|
* instance, the contents of header "MIME-Version" is stored in a structure
|
|
* called sip_mime_version_t.
|
|
*
|
|
*/
|
|
|
|
/**@ingroup sip_headers
|
|
* @defgroup sip_header_x SIP Header X - Conventions
|
|
*
|
|
* For a SIP header X, there are types, functions, macros and global data
|
|
* declared in <sofia-sip/sip_protos.h> and <sofia-sip/sip_hclass.h> as
|
|
* follows:
|
|
* - #sip_X_t is the structure used to store parsed header,
|
|
* - SIP_X_INIT() initializes a static instance of #sip_X_t,
|
|
* - sip_X_init() initializes a dynamic instance of #sip_X_t,
|
|
* - sip_is_X() tests if header object is instance of header X,
|
|
* - sip_X_make() creates a header X object by decoding given string,
|
|
* - sip_X_format() creates a header X object by decoding given
|
|
* printf() list,
|
|
* - sip_X_dup() duplicates (deeply copies) the header X,
|
|
* - sip_X_copy() copies the header X,
|
|
* - #msg_hclass_t #sip_X_class[] contains the @em header @em class
|
|
* for header X.
|
|
*
|
|
* All header structures contain the common part, a #sip_common_t structure
|
|
* (@a X_common[]), a link to the next header in list (@a X_next), and
|
|
* various fields describing the header value (in this case, @a X_value).
|
|
* The header structure looks like this:
|
|
* @code
|
|
* typedef struct sip_X_s
|
|
* {
|
|
* struct msg_common_s {
|
|
* msg_header_t *h_succ; // Pointer to succeeding fragment
|
|
* msg_header_t **h_prev; // Pointer to preceeding fragment
|
|
* msg_hclass_t *h_class; // Header class
|
|
* void const *h_data; // Encoded data
|
|
* usize_t h_len; // Encoding length (including CRLF)
|
|
* } X_common[1];
|
|
* sip_X_t *X_next; // Link to next X header field
|
|
* uint32_t X_value; // Value of X
|
|
* msg_param_t *X_param; // List of parameters
|
|
* } sip_X_t;
|
|
* @endcode
|
|
*
|
|
* The common structure #msg_common_t (aka #sip_common_t)
|
|
* can be considered as a base class for all
|
|
* headers. The structure contains the pointers for dual-linked
|
|
* fragment chain (@a h_succ, @a h_prev), a pointer to header class (@a
|
|
* h_class), a pointer to the text encoding of header contents (@a h_data)
|
|
* and the length of the encoding (@a h_len). (@a X_common is an array of size
|
|
* 1, as it makes it easy to cast a header pointer to a pointer to
|
|
* msg_common_t.)
|
|
*
|
|
* The @a X_next is a pointer to another header (usually a pointer to
|
|
* structure of same type). If there are multiple headers with same name,
|
|
* like the two "Via" headers in the example above, the @a X_next is used to
|
|
* link the second header to the first. The fragment chain cannot be used
|
|
* for this purpose as the headers with same name are not necessarily
|
|
* adjacent in the parsed message.
|
|
*
|
|
* The rest of the fields contain the parsed or decoded representation of
|
|
* the header. In this case, it is a 32-bit integer followed by a list of
|
|
* parameters. The content of parameters is not parsed, they are just
|
|
* separated from each other and then stored in an dynamically allocated
|
|
* array of string pointers. Pointer to the array is stored to @a X_params.
|
|
*
|
|
* For more complex header structures, see #sip_contact_t or #sip_rack_t.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**The structure #sip_X_t contains representation of a SIP
|
|
* @ref sip_header_x "X" header.
|
|
*
|
|
* The #sip_X_t is defined as follows:
|
|
* @code
|
|
* typedef struct sip_X_s {
|
|
* msg_common_t X_common[1]; // Common fragment info
|
|
* sip_X_t *X_next; // Link to next X header field
|
|
* uint32_t X_value; // Value of X
|
|
* msg_param_t *X_param; // List of parameters
|
|
* } sip_X_t;
|
|
* @endcode
|
|
*/
|
|
typedef struct sip_X_s sip_X_t;
|
|
|
|
/**@var msg_hclass_t sip_X_class[];
|
|
* @brief Header class for SIP X.
|
|
*
|
|
* The header class sip_X_class defines how a SIP
|
|
* X is parsed and printed. It also
|
|
* contains methods used by SIP parser and other functions
|
|
* to manipulate the sip_X_t header structure.
|
|
*
|
|
*/
|
|
SIP_DLL extern msg_hclass_t sip_X_class[];
|
|
|
|
enum {
|
|
/** Hash of X. @internal */
|
|
sip_X_hash = hash
|
|
};
|
|
|
|
/** Parse a X. @internal */
|
|
msg_parse_f sip_X_d;
|
|
|
|
/** Print a X. @internal */
|
|
msg_print_f sip_X_e;
|
|
|
|
/**Initializer for structure sip_X_t.
|
|
*
|
|
* A static sip_X_t structure must be initialized
|
|
* with the SIP_X_INIT() macro. For instance,
|
|
* @code
|
|
*
|
|
* sip_X_t sip_X = SIP_X_INIT;
|
|
*
|
|
* @endcode
|
|
* @HI
|
|
*/
|
|
#define SIP_X_INIT() SIP_HDR_INIT(X)
|
|
|
|
/**Initialize a structure sip_X_t.
|
|
*
|
|
* An sip_X_t structure can be initialized with the
|
|
* sip_X_init() function/macro. For instance,
|
|
* @code
|
|
*
|
|
* sip_X_t sip_X;
|
|
*
|
|
* sip_X_init(&sip_X);
|
|
*
|
|
* @endcode
|
|
* @HI
|
|
*/
|
|
#if SU_HAVE_INLINE
|
|
su_inline sip_X_t *sip_X_init(sip_X_t x[1])
|
|
{
|
|
return SIP_HEADER_INIT(x, sip_X_class, sizeof(sip_X_t));
|
|
}
|
|
#else
|
|
#define sip_X_init(x) \
|
|
SIP_HEADER_INIT(x, sip_X_class, sizeof(sip_X_t))
|
|
#endif
|
|
|
|
/**Test if header object is instance of sip_X_t.
|
|
*
|
|
* The function sip_is_X() returns true (nonzero) if
|
|
* the header class is an instance of X
|
|
* object and false (zero) otherwise.
|
|
*
|
|
* @param header pointer to the header structure to be tested
|
|
*
|
|
* @return
|
|
* The function sip_is_X() returns true (nonzero) if
|
|
* the header object is an instance of header X and
|
|
* false (zero) otherwise.
|
|
*/
|
|
#if SU_HAVE_INLINE
|
|
su_inline int sip_is_X(sip_header_t const *header)
|
|
{
|
|
return header && header->sh_class->hc_id == sip_hdr_X;
|
|
}
|
|
#else
|
|
int sip_is_X(sip_header_t const *header);
|
|
#endif
|
|
|
|
#define sip_X_p(h) sip_is_X((h))
|
|
|
|
/**Duplicate (deep copy) @c sip_X_t.
|
|
*
|
|
* The function sip_X_dup() duplicates a header
|
|
* structure @a hdr. If the header structure @a hdr
|
|
* contains a reference (@c hdr->x_next) to a list of
|
|
* headers, all the headers in the list are duplicated, too.
|
|
*
|
|
* @param home memory home used to allocate new structure
|
|
* @param hdr header structure to be duplicated
|
|
*
|
|
* When duplicating, all parameter lists and non-constant
|
|
* strings attached to the header are copied, too. The
|
|
* function uses given memory @a home to allocate all the
|
|
* memory areas used to copy the header.
|
|
*
|
|
* @par Example
|
|
* @code
|
|
*
|
|
* X = sip_X_dup(home, sip->sip_X);
|
|
*
|
|
* @endcode
|
|
*
|
|
* @return
|
|
* The function sip_X_dup() returns a pointer to the
|
|
* newly duplicated sip_X_t header structure, or NULL
|
|
* upon an error.
|
|
*/
|
|
sip_X_t *sip_X_dup(su_home_t *home, sip_X_t const *hdr);
|
|
|
|
/**Copy a sip_X_t header structure.
|
|
*
|
|
* The function sip_X_copy() copies a header structure @a
|
|
* hdr. If the header structure @a hdr contains a reference (@c
|
|
* hdr->h_next) to a list of headers, all the headers in that
|
|
* list are copied, too. The function uses given memory @a home
|
|
* to allocate all the memory areas used to copy the header
|
|
* structure @a hdr.
|
|
*
|
|
* @param home memory home used to allocate new structure
|
|
* @param hdr pointer to the header structure to be duplicated
|
|
*
|
|
* When copying, only the header structure and parameter lists
|
|
* attached to it are duplicated. The new header structure
|
|
* retains all the references to the strings within the old @a
|
|
* header, including the encoding of the old header, if present.
|
|
*
|
|
* @par Example
|
|
* @code
|
|
*
|
|
* X = sip_X_copy(home, sip->sip_X);
|
|
*
|
|
* @endcode
|
|
*
|
|
* @return
|
|
* The function sip_X_copy() returns a pointer to
|
|
* newly copied header structure, or NULL upon an error.
|
|
*/
|
|
sip_X_t *sip_X_copy(su_home_t *home, sip_X_t const *hdr);
|
|
|
|
/**Make a header structure sip_X_t.
|
|
*
|
|
* The function sip_X_make() makes a new
|
|
* sip_X_t header structure. It allocates a new
|
|
* header structure, and decodes the string @a s as the
|
|
* value of the structure.
|
|
*
|
|
* @param home memory home used to allocate new header structure.
|
|
* @param s string to be decoded as value of the new header structure
|
|
*
|
|
* @note This function is usually implemented as a macro calling
|
|
* sip_header_make().
|
|
*
|
|
* @return
|
|
* The function sip_X_make() returns a pointer to
|
|
* newly maked sip_X_t header structure, or NULL upon
|
|
* an error.
|
|
*/
|
|
#if SU_HAVE_INLINE
|
|
su_inline sip_X_t *sip_X_make(su_home_t *home, char const *s)
|
|
{
|
|
return sip_header_make(home, sip_X_class, s)->sh_X;
|
|
}
|
|
#else
|
|
sip_X_t *sip_X_make(su_home_t *home, char const *s);
|
|
#endif
|
|
|
|
/**Make a X from formatting result.
|
|
*
|
|
* The function sip_X_format() makes a new
|
|
* X object using formatting result as its
|
|
* value. The function first prints the arguments according to
|
|
* the format @a fmt specified. Then it allocates a new header
|
|
* structure, and uses the formatting result as the header
|
|
* value.
|
|
*
|
|
* @param home memory home used to allocate new header structure.
|
|
* @param fmt string used as a printf()-style format
|
|
* @param ... argument list for format
|
|
*
|
|
* @note This function is usually implemented as a macro calling
|
|
* msg_header_format().
|
|
*
|
|
* @return
|
|
* The function sip_X_format() returns a pointer to newly
|
|
* makes header structure, or NULL upon an error.
|
|
*
|
|
* @HIDE
|
|
*/
|
|
#if SU_HAVE_INLINE
|
|
su_inline
|
|
#endif
|
|
sip_X_t *sip_X_format(su_home_t *home, char const *fmt, ...)
|
|
__attribute__((format (printf, 2, 3)));
|
|
|
|
#if SU_HAVE_INLINE
|
|
su_inline sip_X_t *sip_X_format(su_home_t *home, char const *fmt, ...)
|
|
{
|
|
sip_header_t *h;
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
h = sip_header_vformat(home, sip_X_class, fmt, ap);
|
|
va_end(ap);
|
|
|
|
return h->sh_X;
|
|
}
|
|
#endif
|
|
|
|
/**Decode a header X.
|
|
*
|
|
* The function sip_X_d() decodes value of the header X in the preallocated
|
|
* header structure @a h. The string @a s to be decoded should not contain
|
|
* the header name or colon. The decoding function also expects that the
|
|
* leading and trailing whitespace has been removed from the string @a s.
|
|
*
|
|
* @param home memory home used to allocate new header structure.
|
|
* @param h sip_X_t header structure
|
|
* @param s string to be decoded
|
|
* @param bsiz length of string @a s
|
|
*
|
|
* @return
|
|
* The function sip_X_d() returns non-negative value when successful, or
|
|
* -1 upon an error.
|
|
*/
|
|
int sip_X_d(su_home_t *home, sip_header_t *h, char *s, int bsiz);
|
|
|
|
/**Encode a header X.
|
|
*
|
|
* The function sip_X_e() encodes a header structure @a h to the given
|
|
* buffer @a buf. Even if the given buffer @a buf is NULL or its size @a
|
|
* bufsiz is too small to fit the encoding result, the function returns the
|
|
* number of characters required for the encoding.
|
|
*
|
|
* @param buf buffer to store the encoding result
|
|
* @param bsiz size of the encoding buffer
|
|
* @param h header to be encoded.
|
|
* @param flags flags controlling the encoding
|
|
*
|
|
* @note
|
|
* The encoding buffer size @b must be @b bigger than, not equal to,
|
|
* the actual encoding result.
|
|
*
|
|
* @return
|
|
* The function sip_X_e() returns the number of characters required for the
|
|
* encoding.
|
|
*
|
|
*/
|
|
int sip_X_e(char buf[], int bsiz, sip_header_t const *h, int flags);
|
|
|
|
/** @} */
|
|
|
|
/**@defgroup sip_status_codes SIP Status Codes and Reason Phrases
|
|
*
|
|
* The macros and variables for the standard SIP status codes and reason
|
|
* phrases are defined in <sip_status.h>.
|
|
*/
|
|
|
|
/**@defgroup sip_tag SIP Tags
|
|
*
|
|
* SIP headers in tag item lists and tagged argument lists.
|
|
*
|
|
* The include file <sip_tag.h> defines tags and tag items for including SIP
|
|
* headers in tag item lists or tagged argument lists. For each header,
|
|
* there is a tag for pointer to header object and an another tag for string
|
|
* containing header value. For example, @From header has tags
|
|
* SIPTAG_FROM() and SIPTAG_FROM_STR().
|
|
*
|
|
* It is also possible to include user-defined headers or non-standard
|
|
* headers using SIPTAG_HEADER_STR().
|
|
*
|
|
* A function taking SIP headers as arguments could be called like this:
|
|
* @code
|
|
* sip_payload_t *payload;
|
|
* ...
|
|
* sip_add_tl(msg, sip,
|
|
* SIPTAG_CONTENT_TYPE_STR("text/plain"),
|
|
* SIPTAG_USER_AGENT(agent->user_agent),
|
|
* SIPTAG_PAYLOAD(payload),
|
|
* SIPTAG_HEADER_STR("X-Header: contents\nP-Header: bar"),
|
|
* TAG_END());
|
|
* ...
|
|
* @endcode
|
|
*
|
|
* In the above fragment, the function sip_add_tl() will add @ContentType
|
|
* and @UserAgent headers along with message payload to the SIP message.
|
|
* The @ContentType header is made with value "text/plain".
|
|
*
|
|
*/
|