SIP API Developer's Guide

Header Management Layer

This layer provides interfaces that enable an application to create, parse, modify, and examine SIP messages. A SIP message consists of a start line, a variable number of headers, and an optional message body. The start line and headers are terminated by a single Carriage Return/Line Feed (CRLF) character. The message body is preceded by an empty line that contains only a CRLF. SIP allows the combination of multiple headers of the same name type under one header. A single header can have multiple values. A header value consists of a number of descriptive parameters and an optional name-value pair. The Backus-Naur Form (BNF) for a VIA header is defined in section 24 of RFC 3261 as the following:

via        = ("Via" / "v") HCOLON via-parm * (COMMA via-parm)
via-parm   = sent-protocol LWS sent-by *(SEMI via-params)
via-params = via-ttl / via-maddr / via-branch / via-received / via-extension

The values of via-parm are descriptive parameters. The values of via-params are name-value pairs. The combination of via-parm and via-params constitute the value of the header. The stack maintains a sip_header_name_value_t structure for each SIP header. In the case of a VIA header, the structure is sip_via_value_t. A header can have multiple values separated by a comma. A header with multiple values lists a sip_header_name_value_t structure for each value. For example, a SIP header with multiple VIA headers would list multiple sip_via_value_t structures, with a corresponding via-parm parameter for each structure.

The SIP message contains a list of all the headers and the content. The stack uses the receive function that the application registered with the stack to pass the message to the application.

SIP messages implement a reference count mechanism. An application can hold a reference to a SIP message by using the sip_hold_msg() function. An application can release a reference to a SIP message by using the sip_free_msg() function. The stack destroys messages whose reference count drops to zero when the application calls the sip_free_msg() function.

The stack can forward a SIP message to a SIP entity directly or after modifying the message. The stack cannot modify a message after sending it.

typedef struct sip_header_general {
        char                    		*sip_hdr_start;
        char                    		*sip_hdr_end;
        char                    		*sip_hdr_current;
        sip_parsed_header_t     	  *sip_hdr_parsed;
}sip_hdr_general_t;

typedef struct header_function_table {
        char            	*header_name;
        char            	*header_short_name;
        int             	(*header_parse_func)(struct sip_header *,
                           	    struct sip_parsed_header **);
        boolean_t       	(*header_check_compliance)(struct sip_parsed_header *);
        boolean_t       	(*header_is_equal)(struct sip_parsed_header *,
                           	    struct sip_parsed_header *);
        void            	(*header_free)(struct sip_parsed_header *);
}sip_header_function_t;

The SIP header contains a sip_header_general_t structure that provides pointers to the start and end of the header string. The structure also has a pointer to the current position in the string that a parser can use when it is processing the header. When the stack parses a header for the first time, it caches the result in sip_hdr_parsed for future reference.

SIP allows the inclusion of custom message headers that are not defined in RFC 3261. An application can provide a table of custom headers and parsing functions to support those custom headers. The application provides an array, sip_header_function_t, for this purpose. The table entries that the application provides override the header entries that are in the default function table.

The library maintains a table that has an entry for each header that is defined in RFC 3261. This table specifies the header name in long form, as well as the compact form where present. The table also specifies the associated parsing function and any other functions listed in the sip_header_function_t array.

When the application deletes a header, the value of the sip_header_state attribute is set to SIP_HEADER_DELETED. Existing references to the header remain, but new lookups will not return the deleted header. The library frees all of the message headers at the same time that the library frees the message.

The following structure represents a parsed SIP header:

typedef struct sip_parsed_header {
        int              	sip_parsed_header_version;
        struct sip_value 	*value;
        sip_header_t    	sip_header;
}sip_parsed_header_t;

The member value is a pointer to a sip_header_name_value_t structure. The stack sets the structure as a result of parsing the SIP header. The first field of the sip_header_name_value_t structure is always a sip_value_t structure. The following code defines the sip_value_t structure:

typedef struct sip_value {
        int                        sip_value_version;
        void                       *next;
        sip_param_t                *param_list;
        sip_value_state_t          value_state;
        sip_parsed_header_t        *parsed_header;
        char                       *value_start;
        char                       *value_end;
        sip_str_t                  *sip_value_uri_str;
        sip_uri_t                  sip_value_parse_uri;
}sip_value_t;

The values in the param_list array is the list of parameters for the value that the system is parsing. The following code defines the sip_param_t structure:

typedef struct sip_param {
        sip_str_t       		param_name;
        sip_str_t       		param_value;
        struct sip_param 		*param_next;
}sip_param_t;


typedef struct sip_str {
        char 			*sip_str_ptr;
        int 			sip_str_len;
}sip_str_t;

When the library deletes a value from a header, the library sets the value of the sip_header_state attribute to SIP_HEADER_DELETED_VAL. The library also sets the value of the value_state attribute to SIP_VALUE_DELETED. Existing references to the value remain. New lookups ignore the deleted value.

Traverse the following hierarchy to get to a value from a SIP message:

sip_msg_t -> sip_header_t -> sip_parsed_header_t -> sip_<header_name>_value_t

Using the free function that corresponds to a given structure also frees all of the structures that are under it in the hierarchy.

The library performs lazy header parsing. The library only parses or checks for compliance headers whose values are used by the application. This behavior complies with section 16.3 of RFC 3261, Request Validation and Reasonable syntax check. When the parser encounters an invalid value, the parser sets the value_state attribute to SIP_VALUE_BAD.

Writing Parsers For Custom Headers

An application can define custom headers or specialized versions of standard headers. Applications that define headers must register parsing functions with the library to support those headers. Use the following structures to write parsing functions:

sip_header_general_t

This structure provides the start and end of a header within a message. The parser sets the parsed header element to point to the sip_parsed_header_t structure that the parser allocates.

sip_parsed_header_t

The parser allocates and assigns this structure. The parser passes this structure back to the caller.

sip_value_t

The application defines the value of this structure depending on the header. The first element of the structure must be sip_value_t. The parser creates a linked list of values if multiple values exist. The parser sets the value of the value field in the parsed header to the first value. The application must provide any access function that value members require.