summaryrefslogtreecommitdiff
path: root/pjsip/include/pjsip/sip_parser.h
blob: 72c103a79d3f3f83bdeddab888a1fc53cb7209a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
/* $Id$ */
/* 
 * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJSIP_SIP_PARSER_H__
#define __PJSIP_SIP_PARSER_H__

/**
 * @file sip_parser.h
 * @brief SIP Message Parser
 */

#include <pjsip/sip_msg.h>
#include <pjlib-util/scanner.h>
#include <pj/list.h>

PJ_BEGIN_DECL

/**
 * @defgroup PJSIP_PARSER Parser
 * @ingroup PJSIP_MSG
 * @brief Message and message elements parsing.
 * @{
 */

/**
 * URI Parsing options.
 */
enum
{
    /** If this option is specified, function #pjsip_parse_uri will return
     *  the URI object as pjsip_name_addr instead of the corresponding
     *  URI object.
     */
    PJSIP_PARSE_URI_AS_NAMEADDR = 1,

    /** If this option is specified, function #pjsip_parse_uri and other
     *  internal functions that this function calls will parse URI according
     *  to convention for parsing From/To/Contact header. For example, when 
     *  the URI is not enclosed in brackets ("<" and ">"), all parameters 
     *  are treated as header parameters (not URI parameters).
     */
    PJSIP_PARSE_URI_IN_FROM_TO_HDR = 2
};

/**
 * Parser syntax error exception value.
 */
extern int PJSIP_SYN_ERR_EXCEPTION;

/**
 * This structure is used to get error reporting from parser.
 */
typedef struct pjsip_parser_err_report
{
    /** Standard header fields. */
    PJ_DECL_LIST_MEMBER(struct pjsip_parser_err_report);
    int		except_code;	/**< Error exception (e.g. PJSIP_SYN_ERR_EXCEPTION) */
    int		line;		/**< Line number. */
    int		col;		/**< Column number. */
    pj_str_t	hname;		/**< Header name, if any. */
} pjsip_parser_err_report;


/**
 * Parsing context, the default argument for parsing functions.
 */
typedef struct pjsip_parse_ctx
{
    pj_scanner      *scanner;   /**< The scanner.       */
    pj_pool_t       *pool;      /**< The pool.          */
    pjsip_rx_data   *rdata;     /**< Optional rdata.    */
} pjsip_parse_ctx;


/**
 * Type of function to parse header. The parsing function must follow these
 * specification:
 *   - It must not modify the input text.
 *   - The hname and HCOLON has been parsed prior to invoking the handler.
 *   - It returns the header instance on success.
 *   - For error reporting, it must throw PJSIP_SYN_ERR_EXCEPTION exception 
 *     instead of just returning NULL. 
 *     When exception is thrown, the return value is ignored.
 *   - It must read the header separator after finished reading the header
 *     body. The separator types are described below, and if they don't exist,
 *     exception must be thrown. Header separator can be a:
 *	- newline, such as when the header is part of a SIP message.
 *	- ampersand, such as when the header is part of an URI.
 *	- for the last header, these separator is optional since parsing
 *        can be terminated when seeing EOF.
 */
typedef pjsip_hdr* (pjsip_parse_hdr_func)(pjsip_parse_ctx *context);

/**
 * Type of function to parse URI scheme.
 * Most of the specification of header parser handler (pjsip_parse_hdr_func)
 * also applies here (except the separator part).
 */
typedef void* (pjsip_parse_uri_func)(pj_scanner *scanner, pj_pool_t *pool,
				     pj_bool_t parse_params);

/**
 * Register header parser handler. The parser handler MUST follow the 
 * specification of header parser handler function. New registration 
 * overwrites previous registration with the same name.
 *
 * @param hname		The header name.
 * @param hshortname	The short header name or NULL.
 * @param fptr		The pointer to function to parser the header.
 *
 * @return		PJ_SUCCESS if success, or the appropriate error code.
 */
PJ_DECL(pj_status_t) pjsip_register_hdr_parser( const char *hname,
						const char *hshortname,
						pjsip_parse_hdr_func *fptr);

/**
 * Unregister previously registered header parser handler.
 * All the arguments MUST exactly equal to the value specified upon 
 * registration of the handler.
 *
 * @param hname		The header name registered.
 * @param hshortname	The short header name registered, or NULL.
 * @param fptr		Previously registered function to parse the header.
 *
 * @return		zero if unregistration was successfull.
 */
PJ_DECL(pj_status_t) pjsip_unregister_hdr_parser( const char *hname,
						  const char *hshortname,
						  pjsip_parse_hdr_func *fptr);

/**
 * Register URI scheme parser handler.
 *
 * @param scheme	The URI scheme registered.
 * @param func		The URI parser function.
 *
 * @return		zero on success.
 */
PJ_DECL(pj_status_t) pjsip_register_uri_parser( char *scheme,
					        pjsip_parse_uri_func *func);

