msg_parser.c File Reference


Detailed Description

HTTP-like message parser engine.

Author:
Pekka Pessi <Pekka.Pessi@nokia-email.address.hidden>
Date:
Created: Thu Oct 5 14:01:24 2000 ppessi

#include "config.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>
#include <stdarg.h>
#include <sofia-sip/su_tagarg.h>
#include <sofia-sip/su.h>
#include <sofia-sip/su_alloc.h>
#include "msg_internal.h"
#include "sofia-sip/msg_header.h"
#include "sofia-sip/bnf.h"
#include "sofia-sip/msg_parser.h"
#include "sofia-sip/msg_mclass.h"
#include "sofia-sip/msg_mclass_hash.h"
#include "sofia-sip/msg_mime.h"

Include dependency graph for msg_parser.c:


Defines

#define msg_header_is_removed(h)
 Test if header is not in the chain.
#define CRLF_TEST(b)
 Calculate length of line ending (0, 1 or 2).

Functions

msg_header_tmsg_chain_remove (msg_t *msg, msg_header_t *h)
 Remove a message from header chain.
unsigned msg_get_flags (msg_t const *msg, unsigned mask)
 Get message flags.
unsigned msg_set_flags (msg_t *msg, unsigned mask)
 Set message flags.
unsigned msg_zap_flags (msg_t *msg, unsigned mask)
 Clear message flags.
int msg_is_streaming (msg_t const *msg)
 Test if streaming is in progress.
void msg_set_streaming (msg_t *msg, enum msg_streaming_status what)
 Enable/disable streaming.
void * msg_buf_alloc (msg_t *msg, usize_t size)
 Allocate a buffer of size octets, with slack of msg_min_size.
void * msg_buf_exact (msg_t *msg, usize_t size)
 Allocate a buffer exactly of size octets, without any slack.
usize_t msg_buf_commit (msg_t *msg, usize_t size, int eos)
 Commit data into buffer.
usize_t msg_buf_committed (msg_t const *msg)
 Get length of committed data.
void * msg_buf_committed_data (msg_t const *msg)
 Get committed data.
void msg_buf_set (msg_t *msg, void *b, usize_t size)
 Set buffer.
void * msg_buf_move (msg_t *dst, msg_t const *src)
 Move unparsed data from src to dst.
issize_t msg_recv_iovec (msg_t *msg, msg_iovec_t vec[], isize_t veclen, usize_t n, int exact)
 Obtain I/O vector for receiving the data.
issize_t msg_recv_buffer (msg_t *msg, void **return_buffer)
 Obtain a buffer for receiving data.
isize_t msg_recv_commit (msg_t *msg, usize_t n, int eos)
 Commit n bytes of buffers.
msg_tmsg_next (msg_t *msg)
 Get a next message of the stream.
int msg_set_next (msg_t *msg, msg_t *next)
 Set next message of the stream.
void msg_clear_committed (msg_t *msg)
 Clear committed data.
unsigned msg_mark_as_complete (msg_t *msg, unsigned mask)
 Mark message as complete.
int msg_is_complete (msg_t const *msg)
 Return true if message is complete.
int msg_has_error (msg_t const *msg)
 Return true if message has parsing errors.
usize_t msg_size (msg_t const *msg)
 Total size of message.
usize_t msg_maxsize (msg_t *msg, usize_t maxsize)
 Set the maximum size of a message.
int msg_streaming_size (msg_t *msg, usize_t ssize)
 Set the size of next fragment.
issize_t msg_buf_external (msg_t *msg, usize_t N, usize_t blocksize)
 Allocate a list of external buffers.
int extract_incomplete_chunks (msg_t *msg, int eos)
 Extract incomplete chunks.
void append_parsed (msg_t *msg, msg_pub_t *mo, msg_href_t const *hr, msg_header_t *h, int always_into_chain)
 Append a parsed header object into the message structure.
int msg_extract (msg_t *msg)
 Extract and parse a message from internal buffer.
issize_t msg_extract_header (msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos)
 Extract a header.
issize_t msg_parse_next_field (su_home_t *home, msg_header_t *prev, char *s, isize_t slen)
 Complete this header field and parse next header field.
