msg_parser.h 10.5 KB
Newer Older
Pekka Pessi's avatar
Pekka Pessi committed
1 2 3 4 5 6 7
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2005 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
8
 * This library is free software; you can redistribute it and/or
Pekka Pessi's avatar
Pekka Pessi committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

Pekka Pessi's avatar
Pekka Pessi committed
25 26
#ifndef MSG_PARSER_H
/** Defined when <sofia-sip/msg_parser.h> has been included. */
Pekka Pessi's avatar
Pekka Pessi committed
27 28
#define MSG_PARSER_H 

Pekka Pessi's avatar
Pekka Pessi committed
29
/**@ingroup msg_parser
Pekka Pessi's avatar
Pekka Pessi committed
30
 * @file sofia-sip/msg_parser.h
Pekka Pessi's avatar
Pekka Pessi committed
31 32 33 34 35 36 37 38 39 40
 *
 * Message parser interface.
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Tue Aug 21 16:03:45 2001 ppessi
 *
 */

#ifndef SU_ALLOC_H
41
#include <sofia-sip/su_alloc.h>
Pekka Pessi's avatar
Pekka Pessi committed
42 43
#endif
#ifndef MSG_HEADER_H
44
#include <sofia-sip/msg_header.h>
Pekka Pessi's avatar
Pekka Pessi committed
45 46
#endif
#ifndef BNF_H
47
#include <sofia-sip/bnf.h>
Pekka Pessi's avatar
Pekka Pessi committed
48 49
#endif
#ifndef URL_H
50
#include <sofia-sip/url.h>
Pekka Pessi's avatar
Pekka Pessi committed
51 52
#endif

53 54
SOFIA_BEGIN_DECLS

Pekka Pessi's avatar
Pekka Pessi committed
55 56 57 58
/* ---------------------------------------------------------------------------
 * 1) Header class definitions.
 */

59 60
/* Do not use keywords until you fix msg_kind_foo_critical thing! */ \
#if HAVE_STRUCT_KEYWORDS && 0
Pekka Pessi's avatar
Pekka Pessi committed
61
/** Define a header class */
62 63 64 65 66 67 68 69 70 71 72 73 74 75
#define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd)	\
  {{								\
    hc_hash:	pr##c##_hash,					\
    hc_parse:	pr##c##_d,					\
    hc_print:	pr##c##_e,					\
    hc_dxtra:	dup##_dup_xtra,					\
    hc_dup_one: dup##_dup_one,					\
    hc_update:	upd##_update,					\
    hc_name:	l,						\
    hc_len:	sizeof(l) - 1,					\
    hc_short:	s,						\
    hc_size:	MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)),	\
    hc_params:	offsetof(pr##c##_t, params),			\
    hc_kind:	msg_kind_##kind,				\
Pekka Pessi's avatar
Pekka Pessi committed
76 77
  }}