/**
 * Unregister URI scheme parser handler.
 * All the arguments MUST exactly equal to the value specified upon 
 * registration of the handler.
 *
 * @param scheme	The URI scheme as registered previously.
 * @param func		The function handler as registered previously.
 *
 * @return		zero if the registration was successfull.
 */
PJ_DECL(pj_status_t) pjsip_unregister_uri_parser( const char *scheme,
						  pjsip_parse_uri_func *func);

/**
 * Parse an URI in the input and return the correct instance of URI.
 *
 * @param pool		The pool to get memory allocations.
 * @param buf		The input buffer, which size must be at least (size+1)
 *			because the function will temporarily put NULL 
 *			termination at the end of the buffer during parsing.
 * @param size		The length of the string (not counting NULL terminator).
 * @param options	If no options are given (value is zero), the object 
 *			returned is dependent on the syntax of the URI, 
 *			eg. basic SIP URL, TEL URL, or name address. 
 *			If option PJSIP_PARSE_URI_AS_NAMEADDR is given,
 *			then the returned object is always name address object,
 *			with the relevant URI object contained in the name 
 *			address object.
 * @return		The URI or NULL when failed. No exception is thrown by 
 *			this function (or any public parser functions).
 */
PJ_DECL(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool, 
				     char *buf, pj_size_t size,
				     unsigned options);

/**
 * Parse SIP status line.
 *
 * @param buf		Text buffer to parse.
 * @param size		The size of the buffer.
 * @param status_line	Structure to receive the parsed elements.
 *
 * @return		PJ_SUCCESS if a status line is parsed successfully.
 */
PJ_DECL(pj_status_t) pjsip_parse_status_line(char *buf, pj_size_t size,
					     pjsip_status_line *status_line);


/**
 * Parse a packet buffer and build a full SIP message from the packet. This
 * function parses all parts of the message, including request/status line,
 * all headers, and the message body. The message body however is only 
 * treated as a text block, ie. the function will not try to parse the content
 * of the body.
 *
 * @param pool		The pool to allocate memory.
 * @param buf		The input buffer, which size must be at least (size+1)
 *			because the function will temporarily put NULL 
 *			termination at the end of the buffer during parsing.
 * @param size		The length of the string (not counting NULL terminator).
 * @param err_list	If this parameter is not NULL, then the parser will
 *			put error messages during parsing in this list.
 *
 * @return		The message or NULL when failed. No exception is thrown
 *			by this function (or any public parser functions).
 */
PJ_DECL(pjsip_msg *) pjsip_parse_msg( pj_pool_t *pool, 
				      char *buf, pj_size_t size,
				      pjsip_parser_err_report *err_list);


/**
 * Parse a packet buffer and build a rdata. The resulting message will be
 * stored in \c msg field in the \c rdata. This behaves pretty much like
 * #pjsip_parse_msg(), except that it will also initialize the header fields
 * in the \c rdata.
 *
 * This function is normally called by the transport layer.
 *
 * @param buf           The input buffer
 * @param buf		The input buffer, which size must be at least (size+1)
 *			because the function will temporarily put NULL 
 *			termination at the end of the buffer during parsing.
 * @param size		The length of the string (not counting NULL terminator).
 * @param rdata         The receive data buffer to store the message and
 *                      its elements.
 *
 * @return              The message inside the rdata if successfull, or NULL.
 */
PJ_DECL(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
                                        pjsip_rx_data *rdata );

/**
 * Check incoming packet to see if a (probably) valid SIP message has been 
 * received.
 *
 * @param buf		The input buffer, which must be NULL terminated.
 * @param size		The buffer size.
 * @param is_datagram	Put non-zero if transport is datagram oriented.
 * @param msg_size	[out] If message is valid, this parameter will contain
 *			the size of the SIP message (including body, if any).
 *
 * @return		PJ_SUCCESS if a message is found, or an error code.
 */
PJ_DECL(pj_status_t) pjsip_find_msg(const char *buf, 
                                    pj_size_t size, 
				    pj_bool_t is_datagram, 
                                    pj_size_t *msg_size);

/**
 * Parse the content of a header and return the header instance.
 * This function parses the content of a header (ie. part after colon) according
 * to the expected name, and will return the correct instance of header.
 *
 * @param pool		Pool to allocate memory for the header.
 * @param hname		Header name which is used to find the correct function
 *			to parse the header.
 * @param line		Header content, which size must be at least size+1.
 * @param size		The length of the string (not counting NULL terminator,
 *			if any).
 * @param parsed_len	If the value is not NULL, then upon return the function
 *			will fill the pointer with the length of the string
 *			that has been parsed. This is usefull for two purposes,
 *			one is when the string may contain more than one header
 *			lines, and two when an error happen the value can
 *			pinpoint the location of the error in the buffer.
 *
 * @return		The instance of the header if parsing was successfull,
 *			or otherwise a NULL pointer will be returned.
 */
