libosip  4.0.0
How-To parse SIP message.
The GNU oSIP stack

Parser API

For the SIP parser, the API is documented in osip_message.h

Basic Parser operations

Because the SIP message can contains binary data in its body part, the length of the buffer must be given to the API.

int i;
if (i!=0) { fprintf(stderr, "cannot allocate\n"); return -1; }
i=osip_message_parse(sip, buffer, length_of_buffer);
if (i!=0) { fprintf(stderr, "cannot parse sip message\n"); }

Note: dest is allocated dynamically and must be released at the end of the call sequence to avoid memory leaks.

When converting SIP message, the final length of the allocated buffer will be returned in the third argument. You then have the knowledge of the length of the data received.

char *dest=NULL;
int length=0;
i = osip_message_to_str(sip, &dest, &length);
if (i!=0) { fprintf(stderr, "cannot get printable message\n"); return -1; }
fprintf(stdout, "message:\n%s\n", dest);
osip_free(dest);

When using libosip2 and its transaction management features, you'll generally only need to create a suitable events. Thus, you'll probably use this API (only for SIP message that you receive!):

int length = size_of_buffer;
evt = osip_parse(buffer, i);

Note: It is important to understand that the libosip2 parser will not check completely if the message is compliant and well formed. The application layer is still responsible for this.

The libosip2 parser will not detect all errors (like missing headers) and it will be up to you to verify at every action that things are as you are expecting them to be!

Built-in Header Operations

osip_message_t structure contains pointers to most common headers. Other headers (Any of them, even ones not being defined by rfc) will be saved into a list of other headers.

struct osip_message {
...
...
};

Other Header Operations

Any other headers will be saved into a list of other headers.

struct osip_message {
...
...
};

Note: Those headers, even if not built-in, may have the same syntax as other headers (many contains URI for example)ยต. So you can easily re-use already existing headers API to analyse them.

osip_message_set_header (msg, "Refer-to", refer_to_header);
osip_message_set_header (msg, "Subscription-State", subscription_state_header);
osip_message_set_header (msg, "Require", "timer");
osip_message_set_header (msg, "RAck", rack_header);
osip_message_set_header (msg, "Min-SE", min_se_header);
osip_message_set_header (msg, "x-header", x_header);
osip_message_header_get_byname (msg, "min-se", 0, &min_se_header);
if (min_se_header != NULL && min_se_header->hvalue != NULL) {

Note: if you are looking for all headers with same name, you need to find the first one and re-use the return position as a parameter to search for the next one.

int pos=0;
while (1) {
pos = osip_message_header_get_byname (msg, "x-header", pos, &min_se_new);
if (min_se_new == NULL) {
break; //no more headers
}
}

In some case, short name are used in SIP message for some headers. For example, "x" is equivalent to "session-expires". In that case, you need to search for both:

osip_message_header_get_byname (msg, "session-expires", 0, &exp);
if (exp == NULL)
osip_message_header_get_byname (msg, "x", 0, &exp);

Known header parser

You can browse the API documentation to know more about header parser. libosipparser2 provides specific parser for the built-in headers (like via, from, to, call-id, route, etc... see above for full list)

Here are some sample code for Via.

osip_via_t *dest;
osip_message_get_via (msg, 0, &dest);
char tmp[200];
snprintf (tmp, 200, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u", ip, port, osip_build_random_number ());
osip_via_t *header;
char tmp[200];
snprintf (tmp, 200, "SIP/2.0/UDP %s:%s;rport;branch=z9hG4bK%u", ip, port, osip_build_random_number ());
osip_via_init (&header);
osip_via_parse (header, tmp);
osip_free(header);