msg_header_tmsg_header_d (su_home_t *home, msg_t const *msg, char const *b)
 Decode a message header.
issize_t msg_extract_separator (msg_t *msg, msg_pub_t *mo, char b[], isize_t bsiz, int eos)
 Extract a separator line.
msg_header_t ** msg_chain_tail (msg_t const *msg)
 Return tail of the fragment chain.
issize_t msg_extract_payload (msg_t *msg, msg_pub_t *mo, msg_header_t **return_payload, usize_t body_len, char b[], isize_t bsiz, int eos)
 Extract a message body of body_len bytes.
size_t msg_header_name_e (char b[], size_t bsiz, msg_header_t const *h, int flags)
 Encode header name.
int msg_prepare (msg_t *msg)
 Encode all message fragments.
void msg_unprepare (msg_t *msg)
 Clear 'prepared' flag.
int msg_is_prepared (msg_t const *msg)
 Return true if message is prepared.
issize_t msg_headers_prepare (msg_t *msg, msg_header_t *headers, int flags)
 Encode headers in chain.
issize_t msg_header_e (char b[], isize_t bsiz, msg_header_t const *h, int flags)
 Encode a header.
char * msg_as_string (su_home_t *home, msg_t *msg, msg_pub_t *pub, int flags, size_t *return_len)
 Convert a message to a string.
msg_header_t ** msg_chain_head (msg_t const *msg)
 Return head of the fragment chain.
int msg_serialize (msg_t *msg, msg_pub_t *pub)
 Serialize headers into the fragment chain.
isize_t msg_iovec (msg_t *msg, msg_iovec_t vec[], isize_t veclen)
 Fill an I/O vector with message contents.
msg_header_tmsg_header_alloc (su_home_t *home, msg_hclass_t *hc, isize_t extra)
 Allocate a header structure.
int msg_header_add (msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h)
 Add a (list of) header(s) to the header structure and fragment chain.
int msg_header_prepend (msg_t *msg, msg_pub_t *pub, msg_header_t **hh, msg_header_t *h)
 Prepend a (list of) header(s) to the header structure and fragment chain.
msg_header_t ** msg_hclass_offset (msg_mclass_t const *mc, msg_pub_t const *mo, msg_hclass_t *hc)
 Find place to insert header of the class hc.
int msg_header_add_dup (msg_t *msg, msg_pub_t *pub, msg_header_t const *src)
 Duplicate and add a (list of) header(s) to the message.
int msg_header_add_dup_as (msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, msg_header_t const *src)
 Duplicate a header as a given type and add the duplicate into message.
int msg_header_add_make (msg_t *msg, msg_pub_t *pub, msg_hclass_t *hc, char const *s)
 Parse a string as a given header field and add result to the message.
int msg_header_add_str (msg_t *msg, msg_pub_t *pub, char const *str)
 Add string contents to message.
int msg_header_parse_str (msg_t *msg, msg_pub_t *pub, char *s)
 Add string to message.
int msg_header_insert (msg_t *msg, msg_pub_t *pub, msg_header_t *h)
 Insert a (list of) header(s) to the fragment chain.
int msg_header_remove (msg_t *msg, msg_pub_t *pub, msg_header_t *h)
 Remove a header from the header structure and fragment chain.
int msg_header_remove_all (msg_t *msg, msg_pub_t *pub, msg_header_t *h)
 Remove a header list from the header structure and fragment chain.
int msg_header_replace (msg_t *msg, msg_pub_t *pub, msg_header_t *replaced, msg_header_t *h)
 Replace a header item with a (list of) header(s).
void msg_header_free (su_home_t *home, msg_header_t *h)
 Free a header structure.
void msg_header_free_all (su_home_t *home, msg_header_t *h)
 Free a (list of) header structures.

Function Documentation

int extract_incomplete_chunks ( msg_t ,
int  eos 
) [inline]

Extract incomplete chunks.

Return values:
1 when message is complete
0 when message is incomplete
-1 upon an error

char* msg_as_string ( su_home_t home,
msg_t msg,
msg_pub_t pub,
int  flags,
size_t *  return_len 
)

Convert a message to a string.

A message is encoded and the encoding result is returned as a string. Because the message may contain binary payload (or NUL in headers), the message length is returned separately in *return_len, too.