PJ_DECL(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
				char *line, pj_size_t size,
				int *parsed_len);

/**
 * Parse header line(s). Multiple headers can be parsed by this function.
 * When there are multiple headers, the headers MUST be separated by either
 * a newline (as in SIP message) or ampersand mark (as in URI). This separator
 * however is optional for the last header.
 *
 * @param pool		the pool.
 * @param input		the input text to parse.
 * @param size		the text length.
 * @param hlist		the header list to store the parsed headers. 
 *			This list must have been initialized before calling 
 *			this function.
 * @return		zero if successfull, or -1 if error is encountered. 
 *			Upon error, the \a hlist argument MAY contain 
 *			successfully parsed headers.
 */
PJ_DECL(pj_status_t) pjsip_parse_headers( pj_pool_t *pool,
					  char *input, pj_size_t size,
					  pj_list *hlist );


/**
 * @}
 */


/*
 * Various specification used in parsing, exported here as extern for other
 * parsers.
 */
extern pj_cis_t    
    pjsip_HOST_SPEC,		/**< For scanning host part. */
    pjsip_DIGIT_SPEC,		/**< Decimal digits */
    pjsip_ALPHA_SPEC,		/**< Alpha (A-Z, a-z) */
    pjsip_ALNUM_SPEC,		/**< Decimal + Alpha. */
    pjsip_TOKEN_SPEC,		/**< Token. */
    pjsip_TOKEN_SPEC_ESC,	/**< Token without '%' character */
    pjsip_HEX_SPEC,	        /**< Hexadecimal digits. */
    pjsip_PARAM_CHAR_SPEC,      /**< For scanning pname (or pvalue when it's 
				     not quoted.) in URI */
    pjsip_PARAM_CHAR_SPEC_ESC,	/**< Variant without the escape ('%') char */
    pjsip_HDR_CHAR_SPEC,	/**< Chars in hname/havalue in URL. */
    pjsip_HDR_CHAR_SPEC_ESC,	/**< Variant without the escape ('%') char */
    pjsip_PROBE_USER_HOST_SPEC, /**< Hostname characters. */
    pjsip_PASSWD_SPEC,		/**< Password. */
    pjsip_PASSWD_SPEC_ESC,	/**< Variant without the escape ('%') char */
    pjsip_USER_SPEC,		/**< User */
    pjsip_USER_SPEC_ESC,	/**< Variant without the escape ('%') char */
    pjsip_NOT_NEWLINE,		/**< For eating up header, basicly any chars
				     except newlines or zero. */
    pjsip_NOT_COMMA_OR_NEWLINE, /**< Array elements. */
    pjsip_DISPLAY_SPEC;		/**< Used when searching for display name. */

/*
 * Various string constants.
 */
extern const pj_str_t pjsip_USER_STR,	    /**< "user" string constant.    */
		      pjsip_METHOD_STR,	    /**< "method" string constant   */
		      pjsip_TRANSPORT_STR,  /**< "transport" string const.  */
		      pjsip_MADDR_STR,	    /**< "maddr" string const.	    */
		      pjsip_LR_STR,	    /**< "lr" string const.	    */
		      pjsip_SIP_STR,	    /**< "sip" string constant.	    */
		      pjsip_SIPS_STR,	    /**< "sips" string constant.    */
		      pjsip_TEL_STR,	    /**< "tel" string constant.	    */
		      pjsip_BRANCH_STR,	    /**< "branch" string constant.  */
		      pjsip_TTL_STR,	    /**< "ttl" string constant.	    */
		      pjsip_RECEIVED_STR,   /**< "received" string const.   */
		      pjsip_Q_STR,	    /**< "q" string constant.	    */
		      pjsip_EXPIRES_STR,    /**< "expires" string constant. */
		      pjsip_TAG_STR,	    /**< "tag" string constant.	    */
		      pjsip_RPORT_STR;	    /**< "rport" string const.	    */


/*
 * Parser utilities.
 */
enum
{
    PJSIP_PARSE_REMOVE_QUOTE = 1
};

/* Parse parameter in header (matching the character as token) */
void pjsip_parse_param_imp(  pj_scanner *scanner, pj_pool_t *pool,
			     pj_str_t *pname, pj_str_t *pvalue,
			     unsigned opt);
/* Parse parameter in URL (matching the character as paramchar) */
void pjsip_parse_uri_param_imp(  pj_scanner *scanner, pj_pool_t *pool,
				 pj_str_t *pname, pj_str_t *pvalue,
				 unsigned opt);
void pjsip_concat_param_imp( pj_str_t *param, pj_pool_t *pool, 
			     const pj_str_t *pname, const pj_str_t *pvalue, 
			     int sepchar);
void pjsip_parse_end_hdr_imp ( pj_scanner *scanner );

PJ_END_DECL

#endif	/* __PJSIP_SIP_PARSER_H__ */