#else
78
/** Define a header class */
79
#define MSG_HEADER_CLASS(pr, c, l, s, params, kind, dup, upd)	\
Pekka Pessi's avatar
Pekka Pessi committed
80 81 82 83 84 85
  {{ \
     pr##c##_hash, \
     pr##c##_d, \
     pr##c##_e, \
     dup##_dup_xtra, \
     dup##_dup_one, \
86
     upd##_update, \
Pekka Pessi's avatar
Pekka Pessi committed
87 88 89 90 91 92 93 94 95
     l, \
     sizeof(l) - 1, \
     s, \
     MSG_ALIGN(sizeof(pr##c##_t), sizeof(void*)), \
     offsetof(pr##c##_t, params), \
     msg_kind_##kind, \
  }}
#endif

96 97 98 99
/* Mark headers critical for understanding the message */
#define msg_kind_single_critical msg_kind_single, 1
#define msg_kind_list_critical   msg_kind_list, 1

100 101 102 103 104 105 106 107
SOFIAPUBFUN issize_t msg_extract_header(msg_t *msg, msg_pub_t *mo,
				   char b[], isize_t bsiz, int eos);
SOFIAPUBFUN issize_t msg_extract_separator(msg_t *msg, msg_pub_t *mo,
					   char b[], isize_t bsiz, int eos);
SOFIAPUBFUN 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);
Pekka Pessi's avatar
Pekka Pessi committed
108 109 110 111 112

/* ---------------------------------------------------------------------------
 * 2) Header processing methods for common headers.
 */

Pekka Pessi's avatar
Pekka Pessi committed
113 114
SOFIAPUBFUN int msg_firstline_d(char *s, char **ss2, char **ss3);

115
SOFIAPUBFUN isize_t msg_default_dup_xtra(msg_header_t const *header, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
116 117 118
SOFIAPUBFUN char *msg_default_dup_one(msg_header_t *dst, 
				      msg_header_t const *src,
				      char *b, 
119
				      isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
120

121 122
SOFIAPUBFUN issize_t msg_numeric_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
SOFIAPUBFUN issize_t msg_numeric_e(char [], isize_t, msg_header_t const *, int);
Pekka Pessi's avatar
Pekka Pessi committed
123

124 125 126
SOFIAPUBFUN issize_t msg_list_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
SOFIAPUBFUN issize_t msg_list_e(char [], isize_t, msg_header_t const *, int);
SOFIAPUBFUN isize_t msg_list_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
127 128
SOFIAPUBFUN char *msg_list_dup_one(msg_header_t *dst,
				   msg_header_t const *src,
129
				   char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
130

131 132 133
SOFIAPUBFUN issize_t msg_generic_d(su_home_t *, msg_header_t *, char *, isize_t);
SOFIAPUBFUN issize_t msg_generic_e(char [], isize_t, msg_header_t const *, int);
SOFIAPUBFUN isize_t msg_generic_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
134 135 136
SOFIAPUBFUN char *msg_generic_dup_one(msg_header_t *dst,
				      msg_header_t const *src,
				      char *b, 
137
				      isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
138

139
SOFIAPUBFUN isize_t msg_unknown_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
140 141
SOFIAPUBFUN char *msg_unknown_dup_one(msg_header_t *dst,
				      msg_header_t const *src,
142
				      char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
143

144
SOFIAPUBFUN isize_t msg_error_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
145 146
SOFIAPUBFUN char *msg_error_dup_one(msg_header_t *dst,
				    msg_header_t const *src,
147
				    char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
148

149 150 151
SOFIAPUBFUN issize_t msg_payload_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
SOFIAPUBFUN issize_t msg_payload_e(char b[], isize_t bsiz, msg_header_t const *, int f);
SOFIAPUBFUN isize_t msg_payload_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
152 153
SOFIAPUBFUN char *msg_payload_dup_one(msg_header_t *dst,
				      msg_header_t const *src,
154
				      char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
155

156 157
SOFIAPUBFUN issize_t msg_separator_d(su_home_t *, msg_header_t *, char *, isize_t);
SOFIAPUBFUN issize_t msg_separator_e(char [], isize_t, msg_header_t const *, int);
Pekka Pessi's avatar
Pekka Pessi committed
158

159 160 161
SOFIAPUBFUN issize_t msg_auth_d(su_home_t *, msg_header_t *h, char *s, isize_t slen);
SOFIAPUBFUN issize_t msg_auth_e(char b[], isize_t bsiz, msg_header_t const *h, int f);
SOFIAPUBFUN isize_t msg_auth_dup_xtra(msg_header_t const *h, isize_t offset);
Pekka Pessi's avatar
Pekka Pessi committed
162
SOFIAPUBFUN char *msg_auth_dup_one(msg_header_t *dst, msg_header_t const *src, 
163
				   char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
164 165 166 167 168 169 170 171 172

/* ---------------------------------------------------------------------------
 * 2) Macros and prototypes for building header decoding/encoding functions.
 */

#define MSG_HEADER_DATA(h) ((char *)(h) + (h)->sh_class->hc_size)

#define MSG_HEADER_TEST(h) ((h) && (h)->sh_class)

Pekka Pessi's avatar
Pekka Pessi committed
173
su_inline void *msg_header_data(msg_frg_t *h);
Pekka Pessi's avatar
Pekka Pessi committed
174

Pekka Pessi's avatar
Pekka Pessi committed
175 176 177
SOFIAPUBFUN int msg_hostport_d(char **ss,
			       char const **return_host,
			       char const **return_port);
Pekka Pessi's avatar
Pekka Pessi committed
178

179 180 181 182 183
SOFIAPUBFUN issize_t msg_token_d(char **ss, char const **return_token);
SOFIAPUBFUN issize_t msg_uint32_d(char **ss, uint32_t *return_value);
SOFIAPUBFUN issize_t msg_comment_d(char **ss, char const **return_comment);
SOFIAPUBFUN issize_t msg_quoted_d(char **ss, char **return_unquoted);
SOFIAPUBFUN issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s);
Pekka Pessi's avatar
Pekka Pessi committed
184

185 186 187
SOFIAPUBFUN issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev,
					  char *s, isize_t slen);

Pekka Pessi's avatar
Pekka Pessi committed
188 189 190 191 192 193 194 195 196 197 198
/** Terminate encoding. @HI */
#define MSG_TERM_E(p, e) ((p) < (e) ? (p)[0] = '\0' : '\0')

/** Encode a character. @HI */
#define MSG_CHAR_E(p, e, c) (++(p) < (e) ? ((p)[-1]=(c)) : (c)) 

/** Calculate separator and string length. @HI */
#define MSG_STRING_LEN(s, sep_size) ((s) ? (strlen(s) + sep_size) : 0)

/** Encode a string. @HI */
#define MSG_STRING_E(p, e, s) do { \
199
  size_t _n = strlen(s); if (p + _n+1 < e) memcpy(p, s, _n+1); p+= _n; } while(0)
Pekka Pessi's avatar
Pekka Pessi committed
200 201 202

/** Duplicate string. @HI */
#define MSG_STRING_DUP(p, d, s) \
203
  (void)((s)?((p)=(char*)memccpy((void *)((d)=(char*)p),(s),0,INT_MAX))\
Pekka Pessi's avatar
Pekka Pessi committed
204
	    :((d)=NULL))
Pekka Pessi's avatar
Pekka Pessi committed
205

206 207
/* Solaris has broken memccpy - it considers last argument as signed */

Pekka Pessi's avatar
Pekka Pessi committed
208 209 210
/** Calculate string size. @HI */
#define MSG_STRING_SIZE(s) ((s) ? (strlen(s) + 1) : 0)

211
SOFIAPUBFUN issize_t msg_commalist_d(su_home_t *, char **ss,
212
				     msg_param_t **append_list,
213 214 215
				     issize_t (*scanner)(char *s));
SOFIAPUBFUN issize_t msg_token_scan(char *start);
SOFIAPUBFUN issize_t msg_attribute_value_scanner(char *s);
Pekka Pessi's avatar
Pekka Pessi committed
216

217
SOFIAPUBFUN issize_t msg_any_list_d(su_home_t *, char **ss, 
218 219 220
				    msg_param_t **append_list,
				    issize_t (*scanner)(char *s),
				    int sep);
Pekka Pessi's avatar
Pekka Pessi committed
221 222 223 224 225 226 227 228 229 230

/** Encode a comma-separated parameter list */
#define MSG_COMMALIST_E(b, end, params, compact) do { \
  char const * const *p_; char const * c_ = ""; \
  for (p_ = (params); p_ && *p_; p_++, c_ = (compact ? "," : ", ")) \
    { MSG_STRING_E(b, (end), c_); MSG_STRING_E(b, (end), *p_); } \
} while(0)

/* Parameter lists */

Pekka Pessi's avatar
Pekka Pessi committed
231
SOFIAPUBFUN int msg_header_update_params(msg_common_t *h, int clear);
232

Pekka Pessi's avatar
Pekka Pessi committed
233 234 235 236 237 238 239 240 241 242 243
/** Match a parameter with any value. @HI */
#define MSG_PARAM_MATCH(v, s, name) \
  (strncasecmp(s, name "=", sizeof(name)) == 0 ? (v = s + sizeof(name)) : NULL)

/** Match a parameter with known value. @HI */
#define MSG_PARAM_MATCH_P(v, s, name) \
  ((strncasecmp((s), name "", sizeof(name) - 1) == 0 &&			\
    ((s)[sizeof(name) - 1] == '=' || (s)[sizeof(name) - 1] == '\0')) ? \
   ((v) = 1) : 0)

/** Calculate allocated number of items in parameter list. @HI */
244
#define MSG_PARAMS_NUM(n) (((n) + MSG_N_PARAMS - 1) & (size_t)(0 - MSG_N_PARAMS))
Pekka Pessi's avatar
Pekka Pessi committed
245

Pekka Pessi's avatar
Pekka Pessi committed
246
/** Parse a semicolong-separated attribute-value list. @HI */
247 248
SOFIAPUBFUN issize_t msg_avlist_d(su_home_t *, char **ss,
				  msg_param_t const **return_params);
Pekka Pessi's avatar
Pekka Pessi committed
249

Pekka Pessi's avatar
Pekka Pessi committed
250
/** Parse a semicolon-separated parameter list starting with semicolon. @HI */
251 252
SOFIAPUBFUN issize_t msg_params_d(su_home_t *, char **ss,
				  msg_param_t const **return_params);
Pekka Pessi's avatar
Pekka Pessi committed
253 254

/** Encode a list of parameters. */
255
SOFIAPUBFUN isize_t msg_params_e(char b[], isize_t bsiz, msg_param_t const pparams[]);
Pekka Pessi's avatar
Pekka Pessi committed
256 257

/** Join list of parameters */
258 259 260 261 262
SOFIAPUBFUN issize_t msg_params_join(su_home_t *,
				     msg_param_t **dst,
				     msg_param_t const *src,
				     unsigned prune,
				     int dup);
Pekka Pessi's avatar
Pekka Pessi committed
263 264 265

/** Encode a list of parameters. @HI */
#define MSG_PARAMS_E(b, end, params, flags) \
266
  (b) += msg_params_e((b), (size_t)((b) < (end) ? (end) - (b) : 0), (params))
Pekka Pessi's avatar
Pekka Pessi committed
267 268 269 270 271

/** Calculate extra size of parametes. @HI */
#define MSG_PARAMS_SIZE(rv, params) (rv = msg_params_dup_xtra(params, rv))

/** Duplicate a parameter list */
Pekka Pessi's avatar
Pekka Pessi committed
272
SOFIAPUBFUN char *msg_params_dup(msg_param_t const **d, msg_param_t const *s, 
273
				 char *b, isize_t xtra);
Pekka Pessi's avatar
Pekka Pessi committed
274 275

/** Count number of parameters in the list */
276
su_inline isize_t msg_params_count(msg_param_t const params[])
Pekka Pessi's avatar
Pekka Pessi committed
277 278
{
  if (params) {
279
    size_t n;
Pekka Pessi's avatar
Pekka Pessi committed
280 281 282 283 284 285 286 287 288 289
    for (n = 0; params[n]; n++)
      ;
    return n;
  }
  else {
    return 0;
  }
}

/** Calculate memory size required by parameter list */
290
su_inline isize_t msg_params_dup_xtra(msg_param_t const params[], isize_t offset)
Pekka Pessi's avatar
Pekka Pessi committed
291
{
292
  isize_t n = msg_params_count(params);
Pekka Pessi's avatar
Pekka Pessi committed
293 294 295 296 297 298 299 300 301 302
  if (n) {
    MSG_STRUCT_SIZE_ALIGN(offset);
    offset += MSG_PARAMS_NUM(n + 1) * sizeof(msg_param_t);
    for (n = 0; params[n]; n++)
      offset += strlen(params[n]) + 1;
  }
  return offset;
}

/** Return pointer to extra data after header structure */
Pekka Pessi's avatar
Pekka Pessi committed
303
su_inline void *msg_header_data(msg_frg_t *h)
Pekka Pessi's avatar
Pekka Pessi committed
304 305 306 307 308 309 310
{
  if (h)
    return (char *)h + h->h_class->hc_size;
  else
    return NULL;
}

311 312
SOFIA_END_DECLS

Pekka Pessi's avatar
Pekka Pessi committed
313
#endif /** MSG_PARSER_H */