Note that the message is serialized as a side effect.

Parameters:
home memory home used to allocate the string
msg message to encode
pub message object to encode (may be NULL)
flags flags used when encoding
return_len return-value parameter for encoded message length
Returns:
Encoding result as a C string.
Since:
New in 1.12.4
See also:
msg_make(), msg_prepare(), msg_serialize().

issize_t msg_buf_external ( msg_t msg,
usize_t  N,
usize_t  blocksize 
)

Allocate a list of external buffers.

The function msg_buf_external() allocates at most msg_n_fragments external buffers for the message body.

Returns:
The function msg_buf_external() returns number of allocated buffers, or -1 upon an error.

msg_header_t * msg_chain_remove ( msg_t msg,
msg_header_t h 
) [inline]

Remove a message from header chain.

The function msg_chain_remove() removes a message header from the header chain.

Parameters:
msg pointer to the message
h pointer to the header in the list to be removed
Returns:
The pointer to the header just removed.

int msg_extract ( msg_t msg  ) 

Extract and parse a message from internal buffer.

This function parses the internal buffer and adds the parsed fragments to the message object. It marks the successfully parsed data as extracted.

Parameters:
msg message to be parsed
Return values:
positive if a complete message was parsed
0 if message was incomplete
negative if an error occurred

int msg_header_add ( msg_t msg,
msg_pub_t pub,
msg_header_t **  hh,
msg_header_t h 
)

Add a (list of) header(s) to the header structure and fragment chain.

The function msg_header_add() adds a header or list of headers into the given place within the message structure. It also inserts the headers into the the message fragment chain, if it exists.

If the header is a prepend header, the new header is inserted before existing headers of the same class. If the header is an append header, the new header is inserted after existing headers of the same class. If the header is a singleton, existing headers of the same class are removed. If the header is a list header, the values in the new header are added to the existing list.

Parameters:
msg message owning the fragment chain
pub public message structure
hh place in message structure to which header is added
h list of header(s) to be added

int msg_header_add_dup ( msg_t msg,
msg_pub_t pub,
msg_header_t const *  src 
)

Duplicate and add a (list of) header(s) to the message.

The function msg_header_add_dup() duplicates and adds a (list of) header(s) into a message structure.

When inserting headers into the fragment chain, a request (or status) is inserted first and replaces the existing request (or status). Other headers are inserted after the request or status.

If the header is a singleton, existing headers with the same class are removed.

Parameters:
msg message owning the fragment chain
pub public message structure to which header is added
src list of header(s) to be added

int msg_header_add_dup_as ( msg_t msg,
msg_pub_t pub,
msg_hclass_t hc,
msg_header_t const *  src 
)

Duplicate a header as a given type and add the duplicate into message.

The function msg_header_add_dup_as() duplicates a header as a instance of the given header class. It adds the new copy into the message.

When inserting headers into the fragment chain, a request (or status) is inserted first and replaces the existing request (or status). Other headers are inserted after the request or status.

If the header is a singleton, existing headers with the same class are removed.

Parameters:
msg message owning the fragment chain
pub public message structure to which header is added
hc header class for header target type
src list of header(s) to be duplicated and added

int msg_header_add_str ( msg_t msg,
msg_pub_t pub,
char const *  str 
)

Add string contents to message.

Duplicate a string containing headers (or a message body, if the string starts with linefeed), parse it and add resulting header objects to the message object.

Parameters:
msg message object
pub message header structure where heades are added (may be NULL)
str string to be copied and parsed (not modified, may be NULL)
Return values:
0 when succesful
-1 upon an error

msg_header_t* msg_header_alloc ( su_home_t home,
msg_hclass_t hc,
isize_t  extra 
)

Allocate a header structure.

The msg_header_alloc() function allocates a generic MO header structure and returns a pointer to it.

Parameters:
home memory home
hc header class
extra amount of extra memory to be allocated after header structure
Returns:
A pointer to the newly created header object, or NULL upon an error.

issize_t msg_header_e ( char  b[],
isize_t  bsiz,
msg_header_t const *  h,
int  flags 
)

Encode a header.

