Bug Summary

File:libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c
Location:line 890, column 9
Description:Value stored to 'end' during its initialization is never read

Annotated Source Code

1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25/**@CFILE sip_extra.c
26 * @brief Non-critical SIP headers
27 *
28 * This file contains implementation of @CallInfo, @ErrorInfo,
29 * @Organization, @Priority, @RetryAfter, @Server, @Subject,
30 * @Timestamp, and @UserAgent headers.
31 *
32 * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
33 *
34 * @date Created: Tue Jun 13 02:57:51 2000 ppessi
35 */
36
37#include "config.h"
38
39/* Avoid casting sip_t to msg_pub_t and sip_header_t to msg_header_t */
40#define MSG_PUB_Tstruct sip_s struct sip_s
41#define MSG_HDR_Tunion sip_header_u union sip_header_u
42
43
44#include "sofia-sip/sip_parser.h"
45#include "sofia-sip/sip_extra.h"
46#include "../su/sofia-sip/su_alloc.h"
47
48#include <stdio.h>
49#include <stddef.h>
50#include <stdlib.h>
51#include <string.h>
52#include <limits.h>
53#
54#include <assert.h>
55
56/* ====================================================================== */
57
58static issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen);
59
60static isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset);
61static char *sip_info_dup_one(sip_header_t *dst,
62 sip_header_t const *src,
63 char *b,
64 isize_t xtra);
65
66#define sip_info_update((void*)0) NULL((void*)0)
67
68/* ====================================================================== */
69
70/**@SIP_HEADER sip_call_info Call-Info Header
71 *
72 * The Call-Info header provides additional information about the caller or
73 * callee. Its syntax is defined in @RFC3261 as follows:
74 *
75 * @code
76 * Call-Info = "Call-Info" HCOLON info *(COMMA info)
77 * info = LAQUOT absoluteURI RAQUOT *( SEMI info-param)
78 * info-param = ( "purpose" EQUAL ( "icon" / "info"
79 * / "card" / token ) ) / generic-param
80 * @endcode
81 *
82 *
83 * The parsed Call-Info header is stored in #sip_call_info_t structure.
84 */
85
86/**@ingroup sip_call_info
87 * @typedef struct sip_call_info_s sip_call_info_t;
88 *
89 * The structure #sip_call_info_t contains representation of an
90 * @CallInfo header.
91 *
92 * The #sip_call_info_t is defined as follows:
93 * @code
94 * struct sip_call_info_s
95 * {
96 * sip_common_t ci_common[1]; // Common fragment info
97 * sip_call_info_t *ci_next; // Link to next @CallInfo
98 * url_t ci_url[1]; // URI to call info
99 * msg_param_t const *ci_params; // List of parameters
100 * char const *ci_purpose; // Value of @b purpose parameter
101 * };
102 * @endcode
103 */
104
105#define sip_call_info_dup_xtrasip_info_dup_xtra sip_info_dup_xtra
106#define sip_call_info_dup_onesip_info_dup_one sip_info_dup_one
107static msg_update_f sip_call_info_update;
108
109msg_hclass_t sip_call_info_class[] =
110SIP_HEADER_CLASS(call_info, "Call-Info", "",{{ sip_call_info_hash, sip_call_info_d, sip_call_info_e, sip_info_dup_xtra
, sip_info_dup_one, sip_call_info_update, "Call-Info", sizeof
("Call-Info") - 1, "", (((uintptr_t)(sizeof(sip_call_info_t))
+ (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))
)), __builtin_offsetof(sip_call_info_t, ci_params), msg_kind_append
, }}
111 ci_params, append, call_info){{ sip_call_info_hash, sip_call_info_d, sip_call_info_e, sip_info_dup_xtra
, sip_info_dup_one, sip_call_info_update, "Call-Info", sizeof
("Call-Info") - 1, "", (((uintptr_t)(sizeof(sip_call_info_t))
+ (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))
)), __builtin_offsetof(sip_call_info_t, ci_params), msg_kind_append
, }}
;
112
113issize_t sip_call_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
114{
115 issize_t retval = sip_info_d(home, h, s, slen);
116
117 if (retval == 0)
118 for (;h; h = h->sh_nextsh_header_next->shn_next)
119 msg_header_update_params(h->sh_common, 0);
120
121 return retval;
122}
123
124issize_t sip_call_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
125{
126 sip_call_info_t *ci = (sip_call_info_t *)h;
127
128 assert(sip_call_info_p(h))((sip_is_call_info((h))) ? (void) (0) : __assert_fail ("sip_is_call_info((h))"
, "sip_extra.c", 128, __PRETTY_FUNCTION__))
;
129
130 return sip_name_addr_e(b, bsiz, f, NULL((void*)0), 1, ci->ci_url, ci->ci_params, NULL((void*)0));
131}
132
133/** @internal
134 * Update parameter in a @CallInfo object.
135 *
136 */
137static int
138sip_call_info_update(msg_common_t *h,
139 char const *name, isize_t namelen,
140 char const *value)
141{
142 sip_call_info_t *ci = (sip_call_info_t *)h;
143
144 if (name == NULL((void*)0)) {
145 ci->ci_purpose = NULL((void*)0);
146 }
147 else if (namelen == strlen("purpose") &&
148 su_casenmatch(name, "purpose", namelen)) {
149 ci->ci_purpose = value;
150 }
151
152 return 0;
153}
154
155/* ====================================================================== */
156
157/**@SIP_HEADER sip_error_info Error-Info Header
158 *
159 * The Error-Info header provides a pointer to additional information about
160 * the error status response. Its syntax is defined in @RFC3261 as follows:
161 *
162 * @code
163 * Error-Info = "Error-Info" HCOLON error-uri *(COMMA error-uri)
164 * error-uri = LAQUOT absoluteURI RAQUOT *( SEMI generic-param )
165 * @endcode
166 *
167 *
168 * The parsed Error-Info header is stored in #sip_error_info_t structure.
169 */
170
171/**@ingroup sip_error_info
172 * @typedef struct sip_error_info_s sip_error_info_t;
173 *
174 * The structure #sip_error_info_t contains representation of an
175 * @ErrorInfo header.
176 *
177 * The #sip_error_info_t is defined as follows:
178 * @code
179 * struct sip_error_info_s
180 * {
181 * sip_common_t ei_common[1]; // Common fragment info
182 * sip_error_info_t *ei_next; // Link to next @ErrorInfo
183 * url_t ei_url[1]; // URI to error info
184 * msg_param_t const *ei_params; // List of parameters
185 * };
186 * @endcode
187 */
188
189msg_hclass_t sip_error_info_class[] =
190SIP_HEADER_CLASS(error_info, "Error-Info", "",{{ sip_error_info_hash, sip_error_info_d, sip_error_info_e, sip_info_dup_xtra
, sip_info_dup_one, ((void*)0), "Error-Info", sizeof("Error-Info"
) - 1, "", (((uintptr_t)(sizeof(sip_error_info_t)) + (sizeof(
void*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_error_info_t, ei_params), msg_kind_append, }}
191 ei_params, append, info){{ sip_error_info_hash, sip_error_info_d, sip_error_info_e, sip_info_dup_xtra
, sip_info_dup_one, ((void*)0), "Error-Info", sizeof("Error-Info"
) - 1, "", (((uintptr_t)(sizeof(sip_error_info_t)) + (sizeof(
void*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_error_info_t, ei_params), msg_kind_append, }}
;
192
193issize_t sip_error_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
194{
195 return sip_info_d(home, h, s, slen);
196}
197
198issize_t sip_error_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
199{
200 sip_error_info_t const *ei = h->sh_error_info;
201
202 assert(sip_error_info_p(h))((sip_is_error_info((h))) ? (void) (0) : __assert_fail ("sip_is_error_info((h))"
, "sip_extra.c", 202, __PRETTY_FUNCTION__))
;
203
204 return sip_name_addr_e(b, bsiz, f,
205 NULL((void*)0), 1, ei->ei_url, ei->ei_params, NULL((void*)0));
206}
207
208/* ====================================================================== */
209
210/**@SIP_HEADER sip_alert_info Alert-Info Header
211 *
212 * When present in an INVITE request, the Alert-Info header field
213 * specifies an alternative ring tone to the UAS. When present in a 180
214 * (Ringing) response, the Alert-Info header field specifies an
215 * alternative ringback tone to the UAC. A typical usage is for a proxy
216 * to insert this header field to provide a distinctive ring feature.
217 *
218 * @code
219 * Alert-Info = "Alert-Info" HCOLON alert-param *(COMMA alert-param)
220 * alert-param = LAQUOT absoluteURI RAQUOT *(SEMI generic-param)
221 * @endcode
222 *
223 * The parsed Alert-Info header is stored in #sip_alert_info_t structure.
224 *
225 * @NEW_1_12_7. In order to use @b Alert-Info header, initialize the SIP
226 * parser before calling nta_agent_create() or nua_create() with, e.g.,
227 * sip_update_default_mclass(sip_extend_mclass(NULL)).
228 *
229 * The #sip_t structure does not contain a @a sip_alert_info field, but
230 * sip_alert_info() function should be used for accessing the @b Alert-Info
231 * header structure.
232 */
233
234/**@ingroup sip_alert_info
235 * @typedef struct sip_alert_info_s sip_alert_info_t;
236 *
237 * The structure #sip_alert_info_t contains representation of an
238 * @AlertInfo header.
239 *
240 * The #sip_alert_info_t is defined as follows:
241 * @code
242 * struct sip_alert_info_s
243 * {
244 * sip_common_t ai_common[1]; // Common fragment info
245 * sip_alert_info_t *ai_next; // Link to next @AlertInfo
246 * url_t ai_url[1]; // URI to alert info
247 * msg_param_t const *ai_params; // List of optional parameters
248 * };
249 * @endcode
250 *
251 * @NEW_1_12_7.
252 */
253
254msg_hclass_t sip_alert_info_class[] =
255SIP_HEADER_CLASS(alert_info, "Alert-Info", "",{{ sip_alert_info_hash, sip_alert_info_d, sip_alert_info_e, sip_info_dup_xtra
, sip_info_dup_one, ((void*)0), "Alert-Info", sizeof("Alert-Info"
) - 1, "", (((uintptr_t)(sizeof(sip_alert_info_t)) + (sizeof(
void*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_alert_info_t, ai_params), msg_kind_append, }}
256 ai_params, append, info){{ sip_alert_info_hash, sip_alert_info_d, sip_alert_info_e, sip_info_dup_xtra
, sip_info_dup_one, ((void*)0), "Alert-Info", sizeof("Alert-Info"
) - 1, "", (((uintptr_t)(sizeof(sip_alert_info_t)) + (sizeof(
void*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_alert_info_t, ai_params), msg_kind_append, }}
;
257
258issize_t sip_alert_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
259{
260 return sip_info_d(home, h, s, slen);
261}
262
263issize_t sip_alert_info_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
264{
265 sip_alert_info_t *ai = (sip_alert_info_t *)h;
266 return sip_name_addr_e(b, bsiz, f, NULL((void*)0), 1, ai->ai_url, ai->ai_params, NULL((void*)0));
267}
268
269/* ====================================================================== */
270
271/**@SIP_HEADER sip_reply_to Reply-To Header
272 *
273 * The @b Reply-To header field contains a logical return URI that may be
274 * different from the @From header field. For example, the URI MAY be used to
275 * return missed calls or unestablished sessions. If the user wished to
276 * remain anonymous, the header field SHOULD either be omitted from the
277 * request or populated in such a way that does not reveal any private
278 * information. Its syntax is defined in @RFC3261 as follows:
279 *
280 * @code
281 * Reply-To = "Reply-To" HCOLON rplyto-spec
282 * rplyto-spec = ( name-addr / addr-spec )
283 * *( SEMI rplyto-param )
284 * rplyto-param = generic-param
285 * @endcode
286 *
287 * The parsed Reply-To header is stored in #sip_reply_to_t structure.
288 *
289 * @sa sip_update_default_mclass()
290 *
291 * @NEW_1_12_7. In order to use @b Reply-To header,
292 * initialize the SIP parser before calling nta_agent_create() or
293 * nua_create() with, e.g.,
294 * sip_update_default_mclass(sip_extend_mclass(NULL)).
295 *
296 * @note
297 * The #sip_t structure does not contain a @a sip_reply_to field, but
298 * sip_reply_to() function should be used for accessing the @b Reply-To
299 * header structure.
300 */
301
302/**@ingroup sip_reply_to
303 * @typedef struct msg_list_s sip_reply_to_t;
304 *
305 * The structure #sip_reply_to_t contains representation of SIP
306 * @ReplyTo header.
307 *
308 * The #sip_reply_to_t is defined as follows:
309 * @code
310 * struct sip_reply_to_s
311 * {
312 * sip_common_t rplyto_common[1]; // Common fragment info
313
314 * sip_reply_to_t *rplyto_next; // Dummy link to next header
315 * char const *rplyto_display; // Display name
316 * url_t rplyto_url[1]; // Return URI
317 * msg_param_t const *rplyto_params; // List of optional parameters
318 * };
319 * @endcode
320 */
321
322static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset);
323static char *sip_reply_to_dup_one(sip_header_t *dst,
324 sip_header_t const *src,
325 char *b,
326 isize_t xtra);
327#define sip_reply_to_update((void*)0) NULL((void*)0)
328
329msg_hclass_t sip_reply_to_class[] =
330 SIP_HEADER_CLASS(reply_to, "Reply-To", "", rplyto_params, single, reply_to){{ sip_reply_to_hash, sip_reply_to_d, sip_reply_to_e, sip_reply_to_dup_xtra
, sip_reply_to_dup_one, ((void*)0), "Reply-To", sizeof("Reply-To"
) - 1, "", (((uintptr_t)(sizeof(sip_reply_to_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_reply_to_t, rplyto_params), msg_kind_single, }}
;
331
332issize_t sip_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
333{
334 sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
335
336 return sip_name_addr_d(home,
337 &s,
338 &rplyto->rplyto_display,
339 rplyto->rplyto_url,
340 &rplyto->rplyto_params,
341 NULL((void*)0));
342}
343
344issize_t sip_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
345{
346 sip_reply_to_t *rplyto = (sip_reply_to_t *)h;
347
348 return sip_name_addr_e(b, bsiz,
349 flags,
350 rplyto->rplyto_display,
351 MSG_IS_CANONIC(flags)((((flags)) & (MSG_FLG_CANONIC)) == MSG_FLG_CANONIC), rplyto->rplyto_url,
352 rplyto->rplyto_params,
353 NULL((void*)0));
354}
355
356static isize_t sip_reply_to_dup_xtra(sip_header_t const *h, isize_t offset)
357{
358 sip_reply_to_t const *rplyto = (sip_reply_to_t const *)h;
359
360 return sip_name_addr_xtra(rplyto->rplyto_display,
361 rplyto->rplyto_url,
362 rplyto->rplyto_params,
363 offset);
364}
365
366/**@internal Duplicate one sip_reply_to_t object. */
367static char *sip_reply_to_dup_one(sip_header_t *dst, sip_header_t const *src,
368 char *b, isize_t xtra)
369{
370 sip_reply_to_t *rplyto = (sip_reply_to_t *)dst;
371 sip_reply_to_t const *o = (sip_reply_to_t *)src;
372
373 return sip_name_addr_dup(&rplyto->rplyto_display, o->rplyto_display,
374 rplyto->rplyto_url, o->rplyto_url,
375 &rplyto->rplyto_params, o->rplyto_params,
376 b, xtra);
377}
378
379/* ====================================================================== */
380
381/**@SIP_HEADER sip_in_reply_to In-Reply-To Header
382 *
383 * The @b In-Reply-To request header field enumerates the
384 * @ref sip_call_id "Call-IDs" that this call references or returns.
385 * Its syntax is defined in @RFC3261 as follows:
386 *
387 * @code
388 * In-Reply-To = "In-Reply-To" HCOLON callid *(COMMA callid)
389 * @endcode
390 *
391 * The parsed In-Reply-To header is stored in #sip_in_reply_to_t structure.
392 */
393
394/**@ingroup sip_in_reply_to
395 * @typedef struct msg_list_s sip_in_reply_to_t;
396 *
397 * The structure #sip_in_reply_to_t contains representation of SIP
398 * @InReplyTo header.
399 *
400 * The #sip_in_reply_to_t is defined as follows:
401 * @code
402 * typedef struct msg_list_s
403 * {
404 * msg_common_t k_common[1]; // Common fragment info
405 * msg_list_t *k_next; // Link to next header
406 * msg_param_t *k_items; // List of call ids
407 * } sip_in_reply_to_t;
408 * @endcode
409 */
410
411msg_hclass_t sip_in_reply_to_class[] =
412SIP_HEADER_CLASS_LIST(in_reply_to, "In-Reply-To", "", list){{ sip_in_reply_to_hash, sip_in_reply_to_d, sip_in_reply_to_e
, msg_list_dup_xtra, msg_list_dup_one, ((void*)0), "In-Reply-To"
, sizeof("In-Reply-To") - 1, "", (((uintptr_t)(sizeof(sip_in_reply_to_t
)) + (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*
)))), __builtin_offsetof(sip_in_reply_to_t, k_items), msg_kind_list
, }}
;
413
414issize_t sip_in_reply_to_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
415{
416 return msg_list_d(home, h, s, slen);
417}
418
419issize_t sip_in_reply_to_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
420{
421 assert(sip_in_reply_to_p(h))((sip_is_in_reply_to((h))) ? (void) (0) : __assert_fail ("sip_is_in_reply_to((h))"
, "sip_extra.c", 421, __PRETTY_FUNCTION__))
;
422 return msg_list_e(b, bsiz, h, f);
423}
424
425/* ====================================================================== */
426
427/**@SIP_HEADER sip_organization Organization Header
428 *
429 * The Organization header field conveys the name of the organization to
430 * which the entity issuing the request or response belongs. Its syntax is
431 * defined in @RFC3261 as follows:
432 *
433 * @code
434 * Organization = "Organization" HCOLON [TEXT-UTF8-TRIM]
435 * @endcode
436 *
437 *
438 * The parsed Organization header is stored in #sip_organization_t structure.
439 */
440
441/**@ingroup sip_organization
442 * @typedef struct msg_generic_s sip_organization_t;
443 *
444 * The structure #sip_organization_t contains representation of a SIP
445 * @Organization header.
446 *
447 * The #sip_organization_t is defined as follows:
448 * @code
449 * typedef struct msg_generic_s
450 * {
451 * msg_common_t g_common[1]; // Common fragment info
452 * msg_generic_t *g_next; // Link to next header
453 * char const *g_string; // Organization text
454 * } sip_organization_t;
455 * @endcode
456 */
457
458msg_hclass_t sip_organization_class[] =
459SIP_HEADER_CLASS_G(organization, "Organization", "", single){{ sip_organization_hash, sip_organization_d, sip_organization_e
, msg_generic_dup_xtra, msg_generic_dup_one, ((void*)0), "Organization"
, sizeof("Organization") - 1, "", (((uintptr_t)(sizeof(sip_organization_t
)) + (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*
)))), __builtin_offsetof(sip_organization_t, g_common), msg_kind_single
, }}
;
460
461issize_t sip_organization_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
462{
463 return sip_generic_dmsg_generic_d(home, h, s, slen);
464}
465
466issize_t sip_organization_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
467{
468 assert(sip_organization_p(h))((sip_is_organization((h))) ? (void) (0) : __assert_fail ("sip_is_organization((h))"
, "sip_extra.c", 468, __PRETTY_FUNCTION__))
;
469 return sip_generic_emsg_generic_e(b, bsiz, h, f);
470}
471
472/* ====================================================================== */
473
474/**@SIP_HEADER sip_priority Priority Header
475 *
476 * The Priority request-header field indicates the urgency of the request as
477 * perceived by the client. Its syntax is defined in @RFC3261 as follows:
478 *
479 * @code
480 * Priority = "Priority" HCOLON priority-value
481 * priority-value = "emergency" / "urgent" / "normal"
482 * / "non-urgent" / other-priority
483 * other-priority = token
484 * @endcode
485 *
486 *
487 * The parsed Priority header is stored in #sip_priority_t structure.
488 */
489
490/**@ingroup sip_priority
491 * @typedef struct msg_generic_s sip_priority_t;
492 *
493 * The structure #sip_priority_t contains representation of a SIP
494 * @Priority header.
495 *
496 * The #sip_priority_t is defined as follows:
497 * @code
498 * typedef struct msg_generic_s
499 * {
500 * msg_common_t g_common[1]; // Common fragment info
501 * msg_generic_t *g_next; // Dummy link to next header
502 * char const *g_string; // Priority token
503 * } sip_priority_t;
504 * @endcode
505 */
506
507msg_hclass_t sip_priority_class[] =
508SIP_HEADER_CLASS_G(priority, "Priority", "", single){{ sip_priority_hash, sip_priority_d, sip_priority_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "Priority", sizeof("Priority"
) - 1, "", (((uintptr_t)(sizeof(sip_priority_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_priority_t, g_common), msg_kind_single, }}
;
509
510issize_t sip_priority_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
511{
512 sip_priority_t *priority = (sip_priority_t *)h;
513
514 if (msg_token_d(&s, &priority->g_string) < 0)
515 return -1;
516
517 if (*s && !IS_LWS(*s)((*s) == ' ' || (*s) == '\t' || (*s) == '\r' || (*s) == '\n')) /* Something extra after priority token? */
518 return -1;
519
520 return 0;
521}
522
523issize_t sip_priority_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
524{
525 assert(sip_priority_p(h))((sip_is_priority((h))) ? (void) (0) : __assert_fail ("sip_is_priority((h))"
, "sip_extra.c", 525, __PRETTY_FUNCTION__))
;
526 return sip_generic_emsg_generic_e(b, bsiz, h, f);
527}
528
529/* ====================================================================== */
530
531/**@SIP_HEADER sip_server Server Header
532 *
533 * The Server response-header field contains information about the software
534 * used by the user agent server to handle the request. Its syntax is
535 * defined in @RFC2616 section 14.38 and @RFC3261 as follows:
536 *
537 * @code
538 * Server = "Server" HCOLON server-val *(LWS server-val)
539 * server-val = product / comment
540 * product = token [SLASH product-version]
541 * product-version = token
542 * @endcode
543 *
544 * The parsed Server header is stored in #sip_server_t structure.
545 */
546
547/**@ingroup sip_server
548 * @typedef struct msg_generic_s sip_server_t;
549 *
550 * The structure #sip_server_t contains representation of a SIP
551 * @Server header.
552 *
553 * The #sip_server_t is defined as follows:
554 * @code
555 * typedef struct msg_generic_s
556 * {
557 * msg_common_t g_common[1]; // Common fragment info
558 * msg_generic_t *g_next; // Link to next header
559 * char const *g_string; // Server tokens
560 * } sip_server_t;
561 * @endcode
562 */
563
564msg_hclass_t sip_server_class[] =
565SIP_HEADER_CLASS_G(server, "Server", "", single){{ sip_server_hash, sip_server_d, sip_server_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "Server", sizeof("Server")
- 1, "", (((uintptr_t)(sizeof(sip_server_t)) + (sizeof(void*
)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_server_t, g_common), msg_kind_single, }}
;
566
567issize_t sip_server_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
568{
569 return sip_generic_dmsg_generic_d(home, h, s, slen);
570}
571
572issize_t sip_server_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
573{
574 assert(sip_server_p(h))((sip_is_server((h))) ? (void) (0) : __assert_fail ("sip_is_server((h))"
, "sip_extra.c", 574, __PRETTY_FUNCTION__))
;
575 return sip_generic_emsg_generic_e(b, bsiz, h, f);
576}
577
578/* ====================================================================== */
579
580/**@SIP_HEADER sip_subject Subject Header
581 *
582 * The Subject header provides a summary or indicates the nature of the
583 * request. Its syntax is defined in @RFC3261 as follows:
584 *
585 * @code
586 * Subject = ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]
587 * @endcode
588 *
589 * The parsed Subject header is stored in #sip_subject_t structure.
590 */
591
592/**@ingroup sip_subject
593 * @typedef struct msg_generic_s sip_subject_t;
594 *
595 * The structure #sip_subject_t contains representation of a SIP
596 * @Subject header.
597 *
598 * The #sip_subject_t is defined as follows:
599 * @code
600 * typedef struct msg_generic_s
601 * {
602 * msg_common_t g_common[1]; // Common fragment info
603 * msg_generic_t *g_next; // Link to next header
604 * char const *g_string; // Subject text
605 * } sip_subject_t;
606 * @endcode
607 */
608
609msg_hclass_t sip_subject_class[] =
610SIP_HEADER_CLASS_G(subject, "Subject", "s", single){{ sip_subject_hash, sip_subject_d, sip_subject_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "Subject", sizeof("Subject"
) - 1, "s", (((uintptr_t)(sizeof(sip_subject_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_subject_t, g_common), msg_kind_single, }}
;
611
612issize_t sip_subject_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
613{
614 return sip_generic_dmsg_generic_d(home, h, s, slen);
615}
616
617issize_t sip_subject_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
618{
619 assert(sip_subject_p(h))((sip_is_subject((h))) ? (void) (0) : __assert_fail ("sip_is_subject((h))"
, "sip_extra.c", 619, __PRETTY_FUNCTION__))
;
620 return sip_generic_emsg_generic_e(b, bsiz, h, f);
621}
622
623/* ====================================================================== */
624
625/**@SIP_HEADER sip_timestamp Timestamp Header
626 *
627 * The @b Timestamp header describes when the client sent the request to the
628 * server, and it is used by the client to adjust its retransmission
629 * intervals. Its syntax is defined in @RFC3261 as follows:
630 *
631 * @code
632 * Timestamp = "Timestamp" HCOLON 1*(DIGIT)
633 * [ "." *(DIGIT) ] [ LWS delay ]
634 * delay = *(DIGIT) [ "." *(DIGIT) ]
635 * @endcode
636 *
637 * The parsed Timestamp header is stored in #sip_timestamp_t structure.
638 */
639
640/**@ingroup sip_timestamp
641 * @typedef struct sip_timestamp_s sip_timestamp_t;
642 *
643 * The structure #sip_timestamp_t contains representation of a SIP
644 * @Timestamp header.
645 *
646 * The #sip_timestamp_t is defined as follows:
647 * @code
648 * typedef struct sip_timestamp_s
649 * {
650 * sip_common_t ts_common[1]; // Common fragment info
651 * sip_error_t *ts_next; // Dummy link
652 * char const *ts_stamp; // Original timestamp
653 * char const *ts_delay; // Delay at UAS
654 * } sip_timestamp_t;
655 * @endcode
656 */
657
658static isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset);
659static char *sip_timestamp_dup_one(sip_header_t *dst,
660 sip_header_t const *src,
661 char *b,
662 isize_t xtra);
663#define sip_timestamp_update((void*)0) NULL((void*)0)
664
665msg_hclass_t sip_timestamp_class[] =
666SIP_HEADER_CLASS(timestamp, "Timestamp", "", ts_common, single,{{ sip_timestamp_hash, sip_timestamp_d, sip_timestamp_e, sip_timestamp_dup_xtra
, sip_timestamp_dup_one, ((void*)0), "Timestamp", sizeof("Timestamp"
) - 1, "", (((uintptr_t)(sizeof(sip_timestamp_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_timestamp_t, ts_common), msg_kind_single, }}
667 timestamp){{ sip_timestamp_hash, sip_timestamp_d, sip_timestamp_e, sip_timestamp_dup_xtra
, sip_timestamp_dup_one, ((void*)0), "Timestamp", sizeof("Timestamp"
) - 1, "", (((uintptr_t)(sizeof(sip_timestamp_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_timestamp_t, ts_common), msg_kind_single, }}
;
668
669issize_t sip_timestamp_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
670{
671 sip_timestamp_t *ts = (sip_timestamp_t*)h;
672
673 ts->ts_stamp = s;
674 s += span_digit(s);
675 if (s == ts->ts_stamp)
676 return -1;
677 if (*s == '.') { s += span_digit(s + 1) + 1; }
678
679 if (IS_LWS(*s)((*s) == ' ' || (*s) == '\t' || (*s) == '\r' || (*s) == '\n')) {
680 *s = '\0';
681 s += span_lws(s + 1) + 1;
682 ts->ts_delay = s;
683 s += span_digit(s); if (*s == '.') { s += span_digit(s + 1) + 1; }
684 }
685
686 if (!*s || IS_LWS(*s)((*s) == ' ' || (*s) == '\t' || (*s) == '\r' || (*s) == '\n'))
687 *s++ = '\0';
688 else
689 return -1;
690
691 return 0;
692}
693
694issize_t sip_timestamp_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
695{
696 sip_timestamp_t const *ts = h->sh_timestamp;
697 char *end = b + bsiz, *b0 = b;
698
699 assert(sip_timestamp_p(h))((sip_is_timestamp((h))) ? (void) (0) : __assert_fail ("sip_is_timestamp((h))"
, "sip_extra.c", 699, __PRETTY_FUNCTION__))
;
700
701 MSG_STRING_E(b, end, ts->ts_stamp)do { size_t _n = strlen(ts->ts_stamp); if (b + _n+1 < end
) memcpy(b, ts->ts_stamp, _n+1); b+= _n; } while(0)
;
702 if (ts->ts_delay) {
703 MSG_CHAR_E(b, end, ' ')(++(b) < (end) ? ((b)[-1]=(' ')) : (' '));
704 MSG_STRING_E(b, end, ts->ts_delay)do { size_t _n = strlen(ts->ts_delay); if (b + _n+1 < end
) memcpy(b, ts->ts_delay, _n+1); b+= _n; } while(0)
;
705 }
706
707 MSG_TERM_E(b, end)((b) < (end) ? (b)[0] = '\0' : '\0');
708
709 return b - b0;
710}
711
712static
713isize_t sip_timestamp_dup_xtra(sip_header_t const *h, isize_t offset)
714{
715 sip_timestamp_t const *ts = h->sh_timestamp;
716
717 offset += MSG_STRING_SIZE(ts->ts_stamp)((ts->ts_stamp) ? (strlen(ts->ts_stamp) + 1) : 0);
718 offset += MSG_STRING_SIZE(ts->ts_delay)((ts->ts_delay) ? (strlen(ts->ts_delay) + 1) : 0);
719
720 return offset;
721}
722
723static
724char *sip_timestamp_dup_one(sip_header_t *dst,
725 sip_header_t const *src,
726 char *b,
727 isize_t xtra)
728{
729 sip_timestamp_t *ts = dst->sh_timestamp;
730 sip_timestamp_t const *o = src->sh_timestamp;
731 char *end = b + xtra;
732
733 MSG_STRING_DUP(b, ts->ts_stamp, o->ts_stamp)(void)((o->ts_stamp)?((b)=(char*)memccpy((void *)((ts->
ts_stamp)=(char*)b),(o->ts_stamp),0,2147483647)) :((ts->
ts_stamp)=((void*)0)))
;
734 MSG_STRING_DUP(b, ts->ts_delay, o->ts_delay)(void)((o->ts_delay)?((b)=(char*)memccpy((void *)((ts->
ts_delay)=(char*)b),(o->ts_delay),0,2147483647)) :((ts->
ts_delay)=((void*)0)))
;
735
736 assert(b <= end)((b <= end) ? (void) (0) : __assert_fail ("b <= end", "sip_extra.c"
, 736, __PRETTY_FUNCTION__))
; (void)end;
737
738 return b;
739}
740
741/* ====================================================================== */
742
743/**@SIP_HEADER sip_user_agent User-Agent Header
744 *
745 * The User-Agent header contains information about the client user agent
746 * originating the request. Its syntax is defined in [H14.43, S10.45] as
747 * follows:
748 *
749 * @code
750 * User-Agent = "User-Agent" HCOLON server-val *(LWS server-val)
751 * server-val = product / comment
752 * product = token [SLASH product-version]
753 * product-version = token
754 * @endcode
755 *
756 * The parsed User-Agent header is stored in #sip_user_agent_t structure.
757 */
758
759/**@ingroup sip_user_agent
760 * @typedef struct msg_generic_s sip_user_agent_t;
761 *
762 * The structure #sip_user_agent_t contains representation of a SIP
763 * @UserAgent header.
764 *
765 * The #sip_user_agent_t is defined as follows:
766 * @code
767 * typedef struct msg_generic_s
768 * {
769 * msg_common_t g_common[1]; // Common fragment info
770 * msg_generic_t *g_next; // Link to next header
771 * char const *g_string; // User-Agent components
772 * } sip_user_agent_t;
773 * @endcode
774 */
775
776msg_hclass_t sip_user_agent_class[] =
777SIP_HEADER_CLASS_G(user_agent, "User-Agent", "", single){{ sip_user_agent_hash, sip_user_agent_d, sip_user_agent_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "User-Agent", sizeof("User-Agent"
) - 1, "", (((uintptr_t)(sizeof(sip_user_agent_t)) + (sizeof(
void*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_user_agent_t, g_common), msg_kind_single, }}
;
778
779issize_t sip_user_agent_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
780{
781 return sip_generic_dmsg_generic_d(home, h, s, slen);
782}
783
784issize_t sip_user_agent_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
785{
786 assert(sip_user_agent_p(h))((sip_is_user_agent((h))) ? (void) (0) : __assert_fail ("sip_is_user_agent((h))"
, "sip_extra.c", 786, __PRETTY_FUNCTION__))
;
787 return sip_generic_emsg_generic_e(b, bsiz, h, f);
788}
789
790/* ====================================================================== */
791
792/**@SIP_HEADER sip_etag SIP-ETag Header
793 *
794 * The @b SIP-ETag header field identifies the published event state. Its
795 * syntax is defined in @RFC3903 as follows:
796 *
797 * @code
798 * SIP-ETag = "SIP-ETag" HCOLON entity-tag
799 * entity-tag = token
800 * @endcode
801 *
802 * The parsed SIP-ETag header is stored in #sip_etag_t structure.
803 */
804
805/**@ingroup sip_etag
806 * @typedef struct msg_generic_s sip_etag_t;
807 *
808 * The structure #sip_etag_t contains representation of a SIP
809 * @SIPETag header.
810 *
811 * The #sip_etag_t is defined as follows:
812 * @code
813 * typedef struct msg_generic_s
814 * {
815 * msg_common_t g_common[1]; // Common fragment info
816 * msg_generic_t *g_next; // Link to next header
817 * char const *g_string; // entity-tag
818 * } sip_etag_t;
819 * @endcode
820 */
821
822msg_hclass_t sip_etag_class[] =
823SIP_HEADER_CLASS_G(etag, "SIP-ETag", "", single){{ sip_etag_hash, sip_etag_d, sip_etag_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "SIP-ETag", sizeof("SIP-ETag"
) - 1, "", (((uintptr_t)(sizeof(sip_etag_t)) + (sizeof(void*)
) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_etag_t, g_common), msg_kind_single, }}
;
824
825issize_t sip_etag_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
826{
827 sip_etag_t *etag = (sip_etag_t *)h;
828
829 return msg_token_d(&s, &etag->g_valueg_string);
830}
831
832issize_t sip_etag_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
833{
834 return msg_generic_e(b, bsiz, h, f);
835}
836
837/* ====================================================================== */
838
839/**@SIP_HEADER sip_if_match SIP-If-Match Header
840 *
841 * The @b SIP-If-Match header field identifies the specific entity of event
842 * state that the request is refreshing, modifying or removing. Its syntax
843 * is defined in @RFC3903 as follows:
844 *
845 * @code
846 * SIP-If-Match = "SIP-If-Match" HCOLON entity-tag
847 * entity-tag = token
848 * @endcode
849 *
850 * The parsed SIP-If-Match header is stored in #sip_if_match_t structure.
851 */
852
853/**@ingroup sip_if_match
854 * @typedef struct msg_generic_s sip_if_match_t;
855 *
856 * The structure #sip_if_match_t contains representation of a SIP
857 * @SIPIfMatch header.
858 *
859 * The #sip_if_match_t is defined as follows:
860 * @code
861 * typedef struct msg_generic_s
862 * {
863 * msg_common_t g_common[1]; // Common fragment info
864 * msg_generic_t *g_next; // Link to next header
865 * char const *g_string; // entity-tag
866 * } sip_if_match_t;
867 * @endcode
868 */
869
870msg_hclass_t sip_if_match_class[] =
871SIP_HEADER_CLASS_G(if_match, "SIP-If-Match", "", single){{ sip_if_match_hash, sip_if_match_d, sip_if_match_e, msg_generic_dup_xtra
, msg_generic_dup_one, ((void*)0), "SIP-If-Match", sizeof("SIP-If-Match"
) - 1, "", (((uintptr_t)(sizeof(sip_if_match_t)) + (sizeof(void
*)) - 1) & (0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof
(sip_if_match_t, g_common), msg_kind_single, }}
;
872
873issize_t sip_if_match_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
874{
875 return sip_etag_d(home, h, s, slen);
876}
877
878issize_t sip_if_match_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
879{
880 return sip_etag_e(b, bsiz, h, f);
881}
882
883/* ====================================================================== */
884
885/** Parsing @CallInfo, @ErrorInfo. */
886static
887issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
888{
889 sip_call_info_t *ci = h->sh_call_info;
890 char *end = s + slen;
Value stored to 'end' during its initialization is never read
891
892 for(;;) {
893 ci = h->sh_call_info;
894 end = s + slen;
895
896 while (*s == ',')
897 s += span_lws(s + 1) + 1;
898
899 if (sip_name_addr_d(home, &s, NULL((void*)0), ci->ci_url, &ci->ci_params, NULL((void*)0)) < 0)
900 return -1;
901
902 slen = end - s;
903 msg_parse_next_field_without_recursion(){ msg_header_t *prev = h; msg_hclass_t *hc = prev->sh_common
->h_class; char *end = s + slen; if (*s && *s != ','
) return -1; if (msg_header_update_params(prev->sh_common,
0) < 0) return -1; while (*s == ',') *s = '\0', s += span_lws
(s + 1) + 1; if (*s == 0) return 0; h = msg_header_alloc(home
, hc, 0); if (!h) return -1; prev->sh_common->h_succ = h
, h->sh_common->h_prev = &prev->sh_common->h_succ
; prev->sh_header_next->shn_next = h; slen = end - s; }
;
904 }
905}
906
907isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
908{
909 sip_call_info_t const *ci = h->sh_call_info;
910
911 return sip_name_addr_xtra(NULL((void*)0),
912 ci->ci_url,
913 ci->ci_params,
914 offset);
915}
916
917char *sip_info_dup_one(sip_header_t *dst,
918 sip_header_t const *src,
919 char *b,
920 isize_t xtra)
921{
922 sip_call_info_t *ci = dst->sh_call_info;
923 sip_call_info_t const *o = src->sh_call_info;
924
925 return sip_name_addr_dup(NULL((void*)0), NULL((void*)0),
926 ci->ci_url, o->ci_url,
927 &ci->ci_params, o->ci_params,
928 b, xtra);
929}
930
931/* ====================================================================== */
932
933#if SU_HAVE_EXPERIMENTAL
934
935/**@SIP_HEADER sip_suppress_body_if_match Suppress-Body-If-Match Header
936 *
937 * The @b Suppress-Body-If-Match header field identifies a SIP event content
938 * already known by the watcher. Its syntax is defined in
939 * draft-niemi-sip-subnot-etags-01 as follows:
940 *
941 * @code
942 * Suppress-Body-If-Match = "Suppress-Body-If-Match" HCOLON entity-tag
943 * entity-tag = token
944 * @endcode
945 *
946 * The parsed Suppress-Body-If-Match header is stored in
947 * #sip_suppress_body_if_match_t structure.
948 *
949 * @sa @RFC3265, draft-niemi-sip-subnot-etags-01.txt
950 *
951 * @EXP_1_12_5.
952 * In order to use @b Suppress-Body-If-Match header,
953 * initialize the SIP parser with, e.g.,
954 * sip_update_default_mclass(sip_extend_mclass(NULL)).
955 *
956 * @note
957 * The #sip_t structure does not contain a @a
958 * sip_suppress_body_if_match field, but sip_suppress_body_if_match()
959 * function should be used for accessing the @b Suppress-Body-If-Match
960 * header structure.
961 */
962
963/**@ingroup sip_suppress_body_if_match
964 * @typedef struct sip_suppress_body_if_match_s sip_suppress_body_if_match_t;
965 *
966 * The structure #sip_suppress_body_if_match_t contains representation of a
967 * SIP @SuppressBodyIfMatch header.
968 *
969 * The #sip_suppress_body_if_match_t is defined as follows:
970 * @code
971 * typedef struct sip_suppress_body_if_match_s
972 * {
973 * sip_common_t sbim_common[1]; // Common fragment info
974 * sip_error_t *sbim_next; // Dummy link to next header
975 * char const *sbim_tag; // entity-tag
976 * } sip_suppress_body_if_match_t;
977 * @endcode
978 */
979
980#define sip_suppress_body_if_match_dup_xtra msg_generic_dup_xtra
981#define sip_suppress_body_if_match_dup_one msg_generic_dup_one
982#define sip_suppress_body_if_match_update NULL((void*)0)
983
984msg_hclass_t sip_suppress_body_if_match_class[] =
985SIP_HEADER_CLASS(suppress_body_if_match,{{ sip_suppress_body_if_match_hash, sip_suppress_body_if_match_d
, sip_suppress_body_if_match_e, sip_suppress_body_if_match_dup_xtra
, sip_suppress_body_if_match_dup_one, sip_suppress_body_if_match_update
, "Suppress-Body-If-Match", sizeof("Suppress-Body-If-Match") -
1, "", (((uintptr_t)(sizeof(sip_suppress_body_if_match_t)) +
(sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))))
, __builtin_offsetof(sip_suppress_body_if_match_t, sbim_common
), msg_kind_single, }}
986 "Suppress-Body-If-Match", "",{{ sip_suppress_body_if_match_hash, sip_suppress_body_if_match_d
, sip_suppress_body_if_match_e, sip_suppress_body_if_match_dup_xtra
, sip_suppress_body_if_match_dup_one, sip_suppress_body_if_match_update
, "Suppress-Body-If-Match", sizeof("Suppress-Body-If-Match") -
1, "", (((uintptr_t)(sizeof(sip_suppress_body_if_match_t)) +
(sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))))
, __builtin_offsetof(sip_suppress_body_if_match_t, sbim_common
), msg_kind_single, }}
987 sbim_common, single, suppress_body_if_match){{ sip_suppress_body_if_match_hash, sip_suppress_body_if_match_d
, sip_suppress_body_if_match_e, sip_suppress_body_if_match_dup_xtra
, sip_suppress_body_if_match_dup_one, sip_suppress_body_if_match_update
, "Suppress-Body-If-Match", sizeof("Suppress-Body-If-Match") -
1, "", (((uintptr_t)(sizeof(sip_suppress_body_if_match_t)) +
(sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))))
, __builtin_offsetof(sip_suppress_body_if_match_t, sbim_common
), msg_kind_single, }}
;
988
989issize_t sip_suppress_body_if_match_d(su_home_t *home,
990 sip_header_t *h,
991 char *s, isize_t slen)
992{
993 sip_suppress_body_if_match_t *sbim = (void *)h;
994 return msg_token_d(&s, &sbim->sbim_tag);
995}
996
997issize_t sip_suppress_body_if_match_e(char b[], isize_t bsiz,
998 sip_header_t const *h,
999 int f)
1000{
1001 return sip_etag_e(b, bsiz, h, f);
1002}
1003
1004
1005/* ====================================================================== */
1006
1007/**@SIP_HEADER sip_suppress_notify_if_match Suppress-Notify-If-Match Header
1008 *
1009 * The @b Suppress-Notify-If-Match header is used to suppress
1010 * superfluous NOTIFY transactions. Its syntax is defined in
1011 * draft-niemi-sip-subnot-etags-01 as follows:
1012 *
1013 * @code
1014 * Suppress-Notify-If-Match = "Suppress-Notify-If-Match" HCOLON entity-tag
1015 * entity-tag = token
1016 * @endcode
1017 *
1018 * The parsed Suppress-Notify-If-Match header is stored in
1019 * #sip_suppress_notify_if_match_t structure.
1020 *
1021 * @sa @RFC3265, draft-niemi-sip-subnot-etag-01
1022 *
1023 * @EXP_1_12_5.
1024 * In order to use @b Suppress-Notify-If-Match header,
1025 * initialize the SIP parser with, e.g.,
1026 * sip_update_default_mclass(sip_extend_mclass(NULL)).
1027 *
1028 * @note
1029 * The #sip_t struct does not contain @a sip_suppress_notify_if_match field,
1030 * but sip_suppress_notify_if_match() function should be used for accessing
1031 * the @b Suppress-Notify-If-Match header structure.
1032 */
1033
1034/**@ingroup sip_suppress_notify_if_match
1035 * @typedef struct sip_suppress_notify_if_match_s \
1036 * sip_suppress_notify_if_match_t;
1037 *
1038 * The structure #sip_suppress_notify_if_match_t contains representation of a
1039 * SIP @SuppressNotifyIfMatch header.
1040 *
1041 * The #sip_suppress_notify_if_match_t is defined as follows:
1042 * @code
1043 * typedef struct sip_suppress_notify_if_match_s
1044 * {
1045 * sip_common_t snim_common[1]; // Common fragment info
1046 * sip_error_t *snim_next; // Dummy link to next header
1047 * char const *snim_tag; // entity-tag
1048 * } sip_suppress_notify_if_match_t;
1049 * @endcode
1050 */
1051
1052#define sip_suppress_notify_if_match_dup_xtra msg_generic_dup_xtra
1053#define sip_suppress_notify_if_match_dup_one msg_generic_dup_one
1054#define sip_suppress_notify_if_match_update NULL((void*)0)
1055
1056msg_hclass_t sip_suppress_notify_if_match_class[] =
1057SIP_HEADER_CLASS(suppress_notify_if_match,{{ sip_suppress_notify_if_match_hash, sip_suppress_notify_if_match_d
, sip_suppress_notify_if_match_e, sip_suppress_notify_if_match_dup_xtra
, sip_suppress_notify_if_match_dup_one, sip_suppress_notify_if_match_update
, "Suppress-Notify-If-Match", sizeof("Suppress-Notify-If-Match"
) - 1, "", (((uintptr_t)(sizeof(sip_suppress_notify_if_match_t
)) + (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*
)))), __builtin_offsetof(sip_suppress_notify_if_match_t, snim_common
), msg_kind_single, }}
1058 "Suppress-Notify-If-Match", "",{{ sip_suppress_notify_if_match_hash, sip_suppress_notify_if_match_d
, sip_suppress_notify_if_match_e, sip_suppress_notify_if_match_dup_xtra
, sip_suppress_notify_if_match_dup_one, sip_suppress_notify_if_match_update
, "Suppress-Notify-If-Match", sizeof("Suppress-Notify-If-Match"
) - 1, "", (((uintptr_t)(sizeof(sip_suppress_notify_if_match_t
)) + (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*
)))), __builtin_offsetof(sip_suppress_notify_if_match_t, snim_common
), msg_kind_single, }}
1059 snim_common, single, suppress_notify_if_match){{ sip_suppress_notify_if_match_hash, sip_suppress_notify_if_match_d
, sip_suppress_notify_if_match_e, sip_suppress_notify_if_match_dup_xtra
, sip_suppress_notify_if_match_dup_one, sip_suppress_notify_if_match_update
, "Suppress-Notify-If-Match", sizeof("Suppress-Notify-If-Match"
) - 1, "", (((uintptr_t)(sizeof(sip_suppress_notify_if_match_t
)) + (sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*
)))), __builtin_offsetof(sip_suppress_notify_if_match_t, snim_common
), msg_kind_single, }}
;
1060
1061issize_t sip_suppress_notify_if_match_d(su_home_t *home,
1062 sip_header_t *h,
1063 char *s, isize_t slen)
1064{
1065 sip_suppress_notify_if_match_t *snim = (void *)h;
1066 return msg_token_d(&s, &snim->snim_tag);
1067}
1068
1069issize_t sip_suppress_notify_if_match_e(char b[], isize_t bsiz,
1070 sip_header_t const *h,
1071 int f)
1072{
1073 return msg_generic_e(b, bsiz, h, f);
1074}
1075
1076#endif
1077
1078#if SIP_HAVE_REMOTE_PARTY_ID1
1079
1080/**@SIP_HEADER sip_remote_party_id Remote-Party-ID Header
1081 *
1082 * The syntax of the Remote-Party-ID header is described as follows:
1083 * @code
1084 * Remote-Party-ID = "Remote-Party-ID" HCOLON rpid *(COMMA rpid)
1085 *
1086 * rpid = [display-name] LAQUOT addr-spec RAQUOT
1087 * *(SEMI rpi-token)
1088 *
1089 * rpi-token = rpi-screen / rpi-pty-type /
1090 * rpi-id-type / rpi-privacy / other-rpi-token
1091 *
1092 * rpi-screen = "screen" EQUAL ("no" / "yes")
1093 *
1094 * rpi-pty-type = "party" EQUAL ("calling" / "called" / token)
1095 *
1096 * rpi-id-type = "id-type" EQUAL ("subscriber" / "user" /
1097 * "term" / token)
1098 *
1099 * rpi-privacy = "privacy" EQUAL
1100 * ( rpi-priv-element
1101 * / (LDQUOT rpi-priv-element
1102 * *(COMMA rpi-priv-element) RDQUOT) )
1103 *
1104 * rpi-priv-element = ("full" / "name" / "uri" / "off" / token)
1105 * ["-" ( "network" / token )]
1106 *
1107 * other-rpi-token = ["-"] token [EQUAL (token / quoted-string)]
1108 *
1109 * @endcode
1110 *
1111 * @sa sip_update_default_mclass(), draft-ietf-sip-privacy-04.txt, @RFC3325
1112 *
1113 * @NEW_1_12_7. In order to use @b Remote-Party-ID header,
1114 * initialize the SIP parser before calling nta_agent_create() or
1115 * nua_create() with, e.g.,
1116 * sip_update_default_mclass(sip_extend_mclass(NULL)).
1117 *
1118 * @note
1119 * The #sip_t structure does not contain @a sip_remote_party_id field, but
1120 * sip_remote_party_id() function should be used for accessing the @b
1121 * Remote-Party-ID header structure.
1122 */
1123
1124/**@ingroup sip_remote_party_id
1125 * @typedef typedef struct sip_remote_party_id_s sip_remote_party_id_t;
1126 *
1127 * The structure #sip_remote_party_id_t contains representation of SIP
1128 * @RemotePartyID header.
1129 *
1130 * The #sip_remote_party_id_t is defined as follows:
1131 * @code
1132 * typedef struct sip_remote_party_id_s {
1133 * sip_common_t rpid_common[1]; // Common fragment info
1134 * sip_remote_party_id_t *rpid_next; // Link to next
1135 * char const *rpid_display; // Display name
1136 * url_t rpid_url[1]; // URL
1137 * sip_param_t const *rpid_params; // Parameters
1138 * // Shortcuts to screen, party, id-type and privacy parameters
1139 * char const *rpid_screen, *rpid_party, *rpid_id_type, *rpid_privacy;
1140 * } sip_remote_party_id_t;
1141 * @endcode
1142 */
1143
1144extern msg_xtra_f sip_remote_party_id_dup_xtra;
1145extern msg_dup_f sip_remote_party_id_dup_one;
1146
1147static msg_update_f sip_remote_party_id_update;
1148
1149msg_hclass_t sip_remote_party_id_class[] =
1150SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "",{{ sip_remote_party_id_hash, sip_remote_party_id_d, sip_remote_party_id_e
, sip_remote_party_id_dup_xtra, sip_remote_party_id_dup_one, sip_remote_party_id_update
, "Remote-Party-ID", sizeof("Remote-Party-ID") - 1, "", (((uintptr_t
)(sizeof(sip_remote_party_id_t)) + (sizeof(void*)) - 1) &
(0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof(sip_remote_party_id_t
, rpid_params), msg_kind_append, }}
1151 rpid_params, append, remote_party_id){{ sip_remote_party_id_hash, sip_remote_party_id_d, sip_remote_party_id_e
, sip_remote_party_id_dup_xtra, sip_remote_party_id_dup_one, sip_remote_party_id_update
, "Remote-Party-ID", sizeof("Remote-Party-ID") - 1, "", (((uintptr_t
)(sizeof(sip_remote_party_id_t)) + (sizeof(void*)) - 1) &
(0 - (uintptr_t)(sizeof(void*)))), __builtin_offsetof(sip_remote_party_id_t
, rpid_params), msg_kind_append, }}
;
1152
1153issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h,
1154 char *s, isize_t slen)
1155{
1156 sip_remote_party_id_t *rpid;
1157
1158 for(;;) {
1159 rpid = (sip_remote_party_id_t *)h;
1160
1161 while (*s == ',') /* Ignore empty entries (comma-whitespace) */
1162 *s = '\0', s += span_lws(s + 1) + 1;
1163
1164 if (sip_name_addr_d(home, &s,
1165 &rpid->rpid_display,
1166 rpid->rpid_url,
1167 &rpid->rpid_params, NULL((void*)0)) == -1)
1168 return -1;
1169
1170 msg_parse_next_field_without_recursion(){ msg_header_t *prev = h; msg_hclass_t *hc = prev->sh_common
->h_class; char *end = s + slen; if (*s && *s != ','
) return -1; if (msg_header_update_params(prev->sh_common,
0) < 0) return -1; while (*s == ',') *s = '\0', s += span_lws
(s + 1) + 1; if (*s == 0) return 0; h = msg_header_alloc(home
, hc, 0); if (!h) return -1; prev->sh_common->h_succ = h
, h->sh_common->h_prev = &prev->sh_common->h_succ
; prev->sh_header_next->shn_next = h; slen = end - s; }
;
1171 }
1172
1173}
1174
1175issize_t sip_remote_party_id_e(char b[], isize_t bsiz,
1176 sip_header_t const *h, int f)
1177{
1178 sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
1179
1180 return sip_name_addr_e(b, bsiz, f,
1181 rpid->rpid_display, 1,
1182 rpid->rpid_url,
1183 rpid->rpid_params,
1184 NULL((void*)0));
1185}
1186
1187/** Calculate size of extra data required for duplicating one
1188 * sip_remote_party_id_t header.
1189 */
1190isize_t sip_remote_party_id_dup_xtra(sip_header_t const *h, isize_t offset)
1191{
1192 sip_remote_party_id_t const *rpid = (sip_remote_party_id_t *)h;
1193 return sip_name_addr_xtra(rpid->rpid_display,
1194 rpid->rpid_url,
1195 rpid->rpid_params,
1196 offset);
1197}
1198
1199/** Duplicate one sip_remote_party_id_t object */
1200char *sip_remote_party_id_dup_one(sip_header_t *dst,
1201 sip_header_t const *src,
1202 char *b, isize_t xtra)
1203{
1204 sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)dst;
1205 sip_remote_party_id_t const *o = (sip_remote_party_id_t const *)src;
1206
1207 return sip_name_addr_dup(&rpid->rpid_display, o->rpid_display,
1208 rpid->rpid_url, o->rpid_url,
1209 &rpid->rpid_params, o->rpid_params,
1210 b, xtra);
1211}
1212
1213static int sip_remote_party_id_update(msg_common_t *h,
1214 char const *name, isize_t namelen,
1215 char const *value)
1216{
1217 sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h;
1218
1219 if (name == NULL((void*)0)) {
1220 rpid->rpid_screen = NULL((void*)0);
1221 rpid->rpid_party = NULL((void*)0);
1222 rpid->rpid_id_type = NULL((void*)0);
1223 rpid->rpid_privacy = NULL((void*)0);
1224 }
1225
1226#define MATCH(s) (namelen == strlen(#s) && su_casenmatch(name, #s, strlen(#s)))
1227
1228 else if (MATCH(screen))
1229 rpid->rpid_screen = value;
1230 else if (MATCH(party))
1231 rpid->rpid_party = value;
1232 else if (MATCH(id-type))
1233 rpid->rpid_id_type = value;
1234 else if (MATCH(privacy))
1235 rpid->rpid_privacy = value;
1236
1237#undef MATCH
1238
1239 return 0;
1240}
1241
1242#endif
1243
1244#if SIP_HAVE_P_ASSERTED_IDENTITY1
1245
1246/**@SIP_HEADER sip_p_asserted_identity P-Asserted-Identity Header
1247 *
1248 * The P-Asserted-Identity header is used used among trusted SIP entities
1249 * (typically intermediaries) to carry the identity of the user sending a
1250 * SIP message as it was verified by authentication. It is "defined" in
1251 * @RFC3325 section 9.1 as follows:
1252 *
1253 * @code
1254 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
1255 * *(COMMA PAssertedID-value)
1256 * PAssertedID-value = name-addr / addr-spec
1257 * @endcode
1258 *
1259 * @sa @RFC3325, @PPreferredIdentity
1260 *
1261 * @NEW_1_12_7. In order to use @b P-Asserted-Identity header,
1262 * initialize the SIP parser before calling nta_agent_create() or
1263 * nua_create() with, e.g.,
1264 * sip_update_default_mclass(sip_extend_mclass(NULL)).
1265 *
1266 * @note
1267 * The #sip_t structure does not contain @a sip_p_asserted_identity field,
1268 * but sip_p_asserted_identity() function should be used for accessing the
1269 * @b P-Asserted-Identity header structure.
1270 */
1271
1272/**@ingroup sip_p_asserted_identity
1273 * @typedef typedef struct sip_p_asserted_identity_s sip_p_asserted_identity_t;
1274 *
1275 * The structure #sip_p_asserted_identity_t contains representation of SIP
1276 * @PAssertedIdentity header.
1277 *
1278 * The #sip_p_asserted_identity_t is defined as follows:
1279 * @code
1280 * typedef struct sip_p_asserted_identity_s {
1281 * sip_common_t paid_common[1]; // Common fragment info
1282 * sip_p_asserted_identity_t *paid_next; // Link to next
1283 * char const *paid_display; // Display name
1284 * url_t paid_url[1]; // URL
1285 * } sip_p_asserted_identity_t;
1286 * @endcode
1287 */
1288
1289static msg_xtra_f sip_p_asserted_identity_dup_xtra;
1290static msg_dup_f sip_p_asserted_identity_dup_one;
1291
1292#define sip_p_asserted_identity_update((void*)0) NULL((void*)0)
1293
1294msg_hclass_t sip_p_asserted_identity_class[] =
1295SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "",{{ sip_p_asserted_identity_hash, sip_p_asserted_identity_d, sip_p_asserted_identity_e
, sip_p_asserted_identity_dup_xtra, sip_p_asserted_identity_dup_one
, ((void*)0), "P-Asserted-Identity", sizeof("P-Asserted-Identity"
) - 1, "", (((uintptr_t)(sizeof(sip_p_asserted_identity_t)) +
(sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))))
, __builtin_offsetof(sip_p_asserted_identity_t, paid_common),
msg_kind_append, }}
1296 paid_common, append, p_asserted_identity){{ sip_p_asserted_identity_hash, sip_p_asserted_identity_d, sip_p_asserted_identity_e
, sip_p_asserted_identity_dup_xtra, sip_p_asserted_identity_dup_one
, ((void*)0), "P-Asserted-Identity", sizeof("P-Asserted-Identity"
) - 1, "", (((uintptr_t)(sizeof(sip_p_asserted_identity_t)) +
(sizeof(void*)) - 1) & (0 - (uintptr_t)(sizeof(void*))))
, __builtin_offsetof(sip_p_asserted_identity_t, paid_common),
msg_kind_append, }}
;
1297
1298issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h,
1299 char *s, isize_t slen)
1300{
1301 sip_p_asserted_identity_t *paid;
1302
1303 for(;;) {
1304 paid = (sip_p_asserted_identity_t *)h;
1305 while (*s == ',') /* Ignore empty entries (comma-whitespace) */
1306 *s = '\0', s += span_lws(s + 1) + 1;
1307
1308 if (sip_name_addr_d(home, &s,
1309 &paid->paid_display,
1310 paid->paid_url,
1311 NULL((void*)0), NULL((void*)0)) == -1)
1312 return -1;
1313
1314 msg_parse_next_field_without_recursion(){ msg_header_t *prev = h; msg_hclass_t *hc = prev->sh_common
->h_class; char *end = s + slen; if (*s && *s != ','
) return -1; if (msg_header_update_params(prev->sh_common,
0) < 0) return -1; while (*s == ',') *s = '\0', s += span_lws
(s + 1) + 1; if (*s == 0) return 0; h = msg_header_alloc(home
, hc, 0); if (!h) return -1; prev->sh_common->h_succ = h
, h->sh_common->h_prev = &prev->sh_common->h_succ
; prev->sh_header_next->shn_next = h; slen = end - s; }
;
1315 }
1316
1317}
1318
1319issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz,
1320 sip_header_t const *h, int f)
1321{
1322 sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
1323
1324 return sip_name_addr_e(b, bsiz, f,
1325 paid->paid_display, MSG_IS_CANONIC(f)((((f)) & (MSG_FLG_CANONIC)) == MSG_FLG_CANONIC),
1326 paid->paid_url,
1327 NULL((void*)0),
1328 NULL((void*)0));
1329}
1330
1331isize_t sip_p_asserted_identity_dup_xtra(sip_header_t const *h, isize_t offset)
1332{
1333 sip_p_asserted_identity_t const *paid = (sip_p_asserted_identity_t *)h;
1334
1335 return sip_name_addr_xtra(paid->paid_display,
1336 paid->paid_url,
1337 NULL((void*)0),
1338 offset);
1339}
1340
1341/** Duplicate one sip_p_asserted_identity_t object */
1342char *sip_p_asserted_identity_dup_one(sip_header_t *dst,
1343 sip_header_t const *src,
1344 char *b, isize_t xtra)
1345{
1346 sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)dst;
1347 sip_p_asserted_identity_t const *o = (sip_p_asserted_identity_t *)src;
1348
1349 return sip_name_addr_dup(&paid->paid_display, o->paid_display,
1350 paid->paid_url, o->paid_url,
1351 NULL((void*)0), NULL((void*)0),
1352 b, xtra);
1353}
1354
1355#endif
1356
1357#if SIP_HAVE_P_PREFERRED_IDENTITY1
1358
1359/**@SIP_HEADER sip_p_preferred_identity P-Preferred-Identity Header
1360 *
1361 * The P-Preferred-Identity header is used used among trusted SIP entities
1362 * (typically intermediaries) to carry the identity of the user sending a
1363 * SIP message as it was verified by authentication. It is "defined" in
1364 * @RFC3325 section 9.1 as follows:
1365 *
1366 * @code
1367 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
1368 * *(COMMA PPreferredID-value)
1369 * PPreferredID-value = name-addr / addr-spec
1370 * @endcode
1371 *
1372 * @sa @RFC3325, @PAssertedIdentity
1373 *
1374 * @NEW_1_12_7. In order to use @b P-Preferred-Identity header,
1375 * initialize the SIP parser before calling nta_agent_create() or
1376 * nua_create() with, e.g.,
1377 * sip_update_default_mclass(sip_extend_mclass(NULL)).
1378 *
1379 * @note
1380 * The #sip_t structure does not contain @a sip_p_preferred_identity field,
1381 * but sip_p_preferred_identity() function should be used for accessing the
1382 * @b P-Preferred-Identity header structure.
1383 */
1384
1385/**@ingroup sip_p_preferred_identity
1386 * @typedef typedef struct sip_p_preferred_identity_s sip_p_preferred_identity_t;
1387 *
1388 * The structure #sip_p_preferred_identity_t contains representation of SIP
1389 * @PPreferredIdentity header.
1390 *
1391 * The #sip_p_preferred_identity_t is defined as follows:
1392 * @code
1393 * typedef struct sip_p_preferred_identity_s {
1394 * sip_common_t ppid_common[1]; // Common fragment info
1395 * sip_p_preferred_identity_t *ppid_next; // Link to next
1396 * char const *ppid_display; // Display name
1397 * url_t ppid_url[1]; // URL
1398 * } sip_p_preferred_identity_t;
1399 * @endcode
1400 */
1401
1402
1403msg_hclass_t sip_p_preferred_identity_class[] =
1404SIP_HEADER_CLASS(p_preferred_identity, "P-Preferred-Identity", "",{{ sip_p_preferred_identity_hash, sip_p_preferred_identity_d,
sip_p_preferred_identity_e, sip_p_asserted_identity_dup_xtra
, sip_p_asserted_identity_dup_one, ((void*)0), "P-Preferred-Identity"
, sizeof("P-Preferred-Identity") - 1, "", (((uintptr_t)(sizeof
(sip_p_preferred_identity_t)) + (sizeof(void*)) - 1) & (0
- (uintptr_t)(sizeof(void*)))), __builtin_offsetof(sip_p_preferred_identity_t
, ppid_common), msg_kind_append, }}
1405 ppid_common, append, p_asserted_identity){{ sip_p_preferred_identity_hash, sip_p_preferred_identity_d,
sip_p_preferred_identity_e, sip_p_asserted_identity_dup_xtra
, sip_p_asserted_identity_dup_one, ((void*)0), "P-Preferred-Identity"
, sizeof("P-Preferred-Identity") - 1, "", (((uintptr_t)(sizeof
(sip_p_preferred_identity_t)) + (sizeof(void*)) - 1) & (0
- (uintptr_t)(sizeof(void*)))), __builtin_offsetof(sip_p_preferred_identity_t
, ppid_common), msg_kind_append, }}
;
1406
1407issize_t sip_p_preferred_identity_d(su_home_t *home, sip_header_t *h,
1408 char *s, isize_t slen)
1409{
1410 return sip_p_asserted_identity_d(home, h, s, slen);
1411}
1412
1413issize_t sip_p_preferred_identity_e(char b[], isize_t bsiz,
1414 sip_header_t const *h, int f)
1415{
1416 return sip_p_asserted_identity_e(b, bsiz, h, f);
1417}
1418
1419#endif