The function msg_header_e() encodes a header field in the buffer b[]. The encoding includes its name and trailing CRLF. The function returns the length of the encoding in bytes, excluding the final NUL. The buffer b must be large enough for whole encoding, including the final NUL.

The flags parameter define how the encoding is done. If the flags specify MSG_DO_COMPACT, the encoding is compact (short form with minimal whitespace).

int msg_header_insert ( msg_t msg,
msg_pub_t pub,
msg_header_t h 
)

Insert a (list of) header(s) to the fragment chain.

The function msg_header_insert() inserts header or list of headers into a message structure. It also inserts them into the the message fragment chain, if it exists.

When inserting headers into the fragment chain, a request (or status) is inserted first and replaces the existing request (or status). Other headers are inserted after the request or status.

If there can be only one header field of this type (hc_kind is msg_kind_single), existing header objects with the same class are removed.

Parameters:
msg message object owning the fragment chain
pub public message structure to which header is added
h list of header(s) to be added

int msg_header_parse_str ( msg_t msg,
msg_pub_t pub,
char *  s 
)

Add string to message.

Parse a string containing headers (or a message body, if the string starts with linefeed) and add resulting header objects to the message object.

Parameters:
msg message object
pub message header structure where heades are added (may be NULL)
s string to be parsed (and modified)
Return values:
0 when succesful
-1 upon an error
See also:
msg_header_add_str(), url_headers_as_string()
Since:
New in 1.12.4.

int msg_header_prepend ( msg_t msg,
msg_pub_t pub,
msg_header_t **  hh,
msg_header_t h 
)

Prepend a (list of) header(s) to the header structure and fragment chain.

The function msg_header_prepend() adds a header or list of headers into the given place within the message structure. It also inserts the headers into the the message fragment chain, if it exists.

Unlike msg_header_add(), msg_header_prepend() always inserts header h before other headers of the same class. If the header is a singleton, existing headers of the same class are removed. If the header is a list header, the values in the new header are prepended to the existing list.

Parameters:
msg message owning the fragment chain
pub public message structure
hh place in message structure to which header is added
h list of header(s) to be added

int msg_header_remove ( msg_t msg,
msg_pub_t pub,
msg_header_t h 
)

Remove a header from the header structure and fragment chain.

The function msg_header_remove() removes a header from a message structure. It also removes the message from the message fragment chain and clears the encoding of other headers objects that share same encoding.

Parameters:
msg message owning the fragment chain
pub public message structure to which header is added
h header to be removed

int msg_header_remove_all ( msg_t msg,
msg_pub_t pub,
msg_header_t h 
)

Remove a header list from the header structure and fragment chain.

The function msg_header_remove_all() removes a list of headers from a message structure. It also removes the message from the message fragment chain and clears the encoding of other headers objects that share same encoding.

Parameters:
msg message owning the fragment chain
pub public message structure to which header is added
h header list to be removed

int msg_header_replace ( msg_t msg,
msg_pub_t pub,
msg_header_t replaced,
msg_header_t h 
)

Replace a header item with a (list of) header(s).

The function msg_header_replace() removes a header structure from message and replaces it with a new one or a list of headers. It inserts the new headers into the the message fragment chain, if it exists.

Parameters:
msg message object owning the fragment chain
pub public message structure to which header is added
replaced old header to be removed
h list of header(s) to be added

issize_t msg_headers_prepare ( msg_t msg,
msg_header_t headers,
int  flags 
)

Encode headers in chain.

The function msg_headers_prepare() encodes all the headers in the header chain. You have to call msg_serialize() before calling msg_headers_prepare() in order to make sure that all the heades and other message fragments are included in the chain.

Returns:
The size of all the headers in chain, or -1 upon an error.

isize_t msg_iovec ( msg_t msg,
msg_iovec_t  vec[],
isize_t  veclen 
)

Fill an I/O vector with message contents.

Calculate number of entries in the I/O vector required to send a message msg. It also fills in the I/O vector array, if it is provided by the caller and it is large enough.

Parameters:
msg pointer to message object
vec I/O vector (may be NULL)
veclen length of I/O vector in vec
Returns:
Number of entries of I/O vector required by msg, or 0 upon an error.
Note:
The caller should check that the I/O vector vec has enough entries. If the vec is too short, it should allocate big enough vector and re-invoke msg_iovec().
See also:
msg_recv_iovec(), su_vsend()

usize_t msg_maxsize ( msg_t msg,
usize_t  maxsize 
)

Set the maximum size of a message.

The function msg_maxsize() sets the maximum buffer size of a message. It returns the previous maximum size. If the maxsize is 0, maximum size is not set, but the current maximum size is returned.

If the message size exceeds maxsize, msg_errno() returns ENOBUFS, MSG_FLG_TOOLARGE and MSG_FLG_ERROR flags are set.

msg_t* msg_next ( msg_t msg  ) 

Get a next message of the stream.

When parsing a transport stream, only the first message in the stream is created with msg_create(). The rest of the messages should be created with msg_next() after previous message has been completely received and parsed.

issize_t msg_parse_next_field ( su_home_t home,
msg_header_t prev,
char *  s,
isize_t  slen 
)

Complete this header field and parse next header field.

This function completes parsing a multi-field header like Accept, Contact, Via or Warning. It scans for the next header field and if one is found, it calls the parsing function recursively.

Parameters:
home memory home used ot allocate new header structures and parameter lists
prev pointer to header structure already parsed
s header content to parse; should point to the area after current header field (either end of line or to a comma separating header fields)
slen ignored
Since:
New in 1.12.4.
Return values:
>= 0 when successful
-1 upon an error

int msg_prepare ( msg_t msg  ) 

Encode all message fragments.

The function msg_prepare() prepares a message for sending. It encodes all serialized fragments in the message. You have to call msg_serialize() before calling msg_headers_prepare() in order to make sure that all the heades and other message fragments are included in the chain.

After encoding, the msg_common_s::h_data field will point to the encoding result of size msg_common_s::h_len bytes in in each fragment.

When multiple header fields are represented as a comma-separated list within a single header line, the first fragment in the header will contain all the text belonging to the header. The rest of the header fields will have zero-length encoding with msg_common_s::h_data that points to the end of the line.

Returns:
Total size of the encoded message in bytes, or -1 upon an error.
See also:
msg_extract(), msg_serialize()

isize_t msg_recv_commit ( msg_t msg,
usize_t  n,
int  eos 
)

Commit n bytes of buffers.

The function msg_recv_commit() is called after n bytes of data has been received to the message buffers and the parser can extract the received data.

Parameters:
msg pointer to message object
n number of bytes received
eos true if stream is complete
Note:
The eos should be always true for message-based transports. It should also be true when a stram oin stream-based transport ends, for instance, when TCP FIN is received.
Return values:
0 when successful
-1 upon an error.

issize_t msg_recv_iovec ( msg_t msg,
msg_iovec_t  vec[],
isize_t  veclen,
usize_t  n,
int  exact 
)

Obtain I/O vector for receiving the data.

Allocate buffers for receiving n bytes of data available from network. Function returns the buffers in the I/O vector vec. The vec is allocated by the caller, the available length is given as veclen. If the protocol is message-oriented like UDP or SCTP and the available data ends at message boundary, the caller should set the exact as 1. Otherwise some extra buffer (known as slack) is allocated).

Currently, the msg_recv_iovec() allocates receive buffers in at most two blocks, so the caller should allocate at least two elements for the I/O vector vec.

Parameters:
[in] msg message object
[out] vec I/O vector
[in] veclen available length of vec
[in] n number of possibly available bytes 
[in] exact true if data ends at message boundary
Returns:
The length of I/O vector to receive data, 0 if there are not enough buffers, or -1 upon an error.
See also:
msg_iovec(), su_vrecv()

int msg_serialize ( msg_t msg,
msg_pub_t pub 
)

Serialize headers into the fragment chain.

The msg_serialize() collects the headers and other message components in the fragment chain. It should be called before msg_prepare().

Parameters:
msg pointer to message object
pub public message structure
Return values:
0 when successful
-1 upon an error

int msg_streaming_size ( msg_t msg,
usize_t  ssize 
)

Set the size of next fragment.

The function msg_streaming_size() sets the size of the message body for streaming.


Sofia-SIP 1.12.6 - Copyright (C) 2006 Nokia Corporation. All rights reserved. Licensed under the terms of the GNU Lesser General Public License.