Bug Summary

File:nta.c
Warning:line 2476, column 5
Access to field 'h_data' results in a dereference of a null pointer (loaded from field 'v_common')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name nta.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-11/lib/clang/11.0.1 -D HAVE_CONFIG_H -I . -I ../.. -I ../../libsofia-sip-ua/su/sofia-sip -I ./../ipt -I ../ipt -I ./../msg -I ../msg -I ./../sip -I ../sip -I ./../bnf -I ../bnf -I ./../sresolv -I ../sresolv -I ./../tport -I ../tport -I ./../url -I ../url -I ./../features -I ../features -I ./../su -I ../su -I ../../s2check -I ./../stun -I ../stun -D SU_DEBUG=0 -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir /drone/src/libsofia-sip-ua/nta -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -o /drone/src/scan-build/2023-06-16-162611-12-1 -x c nta.c

nta.c

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 nta.c
26 * @brief Sofia SIP Transaction API implementation
27 *
28 * This source file has been divided into sections as follows:
29 * 1) agent
30 * 2) tport handling
31 * 3) dispatching messages received from network
32 * 4) message creation and message utility functions
33 * 5) stateless operation
34 * 6) dialogs (legs)
35 * 7) server transactions (incoming)
36 * 8) client transactions (outgoing)
37 * 9) resolving URLs for client transactions
38 * 10) 100rel reliable responses (reliable)
39 * 11) SigComp handling and public transport interface
40 *
41 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
42 *
43 * @date Created: Tue Jun 13 02:57:51 2000 ppessi
44 *
45 * @sa
46 * @RFC3261, @RFC4320
47 */
48
49#include "config.h"
50#ifdef HAVE_ZLIB_COMPRESS1
51#include <zlib.h>
52#endif
53#include <sofia-sip/su_string.h>
54
55/** @internal SU message argument structure type */
56#define SU_MSG_ARG_Tunion sm_arg_u union sm_arg_u
57/** @internal SU timer argument pointer type */
58#define SU_TIMER_ARG_Tstruct nta_agent_s struct nta_agent_s
59
60#include <sofia-sip/su_alloc.h>
61#include <sofia-sip/su.h>
62#include <sofia-sip/su_time.h>
63#include <sofia-sip/su_wait.h>
64#include <sofia-sip/su_tagarg.h>
65
66#include <sofia-sip/base64.h>
67#include <sofia-sip/su_uniqueid.h>
68
69#include <sofia-sip/sip.h>
70#include <sofia-sip/sip_header.h>
71#include <sofia-sip/sip_util.h>
72#include <sofia-sip/sip_status.h>
73
74#include <sofia-sip/hostdomain.h>
75#include <sofia-sip/url_tag.h>
76
77#include <sofia-sip/msg_addr.h>
78#include <sofia-sip/msg_parser.h>
79#include <sofia-sip/htable.h>
80
81/* Resolver context type */
82#define SRES_CONTEXT_Tnta_outgoing_t nta_outgoing_t
83
84/* We are customer of tport_t */
85#define TP_AGENT_Tnta_agent_t nta_agent_t
86#define TP_MAGIC_Tsip_via_t sip_via_t
87#define TP_CLIENT_Tnta_outgoing_t nta_outgoing_t
88
89#include "nta_internal.h"
90
91#include <stddef.h>
92#include <stdlib.h>
93#include <stdio.h>
94#include <stdarg.h>
95#include <assert.h>
96#include <limits.h>
97#include <errno(*__errno_location ()).h>
98
99/* From AM_INIT/AC_INIT in our "config.h" */
100char const nta_version[] = PACKAGE_VERSION"1.13.15";
101
102#if HAVE_FUNC1
103#elif HAVE_FUNCTION1
104#define __func__ __FUNCTION__
105#else
106static char const __func__[] = "nta";
107#endif
108
109#ifndef _MSC_VER
110#define NONE((void *)-1) ((void *)-1)
111#else
112#define NONE((void *)-1) ((void *)(INT_PTR)-1)
113#endif
114/* ------------------------------------------------------------------------- */
115
116/** Resolving order */
117enum nta_res_order_e
118{
119 nta_res_ip6_ip4,
120 nta_res_ip4_ip6,
121 nta_res_ip6_only,
122 nta_res_ip4_only
123};
124
125HTABLE_DECLARE_WITH(leg_htable, lht, nta_leg_t, size_t, hash_value_t)typedef struct leg_htable_s { size_t lht_size; size_t lht_used
; nta_leg_t**lht_table; } leg_htable_t
;
126HTABLE_DECLARE_WITH(outgoing_htable, oht, nta_outgoing_t, size_t, hash_value_t)typedef struct outgoing_htable_s { size_t oht_size; size_t oht_used
; nta_outgoing_t**oht_table; } outgoing_htable_t
;
127HTABLE_DECLARE_WITH(incoming_htable, iht, nta_incoming_t, size_t, hash_value_t)typedef struct incoming_htable_s { size_t iht_size; size_t iht_used
; nta_incoming_t**iht_table; } incoming_htable_t
;
128
129typedef struct outgoing_queue_t {
130 nta_outgoing_t **q_tail;
131 nta_outgoing_t *q_head;
132 size_t q_length;
133 unsigned q_timeout;
134} outgoing_queue_t;
135
136typedef struct incoming_queue_t {
137 nta_incoming_t **q_tail;
138 nta_incoming_t *q_head;
139 size_t q_length;
140 unsigned q_timeout;
141} incoming_queue_t;
142
143struct nta_agent_s
144{
145 su_home_t sa_home[1];
146 su_root_t *sa_root;
147 su_timer_t *sa_timer;
148 nta_agent_magic_t *sa_magic;
149 nta_message_f *sa_callback;
150
151 nta_update_magic_t *sa_update_magic;
152 nta_update_tport_f *sa_update_tport;
153
154 nta_error_magic_t *sa_error_magic;
155 nta_error_tport_f *sa_error_tport;
156
157 uint32_t sa_next; /**< Timestamp for next agent_timer. */
158
159 msg_mclass_t const *sa_mclass;
160 uint32_t sa_flags; /**< SIP message flags */
161 unsigned sa_preload; /**< Memory preload for SIP messages. */
162
163 tport_t *sa_tports;
164 sip_contact_t *sa_contact;
165 sip_via_t *sa_vias; /**< @Via headers for all transports */
166 sip_via_t *sa_public_vias; /**< @Vias for public transports */
167 sip_contact_t *sa_aliases;/**< List of aliases for agent */
168
169 uint64_t sa_branch; /**< Generator for branch parameters */
170 uint64_t sa_tags; /**< Generator for tag parameters */
171
172#if HAVE_SOFIA_SRESOLV1
173 sres_resolver_t *sa_resolver; /**< DNS resolver */
174 enum nta_res_order_e sa_res_order; /** Resolving order (AAAA/A) */
175#endif
176
177 url_t *sa_default_proxy; /**< Default outbound proxy */
178 unsigned sa_bad_req_mask; /**< Request error mask */
179 unsigned sa_bad_resp_mask; /**< Response error mask */
180 usize_t sa_maxsize; /**< Maximum size of incoming messages */
181 usize_t sa_max_proceeding; /**< Maximum size of proceeding queue */
182 usize_t sa_max_recv_requests_per_second; /**< Maximum receiving requests per second */
183
184 unsigned sa_udp_mtu; /**< Maximum size of outgoing UDP requests */
185
186 unsigned sa_t1; /**< SIP T1 - initial retransmit interval (500 ms) */
187 unsigned sa_t2; /**< SIP T2 - maximum retransmit interval (4000 ms) */
188 unsigned sa_t4; /**< SIP T4 - clear message time (5000 ms) */
189
190
191 unsigned sa_t1x64; /**< SIP T1X64 - transaction lifetime (32 s) */
192
193 unsigned sa_tls_orq_connect_timeout; /**< Connect Timeout for outgoing requests using TLS (ms) */
194
195 unsigned sa_progress; /**< Progress timer.
196 Interval between retransmitting
197 provisional responses. */
198
199 unsigned sa_timer_c; /**< SIP timer C.
200 Maximum interval between receiving
201 provisional responses. */
202
203 unsigned sa_graylist; /**< Graylisting period */
204 unsigned sa_blacklist; /**< Blacklisting period */
205
206 unsigned sa_drop_prob : 10; /**< NTA is used to test packet drop */
207 unsigned sa_is_a_uas : 1; /**< NTA is acting as an User Agent server */
208 unsigned sa_is_stateless : 1; /**< Process requests statelessly
209 * unless they match existing dialog.
210 */
211 unsigned sa_user_via:1; /**< Let application provide @Via headers */
212 unsigned sa_extra_100:1; /**< Allow NTA to return "100 Trying" response
213 * even if application has not responded.
214 */
215 unsigned sa_pass_100:1; /**< Pass the "100 Trying"
216 * provisional responses to the application
217 */
218 unsigned sa_timeout_408:1; /**< A "408 Request Timeout" message
219 * is generated when outgoing request expires.
220 */
221 unsigned sa_pass_408:1; /**< A "408 Request Timeout" responses
222 * are passed to client.
223 */
224 unsigned sa_merge_482 : 1; /**< A "482 Request Merged" response is returned
225 * to merged requests.
226 */
227 unsigned sa_cancel_2543 : 1; /**< Send a CANCEL to an INVITE without
228 * waiting for an provisional response.
229 */
230 unsigned sa_cancel_487 : 1; /**< Return 487 response automatically when
231 * a CANCEL is received.
232 */
233
234 unsigned sa_invite_100rel:1; /**< Include 100rel in INVITE requests. */
235 unsigned sa_timestamp : 1; /**< Insert @Timestamp in requests. */
236
237 unsigned sa_tport_ip4 : 1; /**< Transports support IPv4. */
238 unsigned sa_tport_ip6 : 1; /**< Transports support IPv6. */
239 unsigned sa_tport_udp : 1; /**< Transports support UDP. */
240 unsigned sa_tport_tcp : 1; /**< Transports support TCP. */
241 unsigned sa_tport_sctp : 1; /**< Transports support SCTP. */
242 unsigned sa_tport_tls : 1; /**< Transports support TLS. */
243 unsigned sa_tport_ws : 1; /**< Transports support WS. */
244 unsigned sa_tport_wss : 1; /**< Transports support WSS. */
245
246 unsigned sa_use_naptr : 1; /**< Use NAPTR lookup */
247 unsigned sa_use_srv : 1; /**< Use SRV lookup */
248
249 unsigned sa_srv_503 : 1; /**< SRV: choice another destination on 503 RFC 3263 */
250
251 unsigned sa_tport_threadpool:1; /**< Transports use threadpool */
252
253 unsigned sa_rport:1; /**< Use rport at client */
254 unsigned sa_server_rport:2; /**< Use rport at server */
255 unsigned sa_tcp_rport:1; /**< Use rport with tcp, too */
256 unsigned sa_tls_rport:1; /**< Use rport with tls, too */
257
258 unsigned sa_auto_comp:1; /**< Automatically create compartments */
259 unsigned sa_in_timer:1; /**< Set when executing timers */
260 unsigned sa_use_timer_c:1; /**< Application has set value for timer C */
261
262 unsigned :0;
263
264#if HAVE_SMIME
265 sm_object_t *sa_smime;
266#else
267 void *sa_smime;
268#endif
269
270 /** @MaxForwards */
271 sip_max_forwards_t sa_max_forwards[1];
272
273 /** Name of SigComp algorithm */
274 char const *sa_algorithm;
275 /** Options for SigComp. */
276 char const *sa_sigcomp_options;
277 char const* const *sa_sigcomp_option_list;
278 char const *sa_sigcomp_option_free;
279
280 nta_compressor_t *sa_compressor;
281
282 /* Statistics */
283 struct {
284 usize_t as_recv_msg;
285 usize_t as_recv_request;
286 usize_t as_recv_response;
287 usize_t as_bad_message;
288 usize_t as_bad_request;
289 usize_t as_bad_response;
290 usize_t as_drop_request;
291 usize_t as_drop_response;
292 usize_t as_client_tr;
293 usize_t as_server_tr;
294 usize_t as_dialog_tr;
295 usize_t as_acked_tr;
296 usize_t as_canceled_tr;
297 usize_t as_trless_request;
298 usize_t as_trless_to_tr;
299 usize_t as_trless_response;
300 usize_t as_trless_200;
301 usize_t as_merged_request;
302 usize_t as_sent_msg;
303 usize_t as_sent_request;
304 usize_t as_sent_response;
305 usize_t as_retry_request;
306 usize_t as_retry_response;
307 usize_t as_recv_retry;
308 usize_t as_tout_request;
309 usize_t as_tout_response;
310 } sa_stats[1];
311
312 /** Current load in receiving messages per second */
313 struct {
314 usize_t as_recv_request_last;
315 su_time_t last_time;
316 unsigned requests_per_second;
317 } sa_load[1];
318
319 /** Hash of dialogs. */
320 leg_htable_t sa_dialogs[1];
321 /** Default leg */
322 nta_leg_t *sa_default_leg;
323 /** Hash of legs without dialogs. */
324 leg_htable_t sa_defaults[1];
325 /** Hash table for outgoing transactions */
326 outgoing_htable_t sa_outgoing[1];
327 nta_outgoing_t *sa_default_outgoing;
328 /** Hash table for incoming transactions */
329 incoming_htable_t sa_incoming[1];
330 nta_incoming_t *sa_default_incoming;
331
332 /* Queues (states) for outgoing client transactions */
333 struct {
334 /** Queue for retrying client transactions */
335 nta_outgoing_t *re_list;
336 nta_outgoing_t **re_t1; /**< Special place for T1 timer */
337 size_t re_length; /**< Length of sa_out.re_list */
338
339 outgoing_queue_t delayed[1];
340 outgoing_queue_t resolving[1];
341
342 outgoing_queue_t trying[1]; /* Timer F / Timer E */
343 outgoing_queue_t completed[1]; /* Timer K */
344 outgoing_queue_t terminated[1];
345
346 /* Special queues (states) for outgoing INVITE transactions */
347 outgoing_queue_t inv_calling[1]; /* Timer B/A */
348 outgoing_queue_t inv_proceeding[1]; /* Timer C */
349 outgoing_queue_t inv_completed[1]; /* Timer D */
350
351 /* Temporary queue for transactions waiting to be freed */
352 outgoing_queue_t *free;
353 } sa_out;
354
355 /* Queues (states) for incoming server transactions */
356 struct {
357 /** Queue for retransmitting response of server transactions */
358 nta_incoming_t *re_list;
359 nta_incoming_t **re_t1; /**< Special place for T1 timer */
360 size_t re_length; /**< Length of sa_in.re_list */
361
362 incoming_queue_t proceeding[1]; /**< Request received */
363 incoming_queue_t preliminary[1]; /**< 100rel sent */
364 incoming_queue_t completed[1]; /**< Final answer sent (non-invite). */
365 incoming_queue_t inv_completed[1]; /**< Final answer sent (INVITE). */
366 incoming_queue_t inv_confirmed[1]; /**< Final answer sent, ACK recvd. */
367 incoming_queue_t terminated[1]; /**< Terminated, ready to free. */
368 incoming_queue_t final_failed[1];
369 } sa_in;
370
371 /* Special task for freeing memory */
372 su_clone_r sa_terminator;
373};
374
375struct nta_leg_s
376{
377 su_home_t leg_home[1];
378 hash_value_t leg_hash;
379
380 unsigned leg_dialog : 1;
381 unsigned leg_stateless : 1; /**< Process requests statelessly */
382#ifdef NTA_STRICT_ROUTING
383 unsigned leg_contact_set : 1;
384#else
385 unsigned leg_loose_route : 1; /**< Topmost route in set is LR */
386#endif
387 unsigned leg_route_set : 1; /**< Route set has been saved */
388 unsigned leg_local_is_to : 1; /**< Backwards-compatibility. */
389 unsigned leg_tagged : 1; /**< Tagged after creation.
390 *
391 * Request missing @To tag matches
392 * a tagged leg even after tagging.
393 */
394 unsigned leg_compressed:1;
395 unsigned:0;
396 nta_request_f *leg_callback;
397 nta_leg_magic_t *leg_magic;
398 nta_agent_t *leg_agent;
399
400 url_t const *leg_url; /**< Match incoming requests. */
401 char const *leg_method; /**< Match incoming requests. */
402
403 uint32_t leg_seq; /**< Sequence number for next transaction */
404 uint32_t leg_rseq; /**< Remote sequence number */
405 sip_call_id_t *leg_id; /**< Call ID */
406 sip_from_t *leg_remote; /**< Remote address (@To/@From) */
407 sip_to_t *leg_local; /**< Local address (@From/@To) */
408
409 sip_route_t *leg_route; /**< @Route for outgoing requests. */
410 sip_contact_t *leg_target; /**< Remote destination (from @Contact). */
411};
412
413struct nta_incoming_s
414{
415 su_home_t *irq_home;
416 hash_value_t irq_hash;
417 nta_agent_t *irq_agent;
418 nta_ack_cancel_f *irq_callback;
419 nta_incoming_magic_t *irq_magic;
420
421 /* Timeout/state queue */
422 nta_incoming_t **irq_prev;
423 nta_incoming_t *irq_next;
424 incoming_queue_t *irq_queue;
425
426 /* Retry queue */
427 nta_incoming_t **irq_rprev;
428 nta_incoming_t *irq_rnext;
429
430 sip_method_t irq_method;
431 sip_request_t *irq_rq;
432 sip_from_t *irq_from;
433 sip_to_t *irq_to;
434 char const *irq_tag;
435 sip_cseq_t *irq_cseq;
436 sip_call_id_t *irq_call_id;
437 sip_via_t *irq_via;
438 sip_record_route_t *irq_record_route;
439 char const *irq_branch;
440
441 uint32_t irq_rseq;
442
443 sip_timestamp_t *irq_timestamp;
444 su_time_t irq_received;
445
446 uint32_t irq_timeout; /**< Timer H, I, J */
447 uint32_t irq_retry; /**< Timer G */
448 unsigned short irq_interval; /**< Next timer */
449
450 short irq_status;
451
452 unsigned irq_retries:8;
453 unsigned irq_default:1; /**< Default transaction */
454 unsigned irq_canceled:1; /**< Transaction is canceled */
455 unsigned irq_completed:1; /**< Transaction is completed */
456 unsigned irq_confirmed:1; /**< Response has been acked */
457 unsigned irq_terminated:1; /**< Transaction is terminated */
458 unsigned irq_final_failed:1; /**< Sending final response failed */
459 unsigned irq_destroyed :1; /**< Transaction is destroyed */
460 unsigned irq_in_callback:1; /**< Callback is being invoked */
461 unsigned irq_reliable_tp:1; /**< Transport is reliable */
462 unsigned irq_sigcomp_zap:1; /**< Reset SigComp */
463 unsigned irq_must_100rel:1; /**< 100rel is required */
464 unsigned irq_extra_100:1; /**< 100 Trying should be sent */
465 unsigned irq_tag_set:1; /**< Tag is not from request */
466 unsigned irq_compressed:1;
467 unsigned :0;
468
469 tp_name_t irq_tpn[1];
470 tport_t *irq_tport;
471 struct sigcomp_compartment *irq_cc;
472 msg_t *irq_request;
473 msg_t *irq_request2; /**< ACK/CANCEL */
474 msg_t *irq_response;
475
476 nta_reliable_t *irq_reliable; /**< List of reliable responses */
477};
478
479struct nta_reliable_s
480{
481 nta_reliable_t *rel_next;
482 nta_incoming_t *rel_irq;
483 nta_prack_f *rel_callback;
484 nta_reliable_magic_t *rel_magic;
485 uint32_t rel_rseq;
486 unsigned short rel_status;
487 unsigned rel_pracked:1;
488 unsigned rel_precious:1;
489 msg_t *rel_response;
490 msg_t *rel_unsent;
491};
492
493typedef struct sipdns_resolver sipdns_resolver_t;
494
495struct nta_outgoing_s
496{
497 hash_value_t orq_hash; /**< Hash value */
498 nta_agent_t *orq_agent;
499 nta_response_f *orq_callback;
500 nta_outgoing_magic_t *orq_magic;
501
502 /* Timeout/state queue */
503 nta_outgoing_t **orq_prev;
504 nta_outgoing_t *orq_next;
505 outgoing_queue_t *orq_queue;
506
507 /* Retry queue */
508 nta_outgoing_t **orq_rprev;
509 nta_outgoing_t *orq_rnext;
510
511 sip_method_t orq_method;
512 char const *orq_method_name;
513 url_t const *orq_url; /**< Original RequestURI */
514
515 sip_from_t const *orq_from;
516 sip_to_t const *orq_to;
517 char const *orq_tag; /**< Tag from final response. */
518
519 sip_cseq_t const *orq_cseq;
520 sip_call_id_t const *orq_call_id;
521
522 msg_t *orq_request;
523 msg_t *orq_response;
524
525 su_time_t orq_sent; /**< When request was sent? */
526 unsigned orq_delay; /**< RTT estimate */
527
528 uint32_t orq_retry; /**< Timer A, E */
529 uint32_t orq_timeout; /**< Timer B, D, F, K */
530
531 unsigned short orq_interval; /**< Next timer A/E */
532
533 unsigned short orq_status;
534 unsigned char orq_retries; /**< Number of tries this far */
535
536 unsigned orq_default:1; /**< This is default transaction */
537 unsigned orq_inserted:1;
538 unsigned orq_resolved:1;
539 unsigned orq_via_added:1;
540 unsigned orq_prepared:1;
541 unsigned orq_canceled:1;
542 unsigned orq_terminated:1;
543 unsigned orq_destroyed:1;
544 unsigned orq_completed:1;
545 unsigned orq_delayed:1;
546 unsigned orq_user_tport:1; /**< Application provided tport - don't retry */
547 unsigned orq_try_tcp_instead:1;
548 unsigned orq_try_udp_instead:1;
549 unsigned orq_reliable:1; /**< Transport is reliable */
550 unsigned orq_call_tls_connect_timeout_is_set:1; /** Per Call connect timeout for outgoing requests using TLS set flag*/
551
552 unsigned orq_forked:1; /**< Tagged fork */
553
554 /* Attributes */
555 unsigned orq_sips:1;
556 unsigned orq_uas:1; /**< Running this transaction as UAS */
557 unsigned orq_user_via:1;
558 unsigned orq_stateless:1;
559 unsigned orq_pass_100:1;
560 unsigned orq_sigcomp_new:1; /**< Create compartment if needed */
561 unsigned orq_sigcomp_zap:1; /**< Reset SigComp after completing */
562 unsigned orq_must_100rel:1;
563 unsigned orq_timestamp:1; /**< Insert @Timestamp header. */
564 unsigned orq_100rel:1; /**< Support 100rel */
565 unsigned:0; /* pad */
566
567#if HAVE_SOFIA_SRESOLV1
568 sipdns_resolver_t *orq_resolver;
569#endif
570 url_t *orq_route; /**< Route URL */
571 tp_name_t orq_tpn[1]; /**< Where to send request */
572
573 tport_t *orq_tport;
574 struct sigcomp_compartment *orq_cc;
575 tagi_t *orq_tags; /**< Tport tag items */
576
577 char const *orq_branch; /**< Transaction branch */
578 char const *orq_via_branch; /**< @Via branch */
579
580 int *orq_status2b; /**< Delayed response */
581
582 nta_outgoing_t *orq_cancel; /**< Delayed CANCEL transaction */
583
584 nta_outgoing_t *orq_forking; /**< Untagged transaction */
585 nta_outgoing_t *orq_forks; /**< Tagged transactions */
586 uint32_t orq_rseq; /**< Latest incoming rseq */
587 int orq_pending; /**< Request is pending in tport */
588 uint32_t orq_call_tls_connect_timeout; /** Per Call connect timeout for outgoing requests using TLS */
589};
590
591/* ------------------------------------------------------------------------- */
592
593/* Internal tags */
594
595/* Delay sending of request */
596#define NTATAG_DELAY_SENDING(x)ntatag_delay_sending, tag_bool_v((x)) ntatag_delay_sending, tag_bool_v((x))
597#define NTATAG_DELAY_SENDING_REF(x)ntatag_delay_sending_ref, tag_bool_vr(&(x)) \
598ntatag_delay_sending_ref, tag_bool_vr(&(x))
599
600extern tag_typedef_t ntatag_delay_sending;
601extern tag_typedef_t ntatag_delay_sending_ref;
602
603/* Allow sending incomplete responses */
604#define NTATAG_INCOMPLETE(x)ntatag_incomplete, tag_bool_v((x)) ntatag_incomplete, tag_bool_v((x))
605#define NTATAG_INCOMPLETE_REF(x)ntatag_incomplete_ref, tag_bool_vr(&(x)) \
606ntatag_incomplete_ref, tag_bool_vr(&(x))
607
608extern tag_typedef_t ntatag_incomplete;
609extern tag_typedef_t ntatag_incomplete_ref;
610
611nta_compressor_vtable_t *nta_compressor_vtable = NULL((void*)0);
612
613/* Agent */
614static int agent_tag_init(nta_agent_t *self);
615static int agent_timer_init(nta_agent_t *agent);
616static void agent_timer(su_root_magic_t *rm, su_timer_t *, nta_agent_t *);
617static int agent_launch_terminator(nta_agent_t *agent);
618static void agent_kill_terminator(nta_agent_t *agent);
619static int agent_set_params(nta_agent_t *agent, tagi_t *tags);
620static void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu);
621static int agent_get_params(nta_agent_t *agent, tagi_t *tags);
622
623/* Transport interface */
624static sip_via_t const *agent_tport_via(tport_t *tport);
625static int outgoing_insert_via(nta_outgoing_t *orq, sip_via_t const *);
626static int nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport);
627
628static msg_t *nta_msg_create_for_transport(nta_agent_t *agent, int flags,
629 char const data[], usize_t dlen,
630 tport_t const *tport,
631 tp_client_t *via);
632
633static int complete_response(msg_t *response,
634 int status, char const *phrase,
635 msg_t *request);
636
637static int mreply(nta_agent_t *agent,
638 msg_t *reply,
639 int status, char const *phrase,
640 msg_t *req_msg,
641 tport_t *tport,
642 int incomplete,
643 int sdwn_after,
644 char const *to_tag,
645 tag_type_t tag, tag_value_t value, ...);
646
647#define IF_SIGCOMP_TPTAG_COMPARTMENT(cc)!(cc && cc != ((void *)-1)) ? tag_skip : tptag_compartment
, tag_ptr_v((cc)),
TAG_IF(cc && cc != NONE, TPTAG_COMPARTMENT(cc))!(cc && cc != ((void *)-1)) ? tag_skip : tptag_compartment
, tag_ptr_v((cc))
,
648#define IF_SIGCOMP_TPTAG_COMPARTMENT_REF(cc)tptag_compartment_ref, tag_ptr_vr(&(cc), cc), TPTAG_COMPARTMENT_REF(cc)tptag_compartment_ref, tag_ptr_vr(&(cc), cc),
649
650struct sigcomp_compartment;
651
652struct sigcomp_compartment *
653nta_compartment_ref(struct sigcomp_compartment *cc);
654
655static
656struct sigcomp_compartment *
657agent_compression_compartment(nta_agent_t *sa, tport_t *tp, tp_name_t const *tpn,
658 int new_if_needed);
659
660static
661int agent_accept_compressed(nta_agent_t *sa, msg_t *msg,
662 struct sigcomp_compartment *cc);
663
664static int agent_close_compressor(nta_agent_t *sa,
665 struct sigcomp_compartment *cc);
666
667static int agent_zap_compressor(nta_agent_t *sa,
668 struct sigcomp_compartment *cc);
669
670
671static char const * stateful_branch(su_home_t *home, nta_agent_t *);
672static char const * stateless_branch(nta_agent_t *, msg_t *, sip_t const *,
673 tp_name_t const *tp);
674
675#define NTA_BRANCH_PRIME(uint64_t)(0xB9591D1C361C6521ULL) SU_U64_C(0xB9591D1C361C6521)(uint64_t)(0xB9591D1C361C6521ULL)
676#define NTA_TAG_PRIME(uint64_t)(0xB9591D1C361C6521ULL) SU_U64_C(0xB9591D1C361C6521)(uint64_t)(0xB9591D1C361C6521ULL)
677
678#ifndef UINT32_MAX(4294967295U)
679#define UINT32_MAX(4294967295U) (0xffffffffU)
680#endif
681
682HTABLE_PROTOS_WITH(leg_htable, lht, nta_leg_t, size_t, hash_value_t)static inline int leg_htable_resize(su_home_t *, leg_htable_t
lht[1], size_t); static inline int leg_htable_is_full(leg_htable_t
const *); static inline nta_leg_t **leg_htable_hash(leg_htable_t
const *, hash_value_t hv); static inline nta_leg_t **leg_htable_next
(leg_htable_t const *, nta_leg_t * const *ee); static inline void
leg_htable_append(leg_htable_t *lht, nta_leg_t const *e); static
inline void leg_htable_insert(leg_htable_t *lht, nta_leg_t const
*e); static inline int leg_htable_remove(leg_htable_t *, nta_leg_t
const *e)
;
683static nta_leg_t *leg_find(nta_agent_t const *sa,
684 char const *method_name,
685 url_t const *request_uri,
686 sip_call_id_t const *i,
687 char const *from_tag,
688 char const *to_tag);
689static nta_leg_t *dst_find(nta_agent_t const *sa, url_t const *u0,
690 char const *method);
691static void leg_recv(nta_leg_t *, msg_t *, sip_t *, tport_t *);
692static void leg_free(nta_agent_t *sa, nta_leg_t *leg);
693
694#define NTA_HASH(i, cs)((i)->i_hash + 26839U * (uint32_t)(cs)) ((i)->i_hash + 26839U * (uint32_t)(cs))
695
696HTABLE_PROTOS_WITH(incoming_htable, iht, nta_incoming_t, size_t, hash_value_t)static inline int incoming_htable_resize(su_home_t *, incoming_htable_t
iht[1], size_t); static inline int incoming_htable_is_full(incoming_htable_t
const *); static inline nta_incoming_t **incoming_htable_hash
(incoming_htable_t const *, hash_value_t hv); static inline nta_incoming_t
**incoming_htable_next(incoming_htable_t const *, nta_incoming_t
* const *ee); static inline void incoming_htable_append(incoming_htable_t
*iht, nta_incoming_t const *e); static inline void incoming_htable_insert
(incoming_htable_t *iht, nta_incoming_t const *e); static inline
int incoming_htable_remove(incoming_htable_t *, nta_incoming_t
const *e)
;
697static nta_incoming_t *incoming_create(nta_agent_t *agent,
698 msg_t *request,
699 sip_t *sip,
700 tport_t *tport,
701 char const *tag);
702static int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip);
703static void incoming_free(nta_incoming_t *irq);
704su_inlinestatic inline void incoming_cut_off(nta_incoming_t *irq);
705su_inlinestatic inline void incoming_reclaim(nta_incoming_t *irq);
706static void incoming_queue_init(incoming_queue_t *,
707 unsigned timeout);
708static void incoming_queue_adjust(nta_agent_t *sa,
709 incoming_queue_t *queue,
710 unsigned timeout);
711
712static nta_incoming_t *incoming_find(nta_agent_t const *agent,
713 sip_t const *sip,
714 sip_via_t const *v,
715 nta_incoming_t **merge,
716 nta_incoming_t **ack,
717 nta_incoming_t **cancel);
718static int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip);
719su_inlinestatic inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
720 tport_t *tport);
721su_inlinestatic inline int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
722 tport_t *tport);
723su_inlinestatic inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
724 tport_t *tport);
725static void request_merge(nta_agent_t *,
726 msg_t *msg, sip_t *sip, tport_t *tport,
727 char const *to_tag);
728su_inlinestatic inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *);
729static void _nta_incoming_timer(nta_agent_t *);
730
731static nta_reliable_t *reliable_mreply(nta_incoming_t *,
732 nta_prack_f *, nta_reliable_magic_t *,
733 msg_t *, sip_t *);
734static int reliable_send(nta_incoming_t *, nta_reliable_t *, msg_t *, sip_t *);
735static int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip);
736static msg_t *reliable_response(nta_incoming_t *irq);
737static nta_reliable_t *reliable_find(nta_agent_t const *, sip_t const *);
738static int reliable_recv(nta_reliable_t *rel, msg_t *, sip_t *, tport_t *);
739static void reliable_flush(nta_incoming_t *irq);
740static void reliable_timeout(nta_incoming_t *irq, int timeout);
741
742HTABLE_PROTOS_WITH(outgoing_htable, oht, nta_outgoing_t, size_t, hash_value_t)static inline int outgoing_htable_resize(su_home_t *, outgoing_htable_t
oht[1], size_t); static inline int outgoing_htable_is_full(outgoing_htable_t
const *); static inline nta_outgoing_t **outgoing_htable_hash
(outgoing_htable_t const *, hash_value_t hv); static inline nta_outgoing_t
**outgoing_htable_next(outgoing_htable_t const *, nta_outgoing_t
* const *ee); static inline void outgoing_htable_append(outgoing_htable_t
*oht, nta_outgoing_t const *e); static inline void outgoing_htable_insert
(outgoing_htable_t *oht, nta_outgoing_t const *e); static inline
int outgoing_htable_remove(outgoing_htable_t *, nta_outgoing_t
const *e)
;
743static nta_outgoing_t *outgoing_create(nta_agent_t *agent,
744 nta_response_f *callback,
745 nta_outgoing_magic_t *magic,
746 url_string_t const *route_url,
747 tp_name_t const *tpn,
748 msg_t *msg,
749 tag_type_t tag, tag_value_t value, ...);
750static void outgoing_queue_init(outgoing_queue_t *,
751 unsigned timeout);
752static void outgoing_queue_adjust(nta_agent_t *sa,
753 outgoing_queue_t *queue,
754 unsigned timeout);
755static void outgoing_free(nta_outgoing_t *orq);
756su_inlinestatic inline void outgoing_cut_off(nta_outgoing_t *orq);
757su_inlinestatic inline void outgoing_reclaim(nta_outgoing_t *orq);
758static nta_outgoing_t *outgoing_find(nta_agent_t const *sa,
759 msg_t const *msg,
760 sip_t const *sip,
761 sip_via_t const *v);
762static int outgoing_recv(nta_outgoing_t *orq, int status, msg_t *, sip_t *);
763static void outgoing_default_recv(nta_outgoing_t *, int, msg_t *, sip_t *);
764static void _nta_outgoing_timer(nta_agent_t *);
765static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);
766
767/* Internal message passing */
768union sm_arg_u {
769 struct outgoing_recv_s {
770 nta_outgoing_t *orq;
771 msg_t *msg;
772 sip_t *sip;
773 int status;
774 } a_outgoing_recv[1];
775
776 incoming_queue_t a_incoming_queue[1];
777 outgoing_queue_t a_outgoing_queue[1];
778};
779
780/* Global module data */
781
782/**@var char const NTA_DEBUG[];
783 *
784 * Environment variable determining the default debug log level.
785 *
786 * The NTA_DEBUG environment variable is used to determine the default
787 * debug logging level. The normal level is 3.
788 *
789 * @sa <sofia-sip/su_debug.h>, #su_log_global, #SOFIA_DEBUG
790 */
791#ifdef DOXYGEN
792extern char const NTA_DEBUG[]; /* dummy declaration for Doxygen */
793#endif
794
795#ifndef SU_DEBUG0
796#define SU_DEBUG0 3
797#endif
798
799/**Debug log for @b nta module.
800 *
801 * The nta_log is the log object used by @b nta module. The level of
802 * nta_log is set using #NTA_DEBUG environment variable.
803 */
804su_log_t nta_log[] = { SU_LOG_INIT("nta", "NTA_DEBUG", SU_DEBUG){ sizeof(su_log_t), "nta", "NTA_DEBUG", 0, SU_LOG_MAX, 0, ((void
*)0), ((void*)0), }
};
805
806/* ====================================================================== */
807/* 1) Agent */
808
809/**
810 * Create an NTA agent object.
811 *
812 * Create an NTA agent object. The agent
813 * object creates and binds a server socket with address specified in @e url.
814 * If the @e host portion of the @e url is @c "*", the agent listens to all
815 * addresses available on the host.
816 *
817 * When a message is received, the agent object parses it. If the result is
818 * a valid SIP message, the agent object passes the message to the
819 * application by invoking the nta_message_f @e callback function.
820 *
821 * @note
822 * The @e url can be either parsed url (of type url_t ()), or a valid
823 * SIP URL as a string.
824 *
825 * @note
826 * If @e url is @c NULL, the default @e url @c "sip:*" is used.
827 * @par
828 * If @e url is @c NONE (iow, (void*)-1), no server sockets are bound.
829 * @par
830 * If @p transport parameters are specified in @a url, agent uses only
831 * specified transport type.
832 *
833 * @par
834 * If an @p maddr parameter is specified in @e url, agent binds to the
835 * specified address, but uses @e host part of @e url when it generates
836 * @Contact and @Via headers. The @p maddr parameter is also included,
837 * unless it equals to @c INADDR_ANY (@p 0.0.0.0 or @p [::]).
838 *
839 * @param root pointer to a su_root_t used for synchronization
840 * @param contact_url URL that agent uses to bind the server sockets
841 * @param callback pointer to callback function
842 * @param magic pointer to user data
843 * @param tag,value,... tagged arguments
844 *
845 * @TAGS
846 * NTATAG_ALIASES(),
847 * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
848 * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
849 * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
850 * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(),
851 * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
852 * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(),
853 * NTATAG_REL100(),
854 * NTATAG_SERVER_RPORT(),
855 * NTATAG_SIPFLAGS(),
856 * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
857 * NTATAG_STATELESS(),
858 * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
859 * NTATAG_TLS_RPORT(), NTATAG_TLS_ORQ_CONNECT_TIMEOUT(),
860 * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(),
861 * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
862 * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
863 *
864 * @note The value from following tags are stored, but they currently do nothing:
865 * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
866 *
867 * @note It is possible to provide @c (url_string_t*)-1 as @a contact_url.
868 * In that case, no server sockets are bound.
869 *
870 * @retval handle to the agent when successful,
871 * @retval NULL upon an error.
872 *
873 * @sa NUTAG_
874 */
875nta_agent_t *nta_agent_create(su_root_t *root,
876 url_string_t const *contact_url,
877 nta_message_f *callback,
878 nta_agent_magic_t *magic,
879 tag_type_t tag, tag_value_t value, ...)
880{
881 nta_agent_t *agent;
882 ta_list ta;
883
884 if (root == NULL((void*)0))
885 return su_seterrno(EINVAL22), NULL((void*)0);
886
887 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
888
889 if ((agent = su_home_new(sizeof(*agent)))) {
890 unsigned timer_c = 0, timer_d = 32000;
891
892 agent->sa_root = root;
893 agent->sa_callback = callback;
894 agent->sa_magic = magic;
895 agent->sa_flags = MSG_DO_CANONICMSG_FLG_CANONIC;
896
897 agent->sa_maxsize = 2 * 1024 * 1024; /* 2 MB */
898 agent->sa_bad_req_mask =
899 /*
900 * Bit-wise not of these - what is left is suitable for UAs with
901 * 100rel, timer, events, publish
902 */
903 (unsigned) ~(sip_mask_response | sip_mask_proxy | sip_mask_registrar |
904 sip_mask_pref | sip_mask_privacy);
905 agent->sa_bad_resp_mask =
906 (unsigned) ~(sip_mask_request | sip_mask_proxy | sip_mask_registrar |
907 sip_mask_pref | sip_mask_privacy);
908 agent->sa_t1 = NTA_SIP_T1;
909 agent->sa_t2 = NTA_SIP_T2;
910 agent->sa_t4 = NTA_SIP_T4;
911 agent->sa_t1x64 = 64 * NTA_SIP_T1;
912 agent->sa_timer_c = 185 * 1000;
913 agent->sa_graylist = 600;
914 agent->sa_drop_prob = 0;
915 agent->sa_is_a_uas = 0;
916 agent->sa_progress = 60 * 1000;
917 agent->sa_user_via = 0;
918 agent->sa_extra_100 = 0;
919 agent->sa_pass_100 = 0;
920 agent->sa_timeout_408 = 1;
921 agent->sa_pass_408 = 0;
922 agent->sa_merge_482 = 0;
923 agent->sa_cancel_2543 = 0;
924 agent->sa_cancel_487 = 1;
925 agent->sa_invite_100rel = 0;
926 agent->sa_timestamp = 0;
927 agent->sa_use_naptr = 1;
928 agent->sa_use_srv = 1;
929 agent->sa_srv_503 = 1;
930 agent->sa_auto_comp = 0;
931 agent->sa_server_rport = 1;
932
933 /* RFC 3261 section 8.1.1.6 */
934 sip_max_forwards_init(agent->sa_max_forwards);
935
936 if (getenv("SIPCOMPACT"))
937 agent->sa_flags |= MSG_DO_COMPACTMSG_FLG_COMPACT;
938
939 agent_set_params(agent, ta_args(ta)(ta).tl);
940
941 if (agent->sa_mclass == NULL((void*)0))
942 agent->sa_mclass = sip_default_mclass();
943
944 agent->sa_in.re_t1 = &agent->sa_in.re_list;
945
946 incoming_queue_init(agent->sa_in.proceeding, 0);
947 incoming_queue_init(agent->sa_in.preliminary, agent->sa_t1x64); /* P1 */
948 incoming_queue_init(agent->sa_in.inv_completed, agent->sa_t1x64); /* H */
949 incoming_queue_init(agent->sa_in.inv_confirmed, agent->sa_t4); /* I */
950 incoming_queue_init(agent->sa_in.completed, agent->sa_t1x64); /* J */
951 incoming_queue_init(agent->sa_in.terminated, 0);
952 incoming_queue_init(agent->sa_in.final_failed, 0);
953
954 agent->sa_out.re_t1 = &agent->sa_out.re_list;
955
956 if (agent->sa_use_timer_c || !agent->sa_is_a_uas)
957 timer_c = agent->sa_timer_c;
958 if (timer_d < agent->sa_t1x64)
959 timer_d = agent->sa_t1x64;
960
961 outgoing_queue_init(agent->sa_out.delayed, 0);
962 outgoing_queue_init(agent->sa_out.resolving, 0);
963 outgoing_queue_init(agent->sa_out.trying, agent->sa_t1x64); /* F */
964 outgoing_queue_init(agent->sa_out.completed, agent->sa_t4); /* K */
965 outgoing_queue_init(agent->sa_out.terminated, 0);
966 /* Special queues (states) for outgoing INVITE transactions */
967 outgoing_queue_init(agent->sa_out.inv_calling, agent->sa_t1x64); /* B */
968 outgoing_queue_init(agent->sa_out.inv_proceeding, timer_c); /* C */
969 outgoing_queue_init(agent->sa_out.inv_completed, timer_d); /* D */
970
971 if (leg_htable_resize(agent->sa_home, agent->sa_dialogs, 0) < 0 ||
972 leg_htable_resize(agent->sa_home, agent->sa_defaults, 0) < 0 ||
973 outgoing_htable_resize(agent->sa_home, agent->sa_outgoing, 0) < 0 ||
974 incoming_htable_resize(agent->sa_home, agent->sa_incoming, 0) < 0) {
975 SU_DEBUG_0(("nta_agent_create: failure with %s\n", "hash tables"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 0 ? (_su_llog(nta_log, 0, "nta.c", (const char *)__func__
, 975, "nta_agent_create: failure with %s\n", "hash tables"))
: (void)0)
;
976 goto deinit;
977 }
978 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "hash tables"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 978, "nta_agent_create: initialized %s\n", "hash tables")) :
(void)0)
;
979
980 if (contact_url != (url_string_t *)-1 &&
981 nta_agent_add_tport(agent, contact_url, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0) {
982 SU_DEBUG_7(("nta_agent_create: failure with %s\n", "transport"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 982, "nta_agent_create: failure with %s\n", "transport")) :
(void)0)
;
983 goto deinit;
984 }
985 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "transports"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 985, "nta_agent_create: initialized %s\n", "transports")) :
(void)0)
;
986
987 if (agent_tag_init(agent) < 0) {
988 SU_DEBUG_3(("nta_agent_create: failure with %s\n", "random identifiers"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 988, "nta_agent_create: failure with %s\n", "random identifiers"
)) : (void)0)
;
989 goto deinit;
990 }
991 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "random identifiers"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 991, "nta_agent_create: initialized %s\n", "random identifiers"
)) : (void)0)
;
992
993 if (agent_timer_init(agent) < 0) {
994 SU_DEBUG_0(("nta_agent_create: failure with %s\n", "timer"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 0 ? (_su_llog(nta_log, 0, "nta.c", (const char *)__func__
, 994, "nta_agent_create: failure with %s\n", "timer")) : (void
)0)
;
995 goto deinit;
996 }
997 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "timer"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 997, "nta_agent_create: initialized %s\n", "timer")) : (void
)0)
;
998
999 if (agent_launch_terminator(agent) == 0)
1000 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "threads"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1000, "nta_agent_create: initialized %s\n", "threads")) : (
void)0)
;
1001
1002#if HAVE_SOFIA_SRESOLV1
1003 agent->sa_resolver = sres_resolver_create(root, NULL((void*)0), ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
1004 if (!agent->sa_resolver) {
1005 SU_DEBUG_0(("nta_agent_create: failure with %s\n", "resolver"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 0 ? (_su_llog(nta_log, 0, "nta.c", (const char *)__func__
, 1005, "nta_agent_create: failure with %s\n", "resolver")) :
(void)0)
;
1006 }
1007 SU_DEBUG_9(("nta_agent_create: initialized %s\n", "resolver"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1007, "nta_agent_create: initialized %s\n", "resolver")) : (
void)0)
;
1008#endif
1009
1010 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1011
1012 return agent;
1013
1014 deinit:
1015 nta_agent_destroy(agent);
1016 }
1017
1018 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1019
1020 return NULL((void*)0);
1021}
1022
1023/**
1024 * Destroy an NTA agent object.
1025 *
1026 * @param agent the NTA agent object to be destroyed.
1027 *
1028 */
1029void nta_agent_destroy(nta_agent_t *agent)
1030{
1031 if (agent) {
1032 size_t i;
1033 outgoing_htable_t *oht = agent->sa_outgoing;
1034 incoming_htable_t *iht = agent->sa_incoming;
1035 /* Currently, this is pretty pointless, as legs don't keep any resources */
1036 leg_htable_t *lht;
1037 nta_leg_t *leg;
1038
1039 for (i = 0, lht = agent->sa_dialogs; i < lht->lht_size; i++) {
1040 if ((leg = lht->lht_table[i])) {
1041 SU_DEBUG_3(("nta_agent_destroy: destroying dialog with <"(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1043, "nta_agent_destroy: destroying dialog with <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", (leg->leg_remote->a_url)->url_scheme ? (leg
->leg_remote->a_url)->url_scheme : "", (leg->leg_remote
->a_url)->url_type != url_any && (leg->leg_remote
->a_url)->url_scheme && (leg->leg_remote->
a_url)->url_scheme[0] ? ":" : "", (leg->leg_remote->
a_url)->url_root && ((leg->leg_remote->a_url
)->url_host || (leg->leg_remote->a_url)->url_user
) ? "//" : "", (leg->leg_remote->a_url)->url_user ? (
leg->leg_remote->a_url)->url_user : "", (leg->leg_remote
->a_url)->url_user && (leg->leg_remote->a_url
)->url_password ? ":" : "", (leg->leg_remote->a_url)
->url_user && (leg->leg_remote->a_url)->url_password
? (leg->leg_remote->a_url)->url_password : "", (leg
->leg_remote->a_url)->url_user && (leg->leg_remote
->a_url)->url_host ? "@" : "", (leg->leg_remote->
a_url)->url_host ? (leg->leg_remote->a_url)->url_host
: "", (leg->leg_remote->a_url)->url_host &&
(leg->leg_remote->a_url)->url_port ? ":" : "", (leg
->leg_remote->a_url)->url_host && (leg->leg_remote
->a_url)->url_port ? (leg->leg_remote->a_url)->
url_port : "", (leg->leg_remote->a_url)->url_root &&
(leg->leg_remote->a_url)->url_path ? "/" : "", (leg
->leg_remote->a_url)->url_path ? (leg->leg_remote
->a_url)->url_path : "", (leg->leg_remote->a_url)
->url_params ? ";" : "", (leg->leg_remote->a_url)->
url_params ? (leg->leg_remote->a_url)->url_params : ""
, (leg->leg_remote->a_url)->url_headers ? "?" : "", (
leg->leg_remote->a_url)->url_headers ? (leg->leg_remote
->a_url)->url_headers : "", (leg->leg_remote->a_url
)->url_fragment ? "#" : "", (leg->leg_remote->a_url)
->url_fragment ? (leg->leg_remote->a_url)->url_fragment
: "")) : (void)0)
1042 URL_PRINT_FORMAT ">\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1043, "nta_agent_destroy: destroying dialog with <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", (leg->leg_remote->a_url)->url_scheme ? (leg
->leg_remote->a_url)->url_scheme : "", (leg->leg_remote
->a_url)->url_type != url_any && (leg->leg_remote
->a_url)->url_scheme && (leg->leg_remote->
a_url)->url_scheme[0] ? ":" : "", (leg->leg_remote->
a_url)->url_root && ((leg->leg_remote->a_url
)->url_host || (leg->leg_remote->a_url)->url_user
) ? "//" : "", (leg->leg_remote->a_url)->url_user ? (
leg->leg_remote->a_url)->url_user : "", (leg->leg_remote
->a_url)->url_user && (leg->leg_remote->a_url
)->url_password ? ":" : "", (leg->leg_remote->a_url)
->url_user && (leg->leg_remote->a_url)->url_password
? (leg->leg_remote->a_url)->url_password : "", (leg
->leg_remote->a_url)->url_user && (leg->leg_remote
->a_url)->url_host ? "@" : "", (leg->leg_remote->
a_url)->url_host ? (leg->leg_remote->a_url)->url_host
: "", (leg->leg_remote->a_url)->url_host &&
(leg->leg_remote->a_url)->url_port ? ":" : "", (leg
->leg_remote->a_url)->url_host && (leg->leg_remote
->a_url)->url_port ? (leg->leg_remote->a_url)->
url_port : "", (leg->leg_remote->a_url)->url_root &&
(leg->leg_remote->a_url)->url_path ? "/" : "", (leg
->leg_remote->a_url)->url_path ? (leg->leg_remote
->a_url)->url_path : "", (leg->leg_remote->a_url)
->url_params ? ";" : "", (leg->leg_remote->a_url)->
url_params ? (leg->leg_remote->a_url)->url_params : ""
, (leg->leg_remote->a_url)->url_headers ? "?" : "", (
leg->leg_remote->a_url)->url_headers ? (leg->leg_remote
->a_url)->url_headers : "", (leg->leg_remote->a_url
)->url_fragment ? "#" : "", (leg->leg_remote->a_url)
->url_fragment ? (leg->leg_remote->a_url)->url_fragment
: "")) : (void)0)
1043 URL_PRINT_ARGS(leg->leg_remote->a_url)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1043, "nta_agent_destroy: destroying dialog with <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", (leg->leg_remote->a_url)->url_scheme ? (leg
->leg_remote->a_url)->url_scheme : "", (leg->leg_remote
->a_url)->url_type != url_any && (leg->leg_remote
->a_url)->url_scheme && (leg->leg_remote->
a_url)->url_scheme[0] ? ":" : "", (leg->leg_remote->
a_url)->url_root && ((leg->leg_remote->a_url
)->url_host || (leg->leg_remote->a_url)->url_user
) ? "//" : "", (leg->leg_remote->a_url)->url_user ? (
leg->leg_remote->a_url)->url_user : "", (leg->leg_remote
->a_url)->url_user && (leg->leg_remote->a_url
)->url_password ? ":" : "", (leg->leg_remote->a_url)
->url_user && (leg->leg_remote->a_url)->url_password
? (leg->leg_remote->a_url)->url_password : "", (leg
->leg_remote->a_url)->url_user && (leg->leg_remote
->a_url)->url_host ? "@" : "", (leg->leg_remote->
a_url)->url_host ? (leg->leg_remote->a_url)->url_host
: "", (leg->leg_remote->a_url)->url_host &&
(leg->leg_remote->a_url)->url_port ? ":" : "", (leg
->leg_remote->a_url)->url_host && (leg->leg_remote
->a_url)->url_port ? (leg->leg_remote->a_url)->
url_port : "", (leg->leg_remote->a_url)->url_root &&
(leg->leg_remote->a_url)->url_path ? "/" : "", (leg
->leg_remote->a_url)->url_path ? (leg->leg_remote
->a_url)->url_path : "", (leg->leg_remote->a_url)
->url_params ? ";" : "", (leg->leg_remote->a_url)->
url_params ? (leg->leg_remote->a_url)->url_params : ""
, (leg->leg_remote->a_url)->url_headers ? "?" : "", (
leg->leg_remote->a_url)->url_headers ? (leg->leg_remote
->a_url)->url_headers : "", (leg->leg_remote->a_url
)->url_fragment ? "#" : "", (leg->leg_remote->a_url)
->url_fragment ? (leg->leg_remote->a_url)->url_fragment
: "")) : (void)0)
;
1044 leg_free(agent, leg);
1045 }
1046 }
1047
1048 for (i = 0, lht = agent->sa_defaults; i < lht->lht_size; i++) {
1049 if ((leg = lht->lht_table[i])) {
1050 SU_DEBUG_3(("%s: destroying leg for <"(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1052, "%s: destroying leg for <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (leg->leg_url)->url_scheme ? (leg->
leg_url)->url_scheme : "", (leg->leg_url)->url_type !=
url_any && (leg->leg_url)->url_scheme &&
(leg->leg_url)->url_scheme[0] ? ":" : "", (leg->leg_url
)->url_root && ((leg->leg_url)->url_host || (
leg->leg_url)->url_user) ? "//" : "", (leg->leg_url)
->url_user ? (leg->leg_url)->url_user : "", (leg->
leg_url)->url_user && (leg->leg_url)->url_password
? ":" : "", (leg->leg_url)->url_user && (leg->
leg_url)->url_password ? (leg->leg_url)->url_password
: "", (leg->leg_url)->url_user && (leg->leg_url
)->url_host ? "@" : "", (leg->leg_url)->url_host ? (
leg->leg_url)->url_host : "", (leg->leg_url)->url_host
&& (leg->leg_url)->url_port ? ":" : "", (leg->
leg_url)->url_host && (leg->leg_url)->url_port
? (leg->leg_url)->url_port : "", (leg->leg_url)->
url_root && (leg->leg_url)->url_path ? "/" : ""
, (leg->leg_url)->url_path ? (leg->leg_url)->url_path
: "", (leg->leg_url)->url_params ? ";" : "", (leg->
leg_url)->url_params ? (leg->leg_url)->url_params : ""
, (leg->leg_url)->url_headers ? "?" : "", (leg->leg_url
)->url_headers ? (leg->leg_url)->url_headers : "", (
leg->leg_url)->url_fragment ? "#" : "", (leg->leg_url
)->url_fragment ? (leg->leg_url)->url_fragment : "")
) : (void)0)
1051 URL_PRINT_FORMAT ">\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1052, "%s: destroying leg for <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (leg->leg_url)->url_scheme ? (leg->
leg_url)->url_scheme : "", (leg->leg_url)->url_type !=
url_any && (leg->leg_url)->url_scheme &&
(leg->leg_url)->url_scheme[0] ? ":" : "", (leg->leg_url
)->url_root && ((leg->leg_url)->url_host || (
leg->leg_url)->url_user) ? "//" : "", (leg->leg_url)
->url_user ? (leg->leg_url)->url_user : "", (leg->
leg_url)->url_user && (leg->leg_url)->url_password
? ":" : "", (leg->leg_url)->url_user && (leg->
leg_url)->url_password ? (leg->leg_url)->url_password
: "", (leg->leg_url)->url_user && (leg->leg_url
)->url_host ? "@" : "", (leg->leg_url)->url_host ? (
leg->leg_url)->url_host : "", (leg->leg_url)->url_host
&& (leg->leg_url)->url_port ? ":" : "", (leg->
leg_url)->url_host && (leg->leg_url)->url_port
? (leg->leg_url)->url_port : "", (leg->leg_url)->
url_root && (leg->leg_url)->url_path ? "/" : ""
, (leg->leg_url)->url_path ? (leg->leg_url)->url_path
: "", (leg->leg_url)->url_params ? ";" : "", (leg->
leg_url)->url_params ? (leg->leg_url)->url_params : ""
, (leg->leg_url)->url_headers ? "?" : "", (leg->leg_url
)->url_headers ? (leg->leg_url)->url_headers : "", (
leg->leg_url)->url_fragment ? "#" : "", (leg->leg_url
)->url_fragment ? (leg->leg_url)->url_fragment : "")
) : (void)0)
1052 __func__, URL_PRINT_ARGS(leg->leg_url)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1052, "%s: destroying leg for <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (leg->leg_url)->url_scheme ? (leg->
leg_url)->url_scheme : "", (leg->leg_url)->url_type !=
url_any && (leg->leg_url)->url_scheme &&
(leg->leg_url)->url_scheme[0] ? ":" : "", (leg->leg_url
)->url_root && ((leg->leg_url)->url_host || (
leg->leg_url)->url_user) ? "//" : "", (leg->leg_url)
->url_user ? (leg->leg_url)->url_user : "", (leg->
leg_url)->url_user && (leg->leg_url)->url_password
? ":" : "", (leg->leg_url)->url_user && (leg->
leg_url)->url_password ? (leg->leg_url)->url_password
: "", (leg->leg_url)->url_user && (leg->leg_url
)->url_host ? "@" : "", (leg->leg_url)->url_host ? (
leg->leg_url)->url_host : "", (leg->leg_url)->url_host
&& (leg->leg_url)->url_port ? ":" : "", (leg->
leg_url)->url_host && (leg->leg_url)->url_port
? (leg->leg_url)->url_port : "", (leg->leg_url)->
url_root && (leg->leg_url)->url_path ? "/" : ""
, (leg->leg_url)->url_path ? (leg->leg_url)->url_path
: "", (leg->leg_url)->url_params ? ";" : "", (leg->
leg_url)->url_params ? (leg->leg_url)->url_params : ""
, (leg->leg_url)->url_headers ? "?" : "", (leg->leg_url
)->url_headers ? (leg->leg_url)->url_headers : "", (
leg->leg_url)->url_fragment ? "#" : "", (leg->leg_url
)->url_fragment ? (leg->leg_url)->url_fragment : "")
) : (void)0)
;
1053 leg_free(agent, leg);
1054 }
1055 }
1056
1057 if (agent->sa_default_leg)
1058 leg_free(agent, agent->sa_default_leg);
1059
1060 for (i = iht->iht_size; i-- > 0; )
1061 while (iht->iht_table[i]) {
1062 nta_incoming_t *irq = iht->iht_table[i];
1063
1064 if (!irq->irq_destroyed)
1065 SU_DEBUG_3(("%s: destroying %s server transaction from <"(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1068, "%s: destroying %s server transaction from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, irq->irq_rq->rq_method_name, (irq->
irq_from->a_url)->url_scheme ? (irq->irq_from->a_url
)->url_scheme : "", (irq->irq_from->a_url)->url_type
!= url_any && (irq->irq_from->a_url)->url_scheme
&& (irq->irq_from->a_url)->url_scheme[0] ? ":"
: "", (irq->irq_from->a_url)->url_root && (
(irq->irq_from->a_url)->url_host || (irq->irq_from
->a_url)->url_user) ? "//" : "", (irq->irq_from->
a_url)->url_user ? (irq->irq_from->a_url)->url_user
: "", (irq->irq_from->a_url)->url_user && (
irq->irq_from->a_url)->url_password ? ":" : "", (irq
->irq_from->a_url)->url_user && (irq->irq_from
->a_url)->url_password ? (irq->irq_from->a_url)->
url_password : "", (irq->irq_from->a_url)->url_user &&
(irq->irq_from->a_url)->url_host ? "@" : "", (irq->
irq_from->a_url)->url_host ? (irq->irq_from->a_url
)->url_host : "", (irq->irq_from->a_url)->url_host
&& (irq->irq_from->a_url)->url_port ? ":" :
"", (irq->irq_from->a_url)->url_host && (irq
->irq_from->a_url)->url_port ? (irq->irq_from->
a_url)->url_port : "", (irq->irq_from->a_url)->url_root
&& (irq->irq_from->a_url)->url_path ? "/" :
"", (irq->irq_from->a_url)->url_path ? (irq->irq_from
->a_url)->url_path : "", (irq->irq_from->a_url)->
url_params ? ";" : "", (irq->irq_from->a_url)->url_params
? (irq->irq_from->a_url)->url_params : "", (irq->
irq_from->a_url)->url_headers ? "?" : "", (irq->irq_from
->a_url)->url_headers ? (irq->irq_from->a_url)->
url_headers : "", (irq->irq_from->a_url)->url_fragment
? "#" : "", (irq->irq_from->a_url)->url_fragment ? (
irq->irq_from->a_url)->url_fragment : "")) : (void)0
)
1066 URL_PRINT_FORMAT ">\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1068, "%s: destroying %s server transaction from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, irq->irq_rq->rq_method_name, (irq->
irq_from->a_url)->url_scheme ? (irq->irq_from->a_url
)->url_scheme : "", (irq->irq_from->a_url)->url_type
!= url_any && (irq->irq_from->a_url)->url_scheme
&& (irq->irq_from->a_url)->url_scheme[0] ? ":"
: "", (irq->irq_from->a_url)->url_root && (
(irq->irq_from->a_url)->url_host || (irq->irq_from
->a_url)->url_user) ? "//" : "", (irq->irq_from->
a_url)->url_user ? (irq->irq_from->a_url)->url_user
: "", (irq->irq_from->a_url)->url_user && (
irq->irq_from->a_url)->url_password ? ":" : "", (irq
->irq_from->a_url)->url_user && (irq->irq_from
->a_url)->url_password ? (irq->irq_from->a_url)->
url_password : "", (irq->irq_from->a_url)->url_user &&
(irq->irq_from->a_url)->url_host ? "@" : "", (irq->
irq_from->a_url)->url_host ? (irq->irq_from->a_url
)->url_host : "", (irq->irq_from->a_url)->url_host
&& (irq->irq_from->a_url)->url_port ? ":" :
"", (irq->irq_from->a_url)->url_host && (irq
->irq_from->a_url)->url_port ? (irq->irq_from->
a_url)->url_port : "", (irq->irq_from->a_url)->url_root
&& (irq->irq_from->a_url)->url_path ? "/" :
"", (irq->irq_from->a_url)->url_path ? (irq->irq_from
->a_url)->url_path : "", (irq->irq_from->a_url)->
url_params ? ";" : "", (irq->irq_from->a_url)->url_params
? (irq->irq_from->a_url)->url_params : "", (irq->
irq_from->a_url)->url_headers ? "?" : "", (irq->irq_from
->a_url)->url_headers ? (irq->irq_from->a_url)->
url_headers : "", (irq->irq_from->a_url)->url_fragment
? "#" : "", (irq->irq_from->a_url)->url_fragment ? (
irq->irq_from->a_url)->url_fragment : "")) : (void)0
)
1067 __func__, irq->irq_rq->rq_method_name,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1068, "%s: destroying %s server transaction from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, irq->irq_rq->rq_method_name, (irq->
irq_from->a_url)->url_scheme ? (irq->irq_from->a_url
)->url_scheme : "", (irq->irq_from->a_url)->url_type
!= url_any && (irq->irq_from->a_url)->url_scheme
&& (irq->irq_from->a_url)->url_scheme[0] ? ":"
: "", (irq->irq_from->a_url)->url_root && (
(irq->irq_from->a_url)->url_host || (irq->irq_from
->a_url)->url_user) ? "//" : "", (irq->irq_from->
a_url)->url_user ? (irq->irq_from->a_url)->url_user
: "", (irq->irq_from->a_url)->url_user && (
irq->irq_from->a_url)->url_password ? ":" : "", (irq
->irq_from->a_url)->url_user && (irq->irq_from
->a_url)->url_password ? (irq->irq_from->a_url)->
url_password : "", (irq->irq_from->a_url)->url_user &&
(irq->irq_from->a_url)->url_host ? "@" : "", (irq->
irq_from->a_url)->url_host ? (irq->irq_from->a_url
)->url_host : "", (irq->irq_from->a_url)->url_host
&& (irq->irq_from->a_url)->url_port ? ":" :
"", (irq->irq_from->a_url)->url_host && (irq
->irq_from->a_url)->url_port ? (irq->irq_from->
a_url)->url_port : "", (irq->irq_from->a_url)->url_root
&& (irq->irq_from->a_url)->url_path ? "/" :
"", (irq->irq_from->a_url)->url_path ? (irq->irq_from
->a_url)->url_path : "", (irq->irq_from->a_url)->
url_params ? ";" : "", (irq->irq_from->a_url)->url_params
? (irq->irq_from->a_url)->url_params : "", (irq->
irq_from->a_url)->url_headers ? "?" : "", (irq->irq_from
->a_url)->url_headers ? (irq->irq_from->a_url)->
url_headers : "", (irq->irq_from->a_url)->url_fragment
? "#" : "", (irq->irq_from->a_url)->url_fragment ? (
irq->irq_from->a_url)->url_fragment : "")) : (void)0
)
1068 URL_PRINT_ARGS(irq->irq_from->a_url)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1068, "%s: destroying %s server transaction from <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, irq->irq_rq->rq_method_name, (irq->
irq_from->a_url)->url_scheme ? (irq->irq_from->a_url
)->url_scheme : "", (irq->irq_from->a_url)->url_type
!= url_any && (irq->irq_from->a_url)->url_scheme
&& (irq->irq_from->a_url)->url_scheme[0] ? ":"
: "", (irq->irq_from->a_url)->url_root && (
(irq->irq_from->a_url)->url_host || (irq->irq_from
->a_url)->url_user) ? "//" : "", (irq->irq_from->
a_url)->url_user ? (irq->irq_from->a_url)->url_user
: "", (irq->irq_from->a_url)->url_user && (
irq->irq_from->a_url)->url_password ? ":" : "", (irq
->irq_from->a_url)->url_user && (irq->irq_from
->a_url)->url_password ? (irq->irq_from->a_url)->
url_password : "", (irq->irq_from->a_url)->url_user &&
(irq->irq_from->a_url)->url_host ? "@" : "", (irq->
irq_from->a_url)->url_host ? (irq->irq_from->a_url
)->url_host : "", (irq->irq_from->a_url)->url_host
&& (irq->irq_from->a_url)->url_port ? ":" :
"", (irq->irq_from->a_url)->url_host && (irq
->irq_from->a_url)->url_port ? (irq->irq_from->
a_url)->url_port : "", (irq->irq_from->a_url)->url_root
&& (irq->irq_from->a_url)->url_path ? "/" :
"", (irq->irq_from->a_url)->url_path ? (irq->irq_from
->a_url)->url_path : "", (irq->irq_from->a_url)->
url_params ? ";" : "", (irq->irq_from->a_url)->url_params
? (irq->irq_from->a_url)->url_params : "", (irq->
irq_from->a_url)->url_headers ? "?" : "", (irq->irq_from
->a_url)->url_headers ? (irq->irq_from->a_url)->
url_headers : "", (irq->irq_from->a_url)->url_fragment
? "#" : "", (irq->irq_from->a_url)->url_fragment ? (
irq->irq_from->a_url)->url_fragment : "")) : (void)0
)
;
1069
1070 incoming_free(irq);
1071 }
1072
1073 for (i = oht->oht_size; i-- > 0;)
1074 while (oht->oht_table[i]) {
1075 nta_outgoing_t *orq = oht->oht_table[i];
1076
1077 if (!orq->orq_destroyed)
1078 SU_DEBUG_3(("%s: destroying %s%s client transaction to <"(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
1079 URL_PRINT_FORMAT ">\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
1080 __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
1081 (orq->orq_forking || orq->orq_forks) ? "forked " : "forking",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
1082 orq->orq_method_name,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
1083 URL_PRINT_ARGS(orq->orq_to->a_url)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 1083, "%s: destroying %s%s client transaction to <" "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
">\n", __func__, (orq->orq_forking || orq->orq_forks
) ? "forked " : "forking", orq->orq_method_name, (orq->
orq_to->a_url)->url_scheme ? (orq->orq_to->a_url)
->url_scheme : "", (orq->orq_to->a_url)->url_type
!= url_any && (orq->orq_to->a_url)->url_scheme
&& (orq->orq_to->a_url)->url_scheme[0] ? ":"
: "", (orq->orq_to->a_url)->url_root && ((orq
->orq_to->a_url)->url_host || (orq->orq_to->a_url
)->url_user) ? "//" : "", (orq->orq_to->a_url)->url_user
? (orq->orq_to->a_url)->url_user : "", (orq->orq_to
->a_url)->url_user && (orq->orq_to->a_url
)->url_password ? ":" : "", (orq->orq_to->a_url)->
url_user && (orq->orq_to->a_url)->url_password
? (orq->orq_to->a_url)->url_password : "", (orq->
orq_to->a_url)->url_user && (orq->orq_to->
a_url)->url_host ? "@" : "", (orq->orq_to->a_url)->
url_host ? (orq->orq_to->a_url)->url_host : "", (orq
->orq_to->a_url)->url_host && (orq->orq_to
->a_url)->url_port ? ":" : "", (orq->orq_to->a_url
)->url_host && (orq->orq_to->a_url)->url_port
? (orq->orq_to->a_url)->url_port : "", (orq->orq_to
->a_url)->url_root && (orq->orq_to->a_url
)->url_path ? "/" : "", (orq->orq_to->a_url)->url_path
? (orq->orq_to->a_url)->url_path : "", (orq->orq_to
->a_url)->url_params ? ";" : "", (orq->orq_to->a_url
)->url_params ? (orq->orq_to->a_url)->url_params :
"", (orq->orq_to->a_url)->url_headers ? "?" : "", (
orq->orq_to->a_url)->url_headers ? (orq->orq_to->
a_url)->url_headers : "", (orq->orq_to->a_url)->url_fragment
? "#" : "", (orq->orq_to->a_url)->url_fragment ? (orq
->orq_to->a_url)->url_fragment : "")) : (void)0)
;
1084
1085 orq->orq_forks = NULL((void*)0), orq->orq_forking = NULL((void*)0);
1086 outgoing_free(orq);
1087 }
1088
1089 su_timer_destroy(agent->sa_timer), agent->sa_timer = NULL((void*)0);
1090
1091# if HAVE_SOFIA_SRESOLV1
1092 sres_resolver_destroy(agent->sa_resolver), agent->sa_resolver = NULL((void*)0);
1093# endif
1094
1095 tport_destroy(agent->sa_tports), agent->sa_tports = NULL((void*)0);
1096
1097 agent_kill_terminator(agent);
1098
1099 su_home_unref(agent->sa_home);
1100 }
1101}
1102
1103void nta_agent_resolver_clean_cache(nta_agent_t *agent)
1104{
1105#if HAVE_SOFIA_SRESOLV1
1106 if (agent && agent->sa_resolver) {
1107 sres_resolver_clean_cache(agent->sa_resolver);
1108 }
1109#endif
1110}
1111
1112/** Return agent context. */
1113nta_agent_magic_t *nta_agent_magic(nta_agent_t const *agent)
1114{
1115 return agent ? agent->sa_magic : NULL((void*)0);
1116}
1117
1118/** Return @Contact header.
1119 *
1120 * Get a @Contact header, which can be used to reach @a agent.
1121 *
1122 * @param agent NTA agent object
1123 *
1124 * User agents can insert the @Contact header in the outgoing REGISTER,
1125 * INVITE, and ACK requests and replies to incoming INVITE and OPTIONS
1126 * transactions.
1127 *
1128 * Proxies can use the @Contact header to create appropriate @RecordRoute
1129 * headers:
1130 * @code
1131 * r_r = sip_record_route_create(msg_home(msg),
1132 * sip->sip_request->rq_url,
1133 * contact->m_url);
1134 * @endcode
1135 *
1136 * @return A sip_contact_t object corresponding to the @a agent.
1137 */
1138sip_contact_t *nta_agent_contact(nta_agent_t const *agent)
1139{
1140 return agent ? agent->sa_contact : NULL((void*)0);
1141}
1142
1143/** Return a list of @Via headers.
1144 *
1145 * Get @Via headers for all activated transport.
1146 *
1147 * @param agent NTA agent object
1148 *
1149 * @return A list of #sip_via_t objects used by the @a agent.
1150 */
1151sip_via_t *nta_agent_via(nta_agent_t const *agent)
1152{
1153 return agent ? agent->sa_vias : NULL((void*)0);
1154}
1155
1156/** Return a list of public (UPnP, STUN) @Via headers.
1157 *
1158 * Get public @Via headers for all activated transports.
1159 *
1160 * @param agent NTA agent object
1161 *
1162 * @return A list of #sip_via_t objects used by the @a agent.
1163 */
1164sip_via_t *nta_agent_public_via(nta_agent_t const *agent)
1165{
1166 return agent ? agent->sa_public_vias : NULL((void*)0);
1167}
1168
1169/** Match a @Via header @a v with @Via headers in @a agent.
1170 *
1171 */
1172static
1173sip_via_t *agent_has_via(nta_agent_t const *agent, sip_via_t const *via)
1174{
1175 sip_via_t const *v;
1176
1177 for (v = agent->sa_public_vias; v; v = v->v_next) {
1178 if (!su_casematch(via->v_host, v->v_host))
1179 continue;
1180 if (!su_strmatch(via->v_port, v->v_port))
1181 continue;
1182 if (!su_casematch(via->v_protocol, v->v_protocol))
1183 continue;
1184 return (sip_via_t *)v;
1185 }
1186
1187 for (v = agent->sa_vias; v; v = v->v_next) {
1188 if (!su_casematch(via->v_host, v->v_host))
1189 continue;
1190 if (!su_strmatch(via->v_port, v->v_port))
1191 continue;
1192 if (!su_casematch(via->v_protocol, v->v_protocol))
1193 continue;
1194 return (sip_via_t *)v;
1195 }
1196
1197 return NULL((void*)0);
1198}
1199
1200/** Return @UserAgent header.
1201 *
1202 * Get @UserAgent information with NTA version.
1203 *
1204 * @param agent NTA agent object (may be NULL)
1205 *
1206 * @return A string containing the @a agent version.
1207 */
1208char const *nta_agent_version(nta_agent_t const *agent)
1209{
1210 return "nta" "/" VERSION"1.13.15";
1211}
1212
1213/** Initialize default tag */
1214static int agent_tag_init(nta_agent_t *self)
1215{
1216 sip_contact_t *m = self->sa_contact;
1217 uint32_t hash = su_random();
1218
1219 if (m) {
1220 if (m->m_url->url_user)
1221 hash = 914715421U * hash + msg_hash_string(m->m_url->url_user);
1222 if (m->m_url->url_host)
1223 hash = 914715421U * hash + msg_hash_string(m->m_url->url_host);
1224 if (m->m_url->url_port)
1225 hash = 914715421U * hash + msg_hash_string(m->m_url->url_port);
1226 if (m->m_url->url_params)
1227 hash = 914715421U * hash + msg_hash_string(m->m_url->url_params);
1228 }
1229
1230 if (hash == 0)
1231 hash = 914715421U;
1232
1233 self->sa_branch = NTA_BRANCH_PRIME(uint64_t)(0xB9591D1C361C6521ULL) * (uint64_t)su_nanotime(NULL((void*)0));
1234 self->sa_branch *= hash;
1235
1236 self->sa_tags = NTA_TAG_PRIME(uint64_t)(0xB9591D1C361C6521ULL) * self->sa_branch;
1237
1238 return 0;
1239}
1240
1241/** Initialize agent timer. */
1242static
1243int agent_timer_init(nta_agent_t *agent)
1244{
1245 agent->sa_timer = su_timer_create(su_root_task(agent->sa_root),
1246 NTA_SIP_T1 / 8);
1247#if 0
1248 return su_timer_set(agent->sa_timer,
1249 agent_timer,
1250 agent);
1251#endif
1252 return -(agent->sa_timer == NULL((void*)0));
1253}
1254
1255/**
1256 * Agent timer routine.
1257 */
1258static
1259void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent)
1260{
1261 su_time_t stamp = su_now();
1262 uint32_t now = su_time_ms(stamp), next, latest;
1263
1264 now += now == 0;
1265
1266 agent->sa_next = 0;
1267
1268 agent->sa_in_timer = 1;
1269
1270
1271 _nta_outgoing_timer(agent);
1272 _nta_incoming_timer(agent);
1273
1274 agent->sa_in_timer = 0;
1275
1276 /* Calculate next timeout */
1277 next = latest = now + NTA_TIME_MAX + 1;
1278
1279#define NEXT_TIMEOUT(next, p, f, now) \
1280 (void)(p && (int32_t)(p->f - (next)) < 0 && \
1281 ((next) = ((int32_t)(p->f - (now)) > 0 ? p->f : (now))))
1282
1283 NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now);
1284 NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now);
1285 NEXT_TIMEOUT(next, agent->sa_out.completed->q_head, orq_timeout, now);
1286 NEXT_TIMEOUT(next, agent->sa_out.inv_calling->q_head, orq_timeout, now);
1287 if (agent->sa_out.inv_proceeding->q_timeout)
1288 NEXT_TIMEOUT(next, agent->sa_out.inv_proceeding->q_head, orq_timeout, now);
1289 NEXT_TIMEOUT(next, agent->sa_out.trying->q_head, orq_timeout, now);
1290
1291 NEXT_TIMEOUT(next, agent->sa_in.preliminary->q_head, irq_timeout, now);
1292 NEXT_TIMEOUT(next, agent->sa_in.inv_completed->q_head, irq_timeout, now);
1293 NEXT_TIMEOUT(next, agent->sa_in.inv_confirmed->q_head, irq_timeout, now);
1294 NEXT_TIMEOUT(next, agent->sa_in.completed->q_head, irq_timeout, now);
1295 NEXT_TIMEOUT(next, agent->sa_in.re_list, irq_retry, now);
1296
1297 if (agent->sa_next)
1298 NEXT_TIMEOUT(next, agent, sa_next, now);
1299
1300#undef NEXT_TIMEOUT
1301
1302 if (next == latest) {
1303 /* Do not set timer? */
1304 /* check it there are still things queued, if there are, that means everything scheduled is > 15 days in the future */
1305 /* in this case, we had a large time shift, we should schedule for 15 days in the future (which is probably still before now) */
1306 /* and this should sort itself out on the next run through */
1307 if ( !agent->sa_out.completed->q_head && !agent->sa_out.trying->q_head && !agent->sa_out.inv_calling->q_head &&
1308 !agent->sa_out.re_list && !agent->sa_in.inv_confirmed->q_head && !agent->sa_in.preliminary->q_head &&
1309 !agent->sa_in.completed->q_head && !agent->sa_in.inv_completed->q_head && !agent->sa_in.re_list ) {
1310 SU_DEBUG_9(("nta: timer not set\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1310, "nta: timer not set\n" "%s", "")) : (void)0)
;
1311 return;
1312 }
1313 }
1314
1315 if (next == now) if (++next == 0) ++next;
1316
1317 SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set next", (long)(next - now)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1317, "nta: timer %s to %ld ms\n", "set next", (long)(next -
now))) : (void)0)
;
1318
1319 agent->sa_next = next;
1320
1321 su_timer_set_at(timer, agent_timer, agent, su_time_add(stamp, next - now));
1322}
1323
1324/** Add uin32_t milliseconds to the time. */
1325static su_time_t add_milliseconds(su_time_t t0, uint32_t ms)
1326{
1327 unsigned long sec = ms / 1000, usec = (ms % 1000) * 1000;
1328
1329 t0.tv_usec += usec;
1330 t0.tv_sec += sec;
1331
1332 if (t0.tv_usec >= 1000000) {
1333 t0.tv_sec += 1;
1334 t0.tv_usec -= 1000000;
1335 }
1336
1337 return t0;
1338}
1339
1340/** Calculate nonzero value for timeout.
1341 *
1342 * Sets or adjusts agent timer when needed.
1343 *
1344 * @retval 0 if offset is 0
1345 * @retval timeout (millisecond counter) otherwise
1346 */
1347static
1348uint32_t set_timeout(nta_agent_t *agent, uint32_t offset)
1349{
1350 su_time_t now;
1351 uint32_t next, ms;
1352
1353 if (offset == 0)
1354 return 0;
1355
1356 now = su_now();
1357 ms = su_time_ms(now);
1358
1359 next = ms + offset;
1360
1361 if (next == 0) next = 1;
1362
1363 if (agent->sa_in_timer) /* Currently executing timer */
1364 return next;
1365
1366 if (agent->sa_next == 0 || (int32_t)(agent->sa_next - next - 5L) > 0) {
1367 /* Set timer */
1368 if (agent->sa_next)
1369 SU_DEBUG_9(("nta: timer %s to %ld ms\n", "shortened", (long)offset))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1369, "nta: timer %s to %ld ms\n", "shortened", (long)offset
)) : (void)0)
;
1370 else
1371 SU_DEBUG_9(("nta: timer %s to %ld ms\n", "set", (long)offset))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 1371, "nta: timer %s to %ld ms\n", "set", (long)offset)) : (
void)0)
;
1372
1373 su_timer_set_at(agent->sa_timer, agent_timer, agent,
1374 add_milliseconds(now, offset));
1375 agent->sa_next = next;
1376 }
1377
1378 return next;
1379}
1380
1381
1382/** Return current timeval. */
1383static
1384su_time_t agent_now(nta_agent_t const *agent)
1385{
1386 return su_now();
1387}
1388
1389
1390/** Launch transaction terminator task */
1391static
1392int agent_launch_terminator(nta_agent_t *agent)
1393{
1394#ifdef TPTAG_THRPSIZE
1395 if (agent->sa_tport_threadpool) {
1396 su_home_threadsafe(agent->sa_home);
1397 return su_clone_start(agent->sa_root,
1398 agent->sa_terminator,
1399 NULL((void*)0),
1400 NULL((void*)0),
1401 NULL((void*)0));
1402 }
1403#endif
1404 return -1;
1405}
1406
1407/** Kill transaction terminator task */
1408static
1409void agent_kill_terminator(nta_agent_t *agent)
1410{
1411 su_clone_wait(agent->sa_root, agent->sa_terminator);
1412}
1413
1414
1415/**Set NTA Parameters.
1416 *
1417 * The nta_agent_set_params() function sets the stack parameters. The
1418 * parameters determine the way NTA handles the retransmissions, how long
1419 * NTA keeps transactions alive, does NTA apply proxy or user-agent logic to
1420 * INVITE transactions, or how the @Via headers are generated.
1421 *
1422 * @note
1423 * Setting the parameters NTATAG_MAXSIZE(), NTATAG_UDP_MTU(), NTATAG_MAX_PROCEEDING(),
1424 * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4() to
1425 * 0 selects the default value.
1426 *
1427 * @TAGS
1428 * NTATAG_ALIASES(),
1429 * NTATAG_BAD_REQ_MASK(), NTATAG_BAD_RESP_MASK(), NTATAG_BLACKLIST(),
1430 * NTATAG_CANCEL_2543(), NTATAG_CANCEL_487(), NTATAG_CLIENT_RPORT(),
1431 * NTATAG_DEBUG_DROP_PROB(), NTATAG_DEFAULT_PROXY(),
1432 * NTATAG_EXTRA_100(), NTATAG_GRAYLIST(),
1433 * NTATAG_MAXSIZE(), NTATAG_MAX_FORWARDS(), NTATAG_MERGE_482(), NTATAG_MCLASS()
1434 * NTATAG_PASS_100(), NTATAG_PASS_408(), NTATAG_PRELOAD(), NTATAG_PROGRESS(),
1435 * NTATAG_REL100(),
1436 * NTATAG_SERVER_RPORT(),
1437 * NTATAG_SIPFLAGS(),
1438 * NTATAG_SIP_T1X64(), NTATAG_SIP_T1(), NTATAG_SIP_T2(), NTATAG_SIP_T4(),
1439 * NTATAG_STATELESS(),
1440 * NTATAG_TAG_3261(), NTATAG_TCP_RPORT(), NTATAG_TIMEOUT_408(),
1441 * NTATAG_TLS_RPORT(), NTATAG_TLS_ORQ_CONNECT_TIMEOUT(),
1442 * NTATAG_TIMER_C(), NTATAG_MAX_PROCEEDING(),
1443 * NTATAG_UA(), NTATAG_UDP_MTU(), NTATAG_USER_VIA(),
1444 * NTATAG_USE_NAPTR(), NTATAG_USE_SRV() and NTATAG_USE_TIMESTAMP().
1445 *
1446 * @note The value from following tags are stored, but they currently do nothing:
1447 * NTATAG_SIGCOMP_ALGORITHM(), NTATAG_SIGCOMP_OPTIONS(), NTATAG_SMIME()
1448 */
1449int nta_agent_set_params(nta_agent_t *agent,
1450 tag_type_t tag, tag_value_t value, ...)
1451{
1452 int retval;
1453
1454 if (agent) {
1455 ta_list ta;
1456 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1457 retval = agent_set_params(agent, ta_args(ta)(ta).tl);
1458 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1459 } else {
1460 su_seterrno(EINVAL22);
1461 retval = -1;
1462 }
1463
1464 return retval;
1465}
1466
1467/** Internal function for setting tags */
1468static
1469int agent_set_params(nta_agent_t *agent, tagi_t *tags)
1470{
1471 int n, nC, m;
1472 unsigned bad_req_mask = agent->sa_bad_req_mask;
1473 unsigned bad_resp_mask = agent->sa_bad_resp_mask;
1474 usize_t maxsize = agent->sa_maxsize;
1475 usize_t max_proceeding = agent->sa_max_proceeding;
1476 usize_t max_recv_requests_per_second = agent->sa_max_recv_requests_per_second;
1477 unsigned max_forwards = agent->sa_max_forwards->mf_count;
1478 unsigned udp_mtu = agent->sa_udp_mtu;
1479 unsigned sip_t1 = agent->sa_t1;
1480 unsigned sip_t2 = agent->sa_t2;
1481 unsigned sip_t4 = agent->sa_t4;
1482 unsigned sip_t1x64 = agent->sa_t1x64;
1483 unsigned tls_orq_connect_timeout = agent->sa_tls_orq_connect_timeout;
1484 unsigned timer_c = agent->sa_timer_c;
1485 unsigned timer_d = 32000;
1486 unsigned graylist = agent->sa_graylist;
1487 unsigned blacklist = agent->sa_blacklist;
1488 int ua = agent->sa_is_a_uas;
1489 unsigned progress = agent->sa_progress;
1490 int stateless = agent->sa_is_stateless;
1491 unsigned drop_prob = agent->sa_drop_prob;
1492 int user_via = agent->sa_user_via;
1493 int extra_100 = agent->sa_extra_100;
1494 int pass_100 = agent->sa_pass_100;
1495 int timeout_408 = agent->sa_timeout_408;
1496 int pass_408 = agent->sa_pass_408;
1497 int merge_482 = agent->sa_merge_482;
1498 int cancel_2543 = agent->sa_cancel_2543;
1499 int cancel_487 = agent->sa_cancel_487;
1500 int invite_100rel = agent->sa_invite_100rel;
1501 int use_timestamp = agent->sa_timestamp;
1502 int use_naptr = agent->sa_use_naptr;
1503 int use_srv = agent->sa_use_srv;
1504 int srv_503 = agent->sa_srv_503;
1505 void *smime = agent->sa_smime;
1506 uint32_t flags = agent->sa_flags;
1507 int rport = agent->sa_rport;
1508 int server_rport = agent->sa_server_rport;
1509 int tcp_rport = agent->sa_tcp_rport;
1510 int tls_rport = agent->sa_tls_rport;
1511 unsigned preload = agent->sa_preload;
1512 unsigned threadpool = agent->sa_tport_threadpool;
1513 char const *sigcomp = agent->sa_sigcomp_options;
1514 char const *algorithm = NONE((void *)-1);
1515 msg_mclass_t const *mclass = NONE((void *)-1);
1516 sip_contact_t const *aliases = NONE((void *)-1);
1517 url_string_t const *proxy = NONE((void *)-1);
1518 tport_t *tport;
1519
1520 su_home_t *home = agent->sa_home;
1521
1522 n = tl_gets(tags,
1523 NTATAG_ALIASES_REF(aliases)ntatag_aliases_ref, siptag_contact_vr(&(aliases)),
1524 NTATAG_BAD_REQ_MASK_REF(bad_req_mask)ntatag_bad_req_mask_ref, tag_uint_vr(&(bad_req_mask)),
1525 NTATAG_BAD_RESP_MASK_REF(bad_resp_mask)ntatag_bad_resp_mask_ref, tag_uint_vr(&(bad_resp_mask)),
1526 NTATAG_BLACKLIST_REF(blacklist)ntatag_blacklist_ref, tag_uint_vr(&(blacklist)),
1527 NTATAG_CANCEL_2543_REF(cancel_2543)ntatag_cancel_2543_ref, tag_bool_vr(&(cancel_2543)),
1528 NTATAG_CANCEL_487_REF(cancel_487)ntatag_cancel_487_ref, tag_bool_vr(&(cancel_487)),
1529 NTATAG_DEBUG_DROP_PROB_REF(drop_prob)ntatag_debug_drop_prob_ref, tag_uint_vr(&(drop_prob)),
1530 NTATAG_DEFAULT_PROXY_REF(proxy)ntatag_default_proxy_ref, urltag_url_vr(&(proxy)),
1531 NTATAG_EXTRA_100_REF(extra_100)ntatag_extra_100_ref, tag_bool_vr(&(extra_100)),
1532 NTATAG_GRAYLIST_REF(graylist)ntatag_graylist_ref, tag_uint_vr(&(graylist)),
1533 NTATAG_MAXSIZE_REF(maxsize)ntatag_maxsize_ref, tag_usize_vr(&(maxsize)),
1534 NTATAG_MAX_PROCEEDING_REF(max_proceeding)ntatag_max_proceeding_ref, tag_usize_vr(&(max_proceeding)
)
,
1535 NTATAG_MAX_RECV_REQUESTS_PER_SECOND_REF(max_recv_requests_per_second)ntatag_max_recv_requests_per_second_ref, tag_usize_vr(&(max_recv_requests_per_second
))
,
1536 NTATAG_MAX_FORWARDS_REF(max_forwards)ntatag_max_forwards_ref, tag_uint_vr(&(max_forwards)),
1537 NTATAG_MCLASS_REF(mclass)ntatag_mclass_ref, tag_cptr_vr(&(mclass), (mclass)),
1538 NTATAG_MERGE_482_REF(merge_482)ntatag_merge_482_ref, tag_bool_vr(&(merge_482)),
1539 NTATAG_PASS_100_REF(pass_100)ntatag_pass_100_ref, tag_bool_vr(&(pass_100)),
1540 NTATAG_PASS_408_REF(pass_408)ntatag_pass_408_ref, tag_bool_vr(&(pass_408)),
1541 NTATAG_PRELOAD_REF(preload)ntatag_preload_ref, tag_uint_vr(&(preload)),
1542 NTATAG_PROGRESS_REF(progress)ntatag_progress_ref, tag_uint_vr(&(progress)),
1543 NTATAG_REL100_REF(invite_100rel)ntatag_rel100_ref, tag_bool_vr(&(invite_100rel)),
1544 NTATAG_RPORT_REF(rport)ntatag_client_rport_ref, tag_bool_vr(&(rport)),
1545 NTATAG_SERVER_RPORT_REF(server_rport)ntatag_server_rport_ref, tag_int_vr(&(server_rport)),
1546 NTATAG_SIGCOMP_ALGORITHM_REF(algorithm)ntatag_sigcomp_algorithm_ref, tag_str_vr(&(algorithm)),
1547 NTATAG_SIGCOMP_OPTIONS_REF(sigcomp)ntatag_sigcomp_options_ref, tag_str_vr(&(sigcomp)),
1548 NTATAG_SIPFLAGS_REF(flags)ntatag_sipflags_ref, tag_uint_vr(&(flags)),
1549 NTATAG_SIP_T1X64_REF(sip_t1x64)ntatag_sip_t1x64_ref, tag_uint_vr(&(sip_t1x64)),
1550 NTATAG_SIP_T1_REF(sip_t1)ntatag_sip_t1_ref, tag_uint_vr(&(sip_t1)),
1551 NTATAG_SIP_T2_REF(sip_t2)ntatag_sip_t2_ref, tag_uint_vr(&(sip_t2)),
1552 NTATAG_SIP_T4_REF(sip_t4)ntatag_sip_t4_ref, tag_uint_vr(&(sip_t4)),
1553#if HAVE_SOFIA_SMIME0
1554 NTATAG_SMIME_REF(smime)ntatag_smime_ref, tag_ptr_vr(&(smime), (smime)),
1555#endif
1556 NTATAG_STATELESS_REF(stateless)ntatag_stateless_ref, tag_bool_vr(&(stateless)),
1557 NTATAG_TCP_RPORT_REF(tcp_rport)ntatag_tcp_rport_ref, tag_bool_vr(&(tcp_rport)),
1558 NTATAG_TLS_RPORT_REF(tls_rport)ntatag_tls_rport_ref, tag_bool_vr(&(tls_rport)),
1559 NTATAG_TLS_ORQ_CONNECT_TIMEOUT_REF(tls_orq_connect_timeout)ntatag_tls_orq_connect_timeout_ref, tag_uint_vr(&(tls_orq_connect_timeout
))
,
1560 NTATAG_TIMEOUT_408_REF(timeout_408)ntatag_timeout_408_ref, tag_bool_vr(&(timeout_408)),
1561 NTATAG_UA_REF(ua)ntatag_ua_ref, tag_bool_vr(&(ua)),
1562 NTATAG_UDP_MTU_REF(udp_mtu)ntatag_udp_mtu_ref, tag_uint_vr(&(udp_mtu)),
1563 NTATAG_USER_VIA_REF(user_via)ntatag_user_via_ref, tag_bool_vr(&(user_via)),
1564 NTATAG_USE_NAPTR_REF(use_naptr)ntatag_use_naptr_ref, tag_bool_vr(&(use_naptr)),
1565 NTATAG_USE_SRV_REF(use_srv)ntatag_use_srv_ref, tag_bool_vr(&(use_srv)),
1566 NTATAG_USE_TIMESTAMP_REF(use_timestamp)ntatag_use_timestamp_ref, tag_bool_vr(&(use_timestamp)),
1567#ifdef TPTAG_THRPSIZE
1568 /* If threadpool is enabled, start a separate "reaper thread" */
1569 TPTAG_THRPSIZE_REF(threadpool)tptag_thrpsize_ref, tag_uint_vr(&(threadpool)),
1570#endif
1571 NTATAG_SRV_503_REF(srv_503)ntatag_srv_503_ref, tag_bool_vr(&(srv_503)),
1572 TAG_END()(tag_type_t)0, (tag_value_t)0);
1573 nC = tl_gets(tags,
1574 NTATAG_TIMER_C_REF(timer_c)ntatag_timer_c_ref, tag_uint_vr(&(timer_c)),
1575 TAG_END()(tag_type_t)0, (tag_value_t)0);
1576 n += nC;
1577
1578 if (mclass != NONE((void *)-1))
1579 agent->sa_mclass = mclass ? mclass : sip_default_mclass();
1580
1581 m = 0;
1582 for (tport = agent->sa_tports; tport; tport = tport_next(tport)) {
1583 int m0 = tport_set_params(tport, TAG_NEXT(tags)tag_next, (tag_value_t)(tags));
1584 if (m0 < 0)
1585 return m0;
1586 if (m0 > m)
1587 m = m0;
1588 }
1589
1590 n += m;
1591
1592 if (aliases != NONE((void *)-1)) {
1593 sip_contact_t const *m, *m_next;
1594
1595 m = agent->sa_aliases;
1596 agent->sa_aliases = sip_contact_dup(home, aliases);
1597
1598 for (; m; m = m_next) { /* Free old aliases */
1599 m_next = m->m_next;
1600 su_free(home, (void *)m);
1601 }
1602 }
1603
1604 if (proxy != NONE((void *)-1)) {
1605 url_t *dp = url_hdup(home, proxy->us_url);
1606
1607 url_sanitize(dp);
1608
1609 if (dp == NULL((void*)0) || dp->url_type == url_sip || dp->url_type == url_sips || dp->url_type == url_urn) {
1610 if (agent->sa_default_proxy)
1611 su_free(home, agent->sa_default_proxy);
1612 agent->sa_default_proxy = dp;
1613 }
1614 else
1615 n = -1;
1616 }
1617
1618 if (algorithm != NONE((void *)-1))
1619 agent->sa_algorithm = su_strdup(home, algorithm);
1620
1621 if (!su_strmatch(sigcomp, agent->sa_sigcomp_options)) {
1622 msg_param_t const *l = NULL((void*)0);
1623 char *s = su_strdup(home, sigcomp);
1624 char *s1 = su_strdup(home, s), *s2 = s1;
1625
1626 if (s && s2 && msg_avlist_d(home, &s2, &l) == 0 && *s2 == '\0') {
1627 su_free(home, (void *)agent->sa_sigcomp_options);
1628 su_free(home, (void *)agent->sa_sigcomp_option_list);
1629 agent->sa_sigcomp_options = s;
1630 agent->sa_sigcomp_option_free = s1;
1631 agent->sa_sigcomp_option_list = l;
1632 } else {
1633 su_free(home, s);
1634 su_free(home, s1);
1635 su_free(home, (void *)l);
1636 n = -1;
1637 }
1638 }
1639
1640 if (maxsize == 0) maxsize = 2 * 1024 * 1024;
1641 if (maxsize > UINT32_MAX(4294967295U)) maxsize = UINT32_MAX(4294967295U);
1642 agent->sa_maxsize = maxsize;
1643
1644 if (max_proceeding == 0) max_proceeding = USIZE_MAX(2147483647 *2U +1U);
1645 agent->sa_max_proceeding = max_proceeding;
1646
1647 agent->sa_max_recv_requests_per_second = max_recv_requests_per_second;
1648
1649 if (max_forwards == 0) max_forwards = 70; /* Default value */
1650 agent->sa_max_forwards->mf_count = max_forwards;
1651
1652 if (udp_mtu == 0) udp_mtu = 1300;
1653 if (udp_mtu > 65535) udp_mtu = 65535;
1654 if (agent->sa_udp_mtu != udp_mtu) {
1655 agent->sa_udp_mtu = udp_mtu;
1656 agent_set_udp_params(agent, udp_mtu);
1657 }
1658
1659 if (sip_t1 == 0) sip_t1 = NTA_SIP_T1;
1660 if (sip_t1 > NTA_TIME_MAX) sip_t1 = NTA_TIME_MAX;
1661 agent->sa_t1 = sip_t1;
1662
1663 if (sip_t2 == 0) sip_t2 = NTA_SIP_T2;
1664 if (sip_t2 > NTA_TIME_MAX) sip_t2 = NTA_TIME_MAX;
1665 agent->sa_t2 = sip_t2;
1666
1667 if (sip_t4 == 0) sip_t4 = NTA_SIP_T4;
1668 if (sip_t4 > NTA_TIME_MAX) sip_t4 = NTA_TIME_MAX;
1669 if (agent->sa_t4 != sip_t4) {
1670 incoming_queue_adjust(agent, agent->sa_in.inv_confirmed, sip_t4);
1671 outgoing_queue_adjust(agent, agent->sa_out.completed, sip_t4);
1672 }
1673 agent->sa_t4 = sip_t4;
1674
1675 if (sip_t1x64 == 0) sip_t1x64 = NTA_SIP_T1 * 64;
1676 if (sip_t1x64 > NTA_TIME_MAX) sip_t1x64 = NTA_TIME_MAX;
1677 if (agent->sa_t1x64 != sip_t1x64) {
1678 incoming_queue_adjust(agent, agent->sa_in.preliminary, sip_t1x64);
1679 incoming_queue_adjust(agent, agent->sa_in.completed, sip_t1x64);
1680 incoming_queue_adjust(agent, agent->sa_in.inv_completed, sip_t1x64);
1681 outgoing_queue_adjust(agent, agent->sa_out.trying, sip_t1x64);
1682 outgoing_queue_adjust(agent, agent->sa_out.inv_calling, sip_t1x64);
1683 }
1684 agent->sa_t1x64 = sip_t1x64;
1685 if (nC == 1) {
1686 agent->sa_use_timer_c = 1;
1687 if (timer_c == 0)
1688 timer_c = 185 * 1000;
1689 agent->sa_timer_c = timer_c;
1690 outgoing_queue_adjust(agent, agent->sa_out.inv_proceeding, timer_c);
1691 }
1692 if (timer_d < sip_t1x64)
1693 timer_d = sip_t1x64;
1694 outgoing_queue_adjust(agent, agent->sa_out.inv_completed, timer_d);
1695
1696 if (tls_orq_connect_timeout > NTA_TIME_MAX) tls_orq_connect_timeout = NTA_TIME_MAX;
1697 agent->sa_tls_orq_connect_timeout = tls_orq_connect_timeout;
1698
1699 if (graylist > 24 * 60 * 60)
1700 graylist = 24 * 60 * 60;
1701 agent->sa_graylist = graylist;
1702
1703 if (blacklist > 24 * 60 * 60)
1704 blacklist = 24 * 60 * 60;
1705 agent->sa_blacklist = blacklist;
1706
1707 if (progress == 0)
1708 progress = 60 * 1000;
1709 agent->sa_progress = progress;
1710
1711 if (server_rport > 3)
1712 server_rport = 1;
1713 else if (server_rport < 0)
1714 server_rport = 1;
1715 agent->sa_server_rport = server_rport;
1716
1717 agent->sa_bad_req_mask = bad_req_mask;
1718 agent->sa_bad_resp_mask = bad_resp_mask;
1719
1720 agent->sa_is_a_uas = ua != 0;
1721 agent->sa_is_stateless = stateless != 0;
1722 agent->sa_drop_prob = drop_prob < 1000 ? drop_prob : 1000;
1723 agent->sa_user_via = user_via != 0;
1724 agent->sa_extra_100 = extra_100 != 0;
1725 agent->sa_pass_100 = pass_100 != 0;
1726 agent->sa_timeout_408 = timeout_408 != 0;
1727 agent->sa_pass_408 = pass_408 != 0;
1728 agent->sa_merge_482 = merge_482 != 0;
1729 agent->sa_cancel_2543 = cancel_2543 != 0;
1730 agent->sa_cancel_487 = cancel_487 != 0;
1731 agent->sa_invite_100rel = invite_100rel != 0;
1732 agent->sa_timestamp = use_timestamp != 0;
1733 agent->sa_use_naptr = use_naptr != 0;
1734 agent->sa_use_srv = use_srv != 0;
1735 agent->sa_srv_503 = srv_503 != 0;
1736 agent->sa_smime = smime;
1737 agent->sa_flags = flags & MSG_FLG_USERMASK;
1738 agent->sa_rport = rport != 0;
1739 agent->sa_tcp_rport = tcp_rport != 0;
1740 agent->sa_tls_rport = tls_rport != 0;
1741 agent->sa_preload = preload;
1742 agent->sa_tport_threadpool = threadpool;
1743
1744 return n;
1745}
1746
1747static
1748void agent_set_udp_params(nta_agent_t *self, usize_t udp_mtu)
1749{
1750 tport_t *tp;
1751
1752 /* Set via fields for the tports */
1753 for (tp = tport_primaries(self->sa_tports); tp; tp = tport_next(tp)) {
1754 if (tport_is_udp(tp))
1755 tport_set_params(tp,
1756 TPTAG_TIMEOUT(2 * self->sa_t1x64)tptag_timeout, tag_uint_v((2 * self->sa_t1x64)),
1757 TPTAG_MTU(udp_mtu)tptag_mtu, tag_usize_v((udp_mtu)),
1758 TAG_END()(tag_type_t)0, (tag_value_t)0);
1759 }
1760}
1761
1762/**Get NTA Parameters.
1763 *
1764 * The nta_agent_get_params() function retrieves the stack parameters. The
1765 * parameters determine the way NTA handles the retransmissions, how long
1766 * NTA keeps transactions alive, does NTA apply proxy or user-agent logic to
1767 * INVITE transactions, or how the @Via headers are generated.
1768 *
1769 * @TAGS
1770 * NTATAG_ALIASES_REF(), NTATAG_BLACKLIST_REF(),
1771 * NTATAG_CANCEL_2543_REF(), NTATAG_CANCEL_487_REF(),
1772 * NTATAG_CLIENT_RPORT_REF(), NTATAG_CONTACT_REF(),
1773 * NTATAG_DEBUG_DROP_PROB_REF(), NTATAG_DEFAULT_PROXY_REF(),
1774 * NTATAG_EXTRA_100_REF(), NTATAG_GRAYLIST_REF(),
1775 * NTATAG_MAXSIZE_REF(), NTATAG_MAX_FORWARDS_REF(), NTATAG_MCLASS_REF(),
1776 * NTATAG_MERGE_482_REF(), NTATAG_MAX_PROCEEDING_REF(),
1777 * NTATAG_PASS_100_REF(), NTATAG_PASS_408_REF(), NTATAG_PRELOAD_REF(),
1778 * NTATAG_PROGRESS_REF(),
1779 * NTATAG_REL100_REF(),
1780 * NTATAG_SERVER_RPORT_REF(),
1781 * NTATAG_SIGCOMP_ALGORITHM_REF(), NTATAG_SIGCOMP_OPTIONS_REF(),
1782 * NTATAG_SIPFLAGS_REF(),
1783 * NTATAG_SIP_T1_REF(), NTATAG_SIP_T1X64_REF(), NTATAG_SIP_T2_REF(),
1784 * NTATAG_SIP_T4_REF(), NTATAG_SMIME_REF(), NTATAG_STATELESS_REF(),
1785 * NTATAG_TAG_3261_REF(), NTATAG_TIMEOUT_408_REF(), NTATAG_TIMER_C_REF(),
1786 * NTATAG_UA_REF(), NTATAG_UDP_MTU_REF(), NTATAG_USER_VIA_REF(),
1787 * NTATAG_USE_NAPTR_REF(), NTATAG_USE_SRV_REF(),
1788 * and NTATAG_USE_TIMESTAMP_REF().
1789 *
1790 */
1791int nta_agent_get_params(nta_agent_t *agent,
1792 tag_type_t tag, tag_value_t value, ...)
1793{
1794 int n;
1795 ta_list ta;
1796
1797 if (agent) {
1798 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1799 n = agent_get_params(agent, ta_args(ta)(ta).tl);
1800 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1801 return n;
1802 }
1803
1804 su_seterrno(EINVAL22);
1805 return -1;
1806}
1807
1808/** Get NTA parameters */
1809static
1810int agent_get_params(nta_agent_t *agent, tagi_t *tags)
1811{
1812 return
1813 tl_tgets(tags,
1814 NTATAG_ALIASES(agent->sa_aliases)ntatag_aliases, siptag_contact_v((agent->sa_aliases)),
1815 NTATAG_BLACKLIST(agent->sa_blacklist)ntatag_blacklist, tag_uint_v((agent->sa_blacklist)),
1816 NTATAG_CANCEL_2543(agent->sa_cancel_2543)ntatag_cancel_2543, tag_bool_v((agent->sa_cancel_2543)),
1817 NTATAG_CANCEL_487(agent->sa_cancel_487)ntatag_cancel_487, tag_bool_v((agent->sa_cancel_487)),
1818 NTATAG_CLIENT_RPORT(agent->sa_rport)ntatag_client_rport, tag_bool_v((agent->sa_rport)),
1819 NTATAG_CONTACT(agent->sa_contact)ntatag_contact, siptag_contact_v((agent->sa_contact)),
1820 NTATAG_DEBUG_DROP_PROB(agent->sa_drop_prob)ntatag_debug_drop_prob, tag_uint_v((agent->sa_drop_prob)),
1821 NTATAG_DEFAULT_PROXY(agent->sa_default_proxy)ntatag_default_proxy, urltag_url_v((agent->sa_default_proxy
))
,
1822 NTATAG_EXTRA_100(agent->sa_extra_100)ntatag_extra_100, tag_bool_v((agent->sa_extra_100)),
1823 NTATAG_GRAYLIST(agent->sa_graylist)ntatag_graylist, tag_uint_v((agent->sa_graylist)),
1824 NTATAG_MAXSIZE(agent->sa_maxsize)ntatag_maxsize, tag_usize_v((agent->sa_maxsize)),
1825 NTATAG_MAX_PROCEEDING(agent->sa_max_proceeding)ntatag_max_proceeding, tag_usize_v((agent->sa_max_proceeding
))
,
1826 NTATAG_MAX_RECV_REQUESTS_PER_SECOND(agent->sa_max_recv_requests_per_second)ntatag_max_recv_requests_per_second, tag_usize_v((agent->sa_max_recv_requests_per_second
))
,
1827 NTATAG_MAX_FORWARDS(agent->sa_max_forwards->mf_count)ntatag_max_forwards, tag_uint_v((agent->sa_max_forwards->
mf_count))
,
1828 NTATAG_MCLASS(agent->sa_mclass)ntatag_mclass, tag_cptr_v((agent->sa_mclass)),
1829 NTATAG_MERGE_482(agent->sa_merge_482)ntatag_merge_482, tag_bool_v((agent->sa_merge_482)),
1830 NTATAG_PASS_100(agent->sa_pass_100)ntatag_pass_100, tag_bool_v((agent->sa_pass_100)),
1831 NTATAG_PASS_408(agent->sa_pass_408)ntatag_pass_408, tag_bool_v((agent->sa_pass_408)),
1832 NTATAG_PRELOAD(agent->sa_preload)ntatag_preload, tag_uint_v((agent->sa_preload)),
1833 NTATAG_PROGRESS(agent->sa_progress)ntatag_progress, tag_uint_v((agent->sa_progress)),
1834 NTATAG_REL100(agent->sa_invite_100rel)ntatag_rel100, tag_bool_v((agent->sa_invite_100rel)),
1835 NTATAG_SERVER_RPORT((int)(agent->sa_server_rport))ntatag_server_rport, tag_int_v(((int)(agent->sa_server_rport
)))
,
1836 NTATAG_SIGCOMP_ALGORITHM(agent->sa_algorithm)ntatag_sigcomp_algorithm, tag_str_v((agent->sa_algorithm)),
1837 NTATAG_SIGCOMP_OPTIONS(agent->sa_sigcomp_options ?ntatag_sigcomp_options, tag_str_v((agent->sa_sigcomp_options
? agent->sa_sigcomp_options : "sip"))
1838 agent->sa_sigcomp_options :ntatag_sigcomp_options, tag_str_v((agent->sa_sigcomp_options
? agent->sa_sigcomp_options : "sip"))
1839 "sip")ntatag_sigcomp_options, tag_str_v((agent->sa_sigcomp_options
? agent->sa_sigcomp_options : "sip"))
,
1840 NTATAG_SIPFLAGS(agent->sa_flags)ntatag_sipflags, tag_uint_v((agent->sa_flags)),
1841 NTATAG_SIP_T1(agent->sa_t1)ntatag_sip_t1, tag_uint_v((agent->sa_t1)),
1842 NTATAG_SIP_T1X64(agent->sa_t1x64)ntatag_sip_t1x64, tag_uint_v((agent->sa_t1x64)),
1843 NTATAG_SIP_T2(agent->sa_t2)ntatag_sip_t2, tag_uint_v((agent->sa_t2)),
1844 NTATAG_SIP_T4(agent->sa_t4)ntatag_sip_t4, tag_uint_v((agent->sa_t4)),
1845#if HAVE_SOFIA_SMIME0
1846 NTATAG_SMIME(agent->sa_smime)ntatag_smime, tag_ptr_v((agent->sa_smime)),
1847#else
1848 NTATAG_SMIME(NULL)ntatag_smime, tag_ptr_v((((void*)0))),
1849#endif
1850 NTATAG_STATELESS(agent->sa_is_stateless)ntatag_stateless, tag_bool_v((agent->sa_is_stateless)),
1851 NTATAG_TAG_3261(1)ntatag_tag_3261, tag_bool_v((1)),
1852 NTATAG_TIMEOUT_408(agent->sa_timeout_408)ntatag_timeout_408, tag_bool_v((agent->sa_timeout_408)),
1853 NTATAG_TIMER_C(agent->sa_timer_c)ntatag_timer_c, tag_uint_v((agent->sa_timer_c)),
1854 NTATAG_UA(agent->sa_is_a_uas)ntatag_ua, tag_bool_v((agent->sa_is_a_uas)),
1855 NTATAG_UDP_MTU(agent->sa_udp_mtu)ntatag_udp_mtu, tag_uint_v((agent->sa_udp_mtu)),
1856 NTATAG_USER_VIA(agent->sa_user_via)ntatag_user_via, tag_bool_v((agent->sa_user_via)),
1857 NTATAG_USE_NAPTR(agent->sa_use_naptr)ntatag_use_naptr, tag_bool_v((agent->sa_use_naptr)),
1858 NTATAG_USE_SRV(agent->sa_use_srv)ntatag_use_srv, tag_bool_v((agent->sa_use_srv)),
1859 NTATAG_USE_TIMESTAMP(agent->sa_timestamp)ntatag_use_timestamp, tag_bool_v((agent->sa_timestamp)),
1860 NTATAG_SRV_503(agent->sa_srv_503)ntatag_srv_503, tag_bool_v((agent->sa_srv_503)),
1861 TAG_END()(tag_type_t)0, (tag_value_t)0);
1862}
1863
1864/**Get NTA statistics.
1865 *
1866 * The nta_agent_get_stats() function retrieves the stack statistics.
1867 *
1868 * @TAGS
1869 * NTATAG_S_ACKED_TR_REF(),
1870 * NTATAG_S_BAD_MESSAGE_REF(),
1871 * NTATAG_S_BAD_REQUEST_REF(),
1872 * NTATAG_S_BAD_RESPONSE_REF(),
1873 * NTATAG_S_CANCELED_TR_REF(),
1874 * NTATAG_S_CLIENT_TR_REF(),
1875 * NTATAG_S_DIALOG_TR_REF(),
1876 * NTATAG_S_DROP_REQUEST_REF(),
1877 * NTATAG_S_DROP_RESPONSE_REF(),
1878 * NTATAG_S_IRQ_HASH_REF(),
1879 * NTATAG_S_IRQ_HASH_USED_REF(),
1880 * NTATAG_S_LEG_HASH_REF(),
1881 * NTATAG_S_LEG_HASH_USED_REF(),
1882 * NTATAG_S_MERGED_REQUEST_REF(),
1883 * NTATAG_S_ORQ_HASH_REF(),
1884 * NTATAG_S_ORQ_HASH_USED_REF(),
1885 * NTATAG_S_RECV_MSG_REF(),
1886 * NTATAG_S_RECV_REQUEST_REF(),
1887 * NTATAG_S_RECV_RESPONSE_REF(),
1888 * NTATAG_S_RECV_RETRY_REF(),
1889 * NTATAG_S_RETRY_REQUEST_REF(),
1890 * NTATAG_S_RETRY_RESPONSE_REF(),
1891 * NTATAG_S_SENT_MSG_REF(),
1892 * NTATAG_S_SENT_REQUEST_REF(),
1893 * NTATAG_S_SENT_RESPONSE_REF(),
1894 * NTATAG_S_SERVER_TR_REF(),
1895 * NTATAG_S_TOUT_REQUEST_REF(),
1896 * NTATAG_S_TOUT_RESPONSE_REF(),
1897 * NTATAG_S_TRLESS_200_REF(),
1898 * NTATAG_S_TRLESS_REQUEST_REF(),
1899 * NTATAG_S_TRLESS_RESPONSE_REF(), and
1900 * NTATAG_S_TRLESS_TO_TR_REF(),
1901 */
1902int nta_agent_get_stats(nta_agent_t *agent,
1903 tag_type_t tag, tag_value_t value, ...)
1904{
1905 int n;
1906 ta_list ta;
1907
1908 if (!agent)
1909 return su_seterrno(EINVAL22), -1;
1910
1911 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
1912
1913 n = tl_tgets(ta_args(ta)(ta).tl,
1914 NTATAG_S_IRQ_HASH(agent->sa_incoming->iht_size)ntatag_s_irq_hash, tag_usize_v(agent->sa_incoming->iht_size
)
,
1915 NTATAG_S_ORQ_HASH(agent->sa_outgoing->oht_size)ntatag_s_orq_hash, tag_usize_v(agent->sa_outgoing->oht_size
)
,
1916 NTATAG_S_LEG_HASH(agent->sa_dialogs->lht_size)ntatag_s_leg_hash, tag_usize_v(agent->sa_dialogs->lht_size
)
,
1917 NTATAG_S_IRQ_HASH_USED(agent->sa_incoming->iht_used)ntatag_s_irq_hash_used, tag_usize_v(agent->sa_incoming->
iht_used)
,
1918 NTATAG_S_ORQ_HASH_USED(agent->sa_outgoing->oht_used)ntatag_s_orq_hash_used, tag_usize_v(agent->sa_outgoing->
oht_used)
,
1919 NTATAG_S_LEG_HASH_USED(agent->sa_dialogs->lht_used)ntatag_s_leg_hash_used, tag_usize_v(agent->sa_dialogs->
lht_used)
,
1920 NTATAG_S_RECV_MSG(agent->sa_stats->as_recv_msg)ntatag_s_recv_msg, tag_usize_v(agent->sa_stats->as_recv_msg
)
,
1921 NTATAG_S_RECV_REQUEST(agent->sa_stats->as_recv_request)ntatag_s_recv_request, tag_usize_v(agent->sa_stats->as_recv_request
)
,
1922 NTATAG_S_RECV_RESPONSE(agent->sa_stats->as_recv_response)ntatag_s_recv_response, tag_usize_v(agent->sa_stats->as_recv_response
)
,
1923 NTATAG_S_BAD_MESSAGE(agent->sa_stats->as_bad_message)ntatag_s_bad_message, tag_usize_v(agent->sa_stats->as_bad_message
)
,
1924 NTATAG_S_BAD_REQUEST(agent->sa_stats->as_bad_request)ntatag_s_bad_request, tag_usize_v(agent->sa_stats->as_bad_request
)
,
1925 NTATAG_S_BAD_RESPONSE(agent->sa_stats->as_bad_response)ntatag_s_bad_response, tag_usize_v(agent->sa_stats->as_bad_response
)
,
1926 NTATAG_S_DROP_REQUEST(agent->sa_stats->as_drop_request)ntatag_s_drop_request, tag_usize_v(agent->sa_stats->as_drop_request
)
,
1927 NTATAG_S_DROP_RESPONSE(agent->sa_stats->as_drop_response)ntatag_s_drop_response, tag_usize_v(agent->sa_stats->as_drop_response
)
,
1928 NTATAG_S_CLIENT_TR(agent->sa_stats->as_client_tr)ntatag_s_client_tr, tag_usize_v(agent->sa_stats->as_client_tr
)
,
1929 NTATAG_S_SERVER_TR(agent->sa_stats->as_server_tr)ntatag_s_server_tr, tag_usize_v(agent->sa_stats->as_server_tr
)
,
1930 NTATAG_S_DIALOG_TR(agent->sa_stats->as_dialog_tr)ntatag_s_dialog_tr, tag_usize_v(agent->sa_stats->as_dialog_tr
)
,
1931 NTATAG_S_ACKED_TR(agent->sa_stats->as_acked_tr)ntatag_s_acked_tr, tag_usize_v(agent->sa_stats->as_acked_tr
)
,
1932 NTATAG_S_CANCELED_TR(agent->sa_stats->as_canceled_tr)ntatag_s_canceled_tr, tag_usize_v(agent->sa_stats->as_canceled_tr
)
,
1933 NTATAG_S_TRLESS_REQUEST(agent->sa_stats->as_trless_request)ntatag_s_trless_request, tag_usize_v(agent->sa_stats->as_trless_request
)
,
1934 NTATAG_S_TRLESS_TO_TR(agent->sa_stats->as_trless_to_tr)ntatag_s_trless_to_tr, tag_usize_v(agent->sa_stats->as_trless_to_tr
)
,
1935 NTATAG_S_TRLESS_RESPONSE(agent->sa_stats->as_trless_response)ntatag_s_trless_response, tag_usize_v(agent->sa_stats->
as_trless_response)
,
1936 NTATAG_S_TRLESS_200(agent->sa_stats->as_trless_200)ntatag_s_trless_200, tag_usize_v(agent->sa_stats->as_trless_200
)
,
1937 NTATAG_S_MERGED_REQUEST(agent->sa_stats->as_merged_request)ntatag_s_merged_request, tag_usize_v(agent->sa_stats->as_merged_request
)
,
1938 NTATAG_S_SENT_MSG(agent->sa_stats->as_sent_msg)ntatag_s_sent_msg, tag_usize_v(agent->sa_stats->as_sent_msg
)
,
1939 NTATAG_S_SENT_REQUEST(agent->sa_stats->as_sent_request)ntatag_s_sent_request, tag_usize_v(agent->sa_stats->as_sent_request
)
,
1940 NTATAG_S_SENT_RESPONSE(agent->sa_stats->as_sent_response)ntatag_s_sent_response, tag_usize_v(agent->sa_stats->as_sent_response
)
,
1941 NTATAG_S_RETRY_REQUEST(agent->sa_stats->as_retry_request)ntatag_s_retry_request, tag_usize_v(agent->sa_stats->as_retry_request
)
,
1942 NTATAG_S_RETRY_RESPONSE(agent->sa_stats->as_retry_response)ntatag_s_retry_response, tag_usize_v(agent->sa_stats->as_retry_response
)
,
1943 NTATAG_S_RECV_RETRY(agent->sa_stats->as_recv_retry)ntatag_s_recv_retry, tag_usize_v(agent->sa_stats->as_recv_retry
)
,
1944 NTATAG_S_TOUT_REQUEST(agent->sa_stats->as_tout_request)ntatag_s_tout_request, tag_usize_v(agent->sa_stats->as_tout_request
)
,
1945 NTATAG_S_TOUT_RESPONSE(agent->sa_stats->as_tout_response)ntatag_s_tout_response, tag_usize_v(agent->sa_stats->as_tout_response
)
,
1946 NTATAG_Q_IN_COMPLETED(agent->sa_in.completed->q_length)ntatag_q_in_completed, tag_size_v(agent->sa_in.completed->
q_length)
,
1947 NTATAG_Q_IN_FINAL_FAILED(agent->sa_in.final_failed->q_length)ntatag_q_in_final_failed, tag_size_v(agent->sa_in.final_failed
->q_length)
,
1948 NTATAG_Q_IN_INV_COMPLETED(agent->sa_in.inv_completed->q_length)ntatag_q_in_inv_completed, tag_size_v(agent->sa_in.inv_completed
->q_length)
,
1949 NTATAG_Q_IN_INV_CONFIRMED(agent->sa_in.inv_confirmed->q_length)ntatag_q_in_inv_confirmed, tag_size_v(agent->sa_in.inv_confirmed
->q_length)
,
1950 NTATAG_Q_IN_PRELIMINARY(agent->sa_in.preliminary->q_length)ntatag_q_in_preliminary, tag_size_v(agent->sa_in.preliminary
->q_length)
,
1951 NTATAG_Q_IN_PROCEEDING(agent->sa_in.proceeding->q_length)ntatag_q_in_proceeding, tag_size_v(agent->sa_in.proceeding
->q_length)
,
1952 NTATAG_Q_IN_TERMINATED(agent->sa_in.terminated->q_length)ntatag_q_in_terminated, tag_size_v(agent->sa_in.terminated
->q_length)
,
1953 NTATAG_Q_OUT_COMPLETED(agent->sa_out.completed->q_length)ntatag_q_out_completed, tag_size_v(agent->sa_out.completed
->q_length)
,
1954 NTATAG_Q_OUT_DELAYED(agent->sa_out.delayed->q_length)ntatag_q_out_delayed, tag_size_v(agent->sa_out.delayed->
q_length)
,
1955 NTATAG_Q_OUT_INV_CALLING(agent->sa_out.inv_calling->q_length)ntatag_q_out_inv_calling, tag_size_v(agent->sa_out.inv_calling
->q_length)
,
1956 NTATAG_Q_OUT_INV_COMPLETED(agent->sa_out.inv_completed->q_length)ntatag_q_out_inv_completed, tag_size_v(agent->sa_out.inv_completed
->q_length)
,
1957 NTATAG_Q_OUT_INV_PROCEEDING(agent->sa_out.inv_proceeding->q_length)ntatag_q_out_inv_proceeding, tag_size_v(agent->sa_out.inv_proceeding
->q_length)
,
1958 NTATAG_Q_OUT_RESOLVING(agent->sa_out.resolving->q_length)ntatag_q_out_resolving, tag_size_v(agent->sa_out.resolving
->q_length)
,
1959 NTATAG_Q_OUT_TERMINATED(agent->sa_out.terminated->q_length)ntatag_q_out_terminated, tag_size_v(agent->sa_out.terminated
->q_length)
,
1960 TAG_END()(tag_type_t)0, (tag_value_t)0);
1961
1962 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
1963
1964 return n;
1965}
1966
1967/**Calculate a new unique tag.
1968 *
1969 * This function generates a series of 2**64 unique tags for @From or @To
1970 * headers. The start of the tag series is derived from the NTP time the NTA
1971 * agent was initialized.
1972 *
1973 */
1974char const *nta_agent_newtag(su_home_t *home, char const *fmt, nta_agent_t *sa)
1975{
1976 char tag[(8 * 8 + 4)/ 5 + 1];
1977
1978 if (sa == NULL((void*)0))
1979 return su_seterrno(EINVAL22), NULL((void*)0);
1980
1981 /* XXX - use a cryptographically safe func here? */
1982 sa->sa_tags += NTA_TAG_PRIME(uint64_t)(0xB9591D1C361C6521ULL);
1983
1984 msg_random_token(tag, sizeof(tag) - 1, &sa->sa_tags, sizeof(sa->sa_tags));
1985
1986 if (fmt && fmt[0])
1987 return su_sprintf(home, fmt, tag);
1988 else
1989 return su_strdup(home, tag);
1990}
1991
1992/**
1993 * Calculate branch value.
1994 */
1995static char const *stateful_branch(su_home_t *home, nta_agent_t *sa)
1996{
1997 char branch[(8 * 8 + 4)/ 5 + 1];
1998
1999 /* XXX - use a cryptographically safe func here? */
2000 sa->sa_branch += NTA_BRANCH_PRIME(uint64_t)(0xB9591D1C361C6521ULL);
2001
2002 msg_random_token(branch, sizeof(branch) - 1,
2003 &sa->sa_branch, sizeof(sa->sa_branch));
2004
2005 return su_sprintf(home, "branch=z9hG4bK%s", branch);
2006}
2007
2008#include <sofia-sip/su_md5.h>
2009
2010/**
2011 * Calculate branch value for stateless operation.
2012 *
2013 * XXX - should include HMAC of previous @Via line.
2014 */
2015static
2016char const *stateless_branch(nta_agent_t *sa,
2017 msg_t *msg,
2018 sip_t const *sip,
2019 tp_name_t const *tpn)
2020{
2021 su_md5_t md5[1];
2022 uint8_t digest[SU_MD5_DIGEST_SIZE16];
2023 char branch[(SU_MD5_DIGEST_SIZE16 * 8 + 4)/ 5 + 1];
2024 sip_route_t const *r;
2025
2026 assert(sip->sip_request)((void) sizeof ((sip->sip_request) ? 1 : 0), __extension__
({ if (sip->sip_request) ; else __assert_fail ("sip->sip_request"
, "nta.c", 2026, __extension__ __PRETTY_FUNCTION__); }))
;
2027
2028 if (!sip->sip_via)
2029 return stateful_branch(msg_home(msg)((su_home_t*)(msg)), sa);
2030
2031 su_md5_init(md5);
2032
2033 su_md5_str0update(md5, tpn->tpn_host);
2034 su_md5_str0update(md5, tpn->tpn_port);
2035
2036 url_update(md5, sip->sip_request->rq_url);
2037 if (sip->sip_call_id) {
2038 su_md5_str0update(md5, sip->sip_call_id->i_id);
2039 }
2040 if (sip->sip_from) {
2041 url_update(md5, sip->sip_from->a_url);
2042 su_md5_stri0update(md5, sip->sip_from->a_tag);
2043 }
2044 if (sip->sip_to) {
2045 url_update(md5, sip->sip_to->a_url);
2046 /* XXX - some broken implementations include To tag in CANCEL */
2047 /* su_md5_str0update(md5, sip->sip_to->a_tag); */
2048 }
2049 if (sip->sip_cseq) {
2050 uint32_t cseq = htonl(sip->sip_cseq->cs_seq);
2051 su_md5_update(md5, &cseq, sizeof(cseq));
2052 }
2053
2054 for (r = sip->sip_route; r; r = r->r_next)
2055 url_update(md5, r->r_url);
2056
2057 su_md5_digest(md5, digest);
2058
2059 msg_random_token(branch, sizeof(branch) - 1, digest, sizeof(digest));
2060
2061 return su_sprintf(msg_home(msg)((su_home_t*)(msg)), "branch=z9hG4bK.%s", branch);
2062}
2063
2064/* ====================================================================== */
2065/* 2) Transport interface */
2066
2067/* Local prototypes */
2068static int agent_create_master_transport(nta_agent_t *self, tagi_t *tags);
2069static int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr);
2070static int agent_init_contact(nta_agent_t *self);
2071static void agent_recv_message(nta_agent_t *agent,
2072 tport_t *tport,
2073 msg_t *msg,
2074 sip_via_t *tport_via,
2075 su_time_t now);
2076static void agent_tp_error(nta_agent_t *agent,
2077 tport_t *tport,
2078 int errcode,
2079 char const *remote);
2080static void agent_update_tport(nta_agent_t *agent, tport_t *);
2081
2082/**For each transport, we have name used by tport module, SRV prefixes used
2083 * for resolving, and NAPTR service/conversion.
2084 */
2085static
2086struct sipdns_tport {
2087 char name[6]; /**< Named used by tport module */
2088 char port[6]; /**< Default port number */
2089 char prefix[14]; /**< Prefix for SRV domains */
2090 char service[10]; /**< NAPTR service */
2091}
2092#define SIPDNS_TRANSPORTS(6) (6)
2093const sipdns_tports[SIPDNS_TRANSPORTS(6)] = {
2094 { "udp", "5060", "_sip._udp.", "SIP+D2U" },
2095 { "tcp", "5060", "_sip._tcp.", "SIP+D2T" },
2096 { "sctp", "5060", "_sip._sctp.", "SIP+D2S" },
2097 { "tls", "5061", "_sips._tcp.", "SIPS+D2T" },
2098 { "ws", "5080", "_sips._ws.", "SIP+D2W" },
2099 { "wss", "5081", "_sips._wss.", "SIPS+D2W" },
2100};
2101
2102static char const * const tports_sip[] =
2103 {
2104 "udp", "tcp", "sctp", "ws", NULL((void*)0)
2105 };
2106
2107static char const * const tports_sips[] =
2108 {
2109 "tls", "wss", "ws", NULL((void*)0)
2110 };
2111
2112static tport_stack_class_t nta_agent_class[1] =
2113 {{
2114 sizeof(nta_agent_class),
2115 agent_recv_message,
2116 agent_tp_error,
2117 nta_msg_create_for_transport,
2118 agent_update_tport,
2119 }};
2120
2121
2122/** Add a transport to the agent.
2123 *
2124 * Creates a new transport and binds it
2125 * to the port specified by the @a uri. The @a uri must have sip: or sips:
2126 * scheme or be a wildcard uri ("*"). The @a uri syntax allowed is as
2127 * follows:
2128 *
2129 * @code url <scheme>:<host>[:<port>]<url-params> @endcode
2130 * where <url-params> may be
2131 * @code
2132 * ;transport=<xxx>
2133 * ;maddr=<actual addr>
2134 * ;comp=sigcomp
2135 * @endcode
2136 *
2137 * The scheme part determines which transports are used. "sip" implies UDP
2138 * and TCP, "sips" TLS over TCP. In the future, more transports can be
2139 * supported, for instance, "sip" can use SCTP or DCCP, "sips" DTLS or TLS
2140 * over SCTP.
2141 *
2142 * The "host" part determines what address/domain name is used in @Contact.
2143 * An "*" in "host" part is shorthand for any local IP address. 0.0.0.0
2144 * means that the only the IPv4 addresses are used. [::] means that only
2145 * the IPv6 addresses are used. If a domain name or a specific IP address
2146 * is given as "host" part, an additional "maddr" parameter can be used to
2147 * control which addresses are used by the stack when binding listen
2148 * sockets for incoming requests.
2149 *
2150 * The "port" determines what port is used in contact, and to which port the
2151 * stack binds in order to listen for incoming requests. Empty or missing
2152 * port means that default port should be used (5060 for sip, 5061 for
2153 * sips). An "*" in "port" part means any port, i.e., the stack binds to an
2154 * ephemeral port.
2155 *
2156 * The "transport" parameter determines the transport protocol that is used
2157 * and how they are preferred. If no protocol is specified, both UDP and TCP
2158 * are used for SIP URL and TLS for SIPS URL. The preference can be
2159 * indicated with a comma-separated list of transports, for instance,
2160 * parameter @code transport=tcp,udp @endcode indicates that TCP is
2161 * preferred to UDP.
2162 *
2163 * The "maddr" parameter determines to which address the stack binds in
2164 * order to listen for incoming requests. An "*" in "maddr" parameter is
2165 * shorthand for any local IP address. 0.0.0.0 means that only IPv4 sockets
2166 * are created. [::] means that only IPv6 sockets are created.
2167 *
2168 * The "comp" parameter determines the supported compression protocol.
2169 * Currently only sigcomp is supported (with suitable library).
2170 *
2171 * @par Examples:
2172 * @code sip:172.21.40.24;maddr=* @endcode \n
2173 * @code sip:172.21.40.24:50600;transport=TCP,UDP;comp=sigcomp @endcode \n
2174 * @code sips:* @endcode
2175 *
2176 * @return
2177 * On success, zero is returned. On error, -1 is returned, and @a errno is
2178 * set appropriately.
2179 */
2180int nta_agent_add_tport(nta_agent_t *self,
2181 url_string_t const *uri,
2182 tag_type_t tag, tag_value_t value, ...)
2183{
2184 url_t *url;
2185 char tp[32];
2186 char maddr[256];
2187 char comp[32];
2188 tp_name_t tpn[1] = {{ NULL((void*)0) }};
2189 char const * const * tports = tports_sip;
2190 int error;
2191 ta_list ta;
2192 char *tps[9] = {0};
2193
2194 if (self == NULL((void*)0)) {
2195 su_seterrno(EINVAL22);
2196 return -1;
2197 }
2198
2199 if (uri == NULL((void*)0))
2200 uri = (url_string_t *)"sip:*";
2201 else if (url_string_p(uri) ?
2202 strcmp(uri->us_str, "*") == 0 :
2203 uri->us_url->url_type == url_any) {
2204 uri = (url_string_t *)"sip:*:*";
2205 }
2206
2207 if (!(url = url_hdup(self->sa_home, uri->us_url)) ||
2208 (url->url_type != url_sip && url->url_type != url_sips && url->url_type != url_urn)) {
2209 if (url_string_p(uri))
2210 SU_DEBUG_1(("nta: %s: invalid bind URL\n", uri->us_str))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2210, "nta: %s: invalid bind URL\n", uri->us_str)) : (void
)0)
;
2211 else
2212 SU_DEBUG_1(("nta: invalid bind URL\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2212, "nta: invalid bind URL\n" "%s", "")) : (void)0)
;
2213 su_seterrno(EINVAL22);
2214 return -1;
2215 }
2216
2217 tpn->tpn_canon = url->url_host;
2218 tpn->tpn_host = url->url_host;
2219 tpn->tpn_port = url_port(url);
2220
2221 if (url->url_type == url_sip || url->url_type == url_urn) {
2222 tpn->tpn_proto = "*";
2223 tports = tports_sip;
2224 if (!tpn->tpn_port || !tpn->tpn_port[0])
2225 tpn->tpn_port = SIP_DEFAULT_SERV"5060";
2226 }
2227 else {
2228 assert(url->url_type == url_sips)((void) sizeof ((url->url_type == url_sips) ? 1 : 0), __extension__
({ if (url->url_type == url_sips) ; else __assert_fail ("url->url_type == url_sips"
, "nta.c", 2228, __extension__ __PRETTY_FUNCTION__); }))
;
2229 tpn->tpn_proto = "*";
2230 tports = tports_sips;
2231 if (!tpn->tpn_port || !tpn->tpn_port[0])
2232 tpn->tpn_port = SIPS_DEFAULT_SERV"5061";
2233 }
2234
2235 if (url->url_params) {
2236 if (url_param(url->url_params, "transport", tp, sizeof(tp)) > 0) {
2237 if (strchr(tp, ',')) {
2238 int i; char *t;
2239
2240 /* Split tp into transports */
2241 for (i = 0, t = tp; t && i < 8; i++) {
2242 tps[i] = t;
2243 if ((t = strchr(t, ',')))
2244 *t++ = '\0';
2245 }
2246
2247 tps[i] = NULL((void*)0);
2248 tports = (char const * const *)tps;
2249 } else {
2250 tpn->tpn_proto = tp;
2251 }
2252 }
2253 if (url_param(url->url_params, "maddr", maddr, sizeof(maddr)) > 0)
2254 tpn->tpn_host = maddr;
2255 if (url_param(url->url_params, "comp", comp, sizeof(comp)) > 0)
2256 tpn->tpn_comp = comp;
2257
2258 if (tpn->tpn_comp &&
2259 (nta_compressor_vtable == NULL((void*)0) ||
2260 !su_casematch(tpn->tpn_comp, nta_compressor_vtable->ncv_name))) {
2261 SU_DEBUG_1(("nta(%p): comp=%s not supported for " URL_PRINT_FORMAT "\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2262, "nta(%p): comp=%s not supported for " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"\n", (void *)self, tpn->tpn_comp, (url)->url_scheme ?
(url)->url_scheme : "", (url)->url_type != url_any &&
(url)->url_scheme && (url)->url_scheme[0] ? ":"
: "", (url)->url_root && ((url)->url_host || (
url)->url_user) ? "//" : "", (url)->url_user ? (url)->
url_user : "", (url)->url_user && (url)->url_password
? ":" : "", (url)->url_user && (url)->url_password
? (url)->url_password : "", (url)->url_user &&
(url)->url_host ? "@" : "", (url)->url_host ? (url)->
url_host : "", (url)->url_host && (url)->url_port
? ":" : "", (url)->url_host && (url)->url_port
? (url)->url_port : "", (url)->url_root && (url
)->url_path ? "/" : "", (url)->url_path ? (url)->url_path
: "", (url)->url_params ? ";" : "", (url)->url_params ?
(url)->url_params : "", (url)->url_headers ? "?" : "",
(url)->url_headers ? (url)->url_headers : "", (url)->
url_fragment ? "#" : "", (url)->url_fragment ? (url)->url_fragment
: "")) : (void)0)
2262 (void *)self, tpn->tpn_comp, URL_PRINT_ARGS(url)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2262, "nta(%p): comp=%s not supported for " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
"\n", (void *)self, tpn->tpn_comp, (url)->url_scheme ?
(url)->url_scheme : "", (url)->url_type != url_any &&
(url)->url_scheme && (url)->url_scheme[0] ? ":"
: "", (url)->url_root && ((url)->url_host || (
url)->url_user) ? "//" : "", (url)->url_user ? (url)->
url_user : "", (url)->url_user && (url)->url_password
? ":" : "", (url)->url_user && (url)->url_password
? (url)->url_password : "", (url)->url_user &&
(url)->url_host ? "@" : "", (url)->url_host ? (url)->
url_host : "", (url)->url_host && (url)->url_port
? ":" : "", (url)->url_host && (url)->url_port
? (url)->url_port : "", (url)->url_root && (url
)->url_path ? "/" : "", (url)->url_path ? (url)->url_path
: "", (url)->url_params ? ";" : "", (url)->url_params ?
(url)->url_params : "", (url)->url_headers ? "?" : "",
(url)->url_headers ? (url)->url_headers : "", (url)->
url_fragment ? "#" : "", (url)->url_fragment ? (url)->url_fragment
: "")) : (void)0)
;
2263 }
2264 }
2265
2266 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
2267
2268 if (self->sa_tports == NULL((void*)0)) {
2269 if (agent_create_master_transport(self, ta_args(ta)(ta).tl) < 0) {
2270 error = su_errno();
2271 SU_DEBUG_1(("nta: cannot create master transport: %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2272, "nta: cannot create master transport: %s\n", su_strerror
(error))) : (void)0)
2272 su_strerror(error)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2272, "nta: cannot create master transport: %s\n", su_strerror
(error))) : (void)0)
;
2273 goto error;
2274 }
2275 }
2276
2277 if (tport_tbind(self->sa_tports, tpn, tports, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0) {
2278 error = su_errno();
2279 SU_DEBUG_1(("nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2280 tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2281 tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2282 tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2283 tpn->tpn_comp ? ";comp=" : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2284 tpn->tpn_comp ? tpn->tpn_comp : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
2285 su_strerror(error)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2285, "nta: bind(%s:%s;transport=%s%s%s%s%s): %s\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "", su_strerror(
error))) : (void)0)
;
2286 goto error;
2287 }
2288 else
2289 SU_DEBUG_5(("nta: bound to (%s:%s;transport=%s%s%s%s%s)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
2290 tpn->tpn_canon, tpn->tpn_port, tpn->tpn_proto,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
2291 tpn->tpn_canon != tpn->tpn_host ? ";maddr=" : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
2292 tpn->tpn_canon != tpn->tpn_host ? tpn->tpn_host : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
2293 tpn->tpn_comp ? ";comp=" : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
2294 tpn->tpn_comp ? tpn->tpn_comp : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2294, "nta: bound to (%s:%s;transport=%s%s%s%s%s)\n", tpn->
tpn_canon, tpn->tpn_port, tpn->tpn_proto, tpn->tpn_canon
!= tpn->tpn_host ? ";maddr=" : "", tpn->tpn_canon != tpn
->tpn_host ? tpn->tpn_host : "", tpn->tpn_comp ? ";comp="
: "", tpn->tpn_comp ? tpn->tpn_comp : "")) : (void)0)
;
2295
2296 /* XXX - when to use maddr? */
2297 if ((agent_init_via(self, tport_primaries(self->sa_tports), 0)) < 0) {
2298 error = su_errno();
2299 SU_DEBUG_1(("nta: cannot create Via headers\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2299, "nta: cannot create Via headers\n" "%s", "")) : (void
)0)
;
2300 goto error;
2301 }
2302 else
2303 SU_DEBUG_9(("nta: Via fields initialized\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2303, "nta: Via fields initialized\n" "%s", "")) : (void)0)
;
2304
2305 if ((agent_init_contact(self)) < 0) {
2306 error = su_errno();
2307 SU_DEBUG_1(("nta: cannot create Contact header\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2307, "nta: cannot create Contact header\n" "%s", "")) : (void
)0)
;
2308 goto error;
2309 }
2310 else
2311 SU_DEBUG_9(("nta: Contact header created\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2311, "nta: Contact header created\n" "%s", "")) : (void)0)
;
2312
2313 su_free(self->sa_home, url);
2314 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
2315
2316 return 0;
2317
2318 error:
2319 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
2320 su_seterrno(error);
2321 return -1;
2322}
2323
2324static
2325int agent_create_master_transport(nta_agent_t *self, tagi_t *tags)
2326{
2327 self->sa_tports =
2328 tport_tcreate(self, nta_agent_class, self->sa_root,
2329 TPTAG_IDLE(1800000)tptag_idle, tag_uint_v((1800000)),
2330 TAG_NEXT(tags)tag_next, (tag_value_t)(tags));
2331
2332 if (!self->sa_tports)
2333 return -1;
2334
2335 SU_DEBUG_9(("nta: master transport created\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2335, "nta: master transport created\n" "%s", "")) : (void)
0)
;
2336
2337 return 0;
2338}
2339
2340
2341/** Initialize @Via headers. */
2342static
2343int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr)
2344{
2345 sip_via_t *via = NULL((void*)0), *new_via, *dup_via, *v, **vv = &via;
2346 sip_via_t *new_vias, **next_new_via, *new_publics, **next_new_public;
2347 tport_t *tp;
2348 su_addrinfo_t const *ai;
2349
2350 su_home_t autohome[SU_HOME_AUTO_SIZE(2048)(((2048) + ((sizeof(su_home_t) + 7) & (size_t)~8) + ((3 *
sizeof (void *) + 4 * sizeof(unsigned) + 7 * (sizeof (long) +
sizeof(void *)) + 7) & (size_t)~8)) / sizeof(su_home_t))
];
2351
2352 su_home_auto(autohome, sizeof autohome);
2353
2354 self->sa_tport_ip4 = 0;
2355 self->sa_tport_ip6 = 0;
2356 self->sa_tport_udp = 0;
2357 self->sa_tport_tcp = 0;
2358 self->sa_tport_sctp = 0;
2359 self->sa_tport_tls = 0;
2360 self->sa_tport_ws = 0;
2361 self->sa_tport_wss = 0;
2362
2363 /* Set via fields for the tports */
2364 for (tp = primaries; tp; tp = tport_next(tp)) {
1
Loop condition is true. Entering loop body
48
Loop condition is false. Execution continues on line 2455
2365 int maddr;
2366 tp_name_t tpn[1];
2367 char const *comp = NULL((void*)0);
2368
2369 *tpn = *tport_name(tp);
2370
2371 assert(tpn->tpn_proto)((void) sizeof ((tpn->tpn_proto) ? 1 : 0), __extension__ (
{ if (tpn->tpn_proto) ; else __assert_fail ("tpn->tpn_proto"
, "nta.c", 2371, __extension__ __PRETTY_FUNCTION__); }))
;
2
Assuming field 'tpn_proto' is non-null
3
Taking true branch
2372 assert(tpn->tpn_canon)((void) sizeof ((tpn->tpn_canon) ? 1 : 0), __extension__ (
{ if (tpn->tpn_canon) ; else __assert_fail ("tpn->tpn_canon"
, "nta.c", 2372, __extension__ __PRETTY_FUNCTION__); }))
;
4
Assuming field 'tpn_canon' is non-null
5
Taking true branch
2373 assert(tpn->tpn_host)((void) sizeof ((tpn->tpn_host) ? 1 : 0), __extension__ ({
if (tpn->tpn_host) ; else __assert_fail ("tpn->tpn_host"
, "nta.c", 2373, __extension__ __PRETTY_FUNCTION__); }))
;
6
Assuming field 'tpn_host' is non-null
7
Taking true branch
2374 assert(tpn->tpn_port)((void) sizeof ((tpn->tpn_port) ? 1 : 0), __extension__ ({
if (tpn->tpn_port) ; else __assert_fail ("tpn->tpn_port"
, "nta.c", 2374, __extension__ __PRETTY_FUNCTION__); }))
;
8
Assuming field 'tpn_port' is non-null
9
Taking true branch
2375
2376#if 0
2377 if (getenv("SIP_UDP_CONNECT")
2378 && strcmp(tpn->tpn_proto, "udp") == 0)
2379 tport_set_params(tp, TPTAG_CONNECT(1)tptag_connect, tag_bool_v((1)), TAG_END()(tag_type_t)0, (tag_value_t)0);
2380#endif
2381
2382 if (tport_has_ip4(tp)) self->sa_tport_ip4 = 1;
10
Assuming the condition is false
11
Taking false branch
2383
2384#if SU_HAVE_IN61
2385 if (tport_has_ip6(tp)) self->sa_tport_ip6 = 1;
12
Assuming the condition is false
13
Taking false branch
2386#endif
2387
2388 if (su_casematch(tpn->tpn_proto, "udp"))
14
Assuming the condition is false
15
Taking false branch
2389 self->sa_tport_udp = 1;
2390 else if (su_casematch(tpn->tpn_proto, "tcp"))
16
Assuming the condition is false
17
Taking false branch
2391 self->sa_tport_tcp = 1;
2392 else if (su_casematch(tpn->tpn_proto, "sctp"))
18
Assuming the condition is false
19
Taking false branch
2393 self->sa_tport_sctp = 1;
2394 else if (su_casematch(tpn->tpn_proto, "ws"))
20
Assuming the condition is false
21
Taking false branch
2395 self->sa_tport_ws = 1;
2396 else if (su_casematch(tpn->tpn_proto, "wss"))
22
Assuming the condition is false
23
Taking false branch
2397 self->sa_tport_wss = 1;
2398
2399 if (tport_has_tls(tp)) self->sa_tport_tls = 1;
24
Assuming the condition is false
25
Taking false branch
2400
2401 ai = tport_get_address(tp);
2402
2403 for (; ai; ai = ai->ai_next) {
26
Loop condition is true. Entering loop body
47
Loop condition is false. Execution continues on line 2364
2404 char host[TPORT_HOSTPORTSIZE(55)] = "";
2405 char sport[8];
2406 char const *canon = ai->ai_canonname;
2407 su_sockaddr_t *su = (void *)ai->ai_addr;
2408 int port;
2409
2410 if (su) {
27
Assuming 'su' is null
28
Taking false branch
2411 su_inet_ntopinet_ntop(su->su_familysu_sa.sa_family, SU_ADDR(su)((su)->su_sa.sa_family == 2 ? (void *)&(su)->su_sin
.sin_addr : ((su)->su_sa.sa_family == 10 ? (void *)&(su
)->su_sin6.sin6_addr : (void *)&(su)->su_sa.sa_data
))
, host, sizeof host);
2412 maddr = use_maddr && !su_casematch(canon, host);
2413 port = ntohs(su->su_portsu_sin.sin_port);
2414 }
2415 else {
2416 msg_random_token(host, 16, NULL((void*)0), 0);
2417 canon = strcat(host, ".is.invalid");
2418 maddr = 0;
2419 port = 0;
2420 }
2421
2422 if (su_casenmatch(tpn->tpn_proto, "tls", 3)
29
Assuming the condition is false
30
'?' condition is false
31
Taking false branch
2423 ? port == SIPS_DEFAULT_PORTSIPS_DEFAULT_PORT
2424 : port == SIP_DEFAULT_PORTSIP_DEFAULT_PORT)
2425 port = 0;
2426
2427 snprintf(sport, sizeof sport, ":%u", port);
2428
2429 comp = tpn->tpn_comp;
2430
2431 SU_DEBUG_9(("nta: agent_init_via: "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
32
Assuming the condition is false
33
'?' condition is false
34
Assuming field 'log_init' is <= 1
35
'?' condition is false
36
Assuming the condition is false
37
'?' condition is false
2432 "%s/%s %s%s%s%s%s%s (%s)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
2433 SIP_VERSION_CURRENT, tpn->tpn_proto,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
2434 canon, port ? sport : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
2435 maddr ? ";maddr=" : "", maddr ? host : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
2436 comp ? ";comp=" : "", comp ? comp : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
2437 tpn->tpn_ident ? tpn->tpn_ident : "*"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2437, "nta: agent_init_via: " "%s/%s %s%s%s%s%s%s (%s)\n", sip_version_2_0
, tpn->tpn_proto, canon, port ? sport : "", maddr ? ";maddr="
: "", maddr ? host : "", comp ? ";comp=" : "", comp ? comp :
"", tpn->tpn_ident ? tpn->tpn_ident : "*")) : (void)0)
;
2438
2439 v = sip_via_format(autohome,
2440 "%s/%s %s%s%s%s%s%s",
2441 SIP_VERSION_CURRENTsip_version_2_0, tpn->tpn_proto,
2442 canon, port
37.1
'port' is 0
37.1
'port' is 0
? sport : "",
38
'?' condition is false
2443 maddr
38.1
'maddr' is 0
38.1
'maddr' is 0
? ";maddr=" : "", maddr
39.1
'maddr' is 0
39.1
'maddr' is 0
? host : "",
39
'?' condition is false
40
'?' condition is false
2444 comp ? ";comp=" : "", comp
42.1
'comp' is null
42.1
'comp' is null
? comp : "");
41
Assuming 'comp' is null
42
'?' condition is false
43
'?' condition is false
2445 if (v == NULL((void*)0))
44
Assuming 'v' is not equal to NULL
45
Taking false branch
2446 goto error;
2447
2448 v->v_comment = tpn->tpn_ident;
2449 assert(v->v_common)((void) sizeof ((v->v_common) ? 1 : 0), __extension__ ({ if
(v->v_common) ; else __assert_fail ("v->v_common", "nta.c"
, 2449, __extension__ __PRETTY_FUNCTION__); }))
;
46
Taking true branch
2450 v->v_common->h_data = tp; /* Nasty trick */
2451 *vv = v; vv = &(*vv)->v_next;
2452 }
2453 }
2454
2455 if (!via
48.1
'via' is non-null
48.1
'via' is non-null
) {
49
Taking false branch
2456 SU_DEBUG_9(("nta: agent_init_via failed\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 2456, "nta: agent_init_via failed\n" "%s", "")) : (void)0)
;
2457 goto error;
2458 }
2459
2460 /* Duplicate the list bind to the transports */
2461 new_via = sip_via_dup(self->sa_home, via);
2462 /* Duplicate the complete list shown to the application */
2463 dup_via = sip_via_dup(self->sa_home, via);
50
Calling 'sip_via_dup'
53
Returning from 'sip_via_dup'
2464
2465 if (via
53.1
'via' is non-null
53.1
'via' is non-null
&& (!new_via || !dup_via)) {
54
Assuming 'new_via' is non-null
55
Assuming 'dup_via' is non-null
56
Taking false branch
2466 msg_header_free(self->sa_home, (void *)new_via);
2467 msg_header_free(self->sa_home, (void *)dup_via);
2468 goto error;
2469 }
2470
2471 new_vias = NULL((void*)0), next_new_via = &new_vias;
2472 new_publics = NULL((void*)0), next_new_public = &new_publics;
2473
2474 /* Set via field magic for the tports */
2475 for (tp = primaries; tp; tp = tport_next(tp)) {
57
Loop condition is true. Entering loop body
67
Loop condition is true. Entering loop body
2476 assert(via->v_common->h_data == tp)((void) sizeof ((via->v_common->h_data == tp) ? 1 : 0),
__extension__ ({ if (via->v_common->h_data == tp) ; else
__assert_fail ("via->v_common->h_data == tp", "nta.c",
2476, __extension__ __PRETTY_FUNCTION__); }))
;
58
Assuming 'tp' is equal to field 'h_data'
59
Taking true branch
68
Access to field 'h_data' results in a dereference of a null pointer (loaded from field 'v_common')
2477 v = tport_magic(tp);
2478 tport_set_magic(tp, new_via);
2479 msg_header_free(self->sa_home, (void *)v);
2480
2481 if (tport_is_public(tp))
60
Assuming the condition is false
61
Taking false branch
2482 *next_new_public = dup_via;
2483 else
2484 *next_new_via = dup_via;
2485
2486 while (via->v_next && via->v_next->v_common->h_data == tp)
62
Assuming field 'v_next' is null
2487 via = via->v_next, new_via = new_via->v_next, dup_via = dup_via->v_next;
2488
2489 via = via->v_next;
63
Null pointer value stored to 'via'
2490 /* Break the link in via list between transports */
2491 vv = &new_via->v_next, new_via = *vv, *vv = NULL((void*)0);
2492 vv = &dup_via->v_next, dup_via = *vv, *vv = NULL((void*)0);
2493
2494 if (tport_is_public(tp))
64
Assuming the condition is true
65
Taking true branch
2495 while (*next_new_public) next_new_public = &(*next_new_public)->v_next;
66
Loop condition is false. Execution continues on line 2475
2496 else
2497 while (*next_new_via) next_new_via = &(*next_new_via)->v_next;
2498 }
2499
2500 assert(dup_via == NULL)((void) sizeof ((dup_via == ((void*)0)) ? 1 : 0), __extension__
({ if (dup_via == ((void*)0)) ; else __assert_fail ("dup_via == NULL"
, "nta.c", 2500, __extension__ __PRETTY_FUNCTION__); }))
;
2501 assert(new_via == NULL)((void) sizeof ((new_via == ((void*)0)) ? 1 : 0), __extension__
({ if (new_via == ((void*)0)) ; else __assert_fail ("new_via == NULL"
, "nta.c", 2501, __extension__ __PRETTY_FUNCTION__); }))
;
2502
2503 if (self->sa_tport_udp)
2504 agent_set_udp_params(self, self->sa_udp_mtu);
2505
2506 v = self->sa_vias;
2507 self->sa_vias = new_vias;
2508 msg_header_free(self->sa_home, (void *)v);
2509
2510 v = self->sa_public_vias;
2511 self->sa_public_vias = new_publics;
2512 msg_header_free(self->sa_home, (void *)v);
2513
2514 su_home_deinit(autohome);
2515
2516 return 0;
2517
2518 error:
2519 su_home_deinit(autohome);
2520 return -1;
2521}
2522
2523
2524/** Initialize main contact header. */
2525static
2526int agent_init_contact(nta_agent_t *self)
2527{
2528 sip_via_t const *v1, *v2;
2529 char const *tp;
2530
2531 if (self->sa_contact)
2532 return 0;
2533
2534 for (v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias;
2535 v1;
2536 v1 = v1->v_next) {
2537 if (host_is_ip_address(v1->v_host)) {
2538 if (!host_is_local(v1->v_host))
2539 break;
2540 }
2541 else if (!host_has_domain_invalid(v1->v_host)) {
2542 break;
2543 }
2544 }
2545
2546 if (v1 == NULL((void*)0))
2547 v1 = self->sa_vias ? self->sa_vias : self->sa_public_vias;
2548
2549 if (!v1)
2550 return -1;
2551
2552 tp = strrchr(v1->v_protocol, '/');
2553 if (!tp++)
2554 return -1;
2555
2556 v2 = v1->v_next;
2557
2558 if (v2 &&
2559 su_casematch(v1->v_host, v2->v_host) &&
2560 su_casematch(v1->v_port, v2->v_port)) {
2561 char const *p1 = v1->v_protocol, *p2 = v2->v_protocol;
2562
2563 if (!su_casematch(p1, sip_transport_udp))
2564 p1 = v2->v_protocol, p2 = v1->v_protocol;
2565
2566 if (su_casematch(p1, sip_transport_udp) &&
2567 su_casematch(p2, sip_transport_tcp))
2568 /* Do not include transport if we have both UDP and TCP */
2569 tp = NULL((void*)0);
2570 }
2571
2572 self->sa_contact =
2573 sip_contact_create_from_via_with_transport(self->sa_home, v1, NULL((void*)0), tp);
2574
2575 if (!self->sa_contact)
2576 return -1;
2577
2578 agent_tag_init(self);
2579
2580 return 0;
2581}
2582
2583/** Return @Via line corresponging to tport. */
2584static
2585sip_via_t const *agent_tport_via(tport_t *tport)
2586{
2587 sip_via_t *v = tport_magic(tport);
2588 while (v && v->v_next)
2589 v = v->v_next;
2590 return v;
2591}
2592
2593/** Insert @Via to a request message */
2594static
2595int outgoing_insert_via(nta_outgoing_t *orq,
2596 sip_via_t const *via)
2597{
2598 nta_agent_t *self = orq->orq_agent;
2599 msg_t *msg = orq->orq_request;
2600 sip_t *sip = sip_object(msg);
2601 char const *branch = orq->orq_via_branch;
2602 int already = orq->orq_user_via || orq->orq_via_added;
2603 int user_via = orq->orq_user_via;
2604 sip_via_t *v;
2605 int clear = 0;
2606
2607 assert(sip)((void) sizeof ((sip) ? 1 : 0), __extension__ ({ if (sip) ; else
__assert_fail ("sip", "nta.c", 2607, __extension__ __PRETTY_FUNCTION__
); }))
; assert(via)((void) sizeof ((via) ? 1 : 0), __extension__ ({ if (via) ; else
__assert_fail ("via", "nta.c", 2607, __extension__ __PRETTY_FUNCTION__
); }))
;
2608
2609 if (already && sip->sip_via) {
2610 /* Use existing @Via */
2611 v = sip->sip_via;
2612 }
2613 else if (msg && via && sip->sip_request &&
2614 (v = sip_via_copy(msg_home(msg)((su_home_t*)(msg)), via))) {
2615 if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v) < 0)
2616 return -1;
2617 orq->orq_via_added = 1;
2618 }
2619 else
2620 return -1;
2621
2622 if (!v->v_rport &&
2623 ((self->sa_rport && v->v_protocol == sip_transport_udp) ||
2624 (self->sa_tcp_rport && v->v_protocol == sip_transport_tcp) ||
2625 (self->sa_tls_rport && v->v_protocol == sip_transport_tls)))
2626 msg_header_add_param(msg_home(msg)((su_home_t*)(msg)), v->v_common, "rport");
2627
2628 if (!orq->orq_tpn->tpn_comp)
2629 msg_header_remove_param(v->v_common, "comp");
2630
2631 if (branch && branch != v->v_branch) {
2632 char const *bvalue = branch + strcspn(branch, "=");
2633 if (*bvalue) bvalue++;
2634 if (!v->v_branch || !su_casematch(bvalue, v->v_branch))
2635 msg_header_replace_param(msg_home(msg)((su_home_t*)(msg)), v->v_common, branch);
2636 }
2637
2638 if (!su_casematch(via->v_protocol, v->v_protocol))
2639 clear = 1, v->v_protocol = via->v_protocol;
2640
2641 /* XXX - should we do this? */
2642 if ((!user_via || !v->v_host) &&
2643 !su_strmatch(via->v_host, v->v_host))
2644 clear = 1, v->v_host = via->v_host;
2645
2646 if ((!user_via || !v->v_port ||
2647 /* Replace port in user Via only if we use udp and no rport */
2648 (v->v_protocol == sip_transport_udp && !v->v_rport &&
2649 !orq->orq_stateless)) &&
2650 !su_strmatch(via->v_port, v->v_port))
2651 clear = 1, v->v_port = via->v_port;
2652
2653 if (clear)
2654 msg_fragment_clear(v->v_common);
2655
2656 return 0;
2657}
2658
2659/** Get destination name from @Via.
2660 *
2661 * If @a using_rport is non-null, try rport.
2662 * If *using_rport is non-zero, try rport even if <protocol> is not UDP.
2663 * If <protocol> is UDP, set *using_rport to zero.
2664 */
2665static
2666int nta_tpn_by_via(tp_name_t *tpn, sip_via_t const *v, int *using_rport)
2667{
2668 if (!v)
2669 return -1;
2670
2671 tpn->tpn_proto = sip_via_transport(v);
2672 tpn->tpn_canon = v->v_host;
2673
2674 if (v->v_maddr)
2675 tpn->tpn_host = v->v_maddr;
2676 else if (v->v_received)
2677 tpn->tpn_host = v->v_received;
2678 else
2679 tpn->tpn_host = v->v_host;
2680
2681 tpn->tpn_port = sip_via_port(v, using_rport);
2682 tpn->tpn_comp = v->v_comp;
2683 tpn->tpn_ident = NULL((void*)0);
2684
2685 return 0;
2686}
2687
2688/** Get transport name from URL. */
2689static int
2690nta_tpn_by_url(su_home_t *home,
2691 tp_name_t *tpn,
2692 char const **scheme,
2693 char const **port,
2694 url_string_t const *us)
2695{
2696 url_t url[1];
2697 isize_t n;
2698 char *b;
2699
2700 n = url_xtra(us->us_url);
2701 b = su_alloc(home, n);
2702
2703 if (b == NULL((void*)0) || url_dup(b, n, url, us->us_url) < 0) {
2704 su_free(home, b);
2705 return -1;
2706 }
2707
2708 if (url->url_type != url_sip &&
2709 url->url_type != url_urn &&
2710 url->url_type != url_sips &&
2711 url->url_type != url_im &&
2712 url->url_type != url_pres) {
2713 su_free(home, b);
2714 return -1;
2715 }
2716
2717 SU_DEBUG_7(("nta: selecting scheme %s\n", url->url_scheme))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 2717, "nta: selecting scheme %s\n", url->url_scheme)) : (
void)0)
;
2718
2719 *scheme = url->url_scheme;
2720
2721 tpn->tpn_proto = NULL((void*)0);
2722 tpn->tpn_canon = url->url_host;
2723 tpn->tpn_host = url->url_host;
2724
2725 if (url->url_params) {
2726 for (b = (char *)url->url_params; b[0]; b += n) {
2727 n = strcspn(b, ";");
2728
2729 if (n > 10 && su_casenmatch(b, "transport=", 10))
2730 tpn->tpn_proto = b + 10;
2731 else if (n > 5 && su_casenmatch(b, "comp=", 5))
2732 tpn->tpn_comp = b + 5;
2733 else if (n > 6 && su_casenmatch(b, "maddr=", 6))
2734 tpn->tpn_host = b + 6;
2735
2736 if (b[n])
2737 b[n++] = '\0';
2738 }
2739 }
2740
2741 if ((*port = url->url_port))
2742 tpn->tpn_port = url->url_port;
2743
2744 tpn->tpn_ident = NULL((void*)0);
2745
2746 if (tpn->tpn_proto) {
2747 if (su_casematch(url->url_scheme, "sips") && su_casematch(tpn->tpn_proto, "ws")) {
2748 tpn->tpn_proto = "wss";
2749 }
2750 return 1;
2751 }
2752
2753 if (su_casematch(url->url_scheme, "sips"))
2754 tpn->tpn_proto = "tls";
2755 else
2756 tpn->tpn_proto = "*";
2757
2758 return 0;
2759}
2760
2761/** Handle transport errors. */
2762static
2763void agent_tp_error(nta_agent_t *agent,
2764 tport_t *tport,
2765 int errcode,
2766 char const *remote)
2767{
2768 su_llog(nta_log, 1,_su_llog(nta_log, 1, "nta.c", (const char *)__func__, 2771, "nta_agent: tport: %s%s%s\n"
, remote ? remote : "", remote ? ": " : "", su_strerror(errcode
))
2769 "nta_agent: tport: %s%s%s\n",_su_llog(nta_log, 1, "nta.c", (const char *)__func__, 2771, "nta_agent: tport: %s%s%s\n"
, remote ? remote : "", remote ? ": " : "", su_strerror(errcode
))
2770 remote ? remote : "", remote ? ": " : "",_su_llog(nta_log, 1, "nta.c", (const char *)__func__, 2771, "nta_agent: tport: %s%s%s\n"
, remote ? remote : "", remote ? ": " : "", su_strerror(errcode
))
2771 su_strerror(errcode))_su_llog(nta_log, 1, "nta.c", (const char *)__func__, 2771, "nta_agent: tport: %s%s%s\n"
, remote ? remote : "", remote ? ": " : "", su_strerror(errcode
))
;
2772
2773 if (agent->sa_error_tport) {
2774 agent->sa_error_tport(agent->sa_error_magic, agent, tport);
2775 }
2776}
2777
2778/** Handle updated transport addresses */
2779static void agent_update_tport(nta_agent_t *self, tport_t *tport)
2780{
2781 /* Initialize local Vias first */
2782 agent_init_via(self, tport_primaries(self->sa_tports), 0);
2783
2784 if (self->sa_update_tport) {
2785 self->sa_update_tport(self->sa_update_magic, self);
2786 }
2787 else {
2788 /* XXX - we should do something else? */
2789 SU_DEBUG_3(("%s(%p): %s\n", "nta", (void *)self,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 2790, "%s(%p): %s\n", "nta", (void *)self, "transport address updated"
)) : (void)0)
2790 "transport address updated"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 2790, "%s(%p): %s\n", "nta", (void *)self, "transport address updated"
)) : (void)0)
;
2791 }
2792}
2793
2794/* ====================================================================== */
2795/* 3) Message dispatch */
2796
2797static void agent_recv_request(nta_agent_t *agent,
2798 msg_t *msg,
2799 sip_t *sip,
2800 tport_t *tport);
2801static int agent_check_request_via(nta_agent_t *agent,
2802 msg_t *msg,
2803 sip_t *sip,
2804 sip_via_t *v,
2805 tport_t *tport);
2806static int agent_aliases(nta_agent_t const *, url_t [], tport_t *);
2807static void agent_recv_response(nta_agent_t*, msg_t *, sip_t *,
2808 sip_via_t *, tport_t*);
2809static void agent_recv_garbage(nta_agent_t*, msg_t*, tport_t*);
2810
2811#if HAVE_SOFIA_SRESOLV1
2812static void outgoing_resolve(nta_outgoing_t *orq,
2813 int explicit_transport,
2814 enum nta_res_order_e order);
2815su_inlinestatic inline void outgoing_cancel_resolver(nta_outgoing_t *orq);
2816su_inlinestatic inline void outgoing_destroy_resolver(nta_outgoing_t *orq);
2817static int outgoing_other_destinations(nta_outgoing_t const *orq);
2818static int outgoing_try_another(nta_outgoing_t *orq);
2819#else
2820#define outgoing_other_destinations(orq) (0)
2821#define outgoing_try_another(orq) (0)
2822#endif
2823
2824/** Handle incoming message. */
2825static
2826void agent_recv_message(nta_agent_t *agent,
2827 tport_t *tport,
2828 msg_t *msg,
2829 sip_via_t *tport_via,
2830 su_time_t now)
2831{
2832 sip_t *sip = sip_object(msg);
2833
2834 if (sip && sip->sip_request) {
2835 agent_recv_request(agent, msg, sip, tport);
2836 }
2837 else if (sip && sip->sip_status) {
2838 agent_recv_response(agent, msg, sip, tport_via, tport);
2839 }
2840 else {
2841 agent_recv_garbage(agent, msg, tport);
2842 }
2843}
2844
2845#ifdef HAVE_ZLIB_COMPRESS1
2846int sip_content_encoding_Xflate(msg_t *msg, sip_t *sip, int inflate, int check)
2847{
2848 char const *method_name;
2849 unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0;
2850 int ok = !check;
2851
2852 if (!sip->sip_payload) {
2853 return 0;
2854 }
2855
2856 if (sip->sip_request) {
2857 method_name = sip->sip_request->rq_method_name;
2858 } else if (sip->sip_cseq) {
2859 method_name = sip->sip_cseq->cs_method_name;
2860 } else {
2861 method_name = "Unknown";
2862 }
2863
2864 if (!ok) {
2865 if (sip->sip_content_encoding && sip->sip_content_encoding->k_items) {
2866 const char *val = sip->sip_content_encoding->k_items[0];
2867 if (val && (!strcasecmp(val, "gzip") || !strcasecmp(val, "deflate"))) {
2868 ok = 1;
2869 }
2870 }
2871 }
2872
2873 if (ok) {
2874 unsigned long n = 0;
2875 void *decoded = NULL((void*)0);
2876 const char *id = "N/A";
2877 const char *orig_payload = sip->sip_payload->pl_data;
2878
2879 n = sip->sip_payload->pl_len * 10;
2880
2881 decoded = su_alloc(msg_home(msg)((su_home_t*)(msg)), n);
2882 assert(decoded)((void) sizeof ((decoded) ? 1 : 0), __extension__ ({ if (decoded
) ; else __assert_fail ("decoded", "nta.c", 2882, __extension__
__PRETTY_FUNCTION__); }))
;
2883
2884 if (inflate) {
2885 uncompress(decoded, &n, (void *)sip->sip_payload->pl_data, (unsigned long)sip->sip_payload->pl_len);
2886 } else {
2887 compress(decoded, &n, (void *)sip->sip_payload->pl_data, (unsigned long)sip->sip_payload->pl_len);
2888 }
2889
2890 sip->sip_payload = sip_payload_create(msg_home(msg)((su_home_t*)(msg)), decoded, n);
2891 sip->sip_content_encoding = sip_content_encoding_make(msg_home(msg)((su_home_t*)(msg)), "deflate");
2892
2893 if (sip->sip_call_id) {
2894 id = sip->sip_call_id->i_id;
2895 }
2896
2897 if (inflate) {
2898 SU_DEBUG_1(("nta: %s (%u) (%s) Inflating compressed body:\n%s\n", method_name, cseq, id, (char *)decoded))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2898, "nta: %s (%u) (%s) Inflating compressed body:\n%s\n",
method_name, cseq, id, (char *)decoded)) : (void)0)
;
2899 } else {
2900 SU_DEBUG_1(("nta: %s (%u) (%s) Deflating compressed body:\n%s\n", method_name, cseq, id, orig_payload))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 2900, "nta: %s (%u) (%s) Deflating compressed body:\n%s\n",
method_name, cseq, id, orig_payload)) : (void)0)
;
2901 }
2902
2903 return 1;
2904 }
2905
2906 return 0;
2907}
2908#endif
2909
2910/** @internal Handle incoming requests. */
2911static
2912void agent_recv_request(nta_agent_t *agent,
2913 msg_t *msg,
2914 sip_t *sip,
2915 tport_t *tport)
2916{
2917 nta_leg_t *leg;
2918 nta_incoming_t *irq, *merge = NULL((void*)0), *ack = NULL((void*)0), *cancel = NULL((void*)0);
2919 sip_method_t method = sip->sip_request->rq_method;
2920 char const *method_name = sip->sip_request->rq_method_name;
2921 url_t url[1];
2922 unsigned cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0;
2923 int insane, errors, stream;
2924 unsigned compressed = 0;
2925 su_duration_t sa_load_elapsed_ms = su_duration(su_now(), agent->sa_load->last_time);
2926
2927 agent->sa_stats->as_recv_msg++;
2928 agent->sa_stats->as_recv_request++;
2929
2930 if (agent->sa_load->requests_per_second == 0) agent->sa_load->requests_per_second = 1;
2931
2932 if (sa_load_elapsed_ms >= 1000) {
2933 if (agent->sa_load->as_recv_request_last) {
2934 agent->sa_load->requests_per_second = ((agent->sa_stats->as_recv_request - agent->sa_load->as_recv_request_last) * 1000) / sa_load_elapsed_ms;
2935 }
2936
2937 /** Update */
2938 agent->sa_load->last_time = su_now();
2939 agent->sa_load->as_recv_request_last = agent->sa_stats->as_recv_request;
2940
2941 if (agent->sa_max_recv_requests_per_second && agent->sa_load->requests_per_second > agent->sa_max_recv_requests_per_second) {
2942 SU_DEBUG_5(("SIP flood: Dropped %u incoming SIP messages, %u message / sec (of %u allowed)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2943, "SIP flood: Dropped %u incoming SIP messages, %u message / sec (of %u allowed)\n"
, agent->sa_stats->as_drop_request + 1, agent->sa_load
->requests_per_second, agent->sa_max_recv_requests_per_second
)) : (void)0)
2943 agent->sa_stats->as_drop_request + 1, agent->sa_load->requests_per_second, agent->sa_max_recv_requests_per_second))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2943, "SIP flood: Dropped %u incoming SIP messages, %u message / sec (of %u allowed)\n"
, agent->sa_stats->as_drop_request + 1, agent->sa_load
->requests_per_second, agent->sa_max_recv_requests_per_second
)) : (void)0)
;
2944 }
2945
2946 } else if (sa_load_elapsed_ms == -SU_DURATION_MAXSU_DURATION_MAX) {
2947 /** Initialize */
2948 agent->sa_load->last_time = su_now();
2949 agent->sa_load->as_recv_request_last = agent->sa_stats->as_recv_request;
2950 }
2951
2952 if (agent->sa_max_recv_requests_per_second && agent->sa_load->requests_per_second > agent->sa_max_recv_requests_per_second) {
2953 agent->sa_stats->as_drop_request++;
2954 msg_destroy(msg);
2955 return;
2956 }
2957
2958 SU_DEBUG_5(("nta: received %s " URL_PRINT_FORMAT " %s (CSeq %u) (load: %u rps)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2961, "nta: received %s " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" %s (CSeq %u) (load: %u rps)\n", method_name, (sip->sip_request
->rq_url)->url_scheme ? (sip->sip_request->rq_url
)->url_scheme : "", (sip->sip_request->rq_url)->url_type
!= url_any && (sip->sip_request->rq_url)->url_scheme
&& (sip->sip_request->rq_url)->url_scheme[0
] ? ":" : "", (sip->sip_request->rq_url)->url_root &&
((sip->sip_request->rq_url)->url_host || (sip->sip_request
->rq_url)->url_user) ? "//" : "", (sip->sip_request->
rq_url)->url_user ? (sip->sip_request->rq_url)->url_user
: "", (sip->sip_request->rq_url)->url_user &&
(sip->sip_request->rq_url)->url_password ? ":" : ""
, (sip->sip_request->rq_url)->url_user && (sip
->sip_request->rq_url)->url_password ? (sip->sip_request
->rq_url)->url_password : "", (sip->sip_request->
rq_url)->url_user && (sip->sip_request->rq_url
)->url_host ? "@" : "", (sip->sip_request->rq_url)->
url_host ? (sip->sip_request->rq_url)->url_host : ""
, (sip->sip_request->rq_url)->url_host && (sip
->sip_request->rq_url)->url_port ? ":" : "", (sip->
sip_request->rq_url)->url_host && (sip->sip_request
->rq_url)->url_port ? (sip->sip_request->rq_url)->
url_port : "", (sip->sip_request->rq_url)->url_root &&
(sip->sip_request->rq_url)->url_path ? "/" : "", (sip
->sip_request->rq_url)->url_path ? (sip->sip_request
->rq_url)->url_path : "", (sip->sip_request->rq_url
)->url_params ? ";" : "", (sip->sip_request->rq_url)
->url_params ? (sip->sip_request->rq_url)->url_params
: "", (sip->sip_request->rq_url)->url_headers ? "?"
: "", (sip->sip_request->rq_url)->url_headers ? (sip
->sip_request->rq_url)->url_headers : "", (sip->sip_request
->rq_url)->url_fragment ? "#" : "", (sip->sip_request
->rq_url)->url_fragment ? (sip->sip_request->rq_url
)->url_fragment : "", sip->sip_request->rq_version, cseq
, agent->sa_load->requests_per_second)) : (void)0)
2959 method_name,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2961, "nta: received %s " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" %s (CSeq %u) (load: %u rps)\n", method_name, (sip->sip_request
->rq_url)->url_scheme ? (sip->sip_request->rq_url
)->url_scheme : "", (sip->sip_request->rq_url)->url_type
!= url_any && (sip->sip_request->rq_url)->url_scheme
&& (sip->sip_request->rq_url)->url_scheme[0
] ? ":" : "", (sip->sip_request->rq_url)->url_root &&
((sip->sip_request->rq_url)->url_host || (sip->sip_request
->rq_url)->url_user) ? "//" : "", (sip->sip_request->
rq_url)->url_user ? (sip->sip_request->rq_url)->url_user
: "", (sip->sip_request->rq_url)->url_user &&
(sip->sip_request->rq_url)->url_password ? ":" : ""
, (sip->sip_request->rq_url)->url_user && (sip
->sip_request->rq_url)->url_password ? (sip->sip_request
->rq_url)->url_password : "", (sip->sip_request->
rq_url)->url_user && (sip->sip_request->rq_url
)->url_host ? "@" : "", (sip->sip_request->rq_url)->
url_host ? (sip->sip_request->rq_url)->url_host : ""
, (sip->sip_request->rq_url)->url_host && (sip
->sip_request->rq_url)->url_port ? ":" : "", (sip->
sip_request->rq_url)->url_host && (sip->sip_request
->rq_url)->url_port ? (sip->sip_request->rq_url)->
url_port : "", (sip->sip_request->rq_url)->url_root &&
(sip->sip_request->rq_url)->url_path ? "/" : "", (sip
->sip_request->rq_url)->url_path ? (sip->sip_request
->rq_url)->url_path : "", (sip->sip_request->rq_url
)->url_params ? ";" : "", (sip->sip_request->rq_url)
->url_params ? (sip->sip_request->rq_url)->url_params
: "", (sip->sip_request->rq_url)->url_headers ? "?"
: "", (sip->sip_request->rq_url)->url_headers ? (sip
->sip_request->rq_url)->url_headers : "", (sip->sip_request
->rq_url)->url_fragment ? "#" : "", (sip->sip_request
->rq_url)->url_fragment ? (sip->sip_request->rq_url
)->url_fragment : "", sip->sip_request->rq_version, cseq
, agent->sa_load->requests_per_second)) : (void)0)
2960 URL_PRINT_ARGS(sip->sip_request->rq_url),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2961, "nta: received %s " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" %s (CSeq %u) (load: %u rps)\n", method_name, (sip->sip_request
->rq_url)->url_scheme ? (sip->sip_request->rq_url
)->url_scheme : "", (sip->sip_request->rq_url)->url_type
!= url_any && (sip->sip_request->rq_url)->url_scheme
&& (sip->sip_request->rq_url)->url_scheme[0
] ? ":" : "", (sip->sip_request->rq_url)->url_root &&
((sip->sip_request->rq_url)->url_host || (sip->sip_request
->rq_url)->url_user) ? "//" : "", (sip->sip_request->
rq_url)->url_user ? (sip->sip_request->rq_url)->url_user
: "", (sip->sip_request->rq_url)->url_user &&
(sip->sip_request->rq_url)->url_password ? ":" : ""
, (sip->sip_request->rq_url)->url_user && (sip
->sip_request->rq_url)->url_password ? (sip->sip_request
->rq_url)->url_password : "", (sip->sip_request->
rq_url)->url_user && (sip->sip_request->rq_url
)->url_host ? "@" : "", (sip->sip_request->rq_url)->
url_host ? (sip->sip_request->rq_url)->url_host : ""
, (sip->sip_request->rq_url)->url_host && (sip
->sip_request->rq_url)->url_port ? ":" : "", (sip->
sip_request->rq_url)->url_host && (sip->sip_request
->rq_url)->url_port ? (sip->sip_request->rq_url)->
url_port : "", (sip->sip_request->rq_url)->url_root &&
(sip->sip_request->rq_url)->url_path ? "/" : "", (sip
->sip_request->rq_url)->url_path ? (sip->sip_request
->rq_url)->url_path : "", (sip->sip_request->rq_url
)->url_params ? ";" : "", (sip->sip_request->rq_url)
->url_params ? (sip->sip_request->rq_url)->url_params
: "", (sip->sip_request->rq_url)->url_headers ? "?"
: "", (sip->sip_request->rq_url)->url_headers ? (sip
->sip_request->rq_url)->url_headers : "", (sip->sip_request
->rq_url)->url_fragment ? "#" : "", (sip->sip_request
->rq_url)->url_fragment ? (sip->sip_request->rq_url
)->url_fragment : "", sip->sip_request->rq_version, cseq
, agent->sa_load->requests_per_second)) : (void)0)
2961 sip->sip_request->rq_version, cseq, agent->sa_load->requests_per_second))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2961, "nta: received %s " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" %s (CSeq %u) (load: %u rps)\n", method_name, (sip->sip_request
->rq_url)->url_scheme ? (sip->sip_request->rq_url
)->url_scheme : "", (sip->sip_request->rq_url)->url_type
!= url_any && (sip->sip_request->rq_url)->url_scheme
&& (sip->sip_request->rq_url)->url_scheme[0
] ? ":" : "", (sip->sip_request->rq_url)->url_root &&
((sip->sip_request->rq_url)->url_host || (sip->sip_request
->rq_url)->url_user) ? "//" : "", (sip->sip_request->
rq_url)->url_user ? (sip->sip_request->rq_url)->url_user
: "", (sip->sip_request->rq_url)->url_user &&
(sip->sip_request->rq_url)->url_password ? ":" : ""
, (sip->sip_request->rq_url)->url_user && (sip
->sip_request->rq_url)->url_password ? (sip->sip_request
->rq_url)->url_password : "", (sip->sip_request->
rq_url)->url_user && (sip->sip_request->rq_url
)->url_host ? "@" : "", (sip->sip_request->rq_url)->
url_host ? (sip->sip_request->rq_url)->url_host : ""
, (sip->sip_request->rq_url)->url_host && (sip
->sip_request->rq_url)->url_port ? ":" : "", (sip->
sip_request->rq_url)->url_host && (sip->sip_request
->rq_url)->url_port ? (sip->sip_request->rq_url)->
url_port : "", (sip->sip_request->rq_url)->url_root &&
(sip->sip_request->rq_url)->url_path ? "/" : "", (sip
->sip_request->rq_url)->url_path ? (sip->sip_request
->rq_url)->url_path : "", (sip->sip_request->rq_url
)->url_params ? ";" : "", (sip->sip_request->rq_url)
->url_params ? (sip->sip_request->rq_url)->url_params
: "", (sip->sip_request->rq_url)->url_headers ? "?"
: "", (sip->sip_request->rq_url)->url_headers ? (sip
->sip_request->rq_url)->url_headers : "", (sip->sip_request
->rq_url)->url_fragment ? "#" : "", (sip->sip_request
->rq_url)->url_fragment ? (sip->sip_request->rq_url
)->url_fragment : "", sip->sip_request->rq_version, cseq
, agent->sa_load->requests_per_second)) : (void)0)
;
2962
2963 if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
2964 if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
2965 SU_DEBUG_5(("nta: %s (%u) is %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2966, "nta: %s (%u) is %s\n", method_name, cseq, "dropped simulating packet loss"
)) : (void)0)
2966 method_name, cseq, "dropped simulating packet loss"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2966, "nta: %s (%u) is %s\n", method_name, cseq, "dropped simulating packet loss"
)) : (void)0)
;
2967 agent->sa_stats->as_drop_request++;
2968 msg_destroy(msg);
2969 return;
2970 }
2971 }
2972
2973 stream = tport_is_stream(tport);
2974
2975 /* Try to use compression on reverse direction if @Via has comp=sigcomp */
2976 if (stream &&
2977 sip->sip_via && sip->sip_via->v_comp &&
2978 tport_can_send_sigcomp(tport) &&
2979 tport_name(tport)->tpn_comp == NULL((void*)0) &&
2980 tport_has_compression(tport_parent(tport), sip->sip_via->v_comp)) {
2981 tport_set_compression(tport, sip->sip_via->v_comp);
2982 }
2983
2984 if (sip->sip_flags & MSG_FLG_TOOLARGE) {
2985 SU_DEBUG_5(("nta: %s (%u) is %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2986, "nta: %s (%u) is %s\n", method_name, cseq, sip_413_Request_too_large
)) : (void)0)
2986 method_name, cseq, sip_413_Request_too_large))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 2986, "nta: %s (%u) is %s\n", method_name, cseq, sip_413_Request_too_large
)) : (void)0)
;
2987 agent->sa_stats->as_bad_request++;
2988 mreply(agent, NULL((void*)0), SIP_413_REQUEST_TOO_LARGE413, sip_413_Request_too_large, msg,
2989 tport, 1, stream, NULL((void*)0),
2990 TAG_END()(tag_type_t)0, (tag_value_t)0);
2991 return;
2992 }
2993
2994 insane = 0;
2995
2996 if (agent->sa_bad_req_mask != ~0U)
2997 errors = msg_extract_errors(msg) & agent->sa_bad_req_mask;
2998 else
2999 errors = sip->sip_error != NULL((void*)0);
3000
3001 if (errors ||
3002 (sip->sip_flags & MSG_FLG_ERROR) /* Fatal error */ ||
3003 (insane = (sip_sanity_check(sip) < 0))) {
3004 sip_header_t const *h;
3005 char const *badname = NULL((void*)0), *phrase;
3006
3007 agent->sa_stats->as_bad_message++;
3008 agent->sa_stats->as_bad_request++;
3009
3010 if (insane)
3011 SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3012, "nta: %s (%u) %s\n", method_name, cseq, "failed sanity check"
)) : (void)0)
3012 "failed sanity check"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3012, "nta: %s (%u) %s\n", method_name, cseq, "failed sanity check"
)) : (void)0)
;
3013
3014 for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_nextsh_header_next->shn_next) {
3015 char const *bad;
3016
3017 if (h->sh_classsh_common->h_class == sip_error_class)
3018 bad = h->sh_error->er_name;
3019 else
3020 bad = h->sh_classsh_common->h_class->hc_name;
3021
3022 if (bad)
3023 SU_DEBUG_5(("nta: %s has bad %s header\n", method_name, bad))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3023, "nta: %s has bad %s header\n", method_name, bad)) : (
void)0)
;
3024
3025 if (!badname)
3026 badname = bad;
3027 }
3028
3029 if (sip->sip_via && method != sip_method_ack) {
3030 msg_t *reply = nta_msg_create(agent, 0);
3031
3032 agent_check_request_via(agent, msg, sip, sip->sip_via, tport);
3033
3034 if (badname && reply)
3035 phrase = su_sprintf(msg_home(reply)((su_home_t*)(reply)), "Bad %s Header", badname);
3036 else
3037 phrase = sip_400_Bad_request;
3038
3039 SU_DEBUG_5(("nta: %s (%u) is %s\n", method_name, cseq, phrase))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3039, "nta: %s (%u) is %s\n", method_name, cseq, phrase)) :
(void)0)
;
3040
3041 mreply(agent, reply, 400, phrase, msg,
3042 tport, 1, stream, NULL((void*)0),
3043 TAG_END()(tag_type_t)0, (tag_value_t)0);
3044 }
3045 else {
3046 msg_destroy(msg);
3047 if (stream) /* Send FIN */
3048 tport_shutdown(tport, 1);
3049 }
3050
3051 return;
3052 }
3053
3054 if (!su_casematch(sip->sip_request->rq_version, sip_version_2_0)) {
3055 agent->sa_stats->as_bad_request++;
3056 agent->sa_stats->as_bad_message++;
3057
3058 SU_DEBUG_5(("nta: bad version %s for %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3059, "nta: bad version %s for %s (%u)\n", sip->sip_request
->rq_version, method_name, cseq)) : (void)0)
3059 sip->sip_request->rq_version, method_name, cseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3059, "nta: bad version %s for %s (%u)\n", sip->sip_request
->rq_version, method_name, cseq)) : (void)0)
;
3060
3061 mreply(agent, NULL((void*)0), SIP_505_VERSION_NOT_SUPPORTED505, sip_505_Version_not_supported, msg,
3062 tport, 0, stream, NULL((void*)0),
3063 TAG_END()(tag_type_t)0, (tag_value_t)0);
3064
3065 return;
3066 }
3067
3068 if (agent_check_request_via(agent, msg, sip, sip->sip_via, tport) < 0) {
3069 agent->sa_stats->as_bad_message++;
3070 agent->sa_stats->as_bad_request++;
3071 SU_DEBUG_5(("nta: %s (%u) %s\n", method_name, cseq, "has invalid Via"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3071, "nta: %s (%u) %s\n", method_name, cseq, "has invalid Via"
)) : (void)0)
;
3072 msg_destroy(msg);
3073 return;
3074 }
3075
3076#ifdef HAVE_ZLIB_COMPRESS1
3077 compressed = sip_content_encoding_Xflate(msg, sip, 1, 1);
3078#endif
3079
3080 /* First, try existing incoming requests */
3081 irq = incoming_find(agent, sip, sip->sip_via,
3082 agent->sa_merge_482 &&
3083 !sip->sip_to->a_tag &&
3084 method != sip_method_ack
3085 ? &merge
3086 : NULL((void*)0),
3087 method == sip_method_ack ? &ack : NULL((void*)0),
3088 method == sip_method_cancel ? &cancel : NULL((void*)0));
3089
3090 if (irq) {
3091 /* Match - this is a retransmission */
3092 SU_DEBUG_5(("nta: %s (%u) going to existing %s transaction\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3093, "nta: %s (%u) going to existing %s transaction\n", method_name
, cseq, irq->irq_rq->rq_method_name)) : (void)0)
3093 method_name, cseq, irq->irq_rq->rq_method_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3093, "nta: %s (%u) going to existing %s transaction\n", method_name
, cseq, irq->irq_rq->rq_method_name)) : (void)0)
;
3094 if (incoming_recv(irq, msg, sip, tport) >= 0)
3095 return;
3096 }
3097 else if (ack) {
3098 SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3100, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq
)) : (void)0)
3099 method_name, cseq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3100, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq
)) : (void)0)
3100 ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3100, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq
)) : (void)0)
;
3101 if (incoming_ack(ack, msg, sip, tport) >= 0)
3102 return;
3103 }
3104 else if (cancel) {
3105 SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3107, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, cancel->irq_cseq->cs_method_name, cancel->irq_cseq
->cs_seq)) : (void)0)
3106 method_name, cseq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3107, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, cancel->irq_cseq->cs_method_name, cancel->irq_cseq
->cs_seq)) : (void)0)
3107 cancel->irq_cseq->cs_method_name, cancel->irq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3107, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, cancel->irq_cseq->cs_method_name, cancel->irq_cseq
->cs_seq)) : (void)0)
;
3108 if (incoming_cancel(cancel, msg, sip, tport) >= 0)
3109 return;
3110 }
3111 else if (merge) {
3112 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3113, "nta: %s (%u) %s\n", method_name, cseq, "is a merged request"
)) : (void)0)
3113 method_name, cseq, "is a merged request"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3113, "nta: %s (%u) %s\n", method_name, cseq, "is a merged request"
)) : (void)0)
;
3114 request_merge(agent, msg, sip, tport, merge->irq_tag);
3115 return;
3116 }
3117
3118 if (method == sip_method_prack && sip->sip_rack) {
3119 nta_reliable_t *rel = reliable_find(agent, sip);
3120 if (rel) {
3121 SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3124, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, rel->rel_irq->irq_cseq->cs_method_name, rel->rel_irq
->irq_cseq->cs_seq)) : (void)0)
3122 method_name, cseq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3124, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, rel->rel_irq->irq_cseq->cs_method_name, rel->rel_irq
->irq_cseq->cs_seq)) : (void)0)
3123 rel->rel_irq->irq_cseq->cs_method_name,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3124, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, rel->rel_irq->irq_cseq->cs_method_name, rel->rel_irq
->irq_cseq->cs_seq)) : (void)0)
3124 rel->rel_irq->irq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3124, "nta: %s (%u) is going to %s (%u)\n", method_name, cseq
, rel->rel_irq->irq_cseq->cs_method_name, rel->rel_irq
->irq_cseq->cs_seq)) : (void)0)
;
3125 reliable_recv(rel, msg, sip, tport);
3126 return;
3127 }
3128 }
3129
3130 *url = *sip->sip_request->rq_url;
3131 url->url_params = NULL((void*)0);
3132 agent_aliases(agent, url, tport); /* canonize urls */
3133
3134 if (method != sip_method_subscribe && (leg = leg_find(agent,
3135 method_name, url,
3136 sip->sip_call_id,
3137 sip->sip_from->a_tag,
3138 sip->sip_to->a_tag))) {
3139 /* Try existing dialog */
3140 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3141, "nta: %s (%u) %s\n", method_name, cseq, "going to existing leg"
)) : (void)0)
3141 method_name, cseq, "going to existing leg"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3141, "nta: %s (%u) %s\n", method_name, cseq, "going to existing leg"
)) : (void)0)
;
3142 leg->leg_compressed = compressed;
3143 leg_recv(leg, msg, sip, tport);
3144 return;
3145 }
3146 else if (!agent->sa_is_stateless &&
3147 (leg = dst_find(agent, url, method_name))) {
3148 /* Dialogless legs - let application process transactions statefully */
3149 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3150, "nta: %s (%u) %s\n", method_name, cseq, "going to a dialogless leg"
)) : (void)0)
3150 method_name, cseq, "going to a dialogless leg"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3150, "nta: %s (%u) %s\n", method_name, cseq, "going to a dialogless leg"
)) : (void)0)
;
3151 leg->leg_compressed = compressed;
3152 leg_recv(leg, msg, sip, tport);
3153 }
3154 else if (!agent->sa_is_stateless && (leg = agent->sa_default_leg)) {
3155 if (method == sip_method_invite &&
3156 agent->sa_in.proceeding->q_length >= agent->sa_max_proceeding) {
3157 SU_DEBUG_5(("nta: proceeding queue full for %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3158, "nta: proceeding queue full for %s (%u)\n", method_name
, cseq)) : (void)0)
3158 method_name, cseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3158, "nta: proceeding queue full for %s (%u)\n", method_name
, cseq)) : (void)0)
;
3159 mreply(agent, NULL((void*)0), SIP_503_SERVICE_UNAVAILABLE503, sip_503_Service_unavailable, msg,
3160 tport, 0, 0, NULL((void*)0),
3161 TAG_END()(tag_type_t)0, (tag_value_t)0);
3162 return;
3163 }
3164 else {
3165 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3166, "nta: %s (%u) %s\n", method_name, cseq, "going to a default leg"
)) : (void)0)
3166 method_name, cseq, "going to a default leg"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3166, "nta: %s (%u) %s\n", method_name, cseq, "going to a default leg"
)) : (void)0)
;
3167 leg->leg_compressed = compressed;
3168 leg_recv(leg, msg, sip, tport);
3169 }
3170 }
3171 else if (agent->sa_callback) {
3172 /* Stateless processing for request */
3173 agent->sa_stats->as_trless_request++;
3174 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3175, "nta: %s (%u) %s\n", method_name, cseq, "to message callback"
)) : (void)0)
3175 method_name, cseq, "to message callback"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3175, "nta: %s (%u) %s\n", method_name, cseq, "to message callback"
)) : (void)0)
;
3176 (void)agent->sa_callback(agent->sa_magic, agent, msg, sip);
3177 }
3178 else {
3179 agent->sa_stats->as_trless_request++;
3180 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3182, "nta: %s (%u) %s\n", method_name, cseq, "not processed by application: returning 501"
)) : (void)0)
3181 method_name, cseq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3182, "nta: %s (%u) %s\n", method_name, cseq, "not processed by application: returning 501"
)) : (void)0)
3182 "not processed by application: returning 501"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3182, "nta: %s (%u) %s\n", method_name, cseq, "not processed by application: returning 501"
)) : (void)0)
;
3183 if (method != sip_method_ack)
3184 mreply(agent, NULL((void*)0), SIP_501_NOT_IMPLEMENTED501, sip_501_Not_implemented, msg,
3185 tport, 0, 0, NULL((void*)0),
3186 TAG_END()(tag_type_t)0, (tag_value_t)0);
3187 else
3188 msg_destroy(msg);
3189 }
3190}
3191
3192/** Check @Via header.
3193 *
3194 */
3195static
3196int agent_check_request_via(nta_agent_t *agent,
3197 msg_t *msg,
3198 sip_t *sip,
3199 sip_via_t *v,
3200 tport_t *tport)
3201{
3202 enum { receivedlen = sizeof("received=") - 1 };
3203 char received[receivedlen + TPORT_HOSTPORTSIZE(55)];
3204 char *hostport = received + receivedlen;
3205 char const *rport;
3206 su_sockaddr_t const *from;
3207 sip_via_t const *tpv = agent_tport_via(tport);
3208
3209 assert(tport)((void) sizeof ((tport) ? 1 : 0), __extension__ ({ if (tport)
; else __assert_fail ("tport", "nta.c", 3209, __extension__ __PRETTY_FUNCTION__
); }))
; assert(msg)((void) sizeof ((msg) ? 1 : 0), __extension__ ({ if (msg) ; else
__assert_fail ("msg", "nta.c", 3209, __extension__ __PRETTY_FUNCTION__
); }))
; assert(sip)((void) sizeof ((sip) ? 1 : 0), __extension__ ({ if (sip) ; else
__assert_fail ("sip", "nta.c", 3209, __extension__ __PRETTY_FUNCTION__
); }))
;
3210 assert(sip->sip_request)((void) sizeof ((sip->sip_request) ? 1 : 0), __extension__
({ if (sip->sip_request) ; else __assert_fail ("sip->sip_request"
, "nta.c", 3210, __extension__ __PRETTY_FUNCTION__); }))
; assert(tpv)((void) sizeof ((tpv) ? 1 : 0), __extension__ ({ if (tpv) ; else
__assert_fail ("tpv", "nta.c", 3210, __extension__ __PRETTY_FUNCTION__
); }))
;
3211
3212 from = msg_addr(msg);
3213
3214 if (v == NULL((void*)0)) {
3215 /* Make up a via line */
3216 v = sip_via_format(msg_home(msg)((su_home_t*)(msg)), "SIP/2.0/%s %s",
3217 tport_name(tport)->tpn_proto,
3218 tport_hostport(hostport, TPORT_HOSTPORTSIZE(55), from, 1));
3219 msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)v);
3220
3221 return v ? 0 : -1;
3222 }
3223
3224 if (!su_strmatch(v->v_protocol, tpv->v_protocol)) {
3225 tport_hostport(hostport, TPORT_HOSTPORTSIZE(55), from, 1);
3226 SU_DEBUG_1(("nta: Via check: invalid transport \"%s\" from %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 3227, "nta: Via check: invalid transport \"%s\" from %s\n",
v->v_protocol, hostport)) : (void)0)
3227 v->v_protocol, hostport))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 3227, "nta: Via check: invalid transport \"%s\" from %s\n",
v->v_protocol, hostport)) : (void)0)
;
3228 return -1;
3229 }
3230
3231 if (v->v_received) {
3232 /* Nasty, nasty */
3233 tport_hostport(hostport, TPORT_HOSTPORTSIZE(55), from, 1);
3234 SU_DEBUG_1(("nta: Via check: extra received=%s from %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 3235, "nta: Via check: extra received=%s from %s\n", v->
v_received, hostport)) : (void)0)
3235 v->v_received, hostport))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 3235, "nta: Via check: extra received=%s from %s\n", v->
v_received, hostport)) : (void)0)
;
3236 msg_header_remove_param(v->v_common, "received");
3237 }
3238
3239 if (!tport_hostport(hostport, TPORT_HOSTPORTSIZE(55), from, 0))
3240 return -1;
3241
3242 if (!su_casematch(hostport, v->v_host)) {
3243 size_t rlen;
3244 /* Add the "received" field */
3245 memcpy(received, "received=", receivedlen);
3246
3247 if (hostport[0] == '[') {
3248 rlen = strlen(hostport + 1) - 1;
3249 memmove(hostport, hostport + 1, rlen);
3250 hostport[rlen] = '\0';
3251 }
3252
3253 msg_header_replace_param(msg_home(msg)((su_home_t*)(msg)), v->v_common,
3254 su_strdup(msg_home(msg)((su_home_t*)(msg)), received));
3255 SU_DEBUG_5(("nta: Via check: %s\n", received))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3255, "nta: Via check: %s\n", received)) : (void)0)
;
3256 }
3257
3258 if (!agent->sa_server_rport) {
3259 /*Xyzzy*/;
3260 }
3261 else if (v->v_rport) {
3262 rport = su_sprintf(msg_home(msg)((su_home_t*)(msg)), "rport=%u", ntohs(from->su_portsu_sin.sin_port));
3263 msg_header_replace_param(msg_home(msg)((su_home_t*)(msg)), v->v_common, rport);
3264 }
3265 else if (tport_is_tcp(tport)) {
3266 rport = su_sprintf(msg_home(msg)((su_home_t*)(msg)), "rport=%u", ntohs(from->su_portsu_sin.sin_port));
3267 msg_header_replace_param(msg_home(msg)((su_home_t*)(msg)), v->v_common, rport);
3268 }
3269 else if (agent->sa_server_rport == 2 ||
3270 (agent->sa_server_rport == 3 && sip && sip->sip_user_agent &&
3271 sip->sip_user_agent->g_string &&
3272 (!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) ||
3273 !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20) ||
3274 !strncasecmp(sip->sip_user_agent->g_string, "ADTRAN_Total_Access", 19)))) {
3275 rport = su_sprintf(msg_home(msg)((su_home_t*)(msg)), "rport=%u", ntohs(from->su_portsu_sin.sin_port));
3276 msg_header_replace_param(msg_home(msg)((su_home_t*)(msg)), v->v_common, rport);
3277 }
3278
3279 return 0;
3280}
3281
3282/** @internal Handle aliases of local node.
3283 *
3284 * Return true if @a url is modified.
3285 */
3286static
3287int agent_aliases(nta_agent_t const *agent, url_t url[], tport_t *tport)
3288{
3289 sip_contact_t *m;
3290 sip_via_t const *lv;
3291 char const *tport_port = "";
3292
3293 if (!url->url_host)
3294 return 0;
3295
3296 if (tport)
3297 tport_port = tport_name(tport)->tpn_port;
3298
3299 assert(tport_port)((void) sizeof ((tport_port) ? 1 : 0), __extension__ ({ if (tport_port
) ; else __assert_fail ("tport_port", "nta.c", 3299, __extension__
__PRETTY_FUNCTION__); }))
;
3300
3301 for (m = agent->sa_aliases ? agent->sa_aliases : agent->sa_contact;
3302 m;
3303 m = m->m_next) {
3304 if (url->url_type != m->m_url->url_type)
3305 continue;
3306
3307 if (host_cmp(url->url_host, m->m_url->url_host))
3308 continue;
3309
3310 if (url->url_port == NULL((void*)0))
3311 break;
3312
3313 if (m->m_url->url_port) {
3314 if (strcmp(url->url_port, m->m_url->url_port))
3315 continue;
3316 } else {
3317 if (strcmp(url->url_port, tport_port))
3318 continue;
3319 }
3320
3321 break;
3322 }
3323
3324 if (!m)
3325 return 0;
3326
3327 SU_DEBUG_7(("nta: canonizing " URL_PRINT_FORMAT " with %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 3329, "nta: canonizing " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" with %s\n", (url)->url_scheme ? (url)->url_scheme : ""
, (url)->url_type != url_any && (url)->url_scheme
&& (url)->url_scheme[0] ? ":" : "", (url)->url_root
&& ((url)->url_host || (url)->url_user) ? "//"
: "", (url)->url_user ? (url)->url_user : "", (url)->
url_user && (url)->url_password ? ":" : "", (url)->
url_user && (url)->url_password ? (url)->url_password
: "", (url)->url_user && (url)->url_host ? "@"
: "", (url)->url_host ? (url)->url_host : "", (url)->
url_host && (url)->url_port ? ":" : "", (url)->
url_host && (url)->url_port ? (url)->url_port :
"", (url)->url_root && (url)->url_path ? "/" :
"", (url)->url_path ? (url)->url_path : "", (url)->
url_params ? ";" : "", (url)->url_params ? (url)->url_params
: "", (url)->url_headers ? "?" : "", (url)->url_headers
? (url)->url_headers : "", (url)->url_fragment ? "#" :
"", (url)->url_fragment ? (url)->url_fragment : "", agent
->sa_aliases ? "aliases" : "contact")) : (void)0)
3328 URL_PRINT_ARGS(url),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 3329, "nta: canonizing " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" with %s\n", (url)->url_scheme ? (url)->url_scheme : ""
, (url)->url_type != url_any && (url)->url_scheme
&& (url)->url_scheme[0] ? ":" : "", (url)->url_root
&& ((url)->url_host || (url)->url_user) ? "//"
: "", (url)->url_user ? (url)->url_user : "", (url)->
url_user && (url)->url_password ? ":" : "", (url)->
url_user && (url)->url_password ? (url)->url_password
: "", (url)->url_user && (url)->url_host ? "@"
: "", (url)->url_host ? (url)->url_host : "", (url)->
url_host && (url)->url_port ? ":" : "", (url)->
url_host && (url)->url_port ? (url)->url_port :
"", (url)->url_root && (url)->url_path ? "/" :
"", (url)->url_path ? (url)->url_path : "", (url)->
url_params ? ";" : "", (url)->url_params ? (url)->url_params
: "", (url)->url_headers ? "?" : "", (url)->url_headers
? (url)->url_headers : "", (url)->url_fragment ? "#" :
"", (url)->url_fragment ? (url)->url_fragment : "", agent
->sa_aliases ? "aliases" : "contact")) : (void)0)
3329 agent->sa_aliases ? "aliases" : "contact"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 3329, "nta: canonizing " "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
" with %s\n", (url)->url_scheme ? (url)->url_scheme : ""
, (url)->url_type != url_any && (url)->url_scheme
&& (url)->url_scheme[0] ? ":" : "", (url)->url_root
&& ((url)->url_host || (url)->url_user) ? "//"
: "", (url)->url_user ? (url)->url_user : "", (url)->
url_user && (url)->url_password ? ":" : "", (url)->
url_user && (url)->url_password ? (url)->url_password
: "", (url)->url_user && (url)->url_host ? "@"
: "", (url)->url_host ? (url)->url_host : "", (url)->
url_host && (url)->url_port ? ":" : "", (url)->
url_host && (url)->url_port ? (url)->url_port :
"", (url)->url_root && (url)->url_path ? "/" :
"", (url)->url_path ? (url)->url_path : "", (url)->
url_params ? ";" : "", (url)->url_params ? (url)->url_params
: "", (url)->url_headers ? "?" : "", (url)->url_headers
? (url)->url_headers : "", (url)->url_fragment ? "#" :
"", (url)->url_fragment ? (url)->url_fragment : "", agent
->sa_aliases ? "aliases" : "contact")) : (void)0)
;
3330
3331 url->url_host = "%";
3332
3333 if (agent->sa_aliases) {
3334 url->url_type = agent->sa_aliases->m_url->url_type;
3335 url->url_scheme = agent->sa_aliases->m_url->url_scheme;
3336 url->url_port = agent->sa_aliases->m_url->url_port;
3337 return 1;
3338 }
3339 else {
3340 /* Canonize the request URL port */
3341 if (tport) {
3342 lv = agent_tport_via(tport_parent(tport)); assert(lv)((void) sizeof ((lv) ? 1 : 0), __extension__ ({ if (lv) ; else
__assert_fail ("lv", "nta.c", 3342, __extension__ __PRETTY_FUNCTION__
); }))
;
3343 if (lv->v_port)
3344 /* Add non-default port */
3345 url->url_port = lv->v_port;
3346 return 1;
3347 }
3348 if (su_strmatch(url->url_port, url_port_default((enum url_type_e)url->url_type)) ||
3349 su_strmatch(url->url_port, ""))
3350 /* Remove default or empty port */
3351 url->url_port = NULL((void*)0);
3352
3353 return 0;
3354 }
3355}
3356
3357/** @internal Handle incoming responses. */
3358static
3359void agent_recv_response(nta_agent_t *agent,
3360 msg_t *msg,
3361 sip_t *sip,
3362 sip_via_t *tport_via,
3363 tport_t *tport)
3364{
3365 int status = sip->sip_status->st_status;
3366 int errors;
3367 char const *phrase = sip->sip_status->st_phrase;
3368 char const *method =
3369 sip->sip_cseq ? sip->sip_cseq->cs_method_name : "<UNKNOWN>";
3370 uint32_t cseq = sip->sip_cseq ? sip->sip_cseq->cs_seq : 0;
3371 nta_outgoing_t *orq;
3372 su_home_t *home;
3373 char const *branch = NONE((void *)-1);
3374
3375
3376 agent->sa_stats->as_recv_msg++;
3377 agent->sa_stats->as_recv_response++;
3378
3379 SU_DEBUG_5(("nta: received %03d %s for %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3380, "nta: received %03d %s for %s (%u)\n", status, phrase
, method, cseq)) : (void)0)
3380 status, phrase, method, cseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3380, "nta: received %03d %s for %s (%u)\n", status, phrase
, method, cseq)) : (void)0)
;
3381
3382 if (agent->sa_drop_prob && !tport_is_reliable(tport)) {
3383 if ((unsigned)su_randint(0, 1000) < agent->sa_drop_prob) {
3384 SU_DEBUG_5(("nta: %03d %s %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3385, "nta: %03d %s %s\n", status, phrase, "dropped simulating packet loss"
)) : (void)0)
3385 status, phrase, "dropped simulating packet loss"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3385, "nta: %03d %s %s\n", status, phrase, "dropped simulating packet loss"
)) : (void)0)
;
3386 agent->sa_stats->as_drop_response++;
3387 msg_destroy(msg);
3388 return;
3389 }
3390 }
3391
3392 if (agent->sa_bad_resp_mask)
3393 errors = msg_extract_errors(msg) & agent->sa_bad_resp_mask;
3394 else
3395 errors = sip->sip_error != NULL((void*)0);
3396
3397 if (errors ||
3398 sip_sanity_check(sip) < 0) {
3399 sip_header_t const *h;
3400
3401 agent->sa_stats->as_bad_response++;
3402 agent->sa_stats->as_bad_message++;
3403
3404 SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3407, "nta: %03d %s %s\n", status, phrase, errors ? "has fatal syntax errors"
: "failed sanity check")) : (void)0)
3405 errors(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3407, "nta: %03d %s %s\n", status, phrase, errors ? "has fatal syntax errors"
: "failed sanity check")) : (void)0)
3406 ? "has fatal syntax errors"(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3407, "nta: %03d %s %s\n", status, phrase, errors ? "has fatal syntax errors"
: "failed sanity check")) : (void)0)
3407 : "failed sanity check"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3407, "nta: %03d %s %s\n", status, phrase, errors ? "has fatal syntax errors"
: "failed sanity check")) : (void)0)
;
3408
3409 for (h = (sip_header_t const *)sip->sip_error; h; h = h->sh_nextsh_header_next->shn_next) {
3410 if (h->sh_classsh_common->h_class->hc_name) {
3411 SU_DEBUG_5(("nta: %03d has bad %s header\n", status,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3412, "nta: %03d has bad %s header\n", status, h->sh_common
->h_class->hc_name)) : (void)0)
3412 h->sh_class->hc_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3412, "nta: %03d has bad %s header\n", status, h->sh_common
->h_class->hc_name)) : (void)0)
;
3413 }
3414 }
3415
3416 msg_destroy(msg);
3417 return;
3418 }
3419
3420 if (!su_casematch(sip->sip_status->st_version, sip_version_2_0)) {
3421 agent->sa_stats->as_bad_response++;
3422 agent->sa_stats->as_bad_message++;
3423
3424 SU_DEBUG_5(("nta: bad version %s %03d %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3425, "nta: bad version %s %03d %s\n", sip->sip_status->
st_version, status, phrase)) : (void)0)
3425 sip->sip_status->st_version, status, phrase))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3425, "nta: bad version %s %03d %s\n", sip->sip_status->
st_version, status, phrase)) : (void)0)
;
3426 msg_destroy(msg);
3427 return;
3428 }
3429
3430 if (sip->sip_cseq && sip->sip_cseq->cs_method == sip_method_ack) {
3431 /* Drop response messages to ACK */
3432 agent->sa_stats->as_bad_response++;
3433 agent->sa_stats->as_bad_message++;
3434 SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "is response to ACK"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3434, "nta: %03d %s %s\n", status, phrase, "is response to ACK"
)) : (void)0)
;
3435 msg_destroy(msg);
3436 return;
3437 }
3438
3439 /* XXX - should check if msg should be discarded based on via? */
3440
3441#ifdef HAVE_ZLIB_COMPRESS1
3442 sip_content_encoding_Xflate(msg, sip, 1, 1);
3443#endif
3444
3445 if ((orq = outgoing_find(agent, msg, sip, sip->sip_via))) {
3446 SU_DEBUG_5(("nta: %03d %s %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3447, "nta: %03d %s %s\n", status, phrase, "is going to a transaction"
)) : (void)0)
3447 status, phrase, "is going to a transaction"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3447, "nta: %03d %s %s\n", status, phrase, "is going to a transaction"
)) : (void)0)
;
3448 /* RFC3263 4.3 "503 error response" */
3449 if(agent->sa_srv_503 && status == 503 && outgoing_other_destinations(orq)) {
3450 SU_DEBUG_5(("%s(%p): <%03d> for <%s>, %s\n", "nta", (void *)orq, status, method, "try next after timeout"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3450, "%s(%p): <%03d> for <%s>, %s\n", "nta", (
void *)orq, status, method, "try next after timeout")) : (void
)0)
;
3451 home = msg_home(msg)((su_home_t*)(msg));
3452 if (agent->sa_is_stateless)
3453 branch = stateless_branch(agent, msg, sip, orq->orq_tpn);
3454 else
3455 branch = stateful_branch(home, agent);
3456
3457 orq->orq_branch = branch;
3458 orq->orq_via_branch = branch;
3459 outgoing_try_another(orq);
3460 return;
3461 }
3462
3463 if (outgoing_recv(orq, status, msg, sip) == 0)
3464 return;
3465 }
3466
3467
3468 agent->sa_stats->as_trless_response++;
3469
3470 if ((orq = agent->sa_default_outgoing)) {
3471 SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3472, "nta: %03d %s %s\n", status, phrase, "to the default transaction"
)) : (void)0)
3472 "to the default transaction"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3472, "nta: %03d %s %s\n", status, phrase, "to the default transaction"
)) : (void)0)
;
3473 outgoing_default_recv(orq, status, msg, sip);
3474 return;
3475 }
3476 else if (agent->sa_callback) {
3477 SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "to message callback"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3477, "nta: %03d %s %s\n", status, phrase, "to message callback"
)) : (void)0)
;
3478 /*
3479 * Store message and transport to hook for the duration of the callback
3480 * so that the transport can be obtained by nta_transport().
3481 */
3482 (void)agent->sa_callback(agent->sa_magic, agent, msg, sip);
3483 return;
3484 }
3485
3486 if (sip->sip_cseq && sip->sip_cseq->cs_method == sip_method_invite
3487 && 200 <= sip->sip_status->st_status
3488 && sip->sip_status->st_status < 300
3489 /* Exactly one Via header, belonging to us */
3490 && sip->sip_via && !sip->sip_via->v_next
3491 && agent_has_via(agent, sip->sip_via)) {
3492 agent->sa_stats->as_trless_200++;
3493 }
3494
3495 SU_DEBUG_5(("nta: %03d %s %s\n", status, phrase, "was discarded"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3495, "nta: %03d %s %s\n", status, phrase, "was discarded")
) : (void)0)
;
3496 msg_destroy(msg);
3497}
3498
3499/** @internal Agent receives garbage */
3500static
3501void agent_recv_garbage(nta_agent_t *agent,
3502 msg_t *msg,
3503 tport_t *tport)
3504{
3505 agent->sa_stats->as_recv_msg++;
3506 agent->sa_stats->as_bad_message++;
3507
3508#if SU_DEBUG0 >= 3
3509 if (nta_log->log_level >= 3) {
3510 tp_name_t tpn[1];
3511
3512 tport_delivered_from(tport, msg, tpn);
3513
3514 SU_DEBUG_3(("nta_agent: received garbage from " TPN_FORMAT "\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3515, "nta_agent: received garbage from " "%s/%s:%s%s%s%s%s"
"\n", (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
3515 TPN_ARGS(tpn)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3515, "nta_agent: received garbage from " "%s/%s:%s%s%s%s%s"
"\n", (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
;
3516 }
3517#endif
3518
3519 msg_destroy(msg);
3520}
3521
3522/* ====================================================================== */
3523/* 4) Message handling - create, complete, destroy */
3524
3525/** Create a new message belonging to the agent */
3526msg_t *nta_msg_create(nta_agent_t *agent, int flags)
3527{
3528 msg_t *msg;
3529
3530 if (agent == NULL((void*)0))
3531 return su_seterrno(EINVAL22), NULL((void*)0);
3532
3533 msg = msg_create(agent->sa_mclass, agent->sa_flags | flags);
3534
3535 if (agent->sa_preload)
3536 su_home_preload(msg_home(msg)((su_home_t*)(msg)), 1, agent->sa_preload);
3537
3538 return msg;
3539}
3540
3541/** Create a new message for transport */
3542msg_t *nta_msg_create_for_transport(nta_agent_t *agent, int flags,
3543 char const data[], usize_t dlen,
3544 tport_t const *tport, tp_client_t *via)
3545{
3546 msg_t *msg = msg_create(agent->sa_mclass, agent->sa_flags | flags);
3547
3548 msg_maxsize(msg, agent->sa_maxsize);
3549
3550 if (agent->sa_preload)
3551 su_home_preload(msg_home(msg)((su_home_t*)(msg)), 1, dlen + agent->sa_preload);
3552
3553 return msg;
3554}
3555
3556/** Complete a message. */
3557int nta_msg_complete(msg_t *msg)
3558{
3559 return sip_complete_message(msg);
3560}
3561
3562/** Discard a message */
3563void nta_msg_discard(nta_agent_t *agent, msg_t *msg)
3564{
3565 msg_destroy(msg);
3566}
3567
3568/** Check if the headers are from response generated locally by NTA. */
3569int nta_sip_is_internal(sip_t const *sip)
3570{
3571 return
3572 sip == NULL((void*)0) /* No message generated */
3573 || (sip->sip_flags & NTA_INTERNAL_MSG(1<<15)) == NTA_INTERNAL_MSG(1<<15);
3574}
3575
3576/** Check if the message is internally generated by NTA. */
3577int nta_msg_is_internal(msg_t const *msg)
3578{
3579 return msg_get_flags(msg, NTA_INTERNAL_MSG(1<<15)) == NTA_INTERNAL_MSG(1<<15);
3580}
3581
3582/** Check if the message is internally generated by NTA.
3583 *
3584 * @deprecated Use nta_msg_is_internal() instead
3585 */
3586int nta_is_internal_msg(msg_t const *msg) { return nta_msg_is_internal(msg); }
3587
3588/* ====================================================================== */
3589/* 5) Stateless operation */
3590
3591/**Forward a request or response message.
3592 *
3593 * @note
3594 * The ownership of @a msg is taken over by the function even if the
3595 * function fails.
3596 */
3597int nta_msg_tsend(nta_agent_t *agent, msg_t *msg, url_string_t const *u,
3598 tag_type_t tag, tag_value_t value, ...)
3599{
3600 int retval = -1;
3601 ta_list ta;
3602 sip_t *sip = sip_object(msg);
3603 tp_name_t tpn[1] = {{ NULL((void*)0) }};
3604 char const *what;
3605
3606 if (!sip) {
3607 msg_destroy(msg);
3608 return -1;
3609 }
3610
3611 what =
3612 sip->sip_status ? "nta_msg_tsend(response)" :
3613 sip->sip_request ? "nta_msg_tsend(request)" :
3614 "nta_msg_tsend()";
3615
3616 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3617
3618 if (sip_add_tl(msg, sip, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0)
3619 SU_DEBUG_3(("%s: cannot add headers\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3619, "%s: cannot add headers\n", what)) : (void)0)
;
3620 else if (sip->sip_status) {
3621 tport_t *tport = NULL((void*)0);
3622 int *use_rport = NULL((void*)0);
3623 int retry_without_rport = 0;
3624
3625 struct sigcomp_compartment *cc; cc = NONE((void *)-1);
3626
3627 if (agent->sa_server_rport)
3628 use_rport = &retry_without_rport, retry_without_rport = 1;
3629
3630 tl_gets(ta_args(ta)(ta).tl,
3631 NTATAG_TPORT_REF(tport)ntatag_tport_ref, tag_ptr_vr(&(tport), (tport)),
3632 IF_SIGCOMP_TPTAG_COMPARTMENT_REF(cc)tptag_compartment_ref, tag_ptr_vr(&(cc), cc),
3633 /* NTATAG_INCOMPLETE_REF(incomplete), */
3634 TAG_END()(tag_type_t)0, (tag_value_t)0);
3635
3636 if (!sip->sip_separator &&
3637 !(sip->sip_separator = sip_separator_create(msg_home(msg)((su_home_t*)(msg)))))
3638 SU_DEBUG_3(("%s: cannot create sip_separator\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3638, "%s: cannot create sip_separator\n", what)) : (void)0
)
;
3639 else if (msg_serialize(msg, (msg_pub_t *)sip) != 0)
3640 SU_DEBUG_3(("%s: sip_serialize() failed\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3640, "%s: sip_serialize() failed\n", what)) : (void)0)
;
3641 else if (!sip_via_remove(msg, sip))
3642 SU_DEBUG_3(("%s: cannot remove Via\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3642, "%s: cannot remove Via\n", what)) : (void)0)
;
3643 else if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0)
3644 SU_DEBUG_3(("%s: bad via\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3644, "%s: bad via\n", what)) : (void)0)
;
3645 else {
3646 if (!tport)
3647 tport = tport_by_name(agent->sa_tports, tpn);
3648 if (!tport)
3649 tport = tport_by_protocol(agent->sa_tports, tpn->tpn_proto);
3650
3651 if (retry_without_rport)
3652 tpn->tpn_port = sip_via_port(sip->sip_via, NULL((void*)0));
3653
3654 if (tport && tpn->tpn_comp && cc == NONE((void *)-1))
3655 cc = agent_compression_compartment(agent, tport, tpn, -1);
3656
3657 if (tport_tsend(tport, msg, tpn,
3658 IF_SIGCOMP_TPTAG_COMPARTMENT(cc)!(cc && cc != ((void *)-1)) ? tag_skip : tptag_compartment
, tag_ptr_v((cc)),
3659 TPTAG_MTU(INT_MAX)tptag_mtu, tag_usize_v((2147483647)), ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
, TAG_END()(tag_type_t)0, (tag_value_t)0)) {
3660 agent->sa_stats->as_sent_msg++;
3661 agent->sa_stats->as_sent_response++;
3662 retval = 0;
3663 }
3664 else {
3665 SU_DEBUG_3(("%s: send fails\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3665, "%s: send fails\n", what)) : (void)0)
;
3666 }
3667 }
3668 }
3669 else {
3670 /* Send request */
3671 if (outgoing_create(agent, NULL((void*)0), NULL((void*)0), u, NULL((void*)0), msg_ref_create(msg),
3672 NTATAG_STATELESS(1)ntatag_stateless, tag_bool_v((1)),
3673 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
))
3674 retval = 0;
3675 }
3676
3677 if (retval == 0)
3678 SU_DEBUG_5(("%s\n", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 3678, "%s\n", what)) : (void)0)
;
3679
3680 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3681
3682 msg_destroy(msg);
3683
3684 return retval;
3685}
3686
3687/** Reply to a request message.
3688 *
3689 * @param agent nta agent object
3690 * @param req_msg request message
3691 * @param status status code
3692 * @param phrase status phrase (may be NULL if status code is well-known)
3693 * @param tag, value, ... optional additional headers terminated by TAG_END()
3694 *
3695 * @retval 0 when succesful
3696 * @retval -1 upon an error
3697 *
3698 * @note
3699 * The ownership of @a msg is taken over by the function even if the
3700 * function fails.
3701 */
3702int nta_msg_treply(nta_agent_t *agent,
3703 msg_t *req_msg,
3704 int status, char const *phrase,
3705 tag_type_t tag, tag_value_t value, ...)
3706{
3707 int retval;
3708 ta_list ta;
3709
3710 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3711
3712 retval = mreply(agent, NULL((void*)0), status, phrase, req_msg,
3713 NULL((void*)0), 0, 0, NULL((void*)0),
3714 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
3715 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3716
3717 return retval;
3718}
3719
3720/**Reply to the request message.
3721 *
3722 * @note
3723 * The ownership of @a msg is taken over by the function even if the
3724 * function fails.
3725 */
3726int nta_msg_mreply(nta_agent_t *agent,
3727 msg_t *reply, sip_t *sip,
3728 int status, char const *phrase,
3729 msg_t *req_msg,
3730 tag_type_t tag, tag_value_t value, ...)
3731{
3732 int retval = -1;
3733 ta_list ta;
3734
3735 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3736
3737 retval = mreply(agent, reply, status, phrase, req_msg,
3738 NULL((void*)0), 0, 0, NULL((void*)0),
3739 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
3740 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3741
3742 return retval;
3743}
3744
3745static
3746int mreply(nta_agent_t *agent,
3747 msg_t *reply,
3748 int status, char const *phrase,
3749 msg_t *req_msg,
3750 tport_t *tport,
3751 int incomplete,
3752 int sdwn_after,
3753 char const *to_tag,
3754 tag_type_t tag, tag_value_t value, ...)
3755{
3756 ta_list ta;
3757 sip_t *sip;
3758 int *use_rport = NULL((void*)0);
3759 int retry_without_rport = 0;
3760 tp_name_t tpn[1];
3761 int retval = -1;
3762
3763 if (!agent)
3764 return -1;
3765
3766 if (agent->sa_server_rport)
3767 use_rport = &retry_without_rport, retry_without_rport = 1;
3768
3769 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
3770
3771 tl_gets(ta_args(ta)(ta).tl, NTATAG_TPORT_REF(tport)ntatag_tport_ref, tag_ptr_vr(&(tport), (tport)), TAG_END()(tag_type_t)0, (tag_value_t)0);
3772
3773 if (reply == NULL((void*)0)) {
3774 reply = nta_msg_create(agent, 0);
3775 }
3776 sip = sip_object(reply);
3777
3778 if (!sip) {
3779 SU_DEBUG_3(("%s: cannot create response msg\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3779, "%s: cannot create response msg\n", __func__)) : (void
)0)
;
3780 }
3781 else if (sip_add_tl(reply, sip, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0) {
3782 SU_DEBUG_3(("%s: cannot add user headers\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3782, "%s: cannot add user headers\n", __func__)) : (void)0
)
;
3783 }
3784 else if (complete_response(reply, status, phrase, req_msg) < 0 &&
3785 !incomplete) {
3786 SU_DEBUG_3(("%s: cannot complete message\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3786, "%s: cannot complete message\n", __func__)) : (void)0
)
;
3787 }
3788 else if (sip->sip_status && sip->sip_status->st_status > 100 &&
3789 sip->sip_to && !sip->sip_to->a_tag &&
3790 (to_tag == NONE((void *)-1) ? 0 :
3791 to_tag != NULL((void*)0)
3792 ? sip_to_tag(msg_home(reply)((su_home_t*)(reply)), sip->sip_to, to_tag) < 0
3793 : sip_to_tag(msg_home(reply)((su_home_t*)(reply)), sip->sip_to,
3794 nta_agent_newtag(msg_home(reply)((su_home_t*)(reply)), "tag=%s", agent)) < 0)) {
3795 SU_DEBUG_3(("%s: cannot add To tag\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3795, "%s: cannot add To tag\n", __func__)) : (void)0)
;
3796 }
3797 else if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0) {
3798 SU_DEBUG_3(("%s: no Via\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3798, "%s: no Via\n", __func__)) : (void)0)
;
3799 }
3800 else {
3801 struct sigcomp_compartment *cc = NONE((void *)-1);
3802
3803 if (tport == NULL((void*)0))
3804 tport = tport_delivered_by(agent->sa_tports, req_msg);
3805
3806 if (!tport) {
3807 tport_t *primary = tport_by_protocol(agent->sa_tports, tpn->tpn_proto);
3808
3809 tport = tport_by_name(primary, tpn);
3810
3811 if (!tport)
3812 tport = primary;
3813 }
3814
3815 if (retry_without_rport)
3816 tpn->tpn_port = sip_via_port(sip->sip_via, NULL((void*)0));
3817
3818 if (tport && tpn->tpn_comp) {
3819 tl_gets(ta_args(ta)(ta).tl, TPTAG_COMPARTMENT_REF(cc)tptag_compartment_ref, tag_ptr_vr(&(cc), cc),
3820 /* XXX - should also check ntatag_sigcomp_close() */
3821 TAG_END()(tag_type_t)0, (tag_value_t)0);
3822 if (cc == NONE((void *)-1))
3823 cc = agent_compression_compartment(agent, tport, tpn, -1);
3824
3825 if (cc != NULL((void*)0) && cc != NONE((void *)-1) &&
3826 tport_delivered_with_comp(tport, req_msg, NULL((void*)0)) != -1) {
3827 agent_accept_compressed(agent, req_msg, cc);
3828 }
3829 }
3830
3831 if (tport_tsend(tport, reply, tpn,
3832 IF_SIGCOMP_TPTAG_COMPARTMENT(cc)!(cc && cc != ((void *)-1)) ? tag_skip : tptag_compartment
, tag_ptr_v((cc)),
3833 TPTAG_MTU(INT_MAX)tptag_mtu, tag_usize_v((2147483647)),
3834 TPTAG_SDWN_AFTER(sdwn_after)tptag_sdwn_after, tag_bool_v((sdwn_after)),
3835 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
)) {
3836 agent->sa_stats->as_sent_msg++;
3837 agent->sa_stats->as_sent_response++;
3838 retval = 0; /* Success! */
3839 }
3840 else {
3841 SU_DEBUG_3(("%s: send fails\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 3841, "%s: send fails\n", __func__)) : (void)0)
;
3842 }
3843 }
3844
3845 msg_destroy(reply);
3846 msg_destroy(req_msg);
3847
3848 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
3849
3850 return retval;
3851}
3852
3853/** Add headers from the request to the response message. */
3854static
3855int complete_response(msg_t *response,
3856 int status, char const *phrase,
3857 msg_t *request)
3858{
3859 su_home_t *home = msg_home(response)((su_home_t*)(response));
3860 sip_t *response_sip = sip_object(response);
3861 sip_t const *request_sip = sip_object(request);
3862
3863 int incomplete = 0;
3864
3865 if (!response_sip || !request_sip || !request_sip->sip_request)
3866 return -1;
3867
3868 if (!response_sip->sip_status)
3869 response_sip->sip_status = sip_status_create(home, status, phrase, NULL((void*)0));
3870 if (!response_sip->sip_via)
3871 response_sip->sip_via = sip_via_dup(home, request_sip->sip_via);
3872 if (!response_sip->sip_from)
3873 response_sip->sip_from = sip_from_dup(home, request_sip->sip_from);
3874 if (!response_sip->sip_to)
3875 response_sip->sip_to = sip_to_dup(home, request_sip->sip_to);
3876 if (!response_sip->sip_call_id)
3877 response_sip->sip_call_id =
3878 sip_call_id_dup(home, request_sip->sip_call_id);
3879 if (!response_sip->sip_cseq)
3880 response_sip->sip_cseq = sip_cseq_dup(home, request_sip->sip_cseq);
3881
3882 if (!response_sip->sip_record_route && request_sip->sip_record_route)
3883 sip_add_dup(response, response_sip, (void*)request_sip->sip_record_route);
3884
3885 incomplete = sip_complete_message(response) < 0;
3886
3887 msg_serialize(response, (msg_pub_t *)response_sip);
3888
3889 if (incomplete ||
3890 !response_sip->sip_status ||
3891 !response_sip->sip_via ||
3892 !response_sip->sip_from ||
3893 !response_sip->sip_to ||
3894 !response_sip->sip_call_id ||
3895 !response_sip->sip_cseq ||
3896 !response_sip->sip_content_length ||
3897 !response_sip->sip_separator ||
3898 (request_sip->sip_record_route && !response_sip->sip_record_route))
3899 return -1;
3900
3901 return 0;
3902}
3903
3904/** ACK and BYE an unknown 200 OK response to INVITE.
3905 *
3906 * A UAS may still return a 2XX series response to client request after the
3907 * client transactions has been terminated. In that case, the UAC can not
3908 * really accept the call. This function was used to accept and immediately
3909 * terminate such a call.
3910 *
3911 * @deprecated This was a bad idea: see sf.net bug #1750691. It can be used
3912 * to amplify DoS attacks. Let UAS take care of retransmission timeout and
3913 * let it terminate the session. As of @VERSION_1_12_7, this function just
3914 * returns -1.
3915 */
3916int nta_msg_ackbye(nta_agent_t *agent, msg_t *msg)
3917{
3918 sip_t *sip = sip_object(msg);
3919 msg_t *amsg = nta_msg_create(agent, 0);
3920 sip_t *asip = sip_object(amsg);
3921 msg_t *bmsg = NULL((void*)0);
3922 sip_t *bsip;
3923 url_string_t const *ruri;
3924 nta_outgoing_t *ack = NULL((void*)0);
3925 sip_cseq_t *cseq;
3926 sip_request_t *rq;
3927 sip_route_t *route = NULL((void*)0), *r, r0[1];
3928 su_home_t *home = msg_home(amsg)((su_home_t*)(amsg));
3929
3930 if (asip == NULL((void*)0))
3931 return -1;
3932
3933 sip_add_tl(amsg, asip,
3934 SIPTAG_TO(sip->sip_to)siptag_to, siptag_to_v(sip->sip_to),
3935 SIPTAG_FROM(sip->sip_from)siptag_from, siptag_from_v(sip->sip_from),
3936 SIPTAG_CALL_ID(sip->sip_call_id)siptag_call_id, siptag_call_id_v(sip->sip_call_id),
3937 TAG_END()(tag_type_t)0, (tag_value_t)0);
3938
3939 if (sip->sip_contact) {
3940 ruri = (url_string_t const *)sip->sip_contact->m_url;
3941 } else {
3942 ruri = (url_string_t const *)sip->sip_to->a_url;
3943 }
3944
3945 /* Reverse (and fix) record route */
3946 route = sip_route_reverse(home, sip->sip_record_route);
3947
3948 if (route && !url_has_param(route->r_url, "lr")) {
3949 for (r = route; r->r_next; r = r->r_next)
3950 ;
3951
3952 /* Append r-uri */
3953 *sip_route_init(r0)->r_url = *ruri->us_url;
3954 r->r_next = sip_route_dup(home, r0);
3955
3956 /* Use topmost route as request-uri */
3957 ruri = (url_string_t const *)route->r_url;
3958 route = route->r_next;
3959 }
3960
3961 msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)route);
3962
3963 bmsg = msg_copy(amsg); bsip = sip_object(bmsg);
3964
3965 if (!(cseq = sip_cseq_create(home, sip->sip_cseq->cs_seq, SIP_METHOD_ACKsip_method_ack, "ACK")))
3966 goto err;
3967 else
3968 msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)cseq);
3969
3970 if (!(rq = sip_request_create(home, SIP_METHOD_ACKsip_method_ack, "ACK", ruri, NULL((void*)0))))
3971 goto err;
3972 else
3973 msg_header_insert(amsg, (msg_pub_t *)asip, (msg_header_t *)rq);
3974
3975 if (!(ack = nta_outgoing_mcreate(agent, NULL((void*)0), NULL((void*)0), NULL((void*)0), amsg,
3976 NTATAG_ACK_BRANCH(sip->sip_via->v_branch)ntatag_ack_branch, tag_str_v((sip->sip_via->v_branch)),
3977 NTATAG_STATELESS(1)ntatag_stateless, tag_bool_v((1)),
3978 TAG_END()(tag_type_t)0, (tag_value_t)0)))
3979 goto err;
3980 else
3981 nta_outgoing_destroy(ack);
3982
3983 home = msg_home(bmsg)((su_home_t*)(bmsg));
3984
3985 if (!(cseq = sip_cseq_create(home, 0x7fffffff, SIP_METHOD_BYEsip_method_bye, "BYE")))
3986 goto err;
3987 else
3988 msg_header_insert(bmsg, (msg_pub_t *)bsip, (msg_header_t *)cseq);
3989
3990 if (!(rq = sip_request_create(home, SIP_METHOD_BYEsip_method_bye, "BYE", ruri, NULL((void*)0))))
3991 goto err;
3992 else
3993 msg_header_insert(bmsg, (msg_pub_t *)bsip, (msg_header_t *)rq);
3994
3995 if (!nta_outgoing_mcreate(agent, NULL((void*)0), NULL((void*)0), NULL((void*)0), bmsg,
3996 NTATAG_STATELESS(1)ntatag_stateless, tag_bool_v((1)),
3997 TAG_END()(tag_type_t)0, (tag_value_t)0))
3998 goto err;
3999
4000 msg_destroy(msg);
4001 return 0;
4002
4003 err:
4004
4005 msg_destroy(bmsg);
4006 msg_destroy(amsg);
4007
4008 return -1;
4009}
4010
4011/**Complete a request with values from dialog.
4012 *
4013 * Complete a request message @a msg belonging to a dialog associated with
4014 * @a leg. It increments the local @CSeq value, adds @CallID, @To, @From and
4015 * @Route headers (if there is such headers present in @a leg), and creates
4016 * a new request line object from @a method, @a method_name and @a
4017 * request_uri.
4018 *
4019 * @param msg pointer to a request message object
4020 * @param leg pointer to a #nta_leg_t object
4021 * @param method request method number or #sip_method_unknown
4022 * @param method_name method name (if @a method == #sip_method_unknown)
4023 * @param request_uri request URI
4024 *
4025 * If @a request_uri contains query part, the query part is converted as SIP
4026 * headers and added to the request.
4027 *
4028 * @retval 0 when successful
4029 * @retval -1 upon an error
4030 *
4031 * @sa nta_outgoing_mcreate(), nta_outgoing_tcreate()
4032 */
4033int nta_msg_request_complete(msg_t *msg,
4034 nta_leg_t *leg,
4035 sip_method_t method,
4036 char const *method_name,
4037 url_string_t const *request_uri)
4038{
4039 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
4040 sip_t *sip = sip_object(msg);
4041 sip_to_t const *to;
4042 uint32_t seq;
4043 url_t reg_url[1];
4044 url_string_t const *original = request_uri;
4045
4046 if (!leg || !msg || !sip)
4047 return -1;
4048
4049 if (!sip->sip_route && leg->leg_route) {
4050 if (leg->leg_loose_route) {
4051 if (leg->leg_target) {
4052 request_uri = (url_string_t *)leg->leg_target->m_url;
4053 }
4054 sip->sip_route = sip_route_dup(home, leg->leg_route);
4055 }
4056 else {
4057 sip_route_t **rr;
4058
4059 request_uri = (url_string_t *)leg->leg_route->r_url;
4060 sip->sip_route = sip_route_dup(home, leg->leg_route->r_next);
4061
4062 for (rr = &sip->sip_route; *rr; rr = &(*rr)->r_next)
4063 ;
4064
4065 if (leg->leg_target)
4066 *rr = sip_route_dup(home, (sip_route_t *)leg->leg_target);
4067 }
4068 }
4069 else if (leg->leg_target)
4070 request_uri = (url_string_t *)leg->leg_target->m_url;
4071
4072 if (!request_uri && sip->sip_request)
4073 request_uri = (url_string_t *)sip->sip_request->rq_url;
4074
4075 to = sip->sip_to ? sip->sip_to : leg->leg_remote;
4076
4077 if (!request_uri && to) {
4078 if (method != sip_method_register)
4079 request_uri = (url_string_t *)to->a_url;
4080 else {
4081 /* Remove user part from REGISTER requests */
4082 *reg_url = *to->a_url;
4083 reg_url->url_user = reg_url->url_password = NULL((void*)0);
4084 request_uri = (url_string_t *)reg_url;
4085 }
4086 }
4087
4088 if (!request_uri)
4089 return -1;
4090
4091 if (method || method_name) {
4092 sip_request_t *rq = sip->sip_request;
4093 int use_headers =
4094 request_uri == original || (url_t *)request_uri == rq->rq_url;
4095
4096 if (!rq
4097 || request_uri != (url_string_t *)rq->rq_url
4098 || method != rq->rq_method
4099 || !su_strmatch(method_name, rq->rq_method_name))
4100 rq = NULL((void*)0);
4101
4102 if (rq == NULL((void*)0)) {
4103 rq = sip_request_create(home, method, method_name, request_uri, NULL((void*)0));
4104 if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)rq) < 0)
4105 return -1;
4106 }
4107
4108 /* @RFC3261 table 1 (page 152):
4109 * Req-URI cannot contain method parameter or headers
4110 */
4111 if (rq->rq_url->url_params) {
4112 rq->rq_url->url_params =
4113 url_strip_param_string((char *)rq->rq_url->url_params, "method");
4114 sip_fragment_clear(rq->rq_common)((rq->rq_common)->h_data = ((void*)0), (rq->rq_common
)->h_len = 0)
;
4115 }
4116
4117 if (rq->rq_url->url_headers) {
4118 if (use_headers) {
4119 char *s = url_query_as_header_string(msg_home(msg)((su_home_t*)(msg)),
4120 rq->rq_url->url_headers);
4121 if (!s)
4122 return -1;
4123 msg_header_parse_str(msg, (msg_pub_t*)sip, s);
4124 }
4125 rq->rq_url->url_headers = NULL((void*)0), sip_fragment_clear(rq->rq_common)((rq->rq_common)->h_data = ((void*)0), (rq->rq_common
)->h_len = 0)
;
4126 }
4127 }
4128
4129 if (!sip->sip_request)
4130 return -1;
4131
4132 if (!sip->sip_max_forwards)
4133 sip_add_dup(msg, sip, (sip_header_t *)leg->leg_agent->sa_max_forwards);
4134
4135 if (!sip->sip_from)
4136 sip->sip_from = sip_from_dup(home, leg->leg_local);
4137 else if (leg->leg_local && leg->leg_local->a_tag &&
4138 (!sip->sip_from->a_tag ||
4139 !su_casematch(sip->sip_from->a_tag, leg->leg_local->a_tag)))
4140 sip_from_tag(home, sip->sip_from, leg->leg_local->a_tag);
4141
4142 if (sip->sip_from && !sip->sip_from->a_tag) {
4143 sip_fragment_clear(sip->sip_from->a_common)((sip->sip_from->a_common)->h_data = ((void*)0), (sip
->sip_from->a_common)->h_len = 0)
;
4144 sip_from_add_param(home, sip->sip_from,
4145 nta_agent_newtag(home, "tag=%s", leg->leg_agent));
4146 }
4147
4148 if (sip->sip_to) {
4149 if (leg->leg_remote && leg->leg_remote->a_tag)
4150 sip_to_tag(home, sip->sip_to, leg->leg_remote->a_tag);
4151 }
4152 else if (leg->leg_remote) {
4153 sip->sip_to = sip_to_dup(home, leg->leg_remote);
4154 }
4155 else {
4156 sip_to_t *to = sip_to_create(home, request_uri);
4157 if (to) sip_aor_strip(to->a_url);
4158 sip->sip_to = to;
4159 }
4160
4161 if (!sip->sip_from || !sip->sip_from || !sip->sip_to)
4162 return -1;
4163
4164 method = sip->sip_request->rq_method;
4165 method_name = sip->sip_request->rq_method_name;
4166
4167 if (!leg->leg_id && sip->sip_cseq)
4168 seq = sip->sip_cseq->cs_seq;
4169 else if (method == sip_method_ack || method == sip_method_cancel)
4170 /* Dangerous - we may do PRACK/UPDATE meanwhile */
4171 seq = sip->sip_cseq ? sip->sip_cseq->cs_seq : leg->leg_seq;
4172 else if (leg->leg_seq)
4173 seq = ++leg->leg_seq;
4174 else if (sip->sip_cseq) /* Obtain initial value from existing CSeq header */
4175 seq = leg->leg_seq = sip->sip_cseq->cs_seq;
4176 else
4177 seq = leg->leg_seq = (sip_now() >> 1) & 0x7ffffff;
4178
4179 if (!sip->sip_call_id) {
4180 if (leg->leg_id)
4181 sip->sip_call_id = sip_call_id_dup(home, leg->leg_id);
4182 else
4183 sip->sip_call_id = sip_call_id_create(home, NULL((void*)0));
4184 }
4185
4186 if (!sip->sip_cseq ||
4187 seq != sip->sip_cseq->cs_seq ||
4188 method != sip->sip_cseq->cs_method ||
4189 !su_strmatch(method_name, sip->sip_cseq->cs_method_name)) {
4190 sip_cseq_t *cseq = sip_cseq_create(home, seq, method, method_name);
4191 if (msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)cseq) < 0)
4192 return -1;
4193 }
4194
4195 return 0;
4196}
4197
4198/* ====================================================================== */
4199/* 6) Dialogs (legs) */
4200
4201static void leg_insert(nta_agent_t *agent, nta_leg_t *leg);
4202static int leg_route(nta_leg_t *leg,
4203 sip_record_route_t const *route,
4204 sip_record_route_t const *reverse,
4205 sip_contact_t const *contact,
4206 int reroute);
4207static int leg_callback_default(nta_leg_magic_t*, nta_leg_t*,
4208 nta_incoming_t*, sip_t const *);
4209#define HTABLE_HASH_LEG(leg)((leg)->leg_hash) ((leg)->leg_hash)
4210
4211#ifdef __clang__1
4212#pragma clang diagnostic push
4213#pragma clang diagnostic ignored "-Wunused-function"
4214#endif
4215
4216HTABLE_BODIES_WITH(leg_htable, lht, nta_leg_t, HTABLE_HASH_LEG, size_t, hash_value_t)static inline int leg_htable_resize(su_home_t *home, leg_htable_t
lht[], size_t new_size) { nta_leg_t **new_hash; nta_leg_t **
old_hash = lht->lht_table; size_t old_size; size_t i, j, i0
; unsigned again = 0; size_t used = 0; if (new_size == 0) new_size
= 2 * lht->lht_size + 1; if (new_size < 31) new_size =
31; if (new_size < 5 * lht->lht_used / 4) new_size = 5
* lht->lht_used / 4; if (!(new_hash = su_zalloc(home, sizeof
(*new_hash) * new_size))) return -1; old_size = lht->lht_size
; do for (j = 0; j < old_size; j++) { if (!old_hash[j]) continue
; if (again < 2 && ((old_hash[j])->leg_hash) % old_size
> j) { again = 1; continue; } i0 = ((old_hash[j])->leg_hash
) % new_size; for (i = i0; new_hash[i]; i = (i + 1) % new_size
, ((void) sizeof ((i != i0) ? 1 : 0), __extension__ ({ if (i !=
i0) ; else __assert_fail ("i != i0", "nta.c", 4216, __extension__
__PRETTY_FUNCTION__); }))); new_hash[i] = old_hash[j], old_hash
[j] = ((void*)0); used++; } while (again++ == 1); lht->lht_table
= new_hash, lht->lht_size = new_size; ((void) sizeof ((lht
->lht_used == used) ? 1 : 0), __extension__ ({ if (lht->
lht_used == used) ; else __assert_fail ("lht->lht_used == used"
, "nta.c", 4216, __extension__ __PRETTY_FUNCTION__); })); su_free
(home, old_hash); return 0; } static inline int leg_htable_is_full
(leg_htable_t const *lht) { return lht->lht_table == ((void
*)0) || 3 * lht->lht_used > 2 * lht->lht_size; } static
inline nta_leg_t **leg_htable_hash(leg_htable_t const *lht, hash_value_t
hv) { return lht->lht_table + hv % lht->lht_size; } static
inline nta_leg_t **leg_htable_next(leg_htable_t const *lht, nta_leg_t
* const *ee) { if (++ee < lht->lht_table + lht->lht_size
&& ee >= lht->lht_table) return (nta_leg_t **)
ee; else return lht->lht_table; } static inline void leg_htable_append
(leg_htable_t *lht, nta_leg_t const *e) { nta_leg_t **ee; lht
->lht_used++; for (ee = leg_htable_hash(lht, ((e)->leg_hash
)); *ee; ee = leg_htable_next(lht, ee)) ; *ee = (nta_leg_t *)
e; } static inline void leg_htable_insert(leg_htable_t *lht, nta_leg_t
const *e) { nta_leg_t *e0, **ee; lht->lht_used++; for (ee
= leg_htable_hash(lht, ((e)->leg_hash)); (e0 = *ee); ee =
leg_htable_next(lht, ee)) *ee = (nta_leg_t *)e, e = e0; *ee =
(nta_leg_t *)e; } static inline int leg_htable_remove(leg_htable_t
*lht, nta_leg_t const *e) { size_t i, j, k; size_t size = lht
->lht_size; nta_leg_t **htable = lht->lht_table; if (!e
) return -1; for (i = ((e)->leg_hash) % size; htable[i]; i
= (i + 1) % size) if (e == htable[i]) break; if (!htable[i])
return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1) %
size) { k = ((htable[j])->leg_hash) % size; if (k == j) continue
; if (j > i ? (i < k && k < j) : (i < k ||
k < j)) continue; htable[i] = htable[j], i = j; } lht->
lht_used--; htable[i] = ((void*)0); return 0; } extern int leg_htable_dummy
;
4217
4218#ifdef __clang__1
4219#pragma clang diagnostic pop
4220#endif
4221
4222su_inlinestatic inline
4223hash_value_t hash_istring(char const *, char const *, hash_value_t);
4224
4225/**@typedef nta_request_f
4226 *
4227 * Callback for incoming requests
4228 *
4229 * This is a callback function invoked by NTA for each incoming SIP request.
4230 *
4231 * @param lmagic call leg context
4232 * @param leg call leg handle
4233 * @param ireq incoming request
4234 * @param sip incoming request contents
4235 *
4236 * @retval 100..699
4237 * NTA constructs a reply message with given error code and corresponding
4238 * standard phrase, then sends the reply.
4239 *
4240 * @retval 0
4241 * The application takes care of sending (or not sending) the reply.
4242 *
4243 * @retval other
4244 * All other return values will be interpreted as
4245 * @e 500 @e Internal @e server @e error.
4246 */
4247
4248
4249/**
4250 * Create a new leg object.
4251 *
4252 * Creates a leg object, which is used to represent dialogs, partial dialogs
4253 * (for example, in case of REGISTER), and destinations within a particular
4254 * NTA object.
4255 *
4256 * When a leg is created, a callback pointer and a application context is
4257 * provided. All other parameters are optional.
4258 *
4259 * @param agent agent object
4260 * @param callback function which is called for each
4261 * incoming request belonging to this leg
4262 * @param magic call leg context
4263 * @param tag,value,... optional extra headers in taglist
4264 *
4265 * When a leg representing dialog is created, the tags SIPTAG_CALL_ID(),
4266 * SIPTAG_FROM(), SIPTAG_TO(), and SIPTAG_CSEQ() (for local @CSeq number) are used
4267 * to establish dialog context. The SIPTAG_FROM() is used to pass local
4268 * address (@From header when making a call, @To header when answering
4269 * to a call) to the newly created leg. Respectively, the SIPTAG_TO() is
4270 * used to pass remote address (@To header when making a call, @From
4271 * header when answering to a call).
4272 *
4273 * If there is a (preloaded) route associated with the leg, SIPTAG_ROUTE()
4274 * and NTATAG_TARGET() can be used. A client or server can also set the
4275 * route using @RecordRoute and @Contact headers from a response or
4276 * request message with the functions nta_leg_client_route() and
4277 * nta_leg_server_route(), respectively.
4278 *
4279 * When a leg representing a local destination is created, the tags
4280 * NTATAG_NO_DIALOG(1), NTATAG_METHOD(), and URLTAG_URL() are used. When a
4281 * request with matching request-URI (URLTAG_URL()) and method
4282 * (NTATAG_METHOD()) is received, it is passed to the callback function
4283 * provided with the leg.
4284 *
4285 * @sa nta_leg_stateful(), nta_leg_bind(),
4286 * nta_leg_tag(), nta_leg_rtag(),
4287 * nta_leg_client_route(), nta_leg_server_route(),
4288 * nta_leg_destroy(), nta_outgoing_tcreate(), and nta_request_f().
4289 *
4290 * @TAGS
4291 * NTATAG_NO_DIALOG(), NTATAG_STATELESS(), NTATAG_METHOD(),
4292 * URLTAG_URL(), SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR(), SIPTAG_FROM(),
4293 * SIPTAG_FROM_STR(), SIPTAG_TO(), SIPTAG_TO_STR(), SIPTAG_ROUTE(),
4294 * NTATAG_TARGET() and SIPTAG_CSEQ().
4295 *
4296 */
4297nta_leg_t *nta_leg_tcreate(nta_agent_t *agent,
4298 nta_request_f *callback,
4299 nta_leg_magic_t *magic,
4300 tag_type_t tag, tag_value_t value, ...)
4301{
4302 sip_route_t const *route = NULL((void*)0);
4303 sip_contact_t const *contact = NULL((void*)0);
4304 sip_cseq_t const *cs = NULL((void*)0);
4305 sip_call_id_t const *i = NULL((void*)0);
4306 sip_from_t const *from = NULL((void*)0);
4307 sip_to_t const *to = NULL((void*)0);
4308 char const *method = NULL((void*)0);
4309 char const *i_str = NULL((void*)0), *to_str = NULL((void*)0), *from_str = NULL((void*)0), *cs_str = NULL((void*)0);
4310 url_string_t const *url_string = NULL((void*)0);
4311 int no_dialog = 0;
4312 unsigned rseq = 0;
4313 /* RFC 3261 section 12.2.1.1 */
4314 uint32_t seq = 0;
4315 ta_list ta;
4316 nta_leg_t *leg;
4317 su_home_t *home;
4318 url_t *url;
4319 char const *what = NULL((void*)0);
4320
4321 if (agent == NULL((void*)0))
4322 return su_seterrno(EINVAL22), NULL((void*)0);
4323
4324 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
4325
4326 tl_gets(ta_args(ta)(ta).tl,
4327 NTATAG_NO_DIALOG_REF(no_dialog)ntatag_no_dialog_ref, tag_bool_vr(&(no_dialog)),
4328 NTATAG_METHOD_REF(method)ntatag_method_ref, tag_str_vr(&(method)),
4329 URLTAG_URL_REF(url_string)urltag_url_ref, urltag_url_vr(&(url_string)),
4330 SIPTAG_CALL_ID_REF(i)siptag_call_id_ref, siptag_call_id_vr(&(i)),
4331 SIPTAG_CALL_ID_STR_REF(i_str)siptag_call_id_str_ref, tag_str_vr(&(i_str)),
4332 SIPTAG_FROM_REF(from)siptag_from_ref, siptag_from_vr(&(from)),
4333 SIPTAG_FROM_STR_REF(from_str)siptag_from_str_ref, tag_str_vr(&(from_str)),
4334 SIPTAG_TO_REF(to)siptag_to_ref, siptag_to_vr(&(to)),
4335 SIPTAG_TO_STR_REF(to_str)siptag_to_str_ref, tag_str_vr(&(to_str)),
4336 SIPTAG_ROUTE_REF(route)siptag_route_ref, siptag_route_vr(&(route)),
4337 NTATAG_TARGET_REF(contact)ntatag_target_ref, siptag_contact_vr(&(contact)),
4338 NTATAG_REMOTE_CSEQ_REF(rseq)ntatag_remote_cseq_ref, tag_uint_vr(&(rseq)),
4339 SIPTAG_CSEQ_REF(cs)siptag_cseq_ref, siptag_cseq_vr(&(cs)),
4340 SIPTAG_CSEQ_STR_REF(cs_str)siptag_cseq_str_ref, tag_str_vr(&(cs_str)),
4341 TAG_END()(tag_type_t)0, (tag_value_t)0);
4342
4343 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
4344
4345 if (cs)
4346 seq = cs->cs_seq;
4347 else if (cs_str)
4348 seq = strtoul(cs_str, (char **)&cs_str, 10);
4349
4350 if (i == NONE((void *)-1)) /* Magic value, used for compatibility */
4351 no_dialog = 1;
4352
4353 if (!(leg = su_home_clone(NULL((void*)0), sizeof(*leg))))
4354 return NULL((void*)0);
4355 home = leg->leg_home;
4356
4357 leg->leg_agent = agent;
4358 nta_leg_bind(leg, callback, magic);
4359
4360 if (from) {
4361 /* Now this is kludge */
4362 leg->leg_local_is_to = sip_is_to((sip_header_t*)from);
4363 leg->leg_local = sip_to_dup(home, from);
4364 }
4365 else if (from_str)
4366 leg->leg_local = sip_to_make(home, from_str);
4367
4368 if (to && no_dialog) {
4369 /* Remove tag, if any */
4370 sip_to_t to0[1]; *to0 = *to; to0->a_params = NULL((void*)0);
4371 leg->leg_remote = sip_from_dup(home, to0);
4372 }
4373 else if (to)
4374 leg->leg_remote = sip_from_dup(home, to);
4375 else if (to_str)
4376 leg->leg_remote = sip_from_make(home, to_str);
4377
4378 if (route && route != NONE((void *)-1))
4379 leg->leg_route = sip_route_dup(home, route), leg->leg_route_set = 1;
4380
4381 if (contact && contact != NONE((void *)-1)) {
4382 sip_contact_t m[1];
4383 sip_contact_init(m);
4384 *m->m_url = *contact->m_url;
4385 m->m_url->url_headers = NULL((void*)0);
4386 leg->leg_target = sip_contact_dup(home, m);
4387 }
4388
4389 url = url_hdup(home, url_string->us_url);
4390
4391 /* Match to local hosts */
4392 if (url && agent_aliases(agent, url, NULL((void*)0))) {
4393 url_t *changed = url_hdup(home, url);
4394 su_free(home, url);
4395 url = changed;
4396 }
4397
4398 leg->leg_rseq = rseq;
4399 leg->leg_seq = seq;
4400 leg->leg_url = url;
4401
4402 if (from && from != NONE((void *)-1) && leg->leg_local == NULL((void*)0)) {
4403 what = "cannot duplicate local address";
4404 goto err;
4405 }
4406 else if (to && to != NONE((void *)-1) && leg->leg_remote == NULL((void*)0)) {
4407 what = "cannot duplicate remote address";
4408 goto err;
4409 }
4410 else if (route && route != NONE((void *)-1) && leg->leg_route == NULL((void*)0)) {
4411 what = "cannot duplicate route";
4412 goto err;
4413 }
4414 else if (contact && contact != NONE((void *)-1) && leg->leg_target == NULL((void*)0)) {
4415 what = "cannot duplicate target";
4416 goto err;
4417 }
4418 else if (url_string && leg->leg_url == NULL((void*)0)) {
4419 what = "cannot duplicate local destination";
4420 goto err;
4421 }
4422
4423 if (!no_dialog) {
4424 if (!leg->leg_local || !leg->leg_remote) {
4425 /* To and/or From header missing */
4426 if (leg->leg_remote)
4427 what = "Missing local dialog address";
4428 else if (leg->leg_local)
4429 what = "Missing remote dialog address";
4430 else
4431 what = "Missing dialog addresses";
4432 goto err;
4433 }
4434
4435 leg->leg_dialog = 1;
4436
4437 if (i != NULL((void*)0))
4438 leg->leg_id = sip_call_id_dup(home, i);
4439 else if (i_str != NULL((void*)0))
4440 leg->leg_id = sip_call_id_make(home, i_str);
4441 else
4442 leg->leg_id = sip_call_id_create(home, NULL((void*)0));
4443
4444 if (!leg->leg_id) {
4445 what = "cannot create Call-ID";
4446 goto err;
4447 }
4448
4449 leg->leg_hash = leg->leg_id->i_hash;
4450 }
4451 else if (url) {
4452 /* This is "default leg" with a destination URL. */
4453 hash_value_t hash = 0;
4454
4455 if (method) {
4456 leg->leg_method = su_strdup(home, method);
4457 }
4458#if 0
4459 else if (url->url_params) {
4460 int len = url_param(url->url_params, "method", NULL((void*)0), 0);
4461 if (len) {
4462 char *tmp = su_alloc(home, len);
4463 leg->leg_method = tmp;
4464 url_param(url->url_params, "method", tmp, len);
4465 }
4466 }
4467#endif
4468
4469 if (url->url_user && strcmp(url->url_user, "") == 0)
4470 url->url_user = "%"; /* Match to any user */
4471
4472 hash = hash_istring(url->url_scheme, ":", 0);
4473 hash = hash_istring(url->url_host, "", hash);
4474 hash = hash_istring(url->url_user, "@", hash);
4475
4476 leg->leg_hash = hash;
4477 }
4478 else {
4479 /* This is "default leg" without a destination URL. */
4480 if (agent->sa_default_leg) {
4481 SU_DEBUG_1(("%s(): %s\n", "nta_leg_tcreate", "tried to create second default leg"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 4481, "%s(): %s\n", "nta_leg_tcreate", "tried to create second default leg"
)) : (void)0)
;
4482 su_seterrno(EEXIST17);
4483 goto err;
4484 }
4485 else {
4486 agent->sa_default_leg = leg;
4487 }
4488 return leg;
4489 }
4490
4491 if (url) {
4492 /* Parameters are ignored when comparing incoming URLs */
4493 url->url_params = NULL((void*)0);
4494 }
4495
4496 leg_insert(agent, leg);
4497
4498 SU_DEBUG_9(("%s(%p)\n", "nta_leg_tcreate", (void *)leg))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 4498, "%s(%p)\n", "nta_leg_tcreate", (void *)leg)) : (void)
0)
;
4499
4500 return leg;
4501
4502 err:
4503 if (what)
4504 SU_DEBUG_9(("%s(): %s\n", "nta_leg_tcreate", what))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 4504, "%s(): %s\n", "nta_leg_tcreate", what)) : (void)0)
;
4505
4506 su_home_zap(leg->leg_home)su_home_unref((leg->leg_home));
4507
4508 return NULL((void*)0);
4509}
4510
4511/** Return the default leg, if any */
4512nta_leg_t *nta_default_leg(nta_agent_t const *agent)
4513{
4514 return agent ? agent->sa_default_leg : NULL((void*)0);
4515}
4516
4517
4518/**
4519 * Insert a call leg to agent.
4520 */
4521static
4522void leg_insert(nta_agent_t *sa, nta_leg_t *leg)
4523{
4524 leg_htable_t *leg_hash;
4525 assert(leg)((void) sizeof ((leg) ? 1 : 0), __extension__ ({ if (leg) ; else
__assert_fail ("leg", "nta.c", 4525, __extension__ __PRETTY_FUNCTION__
); }))
;
4526 assert(sa)((void) sizeof ((sa) ? 1 : 0), __extension__ ({ if (sa) ; else
__assert_fail ("sa", "nta.c", 4526, __extension__ __PRETTY_FUNCTION__
); }))
;
4527
4528 if (leg->leg_dialog)
4529 leg_hash = sa->sa_dialogs;
4530 else
4531 leg_hash = sa->sa_defaults;
4532
4533 if (leg_htable_is_full(leg_hash)) {
4534 leg_htable_resize(sa->sa_home, leg_hash, 0);
4535 assert(leg_hash->lht_table)((void) sizeof ((leg_hash->lht_table) ? 1 : 0), __extension__
({ if (leg_hash->lht_table) ; else __assert_fail ("leg_hash->lht_table"
, "nta.c", 4535, __extension__ __PRETTY_FUNCTION__); }))
;
4536 SU_DEBUG_7(("nta: resized%s leg hash to "MOD_ZU"\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 4537, "nta: resized%s leg hash to ""%zu""\n", leg->leg_dialog
? "" : " default", leg_hash->lht_size)) : (void)0)
4537 leg->leg_dialog ? "" : " default", leg_hash->lht_size))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 4537, "nta: resized%s leg hash to ""%zu""\n", leg->leg_dialog
? "" : " default", leg_hash->lht_size)) : (void)0)
;
4538 }
4539
4540 /* Insert entry into hash table (before other legs with same hash) */
4541 leg_htable_insert(leg_hash, leg);
4542}
4543
4544/**
4545 * Destroy a leg.
4546 *
4547 * @param leg leg to be destroyed
4548 */
4549void nta_leg_destroy(nta_leg_t *leg)
4550{
4551 SU_DEBUG_9(("nta_leg_destroy(%p)\n", (void *)leg))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 4551, "nta_leg_destroy(%p)\n", (void *)leg)) : (void)0)
;
4552
4553 if (leg) {
4554 leg_htable_t *leg_hash;
4555 nta_agent_t *sa = leg->leg_agent;
4556
4557 assert(sa)((void) sizeof ((sa) ? 1 : 0), __extension__ ({ if (sa) ; else
__assert_fail ("sa", "nta.c", 4557, __extension__ __PRETTY_FUNCTION__
); }))
;
4558
4559 if (leg->leg_dialog) {
4560 assert(sa->sa_dialogs)((void) sizeof ((sa->sa_dialogs) ? 1 : 0), __extension__ (
{ if (sa->sa_dialogs) ; else __assert_fail ("sa->sa_dialogs"
, "nta.c", 4560, __extension__ __PRETTY_FUNCTION__); }))
;
4561 leg_hash = sa->sa_dialogs;
4562 }
4563 else if (leg != sa->sa_default_leg) {
4564 assert(sa->sa_defaults)((void) sizeof ((sa->sa_defaults) ? 1 : 0), __extension__ (
{ if (sa->sa_defaults) ; else __assert_fail ("sa->sa_defaults"
, "nta.c", 4564, __extension__ __PRETTY_FUNCTION__); }))
;
4565 leg_hash = sa->sa_defaults;
4566 }
4567 else {
4568 sa->sa_default_leg = NULL((void*)0);
4569 leg_hash = NULL((void*)0);
4570 }
4571
4572 if (leg_hash)
4573 leg_htable_remove(leg_hash, leg);
4574
4575 leg_free(sa, leg);
4576 }
4577}
4578
4579static
4580void leg_free(nta_agent_t *sa, nta_leg_t *leg)
4581{
4582 //su_free(sa->sa_home, leg);
4583 su_home_unref((su_home_t *)leg);
4584}
4585
4586/** Return application context for the leg */
4587nta_leg_magic_t *nta_leg_magic(nta_leg_t const *leg,
4588 nta_request_f *callback)
4589{
4590 if (leg)
4591 if (!callback || leg->leg_callback == callback)
4592 return leg->leg_magic;
4593
4594 return NULL((void*)0);
4595}
4596
4597/**Bind a callback function and context to a leg object.
4598 *
4599 * Change the callback function and context pointer attached to a leg
4600 * object.
4601 *
4602 * @param leg leg object to be bound
4603 * @param callback new callback function (or NULL if no callback is desired)
4604 * @param magic new context pointer
4605 */
4606void nta_leg_bind(nta_leg_t *leg,
4607 nta_request_f *callback,
4608 nta_leg_magic_t *magic)
4609{
4610 if (leg) {
4611 if (callback)
4612 leg->leg_callback = callback;
4613 else
4614 leg->leg_callback = leg_callback_default;
4615 leg->leg_magic = magic;
4616 }
4617}
4618
4619/** Add a local tag to the leg.
4620 *
4621 * @param leg leg to be tagged
4622 * @param tag tag to be added (if NULL, a tag generated by @b NTA is added)
4623 *
4624 * @return
4625 * Pointer to tag if successful, NULL otherwise.
4626 */
4627char const *nta_leg_tag(nta_leg_t *leg, char const *tag)
4628{
4629 if (!leg || !leg->leg_local)
4630 return su_seterrno(EINVAL22), NULL((void*)0);
4631
4632 if (tag && strchr(tag, '='))
4633 tag = strchr(tag, '=') + 1;
4634
4635 /* If there already is a tag,
4636 return NULL if it does not match with new one */
4637 if (leg->leg_local->a_tag) {
4638 if (tag == NULL((void*)0) || su_casematch(tag, leg->leg_local->a_tag))
4639 return leg->leg_local->a_tag;
4640 else
4641 return NULL((void*)0);
4642 }
4643
4644 if (tag) {
4645 if (sip_to_tag(leg->leg_home, leg->leg_local, tag) < 0)
4646 return NULL((void*)0);
4647 leg->leg_tagged = 1;
4648 return leg->leg_local->a_tag;
4649 }
4650
4651 tag = nta_agent_newtag(leg->leg_home, "tag=%s", leg->leg_agent);
4652
4653 if (!tag || sip_to_add_param(leg->leg_home, leg->leg_local, tag) < 0)
4654 return NULL((void*)0);
4655
4656 leg->leg_tagged = 1;
4657
4658 return leg->leg_local->a_tag;
4659}
4660
4661/** Get local tag. */
4662char const *nta_leg_get_tag(nta_leg_t const *leg)
4663{
4664 if (leg && leg->leg_local)
4665 return leg->leg_local->a_tag;
4666 else
4667 return NULL((void*)0);
4668}
4669
4670/** Add a remote tag to the leg.
4671 *
4672 * @note No remote tag is ever generated.
4673 *
4674 * @param leg leg to be tagged
4675 * @param tag tag to be added (@b must be non-NULL)
4676 *
4677 * @return
4678 * Pointer to tag if successful, NULL otherwise.
4679 */
4680char const *nta_leg_rtag(nta_leg_t *leg, char const *tag)
4681{
4682 /* Add a tag parameter, unless there already is a tag */
4683 if (leg && leg->leg_remote && tag) {
4684 if (sip_from_tag(leg->leg_home, leg->leg_remote, tag) < 0)
4685 return NULL((void*)0);
4686 }
4687
4688 if (leg && leg->leg_remote)
4689 return leg->leg_remote->a_tag;
4690 else
4691 return NULL((void*)0);
4692}
4693
4694/** Get remote tag. */
4695char const *nta_leg_get_rtag(nta_leg_t const *leg)
4696{
4697 if (leg && leg->leg_remote)
4698 return leg->leg_remote->a_tag;
4699 else
4700 return NULL((void*)0);
4701}
4702
4703/** Get local request sequence number. */
4704uint32_t nta_leg_get_seq(nta_leg_t const *leg)
4705{
4706 return leg ? leg->leg_seq : 0;
4707}
4708
4709/** Get remote request sequence number. */
4710uint32_t nta_leg_get_rseq(nta_leg_t const *leg)
4711{
4712 return leg ? leg->leg_rseq : 0;
4713}
4714
4715/** Save target and route set at UAC side.
4716 *
4717 * @sa nta_leg_client_reroute(), nta_leg_server_route(), @RFC3261 section 12.1.2
4718 *
4719 * @bug Allows modifying the route set after initial transaction, if initial
4720 * transaction had no @RecordRoute headers.
4721 *
4722 * @deprecated Use nta_leg_client_reroute() instead.
4723 */
4724int nta_leg_client_route(nta_leg_t *leg,
4725 sip_record_route_t const *route,
4726 sip_contact_t const *contact)
4727{
4728 return leg_route(leg, NULL((void*)0), route, contact, 0);
4729}
4730
4731/** Save target and route set at UAC side.
4732 *
4733 * If @a initial is true, the route set is modified even if it has been set
4734 * earlier.
4735 *
4736 * @param leg pointer to dialog leg
4737 * @param route @RecordRoute headers from response
4738 * @param contact @Contact header from response
4739 * @param initial true if response to initial transaction
4740 *
4741 * @sa nta_leg_client_route(), nta_leg_server_route(), @RFC3261 section 12.1.2
4742 *
4743 * @NEW_1_12_11
4744 */
4745int nta_leg_client_reroute(nta_leg_t *leg,
4746 sip_record_route_t const *route,
4747 sip_contact_t const *contact,
4748 int initial)
4749{
4750 return leg_route(leg, NULL((void*)0), route, contact, initial ? 2 : 1);
4751}
4752
4753/** Save target and route set at UAS side.
4754 *
4755 * @param leg pointer to dialog leg
4756 * @param route @RecordRoute headers from request
4757 * @param contact @Contact header from request
4758 *
4759 * @sa nta_leg_client_reroute(), @RFC3261 section 12.1.1
4760 */
4761int nta_leg_server_route(nta_leg_t *leg,
4762 sip_record_route_t const *route,
4763 sip_contact_t const *contact)
4764{
4765 return leg_route(leg, route, NULL((void*)0), contact, 1);
4766}
4767
4768/** Return route components. */
4769int nta_leg_get_route(nta_leg_t *leg,
4770 sip_route_t const **return_route,
4771 sip_contact_t const **return_target)
4772{
4773 if (!leg)
4774 return -1;
4775
4776 if (return_route)
4777 *return_route = leg->leg_route;
4778
4779 if (return_target)
4780 *return_target = leg->leg_target;
4781
4782 return 0;
4783}
4784
4785/** Generate @Replaces header.
4786 *
4787 * @since New in @VERSION_1_12_2.
4788 */
4789sip_replaces_t *
4790nta_leg_make_replaces(nta_leg_t *leg,
4791 su_home_t *home,
4792 int early_only)
4793{
4794 char const *from_tag, *to_tag;
4795
4796 if (!leg)
4797 return NULL((void*)0);
4798 if (!leg->leg_dialog || !leg->leg_local || !leg->leg_remote || !leg->leg_id)
4799 return NULL((void*)0);
4800
4801 from_tag = leg->leg_local->a_tag; if (!from_tag) from_tag = "0";
4802 to_tag = leg->leg_remote->a_tag; if (!to_tag) to_tag = "0";
4803
4804 return sip_replaces_format(home, "%s;from-tag=%s;to-tag=%s%s",
4805 leg->leg_id->i_id, from_tag, to_tag,
4806 early_only ? ";early-only" : "");
4807}
4808
4809/** Get dialog leg by @Replaces header.
4810 *
4811 * @since New in @VERSION_1_12_2.
4812 */
4813nta_leg_t *
4814nta_leg_by_replaces(nta_agent_t *sa, sip_replaces_t const *rp)
4815{
4816 nta_leg_t *leg = NULL((void*)0);
4817
4818 if (sa && rp && rp->rp_call_id && rp->rp_from_tag && rp->rp_to_tag) {
4819 char const *from_tag = rp->rp_from_tag, *to_tag = rp->rp_to_tag;
4820 sip_call_id_t id[1];
4821 sip_call_id_init(id);
4822
4823 id->i_hash = msg_hash_string(id->i_id = rp->rp_call_id);
4824
4825 leg = leg_find(sa, NULL((void*)0), NULL((void*)0), id, from_tag, to_tag);
4826
4827 if (leg == NULL((void*)0) && strcmp(from_tag, "0") == 0)
4828 leg = leg_find(sa, NULL((void*)0), NULL((void*)0), id, NULL((void*)0), to_tag);
4829 if (leg == NULL((void*)0) && strcmp(to_tag, "0") == 0)
4830 leg = leg_find(sa, NULL((void*)0), NULL((void*)0), id, from_tag, NULL((void*)0));
4831 }
4832
4833 return leg;
4834}
4835
4836/**@internal
4837 * Find a leg corresponding to the request message.
4838 *
4839 */
4840static nta_leg_t *
4841leg_find_call_id(nta_agent_t const *sa,
4842 sip_call_id_t const *i)
4843{
4844 hash_value_t hash = i->i_hash;
4845 leg_htable_t const *lht = sa->sa_dialogs;
4846 nta_leg_t **ll, *leg = NULL((void*)0);
4847
4848 for (ll = leg_htable_hash(lht, hash);
4849 (leg = *ll);
4850 ll = leg_htable_next(lht, ll)) {
4851 sip_call_id_t const *leg_i = leg->leg_id;
4852
4853 if (leg->leg_hash != hash)
4854 continue;
4855 if (strcmp(leg_i->i_id, i->i_id) != 0)
4856 continue;
4857
4858 return leg;
4859 }
4860
4861 return leg;
4862}
4863
4864/** Get dialog leg by @CallID.
4865 *
4866 * @note Usually there should be only single dialog per @CallID on
4867 * User-Agents. However, proxies may fork requests initiating the dialog and
4868 * result in multiple calls per @CallID.
4869 *
4870 * @since New in @VERSION_1_12_9.
4871 */
4872nta_leg_t *
4873nta_leg_by_call_id(nta_agent_t *sa, const char *call_id)
4874{
4875 nta_leg_t *leg = NULL((void*)0);
4876
4877 if (call_id) {
4878 sip_call_id_t id[1];
4879 sip_call_id_init(id);
4880
4881 id->i_hash = msg_hash_string(id->i_id = call_id);
4882
4883 leg = leg_find_call_id(sa, id);
4884 }
4885
4886 return leg;
4887}
4888
4889/** Calculate a simple case-insensitive hash over a string */
4890su_inlinestatic inline
4891hash_value_t hash_istring(char const *s, char const *term, hash_value_t hash)
4892{
4893 if (s) {
4894 for (; *s; s++) {
4895 unsigned char c = *s;
4896 if ('A' <= c && c <= 'Z')
4897 c += 'a' - 'A';
4898 hash = 38501U * (hash + c);
4899 }
4900 for (s = term; *s; s++) {
4901 unsigned char c = *s;
4902 hash = 38501U * (hash + c);
4903 }
4904 }
4905
4906 return hash;
4907}
4908
4909/** @internal Handle requests intended for this leg. */
4910static
4911void leg_recv(nta_leg_t *leg, msg_t *msg, sip_t *sip, tport_t *tport)
4912{
4913 nta_agent_t *agent = leg->leg_agent;
4914 nta_incoming_t *irq;
4915 sip_method_t method = sip->sip_request->rq_method;
4916 char const *method_name = sip->sip_request->rq_method_name;
4917 char const *tag = NULL((void*)0);
4918 int status;
4919
4920 if (leg->leg_local)
4921 tag = leg->leg_local->a_tag;
4922
4923 if (leg->leg_dialog)
4924 agent->sa_stats->as_dialog_tr++;
4925
4926 /* RFC-3262 section 3 (page 4) */
4927 if (agent->sa_is_a_uas && method == sip_method_prack) {
4928 mreply(agent, NULL((void*)0), 481, "No such response", msg,
4929 tport, 0, 0, NULL((void*)0),
4930 TAG_END()(tag_type_t)0, (tag_value_t)0);
4931 return;
4932 }
4933
4934 if (!(irq = incoming_create(agent, msg, sip, tport, tag))) {
4935 SU_DEBUG_3(("nta: leg_recv(%p): cannot create transaction for %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4936, "nta: leg_recv(%p): cannot create transaction for %s\n"
, (void *)leg, method_name)) : (void)0)
4936 (void *)leg, method_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4936, "nta: leg_recv(%p): cannot create transaction for %s\n"
, (void *)leg, method_name)) : (void)0)
;
4937 mreply(agent, NULL((void*)0), SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error, msg,
4938 tport, 0, 0, NULL((void*)0),
4939 TAG_END()(tag_type_t)0, (tag_value_t)0);
4940 return;
4941 }
4942
4943 irq->irq_compressed = leg->leg_compressed;
4944 irq->irq_in_callback = 1;
4945 status = incoming_callback(leg, irq, sip);
4946 irq->irq_in_callback = 0;
4947
4948 if (irq->irq_destroyed) {
4949 if (irq->irq_terminated) {
4950 incoming_free(irq);
4951 return;
4952 }
4953 if (status < 200)
4954 status = 500;
4955 }
4956
4957 if (status == 0)
4958 return;
4959
4960 if (status < 100 || status > 699) {
4961 SU_DEBUG_3(("nta_leg(%p): invalid status %03d from callback\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4962, "nta_leg(%p): invalid status %03d from callback\n", (
void *)leg, status)) : (void)0)
4962 (void *)leg, status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4962, "nta_leg(%p): invalid status %03d from callback\n", (
void *)leg, status)) : (void)0)
;
4963 status = 500;
4964 }
4965 else if (method == sip_method_invite && status >= 200 && status < 300) {
4966 SU_DEBUG_3(("nta_leg(%p): invalid INVITE status %03d from callback\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4967, "nta_leg(%p): invalid INVITE status %03d from callback\n"
, (void *)leg, status)) : (void)0)
4967 (void *)leg, status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 4967, "nta_leg(%p): invalid INVITE status %03d from callback\n"
, (void *)leg, status)) : (void)0)
;
4968 status = 500;
4969 }
4970
4971 if (status >= 100 && irq->irq_status < 200)
4972 nta_incoming_treply(irq, status, NULL((void*)0), TAG_END()(tag_type_t)0, (tag_value_t)0);
4973
4974 if (status >= 200)
4975 nta_incoming_destroy(irq);
4976}
4977
4978#if 0
4979/**Compare two SIP from/to fields.
4980 *
4981 * @retval nonzero if matching.
4982 * @retval zero if not matching.
4983 */
4984su_inlinestatic inline
4985int addr_cmp(url_t const *a, url_t const *b)
4986{
4987 if (b == NULL((void*)0))
4988 return 0;
4989 else
4990 return
4991 host_cmp(a->url_host, b->url_host) ||
4992 su_strcmp(a->url_port, b->url_port) ||
4993 su_strcmp(a->url_user, b->url_user);
4994}
4995#endif
4996
4997/** Get a leg by dialog.
4998 *
4999 * Search for a dialog leg from agent's hash table. The matching rules based
5000 * on parameters are as follows:
5001 *
5002 * @param agent pointer to agent object
5003 * @param request_uri if non-NULL, and there is destination URI
5004 * associated with the dialog, these URIs must match
5005 * @param call_id if non-NULL, must match with @CallID header contents
5006 * @param remote_tag if there is remote tag
5007 * associated with dialog, @a remote_tag must match
5008 * @param remote_uri ignored
5009 * @param local_tag if non-NULL and there is local tag associated with leg,
5010 * it must math
5011 * @param local_uri ignored
5012 *
5013 * @note
5014 * If @a remote_tag or @a local_tag is an empty string (""), the tag is
5015 * ignored when matching legs.
5016 */
5017nta_leg_t *nta_leg_by_dialog(nta_agent_t const *agent,
5018 url_t const *request_uri,
5019 sip_call_id_t const *call_id,
5020 char const *remote_tag,
5021 url_t const *remote_uri,
5022 char const *local_tag,
5023 url_t const *local_uri)
5024{
5025 void *to_be_freed = NULL((void*)0);
5026 url_t *url;
5027 url_t url0[1];
5028 nta_leg_t *leg;
5029
5030 if (!agent || !call_id)
5031 return su_seterrno(EINVAL22), NULL((void*)0);
5032
5033 if (request_uri == NULL((void*)0)) {
5034 url = NULL((void*)0);
5035 }
5036 else if (URL_IS_STRING(request_uri)((request_uri) && *((url_string_t*)(request_uri))->
us_str != 0)
) {
5037 /* accept a string as URL */
5038 to_be_freed = url = url_hdup(NULL((void*)0), request_uri);
5039 }
5040 else {
5041 *url0 = *request_uri, url = url0;
5042 }
5043
5044 if (url) {
5045 url->url_params = NULL((void*)0);
5046 agent_aliases(agent, url, NULL((void*)0)); /* canonize url */
5047 }
5048
5049 if (remote_tag && remote_tag[0] == '\0')
5050 remote_tag = NULL((void*)0);
5051 if (local_tag && local_tag[0] == '\0')
5052 local_tag = NULL((void*)0);
5053
5054 leg = leg_find(agent,
5055 NULL((void*)0), url,
5056 call_id,
5057 remote_tag,
5058 local_tag);
5059
5060 if (to_be_freed) su_free(NULL((void*)0), to_be_freed);
5061
5062 return leg;
5063}
5064
5065/**@internal
5066 * Find a leg corresponding to the request message.
5067 *
5068 * A leg matches to message if leg_match_request() returns true ("Call-ID",
5069 * "To"-tag, and "From"-tag match).
5070 */
5071static
5072nta_leg_t *leg_find(nta_agent_t const *sa,
5073 char const *method_name,
5074 url_t const *request_uri,
5075 sip_call_id_t const *i,
5076 char const *from_tag,
5077 char const *to_tag)
5078{
5079 hash_value_t hash = i->i_hash;
5080 leg_htable_t const *lht = sa->sa_dialogs;
5081 nta_leg_t **ll, *leg, *loose_match = NULL((void*)0);
5082
5083 for (ll = leg_htable_hash(lht, hash);
5084 (leg = *ll);
5085 ll = leg_htable_next(lht, ll)) {
5086 sip_call_id_t const *leg_i = leg->leg_id;
5087 char const *remote_tag = leg->leg_remote->a_tag;
5088 char const *local_tag = leg->leg_local->a_tag;
5089
5090 url_t const *leg_url = leg->leg_url;
5091 char const *leg_method = leg->leg_method;
5092
5093 if (leg->leg_hash != hash)
5094 continue;
5095 if (strcmp(leg_i->i_id, i->i_id) != 0)
5096 continue;
5097
5098 /* Do not match if the incoming To has tag, but the local does not */
5099 if (!local_tag && to_tag)
5100 continue;
5101
5102 /*
5103 * Do not match if incoming To has no tag and we have local tag
5104 * and the tag has been there from the beginning.
5105 */
5106 if (local_tag && !to_tag && !leg->leg_tagged)
5107 continue;
5108
5109 /* Do not match if incoming From has no tag but remote has a tag */
5110 if (remote_tag && !from_tag)
5111 continue;
5112
5113 /* Avoid matching with itself */
5114 if (!remote_tag != !from_tag && !local_tag != !to_tag)
5115 continue;
5116
5117 if (local_tag && to_tag && !su_casematch(local_tag, to_tag) && to_tag[0])
5118 continue;
5119 if (remote_tag && from_tag && !su_casematch(remote_tag, from_tag) && from_tag[0])
5120 continue;
5121
5122 if (leg_url && request_uri && url_cmp(leg_url, request_uri))
5123 continue;
5124 if (leg_method && method_name && !su_casematch(method_name, leg_method))
5125 continue;
5126
5127 /* Perfect match if both local and To have tag
5128 * or local does not have tag.
5129 */
5130 if ((!local_tag || to_tag))
5131 return leg;
5132
5133 if (loose_match == NULL((void*)0))
5134 loose_match = leg;
5135 }
5136
5137 return loose_match;
5138}
5139
5140/** Get leg by destination */
5141nta_leg_t *nta_leg_by_uri(nta_agent_t const *agent, url_string_t const *us)
5142{
5143 url_t *url;
5144 nta_leg_t *leg = NULL((void*)0);
5145
5146 if (!agent)
5147 return NULL((void*)0);
5148
5149 if (!us)
5150 return agent->sa_default_leg;
5151
5152 url = url_hdup(NULL((void*)0), us->us_url);
5153
5154 if (url) {
5155 agent_aliases(agent, url, NULL((void*)0));
5156 leg = dst_find(agent, url, NULL((void*)0));
5157 su_free(NULL((void*)0), url);
5158 }
5159
5160 return leg;
5161}
5162
5163/** Find a non-dialog leg corresponding to the request uri u0 */
5164static
5165nta_leg_t *dst_find(nta_agent_t const *sa,
5166 url_t const *u0,
5167 char const *method_name)
5168{
5169 hash_value_t hash, hash2;
5170 leg_htable_t const *lht = sa->sa_defaults;
5171 nta_leg_t **ll, *leg, *loose_match = NULL((void*)0);
5172 int again;
5173 url_t url[1];
5174
5175 *url = *u0;
5176 hash = hash_istring(url->url_scheme, ":", 0);
5177 hash = hash_istring(url->url_host, "", hash);
5178 hash2 = hash_istring("%", "@", hash);
5179 hash = hash_istring(url->url_user, "@", hash);
5180
5181 /* First round, search with user name */
5182 /* Second round, search without user name */
5183 do {
5184 for (ll = leg_htable_hash(lht, hash);
5185 (leg = *ll);
5186 ll = leg_htable_next(lht, ll)) {
5187 if (leg->leg_hash != hash)
5188 continue;
5189 if (url_cmp(url, leg->leg_url))
5190 continue;
5191 if (!method_name) {
5192 if (leg->leg_method)
5193 continue;
5194 return leg;
5195 }
5196 else if (leg->leg_method) {
5197 if (!su_casematch(method_name, leg->leg_method))
5198 continue;
5199 return leg;
5200 }
5201 loose_match = leg;
5202 }
5203 if (loose_match)
5204 return loose_match;
5205
5206 again = 0;
5207
5208 if (url->url_user && strcmp(url->url_user, "%")) {
5209 url->url_user = "%";
5210 hash = hash2;
5211 again = 1;
5212 }
5213 } while (again);
5214
5215 return NULL((void*)0);
5216}
5217
5218/** Set leg route and target URL.
5219 *
5220 * Sets the leg route and contact using the @RecordRoute and @Contact
5221 * headers.
5222 *
5223 * @param reroute - allow rerouting
5224 * - if 1, follow @RFC3261 semantics
5225 * - if 2, response to initial transaction)
5226 */
5227static
5228int leg_route(nta_leg_t *leg,
5229 sip_record_route_t const *route,
5230 sip_record_route_t const *reverse,
5231 sip_contact_t const *contact,
5232 int reroute)
5233{
5234 su_home_t *home = leg->leg_home;
5235 sip_route_t *r, r0[1], *old;
5236 int route_is_set;
5237
5238 if (!leg)
5239 return -1;
5240
5241 if (route == NULL((void*)0) && reverse == NULL((void*)0) && contact == NULL((void*)0))
5242 return 0;
5243
5244 sip_route_init(r0);
5245
5246 route_is_set = reroute ? leg->leg_route_set : leg->leg_route != NULL((void*)0);
5247
5248 if (route_is_set && reroute <= 1) {
5249 r = leg->leg_route;
5250 }
5251 else if (route) {
5252 r = sip_route_fixdup(home, route); if (!r) return -1;
5253 }
5254 else if (reverse) {
5255 r = sip_route_reverse(home, reverse); if (!r) return -1;
5256 }
5257 else
5258 r = NULL((void*)0);
5259
5260#ifdef NTA_STRICT_ROUTING
5261 /*
5262 * Handle Contact according to the RFC2543bis04 sections 16.1, 16.2 and 16.4.
5263 */
5264 if (contact) {
5265 *r0->r_url = *contact->m_url;
5266
5267 if (!(m_r = sip_route_dup(leg->leg_home, r0)))
5268 return -1;
5269
5270 /* Append, but replace last entry if it was generated from contact */
5271 for (rr = &r; *rr; rr = &(*rr)->r_next)
5272 if (leg->leg_contact_set && (*rr)->r_next == NULL((void*)0))
5273 break;
5274 }
5275 else
5276 rr = NULL((void*)0);
5277
5278 if (rr) {
5279 if (*rr)
5280 su_free(leg->leg_home, *rr);
5281 *rr = m_r;
5282 }
5283 if (m_r != NULL((void*)0))
5284 leg->leg_contact_set = 1;
5285
5286#else
5287 if (r && r->r_url->url_params)
5288 leg->leg_loose_route = url_has_param(r->r_url, "lr");
5289
5290 if (contact) {
5291 sip_contact_t *target, m[1], *m0;
5292
5293 sip_contact_init(m);
5294 *m->m_url = *contact->m_url;
5295 m->m_url->url_headers = NULL((void*)0);
5296 target = sip_contact_dup(leg->leg_home, m);
5297
5298 if (target && target->m_url->url_params) {
5299 /* Remove ttl, method. @RFC3261 table 1, page 152 */
5300 char *p = (char *)target->m_url->url_params;
5301 p = url_strip_param_string(p, "method");
5302 p = url_strip_param_string(p, "ttl");
5303 target->m_url->url_params = p;
5304 }
5305
5306 m0 = leg->leg_target, leg->leg_target = target;
5307
5308 if (m0)
5309 su_free(leg->leg_home, m0);
5310 }
5311#endif
5312
5313 old = leg->leg_route;
5314 leg->leg_route = r;
5315
5316 if (old && old != r)
5317 msg_header_free(leg->leg_home, (msg_header_t *)old);
5318
5319 leg->leg_route_set = 1;
5320
5321 return 0;
5322}
5323
5324/** @internal Default leg callback. */
5325static int
5326leg_callback_default(nta_leg_magic_t *magic,
5327 nta_leg_t *leg,
5328 nta_incoming_t *irq,
5329 sip_t const *sip)
5330{
5331 nta_incoming_treply(irq,
5332 SIP_501_NOT_IMPLEMENTED501, sip_501_Not_implemented,
5333 TAG_END()(tag_type_t)0, (tag_value_t)0);
5334 return 501;
5335}
5336
5337/* ====================================================================== */
5338/* 7) Server-side (incoming) transactions */
5339
5340#define HTABLE_HASH_IRQ(irq)((irq)->irq_hash) ((irq)->irq_hash)
5341HTABLE_BODIES_WITH(incoming_htable, iht, nta_incoming_t, HTABLE_HASH_IRQ,static inline int incoming_htable_resize(su_home_t *home, incoming_htable_t
iht[], size_t new_size) { nta_incoming_t **new_hash; nta_incoming_t
**old_hash = iht->iht_table; size_t old_size; size_t i, j
, i0; unsigned again = 0; size_t used = 0; if (new_size == 0)
new_size = 2 * iht->iht_size + 1; if (new_size < 31) new_size
= 31; if (new_size < 5 * iht->iht_used / 4) new_size =
5 * iht->iht_used / 4; if (!(new_hash = su_zalloc(home, sizeof
(*new_hash) * new_size))) return -1; old_size = iht->iht_size
; do for (j = 0; j < old_size; j++) { if (!old_hash[j]) continue
; if (again < 2 && ((old_hash[j])->irq_hash) % old_size
> j) { again = 1; continue; } i0 = ((old_hash[j])->irq_hash
) % new_size; for (i = i0; new_hash[i]; i = (i + 1) % new_size
, ((void) sizeof ((i != i0) ? 1 : 0), __extension__ ({ if (i !=
i0) ; else __assert_fail ("i != i0", "nta.c", 5342, __extension__
__PRETTY_FUNCTION__); }))); new_hash[i] = old_hash[j], old_hash
[j] = ((void*)0); used++; } while (again++ == 1); iht->iht_table
= new_hash, iht->iht_size = new_size; ((void) sizeof ((iht
->iht_used == used) ? 1 : 0), __extension__ ({ if (iht->
iht_used == used) ; else __assert_fail ("iht->iht_used == used"
, "nta.c", 5342, __extension__ __PRETTY_FUNCTION__); })); su_free
(home, old_hash); return 0; } static inline int incoming_htable_is_full
(incoming_htable_t const *iht) { return iht->iht_table == (
(void*)0) || 3 * iht->iht_used > 2 * iht->iht_size; }
static inline nta_incoming_t **incoming_htable_hash(incoming_htable_t
const *iht, hash_value_t hv) { return iht->iht_table + hv
% iht->iht_size; } static inline nta_incoming_t **incoming_htable_next
(incoming_htable_t const *iht, nta_incoming_t * const *ee) { if
(++ee < iht->iht_table + iht->iht_size && ee
>= iht->iht_table) return (nta_incoming_t **)ee; else return
iht->iht_table; } static inline void incoming_htable_append
(incoming_htable_t *iht, nta_incoming_t const *e) { nta_incoming_t
**ee; iht->iht_used++; for (ee = incoming_htable_hash(iht
, ((e)->irq_hash)); *ee; ee = incoming_htable_next(iht, ee
)) ; *ee = (nta_incoming_t *)e; } static inline void incoming_htable_insert
(incoming_htable_t *iht, nta_incoming_t const *e) { nta_incoming_t
*e0, **ee; iht->iht_used++; for (ee = incoming_htable_hash
(iht, ((e)->irq_hash)); (e0 = *ee); ee = incoming_htable_next
(iht, ee)) *ee = (nta_incoming_t *)e, e = e0; *ee = (nta_incoming_t
*)e; } static inline int incoming_htable_remove(incoming_htable_t
*iht, nta_incoming_t const *e) { size_t i, j, k; size_t size
= iht->iht_size; nta_incoming_t **htable = iht->iht_table
; if (!e) return -1; for (i = ((e)->irq_hash) % size; htable
[i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->irq_hash) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } iht->iht_used--; htable[i] = ((void*)0); return 0; } extern
int incoming_htable_dummy
5342 size_t, hash_value_t)static inline int incoming_htable_resize(su_home_t *home, incoming_htable_t
iht[], size_t new_size) { nta_incoming_t **new_hash; nta_incoming_t
**old_hash = iht->iht_table; size_t old_size; size_t i, j
, i0; unsigned again = 0; size_t used = 0; if (new_size == 0)
new_size = 2 * iht->iht_size + 1; if (new_size < 31) new_size
= 31; if (new_size < 5 * iht->iht_used / 4) new_size =
5 * iht->iht_used / 4; if (!(new_hash = su_zalloc(home, sizeof
(*new_hash) * new_size))) return -1; old_size = iht->iht_size
; do for (j = 0; j < old_size; j++) { if (!old_hash[j]) continue
; if (again < 2 && ((old_hash[j])->irq_hash) % old_size
> j) { again = 1; continue; } i0 = ((old_hash[j])->irq_hash
) % new_size; for (i = i0; new_hash[i]; i = (i + 1) % new_size
, ((void) sizeof ((i != i0) ? 1 : 0), __extension__ ({ if (i !=
i0) ; else __assert_fail ("i != i0", "nta.c", 5342, __extension__
__PRETTY_FUNCTION__); }))); new_hash[i] = old_hash[j], old_hash
[j] = ((void*)0); used++; } while (again++ == 1); iht->iht_table
= new_hash, iht->iht_size = new_size; ((void) sizeof ((iht
->iht_used == used) ? 1 : 0), __extension__ ({ if (iht->
iht_used == used) ; else __assert_fail ("iht->iht_used == used"
, "nta.c", 5342, __extension__ __PRETTY_FUNCTION__); })); su_free
(home, old_hash); return 0; } static inline int incoming_htable_is_full
(incoming_htable_t const *iht) { return iht->iht_table == (
(void*)0) || 3 * iht->iht_used > 2 * iht->iht_size; }
static inline nta_incoming_t **incoming_htable_hash(incoming_htable_t
const *iht, hash_value_t hv) { return iht->iht_table + hv
% iht->iht_size; } static inline nta_incoming_t **incoming_htable_next
(incoming_htable_t const *iht, nta_incoming_t * const *ee) { if
(++ee < iht->iht_table + iht->iht_size && ee
>= iht->iht_table) return (nta_incoming_t **)ee; else return
iht->iht_table; } static inline void incoming_htable_append
(incoming_htable_t *iht, nta_incoming_t const *e) { nta_incoming_t
**ee; iht->iht_used++; for (ee = incoming_htable_hash(iht
, ((e)->irq_hash)); *ee; ee = incoming_htable_next(iht, ee
)) ; *ee = (nta_incoming_t *)e; } static inline void incoming_htable_insert
(incoming_htable_t *iht, nta_incoming_t const *e) { nta_incoming_t
*e0, **ee; iht->iht_used++; for (ee = incoming_htable_hash
(iht, ((e)->irq_hash)); (e0 = *ee); ee = incoming_htable_next
(iht, ee)) *ee = (nta_incoming_t *)e, e = e0; *ee = (nta_incoming_t
*)e; } static inline int incoming_htable_remove(incoming_htable_t
*iht, nta_incoming_t const *e) { size_t i, j, k; size_t size
= iht->iht_size; nta_incoming_t **htable = iht->iht_table
; if (!e) return -1; for (i = ((e)->irq_hash) % size; htable
[i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->irq_hash) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } iht->iht_used--; htable[i] = ((void*)0); return 0; } extern
int incoming_htable_dummy
;
5343
5344static void incoming_insert(nta_agent_t *agent,
5345 incoming_queue_t *queue,
5346 nta_incoming_t *irq);
5347
5348su_inlinestatic inline int incoming_is_queued(nta_incoming_t const *irq);
5349su_inlinestatic inline void incoming_queue(incoming_queue_t *queue, nta_incoming_t *);
5350su_inlinestatic inline void incoming_remove(nta_incoming_t *irq);
5351su_inlinestatic inline void incoming_set_timer(nta_incoming_t *, uint32_t interval);
5352su_inlinestatic inline void incoming_reset_timer(nta_incoming_t *);
5353su_inlinestatic inline size_t incoming_mass_destroy(nta_agent_t *, incoming_queue_t *);
5354
5355static int incoming_set_params(nta_incoming_t *irq, tagi_t const *tags);
5356su_inlinestatic inline
5357int incoming_set_compartment(nta_incoming_t *irq, tport_t *tport, msg_t *msg,
5358 int create_if_needed);
5359
5360su_inlinestatic inline nta_incoming_t
5361 *incoming_call_callback(nta_incoming_t *, msg_t *, sip_t *);
5362su_inlinestatic inline int incoming_final_failed(nta_incoming_t *irq, msg_t *);
5363static void incoming_retransmit_reply(nta_incoming_t *irq, tport_t *tport);
5364
5365/** Create a default server transaction.
5366 *
5367 * The default server transaction is used by a proxy to forward responses
5368 * statelessly.
5369 *
5370 * @param agent pointer to agent object
5371 *
5372 * @retval pointer to default server transaction object
5373 * @retval NULL if failed
5374 */
5375nta_incoming_t *nta_incoming_default(nta_agent_t *agent)
5376{
5377 msg_t *msg;
5378 su_home_t *home;
5379 nta_incoming_t *irq;
5380
5381 if (agent == NULL((void*)0))
5382 return su_seterrno(EFAULT14), NULL((void*)0);
5383 if (agent->sa_default_incoming)
5384 return su_seterrno(EEXIST17), NULL((void*)0);
5385
5386 msg = nta_msg_create(agent, 0);
5387 if (!msg)
5388 return NULL((void*)0);
5389
5390 irq = su_zalloc(home = msg_home(msg)((su_home_t*)(msg)), sizeof(*irq));
5391 if (!irq)
5392 return (void)msg_destroy(msg), NULL((void*)0);
5393
5394 irq->irq_home = home;
5395 irq->irq_request = NULL((void*)0);
5396 irq->irq_agent = agent;
5397 irq->irq_received = agent_now(agent);
5398 irq->irq_method = sip_method_invalid;
5399
5400 irq->irq_default = 1;
5401 agent->sa_default_incoming = irq;
5402
5403 return irq;
5404}
5405
5406/** Create a server transaction.
5407 *
5408 * Create a server transaction for a request message. This function is used
5409 * when an element processing requests statelessly wants to process a
5410 * particular request statefully.
5411 *
5412 * @param agent pointer to agent object
5413 * @param leg pointer to leg object (either @a agent or @a leg may be NULL)
5414 * @param msg pointer to message object
5415 * @param sip pointer to SIP structure (may be NULL)
5416 * @param tag,value,... optional tagged parameters
5417 *
5418 * @note
5419 * The ownership of @a msg is taken over by the function even if the
5420 * function fails.
5421 *
5422 * @TAGS
5423 * @TAG NTATAG_TPORT() specifies the transport used to receive the request
5424 * and also default transport for sending the response.
5425 *
5426 * @retval nta_incoming_t pointer to the newly created server transaction
5427 * @retval NULL if failed
5428 */
5429nta_incoming_t *nta_incoming_create(nta_agent_t *agent,
5430 nta_leg_t *leg,
5431 msg_t *msg,
5432 sip_t *sip,
5433 tag_type_t tag, tag_value_t value, ...)
5434{
5435 char const *to_tag = NULL((void*)0);
5436 tport_t *tport = NULL((void*)0);
5437 ta_list ta;
5438 nta_incoming_t *irq;
5439
5440 if (msg == NULL((void*)0))
5441 return NULL((void*)0);
5442
5443 if (agent == NULL((void*)0) && leg != NULL((void*)0))
5444 agent = leg->leg_agent;
5445
5446 if (sip == NULL((void*)0))
5447 sip = sip_object(msg);
5448
5449 if (agent == NULL((void*)0) || sip == NULL((void*)0) || !sip->sip_request || !sip->sip_cseq)
5450 return msg_destroy(msg), NULL((void*)0);
5451
5452 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
5453
5454 tl_gets(ta_args(ta)(ta).tl,
5455 NTATAG_TPORT_REF(tport)ntatag_tport_ref, tag_ptr_vr(&(tport), (tport)),
5456 TAG_END()(tag_type_t)0, (tag_value_t)0);
5457 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
5458
5459 if (leg && leg->leg_local)
5460 to_tag = leg->leg_local->a_tag;
5461
5462 if (tport == NULL((void*)0))
5463 tport = tport_delivered_by(agent->sa_tports, msg);
5464
5465 irq = incoming_create(agent, msg, sip, tport, to_tag);
5466
5467 if (!irq)
5468 msg_destroy(msg);
5469
5470 return irq;
5471}
5472
5473/** @internal Create a new incoming transaction object. */
5474static
5475nta_incoming_t *incoming_create(nta_agent_t *agent,
5476 msg_t *msg,
5477 sip_t *sip,
5478 tport_t *tport,
5479 char const *tag)
5480{
5481 nta_incoming_t *irq = su_zalloc(msg_home(msg)((su_home_t*)(msg)), sizeof(*irq));
5482
5483 agent->sa_stats->as_server_tr++;
5484
5485 if (irq) {
5486 su_home_t *home;
5487 incoming_queue_t *queue;
5488 sip_method_t method = sip->sip_request->rq_method;
5489
5490 irq->irq_request = msg;
5491 irq->irq_home = home = msg_home(msg_ref_create(msg))((su_home_t*)(msg_ref_create(msg)));
5492 irq->irq_agent = agent;
5493
5494 irq->irq_received = agent_now(agent); /* Timestamp originally from tport */
5495
5496 irq->irq_method = method;
5497 irq->irq_rq = sip_request_copy(home, sip->sip_request);
5498 irq->irq_from = sip_from_copy(home, sip->sip_from);
5499 irq->irq_to = sip_to_copy(home, sip->sip_to);
5500 irq->irq_call_id = sip_call_id_copy(home, sip->sip_call_id);
5501 irq->irq_cseq = sip_cseq_copy(home, sip->sip_cseq);
5502 irq->irq_via = sip_via_copy(home, sip->sip_via);
5503 switch (method) {
5504 case sip_method_ack:
5505 case sip_method_cancel:
5506 case sip_method_bye:
5507 case sip_method_options:
5508 case sip_method_register: /* Handling Path is up to application */
5509 case sip_method_info:
5510 case sip_method_prack:
5511 case sip_method_publish:
5512 break;
5513 default:
5514 irq->irq_record_route =
5515 sip_record_route_copy(home, sip->sip_record_route);
5516 }
5517 irq->irq_branch = sip->sip_via->v_branch;
5518 irq->irq_reliable_tp = tport_is_reliable(tport);
5519 irq->irq_extra_100 = 0; /* Sending extra 100 trying false by default */
5520
5521 if (sip->sip_timestamp)
5522 irq->irq_timestamp = sip_timestamp_copy(home, sip->sip_timestamp);
5523
5524 /* Tag transaction */
5525 if (tag)
5526 sip_to_tag(home, irq->irq_to, tag);
5527 irq->irq_tag = irq->irq_to->a_tag;
5528
5529 if (method != sip_method_ack) {
5530 int *use_rport = NULL((void*)0);
5531 int retry_without_rport = 0;
5532
5533 if (agent->sa_server_rport)
5534 use_rport = &retry_without_rport, retry_without_rport = 1;
5535
5536 if (nta_tpn_by_via(irq->irq_tpn, irq->irq_via, use_rport) < 0)
5537 SU_DEBUG_1(("%s: bad via\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 5537, "%s: bad via\n", __func__)) : (void)0)
;
5538 }
5539
5540 incoming_set_compartment(irq, tport, msg, 0);
5541
5542 if (method == sip_method_invite) {
5543 irq->irq_must_100rel =
5544 sip->sip_require && sip_has_feature(sip->sip_require, "100rel");
5545
5546 if (irq->irq_must_100rel ||
5547 (sip->sip_supported &&
5548 sip_has_feature(sip->sip_supported, "100rel"))) {
5549 irq->irq_rseq = su_randint(1, 0x7fffffff); /* Initialize rseq */
5550 }
5551
5552 queue = agent->sa_in.proceeding;
5553
5554 if (irq->irq_reliable_tp)
5555 incoming_set_timer(irq, agent->sa_t2 / 2); /* N1 = T2 / 2 */
5556 else
5557 incoming_set_timer(irq, 200); /* N1 = 200 ms */
5558
5559 irq->irq_tport = tport_ref(tport);
5560 }
5561 else if (method == sip_method_ack) {
5562 irq->irq_status = 700; /* Never send reply to ACK */
5563 irq->irq_completed = 1;
5564 if (irq->irq_reliable_tp || !agent->sa_is_a_uas) {
5565 queue = agent->sa_in.terminated;
5566 irq->irq_terminated = 1;
5567 }
5568 else {
5569 queue = agent->sa_in.completed; /* Timer J */
5570 }
5571 }
5572 else {
5573 queue = agent->sa_in.proceeding;
5574 /* RFC 4320 (nit-actions-03):
5575
5576 Blacklisting on a late response occurs even over reliable transports.
5577 Thus, if an element processing a request received over a reliable
5578 transport is delaying its final response at all, sending a 100 Trying
5579 well in advance of the timeout will prevent blacklisting. Sending a
5580 100 Trying immediately will not harm the transaction as it would over
5581 UDP, but a policy of always sending such a message results in
5582 unneccessary traffic. A policy of sending a 100 Trying after the
5583 period of time in which Timer E reaches T2 had this been a UDP hop is
5584 one reasonable compromise.
5585
5586 */
5587 if (agent->sa_extra_100 && irq->irq_reliable_tp)
5588 incoming_set_timer(irq, agent->sa_t2 / 2); /* T2 / 2 */
5589
5590 irq->irq_tport = tport_ref(tport);
5591 }
5592
5593 irq->irq_hash = NTA_HASH(irq->irq_call_id, irq->irq_cseq->cs_seq)((irq->irq_call_id)->i_hash + 26839U * (uint32_t)(irq->
irq_cseq->cs_seq))
;
5594
5595 incoming_insert(agent, queue, irq);
5596 }
5597
5598 return irq;
5599}
5600
5601/** @internal
5602 * Insert incoming transaction to hash table.
5603 */
5604static void
5605incoming_insert(nta_agent_t *agent,
5606 incoming_queue_t *queue,
5607 nta_incoming_t *irq)
5608{
5609 incoming_queue(queue, irq);
5610
5611 if (incoming_htable_is_full(agent->sa_incoming))
5612 incoming_htable_resize(agent->sa_home, agent->sa_incoming, 0);
5613
5614 if (irq->irq_method != sip_method_ack)
5615 incoming_htable_insert(agent->sa_incoming, irq);
5616 else
5617 /* ACK is appended - final response with tags match with it,
5618 * not with the original INVITE transaction */
5619 /* XXX - what about rfc2543 servers, which do not add tag? */
5620 incoming_htable_append(agent->sa_incoming, irq);
5621}
5622
5623/** Call callback for incoming request */
5624static
5625int incoming_callback(nta_leg_t *leg, nta_incoming_t *irq, sip_t *sip)
5626{
5627 sip_method_t method = sip->sip_request->rq_method;
5628 char const *method_name = sip->sip_request->rq_method_name;
5629
5630 /* RFC-3261 section 12.2.2 (page 76) */
5631 if (leg->leg_dialog &&
5632 irq->irq_agent->sa_is_a_uas &&
5633 method != sip_method_ack) {
5634 uint32_t seq = sip->sip_cseq->cs_seq;
5635
5636 if (leg->leg_rseq > sip->sip_cseq->cs_seq) {
5637 SU_DEBUG_3(("nta_leg(%p): out-of-order %s (%u < %u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 5638, "nta_leg(%p): out-of-order %s (%u < %u)\n", (void *
)leg, method_name, seq, leg->leg_rseq)) : (void)0)
5638 (void *)leg, method_name, seq, leg->leg_rseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 5638, "nta_leg(%p): out-of-order %s (%u < %u)\n", (void *
)leg, method_name, seq, leg->leg_rseq)) : (void)0)
;
5639 return 500;
5640 }
5641
5642 leg->leg_rseq = seq;
5643 }
5644
5645 return leg->leg_callback(leg->leg_magic, leg, irq, sip);
5646}
5647
5648/**
5649 * Destroy an incoming transaction.
5650 *
5651 * This function does not actually free transaction object, but marks it as
5652 * disposable. The object is freed after a timeout.
5653 *
5654 * @param irq incoming request object to be destroyed
5655 */
5656void nta_incoming_destroy(nta_incoming_t *irq)
5657{
5658 if (irq) {
5659 irq->irq_callback = NULL((void*)0);
5660 irq->irq_magic = NULL((void*)0);
5661 irq->irq_destroyed = 1;
5662 if (!irq->irq_in_callback) {
5663 if (irq->irq_terminated || irq->irq_default)
5664 incoming_free(irq);
5665 else if (irq->irq_status < 200)
5666 nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error, TAG_END()(tag_type_t)0, (tag_value_t)0);
5667 }
5668 }
5669}
5670
5671/** @internal
5672 * Initialize a queue for incoming transactions.
5673 */
5674static void
5675incoming_queue_init(incoming_queue_t *queue, unsigned timeout)
5676{
5677 memset(queue, 0, sizeof *queue);
5678 queue->q_tail = &queue->q_head;
5679 queue->q_timeout = timeout;
5680}
5681
5682/** Change the timeout value of a queue */
5683static void
5684incoming_queue_adjust(nta_agent_t *sa,
5685 incoming_queue_t *queue,
5686 uint32_t timeout)
5687{
5688 nta_incoming_t *irq;
5689 uint32_t latest;
5690
5691 if (timeout >= queue->q_timeout || !queue->q_head) {
5692 queue->q_timeout = timeout;
5693 return;
5694 }
5695
5696 latest = set_timeout(sa, queue->q_timeout = timeout);
5697
5698 for (irq = queue->q_head; irq; irq = irq->irq_next) {
5699 if ((int32_t)(irq->irq_timeout - latest) > 0)
5700 irq->irq_timeout = latest;
5701 }
5702}
5703
5704/** @internal
5705 * Test if an incoming transaction is in a queue.
5706 */
5707su_inlinestatic inline
5708int incoming_is_queued(nta_incoming_t const *irq)
5709{
5710 return irq && irq->irq_queue;
5711}
5712
5713/** @internal
5714 * Insert an incoming transaction into a queue.
5715 *
5716 * Insert a server transaction into a queue, and sets the corresponding
5717 * timeout at the same time.
5718 */
5719su_inlinestatic inline
5720void incoming_queue(incoming_queue_t *queue,
5721 nta_incoming_t *irq)
5722{
5723 if (irq->irq_queue == queue) {
5724 assert(queue && queue->q_timeout == 0)((void) sizeof ((queue && queue->q_timeout == 0) ?
1 : 0), __extension__ ({ if (queue && queue->q_timeout
== 0) ; else __assert_fail ("queue && queue->q_timeout == 0"
, "nta.c", 5724, __extension__ __PRETTY_FUNCTION__); }))
;
5725 return;
5726 }
5727
5728 if (incoming_is_queued(irq))
5729 incoming_remove(irq);
5730
5731 assert(queue && *queue->q_tail == NULL)((void) sizeof ((queue && *queue->q_tail == ((void
*)0)) ? 1 : 0), __extension__ ({ if (queue && *queue->
q_tail == ((void*)0)) ; else __assert_fail ("queue && *queue->q_tail == NULL"
, "nta.c", 5731, __extension__ __PRETTY_FUNCTION__); }))
;
5732
5733 irq->irq_timeout = set_timeout(irq->irq_agent, queue->q_timeout);
5734
5735 irq->irq_queue = queue;
5736 irq->irq_prev = queue->q_tail;
5737 *queue->q_tail = irq;
5738 queue->q_tail = &irq->irq_next;
5739 queue->q_length++;
5740}
5741
5742/** @internal
5743 * Remove an incoming transaction from a queue.
5744 */
5745su_inlinestatic inline
5746void incoming_remove(nta_incoming_t *irq)
5747{
5748 assert(incoming_is_queued(irq))((void) sizeof ((incoming_is_queued(irq)) ? 1 : 0), __extension__
({ if (incoming_is_queued(irq)) ; else __assert_fail ("incoming_is_queued(irq)"
, "nta.c", 5748, __extension__ __PRETTY_FUNCTION__); }))
;
5749 assert(irq->irq_queue->q_length > 0)((void) sizeof ((irq->irq_queue->q_length > 0) ? 1 :
0), __extension__ ({ if (irq->irq_queue->q_length >
0) ; else __assert_fail ("irq->irq_queue->q_length > 0"
, "nta.c", 5749, __extension__ __PRETTY_FUNCTION__); }))
;
5750
5751 if ((*irq->irq_prev = irq->irq_next))
5752 irq->irq_next->irq_prev = irq->irq_prev;
5753 else
5754 irq->irq_queue->q_tail = irq->irq_prev, assert(!*irq->irq_queue->q_tail)((void) sizeof ((!*irq->irq_queue->q_tail) ? 1 : 0), __extension__
({ if (!*irq->irq_queue->q_tail) ; else __assert_fail (
"!*irq->irq_queue->q_tail", "nta.c", 5754, __extension__
__PRETTY_FUNCTION__); }))
;
5755
5756 irq->irq_queue->q_length--;
5757 irq->irq_next = NULL((void*)0);
5758 irq->irq_prev = NULL((void*)0);
5759 irq->irq_queue = NULL((void*)0);
5760 irq->irq_timeout = 0;
5761}
5762
5763su_inlinestatic inline
5764void incoming_set_timer(nta_incoming_t *irq, uint32_t interval)
5765{
5766 nta_incoming_t **rq;
5767
5768 assert(irq)((void) sizeof ((irq) ? 1 : 0), __extension__ ({ if (irq) ; else
__assert_fail ("irq", "nta.c", 5768, __extension__ __PRETTY_FUNCTION__
); }))
;
5769
5770 if (interval == 0) {
5771 incoming_reset_timer(irq);
5772 return;
5773 }
5774
5775 if (irq->irq_rprev) {
5776 if ((*irq->irq_rprev = irq->irq_rnext))
5777 irq->irq_rnext->irq_rprev = irq->irq_rprev;
5778 if (irq->irq_agent->sa_in.re_t1 == &irq->irq_rnext)
5779 irq->irq_agent->sa_in.re_t1 = irq->irq_rprev;
5780 } else {
5781 irq->irq_agent->sa_in.re_length++;
5782 }
5783
5784 irq->irq_retry = set_timeout(irq->irq_agent, irq->irq_interval = interval);
5785
5786 rq = irq->irq_agent->sa_in.re_t1;
5787
5788 if (!(*rq) || (int32_t)((*rq)->irq_retry - irq->irq_retry) > 0)
5789 rq = &irq->irq_agent->sa_in.re_list;
5790
5791 while (*rq && (int32_t)((*rq)->irq_retry - irq->irq_retry) <= 0)
5792 rq = &(*rq)->irq_rnext;
5793
5794 if ((irq->irq_rnext = *rq))
5795 irq->irq_rnext->irq_rprev = &irq->irq_rnext;
5796 *rq = irq;
5797 irq->irq_rprev = rq;
5798
5799 /* Optimization: keep special place for transactions with T1 interval */
5800 if (interval == irq->irq_agent->sa_t1)
5801 irq->irq_agent->sa_in.re_t1 = rq;
5802}
5803
5804su_inlinestatic inline
5805void incoming_reset_timer(nta_incoming_t *irq)
5806{
5807 if (irq->irq_rprev) {
5808 if ((*irq->irq_rprev = irq->irq_rnext))
5809 irq->irq_rnext->irq_rprev = irq->irq_rprev;
5810 if (irq->irq_agent->sa_in.re_t1 == &irq->irq_rnext)
5811 irq->irq_agent->sa_in.re_t1 = irq->irq_rprev;
5812 irq->irq_agent->sa_in.re_length--;
5813 }
5814
5815 irq->irq_interval = 0, irq->irq_retry = 0;
5816 irq->irq_rnext = NULL((void*)0), irq->irq_rprev = NULL((void*)0);
5817}
5818
5819/** @internal
5820 * Free an incoming transaction.
5821 */
5822static
5823void incoming_free(nta_incoming_t *irq)
5824{
5825 SU_DEBUG_9(("nta: incoming_free(%p)\n", (void *)irq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 5825, "nta: incoming_free(%p)\n", (void *)irq)) : (void)0)
;
5826
5827 incoming_cut_off(irq);
5828 incoming_reclaim(irq);
5829}
5830
5831/** Remove references to the irq */
5832su_inlinestatic inline
5833void incoming_cut_off(nta_incoming_t *irq)
5834{
5835 nta_agent_t *agent = irq->irq_agent;
5836
5837 assert(agent)((void) sizeof ((agent) ? 1 : 0), __extension__ ({ if (agent)
; else __assert_fail ("agent", "nta.c", 5837, __extension__ __PRETTY_FUNCTION__
); }))
;
5838
5839 if (irq->irq_default) {
5840 if (irq == agent->sa_default_incoming)
5841 agent->sa_default_incoming = NULL((void*)0);
5842 irq->irq_default = 0;
5843 return;
5844 }
5845
5846 if (incoming_is_queued(irq))
5847 incoming_remove(irq);
5848
5849 incoming_reset_timer(irq);
5850
5851 incoming_htable_remove(agent->sa_incoming, irq);
5852
5853 if (irq->irq_cc)
5854 nta_compartment_decref(&irq->irq_cc);
5855
5856 if (irq->irq_tport)
5857 tport_decref(&irq->irq_tport);
5858}
5859
5860/** Reclaim the memory used by irq */
5861su_inlinestatic inline
5862void incoming_reclaim(nta_incoming_t *irq)
5863{
5864 su_home_t *home = irq->irq_home;
5865 nta_reliable_t *rel, *rel_next;
5866
5867 if (irq->irq_request)
5868 msg_destroy(irq->irq_request), irq->irq_request = NULL((void*)0);
5869 if (irq->irq_request2)
5870 msg_destroy(irq->irq_request2), irq->irq_request2 = NULL((void*)0);
5871 if (irq->irq_response)
5872 msg_destroy(irq->irq_response), irq->irq_response = NULL((void*)0);
5873
5874 for (rel = irq->irq_reliable; rel; rel = rel_next) {
5875 rel_next = rel->rel_next;
5876 if (rel->rel_unsent)
5877 msg_destroy(rel->rel_unsent);
5878 su_free(irq->irq_agent->sa_home, rel);
5879 }
5880
5881 irq->irq_home = NULL((void*)0);
5882
5883 su_free(home, irq);
5884
5885 msg_destroy((msg_t *)home);
5886}
5887
5888/** Queue request to be freed */
5889su_inlinestatic inline
5890void incoming_free_queue(incoming_queue_t *q, nta_incoming_t *irq)
5891{
5892 incoming_cut_off(irq);
5893 incoming_queue(q, irq);
5894}
5895
5896/** Reclaim memory used by queue of requests */
5897static
5898void incoming_reclaim_queued(su_root_magic_t *rm,
5899 su_msg_r msg,
5900 union sm_arg_u *u)
5901{
5902 incoming_queue_t *q = u->a_incoming_queue;
5903 nta_incoming_t *irq, *irq_next;
5904
5905 SU_DEBUG_9(("incoming_reclaim_all(%p, %p, %p)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 5906, "incoming_reclaim_all(%p, %p, %p)\n", (void *)rm, (void
*)msg, (void *)u)) : (void)0)
5906 (void *)rm, (void *)msg, (void *)u))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 5906, "incoming_reclaim_all(%p, %p, %p)\n", (void *)rm, (void
*)msg, (void *)u)) : (void)0)
;
5907
5908 for (irq = q->q_head; irq; irq = irq_next) {
5909 irq_next = irq->irq_next;
5910 incoming_reclaim(irq);
5911 }
5912}
5913
5914/**Bind a callback and context to an incoming transaction object
5915 *
5916 * Set the callback function and context pointer attached to an incoming
5917 * request object. The callback function will be invoked if the incoming
5918 * request is cancelled, or if the final response to an incoming @b INVITE
5919 * request has been acknowledged.
5920 *
5921 * If the callback is NULL, or no callback has been bound, NTA invokes the
5922 * request callback of the call leg.
5923 *
5924 * @param irq incoming transaction
5925 * @param callback callback function
5926 * @param magic application context
5927 */
5928void nta_incoming_bind(nta_incoming_t *irq,
5929 nta_ack_cancel_f *callback,
5930 nta_incoming_magic_t *magic)
5931{
5932 if (irq) {
5933 irq->irq_callback = callback;
5934 irq->irq_magic = magic;
5935 }
5936}
5937
5938/** Add a @To tag to incoming request if needed.
5939 *
5940 * If @a tag is NULL, a new tag is generated.
5941 */
5942char const *nta_incoming_tag(nta_incoming_t *irq, char const *tag)
5943{
5944 if (!irq)
5945 return su_seterrno(EFAULT14), NULL((void*)0);
5946
5947 if (irq->irq_default)
5948 return su_seterrno(EINVAL22), NULL((void*)0);
5949
5950 if (tag && strchr(tag, '='))
5951 tag = strchr(tag, '=') + 1;
5952
5953 if (tag && irq->irq_tag && !su_casematch(tag, irq->irq_tag))
5954 return NULL((void*)0);
5955
5956 if (!irq->irq_tag) {
5957 if (tag)
5958 tag = su_strdup(irq->irq_home, tag);
5959 else
5960 tag = nta_agent_newtag(irq->irq_home, NULL((void*)0), irq->irq_agent);
5961
5962 if (!tag)
5963 return tag;
5964
5965 irq->irq_tag = tag;
5966 irq->irq_tag_set = 1;
5967 }
5968
5969 return irq->irq_tag;
5970}
5971
5972
5973/**Get request message.
5974 *
5975 * Retrieve the incoming request message of the incoming transaction. Note
5976 * that the message is not copied, but a new reference to it is created.
5977 *
5978 * @param irq incoming transaction handle
5979 *
5980 * @retval
5981 * A pointer to request message is returned.
5982 */
5983msg_t *nta_incoming_getrequest(nta_incoming_t *irq)
5984{
5985 msg_t *msg = NULL((void*)0);
5986
5987 if (irq && !irq->irq_default)
5988 msg = msg_ref_create(irq->irq_request);
5989
5990 return msg;
5991}
5992
5993/**Get ACK or CANCEL message.
5994 *
5995 * Retrieve the incoming ACK or CANCEL request message of the incoming
5996 * transaction. Note that the ACK or CANCEL message is not copied, but a new
5997 * reference to it is created.
5998 *
5999 * @param irq incoming transaction handle
6000 *
6001 * @retval A pointer to request message is returned, or NULL if there is no
6002 * CANCEL or ACK received.
6003 */
6004msg_t *nta_incoming_getrequest_ackcancel(nta_incoming_t *irq)
6005{
6006 msg_t *msg = NULL((void*)0);
6007
6008 if (irq && irq->irq_request2)
6009 msg = msg_ref_create(irq->irq_request2);
6010
6011 return msg;
6012}
6013
6014/**Get response message.
6015 *
6016 * Retrieve the response message latest sent by the server transaction. Note
6017 * that the message is not copied, but a new reference to it is created. Use
6018 * msg_dup() or msg_copy() to make a copy of it.
6019 *
6020 * @param irq incoming transaction handle
6021 *
6022 * @retval
6023 * A pointer to a response message is returned.
6024 */
6025msg_t *nta_incoming_getresponse(nta_incoming_t *irq)
6026{
6027 msg_t *msg = NULL((void*)0);
6028
6029 if (irq && irq->irq_response)
6030 msg = msg_ref_create(irq->irq_response);
6031
6032 return msg;
6033}
6034
6035/** Get method of a server transaction. */
6036sip_method_t nta_incoming_method(nta_incoming_t const *irq)
6037{
6038 return irq ? irq->irq_method : sip_method_invalid;
6039}
6040
6041/** Get method name of a server transaction. */
6042char const *nta_incoming_method_name(nta_incoming_t const *irq)
6043{
6044 if (irq == NULL((void*)0))
6045 return NULL((void*)0);
6046 else if (irq->irq_rq)
6047 return irq->irq_rq->rq_method_name;
6048 else
6049 return "*";
6050}
6051
6052/** Get Request-URI of a server transaction */
6053url_t const *nta_incoming_url(nta_incoming_t const *irq)
6054{
6055 return irq && irq->irq_rq ? irq->irq_rq->rq_url : NULL((void*)0);
6056}
6057
6058/** Get sequence number of a server transaction.
6059 */
6060uint32_t nta_incoming_cseq(nta_incoming_t const *irq)
6061{
6062 return irq && irq->irq_cseq ? irq->irq_cseq->cs_seq : 0;
6063}
6064
6065/** Get local tag for incoming request */
6066char const *nta_incoming_gettag(nta_incoming_t const *irq)
6067{
6068 return irq ? irq->irq_tag : 0;
6069}
6070
6071/**
6072 * Get status code of a server transaction.
6073 */
6074int nta_incoming_status(nta_incoming_t const *irq)
6075{
6076 return irq ? irq->irq_status : 400;
6077}
6078
6079/** Get application context for a server transaction.
6080 *
6081 * @param irq server transaction
6082 * @param callback callback pointer
6083 *
6084 * Return the application context bound to the server transaction. If the @a
6085 * callback function pointer is given, return application context only if
6086 * the callback matches with the callback bound to the server transaction.
6087 *
6088 */
6089nta_incoming_magic_t *nta_incoming_magic(nta_incoming_t *irq,
6090 nta_ack_cancel_f *callback)
6091{
6092 return irq && (callback == NULL((void*)0) || irq->irq_callback == callback)
6093 ? irq->irq_magic : NULL((void*)0);
6094}
6095
6096/** When received.
6097 *
6098 * Return timestamp from the reception of the initial request.
6099 *
6100 * @NEW_1_12_7.
6101 */
6102sip_time_t nta_incoming_received(nta_incoming_t *irq,
6103 su_nanotime_t *return_nano)
6104{
6105 su_time_t tv = { 0, 0 };
6106
6107 if (irq)
6108 tv = irq->irq_received;
6109
6110 if (return_nano)
6111 *return_nano = (su_nanotime_t)tv.tv_sec * 1000000000 + tv.tv_usec * 1000;
6112
6113 return tv.tv_sec;
6114}
6115
6116/** Find incoming transaction. */
6117nta_incoming_t *nta_incoming_find(nta_agent_t const *agent,
6118 sip_t const *sip,
6119 sip_via_t const *v)
6120{
6121 if (agent && sip && v)
6122 return incoming_find(agent, sip, v, NULL((void*)0), NULL((void*)0), NULL((void*)0));
6123 else
6124 return NULL((void*)0);
6125}
6126
6127/** Find a matching server transaction object.
6128 *
6129 * Check also for requests to merge, to ACK, or to CANCEL.
6130 */
6131static nta_incoming_t *incoming_find(nta_agent_t const *agent,
6132 sip_t const *sip,
6133 sip_via_t const *v,
6134 nta_incoming_t **return_merge,
6135 nta_incoming_t **return_ack,
6136 nta_incoming_t **return_cancel)
6137{
6138 sip_cseq_t const *cseq = sip->sip_cseq;
6139 sip_call_id_t const *i = sip->sip_call_id;
6140 sip_to_t const *to = sip->sip_to;
6141 sip_from_t const *from = sip->sip_from;
6142 sip_request_t *rq = sip->sip_request;
6143 incoming_htable_t const *iht = agent->sa_incoming;
6144 hash_value_t hash;
6145 char const *magic_branch;
6146
6147 nta_incoming_t **ii, *irq;
6148
6149 int is_uas_ack = return_ack && agent->sa_is_a_uas;
6150
6151 assert(cseq)((void) sizeof ((cseq) ? 1 : 0), __extension__ ({ if (cseq) ;
else __assert_fail ("cseq", "nta.c", 6151, __extension__ __PRETTY_FUNCTION__
); }))
;
6152
6153 hash = NTA_HASH(i, cseq->cs_seq)((i)->i_hash + 26839U * (uint32_t)(cseq->cs_seq));
6154
6155 if (v->v_branch && su_casenmatch(v->v_branch, "z9hG4bK", 7))
6156 magic_branch = v->v_branch + 7;
6157 else
6158 magic_branch = NULL((void*)0);
6159
6160 for (ii = incoming_htable_hash(iht, hash);
6161 (irq = *ii);
6162 ii = incoming_htable_next(iht, ii)) {
6163 if (hash != irq->irq_hash ||
6164 irq->irq_call_id->i_hash != i->i_hash ||
6165 strcmp(irq->irq_call_id->i_id, i->i_id))
6166 continue;
6167 if (irq->irq_cseq->cs_seq != cseq->cs_seq)
6168 continue;
6169 if (su_strcasecmp(irq->irq_from->a_tag, from->a_tag))
6170 continue;
6171
6172 if (is_uas_ack &&
6173 irq->irq_method == sip_method_invite &&
6174 200 <= irq->irq_status && irq->irq_status < 300 &&
6175 su_casematch(irq->irq_tag, to->a_tag)) {
6176 *return_ack = irq;
6177 return NULL((void*)0);
6178 }
6179
6180 if (magic_branch) {
6181 /* RFC3261 17.2.3:
6182 *
6183 * The request matches a transaction if branch and sent-by in topmost
6184 * the method of the request matches the one that created the
6185 * transaction, except for ACK, where the method of the request
6186 * that created the transaction is INVITE.
6187 */
6188 if (irq->irq_via->v_branch &&
6189 su_casematch(irq->irq_via->v_branch + 7, magic_branch) &&
6190 su_casematch(irq->irq_via->v_host, v->v_host) &&
6191 su_strmatch(irq->irq_via->v_port, v->v_port)) {
6192 if (irq->irq_method == cseq->cs_method &&
6193 strcmp(irq->irq_cseq->cs_method_name,
6194 cseq->cs_method_name) == 0)
6195 return irq;
6196 if (return_ack && irq->irq_method == sip_method_invite)
6197 return *return_ack = irq, NULL((void*)0);
6198 if (return_cancel && irq->irq_method != sip_method_ack)
6199 return *return_cancel = irq, NULL((void*)0);
6200 }
6201 }
6202 else {
6203 /* No magic branch */
6204
6205 /* INVITE request matches a transaction if
6206 the Request-URI, To tag, From tag, Call-ID, CSeq, and
6207 top Via header match */
6208
6209 /* From tag, Call-ID, and CSeq number has been matched above */
6210
6211 /* Match top Via header field */
6212 if (!su_casematch(irq->irq_via->v_branch, v->v_branch) ||
6213 !su_casematch(irq->irq_via->v_host, v->v_host) ||
6214 !su_strmatch(irq->irq_via->v_port, v->v_port))
6215 ;
6216 /* Match Request-URI */
6217 else if (url_cmp(irq->irq_rq->rq_url, rq->rq_url))
6218 ;
6219 else {
6220 /* Match CSeq */
6221 if (irq->irq_method == cseq->cs_method &&
6222 su_strmatch(irq->irq_cseq->cs_method_name, cseq->cs_method_name)) {
6223 /* Match To tag */
6224 if (!su_strcasecmp(irq->irq_to->a_tag, to->a_tag))
6225 return irq; /* found */
6226 }
6227 else if (
6228 /* Tag set by UAS */
6229 su_strcasecmp(irq->irq_tag, to->a_tag) &&
6230 /* Original tag */
6231 su_strcasecmp(irq->irq_to->a_tag, to->a_tag))
6232 ;
6233 else if (return_ack && irq->irq_method == sip_method_invite)
6234 return *return_ack = irq, NULL((void*)0);
6235 else if (return_cancel && irq->irq_method != sip_method_ack)
6236 return *return_cancel = irq, NULL((void*)0);
6237 }
6238 }
6239
6240 /* RFC3261 - section 8.2.2.2 Merged Requests */
6241 if (return_merge) {
6242 if (irq->irq_cseq->cs_method == cseq->cs_method &&
6243 strcmp(irq->irq_cseq->cs_method_name,
6244 cseq->cs_method_name) == 0)
6245 *return_merge = irq, return_merge = NULL((void*)0);
6246 }
6247 }
6248
6249 return NULL((void*)0);
6250}
6251
6252/** Process retransmitted requests. */
6253su_inlinestatic inline
6254int
6255incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport)
6256{
6257 nta_agent_t *agent = irq->irq_agent;
6258
6259 agent->sa_stats->as_recv_retry++;
6260
6261 if (irq->irq_status >= 100) {
6262 SU_DEBUG_5(("nta: re-received %s request, retransmitting %u reply\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6263, "nta: re-received %s request, retransmitting %u reply\n"
, sip->sip_request->rq_method_name, irq->irq_status)
) : (void)0)
6263 sip->sip_request->rq_method_name, irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6263, "nta: re-received %s request, retransmitting %u reply\n"
, sip->sip_request->rq_method_name, irq->irq_status)
) : (void)0)
;
6264 incoming_retransmit_reply(irq, tport);
6265 }
6266 else if (irq->irq_agent->sa_extra_100 &&
6267 irq->irq_extra_100) {
6268 /* Agent and Irq configured to answer automatically with 100 Trying */
6269 if (irq->irq_method == sip_method_invite ||
6270 /*
6271 * Send 100 trying to non-invite if at least half of T2 has expired
6272 * since the transaction was created.
6273 */
6274 su_duration(agent_now(irq->irq_agent), irq->irq_received) * 2U >
6275 irq->irq_agent->sa_t2) {
6276 SU_DEBUG_5(("nta: re-received %s request, sending 100 Trying\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6277, "nta: re-received %s request, sending 100 Trying\n", sip
->sip_request->rq_method_name)) : (void)0)
6277 sip->sip_request->rq_method_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6277, "nta: re-received %s request, sending 100 Trying\n", sip
->sip_request->rq_method_name)) : (void)0)
;
6278 nta_incoming_treply(irq, SIP_100_TRYING100, sip_100_Trying, NTATAG_TPORT(tport)ntatag_tport, tag_ptr_v((tport)), TAG_END()(tag_type_t)0, (tag_value_t)0);
6279 }
6280 }
6281
6282 msg_destroy(msg);
6283
6284 return 0;
6285}
6286
6287su_inlinestatic inline
6288int incoming_ack(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport)
6289{
6290 nta_agent_t *agent = irq->irq_agent;
6291
6292 /* Process ACK separately? */
6293 if (irq->irq_status >= 200 && irq->irq_status < 300 && !agent->sa_is_a_uas)
6294 return -1;
6295
6296 if (irq->irq_queue == agent->sa_in.inv_completed) {
6297 if (!irq->irq_confirmed)
6298 agent->sa_stats->as_acked_tr++;
6299
6300 irq->irq_confirmed = 1;
6301 incoming_reset_timer(irq); /* Reset timer G */
6302
6303 if (!irq->irq_reliable_tp) {
6304 incoming_queue(agent->sa_in.inv_confirmed, irq); /* Timer I */
6305 }
6306 else {
6307 irq->irq_terminated = 1;
6308 incoming_queue(agent->sa_in.terminated, irq);
6309 }
6310
6311 if (!irq->irq_destroyed) {
6312 if (!irq->irq_callback) /* Process ACK normally */
6313 return -1;
6314
6315 incoming_call_callback(irq, msg, sip); /* ACK callback */
6316 }
6317 } else if (irq->irq_queue == agent->sa_in.proceeding ||
6318 irq->irq_queue == agent->sa_in.preliminary)
6319 return -1;
6320 else
6321 assert(irq->irq_queue == agent->sa_in.inv_confirmed ||((void) sizeof ((irq->irq_queue == agent->sa_in.inv_confirmed
|| irq->irq_queue == agent->sa_in.terminated) ? 1 : 0)
, __extension__ ({ if (irq->irq_queue == agent->sa_in.inv_confirmed
|| irq->irq_queue == agent->sa_in.terminated) ; else __assert_fail
("irq->irq_queue == agent->sa_in.inv_confirmed || irq->irq_queue == agent->sa_in.terminated"
, "nta.c", 6322, __extension__ __PRETTY_FUNCTION__); }))
6322 irq->irq_queue == agent->sa_in.terminated)((void) sizeof ((irq->irq_queue == agent->sa_in.inv_confirmed
|| irq->irq_queue == agent->sa_in.terminated) ? 1 : 0)
, __extension__ ({ if (irq->irq_queue == agent->sa_in.inv_confirmed
|| irq->irq_queue == agent->sa_in.terminated) ; else __assert_fail
("irq->irq_queue == agent->sa_in.inv_confirmed || irq->irq_queue == agent->sa_in.terminated"
, "nta.c", 6322, __extension__ __PRETTY_FUNCTION__); }))
;
6323
6324 msg_destroy(msg);
6325
6326 return 0;
6327}
6328
6329/** Respond to the CANCEL. */
6330su_inlinestatic inline
6331int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
6332 tport_t *tport)
6333{
6334 nta_agent_t *agent = irq->irq_agent;
6335
6336 /* According to the RFC 3261, this INVITE has been destroyed */
6337 if (irq->irq_method == sip_method_invite &&
6338 200 <= irq->irq_status && irq->irq_status < 300) {
6339 mreply(agent, NULL((void*)0), SIP_481_NO_TRANSACTION481, sip_481_No_transaction, msg,
6340 tport, 0, 0, NULL((void*)0),
6341 TAG_END()(tag_type_t)0, (tag_value_t)0);
6342 return 0;
6343 }
6344
6345 /* UAS MUST use same tag in final response to CANCEL and INVITE */
6346 if (agent->sa_is_a_uas && irq->irq_tag == NULL((void*)0)) {
6347 nta_incoming_tag(irq, NULL((void*)0));
6348 }
6349
6350 mreply(agent, NULL((void*)0), SIP_200_OK200, sip_200_OK, msg_ref_create(msg),
6351 tport, 0, 0, irq->irq_tag,
6352 TAG_END()(tag_type_t)0, (tag_value_t)0);
6353
6354 /* We have already sent final response */
6355 if (irq->irq_completed || irq->irq_method != sip_method_invite) {
6356 msg_destroy(msg);
6357 return 0;
6358 }
6359
6360 if (!irq->irq_canceled) {
6361 irq->irq_canceled = 1;
6362 agent->sa_stats->as_canceled_tr++;
6363 irq = incoming_call_callback(irq, msg, sip);
6364 }
6365
6366 if (irq && !irq->irq_completed && agent->sa_cancel_487)
6367 /* Respond to the cancelled request */
6368 nta_incoming_treply(irq, SIP_487_REQUEST_CANCELLED487, sip_487_Request_terminated, TAG_END()(tag_type_t)0, (tag_value_t)0);
6369
6370 msg_destroy(msg);
6371
6372 return 0;
6373}
6374
6375/** Merge request */
6376static
6377void request_merge(nta_agent_t *agent,
6378 msg_t *msg, sip_t *sip, tport_t *tport,
6379 char const *to_tag)
6380{
6381 nta_incoming_t *irq;
6382
6383 agent->sa_stats->as_merged_request++;
6384
6385 irq = incoming_create(agent, msg, sip, tport, to_tag);
6386
6387 if (irq) {
6388 nta_incoming_treply(irq, 482, "Request merged", TAG_END()(tag_type_t)0, (tag_value_t)0);
6389 nta_incoming_destroy(irq);
6390 } else {
6391 SU_DEBUG_3(("nta: request_merge(): cannot create transaction for %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6392, "nta: request_merge(): cannot create transaction for %s\n"
, sip->sip_request->rq_method_name)) : (void)0)
6392 sip->sip_request->rq_method_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6392, "nta: request_merge(): cannot create transaction for %s\n"
, sip->sip_request->rq_method_name)) : (void)0)
;
6393 mreply(agent, NULL((void*)0), 482, "Request merged", msg,
6394 tport, 0, 0, NULL((void*)0),
6395 TAG_END()(tag_type_t)0, (tag_value_t)0);
6396 }
6397}
6398
6399/**@typedef nta_ack_cancel_f
6400 *
6401 * Callback function prototype for CANCELed/ACKed requests
6402 *
6403 * This is a callback function is invoked by NTA when an incoming request
6404 * has been cancelled or an response to an incoming INVITE request has been
6405 * acknowledged.
6406 *
6407 * @param magic incoming request context
6408 * @param ireq incoming request
6409 * @param sip ACK/CANCEL message
6410 *
6411 * @retval 0
6412 * This callback function should return always 0.
6413 */
6414
6415/** Call callback of incoming transaction */
6416su_inlinestatic inline
6417nta_incoming_t *
6418incoming_call_callback(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
6419{
6420 if (irq->irq_callback) {
6421 irq->irq_in_callback = 1;
6422 irq->irq_request2 = msg;
6423 irq->irq_callback(irq->irq_magic, irq, sip);
6424 irq->irq_request2 = NULL((void*)0);
6425 irq->irq_in_callback = 0;
6426
6427 if (irq->irq_terminated && irq->irq_destroyed)
6428 incoming_free(irq), irq = NULL((void*)0);
6429 }
6430 return irq;
6431}
6432
6433/**Set server transaction parameters.
6434 *
6435 * Sets the server transaction parameters. Among others, parameters determine the way
6436 * the SigComp compression is handled.
6437 *
6438 * @TAGS
6439 * NTATAG_COMP(), NTATAG_SIGCOMP_CLOSE() and NTATAG_EXTRA_100().
6440 *
6441 * @retval number of set parameters when succesful
6442 * @retval -1 upon an error
6443 */
6444int nta_incoming_set_params(nta_incoming_t *irq,
6445 tag_type_t tag, tag_value_t value, ...)
6446{
6447 int retval = -1;
6448
6449 if (irq) {
6450 ta_list ta;
6451 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
6452 retval = incoming_set_params(irq, ta_args(ta)(ta).tl);
6453 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
6454 }
6455 else {
6456 su_seterrno(EINVAL22);
6457 }
6458
6459 return retval;
6460}
6461
6462static
6463int incoming_set_params(nta_incoming_t *irq, tagi_t const *tags)
6464{
6465 int retval = 0;
6466
6467 tagi_t const *t;
6468 char const *comp = NONE((void *)-1);
6469 struct sigcomp_compartment *cc = NONE((void *)-1);
6470
6471 if (irq->irq_default)
6472 return retval;
6473
6474 for (t = tags; t; t = tl_next(t)) {
6475 tag_type_t tt = t->t_tag;
6476
6477 if (ntatag_comp == tt)
6478 comp = (char const *)t->t_value, retval++;
6479
6480 else if (ntatag_sigcomp_close == tt)
6481 irq->irq_sigcomp_zap = t->t_value != 0, retval++;
6482
6483 else if (tptag_compartment == tt)
6484 cc = (void *)t->t_value, retval++;
6485
6486 else if (ntatag_extra_100 == tt)
6487 irq->irq_extra_100 = t->t_value != 0, retval++;
6488 }
6489
6490 if (cc != NONE((void *)-1)) {
6491 if (cc)
6492 agent_accept_compressed(irq->irq_agent, irq->irq_request, cc);
6493 if (irq->irq_cc)
6494 nta_compartment_decref(&irq->irq_cc);
6495 irq->irq_cc = nta_compartment_ref(cc);
6496 }
6497 else if (comp != NULL((void*)0) && comp != NONE((void *)-1) && irq->irq_cc == NULL((void*)0)) {
6498 incoming_set_compartment(irq, irq->irq_tport, irq->irq_request, 1);
6499 }
6500
6501 else if (comp == NULL((void*)0)) {
6502 irq->irq_tpn->tpn_comp = NULL((void*)0);
6503 }
6504
6505 return retval;
6506}
6507
6508su_inlinestatic inline
6509int incoming_set_compartment(nta_incoming_t *irq, tport_t *tport, msg_t *msg,
6510 int create_if_needed)
6511{
6512 if (!nta_compressor_vtable)
6513 return 0;
6514
6515 if (irq->irq_cc == NULL((void*)0)
6516 || irq->irq_tpn->tpn_comp
6517 || tport_delivered_with_comp(tport, msg, NULL((void*)0)) != -1) {
6518 struct sigcomp_compartment *cc;
6519
6520 cc = agent_compression_compartment(irq->irq_agent, tport, irq->irq_tpn,
6521 create_if_needed);
6522
6523 if (cc)
6524 agent_accept_compressed(irq->irq_agent, msg, cc);
6525
6526 irq->irq_cc = cc;
6527 }
6528
6529 return 0;
6530}
6531
6532/** Add essential headers to the response message */
6533static int nta_incoming_response_headers(nta_incoming_t *irq,
6534 msg_t *msg,
6535 sip_t *sip)
6536{
6537 int clone = 0;
6538 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
6539
6540 if (!sip->sip_from)
6541 clone = 1, sip->sip_from = sip_from_copy(home, irq->irq_from);
6542 if (!sip->sip_to)
6543 clone = 1, sip->sip_to = sip_to_copy(home, irq->irq_to);
6544 if (!sip->sip_call_id)
6545 clone = 1, sip->sip_call_id = sip_call_id_copy(home, irq->irq_call_id);
6546 if (!sip->sip_cseq)
6547 clone = 1, sip->sip_cseq = sip_cseq_copy(home, irq->irq_cseq);
6548 if (!sip->sip_via) {
6549 clone = 1;
6550 /* 100 responses are not forwarded by proxies, so only include the topmost Via header */
6551 if (sip->sip_status && sip->sip_status->st_status == 100)
6552 sip->sip_via = (sip_via_t *)msg_header_copy_one(home, (msg_header_t const *)irq->irq_via);
6553 else
6554 sip->sip_via = sip_via_copy(home, irq->irq_via);
6555 }
6556
6557 if (clone)
6558 msg_set_parent(msg, (msg_t *)irq->irq_home);
6559
6560 if (!sip->sip_from || !sip->sip_to || !sip->sip_call_id || !sip->sip_cseq || !sip->sip_via)
6561 return -1;
6562
6563 return 0;
6564}
6565
6566/** Complete a response message.
6567 *
6568 * @param irq server transaction object
6569 * @param msg response message to be completed
6570 * @param status status code (in range 100 - 699)
6571 * @param phrase status phrase (may be NULL)
6572 * @param tag,value,... taged argument list
6573 *
6574 * Generate status structure based on @a status and @a phrase.
6575 * Add essential headers to the response message:
6576 * @From, @To, @CallID, @CSeq, @Via, and optionally
6577 * @RecordRoute.
6578 */
6579int nta_incoming_complete_response(nta_incoming_t *irq,
6580 msg_t *msg,
6581 int status,
6582 char const *phrase,
6583 tag_type_t tag, tag_value_t value, ...)
6584{
6585 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
6586 sip_t *sip = sip_object(msg);
6587 int retval;
6588 ta_list ta;
6589
6590 if (irq == NULL((void*)0) || sip == NULL((void*)0))
6591 return su_seterrno(EFAULT14), -1;
6592
6593 if (status != 0 && (status < 100 || status > 699))
6594 return su_seterrno(EINVAL22), -1;
6595
6596 if (status != 0 && !sip->sip_status)
6597 sip->sip_status = sip_status_create(home, status, phrase, NULL((void*)0));
6598
6599 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
6600 retval = sip_add_tl(msg, sip, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
6601 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
6602
6603 if (retval < 0)
6604 return -1;
6605
6606 if (irq->irq_default)
6607 return sip_complete_message(msg);
6608
6609 if (status > 100 && !irq->irq_tag) {
6610 if (sip->sip_to)
6611 nta_incoming_tag(irq, sip->sip_to->a_tag);
6612 else
6613 nta_incoming_tag(irq, NULL((void*)0));
6614 }
6615
6616 if (nta_incoming_response_headers(irq, msg, sip) < 0)
6617 return -1;
6618
6619 if (sip->sip_status && sip->sip_status->st_status > 100 &&
6620 irq->irq_tag && sip->sip_to && !sip->sip_to->a_tag)
6621 if (sip_to_tag(home, sip->sip_to, irq->irq_tag) < 0)
6622 return -1;
6623
6624 if (status > 100 && status < 300 && !sip->sip_record_route && irq->irq_record_route)
6625 if (sip_add_dup(msg, sip, (sip_header_t *)irq->irq_record_route) < 0)
6626 return -1;
6627
6628 return sip_complete_message(msg);
6629}
6630
6631
6632/** Create a response message for request.
6633 *
6634 * @NEW_1_12_5.
6635 */
6636msg_t *nta_incoming_create_response(nta_incoming_t *irq,
6637 int status, char const *phrase)
6638{
6639 msg_t *msg = NULL((void*)0);
6640 sip_t *sip;
6641
6642 if (irq) {
6643 msg = nta_msg_create(irq->irq_agent, 0);
6644 sip = sip_object(msg);
6645
6646 if (sip) {
6647 if (status != 0)
6648 sip->sip_status = sip_status_create(msg_home(msg)((su_home_t*)(msg)), status, phrase, NULL((void*)0));
6649
6650 if (nta_incoming_response_headers(irq, msg, sip) < 0)
6651 msg_destroy(msg), msg = NULL((void*)0);
6652 }
6653 }
6654
6655 return msg;
6656}
6657
6658
6659/**Reply to an incoming transaction request.
6660 *
6661 * This function creates a response message to an incoming request and sends
6662 * it to the client.
6663 *
6664 * @note
6665 * It is possible to send several non-final (1xx) responses, but only one
6666 * final response.
6667 *
6668 * @param irq incoming request
6669 * @param status status code
6670 * @param phrase status phrase (may be NULL if status code is well-known)
6671 * @param tag,value,... optional additional headers terminated by TAG_END()
6672 *
6673 * @retval 0 when succesful
6674 * @retval -1 upon an error
6675 */
6676int nta_incoming_treply(nta_incoming_t *irq,
6677 int status,
6678 char const *phrase,
6679 tag_type_t tag, tag_value_t value, ...)
6680{
6681 int retval = -1;
6682
6683 if (irq &&
6684 (irq->irq_status < 200 || status < 200 ||
6685 (irq->irq_method == sip_method_invite && status < 300))) {
6686 ta_list ta;
6687 msg_t *msg = nta_msg_create(irq->irq_agent, 0);
6688
6689 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
6690
6691 if (!msg)
6692 ;
6693 else if (nta_incoming_complete_response(irq, msg, status, phrase,
6694 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0)
6695 msg_destroy(msg);
6696 else if (incoming_set_params(irq, ta_args(ta)(ta).tl) < 0)
6697 msg_destroy(msg);
6698 else
6699 retval = nta_incoming_mreply(irq, msg);
6700
6701 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
6702
6703 if (retval < 0 && status >= 200)
6704 incoming_final_failed(irq, NULL((void*)0));
6705 }
6706
6707 return retval;
6708}
6709
6710/**
6711 * Return a response message to client.
6712 *
6713 * @note
6714 * The ownership of @a msg is taken over by the function even if the
6715 * function fails.
6716 *
6717 * @retval 0 when succesful
6718 * @retval -1 upon an error
6719 */
6720int nta_incoming_mreply(nta_incoming_t *irq, msg_t *msg)
6721{
6722 sip_t *sip = sip_object(msg);
6723
6724 int status;
6725
6726 if (irq == NULL((void*)0)) {
6727 msg_destroy(msg);
6728 return -1;
6729 }
6730
6731 if (msg == NULL((void*)0) || sip == NULL((void*)0))
6732 return -1;
6733
6734 if (msg == irq->irq_response)
6735 return 0;
6736
6737 if (!sip->sip_status || !sip->sip_via || !sip->sip_cseq)
6738 return incoming_final_failed(irq, msg);
6739
6740 assert (sip->sip_cseq->cs_method == irq->irq_method || irq->irq_default)((void) sizeof ((sip->sip_cseq->cs_method == irq->irq_method
|| irq->irq_default) ? 1 : 0), __extension__ ({ if (sip->
sip_cseq->cs_method == irq->irq_method || irq->irq_default
) ; else __assert_fail ("sip->sip_cseq->cs_method == irq->irq_method || irq->irq_default"
, "nta.c", 6740, __extension__ __PRETTY_FUNCTION__); }))
;
6741
6742 status = sip->sip_status->st_status;
6743
6744 if (!irq->irq_tag && status > 100 && !irq->irq_default)
6745 nta_incoming_tag(irq, NULL((void*)0));
6746
6747 if (/* (irq->irq_confirmed && status >= 200) || */
6748 (irq->irq_completed && status >= 300)) {
6749 SU_DEBUG_3(("%s: already %s transaction\n", __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6750, "%s: already %s transaction\n", __func__, irq->irq_confirmed
? "confirmed" : "completed")) : (void)0)
6750 irq->irq_confirmed ? "confirmed" : "completed"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6750, "%s: already %s transaction\n", __func__, irq->irq_confirmed
? "confirmed" : "completed")) : (void)0)
;
6751 msg_destroy(msg);
6752 return -1;
6753 }
6754
6755#ifdef HAVE_ZLIB_COMPRESS1
6756 if (irq->irq_compressed) {
6757 sip_content_encoding_Xflate(msg, sip, 0, 0);
6758 }
6759#endif
6760
6761 if (irq->irq_must_100rel && !sip->sip_rseq && status > 100 && status < 200) {
6762 /* This nta_reliable_t object will be destroyed by PRACK or timeout */
6763 if (nta_reliable_mreply(irq, NULL((void*)0), NULL((void*)0), msg))
6764 return 0;
6765
6766 return -1;
6767 }
6768
6769 if (status >= 200 && irq->irq_reliable && irq->irq_reliable->rel_unsent) {
6770 if (reliable_final(irq, msg, sip) == 0)
6771 return 0;
6772 }
6773
6774 return incoming_reply(irq, msg, sip);
6775}
6776
6777
6778
6779/** Send the response message.
6780 *
6781 * @note The ownership of msg is handled to incoming_reply().
6782 */
6783int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
6784{
6785 nta_agent_t *agent = irq->irq_agent;
6786 int status = sip->sip_status->st_status;
6787 int sending = 1;
6788 int *use_rport = NULL((void*)0);
6789 int retry_without_rport = 0;
6790 tp_name_t *tpn, default_tpn[1];
6791
6792 if (status == 408 &&
6793 irq->irq_method != sip_method_invite &&
6794 !agent->sa_pass_408 &&
6795 !irq->irq_default) {
6796 /* RFC 4320 nit-actions-03 Action 2:
6797
6798 A transaction-stateful SIP element MUST NOT send a response with
6799 Status-Code of 408 to a non-INVITE request. As a consequence, an
6800 element that can not respond before the transaction expires will not
6801 send a final response at all.
6802 */
6803 sending = 0;
6804 }
6805
6806 if (irq->irq_status == 0 && irq->irq_timestamp && !sip->sip_timestamp)
6807 incoming_timestamp(irq, msg, sip);
6808
6809 if (irq->irq_default) {
6810 if (agent->sa_server_rport)
6811 use_rport = &retry_without_rport, retry_without_rport = 1;
6812 tpn = default_tpn;
6813 if (nta_tpn_by_via(tpn, sip->sip_via, use_rport) < 0)
6814 tpn = NULL((void*)0);
6815 }
6816 else {
6817 tpn = irq->irq_tpn;
6818 }
6819
6820 if (sip_complete_message(msg) < 0)
6821 SU_DEBUG_1(("%s: sip_complete_message() failed\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 6821, "%s: sip_complete_message() failed\n", __func__)) : (
void)0)
;
6822 else if (msg_serialize(msg, (msg_pub_t *)sip) < 0)
6823 SU_DEBUG_1(("%s: sip_serialize() failed\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 6823, "%s: sip_serialize() failed\n", __func__)) : (void)0)
;
6824 else if (!(irq->irq_tport) &&
6825 !(tport_decref(&irq->irq_tport),
6826 irq->irq_tport = tpn ? tport_by_name(agent->sa_tports, tpn) : 0))
6827 SU_DEBUG_1(("%s: no tport\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 6827, "%s: no tport\n", __func__)) : (void)0)
;
6828 else {
6829 int i, err = 0;
6830 tport_t *tp = NULL((void*)0);
6831 incoming_queue_t *queue;
6832
6833 char const *method_name;
6834 uint32_t cseq;
6835
6836 if (irq->irq_default) {
6837 assert(sip->sip_cseq)((void) sizeof ((sip->sip_cseq) ? 1 : 0), __extension__ ({
if (sip->sip_cseq) ; else __assert_fail ("sip->sip_cseq"
, "nta.c", 6837, __extension__ __PRETTY_FUNCTION__); }))
;
6838 method_name = sip->sip_cseq->cs_method_name, cseq = sip->sip_cseq->cs_seq;
6839 }
6840 else {
6841 method_name = irq->irq_rq->rq_method_name, cseq = irq->irq_cseq->cs_seq;
6842 }
6843
6844 if (sending) {
6845 for (i = 0; i < 3; i++) {
6846 tp = tport_tsend(irq->irq_tport, msg, tpn,
6847 IF_SIGCOMP_TPTAG_COMPARTMENT(irq->irq_cc)!(irq->irq_cc && irq->irq_cc != ((void *)-1)) ?
tag_skip : tptag_compartment, tag_ptr_v((irq->irq_cc)),
6848 TPTAG_MTU(INT_MAX)tptag_mtu, tag_usize_v((2147483647)),
6849 TAG_END()(tag_type_t)0, (tag_value_t)0);
6850 if (tp)
6851 break;
6852
6853 err = msg_errno(msg);
6854 SU_DEBUG_5(("%s: tport_tsend: %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6856, "%s: tport_tsend: %s%s\n", __func__, su_strerror(err)
, err == 32 ? "(retrying)" : "")) : (void)0)
6855 __func__, su_strerror(err),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6856, "%s: tport_tsend: %s%s\n", __func__, su_strerror(err)
, err == 32 ? "(retrying)" : "")) : (void)0)
6856 err == EPIPE ? "(retrying)" : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6856, "%s: tport_tsend: %s%s\n", __func__, su_strerror(err)
, err == 32 ? "(retrying)" : "")) : (void)0)
;
6857
6858 if (err != EPIPE32 && err != ECONNREFUSED111)
6859 break;
6860 tport_decref(&irq->irq_tport);
6861 irq->irq_tport = tport_ref(tport_by_name(agent->sa_tports, tpn));
6862 }
6863
6864 if (!tp) {
6865 SU_DEBUG_3(("%s: tport_tsend: "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6868, "%s: tport_tsend: " "error (%s) while sending %u %s for %s (%u)\n"
, __func__, su_strerror(err), status, sip->sip_status->
st_phrase, method_name, cseq)) : (void)0)
6866 "error (%s) while sending %u %s for %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6868, "%s: tport_tsend: " "error (%s) while sending %u %s for %s (%u)\n"
, __func__, su_strerror(err), status, sip->sip_status->
st_phrase, method_name, cseq)) : (void)0)
6867 __func__, su_strerror(err),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6868, "%s: tport_tsend: " "error (%s) while sending %u %s for %s (%u)\n"
, __func__, su_strerror(err), status, sip->sip_status->
st_phrase, method_name, cseq)) : (void)0)
6868 status, sip->sip_status->st_phrase, method_name, cseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 6868, "%s: tport_tsend: " "error (%s) while sending %u %s for %s (%u)\n"
, __func__, su_strerror(err), status, sip->sip_status->
st_phrase, method_name, cseq)) : (void)0)
;
6869 if (status < 200)
6870 msg_destroy(msg);
6871 else
6872 incoming_final_failed(irq, msg);
6873 return 0;
6874 }
6875
6876 agent->sa_stats->as_sent_msg++;
6877 agent->sa_stats->as_sent_response++;
6878 }
6879
6880 SU_DEBUG_5(("nta: %s %u %s for %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6882, "nta: %s %u %s for %s (%u)\n", sending ? "sent" : "not sending"
, status, sip->sip_status->st_phrase, method_name, cseq
)) : (void)0)
6881 sending ? "sent" : "not sending",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6882, "nta: %s %u %s for %s (%u)\n", sending ? "sent" : "not sending"
, status, sip->sip_status->st_phrase, method_name, cseq
)) : (void)0)
6882 status, sip->sip_status->st_phrase, method_name, cseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 6882, "nta: %s %u %s for %s (%u)\n", sending ? "sent" : "not sending"
, status, sip->sip_status->st_phrase, method_name, cseq
)) : (void)0)
;
6883
6884 if (irq->irq_default) {
6885 msg_destroy(msg);
6886 return 0;
6887 }
6888
6889 incoming_reset_timer(irq);
6890
6891 if (status < 200) {
6892 queue = agent->sa_in.proceeding;
6893
6894 if (irq->irq_method == sip_method_invite && status > 100 &&
6895 agent->sa_progress != UINT_MAX(2147483647 *2U +1U) && agent->sa_is_a_uas) {
6896 /* Retransmit preliminary responses in regular intervals */
6897 incoming_set_timer(irq, agent->sa_progress); /* N2 */
6898 }
6899 }
6900 else {
6901 irq->irq_completed = 1;
6902
6903 /* XXX - we should do this only after message has actually been sent! */
6904 if (irq->irq_sigcomp_zap && irq->irq_cc)
6905 agent_close_compressor(irq->irq_agent, irq->irq_cc);
6906
6907 if (irq->irq_method != sip_method_invite) {
6908 irq->irq_confirmed = 1;
6909
6910 if (irq->irq_reliable_tp) {
6911 irq->irq_terminated = 1;
6912 queue = agent->sa_in.terminated ; /* J - set for 0 seconds */
6913 } else {
6914 queue = agent->sa_in.completed; /* J */
6915 }
6916
6917 tport_decref(&irq->irq_tport);
6918 }
6919 else if (status >= 300 || agent->sa_is_a_uas) {
6920 if (status < 300 || !irq->irq_reliable_tp)
6921 incoming_set_timer(irq, agent->sa_t1); /* G */
6922 queue = agent->sa_in.inv_completed; /* H */
6923 }
6924 else {
6925#if 1
6926 /* Avoid bug in @RFC3261:
6927 Keep INVITE transaction around in order to catch
6928 retransmitted INVITEs
6929 */
6930 irq->irq_confirmed = 1;
6931 queue = agent->sa_in.inv_confirmed; /* H */
6932#else
6933 irq->irq_terminated = 1;
6934 queue = agent->sa_in.terminated;
6935#endif
6936 }
6937 }
6938
6939 if (irq->irq_queue != queue)
6940 incoming_queue(queue, irq);
6941
6942 if (status >= 200 || irq->irq_status < 200) {
6943 if (irq->irq_response)
6944 msg_destroy(irq->irq_response);
6945 assert(msg_home(msg) != irq->irq_home)((void) sizeof ((((su_home_t*)(msg)) != irq->irq_home) ? 1
: 0), __extension__ ({ if (((su_home_t*)(msg)) != irq->irq_home
) ; else __assert_fail ("msg_home(msg) != irq->irq_home", "nta.c"
, 6945, __extension__ __PRETTY_FUNCTION__); }))
;
6946 irq->irq_response = msg;
6947 }
6948 else {
6949 msg_destroy(msg);
6950 }
6951
6952 if (sip->sip_cseq->cs_method == irq->irq_method &&
6953 irq->irq_status < 200 && status > irq->irq_status)
6954 irq->irq_status = status;
6955
6956 return 0;
6957 }
6958
6959 /*
6960 * XXX - handling error is very problematic.
6961 * Nobody checks return code from nta_incoming_*reply()
6962 */
6963 if (status < 200) {
6964 msg_destroy(msg);
6965 return -1;
6966 }
6967
6968 /* We could not send final response. */
6969 return incoming_final_failed(irq, msg);
6970}
6971
6972
6973/** @internal Sending final response has failed.
6974 *
6975 * Put transaction into its own queue, try later to send the response.
6976 */
6977su_inlinestatic inline
6978int incoming_final_failed(nta_incoming_t *irq, msg_t *msg)
6979{
6980 msg_destroy(msg);
6981
6982 if (!irq->irq_default) {
6983 irq->irq_final_failed = 1;
6984 incoming_queue(irq->irq_agent->sa_in.final_failed, irq);
6985 }
6986
6987 return -1;
6988}
6989
6990/** @internal Retransmit the reply */
6991static
6992void incoming_retransmit_reply(nta_incoming_t *irq, tport_t *tport)
6993{
6994 msg_t *msg = NULL((void*)0);
6995
6996 if (irq->irq_final_failed)
6997 return;
6998
6999 if (tport == NULL((void*)0))
7000 tport = irq->irq_tport;
7001
7002 /* Answer with existing reply */
7003 if (irq->irq_reliable && !irq->irq_reliable->rel_pracked)
7004 msg = reliable_response(irq);
7005 else
7006 msg = irq->irq_response;
7007
7008 if (msg && tport) {
7009 irq->irq_retries++;
7010
7011 if (irq->irq_retries == 2 && irq->irq_tpn->tpn_comp) {
7012 irq->irq_tpn->tpn_comp = NULL((void*)0);
7013
7014 if (irq->irq_cc) {
7015 agent_close_compressor(irq->irq_agent, irq->irq_cc);
7016 nta_compartment_decref(&irq->irq_cc);
7017 }
7018 }
7019
7020 tport_tsend(tport, msg, irq->irq_tpn,
7021 IF_SIGCOMP_TPTAG_COMPARTMENT(irq->irq_cc)!(irq->irq_cc && irq->irq_cc != ((void *)-1)) ?
tag_skip : tptag_compartment, tag_ptr_v((irq->irq_cc)),
7022 TPTAG_MTU(INT_MAX)tptag_mtu, tag_usize_v((2147483647)), TAG_END()(tag_type_t)0, (tag_value_t)0);
7023 irq->irq_agent->sa_stats->as_sent_msg++;
7024 irq->irq_agent->sa_stats->as_sent_response++;
7025 }
7026}
7027
7028/** @internal Create timestamp header for response */
7029static
7030int incoming_timestamp(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
7031{
7032 sip_timestamp_t ts[1];
7033 su_time_t now = su_now();
7034 char delay[32];
7035 double diff = su_time_diff(now, irq->irq_received);
7036
7037 snprintf(delay, sizeof delay, "%.06f", diff);
7038
7039 *ts = *irq->irq_timestamp;
7040 ts->ts_delay = delay;
7041
7042 return sip_add_dup(msg, sip, (sip_header_t *)ts);
7043}
7044
7045enum {
7046 timer_max_retransmit = 30,
7047 timer_max_terminate = 100000,
7048 timer_max_timeout = 100
7049};
7050
7051/** @internal Timer routine for the incoming request. */
7052static void
7053_nta_incoming_timer(nta_agent_t *sa)
7054{
7055 uint32_t now;
7056 nta_incoming_t *irq, *irq_next;
7057 size_t retransmitted = 0, timeout = 0, terminated = 0, destroyed = 0;
7058 size_t unconfirmed =
7059 sa->sa_in.inv_completed->q_length +
7060 sa->sa_in.preliminary->q_length;
7061 size_t unterminated =
7062 sa->sa_in.inv_confirmed->q_length +
7063 sa->sa_in.completed->q_length;
7064 size_t total = sa->sa_incoming->iht_used;
7065
7066 incoming_queue_t rq[1];
7067
7068 incoming_queue_init(rq, 0);
7069
7070 /* Handle retry queue */
7071 while ((irq = sa->sa_in.re_list)) {
7072
7073 now = su_time_ms(su_now());
7074
7075 if ((int32_t)(irq->irq_retry - now) > 0)
7076 break;
7077 if (retransmitted >= timer_max_retransmit)
7078 break;
7079
7080 if (irq->irq_method == sip_method_invite && irq->irq_status >= 200) {
7081 /* Timer G */
7082 assert(irq->irq_queue == sa->sa_in.inv_completed)((void) sizeof ((irq->irq_queue == sa->sa_in.inv_completed
) ? 1 : 0), __extension__ ({ if (irq->irq_queue == sa->
sa_in.inv_completed) ; else __assert_fail ("irq->irq_queue == sa->sa_in.inv_completed"
, "nta.c", 7082, __extension__ __PRETTY_FUNCTION__); }))
;
7083
7084 retransmitted++;
7085
7086 SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7087, "nta: timer %s fired, retransmitting %u reply\n", "G"
, irq->irq_status)) : (void)0)
7087 "G", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7087, "nta: timer %s fired, retransmitting %u reply\n", "G"
, irq->irq_status)) : (void)0)
;
7088
7089 incoming_retransmit_reply(irq, irq->irq_tport);
7090
7091 if (2U * irq->irq_interval < sa->sa_t2)
7092 incoming_set_timer(irq, 2U * irq->irq_interval); /* G */
7093 else
7094 incoming_set_timer(irq, sa->sa_t2); /* G */
7095 }
7096 else if (irq->irq_method == sip_method_invite && irq->irq_status >= 100) {
7097 if (irq->irq_queue == sa->sa_in.preliminary) {
7098 /* Timer P1 - PRACK timer */
7099 retransmitted++;
7100 SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7101, "nta: timer %s fired, retransmitting %u reply\n", "P1"
, irq->irq_status)) : (void)0)
7101 "P1", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7101, "nta: timer %s fired, retransmitting %u reply\n", "P1"
, irq->irq_status)) : (void)0)
;
7102
7103 incoming_retransmit_reply(irq, irq->irq_tport);
7104
7105 incoming_set_timer(irq, 2 * irq->irq_interval); /* P1 */
7106 }
7107 else {
7108 /* Retransmitting provisional responses */
7109 SU_DEBUG_5(("nta: timer %s fired, retransmitting %u reply\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7110, "nta: timer %s fired, retransmitting %u reply\n", "N2"
, irq->irq_status)) : (void)0)
7110 "N2", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7110, "nta: timer %s fired, retransmitting %u reply\n", "N2"
, irq->irq_status)) : (void)0)
;
7111 incoming_set_timer(irq, sa->sa_progress);
7112 retransmitted++;
7113 incoming_retransmit_reply(irq, irq->irq_tport);
7114 }
7115 }
7116 else {
7117 /* Timer N1 */
7118 incoming_reset_timer(irq);
7119
7120 if(irq->irq_extra_100) {
7121 SU_DEBUG_5(("nta: timer N1 fired, sending %u %s\n", SIP_100_TRYING))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7121, "nta: timer N1 fired, sending %u %s\n", 100, sip_100_Trying
)) : (void)0)
;
7122 nta_incoming_treply(irq, SIP_100_TRYING100, sip_100_Trying, TAG_END()(tag_type_t)0, (tag_value_t)0);
7123 }
7124 else {
7125 SU_DEBUG_5(("nta: timer N1 fired, but avoided sending %u %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7126, "nta: timer N1 fired, but avoided sending %u %s\n", 100
, sip_100_Trying)) : (void)0)
7126 SIP_100_TRYING))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7126, "nta: timer N1 fired, but avoided sending %u %s\n", 100
, sip_100_Trying)) : (void)0)
;
7127 }
7128 }
7129 }
7130
7131 while ((irq = sa->sa_in.final_failed->q_head)) {
7132
7133
7134 incoming_remove(irq);
7135 irq->irq_final_failed = 0;
7136
7137 /* Report error to application */
7138 SU_DEBUG_5(("nta: sending final response failed, timeout %u response\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7139, "nta: sending final response failed, timeout %u response\n"
, irq->irq_status)) : (void)0)
7139 irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7139, "nta: sending final response failed, timeout %u response\n"
, irq->irq_status)) : (void)0)
;
7140 reliable_timeout(irq, 0);
7141
7142 nta_incoming_treply(irq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error, TAG_END()(tag_type_t)0, (tag_value_t)0);
7143
7144 if (!irq->irq_final_failed) /* We have taken care of the error... */
7145 continue;
7146
7147 if (irq->irq_destroyed) {
7148 incoming_free_queue(rq, irq);
7149 continue;
7150 }
7151
7152 incoming_reset_timer(irq);
7153 irq->irq_confirmed = 1;
7154 irq->irq_terminated = 1;
7155 incoming_queue(sa->sa_in.terminated, irq);
7156 }
7157
7158 /* Timeouts.
7159 * For each state the request is in, there is always a queue of its own
7160 */
7161 while ((irq = sa->sa_in.preliminary->q_head)) {
7162 assert(irq->irq_status < 200)((void) sizeof ((irq->irq_status < 200) ? 1 : 0), __extension__
({ if (irq->irq_status < 200) ; else __assert_fail ("irq->irq_status < 200"
, "nta.c", 7162, __extension__ __PRETTY_FUNCTION__); }))
;
7163 assert(irq->irq_timeout)((void) sizeof ((irq->irq_timeout) ? 1 : 0), __extension__
({ if (irq->irq_timeout) ; else __assert_fail ("irq->irq_timeout"
, "nta.c", 7163, __extension__ __PRETTY_FUNCTION__); }))
;
7164
7165 now = su_time_ms(su_now());
7166
7167 if ((int32_t)(irq->irq_timeout - now) > 0)
7168 break;
7169 if (timeout >= timer_max_timeout)
7170 break;
7171
7172 timeout++;
7173
7174 /* Timer P2 - PRACK timer */
7175 SU_DEBUG_5(("nta: timer %s fired, %s %u response\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7176, "nta: timer %s fired, %s %u response\n", "P2", "timeout"
, irq->irq_status)) : (void)0)
7176 "P2", "timeout", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7176, "nta: timer %s fired, %s %u response\n", "P2", "timeout"
, irq->irq_status)) : (void)0)
;
7177 incoming_reset_timer(irq);
7178 irq->irq_timeout = 0;
7179 reliable_timeout(irq, 1);
7180 }
7181
7182 while ((irq = sa->sa_in.inv_completed->q_head)) {
7183 assert(irq->irq_status >= 200)((void) sizeof ((irq->irq_status >= 200) ? 1 : 0), __extension__
({ if (irq->irq_status >= 200) ; else __assert_fail ("irq->irq_status >= 200"
, "nta.c", 7183, __extension__ __PRETTY_FUNCTION__); }))
;
7184 assert(irq->irq_timeout)((void) sizeof ((irq->irq_timeout) ? 1 : 0), __extension__
({ if (irq->irq_timeout) ; else __assert_fail ("irq->irq_timeout"
, "nta.c", 7184, __extension__ __PRETTY_FUNCTION__); }))
;
7185 assert(irq->irq_method == sip_method_invite)((void) sizeof ((irq->irq_method == sip_method_invite) ? 1
: 0), __extension__ ({ if (irq->irq_method == sip_method_invite
) ; else __assert_fail ("irq->irq_method == sip_method_invite"
, "nta.c", 7185, __extension__ __PRETTY_FUNCTION__); }))
;
7186
7187 now = su_time_ms(su_now());
7188
7189 if ((int32_t)(irq->irq_timeout - now) > 0 ||
7190 timeout >= timer_max_timeout ||
7191 terminated >= timer_max_terminate)
7192 break;
7193
7194 /* Timer H */
7195 SU_DEBUG_5(("nta: timer %s fired, %s %u response\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7196, "nta: timer %s fired, %s %u response\n", "H", "timeout and terminate"
, irq->irq_status)) : (void)0)
7196 "H", "timeout and terminate", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7196, "nta: timer %s fired, %s %u response\n", "H", "timeout and terminate"
, irq->irq_status)) : (void)0)
;
7197 irq->irq_confirmed = 1;
7198 irq->irq_terminated = 1;
7199 incoming_reset_timer(irq);
7200 if (!irq->irq_destroyed) {
7201 timeout++;
7202 incoming_queue(sa->sa_in.terminated, irq);
7203 /* report timeout error to user */
7204 incoming_call_callback(irq, NULL((void*)0), NULL((void*)0));
7205 } else {
7206 timeout++;
7207 terminated++;
7208 incoming_free_queue(rq, irq);
7209 }
7210 }
7211
7212 while ((irq = sa->sa_in.inv_confirmed->q_head)) {
7213 assert(irq->irq_timeout)((void) sizeof ((irq->irq_timeout) ? 1 : 0), __extension__
({ if (irq->irq_timeout) ; else __assert_fail ("irq->irq_timeout"
, "nta.c", 7213, __extension__ __PRETTY_FUNCTION__); }))
;
7214 assert(irq->irq_status >= 200)((void) sizeof ((irq->irq_status >= 200) ? 1 : 0), __extension__
({ if (irq->irq_status >= 200) ; else __assert_fail ("irq->irq_status >= 200"
, "nta.c", 7214, __extension__ __PRETTY_FUNCTION__); }))
;
7215 assert(irq->irq_method == sip_method_invite)((void) sizeof ((irq->irq_method == sip_method_invite) ? 1
: 0), __extension__ ({ if (irq->irq_method == sip_method_invite
) ; else __assert_fail ("irq->irq_method == sip_method_invite"
, "nta.c", 7215, __extension__ __PRETTY_FUNCTION__); }))
;
7216
7217 now = su_time_ms(su_now());
7218
7219 if ((int32_t)(irq->irq_timeout - now) > 0 ||
7220 terminated >= timer_max_terminate)
7221 break;
7222
7223 /* Timer I */
7224 SU_DEBUG_5(("nta: timer %s fired, %s %u response\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7225, "nta: timer %s fired, %s %u response\n", "I", "terminate"
, irq->irq_status)) : (void)0)
7225 "I", "terminate", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7225, "nta: timer %s fired, %s %u response\n", "I", "terminate"
, irq->irq_status)) : (void)0)
;
7226
7227 terminated++;
7228 irq->irq_terminated = 1;
7229
7230 if (!irq->irq_destroyed)
7231 incoming_queue(sa->sa_in.terminated, irq);
7232 else
7233 incoming_free_queue(rq, irq);
7234 }
7235
7236 while ((irq = sa->sa_in.completed->q_head)) {
7237 assert(irq->irq_status >= 200)((void) sizeof ((irq->irq_status >= 200) ? 1 : 0), __extension__
({ if (irq->irq_status >= 200) ; else __assert_fail ("irq->irq_status >= 200"
, "nta.c", 7237, __extension__ __PRETTY_FUNCTION__); }))
;
7238 assert(irq->irq_timeout)((void) sizeof ((irq->irq_timeout) ? 1 : 0), __extension__
({ if (irq->irq_timeout) ; else __assert_fail ("irq->irq_timeout"
, "nta.c", 7238, __extension__ __PRETTY_FUNCTION__); }))
;
7239 assert(irq->irq_method != sip_method_invite)((void) sizeof ((irq->irq_method != sip_method_invite) ? 1
: 0), __extension__ ({ if (irq->irq_method != sip_method_invite
) ; else __assert_fail ("irq->irq_method != sip_method_invite"
, "nta.c", 7239, __extension__ __PRETTY_FUNCTION__); }))
;
7240
7241 now = su_time_ms(su_now());
7242
7243 if ((int32_t)(irq->irq_timeout - now) > 0 ||
7244 terminated >= timer_max_terminate)
7245 break;
7246
7247 /* Timer J */
7248
7249 SU_DEBUG_5(("nta: timer %s fired, %s %u response\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7250, "nta: timer %s fired, %s %u response\n", "J", "terminate"
, irq->irq_status)) : (void)0)
7250 "J", "terminate", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7250, "nta: timer %s fired, %s %u response\n", "J", "terminate"
, irq->irq_status)) : (void)0)
;
7251
7252 terminated++;
7253 irq->irq_terminated = 1;
7254
7255 if (!irq->irq_destroyed)
7256 incoming_queue(sa->sa_in.terminated, irq);
7257 else
7258 incoming_free_queue(rq, irq);
7259 }
7260
7261 for (irq = sa->sa_in.terminated->q_head; irq; irq = irq_next) {
7262
7263 irq_next = irq->irq_next;
7264 if (irq->irq_destroyed)
7265 incoming_free_queue(rq, irq);
7266 }
7267
7268 destroyed = incoming_mass_destroy(sa, rq);
7269
7270 if (retransmitted || timeout || terminated || destroyed)
7271 SU_DEBUG_5(("nta_incoming_timer: "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7272 MOD_ZU"/"MOD_ZU" resent, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7273 MOD_ZU"/"MOD_ZU" tout, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7274 MOD_ZU"/"MOD_ZU" term, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7275 MOD_ZU"/"MOD_ZU" free\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7276 retransmitted, unconfirmed,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7277 timeout, unconfirmed,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7278 terminated, unterminated,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
7279 destroyed, total))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7279, "nta_incoming_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, unconfirmed, timeout, unconfirmed, terminated
, unterminated, destroyed, total)) : (void)0)
;
7280}
7281
7282/** Mass destroy server transactions */
7283su_inlinestatic inline
7284size_t incoming_mass_destroy(nta_agent_t *sa, incoming_queue_t *q)
7285{
7286 size_t destroyed = q->q_length;
7287
7288 if (destroyed > 2 && *sa->sa_terminator) {
7289 su_msg_r m = SU_MSG_R_INIT{ ((void*)0) };
7290
7291 if (su_msg_create(m,
7292 su_clone_task(sa->sa_terminator),
7293 su_root_task(sa->sa_root),
7294 incoming_reclaim_queued,
7295 sizeof(incoming_queue_t)) == SU_SUCCESSsu_success) {
7296 incoming_queue_t *mq = su_msg_data(m)->a_incoming_queue;
7297
7298 *mq = *q;
7299
7300 if (su_msg_send(m) == SU_SUCCESSsu_success)
7301 q->q_length = 0;
7302 }
7303 }
7304
7305 if (q->q_length > 0)
7306 incoming_reclaim_queued(NULL((void*)0), NULL((void*)0), (void *)q);
7307
7308 return destroyed;
7309}
7310
7311/* ====================================================================== */
7312/* 8) Client-side (outgoing) transactions */
7313
7314#define HTABLE_HASH_ORQ(orq)((orq)->orq_hash) ((orq)->orq_hash)
7315
7316#ifdef __clang__1
7317#pragma clang diagnostic push
7318#pragma clang diagnostic ignored "-Wunused-function"
7319#endif
7320
7321HTABLE_BODIES_WITH(outgoing_htable, oht, nta_outgoing_t, HTABLE_HASH_ORQ,static inline int outgoing_htable_resize(su_home_t *home, outgoing_htable_t
oht[], size_t new_size) { nta_outgoing_t **new_hash; nta_outgoing_t
**old_hash = oht->oht_table; size_t old_size; size_t i, j
, i0; unsigned again = 0; size_t used = 0; if (new_size == 0)
new_size = 2 * oht->oht_size + 1; if (new_size < 31) new_size
= 31; if (new_size < 5 * oht->oht_used / 4) new_size =
5 * oht->oht_used / 4; if (!(new_hash = su_zalloc(home, sizeof
(*new_hash) * new_size))) return -1; old_size = oht->oht_size
; do for (j = 0; j < old_size; j++) { if (!old_hash[j]) continue
; if (again < 2 && ((old_hash[j])->orq_hash) % old_size
> j) { again = 1; continue; } i0 = ((old_hash[j])->orq_hash
) % new_size; for (i = i0; new_hash[i]; i = (i + 1) % new_size
, ((void) sizeof ((i != i0) ? 1 : 0), __extension__ ({ if (i !=
i0) ; else __assert_fail ("i != i0", "nta.c", 7322, __extension__
__PRETTY_FUNCTION__); }))); new_hash[i] = old_hash[j], old_hash
[j] = ((void*)0); used++; } while (again++ == 1); oht->oht_table
= new_hash, oht->oht_size = new_size; ((void) sizeof ((oht
->oht_used == used) ? 1 : 0), __extension__ ({ if (oht->
oht_used == used) ; else __assert_fail ("oht->oht_used == used"
, "nta.c", 7322, __extension__ __PRETTY_FUNCTION__); })); su_free
(home, old_hash); return 0; } static inline int outgoing_htable_is_full
(outgoing_htable_t const *oht) { return oht->oht_table == (
(void*)0) || 3 * oht->oht_used > 2 * oht->oht_size; }
static inline nta_outgoing_t **outgoing_htable_hash(outgoing_htable_t
const *oht, hash_value_t hv) { return oht->oht_table + hv
% oht->oht_size; } static inline nta_outgoing_t **outgoing_htable_next
(outgoing_htable_t const *oht, nta_outgoing_t * const *ee) { if
(++ee < oht->oht_table + oht->oht_size && ee
>= oht->oht_table) return (nta_outgoing_t **)ee; else return
oht->oht_table; } static inline void outgoing_htable_append
(outgoing_htable_t *oht, nta_outgoing_t const *e) { nta_outgoing_t
**ee; oht->oht_used++; for (ee = outgoing_htable_hash(oht
, ((e)->orq_hash)); *ee; ee = outgoing_htable_next(oht, ee
)) ; *ee = (nta_outgoing_t *)e; } static inline void outgoing_htable_insert
(outgoing_htable_t *oht, nta_outgoing_t const *e) { nta_outgoing_t
*e0, **ee; oht->oht_used++; for (ee = outgoing_htable_hash
(oht, ((e)->orq_hash)); (e0 = *ee); ee = outgoing_htable_next
(oht, ee)) *ee = (nta_outgoing_t *)e, e = e0; *ee = (nta_outgoing_t
*)e; } static inline int outgoing_htable_remove(outgoing_htable_t
*oht, nta_outgoing_t const *e) { size_t i, j, k; size_t size
= oht->oht_size; nta_outgoing_t **htable = oht->oht_table
; if (!e) return -1; for (i = ((e)->orq_hash) % size; htable
[i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->orq_hash) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } oht->oht_used--; htable[i] = ((void*)0); return 0; } extern
int outgoing_htable_dummy
7322 size_t, hash_value_t)static inline int outgoing_htable_resize(su_home_t *home, outgoing_htable_t
oht[], size_t new_size) { nta_outgoing_t **new_hash; nta_outgoing_t
**old_hash = oht->oht_table; size_t old_size; size_t i, j
, i0; unsigned again = 0; size_t used = 0; if (new_size == 0)
new_size = 2 * oht->oht_size + 1; if (new_size < 31) new_size
= 31; if (new_size < 5 * oht->oht_used / 4) new_size =
5 * oht->oht_used / 4; if (!(new_hash = su_zalloc(home, sizeof
(*new_hash) * new_size))) return -1; old_size = oht->oht_size
; do for (j = 0; j < old_size; j++) { if (!old_hash[j]) continue
; if (again < 2 && ((old_hash[j])->orq_hash) % old_size
> j) { again = 1; continue; } i0 = ((old_hash[j])->orq_hash
) % new_size; for (i = i0; new_hash[i]; i = (i + 1) % new_size
, ((void) sizeof ((i != i0) ? 1 : 0), __extension__ ({ if (i !=
i0) ; else __assert_fail ("i != i0", "nta.c", 7322, __extension__
__PRETTY_FUNCTION__); }))); new_hash[i] = old_hash[j], old_hash
[j] = ((void*)0); used++; } while (again++ == 1); oht->oht_table
= new_hash, oht->oht_size = new_size; ((void) sizeof ((oht
->oht_used == used) ? 1 : 0), __extension__ ({ if (oht->
oht_used == used) ; else __assert_fail ("oht->oht_used == used"
, "nta.c", 7322, __extension__ __PRETTY_FUNCTION__); })); su_free
(home, old_hash); return 0; } static inline int outgoing_htable_is_full
(outgoing_htable_t const *oht) { return oht->oht_table == (
(void*)0) || 3 * oht->oht_used > 2 * oht->oht_size; }
static inline nta_outgoing_t **outgoing_htable_hash(outgoing_htable_t
const *oht, hash_value_t hv) { return oht->oht_table + hv
% oht->oht_size; } static inline nta_outgoing_t **outgoing_htable_next
(outgoing_htable_t const *oht, nta_outgoing_t * const *ee) { if
(++ee < oht->oht_table + oht->oht_size && ee
>= oht->oht_table) return (nta_outgoing_t **)ee; else return
oht->oht_table; } static inline void outgoing_htable_append
(outgoing_htable_t *oht, nta_outgoing_t const *e) { nta_outgoing_t
**ee; oht->oht_used++; for (ee = outgoing_htable_hash(oht
, ((e)->orq_hash)); *ee; ee = outgoing_htable_next(oht, ee
)) ; *ee = (nta_outgoing_t *)e; } static inline void outgoing_htable_insert
(outgoing_htable_t *oht, nta_outgoing_t const *e) { nta_outgoing_t
*e0, **ee; oht->oht_used++; for (ee = outgoing_htable_hash
(oht, ((e)->orq_hash)); (e0 = *ee); ee = outgoing_htable_next
(oht, ee)) *ee = (nta_outgoing_t *)e, e = e0; *ee = (nta_outgoing_t
*)e; } static inline int outgoing_htable_remove(outgoing_htable_t
*oht, nta_outgoing_t const *e) { size_t i, j, k; size_t size
= oht->oht_size; nta_outgoing_t **htable = oht->oht_table
; if (!e) return -1; for (i = ((e)->orq_hash) % size; htable
[i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->orq_hash) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } oht->oht_used--; htable[i] = ((void*)0); return 0; } extern
int outgoing_htable_dummy
;
7323
7324#ifdef __clang__1
7325#pragma clang diagnostic pop
7326#endif
7327
7328static int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq,
7329 msg_t *msg, sip_t *sip,
7330 tagi_t *tags);
7331static void outgoing_prepare_send(nta_outgoing_t *orq);
7332static void outgoing_send_via(nta_outgoing_t *orq, tport_t *tp);
7333static void outgoing_send(nta_outgoing_t *orq, int retransmit);
7334static void outgoing_try_tcp_instead(nta_outgoing_t *orq);
7335static void outgoing_try_udp_instead(nta_outgoing_t *orq, int timeout);
7336static void outgoing_tport_error(nta_agent_t *agent, nta_outgoing_t *orq,
7337 tport_t *tp, msg_t *msg, int error);
7338static void outgoing_print_tport_error(nta_outgoing_t *orq,
7339 int level, char *todo,
7340 tp_name_t const *, msg_t *, int error);
7341static void outgoing_insert(nta_agent_t *sa, nta_outgoing_t *orq);
7342static void outgoing_destroy(nta_outgoing_t *orq);
7343su_inlinestatic inline int outgoing_is_queued(nta_outgoing_t const *orq);
7344su_inlinestatic inline void outgoing_queue(outgoing_queue_t *queue,
7345 nta_outgoing_t *orq);
7346su_inlinestatic inline void outgoing_remove(nta_outgoing_t *orq);
7347su_inlinestatic inline void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval);
7348static void outgoing_reset_timer(nta_outgoing_t *orq);
7349static size_t outgoing_timer_dk(outgoing_queue_t *q,
7350 char const *timer,
7351 uint32_t now);
7352static size_t outgoing_timer_bf(outgoing_queue_t *q,
7353 char const *timer,
7354 uint32_t now);
7355static size_t outgoing_timer_c(outgoing_queue_t *q,
7356 char const *timer,
7357 uint32_t now);
7358
7359static void outgoing_ack(nta_outgoing_t *orq, sip_t *sip);
7360static msg_t *outgoing_ackmsg(nta_outgoing_t *, sip_method_t, char const *,
7361 tag_type_t tag, tag_value_t value, ...);
7362static void outgoing_retransmit(nta_outgoing_t *orq);
7363static void outgoing_trying(nta_outgoing_t *orq);
7364static void outgoing_timeout(nta_outgoing_t *orq, uint32_t now);
7365static int outgoing_complete(nta_outgoing_t *orq);
7366static void outgoing_terminate_invite(nta_outgoing_t *);
7367static void outgoing_remove_fork(nta_outgoing_t *orq);
7368static int outgoing_terminate(nta_outgoing_t *orq);
7369static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q);
7370static void outgoing_estimate_delay(nta_outgoing_t *orq, sip_t *sip);
7371static int outgoing_duplicate(nta_outgoing_t *orq,
7372 msg_t *msg,
7373 sip_t *sip);
7374static int outgoing_reply(nta_outgoing_t *orq,
7375 int status, char const *phrase,
7376 int delayed);
7377
7378static int outgoing_default_cb(nta_outgoing_magic_t *magic,
7379 nta_outgoing_t *request,
7380 sip_t const *sip);
7381
7382
7383/** Create a default outgoing transaction.
7384 *
7385 * The default outgoing transaction is used when agent receives responses
7386 * not belonging to any transaction.
7387 *
7388 * @sa nta_leg_default(), nta_incoming_default().
7389 */
7390nta_outgoing_t *nta_outgoing_default(nta_agent_t *agent,
7391 nta_response_f *callback,
7392 nta_outgoing_magic_t *magic)
7393{
7394 nta_outgoing_t *orq;
7395
7396 if (agent == NULL((void*)0))
7397 return NULL((void*)0);
7398
7399 if (agent->sa_default_outgoing)
7400 return NULL((void*)0);
7401
7402 orq = su_zalloc(agent->sa_home, sizeof *orq);
7403 if (!orq)
7404 return NULL((void*)0);
7405
7406 orq->orq_agent = agent;
7407 orq->orq_callback = callback;
7408 orq->orq_magic = magic;
7409 orq->orq_method = sip_method_invalid;
7410 orq->orq_method_name = "*";
7411 orq->orq_default = 1;
7412 orq->orq_stateless = 1;
7413 orq->orq_delay = UINT_MAX(2147483647 *2U +1U);
7414
7415 return agent->sa_default_outgoing = orq;
7416}
7417
7418/**Create an outgoing request and client transaction belonging to the leg.
7419 *
7420 * Create a request message and pass the request message to an outgoing
7421 * client transaction object. The request is sent to the @a route_url (if
7422 * non-NULL), default proxy (if defined by NTATAG_DEFAULT_PROXY()), or to
7423 * the address specified by @a request_uri. If no @a request_uri is
7424 * specified, it is taken from route-set target or from the @To header.
7425 *
7426 * When NTA receives response to the request, it invokes the @a callback
7427 * function.
7428 *
7429 * @param leg call leg object
7430 * @param callback callback function (may be @c NULL)
7431 * @param magic application context pointer
7432 * @param route_url optional URL used to route transaction requests
7433 * @param method method type
7434 * @param name method name
7435 * @param request_uri Request-URI
7436 * @param tag, value, ... list of tagged arguments
7437 *
7438 * @return
7439 * A pointer to a newly created outgoing transaction object if successful,
7440 * and NULL otherwise.
7441 *
7442 * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL,
7443 * the transaction object is marked as destroyed from the beginning. In that
7444 * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the
7445 * transaction is freed before returning from the function.
7446 *
7447 * @sa
7448 * nta_outgoing_mcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
7449 *
7450 * @TAGS
7451 * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
7452 * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
7453 * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
7454 * SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message.
7455 * SIP tags after SIPTAG_END() are ignored, however.
7456 */
7457nta_outgoing_t *nta_outgoing_tcreate(nta_leg_t *leg,
7458 nta_response_f *callback,
7459 nta_outgoing_magic_t *magic,
7460 url_string_t const *route_url,
7461 sip_method_t method,
7462 char const *name,
7463 url_string_t const *request_uri,
7464 tag_type_t tag, tag_value_t value, ...)
7465{
7466 nta_agent_t *agent;
7467 msg_t *msg;
7468 sip_t *sip;
7469 nta_outgoing_t *orq = NULL((void*)0);
7470 ta_list ta;
7471 tagi_t const *tagi;
7472
7473 if (leg == NULL((void*)0))
7474 return NULL((void*)0);
7475
7476 agent = leg->leg_agent;
7477 msg = nta_msg_create(agent, 0);
7478 sip = sip_object(msg);
7479
7480 if (route_url == NULL((void*)0))
7481 route_url = (url_string_t *)agent->sa_default_proxy;
7482
7483 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
7484
7485 tagi = ta_args(ta)(ta).tl;
7486
7487 if (sip_add_tagis(msg, sip, &tagi) < 0) {
7488 if (tagi && tagi->t_tag) {
7489 tag_type_t t = tagi->t_tag;
7490 SU_DEBUG_5(("%s(): bad tag %s::%s\n", __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7491, "%s(): bad tag %s::%s\n", __func__, t->tt_ns ? t->
tt_ns : "", t->tt_name ? t->tt_name : "")) : (void)0)
7491 t->tt_ns ? t->tt_ns : "", t->tt_name ? t->tt_name : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 7491, "%s(): bad tag %s::%s\n", __func__, t->tt_ns ? t->
tt_ns : "", t->tt_name ? t->tt_name : "")) : (void)0)
;
7492 }
7493 }
7494 else if (route_url == NULL((void*)0) && leg->leg_route &&
7495 leg->leg_loose_route &&
7496 !(route_url = (url_string_t *)leg->leg_route->r_url))
7497 ;
7498 else if (nta_msg_request_complete(msg, leg, method, name, request_uri) < 0)
7499 ;
7500 else
7501 orq = outgoing_create(agent, callback, magic, route_url, NULL((void*)0), msg,
7502 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
7503
7504 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
7505
7506 if (!orq)
7507 msg_destroy(msg);
7508
7509 return orq;
7510}
7511
7512/**Create an outgoing client transaction.
7513 *
7514 * Create an outgoing transaction object. The request message is passed to
7515 * the transaction object, which sends the request to the network. The
7516 * request is sent to the @a route_url (if non-NULL), default proxy (if
7517 * defined by NTATAG_DEFAULT_PROXY()), or to the address specified by @a
7518 * request_uri. If no @a request_uri is specified, it is taken from
7519 * route-set target or from the @To header.
7520 *
7521 * When NTA receives response to the request, it invokes the @a callback
7522 * function.
7523 *
7524 * @param agent NTA agent object
7525 * @param callback callback function (may be @c NULL)
7526 * @param magic application context pointer
7527 * @param route_url optional URL used to route transaction requests
7528 * @param msg request message
7529 * @param tag, value, ... tagged parameter list
7530 *
7531 * @return
7532 * Returns a pointer to newly created outgoing transaction object if
7533 * successful, and NULL otherwise.
7534 *
7535 * @note The caller is responsible for destroying the request message @a msg
7536 * upon failure.
7537 *
7538 * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL,
7539 * the transaction object is marked as destroyed from the beginning. In that
7540 * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the
7541 * transaction is freed before returning from the function.
7542 *
7543 * @sa
7544 * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
7545 *
7546 * @TAGS
7547 * NTATAG_STATELESS(), NTATAG_DELAY_SENDING(), NTATAG_BRANCH_KEY(),
7548 * NTATAG_ACK_BRANCH(), NTATAG_DEFAULT_PROXY(), NTATAG_PASS_100(),
7549 * NTATAG_USE_TIMESTAMP(), NTATAG_USER_VIA(), TPTAG_IDENT(), NTATAG_TPORT(). All
7550 * SIP tags from <sofia-sip/sip_tag.h> can be used to manipulate the request message.
7551 * SIP tags after SIPTAG_END() are ignored, however.
7552 */
7553nta_outgoing_t *nta_outgoing_mcreate(nta_agent_t *agent,
7554 nta_response_f *callback,
7555 nta_outgoing_magic_t *magic,
7556 url_string_t const *route_url,
7557 msg_t *msg,
7558 tag_type_t tag, tag_value_t value, ...)
7559{
7560 nta_outgoing_t *orq = NULL((void*)0);
7561 int cleanup = 0;
7562
7563 if (msg == NONE((void *)-1))
7564 msg = nta_msg_create(agent, 0), cleanup = 1;
7565
7566 if (msg && agent) {
7567 ta_list ta;
7568 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
7569 if (sip_add_tl(msg, sip_object(msg), ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) >= 0)
7570 orq = outgoing_create(agent, callback, magic, route_url, NULL((void*)0), msg,
7571 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
7572 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
7573 }
7574
7575 if (!orq && cleanup)
7576 msg_destroy(msg);
7577
7578 return orq;
7579}
7580
7581/** Cancel the request. */
7582int nta_outgoing_cancel(nta_outgoing_t *orq)
7583{
7584 nta_outgoing_t *cancel =
7585 nta_outgoing_tcancel(orq, NULL((void*)0), NULL((void*)0), TAG_NULL()(tag_type_t)0, (tag_value_t)0);
7586
7587 return (cancel != NULL((void*)0)) - 1;
7588}
7589
7590/** Cancel the request.
7591 *
7592 * Initiate a cancel transaction for client transaction @a orq.
7593 *
7594 * @param orq client transaction to cancel
7595 * @param callback callback function (may be @c NULL)
7596 * @param magic application context pointer
7597 * @param tag, value, ... list of extra arguments
7598 *
7599 * @note The function may return @code (nta_outgoing_t *)-1 @endcode (NONE)
7600 * if callback is NULL.
7601 *
7602 * @TAGS
7603 * NTATAG_CANCEL_2534(), NTATAG_CANCEL_408() and all the tags that are
7604 * accepted by nta_outgoing_tcreate().
7605 *
7606 * If NTATAG_CANCEL_408(1) or NTATAG_CANCEL_2543(1) is given, the stack
7607 * generates a 487 response to the request internally. If
7608 * NTATAG_CANCEL_408(1) is given, no CANCEL request is actually sent.
7609 *
7610 * @note
7611 * nta_outgoing_tcancel() refuses to send a CANCEL request for non-INVITE
7612 * requests.
7613 */
7614nta_outgoing_t *nta_outgoing_tcancel(nta_outgoing_t *orq,
7615 nta_response_f *callback,
7616 nta_outgoing_magic_t *magic,
7617 tag_type_t tag, tag_value_t value, ...)
7618{
7619 msg_t *msg;
7620 int cancel_2543, cancel_408;
7621 ta_list ta;
7622 int delay_sending;
7623
7624 if (orq == NULL((void*)0) || orq == NONE((void *)-1))
7625 return NULL((void*)0);
7626
7627 if (orq->orq_destroyed) {
7628 SU_DEBUG_3(("%s: trying to cancel destroyed request\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 7628, "%s: trying to cancel destroyed request\n", __func__)
) : (void)0)
;
7629 return NULL((void*)0);
7630 }
7631 if (orq->orq_method != sip_method_invite) {
7632 SU_DEBUG_3(("%s: trying to cancel non-INVITE request\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 7632, "%s: trying to cancel non-INVITE request\n", __func__
)) : (void)0)
;
7633 return NULL((void*)0);
7634 }
7635
7636 if (orq->orq_forking)
7637 orq = orq->orq_forking;
7638
7639 if (orq->orq_status >= 200
7640 /* && orq->orq_method != sip_method_invite ... !multicast */) {
7641 SU_DEBUG_3(("%s: trying to cancel completed request\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 7641, "%s: trying to cancel completed request\n", __func__)
) : (void)0)
;
7642 return NULL((void*)0);
7643 }
7644 if (orq->orq_canceled) {
7645 SU_DEBUG_3(("%s: trying to cancel cancelled request\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 7645, "%s: trying to cancel cancelled request\n", __func__)
) : (void)0)
;
7646 return NULL((void*)0);
7647 }
7648 orq->orq_canceled = 1;
7649
7650#if HAVE_SOFIA_SRESOLV1
7651 if (!orq->orq_resolved) {
7652 outgoing_destroy_resolver(orq);
7653 outgoing_reply(orq, SIP_487_REQUEST_CANCELLED487, sip_487_Request_terminated, 1);
7654 return NULL((void*)0); /* XXX - Does anyone care about reply? */
7655 }
7656#endif
7657
7658 cancel_408 = 0; /* Don't really CANCEL, this is timeout. */
7659 cancel_2543 = orq->orq_agent->sa_cancel_2543;
7660 /* CANCEL may be sent only after a provisional response has been received. */
7661 delay_sending = orq->orq_status < 100;
7662
7663 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
7664
7665 tl_gets(ta_args(ta)(ta).tl,
7666 NTATAG_CANCEL_408_REF(cancel_408)ntatag_cancel_408_ref, tag_bool_vr(&(cancel_408)),
7667 NTATAG_CANCEL_2543_REF(cancel_2543)ntatag_cancel_2543_ref, tag_bool_vr(&(cancel_2543)),
7668 TAG_END()(tag_type_t)0, (tag_value_t)0);
7669
7670 if (!cancel_408)
7671 msg = outgoing_ackmsg(orq, SIP_METHOD_CANCELsip_method_cancel, "CANCEL", ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
7672 else
7673 msg = NULL((void*)0);
7674
7675 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
7676
7677 if ((cancel_2543 || cancel_408) && !orq->orq_stateless)
7678 outgoing_reply(orq, SIP_487_REQUEST_CANCELLED487, sip_487_Request_terminated, 1);
7679
7680 if (msg) {
7681 nta_outgoing_t *cancel;
7682 if (cancel_2543) /* Follow RFC 2543 semantics for CANCEL */
7683 delay_sending = 0;
7684
7685 cancel = outgoing_create(orq->orq_agent, callback, magic,
7686 NULL((void*)0), orq->orq_tpn, msg,
7687 NTATAG_BRANCH_KEY(orq->orq_branch)ntatag_branch_key, tag_str_v((orq->orq_branch)),
7688 NTATAG_DELAY_SENDING(delay_sending)ntatag_delay_sending, tag_bool_v((delay_sending)),
7689 NTATAG_USER_VIA(1)ntatag_user_via, tag_bool_v((1)),
7690 TAG_END()(tag_type_t)0, (tag_value_t)0);
7691
7692 if (delay_sending)
7693 orq->orq_cancel = cancel;
7694
7695 if (cancel) {
7696 if (!delay_sending)
7697 outgoing_complete(orq);
7698 return cancel;
7699 }
7700
7701 msg_destroy(msg);
7702 }
7703
7704 return NULL((void*)0);
7705}
7706
7707/**Bind callback and application context to a client transaction.
7708 *
7709 * @param orq outgoing client transaction
7710 * @param callback callback function (may be NULL)
7711 * @param magic application context pointer
7712 * (given as argument to @a callback)
7713 *
7714 * @NEW_1_12_9
7715 */
7716int
7717nta_outgoing_bind(nta_outgoing_t *orq,
7718 nta_response_f *callback,
7719 nta_outgoing_magic_t *magic)
7720{
7721 if (orq && !orq->orq_destroyed) {
7722 if (callback == NULL((void*)0))
7723 callback = outgoing_default_cb;
7724 orq->orq_callback = callback;
7725 orq->orq_magic = magic;
7726 return 0;
7727 }
7728 return -1;
7729}
7730
7731/**Get application context bound to a client transaction.
7732 *
7733 * @param orq outgoing client transaction
7734 * @param callback callback function (may be NULL)
7735 *
7736 * Return the application context bound to a client transaction. If the @a
7737 * callback function pointer is given, return application context only if
7738 * the callback matches with the callback bound to the client transaction.
7739 *
7740 * @NEW_1_12_11
7741 */
7742nta_outgoing_magic_t *
7743nta_outgoing_magic(nta_outgoing_t const *orq,
7744 nta_response_f *callback)
7745{
7746 if (orq && (callback == NULL((void*)0) || callback == orq->orq_callback))
7747 return orq->orq_magic;
7748 else
7749 return NULL((void*)0);
7750}
7751
7752
7753/**
7754 * Destroy a request object.
7755 *
7756 * @note
7757 * This function does not actually free the object, but marks it as
7758 * disposable. The object is freed after a timeout.
7759 */
7760void nta_outgoing_destroy(nta_outgoing_t *orq)
7761{
7762 if (orq == NULL((void*)0) || orq == NONE((void *)-1))
7763 return;
7764
7765 if (orq->orq_destroyed) {
7766 SU_DEBUG_1(("%s(%p): %s\n", "nta_outgoing_destroy", (void *)orq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 7767, "%s(%p): %s\n", "nta_outgoing_destroy", (void *)orq, "already destroyed"
)) : (void)0)
7767 "already destroyed"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 7767, "%s(%p): %s\n", "nta_outgoing_destroy", (void *)orq, "already destroyed"
)) : (void)0)
;
7768 return;
7769 }
7770
7771 outgoing_destroy(orq);
7772}
7773
7774/** Return the request URI */
7775url_t const *nta_outgoing_request_uri(nta_outgoing_t const *orq)
7776{
7777 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_url : NULL((void*)0);
7778}
7779
7780/** Return the URI used to route the request */
7781url_t const *nta_outgoing_route_uri(nta_outgoing_t const *orq)
7782{
7783 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_route : NULL((void*)0);
7784}
7785
7786/** Return method of the client transaction */
7787sip_method_t nta_outgoing_method(nta_outgoing_t const *orq)
7788{
7789 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_method : sip_method_invalid;
7790}
7791
7792/** Return method name of the client transaction */
7793char const *nta_outgoing_method_name(nta_outgoing_t const *orq)
7794{
7795 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_method_name : NULL((void*)0);
7796}
7797
7798/** Get sequence number of a client transaction.
7799 */
7800uint32_t nta_outgoing_cseq(nta_outgoing_t const *orq)
7801{
7802 return orq != NULL((void*)0) && orq != NONE((void *)-1) && orq->orq_cseq
7803 ? orq->orq_cseq->cs_seq : 0;
7804}
7805
7806/**
7807 * Get the status code of a client transaction.
7808 */
7809int nta_outgoing_status(nta_outgoing_t const *orq)
7810{
7811 /* Return 500 Internal server error for invalid handles. */
7812 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_status : 500;
7813}
7814
7815/** Get the RTT delay measured using @Timestamp header. */
7816unsigned nta_outgoing_delay(nta_outgoing_t const *orq)
7817{
7818 return orq != NULL((void*)0) && orq != NONE((void *)-1) ? orq->orq_delay : UINT_MAX(2147483647 *2U +1U);
7819}
7820
7821/** Get the branch parameter. @NEW_1_12_7. */
7822char const *nta_outgoing_branch(nta_outgoing_t const *orq)
7823{
7824 return orq != NULL((void*)0) && orq != NONE((void *)-1) && orq->orq_branch
7825 ? orq->orq_branch + strlen("branch=")
7826 : NULL((void*)0);
7827}
7828
7829/**Get reference to response message.
7830 *
7831 * Retrieve the latest incoming response message to the outgoing
7832 * transaction. Note that the message is not copied, but a new reference to
7833 * it is created instead.
7834 *
7835 * @param orq outgoing transaction handle
7836 *
7837 * @retval
7838 * A pointer to response message is returned, or NULL if no response message
7839 * has been received.
7840 */
7841msg_t *nta_outgoing_getresponse(nta_outgoing_t *orq)
7842{
7843 if (orq != NULL((void*)0) && orq != NONE((void *)-1))
7844 return msg_ref_create(orq->orq_response);
7845 else
7846 return NULL((void*)0);
7847}
7848
7849/**Get request message.
7850 *
7851 * Retrieves the request message sent to the network. Note that the request
7852 * message is @b not copied, but a new reference to it is created.
7853 *
7854 * @retval
7855 * A pointer to the request message is returned, or NULL if an error
7856 * occurred.
7857 */
7858msg_t *nta_outgoing_getrequest(nta_outgoing_t *orq)
7859{
7860 if (orq != NULL((void*)0) && orq != NONE((void *)-1))
7861 return msg_ref_create(orq->orq_request);
7862 else
7863 return NULL((void*)0);
7864}
7865
7866/**Create an outgoing request.
7867 *
7868 * Create an outgoing transaction object and send the request to the
7869 * network. The request is sent to the @a route_url (if non-NULL), default
7870 * proxy (if defined by NTATAG_DEFAULT_PROXY()), or to the address specified
7871 * by @a sip->sip_request->rq_url.
7872 *
7873 * When NTA receives response to the request, it invokes the @a callback
7874 * function.
7875 *
7876 * @param agent nta agent object
7877 * @param callback callback function (may be @c NULL)
7878 * @param magic application context pointer
7879 * @param route_url optional URL used to route transaction requests
7880 * @param msg request message
7881 * @param tpn (optional) transport name
7882 * @param msg request message to
7883 * @param tag, value, ... tagged arguments
7884 *
7885 * @return
7886 * Returns a pointer to newly created outgoing transaction object if
7887 * successful, and NULL otherwise.
7888 *
7889 * @note If NTATAG_STATELESS(1) tag is given and the @a callback is NULL,
7890 * the transaction object is marked as destroyed from the beginning. In that
7891 * case, the function may return @code (nta_outgoing_t *)-1 @endcode if the
7892 * transaction is freed before returning from the function.
7893 *
7894 * @TAG NTATAG_TPORT must point to an existing transport object for
7895 * 'agent' (the passed tport is otherwise ignored).
7896 *
7897 * @sa
7898 * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
7899 */
7900nta_outgoing_t *outgoing_create(nta_agent_t *agent,
7901 nta_response_f *callback,
7902 nta_outgoing_magic_t *magic,
7903 url_string_t const *route_url,
7904 tp_name_t const *tpn,
7905 msg_t *msg,
7906 tag_type_t tag, tag_value_t value, ...)
7907{
7908 nta_outgoing_t *orq;
7909 sip_t *sip;
7910 su_home_t *home;
7911 char const *comp = NONE((void *)-1);
7912 char const *branch = NONE((void *)-1);
7913 char const *ack_branch = NONE((void *)-1);
7914 char const *tp_ident;
7915 int delay_sending = 0, sigcomp_zap = 0;
7916 int pass_100 = agent->sa_pass_100, use_timestamp = agent->sa_timestamp;
7917 enum nta_res_order_e res_order = agent->sa_res_order;
7918 struct sigcomp_compartment *cc = NULL((void*)0);
7919 ta_list ta;
7920 char const *scheme = NULL((void*)0);
7921 char const *port = NULL((void*)0);
7922 int invalid, resolved = 0, stateless = 0, user_via = agent->sa_user_via;
7923 int invite_100rel = agent->sa_invite_100rel;
7924 int explicit_transport = 1;
7925 int call_tls_orq_connect_timeout_is_set = 0;
7926 int call_tls_orq_connect_timeout = 0;
7927
7928 tagi_t const *t;
7929 tport_t *override_tport = NULL((void*)0);
7930
7931 if (!agent->sa_tport_ip6)
7932 res_order = nta_res_ip4_only;
7933 else if (!agent->sa_tport_ip4)
7934 res_order = nta_res_ip6_only;
7935
7936 if (!callback)
7937 callback = outgoing_default_cb;
7938 if (!route_url)
7939 route_url = (url_string_t *)agent->sa_default_proxy;
7940
7941 sip = sip_object(msg);
7942 home = msg_home(msg)((su_home_t*)(msg));
7943
7944#ifdef HAVE_ZLIB_COMPRESS1
7945 sip_content_encoding_Xflate(msg, sip_object(msg), 0, 1);
7946#endif
7947
7948 if (!sip->sip_request || sip_complete_message(msg) < 0) {
7949 SU_DEBUG_3(("nta: outgoing_create: incomplete request\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 7949, "nta: outgoing_create: incomplete request\n" "%s", ""
)) : (void)0)
;
7950 return NULL((void*)0);
7951 }
7952
7953 if (!route_url && !tpn && sip->sip_route &&
7954 sip->sip_route->r_url->url_params &&
7955 url_param(sip->sip_route->r_url->url_params, "lr", NULL((void*)0), 0))
7956 route_url = (url_string_t *)sip->sip_route->r_url;
7957
7958 if (!(orq = su_zalloc(agent->sa_home, sizeof(*orq))))
7959 return NULL((void*)0);
7960
7961 tp_ident = tpn ? tpn->tpn_ident : NULL((void*)0);
7962
7963 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
7964
7965 /* tl_gets() is a bit too slow here... */
7966 for (t = ta_args(ta)(ta).tl; t; t = tl_next(t)) {
7967 tag_type_t tt = t->t_tag;
7968
7969 if (ntatag_stateless == tt)
7970 stateless = t->t_value != 0;
7971 else if (ntatag_delay_sending == tt)
7972 delay_sending = t->t_value != 0;
7973 else if (ntatag_branch_key == tt)
7974 branch = (void *)t->t_value;
7975 else if (ntatag_pass_100 == tt)
7976 pass_100 = t->t_value != 0;
7977 else if (ntatag_use_timestamp == tt)
7978 use_timestamp = t->t_value != 0;
7979 else if (ntatag_user_via == tt)
7980 user_via = t->t_value != 0;
7981 else if (ntatag_ack_branch == tt)
7982 ack_branch = (void *)t->t_value;
7983 else if (ntatag_default_proxy == tt)
7984 route_url = (void *)t->t_value;
7985 else if (tptag_ident == tt)
7986 tp_ident = (void *)t->t_value;
7987 else if (ntatag_comp == tt)
7988 comp = (char const *)t->t_value;
7989 else if (ntatag_sigcomp_close == tt)
7990 sigcomp_zap = t->t_value != 0;
7991 else if (tptag_compartment == tt)
7992 cc = (void *)t->t_value;
7993 else if (ntatag_tport == tt) {
7994 override_tport = (tport_t *)t->t_value;
7995 }
7996 else if (ntatag_rel100 == tt) {
7997 invite_100rel = t->t_value != 0;
7998 }
7999 else if (ntatag_tls_orq_connect_timeout == tt) {
8000 call_tls_orq_connect_timeout_is_set = 1;
8001 call_tls_orq_connect_timeout = t->t_value;
8002 if (call_tls_orq_connect_timeout > NTA_TIME_MAX) call_tls_orq_connect_timeout = NTA_TIME_MAX;
8003 }
8004 }
8005
8006 orq->orq_agent = agent;
8007 orq->orq_callback = callback;
8008 orq->orq_magic = magic;
8009 orq->orq_method = sip->sip_request->rq_method;
8010 orq->orq_method_name = sip->sip_request->rq_method_name;
8011 orq->orq_cseq = sip->sip_cseq;
8012 orq->orq_to = sip->sip_to;
8013 orq->orq_from = sip->sip_from;
8014 orq->orq_call_id = sip->sip_call_id;
8015 orq->orq_tags = tl_afilter(home, tport_tags, ta_args(ta)(ta).tl);
8016 orq->orq_delayed = delay_sending != 0;
8017 orq->orq_pass_100 = pass_100 != 0;
8018 orq->orq_sigcomp_zap = sigcomp_zap;
8019 orq->orq_sigcomp_new = comp != NONE((void *)-1) && comp != NULL((void*)0);
8020 orq->orq_timestamp = use_timestamp;
8021 orq->orq_delay = UINT_MAX(2147483647 *2U +1U);
8022 orq->orq_stateless = stateless != 0;
8023 orq->orq_user_via = user_via != 0 && sip->sip_via;
8024 orq->orq_100rel = invite_100rel;
8025 orq->orq_uas = !stateless && agent->sa_is_a_uas;
8026 orq->orq_call_tls_connect_timeout_is_set = call_tls_orq_connect_timeout_is_set;
8027 orq->orq_call_tls_connect_timeout = (call_tls_orq_connect_timeout > 0) ? call_tls_orq_connect_timeout : 0;
8028
8029 if (cc)
8030 orq->orq_cc = nta_compartment_ref(cc);
8031
8032 /* Add supported features */
8033 outgoing_features(agent, orq, msg, sip, ta_args(ta)(ta).tl);
8034
8035 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
8036
8037 /* select the tport to use for the outgoing message */
8038 if (override_tport) {
8039 /* note: no ref taken to the tport as its only used once here */
8040 if (tport_is_secondary(override_tport)) {
8041 tpn = tport_name(override_tport);
8042 orq->orq_user_tport = 1;
8043 }
8044 }
8045
8046 if (tpn) {
8047 /* CANCEL or ACK to [3456]XX */
8048 invalid = tport_name_dup(home, orq->orq_tpn, tpn);
8049#if 0 //HAVE_SOFIA_SRESOLV
8050 /* We send ACK or CANCEL only if original request was really sent */
8051 assert(tport_name_is_resolved(orq->orq_tpn))((void) sizeof ((tport_name_is_resolved(orq->orq_tpn)) ? 1
: 0), __extension__ ({ if (tport_name_is_resolved(orq->orq_tpn
)) ; else __assert_fail ("tport_name_is_resolved(orq->orq_tpn)"
, "nta.c", 8051, __extension__ __PRETTY_FUNCTION__); }))
;
8052#endif
8053 resolved = tport_name_is_resolved(orq->orq_tpn);
8054 orq->orq_url = url_hdup(home, sip->sip_request->rq_url);
8055 }
8056 else if (route_url && !orq->orq_user_tport) {
8057 invalid = nta_tpn_by_url(home, orq->orq_tpn, &scheme, &port, route_url);
8058 if (invalid >= 0) {
8059 explicit_transport = invalid > 0;
8060 if (override_tport) { /* Use transport protocol name from transport */
8061 if (strcmp(orq->orq_tpn->tpn_proto, "*") == 0)
8062 orq->orq_tpn->tpn_proto = tport_name(override_tport)->tpn_proto;
8063 }
8064
8065 resolved = tport_name_is_resolved(orq->orq_tpn);
8066 orq->orq_url = url_hdup(home, sip->sip_request->rq_url);
8067 if (route_url != (url_string_t *)agent->sa_default_proxy)
8068 orq->orq_route = url_hdup(home, route_url->us_url);
8069 }
8070 }
8071 else {
8072 invalid = nta_tpn_by_url(home, orq->orq_tpn, &scheme, &port,
8073 (url_string_t *)sip->sip_request->rq_url);
8074 if (invalid >= 0) {
8075 explicit_transport = invalid > 0;
8076 resolved = tport_name_is_resolved(orq->orq_tpn);
8077 sip_fragment_clear(sip->sip_request->rq_common)((sip->sip_request->rq_common)->h_data = ((void*)0),
(sip->sip_request->rq_common)->h_len = 0)
;
8078 }
8079 orq->orq_url = url_hdup(home, sip->sip_request->rq_url);
8080 }
8081
8082 if (!override_tport)
8083 orq->orq_tpn->tpn_ident = tp_ident;
8084 else
8085 orq->orq_tpn->tpn_ident = tport_name(override_tport)->tpn_ident;
8086
8087 if (comp == NULL((void*)0))
8088 orq->orq_tpn->tpn_comp = comp;
8089
8090 if (orq->orq_user_via && su_strmatch(orq->orq_tpn->tpn_proto, "*")) {
8091 char const *proto = sip_via_transport(sip->sip_via);
8092 if (proto) orq->orq_tpn->tpn_proto = proto;
8093 }
8094
8095 if (branch && branch != NONE((void *)-1)) {
8096 if (su_casenmatch(branch, "branch=", 7))
8097 branch = su_strdup(home, branch);
8098 else
8099 branch = su_sprintf(home, "branch=%s", branch);
8100 }
8101 else if (orq->orq_user_via && sip->sip_via->v_branch && orq->orq_method != sip_method_invite )
8102 branch = su_sprintf(home, "branch=%s", sip->sip_via->v_branch);
8103 else if (stateless)
8104 branch = stateless_branch(agent, msg, sip, orq->orq_tpn);
8105 else
8106 branch = stateful_branch(home, agent);
8107
8108 orq->orq_branch = branch;
8109 orq->orq_via_branch = branch;
8110
8111 if (orq->orq_method == sip_method_ack) {
8112 /* Find the original INVITE which we are ACKing */
8113 if (ack_branch != NULL((void*)0) && ack_branch != NONE((void *)-1)) {
8114 if (su_casenmatch(ack_branch, "branch=", 7))
8115 orq->orq_branch = su_strdup(home, ack_branch);
8116 else
8117 orq->orq_branch = su_sprintf(home, "branch=%s", ack_branch);
8118 }
8119 else if (orq->orq_uas) {
8120 /*
8121 * ACK redirects further 2XX messages to it.
8122 *
8123 * Use orq_branch from INVITE, but put a different branch in topmost Via.
8124 */
8125 nta_outgoing_t *invite = outgoing_find(agent, msg, sip, NULL((void*)0));
8126
8127 if (invite) {
8128 sip_t const *inv = sip_object(invite->orq_request);
8129
8130 orq->orq_branch = su_strdup(home, invite->orq_branch);
8131
8132 /* @RFC3261 section 13.2.2.4 -
8133 * The ACK MUST contain the same credentials as the INVITE.
8134 */
8135 if (!sip->sip_proxy_authorization && !sip->sip_authorization) {
8136 if (inv->sip_proxy_authorization)
8137 sip_add_dup(msg, sip, (void *)inv->sip_proxy_authorization);
8138 if (inv->sip_authorization)
8139 sip_add_dup(msg, sip, (void *)inv->sip_authorization);
8140 }
8141 }
8142 else {
8143 SU_DEBUG_1(("outgoing_create: ACK without INVITE\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 8143, "outgoing_create: ACK without INVITE\n" "%s", "")) : (
void)0)
;
8144 assert(!"INVITE found for ACK")((void) sizeof ((!"INVITE found for ACK") ? 1 : 0), __extension__
({ if (!"INVITE found for ACK") ; else __assert_fail ("!\"INVITE found for ACK\""
, "nta.c", 8144, __extension__ __PRETTY_FUNCTION__); }))
;
8145 }
8146 }
8147 }
8148
8149#if HAVE_SOFIA_SRESOLV1
8150 if (!resolved)
8151 orq->orq_tpn->tpn_port = port;
8152 orq->orq_resolved = resolved;
8153#else
8154 orq->orq_resolved = resolved = 1;
8155#endif
8156 orq->orq_sips = su_casematch(scheme, "sips");
8157
8158 if (invalid < 0 || !orq->orq_branch || msg_serialize(msg, (void *)sip) < 0) {
8159 SU_DEBUG_3(("nta outgoing create: %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8161, "nta outgoing create: %s\n", invalid < 0 ? "invalid URI"
: !orq->orq_branch ? "no branch" : "invalid message")) : (
void)0)
8160 invalid < 0 ? "invalid URI" :(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8161, "nta outgoing create: %s\n", invalid < 0 ? "invalid URI"
: !orq->orq_branch ? "no branch" : "invalid message")) : (
void)0)
8161 !orq->orq_branch ? "no branch" : "invalid message"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8161, "nta outgoing create: %s\n", invalid < 0 ? "invalid URI"
: !orq->orq_branch ? "no branch" : "invalid message")) : (
void)0)
;
8162 outgoing_free(orq);
8163 return NULL((void*)0);
8164 }
8165
8166 /* Now we are committed in sending the transaction */
8167 orq->orq_request = msg;
8168 agent->sa_stats->as_client_tr++;
8169 orq->orq_hash = NTA_HASH(sip->sip_call_id, sip->sip_cseq->cs_seq)((sip->sip_call_id)->i_hash + 26839U * (uint32_t)(sip->
sip_cseq->cs_seq))
;
8170
8171 if (orq->orq_user_tport)
8172 outgoing_send_via(orq, override_tport);
8173 else if (resolved)
8174 outgoing_prepare_send(orq);
8175#if HAVE_SOFIA_SRESOLV1
8176 else
8177 outgoing_resolve(orq, explicit_transport, res_order);
8178#endif
8179
8180 if (stateless &&
8181 orq->orq_status >= 200 &&
8182 callback == outgoing_default_cb) {
8183 void *retval;
8184
8185 if (orq->orq_status < 300)
8186 retval = (void *)-1; /* NONE */
8187 else
8188 retval = NULL((void*)0), orq->orq_request = NULL((void*)0);
8189
8190 outgoing_free(orq);
8191
8192 return retval;
8193 }
8194
8195 assert(orq->orq_queue)((void) sizeof ((orq->orq_queue) ? 1 : 0), __extension__ (
{ if (orq->orq_queue) ; else __assert_fail ("orq->orq_queue"
, "nta.c", 8195, __extension__ __PRETTY_FUNCTION__); }))
;
8196
8197 outgoing_insert(agent, orq);
8198
8199 return orq;
8200}
8201
8202/** Prepare sending a request */
8203static void
8204outgoing_prepare_send(nta_outgoing_t *orq)
8205{
8206 nta_agent_t *sa = orq->orq_agent;
8207 tport_t *tp;
8208 tp_name_t *tpn = orq->orq_tpn;
8209
8210 /* Select transport by scheme */
8211 if (orq->orq_sips && strcmp(tpn->tpn_proto, "*") == 0)
8212 tpn->tpn_proto = "tls";
8213
8214 if (!tpn->tpn_port)
8215 tpn->tpn_port = "";
8216
8217 tp = tport_by_name(sa->sa_tports, tpn);
8218
8219 if (tpn->tpn_port[0] == '\0') {
8220 if (orq->orq_sips || tport_has_tls(tp))
8221 tpn->tpn_port = "5061";
8222 else
8223 tpn->tpn_port = "5060";
8224 }
8225
8226 if (tp) {
8227 outgoing_send_via(orq, tp);
8228 }
8229 else if (orq->orq_sips) {
8230 SU_DEBUG_3(("nta outgoing create: no secure transport\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8230, "nta outgoing create: no secure transport\n" "%s", ""
)) : (void)0)
;
8231 outgoing_reply(orq, SIP_416_UNSUPPORTED_URI416, sip_416_Unsupported_uri, 1);
8232 }
8233 else {
8234 SU_DEBUG_3(("nta outgoing create: no transport protocol\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8234, "nta outgoing create: no transport protocol\n" "%s", ""
)) : (void)0)
;
8235 outgoing_reply(orq, 503, "No transport", 1);
8236 }
8237}
8238
8239/** Send request using given transport */
8240static void
8241outgoing_send_via(nta_outgoing_t *orq, tport_t *tp)
8242{
8243 tport_t *old_tp = orq->orq_tport;
8244
8245 orq->orq_tport = tport_ref(tp);
8246
8247 if (orq->orq_pending && tp != old_tp) {
8248 tport_release(old_tp, orq->orq_pending,
8249 orq->orq_request, NULL((void*)0), orq, 0);
8250 orq->orq_pending = 0;
8251 }
8252
8253 if (old_tp) tport_unref(old_tp);
8254
8255 if (outgoing_insert_via(orq, agent_tport_via(tp)) < 0) {
8256 SU_DEBUG_3(("nta outgoing create: cannot insert Via line\n" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 8256, "nta outgoing create: cannot insert Via line\n" "%s",
"")) : (void)0)
;
8257 outgoing_reply(orq, 503, "Cannot insert Via", 1);
8258 return;
8259 }
8260
8261#if HAVE_SOFIA_SMIME0
8262 {
8263 sm_object_t *smime = sa->sa_smime;
8264 sip_t *sip = sip_object(orq->orq_request);
8265
8266 if (sa->sa_smime &&
8267 (sip->sip_request->rq_method == sip_method_invite ||
8268 sip->sip_request->rq_method == sip_method_message)) {
8269 msg_prepare(orq->orq_request);
8270 if (sm_encode_message(smime, msg, sip, SM_ID_NULL) < 0) {
8271 outgoing_tport_error(sa, orq, NULL((void*)0),
8272 orq->orq_request, su_errno());
8273 return;
8274 }
8275 }
8276 }
8277#endif
8278
8279 orq->orq_prepared = 1;
8280
8281 if (orq->orq_delayed) {
8282 SU_DEBUG_5(("nta: delayed sending %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8283, "nta: delayed sending %s (%u)\n", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
8283 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8283, "nta: delayed sending %s (%u)\n", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
;
8284 outgoing_queue(orq->orq_agent->sa_out.delayed, orq);
8285 return;
8286 }
8287
8288 outgoing_send(orq, 0);
8289}
8290
8291
8292/** Send a request */
8293static void
8294outgoing_send(nta_outgoing_t *orq, int retransmit)
8295{
8296 int err;
8297 tp_name_t const *tpn = orq->orq_tpn;
8298 msg_t *msg = orq->orq_request;
8299 nta_agent_t *agent = orq->orq_agent;
8300 tport_t *tp;
8301 int once = 0;
8302 su_time_t now = su_now();
8303 tag_type_t tag = tag_skip;
8304 tag_value_t value = 0;
8305 struct sigcomp_compartment *cc; cc = NULL((void*)0);
8306
8307 /* tport can be NULL if we are just switching network */
8308 if (orq->orq_tport == NULL((void*)0)) {
8309 outgoing_tport_error(agent, orq, NULL((void*)0), orq->orq_request, ENETRESET102);
8310 return;
8311 }
8312
8313 if (orq->orq_user_tport && !tport_is_clear_to_send(orq->orq_tport)) {
8314 outgoing_tport_error(agent, orq, NULL((void*)0), orq->orq_request, EPIPE32);
8315 return;
8316 }
8317
8318 if (!retransmit)
8319 orq->orq_sent = now;
8320
8321 if (orq->orq_timestamp) {
8322 sip_t *sip = sip_object(msg);
8323 sip_timestamp_t *ts =
8324 sip_timestamp_format(msg_home(msg)((su_home_t*)(msg)), "%lu.%06lu",
8325 now.tv_sec, now.tv_usec);
8326
8327 if (ts) {
8328 if (sip->sip_timestamp)
8329 msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)sip->sip_timestamp);
8330 msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)ts);
8331 }
8332 }
8333
8334 for (;;) {
8335 if (tpn->tpn_comp == NULL((void*)0)) {
8336 /* xyzzy */
8337 }
8338 else if (orq->orq_cc) {
8339 cc = orq->orq_cc, orq->orq_cc = NULL((void*)0);
8340 }
8341 else {
8342 cc = agent_compression_compartment(agent, orq->orq_tport, tpn,
8343 orq->orq_sigcomp_new);
8344 }
8345
8346 if (orq->orq_try_udp_instead)
8347 tag = tptag_mtu, value = 65535;
8348
8349 if (orq->orq_pending) {
8350 tport_release(orq->orq_tport, orq->orq_pending,
8351 orq->orq_request, NULL((void*)0), orq, 0);
8352 orq->orq_pending = 0;
8353 }
8354
8355 tp = tport_tsend(orq->orq_tport, msg, tpn,
8356 tag, value,
8357 IF_SIGCOMP_TPTAG_COMPARTMENT(cc)!(cc && cc != ((void *)-1)) ? tag_skip : tptag_compartment
, tag_ptr_v((cc)),
8358 TAG_NEXT(orq->orq_tags)tag_next, (tag_value_t)(orq->orq_tags));
8359 if (tp)
8360 break;
8361
8362 err = msg_errno(orq->orq_request);
8363
8364 if (cc)
8365 nta_compartment_decref(&cc);
8366
8367 if (orq->orq_user_tport)
8368 /* No retries */;
8369 /* RFC3261, 18.1.1 */
8370 else if (err == EMSGSIZE90 && !orq->orq_try_tcp_instead) {
8371 if (su_casematch(tpn->tpn_proto, "udp") ||
8372 su_casematch(tpn->tpn_proto, "*")) {
8373 outgoing_try_tcp_instead(orq);
8374 continue;
8375 }
8376 }
8377 else if (err == ECONNREFUSED111 && orq->orq_try_tcp_instead) {
8378 if (su_casematch(tpn->tpn_proto, "tcp") && msg_size(msg) <= 65535) {
8379 outgoing_try_udp_instead(orq, 0);
8380 continue;
8381 }
8382 }
8383 else if (err == EPIPE32) {
8384 /* Connection was closed */
8385 if (!once++) {
8386 orq->orq_retries++;
8387 continue;
8388 }
8389 }
8390
8391 outgoing_tport_error(agent, orq, NULL((void*)0), orq->orq_request, err);
8392
8393 return;
8394 }
8395
8396 agent->sa_stats->as_sent_msg++;
8397 agent->sa_stats->as_sent_request++;
8398 if (retransmit)
8399 agent->sa_stats->as_retry_request++;
8400
8401 SU_DEBUG_5(("nta: %ssent %s (%u) to " TPN_FORMAT "\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8404, "nta: %ssent %s (%u) to " "%s/%s:%s%s%s%s%s" "\n", retransmit
? "re" : "", orq->orq_method_name, orq->orq_cseq->cs_seq
, (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
8402 retransmit ? "re" : "",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8404, "nta: %ssent %s (%u) to " "%s/%s:%s%s%s%s%s" "\n", retransmit
? "re" : "", orq->orq_method_name, orq->orq_cseq->cs_seq
, (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
8403 orq->orq_method_name, orq->orq_cseq->cs_seq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8404, "nta: %ssent %s (%u) to " "%s/%s:%s%s%s%s%s" "\n", retransmit
? "re" : "", orq->orq_method_name, orq->orq_cseq->cs_seq
, (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
8404 TPN_ARGS(tpn)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8404, "nta: %ssent %s (%u) to " "%s/%s:%s%s%s%s%s" "\n", retransmit
? "re" : "", orq->orq_method_name, orq->orq_cseq->cs_seq
, (tpn)->tpn_proto, (tpn)->tpn_host, (tpn)->tpn_port
, (tpn)->tpn_comp ? ";comp=" : "", (tpn)->tpn_comp ? (tpn
)->tpn_comp : "", (tpn)->tpn_ident ? "/" : "", (tpn)->
tpn_ident ? (tpn)->tpn_ident : "")) : (void)0)
;
8405
8406 if (cc) {
8407 if (orq->orq_cc)
8408 nta_compartment_decref(&orq->orq_cc);
8409 }
8410
8411 if (orq->orq_pending) {
8412 assert(orq->orq_tport)((void) sizeof ((orq->orq_tport) ? 1 : 0), __extension__ (
{ if (orq->orq_tport) ; else __assert_fail ("orq->orq_tport"
, "nta.c", 8412, __extension__ __PRETTY_FUNCTION__); }))
;
8413 tport_release(orq->orq_tport, orq->orq_pending,
8414 orq->orq_request, NULL((void*)0), orq, 0);
8415 orq->orq_pending = 0;
8416 }
8417
8418 if (orq->orq_stateless) {
8419 outgoing_reply(orq, 202, NULL((void*)0), 202);
8420 return;
8421 }
8422
8423 if (orq->orq_method != sip_method_ack) {
8424 orq->orq_pending = tport_pend(tp, orq->orq_request,
8425 outgoing_tport_error, orq);
8426 if (orq->orq_pending < 0)
8427 orq->orq_pending = 0;
8428 }
8429
8430 if (tp != orq->orq_tport) {
8431 tport_decref(&orq->orq_tport);
8432 orq->orq_tport = tport_ref(tp);
8433 }
8434
8435 orq->orq_reliable = tport_is_reliable(tp);
8436
8437 if (retransmit)
8438 return;
8439
8440 outgoing_trying(orq); /* Timer B / F */
8441
8442 if (orq->orq_method == sip_method_ack)
8443 ;
8444 else if (!orq->orq_reliable) {
8445 /* race condition on initial t1 timer timeout, set minimum initial timeout to 1000ms */
8446 unsigned t1_timer = agent->sa_t1;
8447 if (t1_timer < 1000) t1_timer = 1000;
8448 outgoing_set_timer(orq, t1_timer); /* Timer A/E */
8449 } else if (orq->orq_try_tcp_instead && !tport_is_connected(tp)) {
8450 outgoing_set_timer(orq, agent->sa_t4); /* Timer N3 */
8451 } else if (su_casenmatch(orq->orq_tpn->tpn_proto, "tls", 3) && !tport_is_connected(tp)) {
8452 unsigned tls_reconect_interval = (orq->orq_call_tls_connect_timeout_is_set) ?
8453 orq->orq_call_tls_connect_timeout : agent->sa_tls_orq_connect_timeout;
8454 if (tls_reconect_interval) {
8455 if (tls_reconect_interval < 1000) tls_reconect_interval = 1000;
8456 outgoing_set_timer(orq, tls_reconect_interval); /* Timer N3 set to (min 1000 ms if set) */
8457 }
8458 }
8459}
8460
8461static void
8462outgoing_try_tcp_instead(nta_outgoing_t *orq)
8463{
8464 tport_t *tp;
8465 tp_name_t tpn[1];
8466
8467 assert(orq->orq_pending == 0)((void) sizeof ((orq->orq_pending == 0) ? 1 : 0), __extension__
({ if (orq->orq_pending == 0) ; else __assert_fail ("orq->orq_pending == 0"
, "nta.c", 8467, __extension__ __PRETTY_FUNCTION__); }))
;
8468
8469 *tpn = *orq->orq_tpn;
8470 tpn->tpn_proto = "tcp";
8471 orq->orq_try_tcp_instead = 1;
8472
8473 tp = tport_by_name(orq->orq_agent->sa_tports, tpn);
8474 if (tp && tp != orq->orq_tport) {
8475 sip_t *sip = sip_object(orq->orq_request);
8476 sip_fragment_clear(sip->sip_via->v_common)((sip->sip_via->v_common)->h_data = ((void*)0), (sip
->sip_via->v_common)->h_len = 0)
;
8477 sip->sip_via->v_protocol = sip_transport_tcp;
8478
8479 SU_DEBUG_5(("nta: %s (%u) too large for UDP, trying TCP\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8480, "nta: %s (%u) too large for UDP, trying TCP\n", orq->
orq_method_name, orq->orq_cseq->cs_seq)) : (void)0)
8480 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8480, "nta: %s (%u) too large for UDP, trying TCP\n", orq->
orq_method_name, orq->orq_cseq->cs_seq)) : (void)0)
;
8481
8482 orq->orq_tpn->tpn_proto = "tcp";
8483 tport_decref(&orq->orq_tport);
8484 orq->orq_tport = tport_ref(tp);
8485
8486 return;
8487 }
8488
8489 /* No TCP - try again with UDP without SIP MTU limit */
8490 tpn->tpn_proto = "udp";
8491 orq->orq_try_udp_instead = 1;
8492
8493 tp = tport_by_name(orq->orq_agent->sa_tports, tpn);
8494 if (tp && tp != orq->orq_tport) {
8495 SU_DEBUG_5(("nta: %s (%u) exceed normal UDP size limit\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8496, "nta: %s (%u) exceed normal UDP size limit\n", orq->
orq_method_name, orq->orq_cseq->cs_seq)) : (void)0)
8496 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8496, "nta: %s (%u) exceed normal UDP size limit\n", orq->
orq_method_name, orq->orq_cseq->cs_seq)) : (void)0)
;
8497
8498 tport_decref(&orq->orq_tport);
8499 orq->orq_tport = tport_ref(tp);
8500 }
8501}
8502
8503static void
8504outgoing_try_udp_instead(nta_outgoing_t *orq, int timeout)
8505{
8506 tport_t *tp;
8507 tp_name_t tpn[1];
8508
8509 if (orq->orq_pending) {
8510 tport_release(orq->orq_tport, orq->orq_pending,
8511 orq->orq_request, NULL((void*)0), orq, 0);
8512 orq->orq_pending = 0;
8513 }
8514
8515 *tpn = *orq->orq_tpn;
8516 tpn->tpn_proto = "udp";
8517 orq->orq_try_udp_instead = 1;
8518
8519 tp = tport_by_name(orq->orq_agent->sa_tports, tpn);
8520 if (tp && tp != orq->orq_tport) {
8521 sip_t *sip = sip_object(orq->orq_request);
8522
8523 sip_fragment_clear(sip->sip_via->v_common)((sip->sip_via->v_common)->h_data = ((void*)0), (sip
->sip_via->v_common)->h_len = 0)
;
8524 sip->sip_via->v_protocol = sip_transport_udp;
8525
8526 SU_DEBUG_5(("nta: %s (%u) TCP %s, trying UDP\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8528, "nta: %s (%u) TCP %s, trying UDP\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, timeout ? "times out" : "refused"
)) : (void)0)
8527 orq->orq_method_name, orq->orq_cseq->cs_seq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8528, "nta: %s (%u) TCP %s, trying UDP\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, timeout ? "times out" : "refused"
)) : (void)0)
8528 timeout ? "times out" : "refused"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8528, "nta: %s (%u) TCP %s, trying UDP\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, timeout ? "times out" : "refused"
)) : (void)0)
;
8529
8530 orq->orq_tpn->tpn_proto = "udp";
8531 tport_decref(&orq->orq_tport);
8532 orq->orq_tport = tport_ref(tp);
8533 }
8534}
8535
8536
8537/** @internal Report transport errors. */
8538void
8539outgoing_tport_error(nta_agent_t *agent, nta_outgoing_t *orq,
8540 tport_t *tp, msg_t *msg, int error)
8541{
8542 tp_name_t const *tpn = tp ? tport_name(tp) : orq->orq_tpn;
8543
8544 if (orq->orq_pending) {
8545 assert(orq->orq_tport)((void) sizeof ((orq->orq_tport) ? 1 : 0), __extension__ (
{ if (orq->orq_tport) ; else __assert_fail ("orq->orq_tport"
, "nta.c", 8545, __extension__ __PRETTY_FUNCTION__); }))
;
8546 tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request,
8547 NULL((void*)0), orq, 0);
8548 orq->orq_pending = 0;
8549 }
8550
8551 if (error == EPIPE32 && orq->orq_retries++ == 0) {
8552 /* XXX - we should retry only if the transport is not newly created */
8553 outgoing_print_tport_error(orq, 5, "retrying once after ",
8554 tpn, msg, error);
8555 outgoing_send(orq, 1);
8556 return;
8557 }
8558 else if (error == ECONNREFUSED111 && orq->orq_try_tcp_instead) {
8559 /* RFC3261, 18.1.1 */
8560 if (su_casematch(tpn->tpn_proto, "tcp") && msg_size(msg) <= 65535) {
8561 outgoing_print_tport_error(orq, 5, "retrying with UDP after ",
8562 tpn, msg, error);
8563 outgoing_try_udp_instead(orq, 0);
8564 outgoing_remove(orq); /* Reset state - this is no resend! */
8565 outgoing_send(orq, 0); /* Send */
8566 return;
8567 }
8568 }
8569 else if (error == 0) {
8570 /*
8571 * Server closed connection. RFC3261:
8572 * "there is no coupling between TCP connection state and SIP
8573 * processing."
8574 */
8575 return;
8576 }
8577
8578 if (outgoing_other_destinations(orq)) {
8579 outgoing_print_tport_error(orq, 5, "trying alternative server after ",
8580 tpn, msg, error);
8581 outgoing_try_another(orq);
8582 return;
8583 }
8584
8585 outgoing_print_tport_error(orq, 3, "", tpn, msg, error);
8586
8587 outgoing_reply(orq, SIP_503_SERVICE_UNAVAILABLE503, sip_503_Service_unavailable, 0);
8588}
8589
8590static
8591void
8592outgoing_print_tport_error(nta_outgoing_t *orq, int level, char *todo,
8593 tp_name_t const *tpn, msg_t *msg, int error)
8594{
8595 su_sockaddr_t const *su = msg_addr(msg);
8596 char addr[SU_ADDRSIZE(48)];
8597
8598 su_llog(nta_log, level,_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8599 "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n",_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8600 orq->orq_method_name, orq->orq_cseq->cs_seq,_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8601 todo, su_strerror(error), error,_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8602 tpn->tpn_proto,_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8603 su_inet_ntop(su->su_family, SU_ADDR(su), addr, sizeof(addr)),_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
8604 htons(su->su_port))_su_llog(nta_log, level, "nta.c", (const char *)__func__, 8604
, "nta: %s (%u): %s%s (%u) with %s/[%s]:%u\n", orq->orq_method_name
, orq->orq_cseq->cs_seq, todo, su_strerror(error), error
, tpn->tpn_proto, inet_ntop(su->su_sa.sa_family, ((su)->
su_sa.sa_family == 2 ? (void *)&(su)->su_sin.sin_addr :
((su)->su_sa.sa_family == 10 ? (void *)&(su)->su_sin6
.sin6_addr : (void *)&(su)->su_sa.sa_data)), addr, sizeof
(addr)), htons(su->su_sin.sin_port))
;
8605}
8606
8607/**@internal
8608 * Add features supported.
8609 */
8610static
8611int outgoing_features(nta_agent_t *agent, nta_outgoing_t *orq,
8612 msg_t *msg, sip_t *sip,
8613 tagi_t *tags)
8614{
8615 char const *supported[8];
8616 int i;
8617
8618 if (orq->orq_method != sip_method_invite) /* fast path for now */
8619 return 0;
8620
8621 supported[i = 0] = NULL((void*)0);
8622
8623 if (orq->orq_method == sip_method_invite) {
8624 int require_100rel = sip_has_feature(sip->sip_require, "100rel");
8625
8626 if (require_100rel) {
8627 orq->orq_must_100rel = 1;
8628 orq->orq_100rel = 1;
8629 }
8630 else if (sip_has_feature(sip->sip_supported, "100rel")) {
8631 orq->orq_100rel = 1;
8632 }
8633 else if (orq->orq_100rel) {
8634 supported[i++] = "100rel";
8635 }
8636 }
8637
8638 if (i) {
8639 supported[i] = NULL((void*)0);
8640
8641 if (sip->sip_supported) {
8642 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
8643 return msg_list_append_items(home, sip->sip_supported, supported);
8644 }
8645 else {
8646 sip_supported_t s[1];
8647 sip_supported_init(s);
8648 s->k_items = supported;
8649 return sip_add_dup(msg, sip, (sip_header_t *)s);
8650 }
8651 }
8652
8653 return 0;
8654}
8655
8656
8657/**@internal
8658 * Insert outgoing request to agent hash table
8659 */
8660static
8661void outgoing_insert(nta_agent_t *agent, nta_outgoing_t *orq)
8662{
8663 if (outgoing_htable_is_full(agent->sa_outgoing))
8664 outgoing_htable_resize(agent->sa_home, agent->sa_outgoing, 0);
8665 outgoing_htable_insert(agent->sa_outgoing, orq);
8666 orq->orq_inserted = 1;
8667}
8668
8669/** @internal
8670 * Initialize a queue for outgoing transactions.
8671 */
8672static void
8673outgoing_queue_init(outgoing_queue_t *queue, unsigned timeout)
8674{
8675 memset(queue, 0, sizeof *queue);
8676 queue->q_tail = &queue->q_head;
8677 queue->q_timeout = timeout;
8678}
8679
8680/** Change the timeout value of a queue */
8681static void
8682outgoing_queue_adjust(nta_agent_t *sa,
8683 outgoing_queue_t *queue,
8684 unsigned timeout)
8685{
8686 nta_outgoing_t *orq;
8687 uint32_t latest;
8688
8689 if (timeout >= queue->q_timeout || !queue->q_head) {
8690 queue->q_timeout = timeout;
8691 return;
8692 }
8693
8694 latest = set_timeout(sa, queue->q_timeout = timeout);
8695
8696 for (orq = queue->q_head; orq; orq = orq->orq_next) {
8697 if (orq->orq_timeout == 0 ||
8698 (int32_t)(orq->orq_timeout - latest) > 0)
8699 orq->orq_timeout = latest;
8700 }
8701}
8702
8703/** @internal
8704 * Test if an outgoing transaction is in a queue.
8705 */
8706su_inlinestatic inline int
8707outgoing_is_queued(nta_outgoing_t const *orq)
8708{
8709 return orq && orq->orq_queue;
8710}
8711
8712/** @internal
8713 * Insert an outgoing transaction into a queue.
8714 *
8715 * Insert a client transaction into a queue and set the corresponding
8716 * timeout at the same time.
8717 */
8718static void
8719outgoing_queue(outgoing_queue_t *queue,
8720 nta_outgoing_t *orq)
8721{
8722 if (orq->orq_queue == queue) {
8723 //assert(queue->q_timeout == 0);
8724 return;
8725 }
8726
8727 assert(!orq->orq_forked)((void) sizeof ((!orq->orq_forked) ? 1 : 0), __extension__
({ if (!orq->orq_forked) ; else __assert_fail ("!orq->orq_forked"
, "nta.c", 8727, __extension__ __PRETTY_FUNCTION__); }))
;
8728
8729 if (outgoing_is_queued(orq))
8730 outgoing_remove(orq);
8731
8732 orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout);
8733
8734 orq->orq_queue = queue;
8735 orq->orq_prev = queue->q_tail;
8736 *queue->q_tail = orq;
8737 queue->q_tail = &orq->orq_next;
8738 queue->q_length++;
8739}
8740
8741/** @internal
8742 * Remove an outgoing transaction from a queue.
8743 */
8744su_inlinestatic inline
8745void outgoing_remove(nta_outgoing_t *orq)
8746{
8747 assert(outgoing_is_queued(orq))((void) sizeof ((outgoing_is_queued(orq)) ? 1 : 0), __extension__
({ if (outgoing_is_queued(orq)) ; else __assert_fail ("outgoing_is_queued(orq)"
, "nta.c", 8747, __extension__ __PRETTY_FUNCTION__); }))
;
8748 assert(orq->orq_queue->q_length > 0)((void) sizeof ((orq->orq_queue->q_length > 0) ? 1 :
0), __extension__ ({ if (orq->orq_queue->q_length >
0) ; else __assert_fail ("orq->orq_queue->q_length > 0"
, "nta.c", 8748, __extension__ __PRETTY_FUNCTION__); }))
;
8749
8750 if ((*orq->orq_prev = orq->orq_next))
8751 orq->orq_next->orq_prev = orq->orq_prev;
8752 else
8753 orq->orq_queue->q_tail = orq->orq_prev;
8754
8755 orq->orq_queue->q_length--;
8756 orq->orq_next = NULL((void*)0);
8757 orq->orq_prev = NULL((void*)0);
8758 orq->orq_queue = NULL((void*)0);
8759 orq->orq_timeout = 0;
8760}
8761
8762/** Set retransmit timer (orq_retry).
8763 *
8764 * Set the retry timer (B/D) on the outgoing request (client transaction).
8765 */
8766su_inlinestatic inline
8767void outgoing_set_timer(nta_outgoing_t *orq, uint32_t interval)
8768{
8769 nta_outgoing_t **rq;
8770
8771 assert(orq)((void) sizeof ((orq) ? 1 : 0), __extension__ ({ if (orq) ; else
__assert_fail ("orq", "nta.c", 8771, __extension__ __PRETTY_FUNCTION__
); }))
;
8772
8773 if (interval == 0) {
8774 outgoing_reset_timer(orq);
8775 return;
8776 }
8777
8778 if (orq->orq_rprev) {
8779 /* Remove transaction from retry dequeue, re-insert it later. */
8780 if ((*orq->orq_rprev = orq->orq_rnext))
8781 orq->orq_rnext->orq_rprev = orq->orq_rprev;
8782 if (orq->orq_agent->sa_out.re_t1 == &orq->orq_rnext)
8783 orq->orq_agent->sa_out.re_t1 = orq->orq_rprev;
8784 }
8785 else {
8786 orq->orq_agent->sa_out.re_length++;
8787 }
8788
8789 orq->orq_retry = set_timeout(orq->orq_agent, orq->orq_interval = interval);
8790
8791 /* Shortcut into queue at SIP T1 */
8792 rq = orq->orq_agent->sa_out.re_t1;
8793
8794 if (!(*rq) || (int32_t)((*rq)->orq_retry - orq->orq_retry) > 0)
8795 rq = &orq->orq_agent->sa_out.re_list;
8796
8797 while (*rq && (int32_t)((*rq)->orq_retry - orq->orq_retry) <= 0)
8798 rq = &(*rq)->orq_rnext;
8799
8800 if ((orq->orq_rnext = *rq))
8801 orq->orq_rnext->orq_rprev = &orq->orq_rnext;
8802 *rq = orq;
8803 orq->orq_rprev = rq;
8804
8805 if (interval == orq->orq_agent->sa_t1)
8806 orq->orq_agent->sa_out.re_t1 = rq;
8807}
8808
8809static
8810void outgoing_reset_timer(nta_outgoing_t *orq)
8811{
8812 if (orq->orq_rprev) {
8813 if ((*orq->orq_rprev = orq->orq_rnext))
8814 orq->orq_rnext->orq_rprev = orq->orq_rprev;
8815 if (orq->orq_agent->sa_out.re_t1 == &orq->orq_rnext)
8816 orq->orq_agent->sa_out.re_t1 = orq->orq_rprev;
8817 orq->orq_agent->sa_out.re_length--;
8818 }
8819
8820 orq->orq_interval = 0, orq->orq_retry = 0;
8821 orq->orq_rnext = NULL((void*)0), orq->orq_rprev = NULL((void*)0);
8822}
8823
8824/** @internal
8825 * Free resources associated with the request.
8826 */
8827static
8828void outgoing_free(nta_outgoing_t *orq)
8829{
8830 SU_DEBUG_9(("nta: outgoing_free(%p)\n", (void *)orq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 8830, "nta: outgoing_free(%p)\n", (void *)orq)) : (void)0)
;
8831 assert(orq->orq_forks == NULL && orq->orq_forking == NULL)((void) sizeof ((orq->orq_forks == ((void*)0) && orq
->orq_forking == ((void*)0)) ? 1 : 0), __extension__ ({ if
(orq->orq_forks == ((void*)0) && orq->orq_forking
== ((void*)0)) ; else __assert_fail ("orq->orq_forks == NULL && orq->orq_forking == NULL"
, "nta.c", 8831, __extension__ __PRETTY_FUNCTION__); }))
;
8832 outgoing_cut_off(orq);
8833 outgoing_reclaim(orq);
8834}
8835
8836/** Remove outgoing request from hash tables */
8837su_inlinestatic inline void
8838outgoing_cut_off(nta_outgoing_t *orq)
8839{
8840 nta_agent_t *agent = orq->orq_agent;
8841
8842 if (orq->orq_default)
8843 agent->sa_default_outgoing = NULL((void*)0);
8844
8845 if (orq->orq_inserted)
8846 outgoing_htable_remove(agent->sa_outgoing, orq), orq->orq_inserted = 0;
8847
8848 if (outgoing_is_queued(orq))
8849 outgoing_remove(orq);
8850
8851#if 0
8852 if (orq->orq_forked)
8853 outgoing_remove_fork(orq);
8854#endif
8855
8856 outgoing_reset_timer(orq);
8857
8858 if (orq->orq_pending) {
8859 tport_release(orq->orq_tport, orq->orq_pending,
8860 orq->orq_request, NULL((void*)0), orq, 0);
8861 }
8862 orq->orq_pending = 0;
8863
8864 if (orq->orq_cc)
8865 nta_compartment_decref(&orq->orq_cc);
8866
8867 if (orq->orq_tport)
8868 tport_decref(&orq->orq_tport);
8869}
8870
8871/** Reclaim outgoing request */
8872su_inlinestatic inline
8873void outgoing_reclaim(nta_outgoing_t *orq)
8874{
8875 if (orq->orq_status2b)
8876 *orq->orq_status2b = -1;
8877
8878 if (orq->orq_request)
8879 msg_destroy(orq->orq_request), orq->orq_request = NULL((void*)0);
8880 if (orq->orq_response)
8881 msg_destroy(orq->orq_response), orq->orq_response = NULL((void*)0);
8882#if HAVE_SOFIA_SRESOLV1
8883 if (orq->orq_resolver)
8884 outgoing_destroy_resolver(orq);
8885#endif
8886 su_free(orq->orq_agent->sa_home, orq);
8887}
8888
8889/** Queue request to be freed */
8890su_inlinestatic inline
8891void outgoing_free_queue(outgoing_queue_t *q, nta_outgoing_t *orq)
8892{
8893 outgoing_cut_off(orq);
8894 outgoing_queue(q, orq);
8895}
8896
8897/** Reclaim memory used by queue of requests */
8898static
8899void outgoing_reclaim_queued(su_root_magic_t *rm,
8900 su_msg_r msg,
8901 union sm_arg_u *u)
8902{
8903 outgoing_queue_t *q = u->a_outgoing_queue;
8904 nta_outgoing_t *orq, *orq_next;
8905
8906 SU_DEBUG_9(("outgoing_reclaim_all(%p, %p, %p)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 8907, "outgoing_reclaim_all(%p, %p, %p)\n", (void *)rm, (void
*)msg, (void *)u)) : (void)0)
8907 (void *)rm, (void *)msg, (void *)u))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 9 ? (_su_llog(nta_log, 9, "nta.c", (const char *)__func__
, 8907, "outgoing_reclaim_all(%p, %p, %p)\n", (void *)rm, (void
*)msg, (void *)u)) : (void)0)
;
8908
8909 for (orq = q->q_head; orq; orq = orq_next) {
8910 orq_next = orq->orq_next;
8911 outgoing_reclaim(orq);
8912 }
8913}
8914
8915/** @internal Default callback for request */
8916int outgoing_default_cb(nta_outgoing_magic_t *magic,
8917 nta_outgoing_t *orq,
8918 sip_t const *sip)
8919{
8920 if (sip == NULL((void*)0) || sip->sip_status->st_status >= 200)
8921 outgoing_destroy(orq);
8922 return 0;
8923}
8924
8925/** @internal Destroy an outgoing transaction */
8926void outgoing_destroy(nta_outgoing_t *orq)
8927{
8928 if (orq->orq_terminated || orq->orq_default) {
8929 if (!orq->orq_forking && !orq->orq_forks) {
8930 outgoing_free(orq);
8931 return;
8932 }
8933 }
8934 /* Application is expected to handle 200 OK statelessly
8935 => kill transaction immediately */
8936 else if (orq->orq_method == sip_method_invite && !orq->orq_completed
8937 /* (unless transaction has been canceled) */
8938 && !orq->orq_canceled
8939 /* or it has been forked */
8940 && !orq->orq_forking && !orq->orq_forks) {
8941 orq->orq_destroyed = 1;
8942 outgoing_terminate(orq);
8943 return;
8944 }
8945
8946 orq->orq_destroyed = 1;
8947 orq->orq_callback = outgoing_default_cb;
8948 orq->orq_magic = NULL((void*)0);
8949}
8950
8951/** @internal Outgoing transaction timer routine.
8952 *
8953 */
8954static void
8955_nta_outgoing_timer(nta_agent_t *sa)
8956{
8957 uint32_t now = su_time_ms(su_now());
8958 nta_outgoing_t *orq;
8959 outgoing_queue_t rq[1];
8960 size_t retransmitted = 0, terminated = 0, timeout = 0, destroyed;
8961 size_t total = sa->sa_outgoing->oht_used;
8962 size_t trying = sa->sa_out.re_length;
8963 size_t pending = sa->sa_out.trying->q_length +
8964 sa->sa_out.inv_calling->q_length;
8965 size_t completed = sa->sa_out.completed->q_length +
8966 sa->sa_out.inv_completed->q_length;
8967
8968 outgoing_queue_init(sa->sa_out.free = rq, 0);
8969
8970 while ((orq = sa->sa_out.re_list)) {
8971
8972 now = su_time_ms(su_now());
8973
8974 if ((int32_t)(orq->orq_retry - now) > 0)
8975 break;
8976 if (retransmitted >= timer_max_retransmit)
8977 break;
8978
8979 if (orq->orq_reliable) {
8980 outgoing_reset_timer(orq);
8981
8982 if (!tport_is_connected(orq->orq_tport)) {
8983 uint32_t tls_connect_timeout = (orq->orq_call_tls_connect_timeout_is_set) ?
8984 orq->orq_call_tls_connect_timeout : sa->sa_tls_orq_connect_timeout;
8985 if (su_casenmatch(orq->orq_tpn->tpn_proto, "tls", 3) && tls_connect_timeout) {
8986 outgoing_remove(orq); /* Reset state - this is no resend! */
8987 if (outgoing_other_destinations(orq)) {
8988 SU_DEBUG_5(("nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8990, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "trying alternative server for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
8989 orq->orq_tpn->tpn_proto, "trying alternative server for",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8990, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "trying alternative server for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
8990 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8990, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "trying alternative server for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
;
8991 outgoing_try_another(orq);
8992 } else {
8993 SU_DEBUG_5(("nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8995, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "retrying for", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
8994 orq->orq_tpn->tpn_proto, "retrying for",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8995, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "retrying for", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
8995 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 8995, "nta: timer %s fired (proto: %s), %s %s (%u)\n", "N3"
, orq->orq_tpn->tpn_proto, "retrying for", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
;
8996 outgoing_send(orq, 0); /* Send */
8997 }
8998 } else {
8999 /*
9000 * Timer N3: try to use UDP if trying to send via TCP
9001 * but no connection is established within SIP T4
9002 */
9003 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", "N3",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9005, "nta: timer %s fired, %s %s (%u)\n", "N3", "try UDP instead for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
9004 "try UDP instead for",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9005, "nta: timer %s fired, %s %s (%u)\n", "N3", "try UDP instead for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
9005 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9005, "nta: timer %s fired, %s %s (%u)\n", "N3", "try UDP instead for"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
;
9006 outgoing_try_udp_instead(orq, 1);
9007 outgoing_remove(orq); /* Reset state - this is no resend! */
9008 outgoing_send(orq, 0); /* Send */
9009 }
9010 }
9011 continue;
9012 }
9013
9014 assert(!orq->orq_reliable && orq->orq_interval != 0)((void) sizeof ((!orq->orq_reliable && orq->orq_interval
!= 0) ? 1 : 0), __extension__ ({ if (!orq->orq_reliable &&
orq->orq_interval != 0) ; else __assert_fail ("!orq->orq_reliable && orq->orq_interval != 0"
, "nta.c", 9014, __extension__ __PRETTY_FUNCTION__); }))
;
9015
9016 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9018, "nta: timer %s fired, %s %s (%u)\n", orq->orq_method
== sip_method_invite ? "A" : "E", "retransmit", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
9017 orq->orq_method == sip_method_invite ? "A" : "E",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9018, "nta: timer %s fired, %s %s (%u)\n", orq->orq_method
== sip_method_invite ? "A" : "E", "retransmit", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
9018 "retransmit", orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9018, "nta: timer %s fired, %s %s (%u)\n", orq->orq_method
== sip_method_invite ? "A" : "E", "retransmit", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
;
9019
9020 outgoing_retransmit(orq);
9021
9022 if (orq->orq_method == sip_method_invite ||
9023 2U * orq->orq_interval < sa->sa_t2)
9024 outgoing_set_timer(orq, 2U * orq->orq_interval);
9025 else
9026 outgoing_set_timer(orq, sa->sa_t2);
9027
9028 if (++retransmitted % 5 == 0)
9029 su_root_yield(sa->sa_root); /* Handle received packets */
9030 }
9031
9032 terminated
9033 = outgoing_timer_dk(sa->sa_out.inv_completed, "D", now)
9034 + outgoing_timer_dk(sa->sa_out.completed, "K", now);
9035
9036 timeout
9037 = outgoing_timer_bf(sa->sa_out.inv_calling, "B", now)
9038 + outgoing_timer_c(sa->sa_out.inv_proceeding, "C", now)
9039 + outgoing_timer_bf(sa->sa_out.trying, "F", now);
9040
9041 destroyed = outgoing_mass_destroy(sa, rq);
9042
9043 sa->sa_out.free = NULL((void*)0);
9044
9045 if (retransmitted || timeout || terminated || destroyed) {
9046 SU_DEBUG_5(("nta_outgoing_timer: "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9047 MOD_ZU"/"MOD_ZU" resent, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9048 MOD_ZU"/"MOD_ZU" tout, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9049 MOD_ZU"/"MOD_ZU" term, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9050 MOD_ZU"/"MOD_ZU" free\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9051 retransmitted, trying,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9052 timeout, pending,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9053 terminated, completed,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
9054 destroyed, total))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9054, "nta_outgoing_timer: " "%zu""/""%zu"" resent, " "%zu"
"/""%zu"" tout, " "%zu""/""%zu"" term, " "%zu""/""%zu"" free\n"
, retransmitted, trying, timeout, pending, terminated, completed
, destroyed, total)) : (void)0)
;
9055 }
9056}
9057
9058/** @internal Retransmit the outgoing request. */
9059void outgoing_retransmit(nta_outgoing_t *orq)
9060{
9061 if (orq->orq_prepared && !orq->orq_delayed) {
9062 orq->orq_retries++;
9063
9064 if (orq->orq_retries >= 4 && orq->orq_cc) {
9065 orq->orq_tpn->tpn_comp = NULL((void*)0);
9066 if (orq->orq_retries == 4) {
9067 agent_close_compressor(orq->orq_agent, orq->orq_cc);
9068 nta_compartment_decref(&orq->orq_cc);
9069 }
9070 }
9071
9072 outgoing_send(orq, 1);
9073 }
9074}
9075
9076/** Trying a client transaction. */
9077static
9078void outgoing_trying(nta_outgoing_t *orq)
9079{
9080 if (orq->orq_forked)
9081 ;
9082 else if (orq->orq_method == sip_method_invite) {
9083 if (!orq->orq_completed) {
9084 outgoing_queue(orq->orq_agent->sa_out.inv_calling, orq);
9085 } else {
9086 SU_DEBUG_5(("nta(%p): completed request can not be put into inv_calling queue (%u)\n", (void *)orq, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9086, "nta(%p): completed request can not be put into inv_calling queue (%u)\n"
, (void *)orq, orq->orq_cseq->cs_seq)) : (void)0)
;
9087 if (orq->orq_queue != orq->orq_agent->sa_out.inv_completed) {
9088 /* Put back into inv_completed if it's not there by any reason */
9089 outgoing_queue(orq->orq_agent->sa_out.inv_completed, orq); /* Timer D */
9090 }
9091 }
9092 }
9093 else
9094 outgoing_queue(orq->orq_agent->sa_out.trying, orq);
9095}
9096
9097/** Handle timers B and F */
9098static
9099size_t outgoing_timer_bf(outgoing_queue_t *q,
9100 char const *timer,
9101 uint32_t now)
9102{
9103 nta_outgoing_t *orq;
9104 size_t timeout = 0;
9105
9106 while ((orq = q->q_head)) {
9107 if ((int32_t)(orq->orq_timeout - now) > 0 ||
9108 timeout >= timer_max_timeout)
9109 break;
9110
9111 timeout++;
9112
9113 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9116, "nta: timer %s fired, %s %s (%u)\n", timer, orq->orq_method
!= sip_method_ack ? "timeout" : "terminating", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
9114 timer,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9116, "nta: timer %s fired, %s %s (%u)\n", timer, orq->orq_method
!= sip_method_ack ? "timeout" : "terminating", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
9115 orq->orq_method != sip_method_ack ? "timeout" : "terminating",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9116, "nta: timer %s fired, %s %s (%u)\n", timer, orq->orq_method
!= sip_method_ack ? "timeout" : "terminating", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
9116 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9116, "nta: timer %s fired, %s %s (%u)\n", timer, orq->orq_method
!= sip_method_ack ? "timeout" : "terminating", orq->orq_method_name
, orq->orq_cseq->cs_seq)) : (void)0)
;
9117
9118 if (orq->orq_method != sip_method_ack)
9119 outgoing_timeout(orq, now);
9120 else
9121 outgoing_terminate(orq);
9122
9123 assert(q->q_head != orq || (int32_t)(orq->orq_timeout - now) > 0)((void) sizeof ((q->q_head != orq || (int32_t)(orq->orq_timeout
- now) > 0) ? 1 : 0), __extension__ ({ if (q->q_head !=
orq || (int32_t)(orq->orq_timeout - now) > 0) ; else __assert_fail
("q->q_head != orq || (int32_t)(orq->orq_timeout - now) > 0"
, "nta.c", 9123, __extension__ __PRETTY_FUNCTION__); }))
;
9124 }
9125
9126 return timeout;
9127}
9128
9129/** Handle timer C */
9130static
9131size_t outgoing_timer_c(outgoing_queue_t *q,
9132 char const *timer,
9133 uint32_t now)
9134{
9135 nta_outgoing_t *orq;
9136 size_t timeout = 0;
9137
9138 if (q->q_timeout == 0)
9139 return 0;
9140
9141 while ((orq = q->q_head)) {
9142 if ((int32_t)(orq->orq_timeout - now) > 0 || timeout >= timer_max_timeout)
9143 break;
9144
9145 timeout++;
9146
9147 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9149, "nta: timer %s fired, %s %s (%u)\n", timer, "CANCEL and timeout"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
9148 timer, "CANCEL and timeout",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9149, "nta: timer %s fired, %s %s (%u)\n", timer, "CANCEL and timeout"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
9149 orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9149, "nta: timer %s fired, %s %s (%u)\n", timer, "CANCEL and timeout"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
;
9150 /*
9151 * If the client transaction has received a provisional response, the
9152 * proxy MUST generate a CANCEL request matching that transaction.
9153 */
9154 nta_outgoing_tcancel(orq, NULL((void*)0), NULL((void*)0), TAG_NULL()(tag_type_t)0, (tag_value_t)0);
9155 }
9156
9157 return timeout;
9158}
9159
9160/** @internal Signal transaction timeout to the application. */
9161void outgoing_timeout(nta_outgoing_t *orq, uint32_t now)
9162{
9163 nta_outgoing_t *cancel = NULL((void*)0);
9164
9165 if (orq->orq_status || orq->orq_canceled)
9166 ;
9167 else if (outgoing_other_destinations(orq)) {
9168 SU_DEBUG_5(("%s(%p): %s\n", "nta", (void *)orq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9169, "%s(%p): %s\n", "nta", (void *)orq, "try next after timeout"
)) : (void)0)
9169 "try next after timeout"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9169, "%s(%p): %s\n", "nta", (void *)orq, "try next after timeout"
)) : (void)0)
;
9170 outgoing_try_another(orq);
9171 return;
9172 }
9173
9174 cancel = orq->orq_cancel, orq->orq_cancel = NULL((void*)0);
9175 orq->orq_agent->sa_stats->as_tout_request++;
9176
9177 outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT408, sip_408_Request_timeout, 0);
9178
9179 if (cancel)
9180 outgoing_timeout(cancel, now);
9181}
9182
9183/** Complete a client transaction.
9184 *
9185 * @return True if transaction was free()d.
9186 */
9187static int
9188outgoing_complete(nta_outgoing_t *orq)
9189{
9190 orq->orq_completed = 1;
9191
9192 outgoing_reset_timer(orq); /* Timer A / Timer E */
9193
9194 if (orq->orq_stateless)
9195 return outgoing_terminate(orq);
9196
9197 if (orq->orq_forked) {
9198 outgoing_remove_fork(orq);
9199 return outgoing_terminate(orq);
9200 }
9201
9202 if (orq->orq_reliable) {
9203 if (orq->orq_method != sip_method_invite || !orq->orq_uas)
9204 return outgoing_terminate(orq);
9205 }
9206
9207 if (orq->orq_method == sip_method_invite) {
9208 if (orq->orq_queue != orq->orq_agent->sa_out.inv_completed)
9209 outgoing_queue(orq->orq_agent->sa_out.inv_completed, orq); /* Timer D */
9210 }
9211 else {
9212 outgoing_queue(orq->orq_agent->sa_out.completed, orq); /* Timer K */
9213 }
9214
9215 return 0;
9216}
9217
9218/** Handle timers D and K */
9219static
9220size_t outgoing_timer_dk(outgoing_queue_t *q,
9221 char const *timer,
9222 uint32_t now)
9223{
9224 nta_outgoing_t *orq;
9225 size_t terminated = 0;
9226
9227 while ((orq = q->q_head)) {
9228 if ((int32_t)(orq->orq_timeout - now) > 0 ||
9229 terminated >= timer_max_terminate)
9230 break;
9231
9232 terminated++;
9233
9234 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u)\n", timer,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9235, "nta: timer %s fired, %s %s (%u)\n", timer, "terminate"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
9235 "terminate", orq->orq_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9235, "nta: timer %s fired, %s %s (%u)\n", timer, "terminate"
, orq->orq_method_name, orq->orq_cseq->cs_seq)) : (void
)0)
;
9236
9237 if (orq->orq_method == sip_method_invite)
9238 outgoing_terminate_invite(orq);
9239 else
9240 outgoing_terminate(orq);
9241 }
9242
9243 return terminated;
9244}
9245
9246
9247/** Terminate an INVITE client transaction. */
9248static void
9249outgoing_terminate_invite(nta_outgoing_t *original)
9250{
9251 nta_outgoing_t *orq = original;
9252
9253 while (original->orq_forks) {
9254 orq = original->orq_forks;
9255 original->orq_forks = orq->orq_forks;
9256
9257 assert(orq->orq_forking == original)((void) sizeof ((orq->orq_forking == original) ? 1 : 0), __extension__
({ if (orq->orq_forking == original) ; else __assert_fail
("orq->orq_forking == original", "nta.c", 9257, __extension__
__PRETTY_FUNCTION__); }))
;
9258
9259 SU_DEBUG_5(("nta: timer %s fired, %s %s (%u);tag=%s\n", "D",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9261, "nta: timer %s fired, %s %s (%u);tag=%s\n", "D", "terminate"
, orq->orq_method_name, orq->orq_cseq->cs_seq, orq->
orq_tag)) : (void)0)
9260 "terminate", orq->orq_method_name, orq->orq_cseq->cs_seq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9261, "nta: timer %s fired, %s %s (%u);tag=%s\n", "D", "terminate"
, orq->orq_method_name, orq->orq_cseq->cs_seq, orq->
orq_tag)) : (void)0)
9261 orq->orq_tag))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9261, "nta: timer %s fired, %s %s (%u);tag=%s\n", "D", "terminate"
, orq->orq_method_name, orq->orq_cseq->cs_seq, orq->
orq_tag)) : (void)0)
;
9262
9263 orq->orq_forking = NULL((void*)0), orq->orq_forks = NULL((void*)0), orq->orq_forked = 0;
9264
9265 if (outgoing_terminate(orq))
9266 continue;
9267
9268 if (orq->orq_status < 200) {
9269 /* Fork has timed out */
9270 orq->orq_agent->sa_stats->as_tout_request++;
9271 outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT408, sip_408_Request_timeout, 0);
9272 }
9273 }
9274
9275 if (outgoing_terminate(orq = original))
9276 return;
9277
9278 if (orq->orq_status < 200) {
9279 /* Original INVITE has timed out */
9280 orq->orq_agent->sa_stats->as_tout_request++;
9281 outgoing_reply(orq, SIP_408_REQUEST_TIMEOUT408, sip_408_Request_timeout, 0);
9282 }
9283}
9284
9285static void
9286outgoing_remove_fork(nta_outgoing_t *orq)
9287{
9288 nta_outgoing_t **slot;
9289
9290 for (slot = &orq->orq_forking->orq_forks;
9291 slot && *slot;
9292 slot = &(*slot)->orq_forks) {
9293 if (orq == *slot) {
9294 *slot = orq->orq_forks;
9295 orq->orq_forks = NULL((void*)0);
9296 orq->orq_forking = NULL((void*)0);
9297 orq->orq_forked = 0;
9298 }
9299 }
9300
9301 assert(orq == NULL)((void) sizeof ((orq == ((void*)0)) ? 1 : 0), __extension__ (
{ if (orq == ((void*)0)) ; else __assert_fail ("orq == NULL",
"nta.c", 9301, __extension__ __PRETTY_FUNCTION__); }))
;
9302}
9303
9304/** Terminate a client transaction. */
9305static
9306int outgoing_terminate(nta_outgoing_t *orq)
9307{
9308 orq->orq_terminated = 1;
9309
9310 if (!orq->orq_destroyed) {
9311 outgoing_queue(orq->orq_agent->sa_out.terminated, orq);
9312 return 0;
9313 }
9314 else if (orq->orq_agent->sa_out.free) {
9315 outgoing_free_queue(orq->orq_agent->sa_out.free, orq);
9316 return 1;
9317 }
9318 else {
9319 outgoing_free(orq);
9320 return 1;
9321 }
9322}
9323
9324/** Mass destroy client transactions */
9325static
9326size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q)
9327{
9328 size_t destroyed = q->q_length;
9329
9330 if (destroyed > 2 && *sa->sa_terminator) {
9331 su_msg_r m = SU_MSG_R_INIT{ ((void*)0) };
9332
9333 if (su_msg_create(m,
9334 su_clone_task(sa->sa_terminator),
9335 su_root_task(sa->sa_root),
9336 outgoing_reclaim_queued,
9337 sizeof(outgoing_queue_t)) == SU_SUCCESSsu_success) {
9338 outgoing_queue_t *mq = su_msg_data(m)->a_outgoing_queue;
9339
9340 *mq = *q;
9341
9342 if (su_msg_send(m) == SU_SUCCESSsu_success)
9343 q->q_length = 0;
9344 }
9345 }
9346
9347 if (q->q_length)
9348 outgoing_reclaim_queued(NULL((void*)0), NULL((void*)0), (void*)q);
9349
9350 return destroyed;
9351}
9352
9353/** Find an outgoing request corresponging to a message and @Via line.
9354 *
9355 * Return an outgoing request object based on a message and the @Via line
9356 * given as argument. This function is used when doing loop checking: if we
9357 * have sent the request and it has been routed back to us.
9358 *
9359 * @param agent
9360 * @param msg
9361 * @param sip
9362 * @param v
9363 */
9364nta_outgoing_t *nta_outgoing_find(nta_agent_t const *agent,
9365 msg_t const *msg,
9366 sip_t const *sip,
9367 sip_via_t const *v)
9368{
9369 if (agent == NULL((void*)0) || msg == NULL((void*)0) || sip == NULL((void*)0) || v == NULL((void*)0)) {
9370 su_seterrno(EFAULT14);
9371 return NULL((void*)0);
9372 }
9373
9374 return outgoing_find(agent, msg, sip, v);
9375}
9376
9377/**@internal
9378 *
9379 * Find an outgoing request corresponging to a message and @Via line.
9380 *
9381 */
9382nta_outgoing_t *outgoing_find(nta_agent_t const *sa,
9383 msg_t const *msg,
9384 sip_t const *sip,
9385 sip_via_t const *v)
9386{
9387 nta_outgoing_t **oo, *orq;
9388 outgoing_htable_t const *oht = sa->sa_outgoing;
9389 sip_cseq_t const *cseq = sip->sip_cseq;
9390 sip_call_id_t const *i = sip->sip_call_id;
9391 hash_value_t hash;
9392 sip_method_t method, method2;
9393 unsigned short status = sip->sip_status ? sip->sip_status->st_status : 0;
9394
9395 if (cseq == NULL((void*)0))
9396 return NULL((void*)0);
9397
9398 hash = NTA_HASH(i, cseq->cs_seq)((i)->i_hash + 26839U * (uint32_t)(cseq->cs_seq));
9399
9400 method = cseq->cs_method;
9401
9402 /* Get original invite when ACKing */
9403 if (sip->sip_request && method == sip_method_ack && v == NULL((void*)0))
9404 method = sip_method_invite, method2 = sip_method_invalid;
9405 else if (sa->sa_is_a_uas && 200 <= status && status < 300 && method == sip_method_invite)
9406 method2 = sip_method_ack;
9407 else
9408 method2 = method;
9409
9410 for (oo = outgoing_htable_hash(oht, hash);
9411 (orq = *oo);
9412 oo = outgoing_htable_next(oht, oo)) {
9413 if (orq->orq_stateless)
9414 continue;
9415 /* Accept terminated transactions when looking for original INVITE */
9416 if (orq->orq_terminated && method2 != sip_method_invalid)
9417 continue;
9418 if (hash != orq->orq_hash)
9419 continue;
9420 if (orq->orq_call_id->i_hash != i->i_hash ||
9421 strcmp(orq->orq_call_id->i_id, i->i_id))
9422 continue;
9423 if (orq->orq_cseq->cs_seq != cseq->cs_seq)
9424 continue;
9425 if (method == sip_method_unknown &&
9426 strcmp(orq->orq_cseq->cs_method_name, cseq->cs_method_name))
9427 continue;
9428 if (orq->orq_method != method && orq->orq_method != method2)
9429 continue;
9430 if (su_strcasecmp(orq->orq_from->a_tag, sip->sip_from->a_tag))
9431 continue;
9432 if (orq->orq_to->a_tag &&
9433 su_strcasecmp(orq->orq_to->a_tag, sip->sip_to->a_tag))
9434 continue;
9435
9436 if (orq->orq_method == sip_method_ack && 300 <= status)
9437 continue;
9438
9439 if (v && !su_casematch(orq->orq_branch + strlen("branch="), v->v_branch))
9440 continue;
9441
9442 break; /* match */
9443 }
9444
9445 return orq;
9446}
9447
9448/** Process a response message. */
9449int outgoing_recv(nta_outgoing_t *_orq,
9450 int status,
9451 msg_t *msg,
9452 sip_t *sip)
9453{
9454 nta_outgoing_t *orq = _orq->orq_forking ? _orq->orq_forking : _orq;
9455 nta_agent_t *sa = orq->orq_agent;
9456 int internal = sip == NULL((void*)0) || (sip->sip_flags & NTA_INTERNAL_MSG(1<<15)) != 0;
9457
9458 assert(!internal || status >= 300)((void) sizeof ((!internal || status >= 300) ? 1 : 0), __extension__
({ if (!internal || status >= 300) ; else __assert_fail (
"!internal || status >= 300", "nta.c", 9458, __extension__
__PRETTY_FUNCTION__); }))
;
9459 assert(orq == _orq || orq->orq_method == sip_method_invite)((void) sizeof ((orq == _orq || orq->orq_method == sip_method_invite
) ? 1 : 0), __extension__ ({ if (orq == _orq || orq->orq_method
== sip_method_invite) ; else __assert_fail ("orq == _orq || orq->orq_method == sip_method_invite"
, "nta.c", 9459, __extension__ __PRETTY_FUNCTION__); }))
;
9460
9461 if (status < 100) status = 100;
9462
9463 if (!internal && orq->orq_delay == UINT_MAX(2147483647 *2U +1U))
9464 outgoing_estimate_delay(orq, sip);
9465
9466 if (orq->orq_cc)
9467 agent_accept_compressed(orq->orq_agent, msg, orq->orq_cc);
9468
9469 if (orq->orq_cancel) {
9470 nta_outgoing_t *cancel;
9471 cancel = orq->orq_cancel; orq->orq_cancel = NULL((void*)0);
9472 cancel->orq_delayed = 0;
9473
9474 if (status < 200) {
9475 outgoing_send(cancel, 0);
9476 outgoing_complete(orq);
9477 }
9478 else {
9479 outgoing_reply(cancel, SIP_481_NO_TRANSACTION481, sip_481_No_transaction, 0);
9480 }
9481 }
9482
9483 if (orq->orq_pending) {
9484 tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request,
9485 msg, orq, status < 200);
9486 if (status >= 200)
9487 orq->orq_pending = 0;
9488 }
9489
9490 /* The state machines */
9491 if (orq->orq_method == sip_method_invite) {
9492 nta_outgoing_t *original = orq;
9493
9494 orq = _orq;
9495
9496 if (orq->orq_destroyed && 200 <= status && status < 300) {
9497 if (orq->orq_uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) {
9498 /* Orphan 200 Ok to INVITE. ACK and BYE it */
9499 SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE %p\n", (void *)orq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9499, "nta: Orphan 200 Ok send ACK&BYE %p\n", (void *)orq
)) : (void)0)
;
9500 return nta_msg_ackbye(sa, msg);
9501 }
9502 return -1; /* Proxy statelessly (RFC3261 section 16.11) */
9503 }
9504
9505 outgoing_reset_timer(original); /* Retransmission */
9506
9507 if (status < 200) {
9508 if (original->orq_status < 200)
9509 original->orq_status = status;
9510 if (orq->orq_status < 200)
9511 orq->orq_status = status;
9512
9513 if (original->orq_queue == sa->sa_out.inv_calling) {
9514 outgoing_queue(sa->sa_out.inv_proceeding, original);
9515 }
9516 else if (original->orq_queue == sa->sa_out.inv_proceeding) {
9517 if (sa->sa_out.inv_proceeding->q_timeout) {
9518 outgoing_remove(original);
9519 outgoing_queue(sa->sa_out.inv_proceeding, original);
9520 }
9521 }
9522
9523 /* Handle 100rel */
9524 if (sip && sip->sip_rseq) {
9525 if (outgoing_recv_reliable(orq, msg, sip) < 0) {
9526 msg_destroy(msg);
9527 return 0;
9528 }
9529 }
9530 }
9531 else {
9532 /* Final response */
9533 if (status >= 300 && !internal)
9534 outgoing_ack(original, sip);
9535
9536 if (!original->orq_completed) {
9537 if (outgoing_complete(original))
9538 return 0;
9539
9540 if (orq->orq_uas && sip && orq == original) {
9541 /*
9542 * We silently discard duplicate final responses to INVITE below
9543 * with outgoing_duplicate()
9544 */
9545 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
9546 orq->orq_tag = su_strdup(home, sip->sip_to->a_tag);
9547 }
9548 }
9549 /* Retransmission or response from another fork */
9550 else if (orq->orq_status >= 200) {
9551 /* Once 2xx has been received, non-2xx will not be forwarded */
9552 if (status >= 300)
9553 return outgoing_duplicate(orq, msg, sip);
9554
9555 if (orq->orq_uas) {
9556 if (su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) == 0)
9557 /* Catch retransmission */
9558 return outgoing_duplicate(orq, msg, sip);
9559
9560 /* Orphan 200 Ok to INVITE. ACK and BYE it */
9561 SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE" VA_NONE))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9561, "nta: Orphan 200 Ok send ACK&BYE" "%s", "")) : (void
)0)
;
9562 return nta_msg_ackbye(sa, msg);
9563 }
9564 }
9565
9566 orq->orq_status = status;
9567 }
9568 }
9569 else if (orq->orq_method != sip_method_ack) {
9570 /* Non-INVITE */
9571 if (orq->orq_queue == sa->sa_out.trying ||
9572 orq->orq_queue == sa->sa_out.resolving) {
9573 /* hacked by freeswitch, this is being hit by options 404 status with 404 orq->orq_status and orq_destroyed = 1, orq_completed = 1 */
9574 /* assert(orq->orq_status < 200); */
9575 if (orq->orq_status >= 200) {msg_destroy(msg); return 0;}
9576
9577 if (status < 200) {
9578 /* @RFC3261 17.1.2.1:
9579 * retransmissions continue for unreliable transports,
9580 * but at an interval of T2.
9581 *
9582 * @RFC4321 1.2:
9583 * Note that Timer E is not altered during the transition
9584 * to Proceeding.
9585 */
9586 if (!orq->orq_reliable)
9587 orq->orq_interval = sa->sa_t2;
9588 }
9589 else if (!outgoing_complete(orq)) {
9590 if (orq->orq_sigcomp_zap && orq->orq_tport && orq->orq_cc)
9591 agent_zap_compressor(orq->orq_agent, orq->orq_cc);
9592 }
9593 else /* outgoing_complete */ {
9594 msg_destroy(msg);
9595 return 0;
9596 }
9597 }
9598 else {
9599 /* Already completed or terminated */
9600 assert(orq->orq_queue == sa->sa_out.completed ||((void) sizeof ((orq->orq_queue == sa->sa_out.completed
|| orq->orq_queue == sa->sa_out.terminated) ? 1 : 0), __extension__
({ if (orq->orq_queue == sa->sa_out.completed || orq->
orq_queue == sa->sa_out.terminated) ; else __assert_fail (
"orq->orq_queue == sa->sa_out.completed || orq->orq_queue == sa->sa_out.terminated"
, "nta.c", 9601, __extension__ __PRETTY_FUNCTION__); }))
9601 orq->orq_queue == sa->sa_out.terminated)((void) sizeof ((orq->orq_queue == sa->sa_out.completed
|| orq->orq_queue == sa->sa_out.terminated) ? 1 : 0), __extension__
({ if (orq->orq_queue == sa->sa_out.completed || orq->
orq_queue == sa->sa_out.terminated) ; else __assert_fail (
"orq->orq_queue == sa->sa_out.completed || orq->orq_queue == sa->sa_out.terminated"
, "nta.c", 9601, __extension__ __PRETTY_FUNCTION__); }))
;
9602 assert(orq->orq_status >= 200)((void) sizeof ((orq->orq_status >= 200) ? 1 : 0), __extension__
({ if (orq->orq_status >= 200) ; else __assert_fail ("orq->orq_status >= 200"
, "nta.c", 9602, __extension__ __PRETTY_FUNCTION__); }))
;
9603 return outgoing_duplicate(orq, msg, sip);
9604 }
9605
9606 orq->orq_status = status;
9607 }
9608 else {
9609 /* ACK */
9610 if (sip && (sip->sip_flags & NTA_INTERNAL_MSG(1<<15)) == 0)
9611 /* Received re-transmitted final reply to INVITE, retransmit ACK */
9612 outgoing_retransmit(orq);
9613 msg_destroy(msg);
9614 return 0;
9615 }
9616
9617 if (100 >= status + orq->orq_pass_100) {
9618 msg_destroy(msg);
9619 return 0;
9620 }
9621
9622 if (orq->orq_destroyed) {
9623 msg_destroy(msg);
9624 return 0;
9625 }
9626
9627 if (orq->orq_response)
9628 msg_destroy(orq->orq_response);
9629 orq->orq_response = msg;
9630 /* Call callback */
9631 orq->orq_callback(orq->orq_magic, orq, sip);
9632 return 0;
9633}
9634
9635static void outgoing_default_recv(nta_outgoing_t *orq,
9636 int status,
9637 msg_t *msg,
9638 sip_t *sip)
9639{
9640 assert(sip->sip_cseq)((void) sizeof ((sip->sip_cseq) ? 1 : 0), __extension__ ({
if (sip->sip_cseq) ; else __assert_fail ("sip->sip_cseq"
, "nta.c", 9640, __extension__ __PRETTY_FUNCTION__); }))
;
9641
9642 orq->orq_status = status;
9643 orq->orq_response = msg;
9644 orq->orq_callback(orq->orq_magic, orq, sip);
9645 orq->orq_response = NULL((void*)0);
9646 orq->orq_status = 0;
9647 msg_destroy(msg);
9648}
9649
9650static void outgoing_estimate_delay(nta_outgoing_t *orq, sip_t *sip)
9651{
9652 su_time_t now = su_now();
9653 double diff = 1000 * su_time_diff(now, orq->orq_sent);
9654
9655 if (orq->orq_timestamp && sip->sip_timestamp) {
9656 double diff2, delay = 0.0;
9657 su_time_t timestamp = { 0, 0 };
9658 char const *bad;
9659
9660 sscanf(sip->sip_timestamp->ts_stamp, "%lu.%lu",
9661 &timestamp.tv_sec, &timestamp.tv_usec);
9662
9663 diff2 = 1000 * su_time_diff(now, timestamp);
9664
9665 if (diff2 < 0)
9666 bad = "negative";
9667 else if (diff2 > diff + 1e-3)
9668 bad = "too large";
9669 else {
9670 if (sip->sip_timestamp->ts_delay)
9671 sscanf(sip->sip_timestamp->ts_delay, "%lg", &delay);
9672
9673 if (1000 * delay <= diff2) {
9674 diff = diff2 - 1000 * delay;
9675 orq->orq_delay = (unsigned)diff;
9676 SU_DEBUG_7(("nta_outgoing: RTT is %g ms, now is %lu.%06lu, "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
9677 "Timestamp was %s %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
9678 diff, now.tv_sec, now.tv_usec,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
9679 sip->sip_timestamp->ts_stamp,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
9680 sip->sip_timestamp->ts_delay ?(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
9681 sip->sip_timestamp->ts_delay : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9681, "nta_outgoing: RTT is %g ms, now is %lu.%06lu, " "Timestamp was %s %s\n"
, diff, now.tv_sec, now.tv_usec, sip->sip_timestamp->ts_stamp
, sip->sip_timestamp->ts_delay ? sip->sip_timestamp->
ts_delay : "")) : (void)0)
;
9682 return;
9683 }
9684 bad = "delay";
9685 }
9686
9687 SU_DEBUG_3(("nta_outgoing: %s Timestamp %lu.%06lu %g "(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9688 "(sent %lu.%06lu, now is %lu.%06lu)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9689 bad,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9690 timestamp.tv_sec, timestamp.tv_usec,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9691 delay,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9692 orq->orq_sent.tv_sec, orq->orq_sent.tv_usec,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
9693 now.tv_sec, now.tv_usec))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9693, "nta_outgoing: %s Timestamp %lu.%06lu %g " "(sent %lu.%06lu, now is %lu.%06lu)\n"
, bad, timestamp.tv_sec, timestamp.tv_usec, delay, orq->orq_sent
.tv_sec, orq->orq_sent.tv_usec, now.tv_sec, now.tv_usec)) :
(void)0)
;
9694 }
9695
9696 if (diff >= 0 && diff < (double)UINT_MAX(2147483647 *2U +1U)) {
9697 orq->orq_delay = (unsigned)diff;
9698 SU_DEBUG_7(("nta_outgoing: RTT is %g ms\n", diff))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 9698, "nta_outgoing: RTT is %g ms\n", diff)) : (void)0)
;
9699 }
9700}
9701
9702/**@typedef nta_response_f
9703 *
9704 * Callback for replies to outgoing requests.
9705 *
9706 * This is a callback function invoked by NTA when it has received a new
9707 * reply to an outgoing request.
9708 *
9709 * @param magic request context
9710 * @param request request handle
9711 * @param sip received status message
9712 *
9713 * @return
9714 * This callback function should return always 0.
9715 *
9716 */
9717
9718/** Process duplicate responses */
9719static int outgoing_duplicate(nta_outgoing_t *orq,
9720 msg_t *msg,
9721 sip_t *sip)
9722{
9723 sip_via_t *v;
9724
9725 if (sip && (sip->sip_flags & NTA_INTERNAL_MSG(1<<15)) == 0) {
9726 v = sip->sip_via;
9727
9728 SU_DEBUG_5(("nta: %u %s is duplicate response to %d %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9730, "nta: %u %s is duplicate response to %d %s\n", sip->
sip_status->st_status, sip->sip_status->st_phrase, orq
->orq_cseq->cs_seq, orq->orq_cseq->cs_method_name
)) : (void)0)
9729 sip->sip_status->st_status, sip->sip_status->st_phrase,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9730, "nta: %u %s is duplicate response to %d %s\n", sip->
sip_status->st_status, sip->sip_status->st_phrase, orq
->orq_cseq->cs_seq, orq->orq_cseq->cs_method_name
)) : (void)0)
9730 orq->orq_cseq->cs_seq, orq->orq_cseq->cs_method_name))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9730, "nta: %u %s is duplicate response to %d %s\n", sip->
sip_status->st_status, sip->sip_status->st_phrase, orq
->orq_cseq->cs_seq, orq->orq_cseq->cs_method_name
)) : (void)0)
;
9731 if (v)
9732 SU_DEBUG_5(("\tVia: %s %s%s%s%s%s%s%s%s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
9733 v->v_protocol, v->v_host,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
9734 SIP_STRLOG(":", v->v_port),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
9735 SIP_STRLOG(" ;received=", v->v_received),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
9736 SIP_STRLOG(" ;maddr=", v->v_maddr),(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
9737 SIP_STRLOG(" ;branch=", v->v_branch)))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 9737, "\tVia: %s %s%s%s%s%s%s%s%s%s\n", v->v_protocol, v
->v_host, ((v->v_port) ? (":") : ""), ((v->v_port) ?
(v->v_port) : ""), ((v->v_received) ? (" ;received=") :
""), ((v->v_received) ? (v->v_received) : ""), ((v->
v_maddr) ? (" ;maddr=") : ""), ((v->v_maddr) ? (v->v_maddr
) : ""), ((v->v_branch) ? (" ;branch=") : ""), ((v->v_branch
) ? (v->v_branch) : ""))) : (void)0)
;
9738 }
9739
9740 msg_destroy(msg);
9741 return 0;
9742}
9743
9744/** @internal ACK to a final response (300..699).
9745 * These messages are ACK'ed via the original URL (and tport)
9746 */
9747void outgoing_ack(nta_outgoing_t *orq, sip_t *sip)
9748{
9749 msg_t *ackmsg;
9750
9751 assert(orq)((void) sizeof ((orq) ? 1 : 0), __extension__ ({ if (orq) ; else
__assert_fail ("orq", "nta.c", 9751, __extension__ __PRETTY_FUNCTION__
); }))
;
9752
9753 /* Do not ack internally generated messages... */
9754 if (sip == NULL((void*)0) || sip->sip_flags & NTA_INTERNAL_MSG(1<<15))
9755 return;
9756
9757 assert(sip)((void) sizeof ((sip) ? 1 : 0), __extension__ ({ if (sip) ; else
__assert_fail ("sip", "nta.c", 9757, __extension__ __PRETTY_FUNCTION__
); }))
; assert(sip->sip_status)((void) sizeof ((sip->sip_status) ? 1 : 0), __extension__ (
{ if (sip->sip_status) ; else __assert_fail ("sip->sip_status"
, "nta.c", 9757, __extension__ __PRETTY_FUNCTION__); }))
;
9758 assert(sip->sip_status->st_status >= 300)((void) sizeof ((sip->sip_status->st_status >= 300) ?
1 : 0), __extension__ ({ if (sip->sip_status->st_status
>= 300) ; else __assert_fail ("sip->sip_status->st_status >= 300"
, "nta.c", 9758, __extension__ __PRETTY_FUNCTION__); }))
;
9759 assert(orq->orq_tport)((void) sizeof ((orq->orq_tport) ? 1 : 0), __extension__ (
{ if (orq->orq_tport) ; else __assert_fail ("orq->orq_tport"
, "nta.c", 9759, __extension__ __PRETTY_FUNCTION__); }))
;
9760
9761 ackmsg = outgoing_ackmsg(orq, SIP_METHOD_ACKsip_method_ack, "ACK", SIPTAG_TO(sip->sip_to)siptag_to, siptag_to_v(sip->sip_to), TAG_END()(tag_type_t)0, (tag_value_t)0);
9762 if (!ackmsg)
9763 return;
9764
9765 if (!outgoing_create(orq->orq_agent, NULL((void*)0), NULL((void*)0),
9766 NULL((void*)0), orq->orq_tpn, ackmsg,
9767 NTATAG_BRANCH_KEY(sip->sip_via->v_branch)ntatag_branch_key, tag_str_v((sip->sip_via->v_branch)),
9768 NTATAG_USER_VIA(1)ntatag_user_via, tag_bool_v((1)),
9769 NTATAG_STATELESS(1)ntatag_stateless, tag_bool_v((1)),
9770 TAG_END()(tag_type_t)0, (tag_value_t)0))
9771 msg_destroy(ackmsg);
9772}
9773
9774/** Generate messages for hop-by-hop ACK or CANCEL.
9775 */
9776msg_t *outgoing_ackmsg(nta_outgoing_t *orq, sip_method_t m, char const *mname,
9777 tag_type_t tag, tag_value_t value, ...)
9778{
9779 msg_t *msg = nta_msg_create(orq->orq_agent, 0);
9780 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
9781 sip_t *sip = sip_object(msg);
9782 sip_t *old = sip_object(orq->orq_request);
9783 sip_via_t via[1];
9784
9785 if (!sip)
9786 return NULL((void*)0);
9787
9788 if (tag) {
9789 ta_list ta;
9790
9791 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
9792
9793 sip_add_tl(msg, sip, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
9794 /* Bug sf.net # 173323:
9795 * Ensure that request-URI, topmost Via, From, To, Call-ID, CSeq,
9796 * Max-Forward, Route, Accept-Contact, Reject-Contact and
9797 * Request-Disposition are copied from original request
9798 */
9799 if (sip->sip_from)
9800 sip_header_remove(msg, sip, (void *)sip->sip_from);
9801 if (sip->sip_to && m != sip_method_ack)
9802 sip_header_remove(msg, sip, (void *)sip->sip_to);
9803 if (sip->sip_call_id)
9804 sip_header_remove(msg, sip, (void *)sip->sip_call_id);
9805 while (sip->sip_route)
9806 sip_header_remove(msg, sip, (void *)sip->sip_route);
9807 while (sip->sip_accept_contact)
9808 sip_header_remove(msg, sip, (void *)sip->sip_accept_contact);
9809 while (sip->sip_reject_contact)
9810 sip_header_remove(msg, sip, (void *)sip->sip_reject_contact);
9811 if (sip->sip_request_disposition)
9812 sip_header_remove(msg, sip, (void *)sip->sip_request_disposition);
9813 while (sip->sip_via)
9814 sip_header_remove(msg, sip, (void *)sip->sip_via);
9815 if (sip->sip_max_forwards)
9816 sip_header_remove(msg, sip, (void *)sip->sip_max_forwards);
9817
9818 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
9819 }
9820
9821 sip->sip_request =
9822 sip_request_create(home, m, mname, (url_string_t *)orq->orq_url, NULL((void*)0));
9823
9824 if (sip->sip_to == NULL((void*)0))
9825 sip_add_dup(msg, sip, (sip_header_t *)old->sip_to);
9826 sip_add_dup(msg, sip, (sip_header_t *)old->sip_from);
9827 sip_add_dup(msg, sip, (sip_header_t *)old->sip_call_id);
9828 sip_add_dup(msg, sip, (sip_header_t *)old->sip_route);
9829 /* @RFC3841. Bug #1326727. */
9830 sip_add_dup(msg, sip, (sip_header_t *)old->sip_accept_contact);
9831 sip_add_dup(msg, sip, (sip_header_t *)old->sip_reject_contact);
9832 sip_add_dup(msg, sip, (sip_header_t *)old->sip_request_disposition);
9833 sip_add_dup(msg, sip, (sip_header_t *)old->sip_max_forwards);
9834
9835 if (old->sip_via) {
9836 /* Add only the topmost Via header */
9837 *via = *old->sip_via; via->v_next = NULL((void*)0);
9838 sip_add_dup(msg, sip, (sip_header_t *)via);
9839 }
9840
9841 sip->sip_cseq = sip_cseq_create(home, old->sip_cseq->cs_seq, m, mname);
9842
9843 if (sip->sip_request &&
9844 sip->sip_to &&
9845 sip->sip_from &&
9846 sip->sip_call_id &&
9847 (!old->sip_route || sip->sip_route) &&
9848 sip->sip_cseq)
9849 return msg;
9850
9851 msg_destroy(msg);
9852
9853 return NULL((void*)0);
9854}
9855
9856static
9857void outgoing_delayed_recv(su_root_magic_t *rm,
9858 su_msg_r msg,
9859 union sm_arg_u *u);
9860
9861/** Respond internally to a transaction. */
9862int outgoing_reply(nta_outgoing_t *orq, int status, char const *phrase,
9863 int delayed)
9864{
9865 nta_agent_t *agent = orq->orq_agent;
9866 msg_t *msg = NULL((void*)0);
9867 sip_t *sip = NULL((void*)0);
9868
9869 assert(status == 202 || status >= 400)((void) sizeof ((status == 202 || status >= 400) ? 1 : 0),
__extension__ ({ if (status == 202 || status >= 400) ; else
__assert_fail ("status == 202 || status >= 400", "nta.c",
9869, __extension__ __PRETTY_FUNCTION__); }))
;
9870
9871 if (orq->orq_pending)
9872 tport_release(orq->orq_tport, orq->orq_pending,
9873 orq->orq_request, NULL((void*)0), orq, 0);
9874 orq->orq_pending = 0;
9875
9876 orq->orq_delayed = 0;
9877
9878 if (orq->orq_method == sip_method_ack) {
9879 if (status != delayed)
9880 SU_DEBUG_3(("nta(%p): responding %u %s to ACK!\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9881, "nta(%p): responding %u %s to ACK!\n", (void *)orq, status
, phrase)) : (void)0)
9881 (void *)orq, status, phrase))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 9881, "nta(%p): responding %u %s to ACK!\n", (void *)orq, status
, phrase)) : (void)0)
;
9882 orq->orq_status = status;
9883 if (orq->orq_queue == NULL((void*)0))
9884 outgoing_trying(orq); /* Timer F */
9885 return 0;
9886 }
9887
9888 if (orq->orq_destroyed) {
9889 if (orq->orq_status < 200)
9890 orq->orq_status = status;
9891 outgoing_complete(orq); /* Timer D / Timer K */
9892 return 0;
9893 }
9894
9895 if (orq->orq_stateless)
9896 ;
9897 else if (orq->orq_queue == NULL((void*)0) ||
9898 orq->orq_queue == orq->orq_agent->sa_out.resolving ||
9899 orq->orq_queue == orq->orq_agent->sa_out.delayed)
9900 outgoing_trying(orq);
9901
9902 /** Insert a dummy Via header */
9903 if (!orq->orq_prepared) {
9904 tport_t *tp = tport_primaries(orq->orq_agent->sa_tports);
9905 outgoing_insert_via(orq, agent_tport_via(tp));
9906 }
9907
9908 /* Create response message, if needed */
9909 if (!orq->orq_stateless &&
9910 !(orq->orq_callback == outgoing_default_cb) &&
9911 !(status == 408 &&
9912 orq->orq_method != sip_method_invite &&
9913 !orq->orq_agent->sa_timeout_408)) {
9914 char const *to_tag;
9915
9916 msg = nta_msg_create(agent, NTA_INTERNAL_MSG(1<<15));
9917
9918 if (complete_response(msg, status, phrase, orq->orq_request) < 0) {
9919 assert(!"complete message")((void) sizeof ((!"complete message") ? 1 : 0), __extension__
({ if (!"complete message") ; else __assert_fail ("!\"complete message\""
, "nta.c", 9919, __extension__ __PRETTY_FUNCTION__); }))
;
9920 return -1;
9921 }
9922
9923 sip = sip_object(msg); assert(sip->sip_flags & NTA_INTERNAL_MSG)((void) sizeof ((sip->sip_flags & (1<<15)) ? 1 :
0), __extension__ ({ if (sip->sip_flags & (1<<15
)) ; else __assert_fail ("sip->sip_flags & NTA_INTERNAL_MSG"
, "nta.c", 9923, __extension__ __PRETTY_FUNCTION__); }))
;
9924 to_tag = nta_agent_newtag(msg_home(msg)((su_home_t*)(msg)), "tag=%s", agent);
9925
9926 if (status > 100 &&
9927 sip->sip_to && !sip->sip_to->a_tag &&
9928 sip->sip_cseq->cs_method != sip_method_cancel &&
9929 sip_to_tag(msg_home(msg)((su_home_t*)(msg)), sip->sip_to, to_tag) < 0) {
9930 assert(!"adding tag")((void) sizeof ((!"adding tag") ? 1 : 0), __extension__ ({ if
(!"adding tag") ; else __assert_fail ("!\"adding tag\"", "nta.c"
, 9930, __extension__ __PRETTY_FUNCTION__); }))
;
9931 return -1;
9932 }
9933
9934 if (status > 400 && agent->sa_blacklist) {
9935 sip_retry_after_t af[1];
9936 sip_retry_after_init(af)->af_delta = agent->sa_blacklist;
9937
9938 sip_add_dup(msg, sip, (sip_header_t *)af);
9939 }
9940 }
9941
9942 if (orq->orq_inserted && !delayed) {
9943 outgoing_recv(orq, status, msg, sip);
9944 return 0;
9945 }
9946 else if (orq->orq_stateless && orq->orq_callback == outgoing_default_cb) {
9947 /* Xyzzy */
9948 orq->orq_status = status;
9949 outgoing_complete(orq);
9950 }
9951 else {
9952 /*
9953 * The thread creating outgoing transaction must return to application
9954 * before transaction callback can be invoked. Therefore processing an
9955 * internally generated response message must be delayed until
9956 * transaction creation is completed.
9957 *
9958 * The internally generated message is transmitted using su_msg_send()
9959 * and it is delivered back to NTA when the application next time
9960 * executes the su_root_t event loop.
9961 */
9962 nta_agent_t *agent = orq->orq_agent;
9963 su_root_t *root = agent->sa_root;
9964 su_msg_r su_msg = SU_MSG_R_INIT{ ((void*)0) };
9965
9966 if (su_msg_create(su_msg,
9967 su_root_task(root),
9968 su_root_task(root),
9969 outgoing_delayed_recv,
9970 sizeof(struct outgoing_recv_s)) == SU_SUCCESSsu_success) {
9971 struct outgoing_recv_s *a = su_msg_data(su_msg)->a_outgoing_recv;
9972
9973 a->orq = orq;
9974 a->msg = msg;
9975 a->sip = sip;
9976 a->status = status;
9977
9978 orq->orq_status2b = &a->status;
9979
9980 if (su_msg_send(su_msg) == SU_SUCCESSsu_success) {
9981 return 0;
9982 }
9983 }
9984 }
9985
9986 if (msg)
9987 msg_destroy(msg);
9988
9989 return -1;
9990}
9991
9992static
9993void outgoing_delayed_recv(su_root_magic_t *rm,
9994 su_msg_r msg,
9995 union sm_arg_u *u)
9996{
9997 struct outgoing_recv_s *a = u->a_outgoing_recv;
9998
9999 if (a->status > 0) {
10000 a->orq->orq_status2b = 0;
10001 if (outgoing_recv(a->orq, a->status, a->msg, a->sip) >= 0)
10002 return;
10003 }
10004
10005 msg_destroy(a->msg);
10006}
10007
10008
10009/* ====================================================================== */
10010/* 9) Resolving (SIP) URL */
10011
10012#if HAVE_SOFIA_SRESOLV1
10013
10014struct sipdns_query;
10015
10016/** DNS resolving for (SIP) URLs */
10017struct sipdns_resolver
10018{
10019 tp_name_t sr_tpn[1]; /**< Copy of original transport name */
10020 sres_query_t *sr_query; /**< Current DNS Query */
10021 char const *sr_target; /**< Target for current query */
10022
10023 struct sipdns_query *sr_current; /**< Current query (with results) */
10024 char **sr_results; /**< A/AAAA results to be used */
10025
10026 struct sipdns_query *sr_head; /**< List of intermediate results */
10027 struct sipdns_query **sr_tail; /**< End of intermediate result list */
10028
10029 struct sipdns_query *sr_done; /**< Completed intermediate results */
10030
10031 struct sipdns_tport const *sr_tport; /**< Selected transport */
10032
10033 /** Transports to consider for this request */
10034 struct sipdns_tport const *sr_tports[SIPDNS_TRANSPORTS(6) + 1];
10035
10036 uint16_t sr_a_aaaa1, sr_a_aaaa2; /**< Order of A and/or AAAA queries. */
10037
10038 unsigned
10039 sr_use_naptr:1,
10040 sr_use_srv:1,
10041 sr_use_a_aaaa:1;
10042};
10043
10044/** Intermediate queries */
10045struct sipdns_query
10046{
10047 struct sipdns_query *sq_next;
10048
10049 char const *sq_proto;
10050 char const *sq_domain;
10051 char sq_port[6]; /* port number */
10052 uint16_t sq_otype; /* origin type of query data (0 means request) */
10053 uint16_t sq_type; /* query type */
10054 uint16_t sq_priority; /* priority or preference */
10055 uint16_t sq_weight; /* preference or weight */
10056 uint16_t sq_grayish; /* candidate for graylisting */
10057};
10058
10059static int outgoing_resolve_next(nta_outgoing_t *orq);
10060static int outgoing_resolving(nta_outgoing_t *orq);
10061static int outgoing_resolving_error(nta_outgoing_t *,
10062 int status, char const *phrase);
10063static void outgoing_graylist(nta_outgoing_t *orq, struct sipdns_query *sq);
10064static int outgoing_query_naptr(nta_outgoing_t *orq, char const *domain);
10065static void outgoing_answer_naptr(sres_context_t *orq, sres_query_t *q,
10066 sres_record_t *answers[]);
10067struct sipdns_tport const *outgoing_naptr_tport(nta_outgoing_t *orq,
10068 sres_record_t *answers[]);
10069
10070static int outgoing_make_srv_query(nta_outgoing_t *orq);
10071static int outgoing_make_a_aaaa_query(nta_outgoing_t *orq);
10072
10073static void outgoing_query_all(nta_outgoing_t *orq);
10074
10075static int outgoing_query_srv(nta_outgoing_t *orq, struct sipdns_query *);
10076static void outgoing_answer_srv(sres_context_t *orq, sres_query_t *q,
10077 sres_record_t *answers[]);
10078
10079#if SU_HAVE_IN61
10080static int outgoing_query_aaaa(nta_outgoing_t *orq, struct sipdns_query *);
10081static void outgoing_answer_aaaa(sres_context_t *orq, sres_query_t *q,
10082 sres_record_t *answers[]);
10083#endif
10084
10085static int outgoing_query_a(nta_outgoing_t *orq, struct sipdns_query *);
10086static void outgoing_answer_a(sres_context_t *orq, sres_query_t *q,
10087 sres_record_t *answers[]);
10088
10089#ifdef __clang_analyzer__1
10090#define FUNC_ATTR_NONNULL(...)__attribute__((nonnull(...))) __attribute__((nonnull(__VA_ARGS__)))
10091#else
10092#define FUNC_ATTR_NONNULL(...)__attribute__((nonnull(...)))
10093#endif
10094
10095static void outgoing_query_results(nta_outgoing_t *orq,
10096 struct sipdns_query *sq,
10097 char *results[],
10098 size_t rlen) FUNC_ATTR_NONNULL(3)__attribute__((nonnull(3)));
10099
10100
10101#define SIPDNS_503_ERROR503, "DNS Error" 503, "DNS Error"
10102
10103/** Resolve a request destination */
10104static void
10105outgoing_resolve(nta_outgoing_t *orq,
10106 int explicit_transport,
10107 enum nta_res_order_e res_order)
10108{
10109 struct sipdns_resolver *sr = NULL((void*)0);
10110 char const *tpname = orq->orq_tpn->tpn_proto;
10111 int tport_known = strcmp(tpname, "*") != 0;
10112
10113 if (orq->orq_agent->sa_resolver)
10114 orq->orq_resolver = sr = su_zalloc(orq->orq_agent->sa_home, (sizeof *sr));
10115
10116 if (!sr) {
10117 outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error);
10118 return;
10119 }
10120
10121 *sr->sr_tpn = *orq->orq_tpn;
10122 sr->sr_use_srv = orq->orq_agent->sa_use_srv;
10123 sr->sr_use_naptr = orq->orq_agent->sa_use_naptr && sr->sr_use_srv;
10124 sr->sr_use_a_aaaa = 1;
10125 sr->sr_tail = &sr->sr_head;
10126
10127 /* RFC 3263:
10128 If the TARGET was not a numeric IP address, but a port is present in
10129 the URI, the client performs an A or AAAA record lookup of the domain
10130 name. The result will be a list of IP addresses, each of which can
10131 be contacted at the specific port from the URI and transport protocol
10132 determined previously. The client SHOULD try the first record. If
10133 an attempt should fail, based on the definition of failure in Section
10134 4.3, the next SHOULD be tried, and if that should fail, the next
10135 SHOULD be tried, and so on.
10136
10137 This is a change from RFC 2543. Previously, if the port was
10138 explicit, but with a value of 5060, SRV records were used. Now, A
10139 or AAAA records will be used.
10140 */
10141 if (sr->sr_tpn->tpn_port)
10142 sr->sr_use_naptr = 0, sr->sr_use_srv = 0;
10143
10144 /* RFC3263:
10145 If [...] a transport was specified explicitly, the client performs an
10146 SRV query for that specific transport,
10147 */
10148 if (explicit_transport)
10149 sr->sr_use_naptr = 0;
10150
10151 {
10152 /* Initialize sr_tports */
10153 tport_t *tport;
10154 char const *ident = sr->sr_tpn->tpn_ident;
10155 int i, j;
10156
10157 for (tport = tport_primary_by_name(orq->orq_agent->sa_tports, orq->orq_tpn);
10158 tport;
10159 tport = tport_next(tport)) {
10160 tp_name_t const *tpn = tport_name(tport);
10161 if (tport_known && !su_casematch(tpn->tpn_proto, tpname))
10162 continue;
10163 if (ident && (tpn->tpn_ident == NULL((void*)0) || strcmp(ident, tpn->tpn_ident)))
10164 continue;
10165
10166 for (j = 0; j < SIPDNS_TRANSPORTS(6); j++)
10167 if (su_casematch(tpn->tpn_proto, sipdns_tports[j].name))
10168 break;
10169
10170 assert(j < SIPDNS_TRANSPORTS)((void) sizeof ((j < (6)) ? 1 : 0), __extension__ ({ if (j
< (6)) ; else __assert_fail ("j < SIPDNS_TRANSPORTS", "nta.c"
, 10170, __extension__ __PRETTY_FUNCTION__); }))
;
10171 if (j == SIPDNS_TRANSPORTS(6))
10172 /* Someone added transport but did not update sipdns_tports */
10173 continue;
10174
10175 for (i = 0; i < SIPDNS_TRANSPORTS(6); i++) {
10176 if (sipdns_tports + j == sr->sr_tports[i] || sr->sr_tports[i] == NULL((void*)0))
10177 break;
10178 }
10179 sr->sr_tports[i] = sipdns_tports + j;
10180
10181 if (tport_known) /* Looking for only one transport */ {
10182 sr->sr_tport = sipdns_tports + j;
10183 break;
10184 }
10185 }
10186
10187 /* Nothing found */
10188 if (!sr->sr_tports[0]) {
10189 SU_DEBUG_3(("nta(%p): transport %s is not supported%s%s\n", (void *)orq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 10190, "nta(%p): transport %s is not supported%s%s\n", (void
*)orq, tpname, ident ? " by interface " : "", ident ? ident :
"")) : (void)0)
10190 tpname, ident ? " by interface " : "", ident ? ident : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 10190, "nta(%p): transport %s is not supported%s%s\n", (void
*)orq, tpname, ident ? " by interface " : "", ident ? ident :
"")) : (void)0)
;
10191 outgoing_resolving_error(orq, SIPDNS_503_ERROR503, "DNS Error");
10192 return;
10193 }
10194 }
10195
10196 switch (res_order) {
10197 default:
10198 case nta_res_ip6_ip4:
10199 sr->sr_a_aaaa1 = sres_type_aaaa, sr->sr_a_aaaa2 = sres_type_a;
10200 break;
10201 case nta_res_ip4_ip6:
10202 sr->sr_a_aaaa1 = sres_type_a, sr->sr_a_aaaa2 = sres_type_aaaa;
10203 break;
10204 case nta_res_ip6_only:
10205 sr->sr_a_aaaa1 = sres_type_aaaa, sr->sr_a_aaaa2 = sres_type_aaaa;
10206 break;
10207 case nta_res_ip4_only:
10208 sr->sr_a_aaaa1 = sres_type_a, sr->sr_a_aaaa2 = sres_type_a;
10209 break;
10210 }
10211
10212 outgoing_resolve_next(orq);
10213}
10214
10215/** Resolve next destination. */
10216static int
10217outgoing_resolve_next(nta_outgoing_t *orq)
10218{
10219 struct sipdns_resolver *sr = orq->orq_resolver;
10220
10221 if (sr == NULL((void*)0)) {
10222 outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error);
10223 return 0;
10224 }
10225
10226 if (sr->sr_results) {
10227 /* Use existing A/AAAA results */
10228 su_free(msg_home(orq->orq_request)((su_home_t*)(orq->orq_request)), sr->sr_results[0]);
10229 sr->sr_results++;
10230 if (sr->sr_results[0]) {
10231 struct sipdns_query *sq = sr->sr_current; assert(sq)((void) sizeof ((sq) ? 1 : 0), __extension__ ({ if (sq) ; else
__assert_fail ("sq", "nta.c", 10231, __extension__ __PRETTY_FUNCTION__
); }))
;
10232
10233 if (sq->sq_proto)
10234 orq->orq_tpn->tpn_proto = sq->sq_proto;
10235 if (sq->sq_port[0])
10236 orq->orq_tpn->tpn_port = sq->sq_port;
10237
10238 orq->orq_tpn->tpn_host = sr->sr_results[0];
10239
10240 outgoing_reset_timer(orq);
10241 outgoing_queue(orq->orq_agent->sa_out.resolving, orq);
10242 outgoing_prepare_send(orq);
10243 return 1;
10244 }
10245 else {
10246 sr->sr_current = NULL((void*)0);
10247 sr->sr_results = NULL((void*)0);
10248 }
10249 }
10250
10251 if (sr->sr_head)
10252 outgoing_query_all(orq);
10253 else if (sr->sr_use_naptr)
10254 outgoing_query_naptr(orq, sr->sr_tpn->tpn_host); /* NAPTR */
10255 else if (sr->sr_use_srv)
10256 outgoing_make_srv_query(orq); /* SRV */
10257 else if (sr->sr_use_a_aaaa)
10258 outgoing_make_a_aaaa_query(orq); /* A/AAAA */
10259 else
10260 return outgoing_resolving_error(orq, SIPDNS_503_ERROR503, "DNS Error");
10261
10262 return 1;
10263}
10264
10265/** Check if can we retry other destinations? */
10266static int
10267outgoing_other_destinations(nta_outgoing_t const *orq)
10268{
10269 struct sipdns_resolver *sr = orq->orq_resolver;
10270
10271 if (!sr)
10272 return 0;
10273
10274 if (sr->sr_use_a_aaaa || sr->sr_use_srv || sr->sr_use_naptr)
10275 return 1;
10276
10277 if (sr->sr_results && sr->sr_results[1])
10278 return 1;
10279
10280 if (sr->sr_head)
10281 return 1;
10282
10283 return 0;
10284}
10285
10286/** Resolve a request destination */
10287static int
10288outgoing_try_another(nta_outgoing_t *orq)
10289{
10290 struct sipdns_resolver *sr = orq->orq_resolver;
10291
10292 if (sr == NULL((void*)0))
10293 return 0;
10294
10295 *orq->orq_tpn = *sr->sr_tpn;
10296 orq->orq_try_tcp_instead = 0, orq->orq_try_udp_instead = 0;
10297 outgoing_reset_timer(orq);
10298 outgoing_queue(orq->orq_agent->sa_out.resolving, orq);
10299
10300 if (orq->orq_status > 0)
10301 /* PP: don't hack priority if a preliminary response has been received */
10302 ;
10303 else if (orq->orq_agent->sa_graylist == 0)
10304 /* PP: priority hacking disabled */
10305 ;
10306 /* NetModule hack:
10307 * Move server that did not work to end of queue in sres cache
10308 *
10309 * the next request does not try to use the server that is currently down
10310 *
10311 * @TODO: fix cases with only A or AAAA answering, or all servers down.
10312 */
10313 else if (sr && sr->sr_target) {
10314 struct sipdns_query *sq;
10315
10316 /* find latest A/AAAA record */
10317 sq = sr->sr_head;
10318 if (sq && sq->sq_type == sr->sr_a_aaaa2 && sr->sr_a_aaaa1 != sr->sr_a_aaaa2) {
10319 sq->sq_grayish = 1;
10320 }
10321 else {
10322 outgoing_graylist(orq, sr->sr_done);
10323 }
10324 }
10325
10326 return outgoing_resolve_next(orq);
10327}
10328
10329/** Graylist SRV records */
10330static void outgoing_graylist(nta_outgoing_t *orq, struct sipdns_query *sq)
10331{
10332 struct sipdns_resolver *sr = orq->orq_resolver;
10333 char const *target = sq->sq_domain, *proto = sq->sq_proto;
10334 unsigned prio = sq->sq_priority, maxprio = prio;
10335
10336 /* Don't know how to graylist but SRV records */
10337 if (sq->sq_otype != sres_type_srv)
10338 return;
10339
10340 SU_DEBUG_5(("nta: graylisting %s:%s;transport=%s\n", target, sq->sq_port, proto))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10340, "nta: graylisting %s:%s;transport=%s\n", target, sq->
sq_port, proto)) : (void)0)
;
10341
10342 for (sq = sr->sr_head; sq; sq = sq->sq_next)
10343 if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio)
10344 maxprio = sq->sq_priority;
10345
10346 for (sq = sr->sr_done; sq; sq = sq->sq_next)
10347 if (sq->sq_otype == sres_type_srv && sq->sq_priority > maxprio)
10348 maxprio = sq->sq_priority;
10349
10350 for (sq = sr->sr_done; sq; sq = sq->sq_next) {
10351 int modified;
10352
10353 if (sq->sq_type != sres_type_srv || strcmp(proto, sq->sq_proto))
10354 continue;
10355
10356 /* modify the SRV record(s) corresponding to the latest A/AAAA record */
10357 modified = sres_set_cached_srv_priority(
10358 orq->orq_agent->sa_resolver,
10359 sq->sq_domain,
10360 target,
10361 sq->sq_port[0] ? (uint16_t)strtoul(sq->sq_port, NULL((void*)0), 10) : 0,
10362 orq->orq_agent->sa_graylist,
10363 maxprio + 1);
10364
10365 if (modified >= 0)
10366 SU_DEBUG_3(("nta: reduced priority of %d %s SRV records (increase value to %u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 10367, "nta: reduced priority of %d %s SRV records (increase value to %u)\n"
, modified, sq->sq_domain, maxprio + 1)) : (void)0)
10367 modified, sq->sq_domain, maxprio + 1))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 10367, "nta: reduced priority of %d %s SRV records (increase value to %u)\n"
, modified, sq->sq_domain, maxprio + 1)) : (void)0)
;
10368 else
10369 SU_DEBUG_3(("nta: failed to reduce %s SRV priority\n", sq->sq_domain))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 10369, "nta: failed to reduce %s SRV priority\n", sq->sq_domain
)) : (void)0)
;
10370 }
10371}
10372
10373/** Cancel resolver query */
10374su_inlinestatic inline void outgoing_cancel_resolver(nta_outgoing_t *orq)
10375{
10376 struct sipdns_resolver *sr = orq->orq_resolver;
10377
10378 assert(orq->orq_resolver)((void) sizeof ((orq->orq_resolver) ? 1 : 0), __extension__
({ if (orq->orq_resolver) ; else __assert_fail ("orq->orq_resolver"
, "nta.c", 10378, __extension__ __PRETTY_FUNCTION__); }))
;
10379
10380 if (sr->sr_query) /* Cancel resolver query */
10381 sres_query_bind(sr->sr_query, NULL((void*)0), NULL((void*)0)), sr->sr_query = NULL((void*)0);
10382}
10383
10384/** Destroy resolver */
10385su_inlinestatic inline void outgoing_destroy_resolver(nta_outgoing_t *orq)
10386{
10387 struct sipdns_resolver *sr = orq->orq_resolver;
10388
10389 assert(orq->orq_resolver)((void) sizeof ((orq->orq_resolver) ? 1 : 0), __extension__
({ if (orq->orq_resolver) ; else __assert_fail ("orq->orq_resolver"
, "nta.c", 10389, __extension__ __PRETTY_FUNCTION__); }))
;
10390
10391 outgoing_cancel_resolver(orq);
10392
10393 su_free(orq->orq_agent->sa_home, sr);
10394
10395 orq->orq_resolver = NULL((void*)0);
10396}
10397
10398/** Check if we are resolving. If not, return 503 response. */
10399static
10400int outgoing_resolving(nta_outgoing_t *orq)
10401{
10402 struct sipdns_resolver *sr = orq->orq_resolver;
10403
10404 assert(orq->orq_resolver)((void) sizeof ((orq->orq_resolver) ? 1 : 0), __extension__
({ if (orq->orq_resolver) ; else __assert_fail ("orq->orq_resolver"
, "nta.c", 10404, __extension__ __PRETTY_FUNCTION__); }))
;
10405
10406 if (!sr->sr_query) {
10407 return outgoing_resolving_error(orq, SIPDNS_503_ERROR503, "DNS Error");
10408 }
10409 else {
10410 outgoing_queue(orq->orq_agent->sa_out.resolving, orq);
10411 return 0;
10412 }
10413}
10414
10415/** Return 503 response */
10416static
10417int outgoing_resolving_error(nta_outgoing_t *orq, int status, char const *phrase)
10418{
10419 orq->orq_resolved = 1;
10420 outgoing_reply(orq, status, phrase, 0);
10421 return -1;
10422}
10423
10424/* Query SRV records (with the given tport). */
10425static
10426int outgoing_make_srv_query(nta_outgoing_t *orq)
10427{
10428 struct sipdns_resolver *sr = orq->orq_resolver;
10429 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10430 struct sipdns_query *sq;
10431 char const *host, *prefix;
10432 int i;
10433 size_t hlen, plen;
10434
10435 sr->sr_use_srv = 0;
10436
10437 host = sr->sr_tpn->tpn_host;
10438 hlen = strlen(host) + 1;
10439
10440 for (i = 0; sr->sr_tports[i]; i++) {
10441 if (sr->sr_tport && sr->sr_tports[i] != sr->sr_tport)
10442 continue;
10443
10444 prefix = sr->sr_tports[i]->prefix;
10445 plen = strlen(prefix);
10446
10447 sq = su_zalloc(home, (sizeof *sq) + plen + hlen);
10448 if (sq) {
10449 *sr->sr_tail = sq, sr->sr_tail = &sq->sq_next;
10450 sq->sq_domain = memcpy(sq + 1, prefix, plen);
10451 memcpy((char *)sq->sq_domain + plen, host, hlen);
10452 sq->sq_proto = sr->sr_tports[i]->name;
10453 sq->sq_type = sres_type_srv;
10454 sq->sq_priority = 1;
10455 sq->sq_weight = 1;
10456 }
10457 }
10458
10459 outgoing_query_all(orq);
10460
10461 return 0;
10462}
10463
10464/* Query A/AAAA records. */
10465static
10466int outgoing_make_a_aaaa_query(nta_outgoing_t *orq)
10467{
10468 struct sipdns_resolver *sr = orq->orq_resolver;
10469 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10470 tp_name_t *tpn = orq->orq_tpn;
10471 struct sipdns_query *sq;
10472
10473 assert(sr)((void) sizeof ((sr) ? 1 : 0), __extension__ ({ if (sr) ; else
__assert_fail ("sr", "nta.c", 10473, __extension__ __PRETTY_FUNCTION__
); }))
;
10474
10475 sr->sr_use_a_aaaa = 0;
10476
10477 sq = su_zalloc(home, 2 * (sizeof *sq));
10478 if (!sq)
10479 return outgoing_resolving(orq);
10480
10481 sq->sq_type = sr->sr_a_aaaa1;
10482 sq->sq_domain = tpn->tpn_host;
10483 sq->sq_priority = 1;
10484
10485 /* Append */
10486 *sr->sr_tail = sq, sr->sr_tail = &sq->sq_next;
10487
10488 outgoing_query_all(orq);
10489
10490 return 0;
10491}
10492
10493
10494/** Start SRV/A/AAAA queries */
10495static
10496void outgoing_query_all(nta_outgoing_t *orq)
10497{
10498 struct sipdns_resolver *sr = orq->orq_resolver;
10499 struct sipdns_query *sq = sr->sr_head;
10500
10501 if (sq == NULL((void*)0)) {
10502 outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error);
10503 return;
10504 }
10505
10506 /* Remove from intermediate list */
10507 if (!(sr->sr_head = sq->sq_next))
10508 sr->sr_tail = &sr->sr_head;
10509
10510 if (sq->sq_type == sres_type_srv)
10511 outgoing_query_srv(orq, sq);
10512#if SU_HAVE_IN61
10513 else if (sq->sq_type == sres_type_aaaa)
10514 outgoing_query_aaaa(orq, sq);
10515#endif
10516 else if (sq->sq_type == sres_type_a)
10517 outgoing_query_a(orq, sq);
10518 else
10519 outgoing_resolving_error(orq, SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error);
10520}
10521
10522/** Query NAPTR record. */
10523static
10524int outgoing_query_naptr(nta_outgoing_t *orq, char const *domain)
10525{
10526 struct sipdns_resolver *sr = orq->orq_resolver;
10527 sres_record_t **answers;
10528
10529 sr->sr_use_naptr = 0;
10530
10531 sr->sr_target = domain;
10532
10533 answers = sres_cached_answers(orq->orq_agent->sa_resolver,
10534 sres_type_naptr, domain);
10535
10536 SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10538, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, domain, "NAPTR", answers ? " (cached)" : "")) :
(void)0)
10537 orq->orq_tpn->tpn_host, domain, "NAPTR",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10538, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, domain, "NAPTR", answers ? " (cached)" : "")) :
(void)0)
10538 answers ? " (cached)" : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10538, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, domain, "NAPTR", answers ? " (cached)" : "")) :
(void)0)
;
10539
10540 if (answers) {
10541 outgoing_answer_naptr(orq, NULL((void*)0), answers);
10542 return 0;
10543 }
10544 else {
10545 sr->sr_query = sres_query(orq->orq_agent->sa_resolver,
10546 outgoing_answer_naptr, orq,
10547 sres_type_naptr, domain);
10548 return outgoing_resolving(orq);
10549 }
10550}
10551
10552/* Process NAPTR records */
10553static
10554void outgoing_answer_naptr(sres_context_t *orq,
10555 sres_query_t *q,
10556 sres_record_t *answers[])
10557{
10558 int i, order = -1;
10559 size_t rlen;
10560 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10561 struct sipdns_resolver *sr = orq->orq_resolver;
10562 tp_name_t tpn[1];
10563 struct sipdns_query *sq, *selected = NULL((void*)0), **tail = &selected, **at;
10564
10565 assert(sr)((void) sizeof ((sr) ? 1 : 0), __extension__ ({ if (sr) ; else
__assert_fail ("sr", "nta.c", 10565, __extension__ __PRETTY_FUNCTION__
); }))
;
10566
10567 sr->sr_query = NULL((void*)0);
10568
10569 *tpn = *sr->sr_tpn;
10570
10571 /* The NAPTR results are sorted first by Order then by Preference */
10572 sres_sort_answers(orq->orq_agent->sa_resolver, answers);
10573
10574 if (sr->sr_tport == NULL((void*)0))
10575 sr->sr_tport = outgoing_naptr_tport(orq, answers);
10576
10577 for (i = 0; answers && answers[i]; i++) {
10578 sres_naptr_record_t const *na = answers[i]->sr_naptr;
10579 uint16_t type;
10580 int valid_tport;
10581
10582 if (na->na_record->r_status)
10583 continue;
10584 if (na->na_record->r_type != sres_type_naptr)
10585 continue;
10586
10587 /* Check if NAPTR matches our target */
10588 if (!su_casenmatch(na->na_services, "SIP+", 4) &&
10589 !su_casenmatch(na->na_services, "SIPS+", 5))
10590 /* Not a SIP/SIPS service */
10591 continue;
10592
10593 /* Use NAPTR results, don't try extra SRV/A/AAAA records */
10594 sr->sr_use_srv = 0, sr->sr_use_a_aaaa = 0;
10595
10596 valid_tport = sr->sr_tport &&
10597 su_casematch(na->na_services, sr->sr_tport->service);
10598
10599 SU_DEBUG_5(("nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10600 na->na_record->r_name,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10601 na->na_order, na->na_prefer,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10602 na->na_flags, na->na_services,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10603 na->na_regexp, na->na_replace,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10604 order >= 0 && order != na->na_order ? " (out of order)" :(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
10605 valid_tport ? "" : " (tport not used)"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10605, "nta: %s IN NAPTR %u %u \"%s\" \"%s\" \"%s\" %s%s\n"
, na->na_record->r_name, na->na_order, na->na_prefer
, na->na_flags, na->na_services, na->na_regexp, na->
na_replace, order >= 0 && order != na->na_order
? " (out of order)" : valid_tport ? "" : " (tport not used)"
)) : (void)0)
;
10606
10607 /* RFC 2915 p 4:
10608 * Order
10609 * A 16-bit unsigned integer specifying the order in which the
10610 * NAPTR records MUST be processed to ensure the correct ordering
10611 * of rules. Low numbers are processed before high numbers, and
10612 * once a NAPTR is found whose rule "matches" the target, the
10613 * client MUST NOT consider any NAPTRs with a higher value for
10614 * order (except as noted below for the Flags field).
10615 */
10616 if (order >= 0 && order != na->na_order)
10617 continue;
10618 if (!valid_tport)
10619 continue;
10620
10621 /* OK, we found matching NAPTR */
10622 order = na->na_order;
10623
10624 /*
10625 * The "S" flag means that the next lookup should be for SRV records
10626 * ... "A" means that the next lookup should be for either an A, AAAA,
10627 * or A6 record.
10628 */
10629 if (na->na_flags[0] == 's' || na->na_flags[0] == 'S')
10630 type = sres_type_srv; /* SRV */
10631 else if (na->na_flags[0] == 'a' || na->na_flags[0] == 'A')
10632 type = sr->sr_a_aaaa1; /* A / AAAA */
10633 else
10634 continue;
10635
10636 rlen = strlen(na->na_replace) + 1;
10637 sq = su_zalloc(home, (sizeof *sq) + rlen);
10638
10639 if (sq == NULL((void*)0))
10640 continue;
10641
10642 *tail = sq, tail = &sq->sq_next;
10643 sq->sq_otype = sres_type_naptr;
10644 sq->sq_priority = na->na_prefer;
10645 sq->sq_weight = 1;
10646 sq->sq_type = type;
10647 sq->sq_domain = memcpy(sq + 1, na->na_replace, rlen);
10648 sq->sq_proto = sr->sr_tport->name;
10649 }
10650
10651 sres_free_answers(orq->orq_agent->sa_resolver, answers);
10652
10653 /* RFC2915:
10654 Preference [...] specifies the order in which NAPTR
10655 records with equal "order" values SHOULD be processed, low
10656 numbers being processed before high numbers. */
10657 at = sr->sr_tail;
10658 while (selected) {
10659 sq = selected, selected = sq->sq_next;
10660
10661 for (tail = at; *tail; tail = &(*tail)->sq_next) {
10662 if (sq->sq_priority < (*tail)->sq_priority)
10663 break;
10664 if (sq->sq_priority == (*tail)->sq_priority &&
10665 sq->sq_weight < (*tail)->sq_weight)
10666 break;
10667 }
10668 /* Insert */
10669 sq->sq_next = *tail, *tail = sq;
10670
10671 if (!sq->sq_next) /* Last one */
10672 sr->sr_tail = &sq->sq_next;
10673 }
10674
10675 outgoing_resolve_next(orq);
10676}
10677
10678/* Find first supported protocol in order and preference */
10679struct sipdns_tport const *
10680outgoing_naptr_tport(nta_outgoing_t *orq, sres_record_t *answers[])
10681{
10682 int i, j, order, pref;
10683 int orders[SIPDNS_TRANSPORTS(6)] = {0}, prefs[SIPDNS_TRANSPORTS(6)] = {0};
10684 struct sipdns_tport const *tport;
10685
10686 struct sipdns_resolver *sr = orq->orq_resolver;
10687
10688 prefs[0] = 0;
10689 for (j = 0; sr->sr_tports[j]; j++) {
10690 tport = sr->sr_tports[j];
10691
10692 orders[j] = 65536, prefs[j] = 65536;
10693
10694 /* Find transport order */
10695 for (i = 0; answers && answers[i]; i++) {
10696 sres_naptr_record_t const *na = answers[i]->sr_naptr;
10697 if (na->na_record->r_status)
10698 continue;
10699 if (na->na_record->r_type != sres_type_naptr)
10700 continue;
10701 /* Check if NAPTR matches transport */
10702 if (!su_casematch(na->na_services, tport->service))
10703 continue;
10704 orders[j] = na->na_order;
10705 prefs[j] = na->na_prefer;
10706 break;
10707 }
10708 }
10709
10710 tport = sr->sr_tports[0], order = orders[0], pref = prefs[0];
10711
10712 for (j = 1; sr->sr_tports[j]; j++) {
10713 if (orders[j] <= order && prefs[j] < pref) {
10714 tport = sr->sr_tports[j], order = orders[j], pref = prefs[j];
10715 }
10716 }
10717
10718 return tport;
10719}
10720
10721
10722/* Query SRV records */
10723static
10724int outgoing_query_srv(nta_outgoing_t *orq,
10725 struct sipdns_query *sq)
10726{
10727 struct sipdns_resolver *sr = orq->orq_resolver;
10728
10729 sres_record_t **answers;
10730
10731 sr->sr_target = sq->sq_domain;
10732 sr->sr_current = sq;
10733
10734 answers = sres_cached_answers(orq->orq_agent->sa_resolver,
10735 sres_type_srv, sq->sq_domain);
10736
10737 SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10739, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "SRV", answers ? " (cached)"
: "")) : (void)0)
10738 orq->orq_tpn->tpn_host, sq->sq_domain, "SRV",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10739, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "SRV", answers ? " (cached)"
: "")) : (void)0)
10739 answers ? " (cached)" : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10739, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "SRV", answers ? " (cached)"
: "")) : (void)0)
;
10740
10741 if (answers) {
10742 outgoing_answer_srv(orq, NULL((void*)0), answers);
10743 return 0;
10744 }
10745 else {
10746 sr->sr_query = sres_query(orq->orq_agent->sa_resolver,
10747 outgoing_answer_srv, orq,
10748 sres_type_srv, sq->sq_domain);
10749 return outgoing_resolving(orq);
10750 }
10751}
10752
10753/* Process SRV records */
10754static
10755void
10756outgoing_answer_srv(sres_context_t *orq, sres_query_t *q,
10757 sres_record_t *answers[])
10758{
10759 struct sipdns_resolver *sr = orq->orq_resolver;
10760 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10761 struct sipdns_query *sq0, *sq, *selected = NULL((void*)0), **tail = &selected, **at;
10762 int i;
10763 size_t tlen;
10764
10765 sr->sr_query = NULL((void*)0);
10766
10767 sq0 = sr->sr_current;
10768 assert(sq0 && sq0->sq_type == sres_type_srv)((void) sizeof ((sq0 && sq0->sq_type == sres_type_srv
) ? 1 : 0), __extension__ ({ if (sq0 && sq0->sq_type
== sres_type_srv) ; else __assert_fail ("sq0 && sq0->sq_type == sres_type_srv"
, "nta.c", 10768, __extension__ __PRETTY_FUNCTION__); }))
;
10769 assert(sq0->sq_domain)((void) sizeof ((sq0->sq_domain) ? 1 : 0), __extension__ (
{ if (sq0->sq_domain) ; else __assert_fail ("sq0->sq_domain"
, "nta.c", 10769, __extension__ __PRETTY_FUNCTION__); }))
; assert(sq0->sq_proto)((void) sizeof ((sq0->sq_proto) ? 1 : 0), __extension__ ({
if (sq0->sq_proto) ; else __assert_fail ("sq0->sq_proto"
, "nta.c", 10769, __extension__ __PRETTY_FUNCTION__); }))
;
10770
10771 /* Sort by priority, weight? */
10772 sres_sort_answers(orq->orq_agent->sa_resolver, answers);
10773
10774 for (i = 0; answers && answers[i]; i++) {
10775 sres_srv_record_t const *srv = answers[i]->sr_srv;
10776
10777 if (srv->srv_record->r_status /* There was an error */ ||
10778 srv->srv_record->r_type != sres_type_srv)
10779 continue;
10780
10781 tlen = strlen(srv->srv_target) + 1;
10782
10783 sq = su_zalloc(home, (sizeof *sq) + tlen);
10784
10785 if (sq) {
10786 *tail = sq, tail = &sq->sq_next;
10787
10788 sq->sq_otype = sres_type_srv;
10789 sq->sq_type = sr->sr_a_aaaa1;
10790 sq->sq_proto = sq0->sq_proto;
10791 sq->sq_domain = memcpy(sq + 1, srv->srv_target, tlen);
10792 snprintf(sq->sq_port, sizeof(sq->sq_port), "%u", srv->srv_port);
10793 sq->sq_priority = srv->srv_priority;
10794 sq->sq_weight = srv->srv_weight;
10795 }
10796 }
10797
10798 sres_free_answers(orq->orq_agent->sa_resolver, answers);
10799
10800 at = &sr->sr_head;
10801
10802 /* Insert sorted by priority, randomly select by weigth */
10803 while (selected) {
10804 unsigned long weight = 0;
10805 unsigned N = 0;
10806 uint16_t priority = selected->sq_priority;
10807
10808 /* Total weight of entries with same priority */
10809 for (sq = selected; sq && priority == sq->sq_priority; sq = sq->sq_next) {
10810 weight += sq->sq_weight;
10811 N ++;
10812 }
10813
10814 tail = &selected;
10815
10816 /* Select by weighted random. Entries with weight 0 are kept in order */
10817 if (N > 1 && weight > 0) {
10818 unsigned rand = su_randint(0, weight - 1);
10819
10820 while (*tail && rand >= (*tail)->sq_weight) {
10821 rand -= (*tail)->sq_weight;
10822 tail = &(*tail)->sq_next;
10823 }
10824 }
10825
10826 /* Remove selected */
10827 if (*tail) {
10828 sq = *tail; *tail = sq->sq_next; assert(sq->sq_priority == priority)((void) sizeof ((sq->sq_priority == priority) ? 1 : 0), __extension__
({ if (sq->sq_priority == priority) ; else __assert_fail (
"sq->sq_priority == priority", "nta.c", 10828, __extension__
__PRETTY_FUNCTION__); }))
;
10829
10830 /* Append at *at */
10831 sq->sq_next = *at; *at = sq; at = &sq->sq_next; if (!*at) sr->sr_tail = at;
10832
10833 SU_DEBUG_5(("nta: %s IN SRV %u %u %s %s (%s)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10836, "nta: %s IN SRV %u %u %s %s (%s)\n", sq0->sq_domain
, (unsigned)sq->sq_priority, (unsigned)sq->sq_weight, sq
->sq_port, sq->sq_domain, sq->sq_proto)) : (void)0)
10834 sq0->sq_domain,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10836, "nta: %s IN SRV %u %u %s %s (%s)\n", sq0->sq_domain
, (unsigned)sq->sq_priority, (unsigned)sq->sq_weight, sq
->sq_port, sq->sq_domain, sq->sq_proto)) : (void)0)
10835 (unsigned)sq->sq_priority, (unsigned)sq->sq_weight,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10836, "nta: %s IN SRV %u %u %s %s (%s)\n", sq0->sq_domain
, (unsigned)sq->sq_priority, (unsigned)sq->sq_weight, sq
->sq_port, sq->sq_domain, sq->sq_proto)) : (void)0)
10836 sq->sq_port, sq->sq_domain, sq->sq_proto))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10836, "nta: %s IN SRV %u %u %s %s (%s)\n", sq0->sq_domain
, (unsigned)sq->sq_priority, (unsigned)sq->sq_weight, sq
->sq_port, sq->sq_domain, sq->sq_proto)) : (void)0)
;
10837 }
10838 }
10839
10840 /* This is not needed anymore (?) */
10841 sr->sr_current = NULL((void*)0);
10842 sq0->sq_next = sr->sr_done; sr->sr_done = sq0;
10843
10844 outgoing_resolve_next(orq);
10845}
10846
10847#if SU_HAVE_IN61
10848/* Query AAAA records */
10849static
10850int outgoing_query_aaaa(nta_outgoing_t *orq, struct sipdns_query *sq)
10851{
10852 struct sipdns_resolver *sr = orq->orq_resolver;
10853 sres_record_t **answers;
10854
10855 sr->sr_target = sq->sq_domain;
10856 sr->sr_current = sq;
10857
10858 answers = sres_cached_answers(orq->orq_agent->sa_resolver,
10859 sres_type_aaaa, sq->sq_domain);
10860
10861 SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10863, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "AAAA", answers ? " (cached)"
: "")) : (void)0)
10862 orq->orq_tpn->tpn_host, sq->sq_domain, "AAAA",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10863, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "AAAA", answers ? " (cached)"
: "")) : (void)0)
10863 answers ? " (cached)" : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10863, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "AAAA", answers ? " (cached)"
: "")) : (void)0)
;
10864
10865 if (answers) {
10866 outgoing_answer_aaaa(orq, NULL((void*)0), answers);
10867 return 0;
10868 }
10869
10870 sr->sr_query = sres_query(orq->orq_agent->sa_resolver,
10871 outgoing_answer_aaaa, orq,
10872 sres_type_aaaa, sq->sq_domain);
10873
10874 return outgoing_resolving(orq);
10875}
10876
10877/* Process AAAA records */
10878static
10879void outgoing_answer_aaaa(sres_context_t *orq, sres_query_t *q,
10880 sres_record_t *answers[])
10881{
10882 struct sipdns_resolver *sr = orq->orq_resolver;
10883 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10884 struct sipdns_query *sq = sr->sr_current;
10885
10886 size_t i, j, found;
10887 char *result, **results = NULL((void*)0);
10888
10889 assert(sq)((void) sizeof ((sq) ? 1 : 0), __extension__ ({ if (sq) ; else
__assert_fail ("sq", "nta.c", 10889, __extension__ __PRETTY_FUNCTION__
); }))
; assert(sq->sq_type == sres_type_aaaa)((void) sizeof ((sq->sq_type == sres_type_aaaa) ? 1 : 0), __extension__
({ if (sq->sq_type == sres_type_aaaa) ; else __assert_fail
("sq->sq_type == sres_type_aaaa", "nta.c", 10889, __extension__
__PRETTY_FUNCTION__); }))
;
10890
10891 sr->sr_query = NULL((void*)0);
10892
10893 for (i = 0, found = 0; answers && answers[i]; i++) {
10894 sres_aaaa_record_t const *aaaa = answers[i]->sr_aaaa;
10895 if (aaaa->aaaa_record->r_status == 0 &&
10896 aaaa->aaaa_record->r_type == sres_type_aaaa)
10897 found++;
10898 }
10899
10900 if (found > 1)
10901 results = su_zalloc(home, (found + 1) * (sizeof *results));
10902 else if (found)
10903 results = &result;
10904
10905 for (i = j = 0; results && answers && answers[i]; i++) {
10906 char addr[SU_ADDRSIZE(48)];
10907 sres_aaaa_record_t const *aaaa = answers[i]->sr_aaaa;
10908
10909 if (aaaa->aaaa_record->r_status ||
10910 aaaa->aaaa_record->r_type != sres_type_aaaa)
10911 continue; /* There was an error */
10912
10913 su_inet_ntopinet_ntop(AF_INET610, &aaaa->aaaa_addr, addr, sizeof(addr));
10914
10915 if (j == 0)
10916 SU_DEBUG_5(("nta(%p): %s IN AAAA %s\n", (void *)orq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10917, "nta(%p): %s IN AAAA %s\n", (void *)orq, aaaa->aaaa_record
->r_name, addr)) : (void)0)
10917 aaaa->aaaa_record->r_name, addr))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10917, "nta(%p): %s IN AAAA %s\n", (void *)orq, aaaa->aaaa_record
->r_name, addr)) : (void)0)
;
10918 else
10919 SU_DEBUG_5(("nta(%p): AAAA %s\n", (void *)orq, addr))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10919, "nta(%p): AAAA %s\n", (void *)orq, addr)) : (void)0
)
;
10920
10921 assert(j < found)((void) sizeof ((j < found) ? 1 : 0), __extension__ ({ if (
j < found) ; else __assert_fail ("j < found", "nta.c", 10921
, __extension__ __PRETTY_FUNCTION__); }))
;
10922 results[j++] = su_strdup(home, addr);
10923 }
10924
10925 sres_free_answers(orq->orq_agent->sa_resolver, answers);
10926
10927 if (results)
10928 outgoing_query_results(orq, sq, results, found);
10929 else if (!q)
10930 outgoing_resolving_error(orq, SIPDNS_503_ERROR503, "DNS Error");
10931}
10932#endif /* SU_HAVE_IN6 */
10933
10934/* Query A records */
10935static
10936int outgoing_query_a(nta_outgoing_t *orq, struct sipdns_query *sq)
10937{
10938 struct sipdns_resolver *sr = orq->orq_resolver;
10939 sres_record_t **answers;
10940
10941 sr->sr_target = sq->sq_domain;
10942 sr->sr_current = sq;
10943
10944 answers = sres_cached_answers(orq->orq_agent->sa_resolver,
10945 sres_type_a, sq->sq_domain);
10946
10947 SU_DEBUG_5(("nta: for \"%s\" query \"%s\" %s%s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10949, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "A", answers ? " (cached)" :
"")) : (void)0)
10948 orq->orq_tpn->tpn_host, sq->sq_domain, "A",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10949, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "A", answers ? " (cached)" :
"")) : (void)0)
10949 answers ? " (cached)" : ""))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 10949, "nta: for \"%s\" query \"%s\" %s%s\n", orq->orq_tpn
->tpn_host, sq->sq_domain, "A", answers ? " (cached)" :
"")) : (void)0)
;
10950
10951 if (answers) {
10952 outgoing_answer_a(orq, NULL((void*)0), answers);
10953 return 0;
10954 }
10955
10956 sr->sr_query = sres_query(orq->orq_agent->sa_resolver,
10957 outgoing_answer_a, orq,
10958 sres_type_a, sq->sq_domain);
10959
10960 return outgoing_resolving(orq);
10961}
10962
10963/* Process A records */
10964static
10965void outgoing_answer_a(sres_context_t *orq, sres_query_t *q,
10966 sres_record_t *answers[])
10967{
10968 struct sipdns_resolver *sr = orq->orq_resolver;
10969 su_home_t *home = msg_home(orq->orq_request)((su_home_t*)(orq->orq_request));
10970 struct sipdns_query *sq = sr->sr_current;
10971
10972 int i, j, found;
10973 char *result, **results = NULL((void*)0);
10974
10975 assert(sq)((void) sizeof ((sq) ? 1 : 0), __extension__ ({ if (sq) ; else
__assert_fail ("sq", "nta.c", 10975, __extension__ __PRETTY_FUNCTION__
); }))
; assert(sq->sq_type == sres_type_a)((void) sizeof ((sq->sq_type == sres_type_a) ? 1 : 0), __extension__
({ if (sq->sq_type == sres_type_a) ; else __assert_fail (
"sq->sq_type == sres_type_a", "nta.c", 10975, __extension__
__PRETTY_FUNCTION__); }))
;
10976
10977 sr->sr_query = NULL((void*)0);
10978
10979 for (i = 0, found = 0; answers && answers[i]; i++) {
10980 sres_a_record_t const *a = answers[i]->sr_a;
10981 if (a->a_record->r_status == 0 &&
10982 a->a_record->r_type == sres_type_a)
10983 found++;
10984 }
10985
10986 if (found > 1)
10987 results = su_zalloc(home, (found + 1) * (sizeof *results));
10988 else if (found)
10989 results = &result;
10990
10991 for (i = j = 0; answers && answers[i]; i++) {
10992 char addr[SU_ADDRSIZE(48)];
10993 sres_a_record_t const *a = answers[i]->sr_a;
10994
10995 if (a->a_record->r_status ||
10996 a->a_record->r_type != sres_type_a)
10997 continue; /* There was an error */
10998
10999 su_inet_ntopinet_ntop(AF_INET2, &a->a_addr, addr, sizeof(addr));
11000
11001 if (j == 0)
11002 SU_DEBUG_5(("nta: %s IN A %s\n", a->a_record->r_name, addr))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11002, "nta: %s IN A %s\n", a->a_record->r_name, addr
)) : (void)0)
;
11003 else
11004 SU_DEBUG_5(("nta(%p): A %s\n", (void *)orq, addr))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11004, "nta(%p): A %s\n", (void *)orq, addr)) : (void)0)
;
11005
11006 assert(j < found)((void) sizeof ((j < found) ? 1 : 0), __extension__ ({ if (
j < found) ; else __assert_fail ("j < found", "nta.c", 11006
, __extension__ __PRETTY_FUNCTION__); }))
;
11007 results[j++] = su_strdup(home, addr);
11008 }
11009
11010 sres_free_answers(orq->orq_agent->sa_resolver, answers);
11011
11012 if (results)
11013 outgoing_query_results(orq, sq, results, found);
11014 else if (!q)
11015 outgoing_resolving_error(orq, SIPDNS_503_ERROR503, "DNS Error");
11016}
11017
11018/** Store A/AAAA query results */
11019static void
11020outgoing_query_results(nta_outgoing_t *orq,
11021 struct sipdns_query *sq,
11022 char *results[],
11023 size_t rlen)
11024{
11025 struct sipdns_resolver *sr = orq->orq_resolver;
11026
11027 if (sq->sq_type == sr->sr_a_aaaa1 &&
11028 sq->sq_type != sr->sr_a_aaaa2) {
11029 sq->sq_type = sr->sr_a_aaaa2;
11030
11031 SU_DEBUG_7(("nta(%p): %s %s record still unresolved\n", (void *)orq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 11032, "nta(%p): %s %s record still unresolved\n", (void *)
orq, sq->sq_domain, sq->sq_type == sres_type_a ? "A" : "AAAA"
)) : (void)0)
11032 sq->sq_domain, sq->sq_type == sres_type_a ? "A" : "AAAA"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 11032, "nta(%p): %s %s record still unresolved\n", (void *)
orq, sq->sq_domain, sq->sq_type == sres_type_a ? "A" : "AAAA"
)) : (void)0)
;
11033
11034 /*
11035 * Three possible policies:
11036 * 1) try each host for AAAA/A, then A/AAAA
11037 * 2) try everything first for AAAA/A, then everything for A/AAAA
11038 * 3) try one SRV record results for AAAA/A, then for A/AAAA,
11039 * then next SRV record
11040 */
11041
11042 /* We use now policy #1 */
11043 if (!(sq->sq_next = sr->sr_head))
11044 sr->sr_tail = &sq->sq_next;
11045 sr->sr_head = sq;
11046 }
11047 else {
11048 sq->sq_next = sr->sr_done, sr->sr_done = sq;
11049
11050 if (rlen == 0 && sq->sq_grayish)
11051 outgoing_graylist(orq, sq);
11052 }
11053
11054 if (rlen > 1)
11055 sr->sr_results = results;
11056 else
11057 sr->sr_current = NULL((void*)0);
11058
11059 if (rlen > 0) {
11060 orq->orq_resolved = 1;
11061 orq->orq_tpn->tpn_host = results[0];
11062 if (sq->sq_proto) orq->orq_tpn->tpn_proto = sq->sq_proto;
11063 if (sq->sq_port[0]) orq->orq_tpn->tpn_port = sq->sq_port;
11064 outgoing_prepare_send(orq);
11065 } else {
11066 outgoing_resolve_next(orq);
11067 }
11068}
11069
11070
11071#endif
11072
11073/* ====================================================================== */
11074/* 10) Reliable responses */
11075
11076static nta_prack_f nta_reliable_destroyed;
11077
11078/**
11079 * Check that server transaction can be used to send reliable provisional
11080 * responses.
11081 */
11082su_inlinestatic inline
11083int reliable_check(nta_incoming_t *irq)
11084{
11085 if (irq == NULL((void*)0) || irq->irq_status >= 200 || !irq->irq_agent)
11086 return 0;
11087
11088 if (irq->irq_reliable && irq->irq_reliable->rel_status >= 200)
11089 return 0;
11090
11091 /* @RSeq is initialized to nonzero when request requires/supports 100rel */
11092 if (irq->irq_rseq == 0)
11093 return 0;
11094
11095 if (irq->irq_rseq == 0xffffffffU) /* already sent >> 2**31 responses */
11096 return 0;
11097
11098 return 1;
11099}
11100
11101/** Respond reliably.
11102 *
11103 * @param irq
11104 * @param callback
11105 * @param rmagic
11106 * @param status
11107 * @param phrase
11108 * @param tag, value, ..
11109 */
11110nta_reliable_t *nta_reliable_treply(nta_incoming_t *irq,
11111 nta_prack_f *callback,
11112 nta_reliable_magic_t *rmagic,
11113 int status, char const *phrase,
11114 tag_type_t tag,
11115 tag_value_t value, ...)
11116{
11117 ta_list ta;
11118 msg_t *msg;
11119 sip_t *sip;
11120 nta_reliable_t *retval = NULL((void*)0);
11121
11122 if (!reliable_check(irq) || (status <= 100 || status >= 200))
11123 return NULL((void*)0);
11124
11125 msg = nta_msg_create(irq->irq_agent, 0);
11126 sip = sip_object(msg);
11127
11128 if (!sip)
11129 return NULL((void*)0);
11130
11131 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
11132
11133 if (0 > nta_incoming_complete_response(irq, msg, status, phrase,
11134 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
))
11135 msg_destroy(msg);
11136 else if (!(retval = reliable_mreply(irq, callback, rmagic, msg, sip)))
11137 msg_destroy(msg);
11138
11139 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
11140
11141 return retval;
11142}
11143
11144/** Respond reliably with @a msg.
11145 *
11146 * @note
11147 * The stack takes over the ownership of @a msg. (It is destroyed even if
11148 * sending the response fails.)
11149 *
11150 * @param irq
11151 * @param callback
11152 * @param rmagic
11153 * @param msg
11154 */
11155nta_reliable_t *nta_reliable_mreply(nta_incoming_t *irq,
11156 nta_prack_f *callback,
11157 nta_reliable_magic_t *rmagic,
11158 msg_t *msg)
11159{
11160 sip_t *sip = sip_object(msg);
11161
11162 if (!reliable_check(irq)) {
11163 msg_destroy(msg);
11164 return NULL((void*)0);
11165 }
11166
11167 if (sip == NULL((void*)0) || !sip->sip_status || sip->sip_status->st_status <= 100) {
11168 msg_destroy(msg);
11169 return NULL((void*)0);
11170 }
11171
11172 if (sip->sip_status->st_status >= 200) {
11173 incoming_final_failed(irq, msg);
11174 return NULL((void*)0);
11175 }
11176
11177 return reliable_mreply(irq, callback, rmagic, msg, sip);
11178}
11179
11180static
11181nta_reliable_t *reliable_mreply(nta_incoming_t *irq,
11182 nta_prack_f *callback,
11183 nta_reliable_magic_t *rmagic,
11184 msg_t *msg,
11185 sip_t *sip)
11186{
11187 nta_reliable_t *rel;
11188 nta_agent_t *agent;
11189
11190 agent = irq->irq_agent;
11191
11192 if (callback == NULL((void*)0))
11193 callback = nta_reliable_destroyed;
11194
11195 rel = su_zalloc(agent->sa_home, sizeof(*rel));
11196 if (rel) {
11197 rel->rel_irq = irq;
11198 rel->rel_callback = callback;
11199 rel->rel_magic = rmagic;
11200 rel->rel_unsent = msg;
11201 rel->rel_status = sip->sip_status->st_status;
11202 rel->rel_precious = sip->sip_payload != NULL((void*)0);
11203 rel->rel_next = irq->irq_reliable;
11204
11205 /*
11206 * If there already is a un-pr-acknowledged response, queue this one
11207 * until at least one response is pr-acknowledged.
11208 */
11209 if (irq->irq_reliable &&
11210 (irq->irq_reliable->rel_next == NULL((void*)0) ||
11211 irq->irq_reliable->rel_rseq == 0)) {
11212 return irq->irq_reliable = rel;
11213 }
11214
11215 if (reliable_send(irq, rel, msg_ref_create(msg), sip) < 0) {
11216 msg_destroy(msg);
11217 su_free(agent->sa_home, rel);
11218 return NULL((void*)0);
11219 }
11220
11221 irq->irq_reliable = rel;
11222
11223 return callback ? rel : (nta_reliable_t *)-1;
11224 }
11225
11226 msg_destroy(msg);
11227 return NULL((void*)0);
11228}
11229
11230static
11231int reliable_send(nta_incoming_t *irq,
11232 nta_reliable_t *rel,
11233 msg_t *msg,
11234 sip_t *sip)
11235{
11236 nta_agent_t *sa = irq->irq_agent;
11237 su_home_t *home = msg_home(msg)((su_home_t*)(msg));
11238 sip_rseq_t rseq[1];
11239 sip_rseq_init(rseq);
11240
11241 if (sip->sip_require)
11242 msg_header_replace_param(home, sip->sip_require->k_common, "100rel");
11243 else
11244 sip_add_make(msg, sip, sip_require_class, "100rel");
11245
11246 rel->rel_rseq = rseq->rs_response = irq->irq_rseq;
11247 sip_add_dup(msg, sip, (sip_header_t *)rseq);
11248
11249 if (!sip->sip_rseq || incoming_reply(irq, msg, sip) < 0) {
11250 msg_destroy(msg);
11251 return -1;
11252 }
11253
11254 irq->irq_rseq++;
11255
11256 if (irq->irq_queue == sa->sa_in.preliminary)
11257 /* Make sure we are moved to the tail */
11258 incoming_remove(irq);
11259
11260 incoming_queue(sa->sa_in.preliminary, irq); /* P1 */
11261 incoming_set_timer(irq, sa->sa_t1); /* P2 */
11262
11263 return 0;
11264}
11265
11266/** Queue final response when there are unsent precious preliminary responses */
11267static
11268int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip)
11269{
11270 nta_reliable_t *r;
11271 unsigned already_in_callback;
11272 /*
11273 * We delay sending final response if it's 2XX and
11274 * an unpracked reliable response contains session description
11275 */
11276 /* Get last unpracked response from queue */
11277 if (sip->sip_status->st_status < 300)
11278 for (r = irq->irq_reliable; r; r = r->rel_next)
11279 if (r->rel_unsent && r->rel_precious) {
11280 /* Delay sending 2XX */
11281 reliable_mreply(irq, NULL((void*)0), NULL((void*)0), msg, sip);
11282 return 0;
11283 }
11284
11285 /* Flush unsent responses. */
11286 already_in_callback = irq->irq_in_callback;
11287 irq->irq_in_callback = 1;
11288 reliable_flush(irq);
11289 irq->irq_in_callback = already_in_callback;
11290
11291 if (!already_in_callback && irq->irq_terminated && irq->irq_destroyed) {
11292 incoming_free(irq);
11293 msg_destroy(msg);
11294 return 0;
11295 }
11296
11297 return 1;
11298}
11299
11300/** Get latest reliably sent response */
11301static
11302msg_t *reliable_response(nta_incoming_t *irq)
11303{
11304 nta_reliable_t *r, *rel;
11305
11306 /* Get last unpracked response from queue */
11307 for (rel = NULL((void*)0), r = irq->irq_reliable; r; r = r->rel_next)
11308 if (!r->rel_pracked)
11309 rel = r;
11310
11311 assert(rel)((void) sizeof ((rel) ? 1 : 0), __extension__ ({ if (rel) ; else
__assert_fail ("rel", "nta.c", 11311, __extension__ __PRETTY_FUNCTION__
); }))
;
11312
11313 return rel->rel_unsent;
11314}
11315
11316/* Find un-PRACKed responses */
11317static
11318nta_reliable_t *reliable_find(nta_agent_t const *agent,
11319 sip_t const *sip)
11320{
11321 incoming_htable_t const *iht = agent->sa_incoming;
11322 nta_incoming_t *irq, **ii;
11323 sip_call_id_t const *i = sip->sip_call_id;
11324 sip_rack_t const *rack = sip->sip_rack;
11325 hash_value_t hash = NTA_HASH(i, rack->ra_cseq)((i)->i_hash + 26839U * (uint32_t)(rack->ra_cseq));
11326
11327 /* XXX - add own hash table for 100rel */
11328
11329 for (ii = incoming_htable_hash(iht, hash);
11330 (irq = *ii);
11331 ii = incoming_htable_next(iht, ii)) {
11332
11333 if (hash == irq->irq_hash &&
11334 irq->irq_call_id->i_hash == i->i_hash &&
11335 irq->irq_cseq->cs_seq == rack->ra_cseq &&
11336 irq->irq_method == sip_method_invite &&
11337 strcmp(irq->irq_call_id->i_id, i->i_id) == 0 &&
11338 (irq->irq_to->a_tag == NULL((void*)0) ||
11339 su_casematch(irq->irq_to->a_tag, sip->sip_to->a_tag)) &&
11340 su_casematch(irq->irq_from->a_tag, sip->sip_from->a_tag)) {
11341
11342 nta_reliable_t const *rel;
11343
11344 /* Found matching INVITE */
11345 for (rel = irq->irq_reliable; rel; rel = rel->rel_next)
11346 if (rel->rel_rseq == rack->ra_response)
11347 return (nta_reliable_t *)rel;
11348
11349 }
11350 }
11351
11352 return NULL((void*)0);
11353}
11354
11355/** Process incoming PRACK with matching @RAck field */
11356static
11357int reliable_recv(nta_reliable_t *rel, msg_t *msg, sip_t *sip, tport_t *tp)
11358{
11359 nta_incoming_t *irq = rel->rel_irq;
11360 nta_incoming_t *pr_irq;
11361 int status;
11362
11363 rel->rel_pracked = 1;
11364 msg_ref_destroy(rel->rel_unsent), rel->rel_unsent = NULL((void*)0);
11365
11366 pr_irq = incoming_create(irq->irq_agent, msg, sip, tp, irq->irq_tag);
11367 if (!pr_irq) {
11368 mreply(irq->irq_agent, NULL((void*)0),
11369 SIP_500_INTERNAL_SERVER_ERROR500, sip_500_Internal_server_error, msg,
11370 tp, 0, 0, NULL((void*)0),
11371 TAG_END()(tag_type_t)0, (tag_value_t)0);
11372 return 0;
11373 }
11374
11375 if (irq->irq_status < 200) {
11376 incoming_queue(irq->irq_agent->sa_in.proceeding, irq); /* Reset P1 */
11377 incoming_reset_timer(irq); /* Reset P2 */
11378 }
11379
11380 irq->irq_in_callback = pr_irq->irq_in_callback = 1;
11381 status = rel->rel_callback(rel->rel_magic, rel, pr_irq, sip); rel = NULL((void*)0);
11382 irq->irq_in_callback = pr_irq->irq_in_callback = 0;
11383
11384 if (pr_irq->irq_completed) { /* Already sent final response */
11385 if (pr_irq->irq_terminated && pr_irq->irq_destroyed)
11386 incoming_free(pr_irq);
11387 }
11388 else if (status != 0) {
11389 if (status < 200 || status > 299) {
11390 SU_DEBUG_3(("nta_reliable(): invalid status %03d from callback\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11391, "nta_reliable(): invalid status %03d from callback\n"
, status)) : (void)0)
11391 status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11391, "nta_reliable(): invalid status %03d from callback\n"
, status)) : (void)0)
;
11392 status = 200;
11393 }
11394 nta_incoming_treply(pr_irq, status, "OK", TAG_END()(tag_type_t)0, (tag_value_t)0);
11395 nta_incoming_destroy(pr_irq);
11396 }
11397
11398 /* If there are queued unsent reliable responses, send them all. */
11399 while (irq->irq_reliable && irq->irq_reliable->rel_rseq == 0) {
11400 nta_reliable_t *r;
11401
11402 for (r = irq->irq_reliable; r; r = r->rel_next)
11403 if (r->rel_rseq == 0)
11404 rel = r;
11405
11406 msg = rel->rel_unsent, sip = sip_object(msg);
11407
11408 if (sip->sip_status->st_status < 200) {
11409 if (reliable_send(irq, rel, msg_ref_create(msg), sip) < 0) {
11410 assert(!"send reliable response")((void) sizeof ((!"send reliable response") ? 1 : 0), __extension__
({ if (!"send reliable response") ; else __assert_fail ("!\"send reliable response\""
, "nta.c", 11410, __extension__ __PRETTY_FUNCTION__); }))
;
11411 }
11412 }
11413 else {
11414 /*
11415 * XXX
11416 * Final response should be delayed until a reliable provisional
11417 * response has been pracked
11418 */
11419 rel->rel_unsent = NULL((void*)0), rel->rel_rseq = (uint32_t)-1;
11420 if (incoming_reply(irq, msg, sip) < 0) {
11421 assert(!"send delayed final response")((void) sizeof ((!"send delayed final response") ? 1 : 0), __extension__
({ if (!"send delayed final response") ; else __assert_fail (
"!\"send delayed final response\"", "nta.c", 11421, __extension__
__PRETTY_FUNCTION__); }))
;
11422 }
11423 }
11424 }
11425
11426 return 0;
11427}
11428
11429/** Flush unacknowledged and unsent reliable responses */
11430void reliable_flush(nta_incoming_t *irq)
11431{
11432 nta_reliable_t *r, *rel;
11433
11434 do {
11435 for (r = irq->irq_reliable, rel = NULL((void*)0); r; r = r->rel_next)
11436 if (r->rel_unsent)
11437 rel = r;
11438
11439 if (rel) {
11440 rel->rel_pracked = 1;
11441 msg_ref_destroy(rel->rel_unsent), rel->rel_unsent = NULL((void*)0);
11442 rel->rel_callback(rel->rel_magic, rel, NULL((void*)0), NULL((void*)0));
11443 }
11444 } while (rel);
11445}
11446
11447void reliable_timeout(nta_incoming_t *irq, int timeout)
11448{
11449 if (timeout)
11450 SU_DEBUG_5(("nta: response timeout with %u\n", irq->irq_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11450, "nta: response timeout with %u\n", irq->irq_status
)) : (void)0)
;
11451
11452 irq->irq_in_callback = 1;
11453
11454 reliable_flush(irq);
11455
11456 if (irq->irq_callback)
11457 irq->irq_callback(irq->irq_magic, irq, NULL((void*)0));
11458
11459 irq->irq_in_callback = 0;
11460
11461 if (!timeout)
11462 return;
11463
11464 if (irq->irq_completed && irq->irq_destroyed)
11465 incoming_free(irq), irq = NULL((void*)0);
11466 else if (irq->irq_status < 200)
11467 nta_incoming_treply(irq, 503, "Reliable Response Time-Out", TAG_END()(tag_type_t)0, (tag_value_t)0);
11468}
11469
11470#if 0 /* Not needed, yet. */
11471/** Use this callback when normal leg callback is supposed to
11472 * process incoming PRACK requests
11473 */
11474int nta_reliable_leg_prack(nta_reliable_magic_t *magic,
11475 nta_reliable_t *rel,
11476 nta_incoming_t *irq,
11477 sip_t const *sip)
11478{
11479 nta_agent_t *agent;
11480 nta_leg_t *leg;
11481 char const *method_name;
11482 url_t url[1];
11483 int retval;
11484
11485 if (irq == NULL((void*)0) || sip == NULL((void*)0) || rel == NULL((void*)0) ||
11486 sip_object(irq->irq_request) != sip)
11487 return 500;
11488
11489 agent = irq->irq_agent;
11490 method_name = sip->sip_request->rq_method_name;
11491 *url = *sip->sip_request->rq_url; url->url_params = NULL((void*)0);
11492 agent_aliases(agent, url, irq->irq_tport); /* canonize urls */
11493
11494 if ((leg = leg_find(irq->irq_agent,
11495 method_name, url,
11496 sip->sip_call_id,
11497 sip->sip_from->a_tag,
11498 sip->sip_to->a_tag))) {
11499 /* Use existing dialog */
11500 SU_DEBUG_5(("nta: %s (%u) %s\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11502, "nta: %s (%u) %s\n", method_name, sip->sip_cseq->
cs_seq, "PRACK processed by default callback, too")) : (void)
0)
11501 method_name, sip->sip_cseq->cs_seq,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11502, "nta: %s (%u) %s\n", method_name, sip->sip_cseq->
cs_seq, "PRACK processed by default callback, too")) : (void)
0)
11502 "PRACK processed by default callback, too"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11502, "nta: %s (%u) %s\n", method_name, sip->sip_cseq->
cs_seq, "PRACK processed by default callback, too")) : (void)
0)
;
11503 retval = leg->leg_callback(leg->leg_magic, leg, irq, sip);
11504 }
11505 else {
11506 retval = 500;
11507 }
11508
11509 nta_reliable_destroy(rel);
11510
11511 return retval;
11512}
11513#endif
11514
11515/** Destroy a reliable response.
11516 *
11517 * Mark a reliable response object for destroyal and free it if possible.
11518 */
11519void nta_reliable_destroy(nta_reliable_t *rel)
11520{
11521 if (rel == NULL((void*)0) || rel == NONE((void *)-1))
11522 return;
11523
11524 if (rel->rel_callback == nta_reliable_destroyed)
11525 SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "already destroyed"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11525, "%s(%p): %s\n", __func__, (void *)rel, "already destroyed"
)) : (void)0)
;
11526
11527 rel->rel_callback = nta_reliable_destroyed;
11528
11529 if (rel->rel_response)
11530 return;
11531
11532 nta_reliable_destroyed(NULL((void*)0), rel, NULL((void*)0), NULL((void*)0));
11533}
11534
11535/** Free and unallocate the nta_reliable_t structure. */
11536static
11537int nta_reliable_destroyed(nta_reliable_magic_t *rmagic,
11538 nta_reliable_t *rel,
11539 nta_incoming_t *prack,
11540 sip_t const *sip)
11541{
11542 nta_reliable_t **prev;
11543
11544 assert(rel)((void) sizeof ((rel) ? 1 : 0), __extension__ ({ if (rel) ; else
__assert_fail ("rel", "nta.c", 11544, __extension__ __PRETTY_FUNCTION__
); }))
; assert(rel->rel_irq)((void) sizeof ((rel->rel_irq) ? 1 : 0), __extension__ ({ if
(rel->rel_irq) ; else __assert_fail ("rel->rel_irq", "nta.c"
, 11544, __extension__ __PRETTY_FUNCTION__); }))
;
11545
11546 for (prev = &rel->rel_irq->irq_reliable; *prev; prev = &(*prev)->rel_next)
11547 if (*prev == rel)
11548 break;
11549
11550 if (!*prev) {
11551 assert(*prev)((void) sizeof ((*prev) ? 1 : 0), __extension__ ({ if (*prev)
; else __assert_fail ("*prev", "nta.c", 11551, __extension__
__PRETTY_FUNCTION__); }))
;
11552 SU_DEBUG_1(("%s(%p): %s\n", __func__, (void *)rel, "not linked"))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11552, "%s(%p): %s\n", __func__, (void *)rel, "not linked")
) : (void)0)
;
11553 return 200;
11554 }
11555
11556 *prev = rel->rel_next;
11557
11558 if (rel->rel_unsent)
11559 msg_destroy(rel->rel_unsent), rel->rel_unsent = NULL((void*)0);
11560
11561 su_free(rel->rel_irq->irq_agent->sa_home, rel);
11562
11563 return 200;
11564}
11565
11566/** Validate a reliable response. */
11567int outgoing_recv_reliable(nta_outgoing_t *orq,
11568 msg_t *msg,
11569 sip_t *sip)
11570{
11571 short status = sip->sip_status->st_status;
11572 char const *phrase = sip->sip_status->st_phrase;
11573 uint32_t rseq = sip->sip_rseq->rs_response;
11574
11575 SU_DEBUG_7(("nta: %03u %s is reliably received with RSeq: %u\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 11576, "nta: %03u %s is reliably received with RSeq: %u\n",
status, phrase, rseq)) : (void)0)
11576 status, phrase, rseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 7 ? (_su_llog(nta_log, 7, "nta.c", (const char *)__func__
, 11576, "nta: %03u %s is reliably received with RSeq: %u\n",
status, phrase, rseq)) : (void)0)
;
11577
11578 /* Cannot handle reliable responses unless we have a full dialog */
11579 if (orq->orq_rseq == 0 && !orq->orq_to->a_tag) {
11580 SU_DEBUG_5(("nta: %03u %s with initial RSeq: %u outside dialog\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11581, "nta: %03u %s with initial RSeq: %u outside dialog\n"
, status, phrase, rseq)) : (void)0)
11581 status, phrase, rseq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 5 ? (_su_llog(nta_log, 5, "nta.c", (const char *)__func__
, 11581, "nta: %03u %s with initial RSeq: %u outside dialog\n"
, status, phrase, rseq)) : (void)0)
;
11582 return 0;
11583 }
11584
11585 if (rseq <= orq->orq_rseq) {
11586 SU_DEBUG_3(("nta: %03u %s already received (RSeq: %u, expecting %u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11587, "nta: %03u %s already received (RSeq: %u, expecting %u)\n"
, status, phrase, rseq, orq->orq_rseq + 1)) : (void)0)
11587 status, phrase, rseq, orq->orq_rseq + 1))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11587, "nta: %03u %s already received (RSeq: %u, expecting %u)\n"
, status, phrase, rseq, orq->orq_rseq + 1)) : (void)0)
;
11588 return -1;
11589 }
11590
11591 if (orq->orq_rseq && orq->orq_rseq + 1 != rseq) {
11592 SU_DEBUG_3(("nta: %03d %s is not expected (RSeq: %u, expecting %u)\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11594, "nta: %03d %s is not expected (RSeq: %u, expecting %u)\n"
, status, sip->sip_status->st_phrase, rseq, orq->orq_rseq
+ 1)) : (void)0)
11593 status, sip->sip_status->st_phrase,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11594, "nta: %03d %s is not expected (RSeq: %u, expecting %u)\n"
, status, sip->sip_status->st_phrase, rseq, orq->orq_rseq
+ 1)) : (void)0)
11594 rseq, orq->orq_rseq + 1))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 3 ? (_su_llog(nta_log, 3, "nta.c", (const char *)__func__
, 11594, "nta: %03d %s is not expected (RSeq: %u, expecting %u)\n"
, status, sip->sip_status->st_phrase, rseq, orq->orq_rseq
+ 1)) : (void)0)
;
11595 return -1;
11596 }
11597
11598 return 0;
11599}
11600
11601/** Create a tagged fork of outgoing request.
11602 *
11603 * When a dialog-creating INVITE request is forked, each response from
11604 * diffent fork will create an early dialog with a distinct tag in @To
11605 * header. When each fork should be handled separately, a tagged INVITE
11606 * request can be used. It will only receive responses from the specified
11607 * fork. Please note that the tagged transaction should be terminated with
11608 * the final response from another fork, too.
11609 *
11610 * @param orq
11611 * @param callback
11612 * @param magic
11613 * @param to_tag
11614 * @param rseq
11615 *
11616 * @bug Fix the memory leak - either one of the requests is left unreleased
11617 * for ever.
11618 */
11619nta_outgoing_t *nta_outgoing_tagged(nta_outgoing_t *orq,
11620 nta_response_f *callback,
11621 nta_outgoing_magic_t *magic,
11622 char const *to_tag,
11623 sip_rseq_t const *rseq)
11624{
11625 nta_agent_t *agent;
11626 su_home_t *home;
11627 nta_outgoing_t *tagged;
11628 sip_to_t *to;
11629
11630 if (orq == NULL((void*)0) || to_tag == NULL((void*)0))
11631 return NULL((void*)0);
11632
11633 if (orq->orq_to->a_tag) {
11634 SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) already in dialog\n", __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11635, "%s: transaction %p (CSeq: %s %u) already in dialog\n"
, __func__, (void *)orq, orq->orq_cseq->cs_method_name,
orq->orq_cseq->cs_seq)) : (void)0)
11635 (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11635, "%s: transaction %p (CSeq: %s %u) already in dialog\n"
, __func__, (void *)orq, orq->orq_cseq->cs_method_name,
orq->orq_cseq->cs_seq)) : (void)0)
;
11636 return NULL((void*)0);
11637 }
11638 if (orq->orq_method != sip_method_invite) {
11639 SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) cannot be tagged\n", __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11640, "%s: transaction %p (CSeq: %s %u) cannot be tagged\n"
, __func__, (void *)orq, orq->orq_cseq->cs_method_name,
orq->orq_cseq->cs_seq)) : (void)0)
11640 (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11640, "%s: transaction %p (CSeq: %s %u) cannot be tagged\n"
, __func__, (void *)orq, orq->orq_cseq->cs_method_name,
orq->orq_cseq->cs_seq)) : (void)0)
;
11641 return NULL((void*)0);
11642 }
11643 if (orq->orq_status < 100) {
11644 SU_DEBUG_1(("%s: transaction %p (CSeq: %s %u) still calling\n", __func__,(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11645, "%s: transaction %p (CSeq: %s %u) still calling\n", __func__
, (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq
->cs_seq)) : (void)0)
11645 (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq->cs_seq))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11645, "%s: transaction %p (CSeq: %s %u) still calling\n", __func__
, (void *)orq, orq->orq_cseq->cs_method_name, orq->orq_cseq
->cs_seq)) : (void)0)
;
11646 return NULL((void*)0);
11647 }
11648
11649 assert(orq->orq_agent)((void) sizeof ((orq->orq_agent) ? 1 : 0), __extension__ (
{ if (orq->orq_agent) ; else __assert_fail ("orq->orq_agent"
, "nta.c", 11649, __extension__ __PRETTY_FUNCTION__); }))
; assert(orq->orq_request)((void) sizeof ((orq->orq_request) ? 1 : 0), __extension__
({ if (orq->orq_request) ; else __assert_fail ("orq->orq_request"
, "nta.c", 11649, __extension__ __PRETTY_FUNCTION__); }))
;
11650
11651 agent = orq->orq_agent;
11652 tagged = su_zalloc(agent->sa_home, sizeof(*tagged));
11653
11654 home = msg_home((msg_t *)orq->orq_request)((su_home_t*)((msg_t *)orq->orq_request));
11655
11656 tagged->orq_hash = orq->orq_hash;
11657 tagged->orq_agent = orq->orq_agent;
11658 tagged->orq_callback = callback;
11659 tagged->orq_magic = magic;
11660
11661 tagged->orq_method = orq->orq_method;
11662 tagged->orq_method_name = orq->orq_method_name;
11663 tagged->orq_url = orq->orq_url;
11664 tagged->orq_from = orq->orq_from;
11665
11666 sip_to_tag(home, to = sip_to_copy(home, orq->orq_to), to_tag);
11667
11668 tagged->orq_to = to;
11669 tagged->orq_tag = to->a_tag;
11670 tagged->orq_cseq = orq->orq_cseq;
11671 tagged->orq_call_id = orq->orq_call_id;
11672
11673 tagged->orq_request = msg_ref_create(orq->orq_request);
11674 tagged->orq_response = msg_ref_create(orq->orq_response);
11675
11676 tagged->orq_status = orq->orq_status;
11677 tagged->orq_via_added = orq->orq_via_added;
11678 tagged->orq_prepared = orq->orq_prepared;
11679 tagged->orq_reliable = orq->orq_reliable;
11680 tagged->orq_sips = orq->orq_sips;
11681 tagged->orq_uas = orq->orq_uas;
11682 tagged->orq_pass_100 = orq->orq_pass_100;
11683 tagged->orq_must_100rel = orq->orq_must_100rel;
11684 tagged->orq_100rel = orq->orq_100rel;
11685 tagged->orq_route = orq->orq_route;
11686 *tagged->orq_tpn = *orq->orq_tpn;
11687 tagged->orq_tport = tport_ref(orq->orq_tport);
11688 if (orq->orq_cc)
11689 tagged->orq_cc = nta_compartment_ref(orq->orq_cc);
11690 tagged->orq_branch = orq->orq_branch;
11691 tagged->orq_via_branch = orq->orq_via_branch;
11692
11693 if (tagged->orq_uas) {
11694 tagged->orq_forking = orq;
11695 tagged->orq_forks = orq->orq_forks;
11696 tagged->orq_forked = 1;
11697 orq->orq_forks = tagged;
11698 }
11699
11700 outgoing_insert(agent, tagged);
11701
11702 return tagged;
11703}
11704
11705/**PRACK a provisional response.
11706 *
11707 * Create and send a PRACK request used to acknowledge a provisional
11708 * response.
11709 *
11710 * The request is sent using the route of the original request @a oorq.
11711 *
11712 * When NTA receives response to the prack request, it invokes the @a
11713 * callback function.
11714 *
11715 * @param leg dialog object
11716 * @param oorq original transaction request
11717 * @param callback callback function (may be @c NULL)
11718 * @param magic application context pointer
11719 * @param route_url optional URL used to route transaction requests
11720 * @param resp (optional) response message to be acknowledged
11721 * @param tag,value,... optional
11722 *
11723 * @return
11724 * If successful, return a pointer to newly created client transaction
11725 * object for PRACK request, NULL otherwise.
11726 *
11727 * @sa
11728 * nta_outgoing_tcreate(), nta_outgoing_tcancel(), nta_outgoing_destroy().
11729 */
11730nta_outgoing_t *nta_outgoing_prack(nta_leg_t *leg,
11731 nta_outgoing_t *oorq,
11732 nta_response_f *callback,
11733 nta_outgoing_magic_t *magic,
11734 url_string_t const *route_url,
11735 sip_t const *resp,
11736 tag_type_t tag, tag_value_t value, ...)
11737{
11738 ta_list ta;
11739 msg_t *msg;
11740 su_home_t *home;
11741 sip_t *sip;
11742 sip_to_t const *to = NULL((void*)0);
11743 sip_route_t *route = NULL((void*)0), r0[1];
11744 nta_outgoing_t *orq = NULL((void*)0);
11745 sip_rack_t *rack = NULL((void*)0), rack0[1];
11746
11747 if (!leg || !oorq) {
11748 SU_DEBUG_1(("%s: invalid arguments\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11748, "%s: invalid arguments\n", __func__)) : (void)0)
;
11749 return NULL((void*)0);
11750 }
11751
11752 sip_rack_init(rack0);
11753
11754 if (resp) {
11755 if (!resp->sip_status) {
11756 SU_DEBUG_1(("%s: invalid arguments\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11756, "%s: invalid arguments\n", __func__)) : (void)0)
;
11757 return NULL((void*)0);
11758 }
11759
11760 if (resp->sip_status->st_status <= 100 ||
11761 resp->sip_status->st_status >= 200) {
11762 SU_DEBUG_1(("%s: %u response cannot be PRACKed\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11763, "%s: %u response cannot be PRACKed\n", __func__, resp
->sip_status->st_status)) : (void)0)
11763 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11763, "%s: %u response cannot be PRACKed\n", __func__, resp
->sip_status->st_status)) : (void)0)
;
11764 return NULL((void*)0);
11765 }
11766
11767 if (!resp->sip_rseq) {
11768 SU_DEBUG_1(("%s: %u response missing RSeq\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11769, "%s: %u response missing RSeq\n", __func__, resp->
sip_status->st_status)) : (void)0)
11769 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11769, "%s: %u response missing RSeq\n", __func__, resp->
sip_status->st_status)) : (void)0)
;
11770 return NULL((void*)0);
11771 }
11772
11773 if (resp->sip_rseq->rs_response <= oorq->orq_rseq) {
11774 SU_DEBUG_1(("%s: %u response RSeq does not match received RSeq\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11775, "%s: %u response RSeq does not match received RSeq\n"
, __func__, resp->sip_status->st_status)) : (void)0)
11775 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11775, "%s: %u response RSeq does not match received RSeq\n"
, __func__, resp->sip_status->st_status)) : (void)0)
;
11776 return NULL((void*)0);
11777 }
11778 if (!oorq->orq_must_100rel &&
11779 !sip_has_feature(resp->sip_require, "100rel")) {
11780 SU_DEBUG_1(("%s: %u response does not require 100rel\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11781, "%s: %u response does not require 100rel\n", __func__
, resp->sip_status->st_status)) : (void)0)
11781 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11781, "%s: %u response does not require 100rel\n", __func__
, resp->sip_status->st_status)) : (void)0)
;
11782 return NULL((void*)0);
11783 }
11784
11785 if (!resp->sip_to->a_tag) {
11786 SU_DEBUG_1(("%s: %u response has no To tag\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11787, "%s: %u response has no To tag\n", __func__, resp->
sip_status->st_status)) : (void)0)
11787 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11787, "%s: %u response has no To tag\n", __func__, resp->
sip_status->st_status)) : (void)0)
;
11788 return NULL((void*)0);
11789 }
11790 if (su_strcasecmp(resp->sip_to->a_tag, leg->leg_remote->a_tag) ||
11791 su_strcasecmp(resp->sip_to->a_tag, oorq->orq_to->a_tag)) {
11792 SU_DEBUG_1(("%s: %u response To tag does not agree with dialog tag\n",(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11793, "%s: %u response To tag does not agree with dialog tag\n"
, __func__, resp->sip_status->st_status)) : (void)0)
11793 __func__, resp->sip_status->st_status))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11793, "%s: %u response To tag does not agree with dialog tag\n"
, __func__, resp->sip_status->st_status)) : (void)0)
;
11794 return NULL((void*)0);
11795 }
11796
11797 to = resp->sip_to;
11798 rack = rack0;
11799
11800 rack->ra_response = resp->sip_rseq->rs_response;
11801 rack->ra_cseq = resp->sip_cseq->cs_seq;
11802 rack->ra_method = resp->sip_cseq->cs_method;
11803 rack->ra_method_name = resp->sip_cseq->cs_method_name;
11804 }
11805
11806 msg = nta_msg_create(leg->leg_agent, 0);
11807 sip = sip_object(msg); home = msg_home(msg)((su_home_t*)(msg));
11808
11809 if (!sip)
11810 return NULL((void*)0);
11811
11812 if (!leg->leg_route && resp) {
11813 /* Insert contact into route */
11814 if (resp->sip_contact) {
11815 sip_route_init(r0)->r_url[0] = resp->sip_contact->m_url[0];
11816 route = sip_route_dup(home, r0);
11817 }
11818
11819 /* Reverse record route */
11820 if (resp->sip_record_route) {
11821 sip_route_t *r, *r_next;
11822 for (r = sip_route_dup(home, resp->sip_record_route); r; r = r_next) {
11823 r_next = r->r_next, r->r_next = route, route = r;
11824 }
11825 }
11826 }
11827
11828 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
11829
11830 if (!resp) {
11831 tagi_t const *t;
11832
11833 if ((t = tl_find(ta_args(ta)(ta).tl, ntatag_rseq)) && t->t_value) {
11834 rack = rack0;
11835 rack->ra_response = (uint32_t)t->t_value;
11836 }
11837
11838 if (rack) {
11839 rack->ra_cseq = oorq->orq_cseq->cs_seq;
11840 rack->ra_method = oorq->orq_cseq->cs_method;
11841 rack->ra_method_name = oorq->orq_cseq->cs_method_name;
11842 }
11843 }
11844
11845 if (sip_add_tl(msg, sip,
11846 TAG_IF(rack, SIPTAG_RACK(rack))!(rack) ? tag_skip : siptag_rack, siptag_rack_v(rack),
11847 TAG_IF(to, SIPTAG_TO(to))!(to) ? tag_skip : siptag_to, siptag_to_v(to),
11848 ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
) < 0)
11849 ;
11850 else if (route && sip_add_dup(msg, sip, (sip_header_t *)route) < 0)
11851 ;
11852 else if (!sip->sip_rack)
11853 SU_DEBUG_1(("%s: RAck header missing\n", __func__))(((nta_log != ((void*)0) && nta_log->log_init) == 0
? 9 : ((nta_log != ((void*)0) && nta_log->log_init
> 1) ? nta_log->log_level : su_log_default->log_level
)) >= 1 ? (_su_llog(nta_log, 1, "nta.c", (const char *)__func__
, 11853, "%s: RAck header missing\n", __func__)) : (void)0)
;
11854 else if (nta_msg_request_complete(msg, leg,
11855 SIP_METHOD_PRACKsip_method_prack, "PRACK",
11856 (url_string_t *)oorq->orq_url) < 0)
11857 ;
11858 else
11859 orq = outgoing_create(leg->leg_agent, callback, magic,
11860 route_url, NULL((void*)0), msg, ta_tags(ta)(ta).tl[0].t_tag, (ta).tl[0].t_value, (ta).tl[1].t_tag, (ta).
tl[1].t_value
);
11861
11862 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
11863
11864 if (!orq)
11865 msg_destroy(msg);
11866 else if (rack)
11867 oorq->orq_rseq = rack->ra_response;
11868 else if (sip->sip_rack)
11869 oorq->orq_rseq = sip->sip_rack->ra_response;
11870
11871 return orq;
11872}
11873
11874/** Get @RSeq value stored with client transaction. */
11875uint32_t nta_outgoing_rseq(nta_outgoing_t const *orq)
11876{
11877 return orq ? orq->orq_rseq : 0;
11878}
11879
11880/** Set @RSeq value stored with client transaction.
11881 *
11882 * @return 0 if rseq was set successfully
11883 * @return -1 if rseq is invalid or orq is NULL.
11884 */
11885int nta_outgoing_setrseq(nta_outgoing_t *orq, uint32_t rseq)
11886{
11887 if (orq && orq->orq_rseq <= rseq) {
11888 orq->orq_rseq = rseq;
11889 return 0;
11890 }
11891
11892 return -1;
11893}
11894
11895/* ------------------------------------------------------------------------ */
11896/* 11) SigComp handling and public transport interface */
11897
11898#include <sofia-sip/nta_tport.h>
11899
11900/** Return the master transport for the agent.
11901 *
11902 * @NEW_1_12_11
11903 */
11904tport_t *
11905nta_agent_tports(nta_agent_t *agent)
11906{
11907 return agent ? agent->sa_tports : NULL((void*)0);
11908}
11909
11910su_inlinestatic inline tport_t *
11911nta_transport_(nta_agent_t *agent,
11912 nta_incoming_t *irq,
11913 msg_t *msg)
11914{
11915 if (irq)
11916 return irq->irq_tport;
11917 else if (agent && msg)
11918 return tport_delivered_by(agent->sa_tports, msg);
11919
11920 errno(*__errno_location ()) = EINVAL22;
11921 return NULL((void*)0);
11922}
11923
11924
11925/** Return a new reference to the transaction transport.
11926 *
11927 * @note The referenced transport must be unreferenced with tport_unref()
11928 */
11929tport_t *
11930nta_incoming_transport(nta_agent_t *agent,
11931 nta_incoming_t *irq,
11932 msg_t *msg)
11933{
11934 return tport_ref(nta_transport_(agent, irq, msg));
11935}
11936
11937nta_compressor_t *nta_agent_init_sigcomp(nta_agent_t *sa)
11938{
11939 if (!nta_compressor_vtable || !sa)
11940 return NULL((void*)0);
11941
11942 if (sa->sa_compressor == NULL((void*)0)) {
11943 char const * const *l = sa->sa_sigcomp_option_list;
11944 nta_compressor_t *comp;
11945 comp = nta_compressor_vtable->ncv_init_agent(sa, l);
11946 sa->sa_compressor = comp;
11947 }
11948
11949 return sa->sa_compressor;
11950}
11951
11952void nta_agent_deinit_sigcomp(nta_agent_t *sa)
11953{
11954 if (nta_compressor_vtable && sa && sa->sa_compressor) {
11955 nta_compressor_vtable->ncv_deinit_agent(sa, sa->sa_compressor);
11956 sa->sa_compressor = NULL((void*)0);
11957 }
11958}
11959
11960struct sigcomp_compartment *
11961nta_incoming_compartment(nta_incoming_t *irq)
11962{
11963 if (nta_compressor_vtable && irq && irq->irq_cc)
11964 return nta_compressor_vtable->ncv_compartment_ref(irq->irq_cc);
11965 else
11966 return NULL((void*)0);
11967}
11968
11969tport_t *
11970nta_outgoing_transport(nta_outgoing_t *orq)
11971{
11972 if (orq)
11973 return tport_ref(orq->orq_tport);
11974 else
11975 return NULL((void*)0);
11976}
11977
11978
11979struct sigcomp_compartment *
11980nta_outgoing_compartment(nta_outgoing_t *orq)
11981{
11982 if (nta_compressor_vtable && orq && orq->orq_cc)
11983 return nta_compressor_vtable->ncv_compartment_ref(orq->orq_cc);
11984 else
11985 return NULL((void*)0);
11986}
11987
11988
11989struct sigcomp_compartment *
11990nta_compartment_ref(struct sigcomp_compartment *cc)
11991{
11992 if (nta_compressor_vtable)
11993 return nta_compressor_vtable->ncv_compartment_ref(cc);
11994 else
11995 return NULL((void*)0);
11996}
11997
11998void
11999nta_compartment_decref(struct sigcomp_compartment **pcc)
12000{
12001 if (nta_compressor_vtable && pcc && *pcc)
12002 nta_compressor_vtable->ncv_compartment_unref(*pcc), *pcc = NULL((void*)0);
12003}
12004
12005
12006/** Get compartment for connection, create it when needed. */
12007static
12008struct sigcomp_compartment *
12009agent_compression_compartment(nta_agent_t *sa,
12010 tport_t *tp,
12011 tp_name_t const *tpn,
12012 int new_if_needed)
12013{
12014 if (nta_compressor_vtable) {
12015 char const * const *l = sa->sa_sigcomp_option_list;
12016 return nta_compressor_vtable->
12017 ncv_compartment(sa, tp, sa->sa_compressor, tpn, l, new_if_needed);
12018 }
12019 else
12020 return NULL((void*)0);
12021}
12022
12023static
12024int agent_accept_compressed(nta_agent_t *sa, msg_t *msg,
12025 struct sigcomp_compartment *cc)
12026{
12027 if (nta_compressor_vtable) {
12028 nta_compressor_t *msc = sa->sa_compressor;
12029 tport_compressor_t *sc = NULL((void*)0);
12030 if (tport_delivered_with_comp(sa->sa_tports, msg, &sc) < 0)
12031 return 0;
12032 return nta_compressor_vtable->ncv_accept_compressed(sa, msc, sc, msg, cc);
12033 }
12034 else
12035 return 0;
12036}
12037
12038/** Close compressor (lose its state). */
12039static
12040int agent_close_compressor(nta_agent_t *sa,
12041 struct sigcomp_compartment *cc)
12042{
12043 if (nta_compressor_vtable)
12044 return nta_compressor_vtable->ncv_close_compressor(sa, cc);
12045 return 0;
12046}
12047
12048/** Close both compressor and decompressor */
12049static
12050int agent_zap_compressor(nta_agent_t *sa,
12051 struct sigcomp_compartment *cc)
12052{
12053 if (nta_compressor_vtable)
12054 return nta_compressor_vtable->ncv_zap_compressor(sa, cc);
12055 return 0;
12056}
12057
12058/** Bind transport update callback */
12059int nta_agent_bind_tport_update(nta_agent_t *agent,
12060 nta_update_magic_t *magic,
12061 nta_update_tport_f *callback)
12062{
12063 if (!agent)
12064 return su_seterrno(EFAULT14), -1;
12065 agent->sa_update_magic = magic;
12066 agent->sa_update_tport = callback;
12067 return 0;
12068}
12069
12070/** Bind transport error callback */
12071int nta_agent_bind_tport_error(nta_agent_t *agent,
12072 nta_error_magic_t *magic,
12073 nta_error_tport_f *callback)
12074{
12075 if (!agent)
12076 return su_seterrno(EFAULT14), -1;
12077 agent->sa_error_magic = magic;
12078 agent->sa_error_tport = callback;
12079 return 0;
12080}
12081
12082/** Check if public transport binding is in progress */
12083int nta_agent_tport_is_updating(nta_agent_t *agent)
12084{
12085 return agent && tport_is_updating(agent->sa_tports);
12086}
12087
12088/** Initiate STUN keepalive controller to TPORT */
12089int nta_tport_keepalive(nta_outgoing_t *orq)
12090{
12091 assert(orq)((void) sizeof ((orq) ? 1 : 0), __extension__ ({ if (orq) ; else
__assert_fail ("orq", "nta.c", 12091, __extension__ __PRETTY_FUNCTION__
); }))
;
12092
12093#if HAVE_SOFIA_STUN
12094 return tport_keepalive(orq->orq_tport, msg_addrinfo(orq->orq_request),
12095 TAG_END()(tag_type_t)0, (tag_value_t)0);
12096#else
12097 return -1;
12098#endif
12099}
12100
12101/** Close all transports. @since Experimental in @VERSION_1_12_2. */
12102int nta_agent_close_tports(nta_agent_t *agent)
12103{
12104 size_t i;
12105 outgoing_htable_t *oht = agent->sa_outgoing;
12106 incoming_htable_t *iht = agent->sa_incoming;
12107
12108 for (i = oht->oht_size; i-- > 0;)
12109 /* while */ if (oht->oht_table[i]) {
12110 nta_outgoing_t *orq = oht->oht_table[i];
12111
12112 if (orq->orq_pending && orq->orq_tport)
12113 tport_release(orq->orq_tport, orq->orq_pending, orq->orq_request,
12114 NULL((void*)0), orq, 0);
12115
12116 orq->orq_pending = 0;
12117 tport_unref(orq->orq_tport), orq->orq_tport = NULL((void*)0);
12118 }
12119
12120
12121 for (i = iht->iht_size; i-- > 0;)
12122 /* while */ if (iht->iht_table[i]) {
12123 nta_incoming_t *irq = iht->iht_table[i];
12124 tport_unref(irq->irq_tport), irq->irq_tport = NULL((void*)0);
12125 }
12126
12127 tport_destroy(agent->sa_tports), agent->sa_tports = NULL((void*)0);
12128
12129 msg_header_free(agent->sa_home, (void *)agent->sa_vias);
12130 agent->sa_vias = NULL((void*)0);
12131 msg_header_free(agent->sa_home, (void *)agent->sa_public_vias);
12132 agent->sa_public_vias = NULL((void*)0);
12133
12134 return 0;
12135}

./../sip/sofia-sip/sip_protos.h

1/* -*- C -*-
2 *
3 * This file is part of the Sofia-SIP package
4 *
5 * Copyright (C) 2005 Nokia Corporation.
6 *
7 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 *
24 */
25
26#ifndef SIP_PROTOS_H
27/** Defined when <sofia-sip/sip_protos.h> has been included. */
28#define SIP_PROTOS_H
29
30/**@file sofia-sip/sip_protos.h
31 *
32 * SIP prototypes and macros for each header.
33 *
34 * This file is automatically generated from <sip.h> by msg_parser.awk.
35 *
36 * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
37 *
38 */
39
40#include <sofia-sip/su_config.h>
41
42#ifndef SIP_HEADER_H
43#include <sofia-sip/sip_header.h>
44#endif
45
46#ifndef SIP_HCLASSES_H
47#include <sofia-sip/sip_hclasses.h>
48#endif
49
50SOFIA_BEGIN_DECLS
51
52#if SU_HAVE_INLINE1
53/** Get SIP structure from msg. */
54su_inlinestatic inline
55sip_t *sip_object(msg_t const *msg)
56{
57 return (sip_t *)msg_public(msg, SIP_PROTOCOL_TAG((void *)0x53495020));
58}
59
60/** Insert a (list of) header(s) to the header structure and fragment chain.
61 *
62 * The function @c sip_header_insert() inserts header or list of headers
63 * into a SIP message. It also inserts them into the the message fragment
64 * chain, if it exists.
65 *
66 * When inserting headers into the fragment chain, a request (or status) is
67 * inserted first and replaces the existing request (or status). The Via
68 * headers are inserted after the request or status, and rest of the headers
69 * after request, status, or Via headers.
70 *
71 * If the header is a singleton, existing headers with the same class are
72 * removed.
73 *
74 * @param msg message owning the fragment chain
75 * @param sip SIP message structure to which header is added
76 * @param h list of header(s) to be added
77 */
78su_inlinestatic inline
79int sip_header_insert(msg_t *msg, sip_t *sip, sip_header_t *h)
80{
81 return msg_header_insert(msg, (msg_pub_t *)sip, (msg_header_t *)h);
82}
83
84/** Remove a header from a SIP message. */
85su_inlinestatic inline
86int sip_header_remove(msg_t *msg, sip_t *sip, sip_header_t *h)
87{
88 return msg_header_remove(msg, (msg_pub_t *)sip, (msg_header_t *)h);
89}
90
91/** Return name of the header. */
92su_inlinestatic inline
93char const *sip_header_name(sip_header_t const *h, int compact)
94{
95 if (compact && h->sh_classsh_common->h_class->hc_short[0])
96 return h->sh_classsh_common->h_class->hc_short;
97 else
98 return h->sh_classsh_common->h_class->hc_name;
99}
100
101/** Return data after header structure. */
102su_inlinestatic inline
103void *sip_header_data(sip_header_t *h)
104{
105 return h && h != SIP_NONE((void const *)-1L) ? h->sh_classsh_common->h_class->hc_size + (char *)h : NULL((void*)0);
106}
107#else
108sip_t *sip_object(msg_t *msg);
109int sip_header_insert(msg_t *msg, sip_t *sip, sip_header_t *h);
110int sip_header_remove(msg_t *msg, sip_t *sip, sip_header_t *h);
111char const *sip_header_name(sip_header_t const *h, int compact);
112void *sip_header_data(sip_header_t *h);
113#endif
114
115/**@addtogroup sip_request
116 * @{
117 */
118
119/** Parse a SIP @ref sip_request "request line". @internal */
120SOFIAPUBFUN issize_t sip_request_d(su_home_t *, msg_header_t *,
121 char *s, isize_t slen);
122
123/** Print a SIP @ref sip_request "request line". @internal */
124SOFIAPUBFUN issize_t sip_request_e(char b[], isize_t bsiz,
125 msg_header_t const *h, int flags);
126
127/**Access a SIP @ref sip_request "request line"
128 * structure #sip_request_t from #sip_t.
129 *
130 */
131#define sip_request(sip)((sip_request_t *)msg_header_access((msg_pub_t*)(sip), sip_request_class
))
\
132 ((sip_request_t *)msg_header_access((msg_pub_t*)(sip), sip_request_class))
133
134/**Initializer for structure #sip_request_t.
135 *
136 * A static #sip_request_t structure for
137 * @ref sip_request "request line" must be initialized with
138 * the SIP_REQUEST_INIT() macro.
139 * For instance,
140 * @code
141 *
142 * sip_request_t sip_request = SIP_REQUEST_INIT;
143 *
144 * @endcode
145 * @HI
146 *
147 */
148#define SIP_REQUEST_INIT(){{{ 0, 0, sip_request_class }}} SIP_HDR_INIT(request){{{ 0, 0, sip_request_class }}}
149
150/**Initialize a structure #sip_request_t.
151 *
152 * An #sip_request_t structure for
153 * @ref sip_request "request line" can be initialized with the
154 * sip_request_init() function/macro. For instance,
155 * @code
156 *
157 * sip_request_t sip_request;
158 *
159 * sip_request_init(&sip_request);
160 *
161 * @endcode
162 * @HI
163 *
164 */
165#if SU_HAVE_INLINE1
166su_inlinestatic inline sip_request_t *sip_request_init(sip_request_t x[1])
167{
168 return SIP_HEADER_INIT(x, sip_request_class, sizeof(sip_request_t))((void)memset((x), 0, (sizeof(sip_request_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_request_class)), (x))
;
169}
170#else
171#define sip_request_init(x) \
172 SIP_HEADER_INIT(x, sip_request_class, sizeof(sip_request_t))((void)memset((x), 0, (sizeof(sip_request_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_request_class)), (x))
173#endif
174
175/**Test if header object is instance of #sip_request_t.
176 *
177 * Check if the header class is an instance of
178 * @ref sip_request "request line" object and return true (nonzero),
179 * otherwise return false (zero).
180 *
181 * @param header pointer to the header structure to be tested
182 *
183 * @retval 1 (true) if the @a header is an instance of header request
184 * @retval 0 (false) otherwise
185 *
186 */
187#if SU_HAVE_INLINE1
188su_inlinestatic inline int sip_is_request(sip_header_t const *header)
189{
190 return header && header->sh_classsh_common->h_class->hc_hash == sip_request_hash;
191}
192#else
193int sip_is_request(sip_header_t const *header);
194#endif
195
196#define sip_request_p(h)sip_is_request((h)) sip_is_request((h))
197
198
199/**Duplicate a list of @ref sip_request "request line" header structures #sip_request_t.
200 *
201 * Duplicate a header
202 * structure @a hdr. If the header structure @a hdr
203 * contains a reference (@c hdr->x_next) to a list of
204 * headers, all the headers in the list are duplicated, too.
205 *
206 * @param home memory home used to allocate new structure
207 * @param hdr header structure to be duplicated
208 *
209 * When duplicating, all parameter lists and non-constant
210 * strings attached to the header are copied, too. The
211 * function uses given memory @a home to allocate all the
212 * memory areas used to copy the header.
213 *
214 * @par Example
215 * @code
216 *
217 * request = sip_request_dup(home, sip->sip_request);
218 *
219 * @endcode
220 *
221 * @return
222 * A pointer to the
223 * newly duplicated #sip_request_t header structure, or NULL
224 * upon an error.
225 *
226 */
227#if SU_HAVE_INLINE1
228su_inlinestatic inline
229#endif
230sip_request_t *sip_request_dup(su_home_t *home, sip_request_t const *hdr)
231 __attribute__((__malloc__));
232
233#if SU_HAVE_INLINE1
234su_inlinestatic inline
235sip_request_t *sip_request_dup(su_home_t *home, sip_request_t const *hdr)
236{
237 return (sip_request_t *)
238 msg_header_dup_as(home, sip_request_class, (msg_header_t const *)hdr);
239}
240#endif
241
242/**Copy a list of @ref sip_request "request line" header structures #sip_request_t.
243 *
244 * The function sip_request_copy() copies a header structure @a
245 * hdr. If the header structure @a hdr contains a reference (@c
246 * hdr->h_next) to a list of headers, all the headers in that
247 * list are copied, too. The function uses given memory @a home
248 * to allocate all the memory areas used to copy the list of header
249 * structure @a hdr.
250 *
251 * @param home memory home used to allocate new structure
252 * @param hdr pointer to the header structure to be copied
253 *
254 * When copying, only the header structure and parameter lists attached to
255 * it are duplicated. The new header structure retains all the references to
256 * the strings within the old @a hdr header, including the encoding of the
257 * old header, if present.
258 *
259 * @par Example
260 * @code
261 *
262 * request = sip_request_copy(home, sip->sip_request);
263 *
264 * @endcode
265 *
266 * @return
267 * A pointer to newly copied header structure, or NULL upon an error.
268 *
269 */
270#if SU_HAVE_INLINE1
271su_inlinestatic inline
272#endif
273sip_request_t *sip_request_copy(su_home_t *home, sip_request_t const *hdr)
274 __attribute__((__malloc__));
275
276#if SU_HAVE_INLINE1
277su_inlinestatic inline
278sip_request_t *sip_request_copy(su_home_t *home, sip_request_t const *hdr)
279{
280 return (sip_request_t *)
281 msg_header_copy_as(home, sip_request_class, (msg_header_t const *)hdr);
282}
283#endif
284
285/**Make a @ref sip_request "request line" structure #sip_request_t.
286 *
287 * The function sip_request_make() makes a new
288 * #sip_request_t header structure. It allocates a new
289 * header structure, and decodes the string @a s as the
290 * value of the structure.
291 *
292 * @param home memory home used to allocate new header structure.
293 * @param s string to be decoded as value of the new header structure
294 *
295 * @return
296 * A pointer to newly maked #sip_request_t header structure, or NULL upon an
297 * error.
298 *
299 */
300#if SU_HAVE_INLINE1
301su_inlinestatic inline
302#endif
303sip_request_t *sip_request_make(su_home_t *home, char const *s)
304 __attribute__((__malloc__));
305
306#if SU_HAVE_INLINE1
307su_inlinestatic inline sip_request_t *sip_request_make(su_home_t *home, char const *s)
308{
309 return (sip_request_t *)sip_header_make(home, sip_request_class, s)((sip_header_t *)msg_header_make((home), (sip_request_class),
(s)))
;
310}
311#endif
312
313/**Make a @ref sip_request "request line" from formatting result.
314 *
315 * Make a new #sip_request_t object using formatting result as its value.
316 * The function first prints the arguments according to the format @a fmt
317 * specified. Then it allocates a new header structure, and parses the
318 * formatting result to the structure #sip_request_t.
319 *
320 * @param home memory home used to allocate new header structure.
321 * @param fmt string used as a printf()-style format
322 * @param ... argument list for format
323 *
324 * @return
325 * A pointer to newly
326 * makes header structure, or NULL upon an error.
327 *
328 * @HIDE
329 *
330 */
331#if SU_HAVE_INLINE1
332su_inlinestatic inline
333#endif
334sip_request_t *sip_request_format(su_home_t *home, char const *fmt, ...)
335 __attribute__((__malloc__, __format__ (printf, 2, 3)));
336
337#if SU_HAVE_INLINE1
338su_inlinestatic inline sip_request_t *sip_request_format(su_home_t *home, char const *fmt, ...)
339{
340 sip_header_t *h;
341 va_list ap;
342
343 va_start(ap, fmt)__builtin_va_start(ap, fmt);
344 h = sip_header_vformat(home, sip_request_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_request_class
), (fmt), (ap)))
;
345 va_end(ap)__builtin_va_end(ap);
346
347 return (sip_request_t *)h;
348}
349#endif
350
351/** @} */
352
353/**@addtogroup sip_status
354 * @{
355 */
356
357/** Parse a SIP @ref sip_status "status line". @internal */
358SOFIAPUBFUN issize_t sip_status_d(su_home_t *, msg_header_t *,
359 char *s, isize_t slen);
360
361/** Print a SIP @ref sip_status "status line". @internal */
362SOFIAPUBFUN issize_t sip_status_e(char b[], isize_t bsiz,
363 msg_header_t const *h, int flags);
364
365/**Access a SIP @ref sip_status "status line"
366 * structure #sip_status_t from #sip_t.
367 *
368 */
369#define sip_status(sip)((sip_status_t *)msg_header_access((msg_pub_t*)(sip), sip_status_class
))
\
370 ((sip_status_t *)msg_header_access((msg_pub_t*)(sip), sip_status_class))
371
372/**Initializer for structure #sip_status_t.
373 *
374 * A static #sip_status_t structure for
375 * @ref sip_status "status line" must be initialized with
376 * the SIP_STATUS_INIT() macro.
377 * For instance,
378 * @code
379 *
380 * sip_status_t sip_status = SIP_STATUS_INIT;
381 *
382 * @endcode
383 * @HI
384 *
385 */
386#define SIP_STATUS_INIT(){{{ 0, 0, sip_status_class }}} SIP_HDR_INIT(status){{{ 0, 0, sip_status_class }}}
387
388/**Initialize a structure #sip_status_t.
389 *
390 * An #sip_status_t structure for
391 * @ref sip_status "status line" can be initialized with the
392 * sip_status_init() function/macro. For instance,
393 * @code
394 *
395 * sip_status_t sip_status;
396 *
397 * sip_status_init(&sip_status);
398 *
399 * @endcode
400 * @HI
401 *
402 */
403#if SU_HAVE_INLINE1
404su_inlinestatic inline sip_status_t *sip_status_init(sip_status_t x[1])
405{
406 return SIP_HEADER_INIT(x, sip_status_class, sizeof(sip_status_t))((void)memset((x), 0, (sizeof(sip_status_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_status_class)), (x))
;
407}
408#else
409#define sip_status_init(x) \
410 SIP_HEADER_INIT(x, sip_status_class, sizeof(sip_status_t))((void)memset((x), 0, (sizeof(sip_status_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_status_class)), (x))
411#endif
412
413/**Test if header object is instance of #sip_status_t.
414 *
415 * Check if the header class is an instance of
416 * @ref sip_status "status line" object and return true (nonzero),
417 * otherwise return false (zero).
418 *
419 * @param header pointer to the header structure to be tested
420 *
421 * @retval 1 (true) if the @a header is an instance of header status
422 * @retval 0 (false) otherwise
423 *
424 */
425#if SU_HAVE_INLINE1
426su_inlinestatic inline int sip_is_status(sip_header_t const *header)
427{
428 return header && header->sh_classsh_common->h_class->hc_hash == sip_status_hash;
429}
430#else
431int sip_is_status(sip_header_t const *header);
432#endif
433
434#define sip_status_p(h)sip_is_status((h)) sip_is_status((h))
435
436
437/**Duplicate a list of @ref sip_status "status line" header structures #sip_status_t.
438 *
439 * Duplicate a header
440 * structure @a hdr. If the header structure @a hdr
441 * contains a reference (@c hdr->x_next) to a list of
442 * headers, all the headers in the list are duplicated, too.
443 *
444 * @param home memory home used to allocate new structure
445 * @param hdr header structure to be duplicated
446 *
447 * When duplicating, all parameter lists and non-constant
448 * strings attached to the header are copied, too. The
449 * function uses given memory @a home to allocate all the
450 * memory areas used to copy the header.
451 *
452 * @par Example
453 * @code
454 *
455 * status = sip_status_dup(home, sip->sip_status);
456 *
457 * @endcode
458 *
459 * @return
460 * A pointer to the
461 * newly duplicated #sip_status_t header structure, or NULL
462 * upon an error.
463 *
464 */
465#if SU_HAVE_INLINE1
466su_inlinestatic inline
467#endif
468sip_status_t *sip_status_dup(su_home_t *home, sip_status_t const *hdr)
469 __attribute__((__malloc__));
470
471#if SU_HAVE_INLINE1
472su_inlinestatic inline
473sip_status_t *sip_status_dup(su_home_t *home, sip_status_t const *hdr)
474{
475 return (sip_status_t *)
476 msg_header_dup_as(home, sip_status_class, (msg_header_t const *)hdr);
477}
478#endif
479
480/**Copy a list of @ref sip_status "status line" header structures #sip_status_t.
481 *
482 * The function sip_status_copy() copies a header structure @a
483 * hdr. If the header structure @a hdr contains a reference (@c
484 * hdr->h_next) to a list of headers, all the headers in that
485 * list are copied, too. The function uses given memory @a home
486 * to allocate all the memory areas used to copy the list of header
487 * structure @a hdr.
488 *
489 * @param home memory home used to allocate new structure
490 * @param hdr pointer to the header structure to be copied
491 *
492 * When copying, only the header structure and parameter lists attached to
493 * it are duplicated. The new header structure retains all the references to
494 * the strings within the old @a hdr header, including the encoding of the
495 * old header, if present.
496 *
497 * @par Example
498 * @code
499 *
500 * status = sip_status_copy(home, sip->sip_status);
501 *
502 * @endcode
503 *
504 * @return
505 * A pointer to newly copied header structure, or NULL upon an error.
506 *
507 */
508#if SU_HAVE_INLINE1
509su_inlinestatic inline
510#endif
511sip_status_t *sip_status_copy(su_home_t *home, sip_status_t const *hdr)
512 __attribute__((__malloc__));
513
514#if SU_HAVE_INLINE1
515su_inlinestatic inline
516sip_status_t *sip_status_copy(su_home_t *home, sip_status_t const *hdr)
517{
518 return (sip_status_t *)
519 msg_header_copy_as(home, sip_status_class, (msg_header_t const *)hdr);
520}
521#endif
522
523/**Make a @ref sip_status "status line" structure #sip_status_t.
524 *
525 * The function sip_status_make() makes a new
526 * #sip_status_t header structure. It allocates a new
527 * header structure, and decodes the string @a s as the
528 * value of the structure.
529 *
530 * @param home memory home used to allocate new header structure.
531 * @param s string to be decoded as value of the new header structure
532 *
533 * @return
534 * A pointer to newly maked #sip_status_t header structure, or NULL upon an
535 * error.
536 *
537 */
538#if SU_HAVE_INLINE1
539su_inlinestatic inline
540#endif
541sip_status_t *sip_status_make(su_home_t *home, char const *s)
542 __attribute__((__malloc__));
543
544#if SU_HAVE_INLINE1
545su_inlinestatic inline sip_status_t *sip_status_make(su_home_t *home, char const *s)
546{
547 return (sip_status_t *)sip_header_make(home, sip_status_class, s)((sip_header_t *)msg_header_make((home), (sip_status_class), (
s)))
;
548}
549#endif
550
551/**Make a @ref sip_status "status line" from formatting result.
552 *
553 * Make a new #sip_status_t object using formatting result as its value.
554 * The function first prints the arguments according to the format @a fmt
555 * specified. Then it allocates a new header structure, and parses the
556 * formatting result to the structure #sip_status_t.
557 *
558 * @param home memory home used to allocate new header structure.
559 * @param fmt string used as a printf()-style format
560 * @param ... argument list for format
561 *
562 * @return
563 * A pointer to newly
564 * makes header structure, or NULL upon an error.
565 *
566 * @HIDE
567 *
568 */
569#if SU_HAVE_INLINE1
570su_inlinestatic inline
571#endif
572sip_status_t *sip_status_format(su_home_t *home, char const *fmt, ...)
573 __attribute__((__malloc__, __format__ (printf, 2, 3)));
574
575#if SU_HAVE_INLINE1
576su_inlinestatic inline sip_status_t *sip_status_format(su_home_t *home, char const *fmt, ...)
577{
578 sip_header_t *h;
579 va_list ap;
580
581 va_start(ap, fmt)__builtin_va_start(ap, fmt);
582 h = sip_header_vformat(home, sip_status_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_status_class
), (fmt), (ap)))
;
583 va_end(ap)__builtin_va_end(ap);
584
585 return (sip_status_t *)h;
586}
587#endif
588
589/** @} */
590
591/**@addtogroup sip_via
592 * @{
593 */
594
595/** Parse a SIP @ref sip_via "Via header". @internal */
596SOFIAPUBFUN issize_t sip_via_d(su_home_t *, msg_header_t *,
597 char *s, isize_t slen);
598
599/** Print a SIP @ref sip_via "Via header". @internal */
600SOFIAPUBFUN issize_t sip_via_e(char b[], isize_t bsiz,
601 msg_header_t const *h, int flags);
602
603/**Access a SIP @ref sip_via "Via header"
604 * structure #sip_via_t from #sip_t.
605 *
606 */
607#define sip_via(sip)((sip_via_t *)msg_header_access((msg_pub_t*)(sip), sip_via_class
))
\
608 ((sip_via_t *)msg_header_access((msg_pub_t*)(sip), sip_via_class))
609
610/**Initializer for structure #sip_via_t.
611 *
612 * A static #sip_via_t structure for
613 * @ref sip_via "Via header" must be initialized with
614 * the SIP_VIA_INIT() macro.
615 * For instance,
616 * @code
617 *
618 * sip_via_t sip_via = SIP_VIA_INIT;
619 *
620 * @endcode
621 * @HI
622 *
623 */
624#define SIP_VIA_INIT(){{{ 0, 0, sip_via_class }}} SIP_HDR_INIT(via){{{ 0, 0, sip_via_class }}}
625
626/**Initialize a structure #sip_via_t.
627 *
628 * An #sip_via_t structure for
629 * @ref sip_via "Via header" can be initialized with the
630 * sip_via_init() function/macro. For instance,
631 * @code
632 *
633 * sip_via_t sip_via;
634 *
635 * sip_via_init(&sip_via);
636 *
637 * @endcode
638 * @HI
639 *
640 */
641#if SU_HAVE_INLINE1
642su_inlinestatic inline sip_via_t *sip_via_init(sip_via_t x[1])
643{
644 return SIP_HEADER_INIT(x, sip_via_class, sizeof(sip_via_t))((void)memset((x), 0, (sizeof(sip_via_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_via_class)), (x))
;
645}
646#else
647#define sip_via_init(x) \
648 SIP_HEADER_INIT(x, sip_via_class, sizeof(sip_via_t))((void)memset((x), 0, (sizeof(sip_via_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_via_class)), (x))
649#endif
650
651/**Test if header object is instance of #sip_via_t.
652 *
653 * Check if the header class is an instance of
654 * @ref sip_via "Via header" object and return true (nonzero),
655 * otherwise return false (zero).
656 *
657 * @param header pointer to the header structure to be tested
658 *
659 * @retval 1 (true) if the @a header is an instance of header via
660 * @retval 0 (false) otherwise
661 *
662 */
663#if SU_HAVE_INLINE1
664su_inlinestatic inline int sip_is_via(sip_header_t const *header)
665{
666 return header && header->sh_classsh_common->h_class->hc_hash == sip_via_hash;
667}
668#else
669int sip_is_via(sip_header_t const *header);
670#endif
671
672#define sip_via_p(h)sip_is_via((h)) sip_is_via((h))
673
674
675/**Duplicate a list of @ref sip_via "Via header" header structures #sip_via_t.
676 *
677 * Duplicate a header
678 * structure @a hdr. If the header structure @a hdr
679 * contains a reference (@c hdr->x_next) to a list of
680 * headers, all the headers in the list are duplicated, too.
681 *
682 * @param home memory home used to allocate new structure
683 * @param hdr header structure to be duplicated
684 *
685 * When duplicating, all parameter lists and non-constant
686 * strings attached to the header are copied, too. The
687 * function uses given memory @a home to allocate all the
688 * memory areas used to copy the header.
689 *
690 * @par Example
691 * @code
692 *
693 * via = sip_via_dup(home, sip->sip_via);
694 *
695 * @endcode
696 *
697 * @return
698 * A pointer to the
699 * newly duplicated #sip_via_t header structure, or NULL
700 * upon an error.
701 *
702 */
703#if SU_HAVE_INLINE1
704su_inlinestatic inline
705#endif
706sip_via_t *sip_via_dup(su_home_t *home, sip_via_t const *hdr)
707 __attribute__((__malloc__));
708
709#if SU_HAVE_INLINE1
710su_inlinestatic inline
711sip_via_t *sip_via_dup(su_home_t *home, sip_via_t const *hdr)
712{
713 return (sip_via_t *)
52
Returning pointer, which participates in a condition later
714 msg_header_dup_as(home, sip_via_class, (msg_header_t const *)hdr);
51
Value assigned to field 'v_next'
715}
716#endif
717
718/**Copy a list of @ref sip_via "Via header" header structures #sip_via_t.
719 *
720 * The function sip_via_copy() copies a header structure @a
721 * hdr. If the header structure @a hdr contains a reference (@c
722 * hdr->h_next) to a list of headers, all the headers in that
723 * list are copied, too. The function uses given memory @a home
724 * to allocate all the memory areas used to copy the list of header
725 * structure @a hdr.
726 *
727 * @param home memory home used to allocate new structure
728 * @param hdr pointer to the header structure to be copied
729 *
730 * When copying, only the header structure and parameter lists attached to
731 * it are duplicated. The new header structure retains all the references to
732 * the strings within the old @a hdr header, including the encoding of the
733 * old header, if present.
734 *
735 * @par Example
736 * @code
737 *
738 * via = sip_via_copy(home, sip->sip_via);
739 *
740 * @endcode
741 *
742 * @return
743 * A pointer to newly copied header structure, or NULL upon an error.
744 *
745 */
746#if SU_HAVE_INLINE1
747su_inlinestatic inline
748#endif
749sip_via_t *sip_via_copy(su_home_t *home, sip_via_t const *hdr)
750 __attribute__((__malloc__));
751
752#if SU_HAVE_INLINE1
753su_inlinestatic inline
754sip_via_t *sip_via_copy(su_home_t *home, sip_via_t const *hdr)
755{
756 return (sip_via_t *)
757 msg_header_copy_as(home, sip_via_class, (msg_header_t const *)hdr);
758}
759#endif
760
761/**Make a @ref sip_via "Via header" structure #sip_via_t.
762 *
763 * The function sip_via_make() makes a new
764 * #sip_via_t header structure. It allocates a new
765 * header structure, and decodes the string @a s as the
766 * value of the structure.
767 *
768 * @param home memory home used to allocate new header structure.
769 * @param s string to be decoded as value of the new header structure
770 *
771 * @return
772 * A pointer to newly maked #sip_via_t header structure, or NULL upon an
773 * error.
774 *
775 */
776#if SU_HAVE_INLINE1
777su_inlinestatic inline
778#endif
779sip_via_t *sip_via_make(su_home_t *home, char const *s)
780 __attribute__((__malloc__));
781
782#if SU_HAVE_INLINE1
783su_inlinestatic inline sip_via_t *sip_via_make(su_home_t *home, char const *s)
784{
785 return (sip_via_t *)sip_header_make(home, sip_via_class, s)((sip_header_t *)msg_header_make((home), (sip_via_class), (s)
))
;
786}
787#endif
788
789/**Make a @ref sip_via "Via header" from formatting result.
790 *
791 * Make a new #sip_via_t object using formatting result as its value.
792 * The function first prints the arguments according to the format @a fmt
793 * specified. Then it allocates a new header structure, and parses the
794 * formatting result to the structure #sip_via_t.
795 *
796 * @param home memory home used to allocate new header structure.
797 * @param fmt string used as a printf()-style format
798 * @param ... argument list for format
799 *
800 * @return
801 * A pointer to newly
802 * makes header structure, or NULL upon an error.
803 *
804 * @HIDE
805 *
806 */
807#if SU_HAVE_INLINE1
808su_inlinestatic inline
809#endif
810sip_via_t *sip_via_format(su_home_t *home, char const *fmt, ...)
811 __attribute__((__malloc__, __format__ (printf, 2, 3)));
812
813#if SU_HAVE_INLINE1
814su_inlinestatic inline sip_via_t *sip_via_format(su_home_t *home, char const *fmt, ...)
815{
816 sip_header_t *h;
817 va_list ap;
818
819 va_start(ap, fmt)__builtin_va_start(ap, fmt);
820 h = sip_header_vformat(home, sip_via_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_via_class), (
fmt), (ap)))
;
821 va_end(ap)__builtin_va_end(ap);
822
823 return (sip_via_t *)h;
824}
825#endif
826
827/** @} */
828
829/**@addtogroup sip_route
830 * @{
831 */
832
833/** Parse a SIP @ref sip_route "Route header". @internal */
834SOFIAPUBFUN issize_t sip_route_d(su_home_t *, msg_header_t *,
835 char *s, isize_t slen);
836
837/** Print a SIP @ref sip_route "Route header". @internal */
838SOFIAPUBFUN issize_t sip_route_e(char b[], isize_t bsiz,
839 msg_header_t const *h, int flags);
840
841/**Access a SIP @ref sip_route "Route header"
842 * structure #sip_route_t from #sip_t.
843 *
844 */
845#define sip_route(sip)((sip_route_t *)msg_header_access((msg_pub_t*)(sip), sip_route_class
))
\
846 ((sip_route_t *)msg_header_access((msg_pub_t*)(sip), sip_route_class))
847
848/**Initializer for structure #sip_route_t.
849 *
850 * A static #sip_route_t structure for
851 * @ref sip_route "Route header" must be initialized with
852 * the SIP_ROUTE_INIT() macro.
853 * For instance,
854 * @code
855 *
856 * sip_route_t sip_route = SIP_ROUTE_INIT;
857 *
858 * @endcode
859 * @HI
860 *
861 */
862#define SIP_ROUTE_INIT(){{{ 0, 0, sip_route_class }}} SIP_HDR_INIT(route){{{ 0, 0, sip_route_class }}}
863
864/**Initialize a structure #sip_route_t.
865 *
866 * An #sip_route_t structure for
867 * @ref sip_route "Route header" can be initialized with the
868 * sip_route_init() function/macro. For instance,
869 * @code
870 *
871 * sip_route_t sip_route;
872 *
873 * sip_route_init(&sip_route);
874 *
875 * @endcode
876 * @HI
877 *
878 */
879#if SU_HAVE_INLINE1
880su_inlinestatic inline sip_route_t *sip_route_init(sip_route_t x[1])
881{
882 return SIP_HEADER_INIT(x, sip_route_class, sizeof(sip_route_t))((void)memset((x), 0, (sizeof(sip_route_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_route_class)), (x))
;
883}
884#else
885#define sip_route_init(x) \
886 SIP_HEADER_INIT(x, sip_route_class, sizeof(sip_route_t))((void)memset((x), 0, (sizeof(sip_route_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_route_class)), (x))
887#endif
888
889/**Test if header object is instance of #sip_route_t.
890 *
891 * Check if the header class is an instance of
892 * @ref sip_route "Route header" object and return true (nonzero),
893 * otherwise return false (zero).
894 *
895 * @param header pointer to the header structure to be tested
896 *
897 * @retval 1 (true) if the @a header is an instance of header route
898 * @retval 0 (false) otherwise
899 *
900 */
901#if SU_HAVE_INLINE1
902su_inlinestatic inline int sip_is_route(sip_header_t const *header)
903{
904 return header && header->sh_classsh_common->h_class->hc_hash == sip_route_hash;
905}
906#else
907int sip_is_route(sip_header_t const *header);
908#endif
909
910#define sip_route_p(h)sip_is_route((h)) sip_is_route((h))
911
912
913/**Duplicate a list of @ref sip_route "Route header" header structures #sip_route_t.
914 *
915 * Duplicate a header
916 * structure @a hdr. If the header structure @a hdr
917 * contains a reference (@c hdr->x_next) to a list of
918 * headers, all the headers in the list are duplicated, too.
919 *
920 * @param home memory home used to allocate new structure
921 * @param hdr header structure to be duplicated
922 *
923 * When duplicating, all parameter lists and non-constant
924 * strings attached to the header are copied, too. The
925 * function uses given memory @a home to allocate all the
926 * memory areas used to copy the header.
927 *
928 * @par Example
929 * @code
930 *
931 * route = sip_route_dup(home, sip->sip_route);
932 *
933 * @endcode
934 *
935 * @return
936 * A pointer to the
937 * newly duplicated #sip_route_t header structure, or NULL
938 * upon an error.
939 *
940 */
941#if SU_HAVE_INLINE1
942su_inlinestatic inline
943#endif
944sip_route_t *sip_route_dup(su_home_t *home, sip_route_t const *hdr)
945 __attribute__((__malloc__));
946
947#if SU_HAVE_INLINE1
948su_inlinestatic inline
949sip_route_t *sip_route_dup(su_home_t *home, sip_route_t const *hdr)
950{
951 return (sip_route_t *)
952 msg_header_dup_as(home, sip_route_class, (msg_header_t const *)hdr);
953}
954#endif
955
956/**Copy a list of @ref sip_route "Route header" header structures #sip_route_t.
957 *
958 * The function sip_route_copy() copies a header structure @a
959 * hdr. If the header structure @a hdr contains a reference (@c
960 * hdr->h_next) to a list of headers, all the headers in that
961 * list are copied, too. The function uses given memory @a home
962 * to allocate all the memory areas used to copy the list of header
963 * structure @a hdr.
964 *
965 * @param home memory home used to allocate new structure
966 * @param hdr pointer to the header structure to be copied
967 *
968 * When copying, only the header structure and parameter lists attached to
969 * it are duplicated. The new header structure retains all the references to
970 * the strings within the old @a hdr header, including the encoding of the
971 * old header, if present.
972 *
973 * @par Example
974 * @code
975 *
976 * route = sip_route_copy(home, sip->sip_route);
977 *
978 * @endcode
979 *
980 * @return
981 * A pointer to newly copied header structure, or NULL upon an error.
982 *
983 */
984#if SU_HAVE_INLINE1
985su_inlinestatic inline
986#endif
987sip_route_t *sip_route_copy(su_home_t *home, sip_route_t const *hdr)
988 __attribute__((__malloc__));
989
990#if SU_HAVE_INLINE1
991su_inlinestatic inline
992sip_route_t *sip_route_copy(su_home_t *home, sip_route_t const *hdr)
993{
994 return (sip_route_t *)
995 msg_header_copy_as(home, sip_route_class, (msg_header_t const *)hdr);
996}
997#endif
998
999/**Make a @ref sip_route "Route header" structure #sip_route_t.
1000 *
1001 * The function sip_route_make() makes a new
1002 * #sip_route_t header structure. It allocates a new
1003 * header structure, and decodes the string @a s as the
1004 * value of the structure.
1005 *
1006 * @param home memory home used to allocate new header structure.
1007 * @param s string to be decoded as value of the new header structure
1008 *
1009 * @return
1010 * A pointer to newly maked #sip_route_t header structure, or NULL upon an
1011 * error.
1012 *
1013 */
1014#if SU_HAVE_INLINE1
1015su_inlinestatic inline
1016#endif
1017sip_route_t *sip_route_make(su_home_t *home, char const *s)
1018 __attribute__((__malloc__));
1019
1020#if SU_HAVE_INLINE1
1021su_inlinestatic inline sip_route_t *sip_route_make(su_home_t *home, char const *s)
1022{
1023 return (sip_route_t *)sip_header_make(home, sip_route_class, s)((sip_header_t *)msg_header_make((home), (sip_route_class), (
s)))
;
1024}
1025#endif
1026
1027/**Make a @ref sip_route "Route header" from formatting result.
1028 *
1029 * Make a new #sip_route_t object using formatting result as its value.
1030 * The function first prints the arguments according to the format @a fmt
1031 * specified. Then it allocates a new header structure, and parses the
1032 * formatting result to the structure #sip_route_t.
1033 *
1034 * @param home memory home used to allocate new header structure.
1035 * @param fmt string used as a printf()-style format
1036 * @param ... argument list for format
1037 *
1038 * @return
1039 * A pointer to newly
1040 * makes header structure, or NULL upon an error.
1041 *
1042 * @HIDE
1043 *
1044 */
1045#if SU_HAVE_INLINE1
1046su_inlinestatic inline
1047#endif
1048sip_route_t *sip_route_format(su_home_t *home, char const *fmt, ...)
1049 __attribute__((__malloc__, __format__ (printf, 2, 3)));
1050
1051#if SU_HAVE_INLINE1
1052su_inlinestatic inline sip_route_t *sip_route_format(su_home_t *home, char const *fmt, ...)
1053{
1054 sip_header_t *h;
1055 va_list ap;
1056
1057 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1058 h = sip_header_vformat(home, sip_route_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_route_class)
, (fmt), (ap)))
;
1059 va_end(ap)__builtin_va_end(ap);
1060
1061 return (sip_route_t *)h;
1062}
1063#endif
1064
1065/** @} */
1066
1067/**@addtogroup sip_record_route
1068 * @{
1069 */
1070
1071/** Parse a SIP @ref sip_record_route "Record-Route header". @internal */
1072SOFIAPUBFUN issize_t sip_record_route_d(su_home_t *, msg_header_t *,
1073 char *s, isize_t slen);
1074
1075/** Print a SIP @ref sip_record_route "Record-Route header". @internal */
1076SOFIAPUBFUN issize_t sip_record_route_e(char b[], isize_t bsiz,
1077 msg_header_t const *h, int flags);
1078
1079/**Access a SIP @ref sip_record_route "Record-Route header"
1080 * structure #sip_record_route_t from #sip_t.
1081 *
1082 */
1083#define sip_record_route(sip)((sip_record_route_t *)msg_header_access((msg_pub_t*)(sip), sip_record_route_class
))
\
1084 ((sip_record_route_t *)msg_header_access((msg_pub_t*)(sip), sip_record_route_class))
1085
1086/**Initializer for structure #sip_record_route_t.
1087 *
1088 * A static #sip_record_route_t structure for
1089 * @ref sip_record_route "Record-Route header" must be initialized with
1090 * the SIP_RECORD_ROUTE_INIT() macro.
1091 * For instance,
1092 * @code
1093 *
1094 * sip_record_route_t sip_record_route = SIP_RECORD_ROUTE_INIT;
1095 *
1096 * @endcode
1097 * @HI
1098 *
1099 */
1100#define SIP_RECORD_ROUTE_INIT(){{{ 0, 0, sip_record_route_class }}} SIP_HDR_INIT(record_route){{{ 0, 0, sip_record_route_class }}}
1101
1102/**Initialize a structure #sip_record_route_t.
1103 *
1104 * An #sip_record_route_t structure for
1105 * @ref sip_record_route "Record-Route header" can be initialized with the
1106 * sip_record_route_init() function/macro. For instance,
1107 * @code
1108 *
1109 * sip_record_route_t sip_record_route;
1110 *
1111 * sip_record_route_init(&sip_record_route);
1112 *
1113 * @endcode
1114 * @HI
1115 *
1116 */
1117#if SU_HAVE_INLINE1
1118su_inlinestatic inline sip_record_route_t *sip_record_route_init(sip_record_route_t x[1])
1119{
1120 return SIP_HEADER_INIT(x, sip_record_route_class, sizeof(sip_record_route_t))((void)memset((x), 0, (sizeof(sip_record_route_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_record_route_class)),
(x))
;
1121}
1122#else
1123#define sip_record_route_init(x) \
1124 SIP_HEADER_INIT(x, sip_record_route_class, sizeof(sip_record_route_t))((void)memset((x), 0, (sizeof(sip_record_route_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_record_route_class)),
(x))
1125#endif
1126
1127/**Test if header object is instance of #sip_record_route_t.
1128 *
1129 * Check if the header class is an instance of
1130 * @ref sip_record_route "Record-Route header" object and return true (nonzero),
1131 * otherwise return false (zero).
1132 *
1133 * @param header pointer to the header structure to be tested
1134 *
1135 * @retval 1 (true) if the @a header is an instance of header record_route
1136 * @retval 0 (false) otherwise
1137 *
1138 */
1139#if SU_HAVE_INLINE1
1140su_inlinestatic inline int sip_is_record_route(sip_header_t const *header)
1141{
1142 return header && header->sh_classsh_common->h_class->hc_hash == sip_record_route_hash;
1143}
1144#else
1145int sip_is_record_route(sip_header_t const *header);
1146#endif
1147
1148#define sip_record_route_p(h)sip_is_record_route((h)) sip_is_record_route((h))
1149
1150
1151/**Duplicate a list of @ref sip_record_route "Record-Route header" header structures #sip_record_route_t.
1152 *
1153 * Duplicate a header
1154 * structure @a hdr. If the header structure @a hdr
1155 * contains a reference (@c hdr->x_next) to a list of
1156 * headers, all the headers in the list are duplicated, too.
1157 *
1158 * @param home memory home used to allocate new structure
1159 * @param hdr header structure to be duplicated
1160 *
1161 * When duplicating, all parameter lists and non-constant
1162 * strings attached to the header are copied, too. The
1163 * function uses given memory @a home to allocate all the
1164 * memory areas used to copy the header.
1165 *
1166 * @par Example
1167 * @code
1168 *
1169 * record_route = sip_record_route_dup(home, sip->sip_record_route);
1170 *
1171 * @endcode
1172 *
1173 * @return
1174 * A pointer to the
1175 * newly duplicated #sip_record_route_t header structure, or NULL
1176 * upon an error.
1177 *
1178 */
1179#if SU_HAVE_INLINE1
1180su_inlinestatic inline
1181#endif
1182sip_record_route_t *sip_record_route_dup(su_home_t *home, sip_record_route_t const *hdr)
1183 __attribute__((__malloc__));
1184
1185#if SU_HAVE_INLINE1
1186su_inlinestatic inline
1187sip_record_route_t *sip_record_route_dup(su_home_t *home, sip_record_route_t const *hdr)
1188{
1189 return (sip_record_route_t *)
1190 msg_header_dup_as(home, sip_record_route_class, (msg_header_t const *)hdr);
1191}
1192#endif
1193
1194/**Copy a list of @ref sip_record_route "Record-Route header" header structures #sip_record_route_t.
1195 *
1196 * The function sip_record_route_copy() copies a header structure @a
1197 * hdr. If the header structure @a hdr contains a reference (@c
1198 * hdr->h_next) to a list of headers, all the headers in that
1199 * list are copied, too. The function uses given memory @a home
1200 * to allocate all the memory areas used to copy the list of header
1201 * structure @a hdr.
1202 *
1203 * @param home memory home used to allocate new structure
1204 * @param hdr pointer to the header structure to be copied
1205 *
1206 * When copying, only the header structure and parameter lists attached to
1207 * it are duplicated. The new header structure retains all the references to
1208 * the strings within the old @a hdr header, including the encoding of the
1209 * old header, if present.
1210 *
1211 * @par Example
1212 * @code
1213 *
1214 * record_route = sip_record_route_copy(home, sip->sip_record_route);
1215 *
1216 * @endcode
1217 *
1218 * @return
1219 * A pointer to newly copied header structure, or NULL upon an error.
1220 *
1221 */
1222#if SU_HAVE_INLINE1
1223su_inlinestatic inline
1224#endif
1225sip_record_route_t *sip_record_route_copy(su_home_t *home, sip_record_route_t const *hdr)
1226 __attribute__((__malloc__));
1227
1228#if SU_HAVE_INLINE1
1229su_inlinestatic inline
1230sip_record_route_t *sip_record_route_copy(su_home_t *home, sip_record_route_t const *hdr)
1231{
1232 return (sip_record_route_t *)
1233 msg_header_copy_as(home, sip_record_route_class, (msg_header_t const *)hdr);
1234}
1235#endif
1236
1237/**Make a @ref sip_record_route "Record-Route header" structure #sip_record_route_t.
1238 *
1239 * The function sip_record_route_make() makes a new
1240 * #sip_record_route_t header structure. It allocates a new
1241 * header structure, and decodes the string @a s as the
1242 * value of the structure.
1243 *
1244 * @param home memory home used to allocate new header structure.
1245 * @param s string to be decoded as value of the new header structure
1246 *
1247 * @return
1248 * A pointer to newly maked #sip_record_route_t header structure, or NULL upon an
1249 * error.
1250 *
1251 */
1252#if SU_HAVE_INLINE1
1253su_inlinestatic inline
1254#endif
1255sip_record_route_t *sip_record_route_make(su_home_t *home, char const *s)
1256 __attribute__((__malloc__));
1257
1258#if SU_HAVE_INLINE1
1259su_inlinestatic inline sip_record_route_t *sip_record_route_make(su_home_t *home, char const *s)
1260{
1261 return (sip_record_route_t *)sip_header_make(home, sip_record_route_class, s)((sip_header_t *)msg_header_make((home), (sip_record_route_class
), (s)))
;
1262}
1263#endif
1264
1265/**Make a @ref sip_record_route "Record-Route header" from formatting result.
1266 *
1267 * Make a new #sip_record_route_t object using formatting result as its value.
1268 * The function first prints the arguments according to the format @a fmt
1269 * specified. Then it allocates a new header structure, and parses the
1270 * formatting result to the structure #sip_record_route_t.
1271 *
1272 * @param home memory home used to allocate new header structure.
1273 * @param fmt string used as a printf()-style format
1274 * @param ... argument list for format
1275 *
1276 * @return
1277 * A pointer to newly
1278 * makes header structure, or NULL upon an error.
1279 *
1280 * @HIDE
1281 *
1282 */
1283#if SU_HAVE_INLINE1
1284su_inlinestatic inline
1285#endif
1286sip_record_route_t *sip_record_route_format(su_home_t *home, char const *fmt, ...)
1287 __attribute__((__malloc__, __format__ (printf, 2, 3)));
1288
1289#if SU_HAVE_INLINE1
1290su_inlinestatic inline sip_record_route_t *sip_record_route_format(su_home_t *home, char const *fmt, ...)
1291{
1292 sip_header_t *h;
1293 va_list ap;
1294
1295 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1296 h = sip_header_vformat(home, sip_record_route_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_record_route_class
), (fmt), (ap)))
;
1297 va_end(ap)__builtin_va_end(ap);
1298
1299 return (sip_record_route_t *)h;
1300}
1301#endif
1302
1303/** @} */
1304
1305/**@addtogroup sip_max_forwards
1306 * @{
1307 */
1308
1309/** Parse a SIP @ref sip_max_forwards "Max-Forwards header". @internal */
1310SOFIAPUBFUN issize_t sip_max_forwards_d(su_home_t *, msg_header_t *,
1311 char *s, isize_t slen);
1312
1313/** Print a SIP @ref sip_max_forwards "Max-Forwards header". @internal */
1314SOFIAPUBFUN issize_t sip_max_forwards_e(char b[], isize_t bsiz,
1315 msg_header_t const *h, int flags);
1316
1317/**Access a SIP @ref sip_max_forwards "Max-Forwards header"
1318 * structure #sip_max_forwards_t from #sip_t.
1319 *
1320 */
1321#define sip_max_forwards(sip)((sip_max_forwards_t *)msg_header_access((msg_pub_t*)(sip), sip_max_forwards_class
))
\
1322 ((sip_max_forwards_t *)msg_header_access((msg_pub_t*)(sip), sip_max_forwards_class))
1323
1324/**Initializer for structure #sip_max_forwards_t.
1325 *
1326 * A static #sip_max_forwards_t structure for
1327 * @ref sip_max_forwards "Max-Forwards header" must be initialized with
1328 * the SIP_MAX_FORWARDS_INIT() macro.
1329 * For instance,
1330 * @code
1331 *
1332 * sip_max_forwards_t sip_max_forwards = SIP_MAX_FORWARDS_INIT;
1333 *
1334 * @endcode
1335 * @HI
1336 *
1337 */
1338#define SIP_MAX_FORWARDS_INIT(){{{ 0, 0, sip_max_forwards_class }}} SIP_HDR_INIT(max_forwards){{{ 0, 0, sip_max_forwards_class }}}
1339
1340/**Initialize a structure #sip_max_forwards_t.
1341 *
1342 * An #sip_max_forwards_t structure for
1343 * @ref sip_max_forwards "Max-Forwards header" can be initialized with the
1344 * sip_max_forwards_init() function/macro. For instance,
1345 * @code
1346 *
1347 * sip_max_forwards_t sip_max_forwards;
1348 *
1349 * sip_max_forwards_init(&sip_max_forwards);
1350 *
1351 * @endcode
1352 * @HI
1353 *
1354 */
1355#if SU_HAVE_INLINE1
1356su_inlinestatic inline sip_max_forwards_t *sip_max_forwards_init(sip_max_forwards_t x[1])
1357{
1358 return SIP_HEADER_INIT(x, sip_max_forwards_class, sizeof(sip_max_forwards_t))((void)memset((x), 0, (sizeof(sip_max_forwards_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_max_forwards_class)),
(x))
;
1359}
1360#else
1361#define sip_max_forwards_init(x) \
1362 SIP_HEADER_INIT(x, sip_max_forwards_class, sizeof(sip_max_forwards_t))((void)memset((x), 0, (sizeof(sip_max_forwards_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_max_forwards_class)),
(x))
1363#endif
1364
1365/**Test if header object is instance of #sip_max_forwards_t.
1366 *
1367 * Check if the header class is an instance of
1368 * @ref sip_max_forwards "Max-Forwards header" object and return true (nonzero),
1369 * otherwise return false (zero).
1370 *
1371 * @param header pointer to the header structure to be tested
1372 *
1373 * @retval 1 (true) if the @a header is an instance of header max_forwards
1374 * @retval 0 (false) otherwise
1375 *
1376 */
1377#if SU_HAVE_INLINE1
1378su_inlinestatic inline int sip_is_max_forwards(sip_header_t const *header)
1379{
1380 return header && header->sh_classsh_common->h_class->hc_hash == sip_max_forwards_hash;
1381}
1382#else
1383int sip_is_max_forwards(sip_header_t const *header);
1384#endif
1385
1386#define sip_max_forwards_p(h)sip_is_max_forwards((h)) sip_is_max_forwards((h))
1387
1388
1389/**Duplicate a list of @ref sip_max_forwards "Max-Forwards header" header structures #sip_max_forwards_t.
1390 *
1391 * Duplicate a header
1392 * structure @a hdr. If the header structure @a hdr
1393 * contains a reference (@c hdr->x_next) to a list of
1394 * headers, all the headers in the list are duplicated, too.
1395 *
1396 * @param home memory home used to allocate new structure
1397 * @param hdr header structure to be duplicated
1398 *
1399 * When duplicating, all parameter lists and non-constant
1400 * strings attached to the header are copied, too. The
1401 * function uses given memory @a home to allocate all the
1402 * memory areas used to copy the header.
1403 *
1404 * @par Example
1405 * @code
1406 *
1407 * max_forwards = sip_max_forwards_dup(home, sip->sip_max_forwards);
1408 *
1409 * @endcode
1410 *
1411 * @return
1412 * A pointer to the
1413 * newly duplicated #sip_max_forwards_t header structure, or NULL
1414 * upon an error.
1415 *
1416 */
1417#if SU_HAVE_INLINE1
1418su_inlinestatic inline
1419#endif
1420sip_max_forwards_t *sip_max_forwards_dup(su_home_t *home, sip_max_forwards_t const *hdr)
1421 __attribute__((__malloc__));
1422
1423#if SU_HAVE_INLINE1
1424su_inlinestatic inline
1425sip_max_forwards_t *sip_max_forwards_dup(su_home_t *home, sip_max_forwards_t const *hdr)
1426{
1427 return (sip_max_forwards_t *)
1428 msg_header_dup_as(home, sip_max_forwards_class, (msg_header_t const *)hdr);
1429}
1430#endif
1431
1432/**Copy a list of @ref sip_max_forwards "Max-Forwards header" header structures #sip_max_forwards_t.
1433 *
1434 * The function sip_max_forwards_copy() copies a header structure @a
1435 * hdr. If the header structure @a hdr contains a reference (@c
1436 * hdr->h_next) to a list of headers, all the headers in that
1437 * list are copied, too. The function uses given memory @a home
1438 * to allocate all the memory areas used to copy the list of header
1439 * structure @a hdr.
1440 *
1441 * @param home memory home used to allocate new structure
1442 * @param hdr pointer to the header structure to be copied
1443 *
1444 * When copying, only the header structure and parameter lists attached to
1445 * it are duplicated. The new header structure retains all the references to
1446 * the strings within the old @a hdr header, including the encoding of the
1447 * old header, if present.
1448 *
1449 * @par Example
1450 * @code
1451 *
1452 * max_forwards = sip_max_forwards_copy(home, sip->sip_max_forwards);
1453 *
1454 * @endcode
1455 *
1456 * @return
1457 * A pointer to newly copied header structure, or NULL upon an error.
1458 *
1459 */
1460#if SU_HAVE_INLINE1
1461su_inlinestatic inline
1462#endif
1463sip_max_forwards_t *sip_max_forwards_copy(su_home_t *home, sip_max_forwards_t const *hdr)
1464 __attribute__((__malloc__));
1465
1466#if SU_HAVE_INLINE1
1467su_inlinestatic inline
1468sip_max_forwards_t *sip_max_forwards_copy(su_home_t *home, sip_max_forwards_t const *hdr)
1469{
1470 return (sip_max_forwards_t *)
1471 msg_header_copy_as(home, sip_max_forwards_class, (msg_header_t const *)hdr);
1472}
1473#endif
1474
1475/**Make a @ref sip_max_forwards "Max-Forwards header" structure #sip_max_forwards_t.
1476 *
1477 * The function sip_max_forwards_make() makes a new
1478 * #sip_max_forwards_t header structure. It allocates a new
1479 * header structure, and decodes the string @a s as the
1480 * value of the structure.
1481 *
1482 * @param home memory home used to allocate new header structure.
1483 * @param s string to be decoded as value of the new header structure
1484 *
1485 * @return
1486 * A pointer to newly maked #sip_max_forwards_t header structure, or NULL upon an
1487 * error.
1488 *
1489 */
1490#if SU_HAVE_INLINE1
1491su_inlinestatic inline
1492#endif
1493sip_max_forwards_t *sip_max_forwards_make(su_home_t *home, char const *s)
1494 __attribute__((__malloc__));
1495
1496#if SU_HAVE_INLINE1
1497su_inlinestatic inline sip_max_forwards_t *sip_max_forwards_make(su_home_t *home, char const *s)
1498{
1499 return (sip_max_forwards_t *)sip_header_make(home, sip_max_forwards_class, s)((sip_header_t *)msg_header_make((home), (sip_max_forwards_class
), (s)))
;
1500}
1501#endif
1502
1503/**Make a @ref sip_max_forwards "Max-Forwards header" from formatting result.
1504 *
1505 * Make a new #sip_max_forwards_t object using formatting result as its value.
1506 * The function first prints the arguments according to the format @a fmt
1507 * specified. Then it allocates a new header structure, and parses the
1508 * formatting result to the structure #sip_max_forwards_t.
1509 *
1510 * @param home memory home used to allocate new header structure.
1511 * @param fmt string used as a printf()-style format
1512 * @param ... argument list for format
1513 *
1514 * @return
1515 * A pointer to newly
1516 * makes header structure, or NULL upon an error.
1517 *
1518 * @HIDE
1519 *
1520 */
1521#if SU_HAVE_INLINE1
1522su_inlinestatic inline
1523#endif
1524sip_max_forwards_t *sip_max_forwards_format(su_home_t *home, char const *fmt, ...)
1525 __attribute__((__malloc__, __format__ (printf, 2, 3)));
1526
1527#if SU_HAVE_INLINE1
1528su_inlinestatic inline sip_max_forwards_t *sip_max_forwards_format(su_home_t *home, char const *fmt, ...)
1529{
1530 sip_header_t *h;
1531 va_list ap;
1532
1533 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1534 h = sip_header_vformat(home, sip_max_forwards_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_max_forwards_class
), (fmt), (ap)))
;
1535 va_end(ap)__builtin_va_end(ap);
1536
1537 return (sip_max_forwards_t *)h;
1538}
1539#endif
1540
1541/** @} */
1542
1543/**@addtogroup sip_proxy_require
1544 * @{
1545 */
1546
1547/** Parse a SIP @ref sip_proxy_require "Proxy-Require header". @internal */
1548SOFIAPUBFUN issize_t sip_proxy_require_d(su_home_t *, msg_header_t *,
1549 char *s, isize_t slen);
1550
1551/** Print a SIP @ref sip_proxy_require "Proxy-Require header". @internal */
1552SOFIAPUBFUN issize_t sip_proxy_require_e(char b[], isize_t bsiz,
1553 msg_header_t const *h, int flags);
1554
1555/**Access a SIP @ref sip_proxy_require "Proxy-Require header"
1556 * structure #sip_proxy_require_t from #sip_t.
1557 *
1558 */
1559#define sip_proxy_require(sip)((sip_proxy_require_t *)msg_header_access((msg_pub_t*)(sip), sip_proxy_require_class
))
\
1560 ((sip_proxy_require_t *)msg_header_access((msg_pub_t*)(sip), sip_proxy_require_class))
1561
1562/**Initializer for structure #sip_proxy_require_t.
1563 *
1564 * A static #sip_proxy_require_t structure for
1565 * @ref sip_proxy_require "Proxy-Require header" must be initialized with
1566 * the SIP_PROXY_REQUIRE_INIT() macro.
1567 * For instance,
1568 * @code
1569 *
1570 * sip_proxy_require_t sip_proxy_require = SIP_PROXY_REQUIRE_INIT;
1571 *
1572 * @endcode
1573 * @HI
1574 *
1575 */
1576#define SIP_PROXY_REQUIRE_INIT(){{{ 0, 0, sip_proxy_require_class }}} SIP_HDR_INIT(proxy_require){{{ 0, 0, sip_proxy_require_class }}}
1577
1578/**Initialize a structure #sip_proxy_require_t.
1579 *
1580 * An #sip_proxy_require_t structure for
1581 * @ref sip_proxy_require "Proxy-Require header" can be initialized with the
1582 * sip_proxy_require_init() function/macro. For instance,
1583 * @code
1584 *
1585 * sip_proxy_require_t sip_proxy_require;
1586 *
1587 * sip_proxy_require_init(&sip_proxy_require);
1588 *
1589 * @endcode
1590 * @HI
1591 *
1592 */
1593#if SU_HAVE_INLINE1
1594su_inlinestatic inline sip_proxy_require_t *sip_proxy_require_init(sip_proxy_require_t x[1])
1595{
1596 return SIP_HEADER_INIT(x, sip_proxy_require_class, sizeof(sip_proxy_require_t))((void)memset((x), 0, (sizeof(sip_proxy_require_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_proxy_require_class)
), (x))
;
1597}
1598#else
1599#define sip_proxy_require_init(x) \
1600 SIP_HEADER_INIT(x, sip_proxy_require_class, sizeof(sip_proxy_require_t))((void)memset((x), 0, (sizeof(sip_proxy_require_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_proxy_require_class)
), (x))
1601#endif
1602
1603/**Test if header object is instance of #sip_proxy_require_t.
1604 *
1605 * Check if the header class is an instance of
1606 * @ref sip_proxy_require "Proxy-Require header" object and return true (nonzero),
1607 * otherwise return false (zero).
1608 *
1609 * @param header pointer to the header structure to be tested
1610 *
1611 * @retval 1 (true) if the @a header is an instance of header proxy_require
1612 * @retval 0 (false) otherwise
1613 *
1614 */
1615#if SU_HAVE_INLINE1
1616su_inlinestatic inline int sip_is_proxy_require(sip_header_t const *header)
1617{
1618 return header && header->sh_classsh_common->h_class->hc_hash == sip_proxy_require_hash;
1619}
1620#else
1621int sip_is_proxy_require(sip_header_t const *header);
1622#endif
1623
1624#define sip_proxy_require_p(h)sip_is_proxy_require((h)) sip_is_proxy_require((h))
1625
1626
1627/**Duplicate a list of @ref sip_proxy_require "Proxy-Require header" header structures #sip_proxy_require_t.
1628 *
1629 * Duplicate a header
1630 * structure @a hdr. If the header structure @a hdr
1631 * contains a reference (@c hdr->x_next) to a list of
1632 * headers, all the headers in the list are duplicated, too.
1633 *
1634 * @param home memory home used to allocate new structure
1635 * @param hdr header structure to be duplicated
1636 *
1637 * When duplicating, all parameter lists and non-constant
1638 * strings attached to the header are copied, too. The
1639 * function uses given memory @a home to allocate all the
1640 * memory areas used to copy the header.
1641 *
1642 * @par Example
1643 * @code
1644 *
1645 * proxy_require = sip_proxy_require_dup(home, sip->sip_proxy_require);
1646 *
1647 * @endcode
1648 *
1649 * @return
1650 * A pointer to the
1651 * newly duplicated #sip_proxy_require_t header structure, or NULL
1652 * upon an error.
1653 *
1654 */
1655#if SU_HAVE_INLINE1
1656su_inlinestatic inline
1657#endif
1658sip_proxy_require_t *sip_proxy_require_dup(su_home_t *home, sip_proxy_require_t const *hdr)
1659 __attribute__((__malloc__));
1660
1661#if SU_HAVE_INLINE1
1662su_inlinestatic inline
1663sip_proxy_require_t *sip_proxy_require_dup(su_home_t *home, sip_proxy_require_t const *hdr)
1664{
1665 return (sip_proxy_require_t *)
1666 msg_header_dup_as(home, sip_proxy_require_class, (msg_header_t const *)hdr);
1667}
1668#endif
1669
1670/**Copy a list of @ref sip_proxy_require "Proxy-Require header" header structures #sip_proxy_require_t.
1671 *
1672 * The function sip_proxy_require_copy() copies a header structure @a
1673 * hdr. If the header structure @a hdr contains a reference (@c
1674 * hdr->h_next) to a list of headers, all the headers in that
1675 * list are copied, too. The function uses given memory @a home
1676 * to allocate all the memory areas used to copy the list of header
1677 * structure @a hdr.
1678 *
1679 * @param home memory home used to allocate new structure
1680 * @param hdr pointer to the header structure to be copied
1681 *
1682 * When copying, only the header structure and parameter lists attached to
1683 * it are duplicated. The new header structure retains all the references to
1684 * the strings within the old @a hdr header, including the encoding of the
1685 * old header, if present.
1686 *
1687 * @par Example
1688 * @code
1689 *
1690 * proxy_require = sip_proxy_require_copy(home, sip->sip_proxy_require);
1691 *
1692 * @endcode
1693 *
1694 * @return
1695 * A pointer to newly copied header structure, or NULL upon an error.
1696 *
1697 */
1698#if SU_HAVE_INLINE1
1699su_inlinestatic inline
1700#endif
1701sip_proxy_require_t *sip_proxy_require_copy(su_home_t *home, sip_proxy_require_t const *hdr)
1702 __attribute__((__malloc__));
1703
1704#if SU_HAVE_INLINE1
1705su_inlinestatic inline
1706sip_proxy_require_t *sip_proxy_require_copy(su_home_t *home, sip_proxy_require_t const *hdr)
1707{
1708 return (sip_proxy_require_t *)
1709 msg_header_copy_as(home, sip_proxy_require_class, (msg_header_t const *)hdr);
1710}
1711#endif
1712
1713/**Make a @ref sip_proxy_require "Proxy-Require header" structure #sip_proxy_require_t.
1714 *
1715 * The function sip_proxy_require_make() makes a new
1716 * #sip_proxy_require_t header structure. It allocates a new
1717 * header structure, and decodes the string @a s as the
1718 * value of the structure.
1719 *
1720 * @param home memory home used to allocate new header structure.
1721 * @param s string to be decoded as value of the new header structure
1722 *
1723 * @return
1724 * A pointer to newly maked #sip_proxy_require_t header structure, or NULL upon an
1725 * error.
1726 *
1727 */
1728#if SU_HAVE_INLINE1
1729su_inlinestatic inline
1730#endif
1731sip_proxy_require_t *sip_proxy_require_make(su_home_t *home, char const *s)
1732 __attribute__((__malloc__));
1733
1734#if SU_HAVE_INLINE1
1735su_inlinestatic inline sip_proxy_require_t *sip_proxy_require_make(su_home_t *home, char const *s)
1736{
1737 return (sip_proxy_require_t *)sip_header_make(home, sip_proxy_require_class, s)((sip_header_t *)msg_header_make((home), (sip_proxy_require_class
), (s)))
;
1738}
1739#endif
1740
1741/**Make a @ref sip_proxy_require "Proxy-Require header" from formatting result.
1742 *
1743 * Make a new #sip_proxy_require_t object using formatting result as its value.
1744 * The function first prints the arguments according to the format @a fmt
1745 * specified. Then it allocates a new header structure, and parses the
1746 * formatting result to the structure #sip_proxy_require_t.
1747 *
1748 * @param home memory home used to allocate new header structure.
1749 * @param fmt string used as a printf()-style format
1750 * @param ... argument list for format
1751 *
1752 * @return
1753 * A pointer to newly
1754 * makes header structure, or NULL upon an error.
1755 *
1756 * @HIDE
1757 *
1758 */
1759#if SU_HAVE_INLINE1
1760su_inlinestatic inline
1761#endif
1762sip_proxy_require_t *sip_proxy_require_format(su_home_t *home, char const *fmt, ...)
1763 __attribute__((__malloc__, __format__ (printf, 2, 3)));
1764
1765#if SU_HAVE_INLINE1
1766su_inlinestatic inline sip_proxy_require_t *sip_proxy_require_format(su_home_t *home, char const *fmt, ...)
1767{
1768 sip_header_t *h;
1769 va_list ap;
1770
1771 va_start(ap, fmt)__builtin_va_start(ap, fmt);
1772 h = sip_header_vformat(home, sip_proxy_require_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_proxy_require_class
), (fmt), (ap)))
;
1773 va_end(ap)__builtin_va_end(ap);
1774
1775 return (sip_proxy_require_t *)h;
1776}
1777#endif
1778
1779/** @} */
1780
1781/**@addtogroup sip_from
1782 * @{
1783 */
1784
1785/** Parse a SIP @ref sip_from "From header". @internal */
1786SOFIAPUBFUN issize_t sip_from_d(su_home_t *, msg_header_t *,
1787 char *s, isize_t slen);
1788
1789/** Print a SIP @ref sip_from "From header". @internal */
1790SOFIAPUBFUN issize_t sip_from_e(char b[], isize_t bsiz,
1791 msg_header_t const *h, int flags);
1792
1793/**Access a SIP @ref sip_from "From header"
1794 * structure #sip_from_t from #sip_t.
1795 *
1796 */
1797#define sip_from(sip)((sip_from_t *)msg_header_access((msg_pub_t*)(sip), sip_from_class
))
\
1798 ((sip_from_t *)msg_header_access((msg_pub_t*)(sip), sip_from_class))
1799
1800/**Initializer for structure #sip_from_t.
1801 *
1802 * A static #sip_from_t structure for
1803 * @ref sip_from "From header" must be initialized with
1804 * the SIP_FROM_INIT() macro.
1805 * For instance,
1806 * @code
1807 *
1808 * sip_from_t sip_from = SIP_FROM_INIT;
1809 *
1810 * @endcode
1811 * @HI
1812 *
1813 */
1814#define SIP_FROM_INIT(){{{ 0, 0, sip_from_class }}} SIP_HDR_INIT(from){{{ 0, 0, sip_from_class }}}
1815
1816/**Initialize a structure #sip_from_t.
1817 *
1818 * An #sip_from_t structure for
1819 * @ref sip_from "From header" can be initialized with the
1820 * sip_from_init() function/macro. For instance,
1821 * @code
1822 *
1823 * sip_from_t sip_from;
1824 *
1825 * sip_from_init(&sip_from);
1826 *
1827 * @endcode
1828 * @HI
1829 *
1830 */
1831#if SU_HAVE_INLINE1
1832su_inlinestatic inline sip_from_t *sip_from_init(sip_from_t x[1])
1833{
1834 return SIP_HEADER_INIT(x, sip_from_class, sizeof(sip_from_t))((void)memset((x), 0, (sizeof(sip_from_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_from_class)), (x))
;
1835}
1836#else
1837#define sip_from_init(x) \
1838 SIP_HEADER_INIT(x, sip_from_class, sizeof(sip_from_t))((void)memset((x), 0, (sizeof(sip_from_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_from_class)), (x))
1839#endif
1840
1841/**Test if header object is instance of #sip_from_t.
1842 *
1843 * Check if the header class is an instance of
1844 * @ref sip_from "From header" object and return true (nonzero),
1845 * otherwise return false (zero).
1846 *
1847 * @param header pointer to the header structure to be tested
1848 *
1849 * @retval 1 (true) if the @a header is an instance of header from
1850 * @retval 0 (false) otherwise
1851 *
1852 */
1853#if SU_HAVE_INLINE1
1854su_inlinestatic inline int sip_is_from(sip_header_t const *header)
1855{
1856 return header && header->sh_classsh_common->h_class->hc_hash == sip_from_hash;
1857}
1858#else
1859int sip_is_from(sip_header_t const *header);
1860#endif
1861
1862#define sip_from_p(h)sip_is_from((h)) sip_is_from((h))
1863
1864
1865/**Duplicate a list of @ref sip_from "From header" header structures #sip_from_t.
1866 *
1867 * Duplicate a header
1868 * structure @a hdr. If the header structure @a hdr
1869 * contains a reference (@c hdr->x_next) to a list of
1870 * headers, all the headers in the list are duplicated, too.
1871 *
1872 * @param home memory home used to allocate new structure
1873 * @param hdr header structure to be duplicated
1874 *
1875 * When duplicating, all parameter lists and non-constant
1876 * strings attached to the header are copied, too. The
1877 * function uses given memory @a home to allocate all the
1878 * memory areas used to copy the header.
1879 *
1880 * @par Example
1881 * @code
1882 *
1883 * from = sip_from_dup(home, sip->sip_from);
1884 *
1885 * @endcode
1886 *
1887 * @return
1888 * A pointer to the
1889 * newly duplicated #sip_from_t header structure, or NULL
1890 * upon an error.
1891 *
1892 */
1893#if SU_HAVE_INLINE1
1894su_inlinestatic inline
1895#endif
1896sip_from_t *sip_from_dup(su_home_t *home, sip_from_t const *hdr)
1897 __attribute__((__malloc__));
1898
1899#if SU_HAVE_INLINE1
1900su_inlinestatic inline
1901sip_from_t *sip_from_dup(su_home_t *home, sip_from_t const *hdr)
1902{
1903 return (sip_from_t *)
1904 msg_header_dup_as(home, sip_from_class, (msg_header_t const *)hdr);
1905}
1906#endif
1907
1908/**Copy a list of @ref sip_from "From header" header structures #sip_from_t.
1909 *
1910 * The function sip_from_copy() copies a header structure @a
1911 * hdr. If the header structure @a hdr contains a reference (@c
1912 * hdr->h_next) to a list of headers, all the headers in that
1913 * list are copied, too. The function uses given memory @a home
1914 * to allocate all the memory areas used to copy the list of header
1915 * structure @a hdr.
1916 *
1917 * @param home memory home used to allocate new structure
1918 * @param hdr pointer to the header structure to be copied
1919 *
1920 * When copying, only the header structure and parameter lists attached to
1921 * it are duplicated. The new header structure retains all the references to
1922 * the strings within the old @a hdr header, including the encoding of the
1923 * old header, if present.
1924 *
1925 * @par Example
1926 * @code
1927 *
1928 * from = sip_from_copy(home, sip->sip_from);
1929 *
1930 * @endcode
1931 *
1932 * @return
1933 * A pointer to newly copied header structure, or NULL upon an error.
1934 *
1935 */
1936#if SU_HAVE_INLINE1
1937su_inlinestatic inline
1938#endif
1939sip_from_t *sip_from_copy(su_home_t *home, sip_from_t const *hdr)
1940 __attribute__((__malloc__));
1941
1942#if SU_HAVE_INLINE1
1943su_inlinestatic inline
1944sip_from_t *sip_from_copy(su_home_t *home, sip_from_t const *hdr)
1945{
1946 return (sip_from_t *)
1947 msg_header_copy_as(home, sip_from_class, (msg_header_t const *)hdr);
1948}
1949#endif
1950
1951/**Make a @ref sip_from "From header" structure #sip_from_t.
1952 *
1953 * The function sip_from_make() makes a new
1954 * #sip_from_t header structure. It allocates a new
1955 * header structure, and decodes the string @a s as the
1956 * value of the structure.
1957 *
1958 * @param home memory home used to allocate new header structure.
1959 * @param s string to be decoded as value of the new header structure
1960 *
1961 * @return
1962 * A pointer to newly maked #sip_from_t header structure, or NULL upon an
1963 * error.
1964 *
1965 */
1966#if SU_HAVE_INLINE1
1967su_inlinestatic inline
1968#endif
1969sip_from_t *sip_from_make(su_home_t *home, char const *s)
1970 __attribute__((__malloc__));
1971
1972#if SU_HAVE_INLINE1
1973su_inlinestatic inline sip_from_t *sip_from_make(su_home_t *home, char const *s)
1974{
1975 return (sip_from_t *)sip_header_make(home, sip_from_class, s)((sip_header_t *)msg_header_make((home), (sip_from_class), (s
)))
;
1976}
1977#endif
1978
1979/**Make a @ref sip_from "From header" from formatting result.
1980 *
1981 * Make a new #sip_from_t object using formatting result as its value.
1982 * The function first prints the arguments according to the format @a fmt
1983 * specified. Then it allocates a new header structure, and parses the
1984 * formatting result to the structure #sip_from_t.
1985 *
1986 * @param home memory home used to allocate new header structure.
1987 * @param fmt string used as a printf()-style format
1988 * @param ... argument list for format
1989 *
1990 * @return
1991 * A pointer to newly
1992 * makes header structure, or NULL upon an error.
1993 *
1994 * @HIDE
1995 *
1996 */
1997#if SU_HAVE_INLINE1
1998su_inlinestatic inline
1999#endif
2000sip_from_t *sip_from_format(su_home_t *home, char const *fmt, ...)
2001 __attribute__((__malloc__, __format__ (printf, 2, 3)));
2002
2003#if SU_HAVE_INLINE1
2004su_inlinestatic inline sip_from_t *sip_from_format(su_home_t *home, char const *fmt, ...)
2005{
2006 sip_header_t *h;
2007 va_list ap;
2008
2009 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2010 h = sip_header_vformat(home, sip_from_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_from_class),
(fmt), (ap)))
;
2011 va_end(ap)__builtin_va_end(ap);
2012
2013 return (sip_from_t *)h;
2014}
2015#endif
2016
2017/** @} */
2018
2019/**@addtogroup sip_to
2020 * @{
2021 */
2022
2023/** Parse a SIP @ref sip_to "To header". @internal */
2024SOFIAPUBFUN issize_t sip_to_d(su_home_t *, msg_header_t *,
2025 char *s, isize_t slen);
2026
2027/** Print a SIP @ref sip_to "To header". @internal */
2028SOFIAPUBFUN issize_t sip_to_e(char b[], isize_t bsiz,
2029 msg_header_t const *h, int flags);
2030
2031/**Access a SIP @ref sip_to "To header"
2032 * structure #sip_to_t from #sip_t.
2033 *
2034 */
2035#define sip_to(sip)((sip_to_t *)msg_header_access((msg_pub_t*)(sip), sip_to_class
))
\
2036 ((sip_to_t *)msg_header_access((msg_pub_t*)(sip), sip_to_class))
2037
2038/**Initializer for structure #sip_to_t.
2039 *
2040 * A static #sip_to_t structure for
2041 * @ref sip_to "To header" must be initialized with
2042 * the SIP_TO_INIT() macro.
2043 * For instance,
2044 * @code
2045 *
2046 * sip_to_t sip_to = SIP_TO_INIT;
2047 *
2048 * @endcode
2049 * @HI
2050 *
2051 */
2052#define SIP_TO_INIT(){{{ 0, 0, sip_to_class }}} SIP_HDR_INIT(to){{{ 0, 0, sip_to_class }}}
2053
2054/**Initialize a structure #sip_to_t.
2055 *
2056 * An #sip_to_t structure for
2057 * @ref sip_to "To header" can be initialized with the
2058 * sip_to_init() function/macro. For instance,
2059 * @code
2060 *
2061 * sip_to_t sip_to;
2062 *
2063 * sip_to_init(&sip_to);
2064 *
2065 * @endcode
2066 * @HI
2067 *
2068 */
2069#if SU_HAVE_INLINE1
2070su_inlinestatic inline sip_to_t *sip_to_init(sip_to_t x[1])
2071{
2072 return SIP_HEADER_INIT(x, sip_to_class, sizeof(sip_to_t))((void)memset((x), 0, (sizeof(sip_to_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_to_class)), (x))
;
2073}
2074#else
2075#define sip_to_init(x) \
2076 SIP_HEADER_INIT(x, sip_to_class, sizeof(sip_to_t))((void)memset((x), 0, (sizeof(sip_to_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_to_class)), (x))
2077#endif
2078
2079/**Test if header object is instance of #sip_to_t.
2080 *
2081 * Check if the header class is an instance of
2082 * @ref sip_to "To header" object and return true (nonzero),
2083 * otherwise return false (zero).
2084 *
2085 * @param header pointer to the header structure to be tested
2086 *
2087 * @retval 1 (true) if the @a header is an instance of header to
2088 * @retval 0 (false) otherwise
2089 *
2090 */
2091#if SU_HAVE_INLINE1
2092su_inlinestatic inline int sip_is_to(sip_header_t const *header)
2093{
2094 return header && header->sh_classsh_common->h_class->hc_hash == sip_to_hash;
2095}
2096#else
2097int sip_is_to(sip_header_t const *header);
2098#endif
2099
2100#define sip_to_p(h)sip_is_to((h)) sip_is_to((h))
2101
2102
2103/**Duplicate a list of @ref sip_to "To header" header structures #sip_to_t.
2104 *
2105 * Duplicate a header
2106 * structure @a hdr. If the header structure @a hdr
2107 * contains a reference (@c hdr->x_next) to a list of
2108 * headers, all the headers in the list are duplicated, too.
2109 *
2110 * @param home memory home used to allocate new structure
2111 * @param hdr header structure to be duplicated
2112 *
2113 * When duplicating, all parameter lists and non-constant
2114 * strings attached to the header are copied, too. The
2115 * function uses given memory @a home to allocate all the
2116 * memory areas used to copy the header.
2117 *
2118 * @par Example
2119 * @code
2120 *
2121 * to = sip_to_dup(home, sip->sip_to);
2122 *
2123 * @endcode
2124 *
2125 * @return
2126 * A pointer to the
2127 * newly duplicated #sip_to_t header structure, or NULL
2128 * upon an error.
2129 *
2130 */
2131#if SU_HAVE_INLINE1
2132su_inlinestatic inline
2133#endif
2134sip_to_t *sip_to_dup(su_home_t *home, sip_to_t const *hdr)
2135 __attribute__((__malloc__));
2136
2137#if SU_HAVE_INLINE1
2138su_inlinestatic inline
2139sip_to_t *sip_to_dup(su_home_t *home, sip_to_t const *hdr)
2140{
2141 return (sip_to_t *)
2142 msg_header_dup_as(home, sip_to_class, (msg_header_t const *)hdr);
2143}
2144#endif
2145
2146/**Copy a list of @ref sip_to "To header" header structures #sip_to_t.
2147 *
2148 * The function sip_to_copy() copies a header structure @a
2149 * hdr. If the header structure @a hdr contains a reference (@c
2150 * hdr->h_next) to a list of headers, all the headers in that
2151 * list are copied, too. The function uses given memory @a home
2152 * to allocate all the memory areas used to copy the list of header
2153 * structure @a hdr.
2154 *
2155 * @param home memory home used to allocate new structure
2156 * @param hdr pointer to the header structure to be copied
2157 *
2158 * When copying, only the header structure and parameter lists attached to
2159 * it are duplicated. The new header structure retains all the references to
2160 * the strings within the old @a hdr header, including the encoding of the
2161 * old header, if present.
2162 *
2163 * @par Example
2164 * @code
2165 *
2166 * to = sip_to_copy(home, sip->sip_to);
2167 *
2168 * @endcode
2169 *
2170 * @return
2171 * A pointer to newly copied header structure, or NULL upon an error.
2172 *
2173 */
2174#if SU_HAVE_INLINE1
2175su_inlinestatic inline
2176#endif
2177sip_to_t *sip_to_copy(su_home_t *home, sip_to_t const *hdr)
2178 __attribute__((__malloc__));
2179
2180#if SU_HAVE_INLINE1
2181su_inlinestatic inline
2182sip_to_t *sip_to_copy(su_home_t *home, sip_to_t const *hdr)
2183{
2184 return (sip_to_t *)
2185 msg_header_copy_as(home, sip_to_class, (msg_header_t const *)hdr);
2186}
2187#endif
2188
2189/**Make a @ref sip_to "To header" structure #sip_to_t.
2190 *
2191 * The function sip_to_make() makes a new
2192 * #sip_to_t header structure. It allocates a new
2193 * header structure, and decodes the string @a s as the
2194 * value of the structure.
2195 *
2196 * @param home memory home used to allocate new header structure.
2197 * @param s string to be decoded as value of the new header structure
2198 *
2199 * @return
2200 * A pointer to newly maked #sip_to_t header structure, or NULL upon an
2201 * error.
2202 *
2203 */
2204#if SU_HAVE_INLINE1
2205su_inlinestatic inline
2206#endif
2207sip_to_t *sip_to_make(su_home_t *home, char const *s)
2208 __attribute__((__malloc__));
2209
2210#if SU_HAVE_INLINE1
2211su_inlinestatic inline sip_to_t *sip_to_make(su_home_t *home, char const *s)
2212{
2213 return (sip_to_t *)sip_header_make(home, sip_to_class, s)((sip_header_t *)msg_header_make((home), (sip_to_class), (s))
)
;
2214}
2215#endif
2216
2217/**Make a @ref sip_to "To header" from formatting result.
2218 *
2219 * Make a new #sip_to_t object using formatting result as its value.
2220 * The function first prints the arguments according to the format @a fmt
2221 * specified. Then it allocates a new header structure, and parses the
2222 * formatting result to the structure #sip_to_t.
2223 *
2224 * @param home memory home used to allocate new header structure.
2225 * @param fmt string used as a printf()-style format
2226 * @param ... argument list for format
2227 *
2228 * @return
2229 * A pointer to newly
2230 * makes header structure, or NULL upon an error.
2231 *
2232 * @HIDE
2233 *
2234 */
2235#if SU_HAVE_INLINE1
2236su_inlinestatic inline
2237#endif
2238sip_to_t *sip_to_format(su_home_t *home, char const *fmt, ...)
2239 __attribute__((__malloc__, __format__ (printf, 2, 3)));
2240
2241#if SU_HAVE_INLINE1
2242su_inlinestatic inline sip_to_t *sip_to_format(su_home_t *home, char const *fmt, ...)
2243{
2244 sip_header_t *h;
2245 va_list ap;
2246
2247 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2248 h = sip_header_vformat(home, sip_to_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_to_class), (
fmt), (ap)))
;
2249 va_end(ap)__builtin_va_end(ap);
2250
2251 return (sip_to_t *)h;
2252}
2253#endif
2254
2255/** @} */
2256
2257/**@addtogroup sip_call_id
2258 * @{
2259 */
2260
2261/** Parse a SIP @ref sip_call_id "Call-ID header". @internal */
2262SOFIAPUBFUN issize_t sip_call_id_d(su_home_t *, msg_header_t *,
2263 char *s, isize_t slen);
2264
2265/** Print a SIP @ref sip_call_id "Call-ID header". @internal */
2266SOFIAPUBFUN issize_t sip_call_id_e(char b[], isize_t bsiz,
2267 msg_header_t const *h, int flags);
2268
2269/**Access a SIP @ref sip_call_id "Call-ID header"
2270 * structure #sip_call_id_t from #sip_t.
2271 *
2272 */
2273#define sip_call_id(sip)((sip_call_id_t *)msg_header_access((msg_pub_t*)(sip), sip_call_id_class
))
\
2274 ((sip_call_id_t *)msg_header_access((msg_pub_t*)(sip), sip_call_id_class))
2275
2276/**Initializer for structure #sip_call_id_t.
2277 *
2278 * A static #sip_call_id_t structure for
2279 * @ref sip_call_id "Call-ID header" must be initialized with
2280 * the SIP_CALL_ID_INIT() macro.
2281 * For instance,
2282 * @code
2283 *
2284 * sip_call_id_t sip_call_id = SIP_CALL_ID_INIT;
2285 *
2286 * @endcode
2287 * @HI
2288 *
2289 */
2290#define SIP_CALL_ID_INIT(){{{ 0, 0, sip_call_id_class }}} SIP_HDR_INIT(call_id){{{ 0, 0, sip_call_id_class }}}
2291
2292/**Initialize a structure #sip_call_id_t.
2293 *
2294 * An #sip_call_id_t structure for
2295 * @ref sip_call_id "Call-ID header" can be initialized with the
2296 * sip_call_id_init() function/macro. For instance,
2297 * @code
2298 *
2299 * sip_call_id_t sip_call_id;
2300 *
2301 * sip_call_id_init(&sip_call_id);
2302 *
2303 * @endcode
2304 * @HI
2305 *
2306 */
2307#if SU_HAVE_INLINE1
2308su_inlinestatic inline sip_call_id_t *sip_call_id_init(sip_call_id_t x[1])
2309{
2310 return SIP_HEADER_INIT(x, sip_call_id_class, sizeof(sip_call_id_t))((void)memset((x), 0, (sizeof(sip_call_id_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_call_id_class)), (x))
;
2311}
2312#else
2313#define sip_call_id_init(x) \
2314 SIP_HEADER_INIT(x, sip_call_id_class, sizeof(sip_call_id_t))((void)memset((x), 0, (sizeof(sip_call_id_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_call_id_class)), (x))
2315#endif
2316
2317/**Test if header object is instance of #sip_call_id_t.
2318 *
2319 * Check if the header class is an instance of
2320 * @ref sip_call_id "Call-ID header" object and return true (nonzero),
2321 * otherwise return false (zero).
2322 *
2323 * @param header pointer to the header structure to be tested
2324 *
2325 * @retval 1 (true) if the @a header is an instance of header call_id
2326 * @retval 0 (false) otherwise
2327 *
2328 */
2329#if SU_HAVE_INLINE1
2330su_inlinestatic inline int sip_is_call_id(sip_header_t const *header)
2331{
2332 return header && header->sh_classsh_common->h_class->hc_hash == sip_call_id_hash;
2333}
2334#else
2335int sip_is_call_id(sip_header_t const *header);
2336#endif
2337
2338#define sip_call_id_p(h)sip_is_call_id((h)) sip_is_call_id((h))
2339
2340
2341/**Duplicate a list of @ref sip_call_id "Call-ID header" header structures #sip_call_id_t.
2342 *
2343 * Duplicate a header
2344 * structure @a hdr. If the header structure @a hdr
2345 * contains a reference (@c hdr->x_next) to a list of
2346 * headers, all the headers in the list are duplicated, too.
2347 *
2348 * @param home memory home used to allocate new structure
2349 * @param hdr header structure to be duplicated
2350 *
2351 * When duplicating, all parameter lists and non-constant
2352 * strings attached to the header are copied, too. The
2353 * function uses given memory @a home to allocate all the
2354 * memory areas used to copy the header.
2355 *
2356 * @par Example
2357 * @code
2358 *
2359 * call_id = sip_call_id_dup(home, sip->sip_call_id);
2360 *
2361 * @endcode
2362 *
2363 * @return
2364 * A pointer to the
2365 * newly duplicated #sip_call_id_t header structure, or NULL
2366 * upon an error.
2367 *
2368 */
2369#if SU_HAVE_INLINE1
2370su_inlinestatic inline
2371#endif
2372sip_call_id_t *sip_call_id_dup(su_home_t *home, sip_call_id_t const *hdr)
2373 __attribute__((__malloc__));
2374
2375#if SU_HAVE_INLINE1
2376su_inlinestatic inline
2377sip_call_id_t *sip_call_id_dup(su_home_t *home, sip_call_id_t const *hdr)
2378{
2379 return (sip_call_id_t *)
2380 msg_header_dup_as(home, sip_call_id_class, (msg_header_t const *)hdr);
2381}
2382#endif
2383
2384/**Copy a list of @ref sip_call_id "Call-ID header" header structures #sip_call_id_t.
2385 *
2386 * The function sip_call_id_copy() copies a header structure @a
2387 * hdr. If the header structure @a hdr contains a reference (@c
2388 * hdr->h_next) to a list of headers, all the headers in that
2389 * list are copied, too. The function uses given memory @a home
2390 * to allocate all the memory areas used to copy the list of header
2391 * structure @a hdr.
2392 *
2393 * @param home memory home used to allocate new structure
2394 * @param hdr pointer to the header structure to be copied
2395 *
2396 * When copying, only the header structure and parameter lists attached to
2397 * it are duplicated. The new header structure retains all the references to
2398 * the strings within the old @a hdr header, including the encoding of the
2399 * old header, if present.
2400 *
2401 * @par Example
2402 * @code
2403 *
2404 * call_id = sip_call_id_copy(home, sip->sip_call_id);
2405 *
2406 * @endcode
2407 *
2408 * @return
2409 * A pointer to newly copied header structure, or NULL upon an error.
2410 *
2411 */
2412#if SU_HAVE_INLINE1
2413su_inlinestatic inline
2414#endif
2415sip_call_id_t *sip_call_id_copy(su_home_t *home, sip_call_id_t const *hdr)
2416 __attribute__((__malloc__));
2417
2418#if SU_HAVE_INLINE1
2419su_inlinestatic inline
2420sip_call_id_t *sip_call_id_copy(su_home_t *home, sip_call_id_t const *hdr)
2421{
2422 return (sip_call_id_t *)
2423 msg_header_copy_as(home, sip_call_id_class, (msg_header_t const *)hdr);
2424}
2425#endif
2426
2427/**Make a @ref sip_call_id "Call-ID header" structure #sip_call_id_t.
2428 *
2429 * The function sip_call_id_make() makes a new
2430 * #sip_call_id_t header structure. It allocates a new
2431 * header structure, and decodes the string @a s as the
2432 * value of the structure.
2433 *
2434 * @param home memory home used to allocate new header structure.
2435 * @param s string to be decoded as value of the new header structure
2436 *
2437 * @return
2438 * A pointer to newly maked #sip_call_id_t header structure, or NULL upon an
2439 * error.
2440 *
2441 */
2442#if SU_HAVE_INLINE1
2443su_inlinestatic inline
2444#endif
2445sip_call_id_t *sip_call_id_make(su_home_t *home, char const *s)
2446 __attribute__((__malloc__));
2447
2448#if SU_HAVE_INLINE1
2449su_inlinestatic inline sip_call_id_t *sip_call_id_make(su_home_t *home, char const *s)
2450{
2451 return (sip_call_id_t *)sip_header_make(home, sip_call_id_class, s)((sip_header_t *)msg_header_make((home), (sip_call_id_class),
(s)))
;
2452}
2453#endif
2454
2455/**Make a @ref sip_call_id "Call-ID header" from formatting result.
2456 *
2457 * Make a new #sip_call_id_t object using formatting result as its value.
2458 * The function first prints the arguments according to the format @a fmt
2459 * specified. Then it allocates a new header structure, and parses the
2460 * formatting result to the structure #sip_call_id_t.
2461 *
2462 * @param home memory home used to allocate new header structure.
2463 * @param fmt string used as a printf()-style format
2464 * @param ... argument list for format
2465 *
2466 * @return
2467 * A pointer to newly
2468 * makes header structure, or NULL upon an error.
2469 *
2470 * @HIDE
2471 *
2472 */
2473#if SU_HAVE_INLINE1
2474su_inlinestatic inline
2475#endif
2476sip_call_id_t *sip_call_id_format(su_home_t *home, char const *fmt, ...)
2477 __attribute__((__malloc__, __format__ (printf, 2, 3)));
2478
2479#if SU_HAVE_INLINE1
2480su_inlinestatic inline sip_call_id_t *sip_call_id_format(su_home_t *home, char const *fmt, ...)
2481{
2482 sip_header_t *h;
2483 va_list ap;
2484
2485 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2486 h = sip_header_vformat(home, sip_call_id_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_call_id_class
), (fmt), (ap)))
;
2487 va_end(ap)__builtin_va_end(ap);
2488
2489 return (sip_call_id_t *)h;
2490}
2491#endif
2492
2493/** @} */
2494
2495/**@addtogroup sip_cseq
2496 * @{
2497 */
2498
2499/** Parse a SIP @ref sip_cseq "CSeq header". @internal */
2500SOFIAPUBFUN issize_t sip_cseq_d(su_home_t *, msg_header_t *,
2501 char *s, isize_t slen);
2502
2503/** Print a SIP @ref sip_cseq "CSeq header". @internal */
2504SOFIAPUBFUN issize_t sip_cseq_e(char b[], isize_t bsiz,
2505 msg_header_t const *h, int flags);
2506
2507/**Access a SIP @ref sip_cseq "CSeq header"
2508 * structure #sip_cseq_t from #sip_t.
2509 *
2510 */
2511#define sip_cseq(sip)((sip_cseq_t *)msg_header_access((msg_pub_t*)(sip), sip_cseq_class
))
\
2512 ((sip_cseq_t *)msg_header_access((msg_pub_t*)(sip), sip_cseq_class))
2513
2514/**Initializer for structure #sip_cseq_t.
2515 *
2516 * A static #sip_cseq_t structure for
2517 * @ref sip_cseq "CSeq header" must be initialized with
2518 * the SIP_CSEQ_INIT() macro.
2519 * For instance,
2520 * @code
2521 *
2522 * sip_cseq_t sip_cseq = SIP_CSEQ_INIT;
2523 *
2524 * @endcode
2525 * @HI
2526 *
2527 */
2528#define SIP_CSEQ_INIT(){{{ 0, 0, sip_cseq_class }}} SIP_HDR_INIT(cseq){{{ 0, 0, sip_cseq_class }}}
2529
2530/**Initialize a structure #sip_cseq_t.
2531 *
2532 * An #sip_cseq_t structure for
2533 * @ref sip_cseq "CSeq header" can be initialized with the
2534 * sip_cseq_init() function/macro. For instance,
2535 * @code
2536 *
2537 * sip_cseq_t sip_cseq;
2538 *
2539 * sip_cseq_init(&sip_cseq);
2540 *
2541 * @endcode
2542 * @HI
2543 *
2544 */
2545#if SU_HAVE_INLINE1
2546su_inlinestatic inline sip_cseq_t *sip_cseq_init(sip_cseq_t x[1])
2547{
2548 return SIP_HEADER_INIT(x, sip_cseq_class, sizeof(sip_cseq_t))((void)memset((x), 0, (sizeof(sip_cseq_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_cseq_class)), (x))
;
2549}
2550#else
2551#define sip_cseq_init(x) \
2552 SIP_HEADER_INIT(x, sip_cseq_class, sizeof(sip_cseq_t))((void)memset((x), 0, (sizeof(sip_cseq_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_cseq_class)), (x))
2553#endif
2554
2555/**Test if header object is instance of #sip_cseq_t.
2556 *
2557 * Check if the header class is an instance of
2558 * @ref sip_cseq "CSeq header" object and return true (nonzero),
2559 * otherwise return false (zero).
2560 *
2561 * @param header pointer to the header structure to be tested
2562 *
2563 * @retval 1 (true) if the @a header is an instance of header cseq
2564 * @retval 0 (false) otherwise
2565 *
2566 */
2567#if SU_HAVE_INLINE1
2568su_inlinestatic inline int sip_is_cseq(sip_header_t const *header)
2569{
2570 return header && header->sh_classsh_common->h_class->hc_hash == sip_cseq_hash;
2571}
2572#else
2573int sip_is_cseq(sip_header_t const *header);
2574#endif
2575
2576#define sip_cseq_p(h)sip_is_cseq((h)) sip_is_cseq((h))
2577
2578
2579/**Duplicate a list of @ref sip_cseq "CSeq header" header structures #sip_cseq_t.
2580 *
2581 * Duplicate a header
2582 * structure @a hdr. If the header structure @a hdr
2583 * contains a reference (@c hdr->x_next) to a list of
2584 * headers, all the headers in the list are duplicated, too.
2585 *
2586 * @param home memory home used to allocate new structure
2587 * @param hdr header structure to be duplicated
2588 *
2589 * When duplicating, all parameter lists and non-constant
2590 * strings attached to the header are copied, too. The
2591 * function uses given memory @a home to allocate all the
2592 * memory areas used to copy the header.
2593 *
2594 * @par Example
2595 * @code
2596 *
2597 * cseq = sip_cseq_dup(home, sip->sip_cseq);
2598 *
2599 * @endcode
2600 *
2601 * @return
2602 * A pointer to the
2603 * newly duplicated #sip_cseq_t header structure, or NULL
2604 * upon an error.
2605 *
2606 */
2607#if SU_HAVE_INLINE1
2608su_inlinestatic inline
2609#endif
2610sip_cseq_t *sip_cseq_dup(su_home_t *home, sip_cseq_t const *hdr)
2611 __attribute__((__malloc__));
2612
2613#if SU_HAVE_INLINE1
2614su_inlinestatic inline
2615sip_cseq_t *sip_cseq_dup(su_home_t *home, sip_cseq_t const *hdr)
2616{
2617 return (sip_cseq_t *)
2618 msg_header_dup_as(home, sip_cseq_class, (msg_header_t const *)hdr);
2619}
2620#endif
2621
2622/**Copy a list of @ref sip_cseq "CSeq header" header structures #sip_cseq_t.
2623 *
2624 * The function sip_cseq_copy() copies a header structure @a
2625 * hdr. If the header structure @a hdr contains a reference (@c
2626 * hdr->h_next) to a list of headers, all the headers in that
2627 * list are copied, too. The function uses given memory @a home
2628 * to allocate all the memory areas used to copy the list of header
2629 * structure @a hdr.
2630 *
2631 * @param home memory home used to allocate new structure
2632 * @param hdr pointer to the header structure to be copied
2633 *
2634 * When copying, only the header structure and parameter lists attached to
2635 * it are duplicated. The new header structure retains all the references to
2636 * the strings within the old @a hdr header, including the encoding of the
2637 * old header, if present.
2638 *
2639 * @par Example
2640 * @code
2641 *
2642 * cseq = sip_cseq_copy(home, sip->sip_cseq);
2643 *
2644 * @endcode
2645 *
2646 * @return
2647 * A pointer to newly copied header structure, or NULL upon an error.
2648 *
2649 */
2650#if SU_HAVE_INLINE1
2651su_inlinestatic inline
2652#endif
2653sip_cseq_t *sip_cseq_copy(su_home_t *home, sip_cseq_t const *hdr)
2654 __attribute__((__malloc__));
2655
2656#if SU_HAVE_INLINE1
2657su_inlinestatic inline
2658sip_cseq_t *sip_cseq_copy(su_home_t *home, sip_cseq_t const *hdr)
2659{
2660 return (sip_cseq_t *)
2661 msg_header_copy_as(home, sip_cseq_class, (msg_header_t const *)hdr);
2662}
2663#endif
2664
2665/**Make a @ref sip_cseq "CSeq header" structure #sip_cseq_t.
2666 *
2667 * The function sip_cseq_make() makes a new
2668 * #sip_cseq_t header structure. It allocates a new
2669 * header structure, and decodes the string @a s as the
2670 * value of the structure.
2671 *
2672 * @param home memory home used to allocate new header structure.
2673 * @param s string to be decoded as value of the new header structure
2674 *
2675 * @return
2676 * A pointer to newly maked #sip_cseq_t header structure, or NULL upon an
2677 * error.
2678 *
2679 */
2680#if SU_HAVE_INLINE1
2681su_inlinestatic inline
2682#endif
2683sip_cseq_t *sip_cseq_make(su_home_t *home, char const *s)
2684 __attribute__((__malloc__));
2685
2686#if SU_HAVE_INLINE1
2687su_inlinestatic inline sip_cseq_t *sip_cseq_make(su_home_t *home, char const *s)
2688{
2689 return (sip_cseq_t *)sip_header_make(home, sip_cseq_class, s)((sip_header_t *)msg_header_make((home), (sip_cseq_class), (s
)))
;
2690}
2691#endif
2692
2693/**Make a @ref sip_cseq "CSeq header" from formatting result.
2694 *
2695 * Make a new #sip_cseq_t object using formatting result as its value.
2696 * The function first prints the arguments according to the format @a fmt
2697 * specified. Then it allocates a new header structure, and parses the
2698 * formatting result to the structure #sip_cseq_t.
2699 *
2700 * @param home memory home used to allocate new header structure.
2701 * @param fmt string used as a printf()-style format
2702 * @param ... argument list for format
2703 *
2704 * @return
2705 * A pointer to newly
2706 * makes header structure, or NULL upon an error.
2707 *
2708 * @HIDE
2709 *
2710 */
2711#if SU_HAVE_INLINE1
2712su_inlinestatic inline
2713#endif
2714sip_cseq_t *sip_cseq_format(su_home_t *home, char const *fmt, ...)
2715 __attribute__((__malloc__, __format__ (printf, 2, 3)));
2716
2717#if SU_HAVE_INLINE1
2718su_inlinestatic inline sip_cseq_t *sip_cseq_format(su_home_t *home, char const *fmt, ...)
2719{
2720 sip_header_t *h;
2721 va_list ap;
2722
2723 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2724 h = sip_header_vformat(home, sip_cseq_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_cseq_class),
(fmt), (ap)))
;
2725 va_end(ap)__builtin_va_end(ap);
2726
2727 return (sip_cseq_t *)h;
2728}
2729#endif
2730
2731/** @} */
2732
2733/**@addtogroup sip_identity
2734 * @{
2735 */
2736
2737/** Parse a SIP @ref sip_identity "Identity header". @internal */
2738SOFIAPUBFUN issize_t sip_identity_d(su_home_t *, msg_header_t *,
2739 char *s, isize_t slen);
2740
2741/** Print a SIP @ref sip_identity "Identity header". @internal */
2742SOFIAPUBFUN issize_t sip_identity_e(char b[], isize_t bsiz,
2743 msg_header_t const *h, int flags);
2744
2745/**Access a SIP @ref sip_identity "Identity header"
2746 * structure #sip_identity_t from #sip_t.
2747 *
2748 */
2749#define sip_identity(sip)((sip_identity_t *)msg_header_access((msg_pub_t*)(sip), sip_identity_class
))
\
2750 ((sip_identity_t *)msg_header_access((msg_pub_t*)(sip), sip_identity_class))
2751
2752/**Initializer for structure #sip_identity_t.
2753 *
2754 * A static #sip_identity_t structure for
2755 * @ref sip_identity "Identity header" must be initialized with
2756 * the SIP_IDENTITY_INIT() macro.
2757 * For instance,
2758 * @code
2759 *
2760 * sip_identity_t sip_identity = SIP_IDENTITY_INIT;
2761 *
2762 * @endcode
2763 * @HI
2764 *
2765 */
2766#define SIP_IDENTITY_INIT(){{{ 0, 0, sip_identity_class }}} SIP_HDR_INIT(identity){{{ 0, 0, sip_identity_class }}}
2767
2768/**Initialize a structure #sip_identity_t.
2769 *
2770 * An #sip_identity_t structure for
2771 * @ref sip_identity "Identity header" can be initialized with the
2772 * sip_identity_init() function/macro. For instance,
2773 * @code
2774 *
2775 * sip_identity_t sip_identity;
2776 *
2777 * sip_identity_init(&sip_identity);
2778 *
2779 * @endcode
2780 * @HI
2781 *
2782 */
2783#if SU_HAVE_INLINE1
2784su_inlinestatic inline sip_identity_t *sip_identity_init(sip_identity_t x[1])
2785{
2786 return SIP_HEADER_INIT(x, sip_identity_class, sizeof(sip_identity_t))((void)memset((x), 0, (sizeof(sip_identity_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_identity_class)), (x))
;
2787}
2788#else
2789#define sip_identity_init(x) \
2790 SIP_HEADER_INIT(x, sip_identity_class, sizeof(sip_identity_t))((void)memset((x), 0, (sizeof(sip_identity_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_identity_class)), (x))
2791#endif
2792
2793/**Test if header object is instance of #sip_identity_t.
2794 *
2795 * Check if the header class is an instance of
2796 * @ref sip_identity "Identity header" object and return true (nonzero),
2797 * otherwise return false (zero).
2798 *
2799 * @param header pointer to the header structure to be tested
2800 *
2801 * @retval 1 (true) if the @a header is an instance of header identity
2802 * @retval 0 (false) otherwise
2803 *
2804 */
2805#if SU_HAVE_INLINE1
2806su_inlinestatic inline int sip_is_identity(sip_header_t const *header)
2807{
2808 return header && header->sh_classsh_common->h_class->hc_hash == sip_identity_hash;
2809}
2810#else
2811int sip_is_identity(sip_header_t const *header);
2812#endif
2813
2814#define sip_identity_p(h)sip_is_identity((h)) sip_is_identity((h))
2815
2816
2817/**Duplicate a list of @ref sip_identity "Identity header" header structures #sip_identity_t.
2818 *
2819 * Duplicate a header
2820 * structure @a hdr. If the header structure @a hdr
2821 * contains a reference (@c hdr->x_next) to a list of
2822 * headers, all the headers in the list are duplicated, too.
2823 *
2824 * @param home memory home used to allocate new structure
2825 * @param hdr header structure to be duplicated
2826 *
2827 * When duplicating, all parameter lists and non-constant
2828 * strings attached to the header are copied, too. The
2829 * function uses given memory @a home to allocate all the
2830 * memory areas used to copy the header.
2831 *
2832 * @par Example
2833 * @code
2834 *
2835 * identity = sip_identity_dup(home, sip->sip_identity);
2836 *
2837 * @endcode
2838 *
2839 * @return
2840 * A pointer to the
2841 * newly duplicated #sip_identity_t header structure, or NULL
2842 * upon an error.
2843 *
2844 */
2845#if SU_HAVE_INLINE1
2846su_inlinestatic inline
2847#endif
2848sip_identity_t *sip_identity_dup(su_home_t *home, sip_identity_t const *hdr)
2849 __attribute__((__malloc__));
2850
2851#if SU_HAVE_INLINE1
2852su_inlinestatic inline
2853sip_identity_t *sip_identity_dup(su_home_t *home, sip_identity_t const *hdr)
2854{
2855 return (sip_identity_t *)
2856 msg_header_dup_as(home, sip_identity_class, (msg_header_t const *)hdr);
2857}
2858#endif
2859
2860/**Copy a list of @ref sip_identity "Identity header" header structures #sip_identity_t.
2861 *
2862 * The function sip_identity_copy() copies a header structure @a
2863 * hdr. If the header structure @a hdr contains a reference (@c
2864 * hdr->h_next) to a list of headers, all the headers in that
2865 * list are copied, too. The function uses given memory @a home
2866 * to allocate all the memory areas used to copy the list of header
2867 * structure @a hdr.
2868 *
2869 * @param home memory home used to allocate new structure
2870 * @param hdr pointer to the header structure to be copied
2871 *
2872 * When copying, only the header structure and parameter lists attached to
2873 * it are duplicated. The new header structure retains all the references to
2874 * the strings within the old @a hdr header, including the encoding of the
2875 * old header, if present.
2876 *
2877 * @par Example
2878 * @code
2879 *
2880 * identity = sip_identity_copy(home, sip->sip_identity);
2881 *
2882 * @endcode
2883 *
2884 * @return
2885 * A pointer to newly copied header structure, or NULL upon an error.
2886 *
2887 */
2888#if SU_HAVE_INLINE1
2889su_inlinestatic inline
2890#endif
2891sip_identity_t *sip_identity_copy(su_home_t *home, sip_identity_t const *hdr)
2892 __attribute__((__malloc__));
2893
2894#if SU_HAVE_INLINE1
2895su_inlinestatic inline
2896sip_identity_t *sip_identity_copy(su_home_t *home, sip_identity_t const *hdr)
2897{
2898 return (sip_identity_t *)
2899 msg_header_copy_as(home, sip_identity_class, (msg_header_t const *)hdr);
2900}
2901#endif
2902
2903/**Make a @ref sip_identity "Identity header" structure #sip_identity_t.
2904 *
2905 * The function sip_identity_make() makes a new
2906 * #sip_identity_t header structure. It allocates a new
2907 * header structure, and decodes the string @a s as the
2908 * value of the structure.
2909 *
2910 * @param home memory home used to allocate new header structure.
2911 * @param s string to be decoded as value of the new header structure
2912 *
2913 * @return
2914 * A pointer to newly maked #sip_identity_t header structure, or NULL upon an
2915 * error.
2916 *
2917 */
2918#if SU_HAVE_INLINE1
2919su_inlinestatic inline
2920#endif
2921sip_identity_t *sip_identity_make(su_home_t *home, char const *s)
2922 __attribute__((__malloc__));
2923
2924#if SU_HAVE_INLINE1
2925su_inlinestatic inline sip_identity_t *sip_identity_make(su_home_t *home, char const *s)
2926{
2927 return (sip_identity_t *)sip_header_make(home, sip_identity_class, s)((sip_header_t *)msg_header_make((home), (sip_identity_class)
, (s)))
;
2928}
2929#endif
2930
2931/**Make a @ref sip_identity "Identity header" from formatting result.
2932 *
2933 * Make a new #sip_identity_t object using formatting result as its value.
2934 * The function first prints the arguments according to the format @a fmt
2935 * specified. Then it allocates a new header structure, and parses the
2936 * formatting result to the structure #sip_identity_t.
2937 *
2938 * @param home memory home used to allocate new header structure.
2939 * @param fmt string used as a printf()-style format
2940 * @param ... argument list for format
2941 *
2942 * @return
2943 * A pointer to newly
2944 * makes header structure, or NULL upon an error.
2945 *
2946 * @HIDE
2947 *
2948 */
2949#if SU_HAVE_INLINE1
2950su_inlinestatic inline
2951#endif
2952sip_identity_t *sip_identity_format(su_home_t *home, char const *fmt, ...)
2953 __attribute__((__malloc__, __format__ (printf, 2, 3)));
2954
2955#if SU_HAVE_INLINE1
2956su_inlinestatic inline sip_identity_t *sip_identity_format(su_home_t *home, char const *fmt, ...)
2957{
2958 sip_header_t *h;
2959 va_list ap;
2960
2961 va_start(ap, fmt)__builtin_va_start(ap, fmt);
2962 h = sip_header_vformat(home, sip_identity_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_identity_class
), (fmt), (ap)))
;
2963 va_end(ap)__builtin_va_end(ap);
2964
2965 return (sip_identity_t *)h;
2966}
2967#endif
2968
2969/** @} */
2970
2971/**@addtogroup sip_contact
2972 * @{
2973 */
2974
2975/** Parse a SIP @ref sip_contact "Contact header". @internal */
2976SOFIAPUBFUN issize_t sip_contact_d(su_home_t *, msg_header_t *,
2977 char *s, isize_t slen);
2978
2979/** Print a SIP @ref sip_contact "Contact header". @internal */
2980SOFIAPUBFUN issize_t sip_contact_e(char b[], isize_t bsiz,
2981 msg_header_t const *h, int flags);
2982
2983/**Access a SIP @ref sip_contact "Contact header"
2984 * structure #sip_contact_t from #sip_t.
2985 *
2986 */
2987#define sip_contact(sip)((sip_contact_t *)msg_header_access((msg_pub_t*)(sip), sip_contact_class
))
\
2988 ((sip_contact_t *)msg_header_access((msg_pub_t*)(sip), sip_contact_class))
2989
2990/**Initializer for structure #sip_contact_t.
2991 *
2992 * A static #sip_contact_t structure for
2993 * @ref sip_contact "Contact header" must be initialized with
2994 * the SIP_CONTACT_INIT() macro.
2995 * For instance,
2996 * @code
2997 *
2998 * sip_contact_t sip_contact = SIP_CONTACT_INIT;
2999 *
3000 * @endcode
3001 * @HI
3002 *
3003 */
3004#define SIP_CONTACT_INIT(){{{ 0, 0, sip_contact_class }}} SIP_HDR_INIT(contact){{{ 0, 0, sip_contact_class }}}
3005
3006/**Initialize a structure #sip_contact_t.
3007 *
3008 * An #sip_contact_t structure for
3009 * @ref sip_contact "Contact header" can be initialized with the
3010 * sip_contact_init() function/macro. For instance,
3011 * @code
3012 *
3013 * sip_contact_t sip_contact;
3014 *
3015 * sip_contact_init(&sip_contact);
3016 *
3017 * @endcode
3018 * @HI
3019 *
3020 */
3021#if SU_HAVE_INLINE1
3022su_inlinestatic inline sip_contact_t *sip_contact_init(sip_contact_t x[1])
3023{
3024 return SIP_HEADER_INIT(x, sip_contact_class, sizeof(sip_contact_t))((void)memset((x), 0, (sizeof(sip_contact_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_contact_class)), (x))
;
3025}
3026#else
3027#define sip_contact_init(x) \
3028 SIP_HEADER_INIT(x, sip_contact_class, sizeof(sip_contact_t))((void)memset((x), 0, (sizeof(sip_contact_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_contact_class)), (x))
3029#endif
3030
3031/**Test if header object is instance of #sip_contact_t.
3032 *
3033 * Check if the header class is an instance of
3034 * @ref sip_contact "Contact header" object and return true (nonzero),
3035 * otherwise return false (zero).
3036 *
3037 * @param header pointer to the header structure to be tested
3038 *
3039 * @retval 1 (true) if the @a header is an instance of header contact
3040 * @retval 0 (false) otherwise
3041 *
3042 */
3043#if SU_HAVE_INLINE1
3044su_inlinestatic inline int sip_is_contact(sip_header_t const *header)
3045{
3046 return header && header->sh_classsh_common->h_class->hc_hash == sip_contact_hash;
3047}
3048#else
3049int sip_is_contact(sip_header_t const *header);
3050#endif
3051
3052#define sip_contact_p(h)sip_is_contact((h)) sip_is_contact((h))
3053
3054
3055/**Duplicate a list of @ref sip_contact "Contact header" header structures #sip_contact_t.
3056 *
3057 * Duplicate a header
3058 * structure @a hdr. If the header structure @a hdr
3059 * contains a reference (@c hdr->x_next) to a list of
3060 * headers, all the headers in the list are duplicated, too.
3061 *
3062 * @param home memory home used to allocate new structure
3063 * @param hdr header structure to be duplicated
3064 *
3065 * When duplicating, all parameter lists and non-constant
3066 * strings attached to the header are copied, too. The
3067 * function uses given memory @a home to allocate all the
3068 * memory areas used to copy the header.
3069 *
3070 * @par Example
3071 * @code
3072 *
3073 * contact = sip_contact_dup(home, sip->sip_contact);
3074 *
3075 * @endcode
3076 *
3077 * @return
3078 * A pointer to the
3079 * newly duplicated #sip_contact_t header structure, or NULL
3080 * upon an error.
3081 *
3082 */
3083#if SU_HAVE_INLINE1
3084su_inlinestatic inline
3085#endif
3086sip_contact_t *sip_contact_dup(su_home_t *home, sip_contact_t const *hdr)
3087 __attribute__((__malloc__));
3088
3089#if SU_HAVE_INLINE1
3090su_inlinestatic inline
3091sip_contact_t *sip_contact_dup(su_home_t *home, sip_contact_t const *hdr)
3092{
3093 return (sip_contact_t *)
3094 msg_header_dup_as(home, sip_contact_class, (msg_header_t const *)hdr);
3095}
3096#endif
3097
3098/**Copy a list of @ref sip_contact "Contact header" header structures #sip_contact_t.
3099 *
3100 * The function sip_contact_copy() copies a header structure @a
3101 * hdr. If the header structure @a hdr contains a reference (@c
3102 * hdr->h_next) to a list of headers, all the headers in that
3103 * list are copied, too. The function uses given memory @a home
3104 * to allocate all the memory areas used to copy the list of header
3105 * structure @a hdr.
3106 *
3107 * @param home memory home used to allocate new structure
3108 * @param hdr pointer to the header structure to be copied
3109 *
3110 * When copying, only the header structure and parameter lists attached to
3111 * it are duplicated. The new header structure retains all the references to
3112 * the strings within the old @a hdr header, including the encoding of the
3113 * old header, if present.
3114 *
3115 * @par Example
3116 * @code
3117 *
3118 * contact = sip_contact_copy(home, sip->sip_contact);
3119 *
3120 * @endcode
3121 *
3122 * @return
3123 * A pointer to newly copied header structure, or NULL upon an error.
3124 *
3125 */
3126#if SU_HAVE_INLINE1
3127su_inlinestatic inline
3128#endif
3129sip_contact_t *sip_contact_copy(su_home_t *home, sip_contact_t const *hdr)
3130 __attribute__((__malloc__));
3131
3132#if SU_HAVE_INLINE1
3133su_inlinestatic inline
3134sip_contact_t *sip_contact_copy(su_home_t *home, sip_contact_t const *hdr)
3135{
3136 return (sip_contact_t *)
3137 msg_header_copy_as(home, sip_contact_class, (msg_header_t const *)hdr);
3138}
3139#endif
3140
3141/**Make a @ref sip_contact "Contact header" structure #sip_contact_t.
3142 *
3143 * The function sip_contact_make() makes a new
3144 * #sip_contact_t header structure. It allocates a new
3145 * header structure, and decodes the string @a s as the
3146 * value of the structure.
3147 *
3148 * @param home memory home used to allocate new header structure.
3149 * @param s string to be decoded as value of the new header structure
3150 *
3151 * @return
3152 * A pointer to newly maked #sip_contact_t header structure, or NULL upon an
3153 * error.
3154 *
3155 */
3156#if SU_HAVE_INLINE1
3157su_inlinestatic inline
3158#endif
3159sip_contact_t *sip_contact_make(su_home_t *home, char const *s)
3160 __attribute__((__malloc__));
3161
3162#if SU_HAVE_INLINE1
3163su_inlinestatic inline sip_contact_t *sip_contact_make(su_home_t *home, char const *s)
3164{
3165 return (sip_contact_t *)sip_header_make(home, sip_contact_class, s)((sip_header_t *)msg_header_make((home), (sip_contact_class),
(s)))
;
3166}
3167#endif
3168
3169/**Make a @ref sip_contact "Contact header" from formatting result.
3170 *
3171 * Make a new #sip_contact_t object using formatting result as its value.
3172 * The function first prints the arguments according to the format @a fmt
3173 * specified. Then it allocates a new header structure, and parses the
3174 * formatting result to the structure #sip_contact_t.
3175 *
3176 * @param home memory home used to allocate new header structure.
3177 * @param fmt string used as a printf()-style format
3178 * @param ... argument list for format
3179 *
3180 * @return
3181 * A pointer to newly
3182 * makes header structure, or NULL upon an error.
3183 *
3184 * @HIDE
3185 *
3186 */
3187#if SU_HAVE_INLINE1
3188su_inlinestatic inline
3189#endif
3190sip_contact_t *sip_contact_format(su_home_t *home, char const *fmt, ...)
3191 __attribute__((__malloc__, __format__ (printf, 2, 3)));
3192
3193#if SU_HAVE_INLINE1
3194su_inlinestatic inline sip_contact_t *sip_contact_format(su_home_t *home, char const *fmt, ...)
3195{
3196 sip_header_t *h;
3197 va_list ap;
3198
3199 va_start(ap, fmt)__builtin_va_start(ap, fmt);
3200 h = sip_header_vformat(home, sip_contact_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_contact_class
), (fmt), (ap)))
;
3201 va_end(ap)__builtin_va_end(ap);
3202
3203 return (sip_contact_t *)h;
3204}
3205#endif
3206
3207/** @} */
3208
3209/**@addtogroup sip_rseq
3210 * @{
3211 */
3212
3213/** Parse a SIP @ref sip_rseq "RSeq header". @internal */
3214SOFIAPUBFUN issize_t sip_rseq_d(su_home_t *, msg_header_t *,
3215 char *s, isize_t slen);
3216
3217/** Print a SIP @ref sip_rseq "RSeq header". @internal */
3218SOFIAPUBFUN issize_t sip_rseq_e(char b[], isize_t bsiz,
3219 msg_header_t const *h, int flags);
3220
3221/**Access a SIP @ref sip_rseq "RSeq header"
3222 * structure #sip_rseq_t from #sip_t.
3223 *
3224 */
3225#define sip_rseq(sip)((sip_rseq_t *)msg_header_access((msg_pub_t*)(sip), sip_rseq_class
))
\
3226 ((sip_rseq_t *)msg_header_access((msg_pub_t*)(sip), sip_rseq_class))
3227
3228/**Initializer for structure #sip_rseq_t.
3229 *
3230 * A static #sip_rseq_t structure for
3231 * @ref sip_rseq "RSeq header" must be initialized with
3232 * the SIP_RSEQ_INIT() macro.
3233 * For instance,
3234 * @code
3235 *
3236 * sip_rseq_t sip_rseq = SIP_RSEQ_INIT;
3237 *
3238 * @endcode
3239 * @HI
3240 *
3241 */
3242#define SIP_RSEQ_INIT(){{{ 0, 0, sip_rseq_class }}} SIP_HDR_INIT(rseq){{{ 0, 0, sip_rseq_class }}}
3243
3244/**Initialize a structure #sip_rseq_t.
3245 *
3246 * An #sip_rseq_t structure for
3247 * @ref sip_rseq "RSeq header" can be initialized with the
3248 * sip_rseq_init() function/macro. For instance,
3249 * @code
3250 *
3251 * sip_rseq_t sip_rseq;
3252 *
3253 * sip_rseq_init(&sip_rseq);
3254 *
3255 * @endcode
3256 * @HI
3257 *
3258 */
3259#if SU_HAVE_INLINE1
3260su_inlinestatic inline sip_rseq_t *sip_rseq_init(sip_rseq_t x[1])
3261{
3262 return SIP_HEADER_INIT(x, sip_rseq_class, sizeof(sip_rseq_t))((void)memset((x), 0, (sizeof(sip_rseq_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_rseq_class)), (x))
;
3263}
3264#else
3265#define sip_rseq_init(x) \
3266 SIP_HEADER_INIT(x, sip_rseq_class, sizeof(sip_rseq_t))((void)memset((x), 0, (sizeof(sip_rseq_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_rseq_class)), (x))
3267#endif
3268
3269/**Test if header object is instance of #sip_rseq_t.
3270 *
3271 * Check if the header class is an instance of
3272 * @ref sip_rseq "RSeq header" object and return true (nonzero),
3273 * otherwise return false (zero).
3274 *
3275 * @param header pointer to the header structure to be tested
3276 *
3277 * @retval 1 (true) if the @a header is an instance of header rseq
3278 * @retval 0 (false) otherwise
3279 *
3280 */
3281#if SU_HAVE_INLINE1
3282su_inlinestatic inline int sip_is_rseq(sip_header_t const *header)
3283{
3284 return header && header->sh_classsh_common->h_class->hc_hash == sip_rseq_hash;
3285}
3286#else
3287int sip_is_rseq(sip_header_t const *header);
3288#endif
3289
3290#define sip_rseq_p(h)sip_is_rseq((h)) sip_is_rseq((h))
3291
3292
3293/**Duplicate a list of @ref sip_rseq "RSeq header" header structures #sip_rseq_t.
3294 *
3295 * Duplicate a header
3296 * structure @a hdr. If the header structure @a hdr
3297 * contains a reference (@c hdr->x_next) to a list of
3298 * headers, all the headers in the list are duplicated, too.
3299 *
3300 * @param home memory home used to allocate new structure
3301 * @param hdr header structure to be duplicated
3302 *
3303 * When duplicating, all parameter lists and non-constant
3304 * strings attached to the header are copied, too. The
3305 * function uses given memory @a home to allocate all the
3306 * memory areas used to copy the header.
3307 *
3308 * @par Example
3309 * @code
3310 *
3311 * rseq = sip_rseq_dup(home, sip->sip_rseq);
3312 *
3313 * @endcode
3314 *
3315 * @return
3316 * A pointer to the
3317 * newly duplicated #sip_rseq_t header structure, or NULL
3318 * upon an error.
3319 *
3320 */
3321#if SU_HAVE_INLINE1
3322su_inlinestatic inline
3323#endif
3324sip_rseq_t *sip_rseq_dup(su_home_t *home, sip_rseq_t const *hdr)
3325 __attribute__((__malloc__));
3326
3327#if SU_HAVE_INLINE1
3328su_inlinestatic inline
3329sip_rseq_t *sip_rseq_dup(su_home_t *home, sip_rseq_t const *hdr)
3330{
3331 return (sip_rseq_t *)
3332 msg_header_dup_as(home, sip_rseq_class, (msg_header_t const *)hdr);
3333}
3334#endif
3335
3336/**Copy a list of @ref sip_rseq "RSeq header" header structures #sip_rseq_t.
3337 *
3338 * The function sip_rseq_copy() copies a header structure @a
3339 * hdr. If the header structure @a hdr contains a reference (@c
3340 * hdr->h_next) to a list of headers, all the headers in that
3341 * list are copied, too. The function uses given memory @a home
3342 * to allocate all the memory areas used to copy the list of header
3343 * structure @a hdr.
3344 *
3345 * @param home memory home used to allocate new structure
3346 * @param hdr pointer to the header structure to be copied
3347 *
3348 * When copying, only the header structure and parameter lists attached to
3349 * it are duplicated. The new header structure retains all the references to
3350 * the strings within the old @a hdr header, including the encoding of the
3351 * old header, if present.
3352 *
3353 * @par Example
3354 * @code
3355 *
3356 * rseq = sip_rseq_copy(home, sip->sip_rseq);
3357 *
3358 * @endcode
3359 *
3360 * @return
3361 * A pointer to newly copied header structure, or NULL upon an error.
3362 *
3363 */
3364#if SU_HAVE_INLINE1
3365su_inlinestatic inline
3366#endif
3367sip_rseq_t *sip_rseq_copy(su_home_t *home, sip_rseq_t const *hdr)
3368 __attribute__((__malloc__));
3369
3370#if SU_HAVE_INLINE1
3371su_inlinestatic inline
3372sip_rseq_t *sip_rseq_copy(su_home_t *home, sip_rseq_t const *hdr)
3373{
3374 return (sip_rseq_t *)
3375 msg_header_copy_as(home, sip_rseq_class, (msg_header_t const *)hdr);
3376}
3377#endif
3378
3379/**Make a @ref sip_rseq "RSeq header" structure #sip_rseq_t.
3380 *
3381 * The function sip_rseq_make() makes a new
3382 * #sip_rseq_t header structure. It allocates a new
3383 * header structure, and decodes the string @a s as the
3384 * value of the structure.
3385 *
3386 * @param home memory home used to allocate new header structure.
3387 * @param s string to be decoded as value of the new header structure
3388 *
3389 * @return
3390 * A pointer to newly maked #sip_rseq_t header structure, or NULL upon an
3391 * error.
3392 *
3393 */
3394#if SU_HAVE_INLINE1
3395su_inlinestatic inline
3396#endif
3397sip_rseq_t *sip_rseq_make(su_home_t *home, char const *s)
3398 __attribute__((__malloc__));
3399
3400#if SU_HAVE_INLINE1
3401su_inlinestatic inline sip_rseq_t *sip_rseq_make(su_home_t *home, char const *s)
3402{
3403 return (sip_rseq_t *)sip_header_make(home, sip_rseq_class, s)((sip_header_t *)msg_header_make((home), (sip_rseq_class), (s
)))
;
3404}
3405#endif
3406
3407/**Make a @ref sip_rseq "RSeq header" from formatting result.
3408 *
3409 * Make a new #sip_rseq_t object using formatting result as its value.
3410 * The function first prints the arguments according to the format @a fmt
3411 * specified. Then it allocates a new header structure, and parses the
3412 * formatting result to the structure #sip_rseq_t.
3413 *
3414 * @param home memory home used to allocate new header structure.
3415 * @param fmt string used as a printf()-style format
3416 * @param ... argument list for format
3417 *
3418 * @return
3419 * A pointer to newly
3420 * makes header structure, or NULL upon an error.
3421 *
3422 * @HIDE
3423 *
3424 */
3425#if SU_HAVE_INLINE1
3426su_inlinestatic inline
3427#endif
3428sip_rseq_t *sip_rseq_format(su_home_t *home, char const *fmt, ...)
3429 __attribute__((__malloc__, __format__ (printf, 2, 3)));
3430
3431#if SU_HAVE_INLINE1
3432su_inlinestatic inline sip_rseq_t *sip_rseq_format(su_home_t *home, char const *fmt, ...)
3433{
3434 sip_header_t *h;
3435 va_list ap;
3436
3437 va_start(ap, fmt)__builtin_va_start(ap, fmt);
3438 h = sip_header_vformat(home, sip_rseq_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_rseq_class),
(fmt), (ap)))
;
3439 va_end(ap)__builtin_va_end(ap);
3440
3441 return (sip_rseq_t *)h;
3442}
3443#endif
3444
3445/** @} */
3446
3447/**@addtogroup sip_rack
3448 * @{
3449 */
3450
3451/** Parse a SIP @ref sip_rack "RAck header". @internal */
3452SOFIAPUBFUN issize_t sip_rack_d(su_home_t *, msg_header_t *,
3453 char *s, isize_t slen);
3454
3455/** Print a SIP @ref sip_rack "RAck header". @internal */
3456SOFIAPUBFUN issize_t sip_rack_e(char b[], isize_t bsiz,
3457 msg_header_t const *h, int flags);
3458
3459/**Access a SIP @ref sip_rack "RAck header"
3460 * structure #sip_rack_t from #sip_t.
3461 *
3462 */
3463#define sip_rack(sip)((sip_rack_t *)msg_header_access((msg_pub_t*)(sip), sip_rack_class
))
\
3464 ((sip_rack_t *)msg_header_access((msg_pub_t*)(sip), sip_rack_class))
3465
3466/**Initializer for structure #sip_rack_t.
3467 *
3468 * A static #sip_rack_t structure for
3469 * @ref sip_rack "RAck header" must be initialized with
3470 * the SIP_RACK_INIT() macro.
3471 * For instance,
3472 * @code
3473 *
3474 * sip_rack_t sip_rack = SIP_RACK_INIT;
3475 *
3476 * @endcode
3477 * @HI
3478 *
3479 */
3480#define SIP_RACK_INIT(){{{ 0, 0, sip_rack_class }}} SIP_HDR_INIT(rack){{{ 0, 0, sip_rack_class }}}
3481
3482/**Initialize a structure #sip_rack_t.
3483 *
3484 * An #sip_rack_t structure for
3485 * @ref sip_rack "RAck header" can be initialized with the
3486 * sip_rack_init() function/macro. For instance,
3487 * @code
3488 *
3489 * sip_rack_t sip_rack;
3490 *
3491 * sip_rack_init(&sip_rack);
3492 *
3493 * @endcode
3494 * @HI
3495 *
3496 */
3497#if SU_HAVE_INLINE1
3498su_inlinestatic inline sip_rack_t *sip_rack_init(sip_rack_t x[1])
3499{
3500 return SIP_HEADER_INIT(x, sip_rack_class, sizeof(sip_rack_t))((void)memset((x), 0, (sizeof(sip_rack_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_rack_class)), (x))
;
3501}
3502#else
3503#define sip_rack_init(x) \
3504 SIP_HEADER_INIT(x, sip_rack_class, sizeof(sip_rack_t))((void)memset((x), 0, (sizeof(sip_rack_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_rack_class)), (x))
3505#endif
3506
3507/**Test if header object is instance of #sip_rack_t.
3508 *
3509 * Check if the header class is an instance of
3510 * @ref sip_rack "RAck header" object and return true (nonzero),
3511 * otherwise return false (zero).
3512 *
3513 * @param header pointer to the header structure to be tested
3514 *
3515 * @retval 1 (true) if the @a header is an instance of header rack
3516 * @retval 0 (false) otherwise
3517 *
3518 */
3519#if SU_HAVE_INLINE1
3520su_inlinestatic inline int sip_is_rack(sip_header_t const *header)
3521{
3522 return header && header->sh_classsh_common->h_class->hc_hash == sip_rack_hash;
3523}
3524#else
3525int sip_is_rack(sip_header_t const *header);
3526#endif
3527
3528#define sip_rack_p(h)sip_is_rack((h)) sip_is_rack((h))
3529
3530
3531/**Duplicate a list of @ref sip_rack "RAck header" header structures #sip_rack_t.
3532 *
3533 * Duplicate a header
3534 * structure @a hdr. If the header structure @a hdr
3535 * contains a reference (@c hdr->x_next) to a list of
3536 * headers, all the headers in the list are duplicated, too.
3537 *
3538 * @param home memory home used to allocate new structure
3539 * @param hdr header structure to be duplicated
3540 *
3541 * When duplicating, all parameter lists and non-constant
3542 * strings attached to the header are copied, too. The
3543 * function uses given memory @a home to allocate all the
3544 * memory areas used to copy the header.
3545 *
3546 * @par Example
3547 * @code
3548 *
3549 * rack = sip_rack_dup(home, sip->sip_rack);
3550 *
3551 * @endcode
3552 *
3553 * @return
3554 * A pointer to the
3555 * newly duplicated #sip_rack_t header structure, or NULL
3556 * upon an error.
3557 *
3558 */
3559#if SU_HAVE_INLINE1
3560su_inlinestatic inline
3561#endif
3562sip_rack_t *sip_rack_dup(su_home_t *home, sip_rack_t const *hdr)
3563 __attribute__((__malloc__));
3564
3565#if SU_HAVE_INLINE1
3566su_inlinestatic inline
3567sip_rack_t *sip_rack_dup(su_home_t *home, sip_rack_t const *hdr)
3568{
3569 return (sip_rack_t *)
3570 msg_header_dup_as(home, sip_rack_class, (msg_header_t const *)hdr);
3571}
3572#endif
3573
3574/**Copy a list of @ref sip_rack "RAck header" header structures #sip_rack_t.
3575 *
3576 * The function sip_rack_copy() copies a header structure @a
3577 * hdr. If the header structure @a hdr contains a reference (@c
3578 * hdr->h_next) to a list of headers, all the headers in that
3579 * list are copied, too. The function uses given memory @a home
3580 * to allocate all the memory areas used to copy the list of header
3581 * structure @a hdr.
3582 *
3583 * @param home memory home used to allocate new structure
3584 * @param hdr pointer to the header structure to be copied
3585 *
3586 * When copying, only the header structure and parameter lists attached to
3587 * it are duplicated. The new header structure retains all the references to
3588 * the strings within the old @a hdr header, including the encoding of the
3589 * old header, if present.
3590 *
3591 * @par Example
3592 * @code
3593 *
3594 * rack = sip_rack_copy(home, sip->sip_rack);
3595 *
3596 * @endcode
3597 *
3598 * @return
3599 * A pointer to newly copied header structure, or NULL upon an error.
3600 *
3601 */
3602#if SU_HAVE_INLINE1
3603su_inlinestatic inline
3604#endif
3605sip_rack_t *sip_rack_copy(su_home_t *home, sip_rack_t const *hdr)
3606 __attribute__((__malloc__));
3607
3608#if SU_HAVE_INLINE1
3609su_inlinestatic inline
3610sip_rack_t *sip_rack_copy(su_home_t *home, sip_rack_t const *hdr)
3611{
3612 return (sip_rack_t *)
3613 msg_header_copy_as(home, sip_rack_class, (msg_header_t const *)hdr);
3614}
3615#endif
3616
3617/**Make a @ref sip_rack "RAck header" structure #sip_rack_t.
3618 *
3619 * The function sip_rack_make() makes a new
3620 * #sip_rack_t header structure. It allocates a new
3621 * header structure, and decodes the string @a s as the
3622 * value of the structure.
3623 *
3624 * @param home memory home used to allocate new header structure.
3625 * @param s string to be decoded as value of the new header structure
3626 *
3627 * @return
3628 * A pointer to newly maked #sip_rack_t header structure, or NULL upon an
3629 * error.
3630 *
3631 */
3632#if SU_HAVE_INLINE1
3633su_inlinestatic inline
3634#endif
3635sip_rack_t *sip_rack_make(su_home_t *home, char const *s)
3636 __attribute__((__malloc__));
3637
3638#if SU_HAVE_INLINE1
3639su_inlinestatic inline sip_rack_t *sip_rack_make(su_home_t *home, char const *s)
3640{
3641 return (sip_rack_t *)sip_header_make(home, sip_rack_class, s)((sip_header_t *)msg_header_make((home), (sip_rack_class), (s
)))
;
3642}
3643#endif
3644
3645/**Make a @ref sip_rack "RAck header" from formatting result.
3646 *
3647 * Make a new #sip_rack_t object using formatting result as its value.
3648 * The function first prints the arguments according to the format @a fmt
3649 * specified. Then it allocates a new header structure, and parses the
3650 * formatting result to the structure #sip_rack_t.
3651 *
3652 * @param home memory home used to allocate new header structure.
3653 * @param fmt string used as a printf()-style format
3654 * @param ... argument list for format
3655 *
3656 * @return
3657 * A pointer to newly
3658 * makes header structure, or NULL upon an error.
3659 *
3660 * @HIDE
3661 *
3662 */
3663#if SU_HAVE_INLINE1
3664su_inlinestatic inline
3665#endif
3666sip_rack_t *sip_rack_format(su_home_t *home, char const *fmt, ...)
3667 __attribute__((__malloc__, __format__ (printf, 2, 3)));
3668
3669#if SU_HAVE_INLINE1
3670su_inlinestatic inline sip_rack_t *sip_rack_format(su_home_t *home, char const *fmt, ...)
3671{
3672 sip_header_t *h;
3673 va_list ap;
3674
3675 va_start(ap, fmt)__builtin_va_start(ap, fmt);
3676 h = sip_header_vformat(home, sip_rack_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_rack_class),
(fmt), (ap)))
;
3677 va_end(ap)__builtin_va_end(ap);
3678
3679 return (sip_rack_t *)h;
3680}
3681#endif
3682
3683/** @} */
3684
3685/**@addtogroup sip_request_disposition
3686 * @{
3687 */
3688
3689/** Parse a SIP @ref sip_request_disposition "Request-Disposition header". @internal */
3690SOFIAPUBFUN issize_t sip_request_disposition_d(su_home_t *, msg_header_t *,
3691 char *s, isize_t slen);
3692
3693/** Print a SIP @ref sip_request_disposition "Request-Disposition header". @internal */
3694SOFIAPUBFUN issize_t sip_request_disposition_e(char b[], isize_t bsiz,
3695 msg_header_t const *h, int flags);
3696
3697/**Access a SIP @ref sip_request_disposition "Request-Disposition header"
3698 * structure #sip_request_disposition_t from #sip_t.
3699 *
3700 */
3701#define sip_request_disposition(sip)((sip_request_disposition_t *)msg_header_access((msg_pub_t*)(
sip), sip_request_disposition_class))
\
3702 ((sip_request_disposition_t *)msg_header_access((msg_pub_t*)(sip), sip_request_disposition_class))
3703
3704/**Initializer for structure #sip_request_disposition_t.
3705 *
3706 * A static #sip_request_disposition_t structure for
3707 * @ref sip_request_disposition "Request-Disposition header" must be initialized with
3708 * the SIP_REQUEST_DISPOSITION_INIT() macro.
3709 * For instance,
3710 * @code
3711 *
3712 * sip_request_disposition_t sip_request_disposition = SIP_REQUEST_DISPOSITION_INIT;
3713 *
3714 * @endcode
3715 * @HI
3716 *
3717 */
3718#define SIP_REQUEST_DISPOSITION_INIT(){{{ 0, 0, sip_request_disposition_class }}} SIP_HDR_INIT(request_disposition){{{ 0, 0, sip_request_disposition_class }}}
3719
3720/**Initialize a structure #sip_request_disposition_t.
3721 *
3722 * An #sip_request_disposition_t structure for
3723 * @ref sip_request_disposition "Request-Disposition header" can be initialized with the
3724 * sip_request_disposition_init() function/macro. For instance,
3725 * @code
3726 *
3727 * sip_request_disposition_t sip_request_disposition;
3728 *
3729 * sip_request_disposition_init(&sip_request_disposition);
3730 *
3731 * @endcode
3732 * @HI
3733 *
3734 */
3735#if SU_HAVE_INLINE1
3736su_inlinestatic inline sip_request_disposition_t *sip_request_disposition_init(sip_request_disposition_t x[1])
3737{
3738 return SIP_HEADER_INIT(x, sip_request_disposition_class, sizeof(sip_request_disposition_t))((void)memset((x), 0, (sizeof(sip_request_disposition_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_request_disposition_class
)), (x))
;
3739}
3740#else
3741#define sip_request_disposition_init(x) \
3742 SIP_HEADER_INIT(x, sip_request_disposition_class, sizeof(sip_request_disposition_t))((void)memset((x), 0, (sizeof(sip_request_disposition_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_request_disposition_class
)), (x))
3743#endif
3744
3745/**Test if header object is instance of #sip_request_disposition_t.
3746 *
3747 * Check if the header class is an instance of
3748 * @ref sip_request_disposition "Request-Disposition header" object and return true (nonzero),
3749 * otherwise return false (zero).
3750 *
3751 * @param header pointer to the header structure to be tested
3752 *
3753 * @retval 1 (true) if the @a header is an instance of header request_disposition
3754 * @retval 0 (false) otherwise
3755 *
3756 */
3757#if SU_HAVE_INLINE1
3758su_inlinestatic inline int sip_is_request_disposition(sip_header_t const *header)
3759{
3760 return header && header->sh_classsh_common->h_class->hc_hash == sip_request_disposition_hash;
3761}
3762#else
3763int sip_is_request_disposition(sip_header_t const *header);
3764#endif
3765
3766#define sip_request_disposition_p(h)sip_is_request_disposition((h)) sip_is_request_disposition((h))
3767
3768
3769/**Duplicate a list of @ref sip_request_disposition "Request-Disposition header" header structures #sip_request_disposition_t.
3770 *
3771 * Duplicate a header
3772 * structure @a hdr. If the header structure @a hdr
3773 * contains a reference (@c hdr->x_next) to a list of
3774 * headers, all the headers in the list are duplicated, too.
3775 *
3776 * @param home memory home used to allocate new structure
3777 * @param hdr header structure to be duplicated
3778 *
3779 * When duplicating, all parameter lists and non-constant
3780 * strings attached to the header are copied, too. The
3781 * function uses given memory @a home to allocate all the
3782 * memory areas used to copy the header.
3783 *
3784 * @par Example
3785 * @code
3786 *
3787 * request_disposition = sip_request_disposition_dup(home, sip->sip_request_disposition);
3788 *
3789 * @endcode
3790 *
3791 * @return
3792 * A pointer to the
3793 * newly duplicated #sip_request_disposition_t header structure, or NULL
3794 * upon an error.
3795 *
3796 */
3797#if SU_HAVE_INLINE1
3798su_inlinestatic inline
3799#endif
3800sip_request_disposition_t *sip_request_disposition_dup(su_home_t *home, sip_request_disposition_t const *hdr)
3801 __attribute__((__malloc__));
3802
3803#if SU_HAVE_INLINE1
3804su_inlinestatic inline
3805sip_request_disposition_t *sip_request_disposition_dup(su_home_t *home, sip_request_disposition_t const *hdr)
3806{
3807 return (sip_request_disposition_t *)
3808 msg_header_dup_as(home, sip_request_disposition_class, (msg_header_t const *)hdr);
3809}
3810#endif
3811
3812/**Copy a list of @ref sip_request_disposition "Request-Disposition header" header structures #sip_request_disposition_t.
3813 *
3814 * The function sip_request_disposition_copy() copies a header structure @a
3815 * hdr. If the header structure @a hdr contains a reference (@c
3816 * hdr->h_next) to a list of headers, all the headers in that
3817 * list are copied, too. The function uses given memory @a home
3818 * to allocate all the memory areas used to copy the list of header
3819 * structure @a hdr.
3820 *
3821 * @param home memory home used to allocate new structure
3822 * @param hdr pointer to the header structure to be copied
3823 *
3824 * When copying, only the header structure and parameter lists attached to
3825 * it are duplicated. The new header structure retains all the references to
3826 * the strings within the old @a hdr header, including the encoding of the
3827 * old header, if present.
3828 *
3829 * @par Example
3830 * @code
3831 *
3832 * request_disposition = sip_request_disposition_copy(home, sip->sip_request_disposition);
3833 *
3834 * @endcode
3835 *
3836 * @return
3837 * A pointer to newly copied header structure, or NULL upon an error.
3838 *
3839 */
3840#if SU_HAVE_INLINE1
3841su_inlinestatic inline
3842#endif
3843sip_request_disposition_t *sip_request_disposition_copy(su_home_t *home, sip_request_disposition_t const *hdr)
3844 __attribute__((__malloc__));
3845
3846#if SU_HAVE_INLINE1
3847su_inlinestatic inline
3848sip_request_disposition_t *sip_request_disposition_copy(su_home_t *home, sip_request_disposition_t const *hdr)
3849{
3850 return (sip_request_disposition_t *)
3851 msg_header_copy_as(home, sip_request_disposition_class, (msg_header_t const *)hdr);
3852}
3853#endif
3854
3855/**Make a @ref sip_request_disposition "Request-Disposition header" structure #sip_request_disposition_t.
3856 *
3857 * The function sip_request_disposition_make() makes a new
3858 * #sip_request_disposition_t header structure. It allocates a new
3859 * header structure, and decodes the string @a s as the
3860 * value of the structure.
3861 *
3862 * @param home memory home used to allocate new header structure.
3863 * @param s string to be decoded as value of the new header structure
3864 *
3865 * @return
3866 * A pointer to newly maked #sip_request_disposition_t header structure, or NULL upon an
3867 * error.
3868 *
3869 */
3870#if SU_HAVE_INLINE1
3871su_inlinestatic inline
3872#endif
3873sip_request_disposition_t *sip_request_disposition_make(su_home_t *home, char const *s)
3874 __attribute__((__malloc__));
3875
3876#if SU_HAVE_INLINE1
3877su_inlinestatic inline sip_request_disposition_t *sip_request_disposition_make(su_home_t *home, char const *s)
3878{
3879 return (sip_request_disposition_t *)sip_header_make(home, sip_request_disposition_class, s)((sip_header_t *)msg_header_make((home), (sip_request_disposition_class
), (s)))
;
3880}
3881#endif
3882
3883/**Make a @ref sip_request_disposition "Request-Disposition header" from formatting result.
3884 *
3885 * Make a new #sip_request_disposition_t object using formatting result as its value.
3886 * The function first prints the arguments according to the format @a fmt
3887 * specified. Then it allocates a new header structure, and parses the
3888 * formatting result to the structure #sip_request_disposition_t.
3889 *
3890 * @param home memory home used to allocate new header structure.
3891 * @param fmt string used as a printf()-style format
3892 * @param ... argument list for format
3893 *
3894 * @return
3895 * A pointer to newly
3896 * makes header structure, or NULL upon an error.
3897 *
3898 * @HIDE
3899 *
3900 */
3901#if SU_HAVE_INLINE1
3902su_inlinestatic inline
3903#endif
3904sip_request_disposition_t *sip_request_disposition_format(su_home_t *home, char const *fmt, ...)
3905 __attribute__((__malloc__, __format__ (printf, 2, 3)));
3906
3907#if SU_HAVE_INLINE1
3908su_inlinestatic inline sip_request_disposition_t *sip_request_disposition_format(su_home_t *home, char const *fmt, ...)
3909{
3910 sip_header_t *h;
3911 va_list ap;
3912
3913 va_start(ap, fmt)__builtin_va_start(ap, fmt);
3914 h = sip_header_vformat(home, sip_request_disposition_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_request_disposition_class
), (fmt), (ap)))
;
3915 va_end(ap)__builtin_va_end(ap);
3916
3917 return (sip_request_disposition_t *)h;
3918}
3919#endif
3920
3921/** @} */
3922
3923/**@addtogroup sip_accept_contact
3924 * @{
3925 */
3926
3927/** Parse a SIP @ref sip_accept_contact "Accept-Contact header". @internal */
3928SOFIAPUBFUN issize_t sip_accept_contact_d(su_home_t *, msg_header_t *,
3929 char *s, isize_t slen);
3930
3931/** Print a SIP @ref sip_accept_contact "Accept-Contact header". @internal */
3932SOFIAPUBFUN issize_t sip_accept_contact_e(char b[], isize_t bsiz,
3933 msg_header_t const *h, int flags);
3934
3935/**Access a SIP @ref sip_accept_contact "Accept-Contact header"
3936 * structure #sip_accept_contact_t from #sip_t.
3937 *
3938 */
3939#define sip_accept_contact(sip)((sip_accept_contact_t *)msg_header_access((msg_pub_t*)(sip),
sip_accept_contact_class))
\
3940 ((sip_accept_contact_t *)msg_header_access((msg_pub_t*)(sip), sip_accept_contact_class))
3941
3942/**Initializer for structure #sip_accept_contact_t.
3943 *
3944 * A static #sip_accept_contact_t structure for
3945 * @ref sip_accept_contact "Accept-Contact header" must be initialized with
3946 * the SIP_ACCEPT_CONTACT_INIT() macro.
3947 * For instance,
3948 * @code
3949 *
3950 * sip_accept_contact_t sip_accept_contact = SIP_ACCEPT_CONTACT_INIT;
3951 *
3952 * @endcode
3953 * @HI
3954 *
3955 */
3956#define SIP_ACCEPT_CONTACT_INIT(){{{ 0, 0, sip_accept_contact_class }}} SIP_HDR_INIT(accept_contact){{{ 0, 0, sip_accept_contact_class }}}
3957
3958/**Initialize a structure #sip_accept_contact_t.
3959 *
3960 * An #sip_accept_contact_t structure for
3961 * @ref sip_accept_contact "Accept-Contact header" can be initialized with the
3962 * sip_accept_contact_init() function/macro. For instance,
3963 * @code
3964 *
3965 * sip_accept_contact_t sip_accept_contact;
3966 *
3967 * sip_accept_contact_init(&sip_accept_contact);
3968 *
3969 * @endcode
3970 * @HI
3971 *
3972 */
3973#if SU_HAVE_INLINE1
3974su_inlinestatic inline sip_accept_contact_t *sip_accept_contact_init(sip_accept_contact_t x[1])
3975{
3976 return SIP_HEADER_INIT(x, sip_accept_contact_class, sizeof(sip_accept_contact_t))((void)memset((x), 0, (sizeof(sip_accept_contact_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_accept_contact_class
)), (x))
;
3977}
3978#else
3979#define sip_accept_contact_init(x) \
3980 SIP_HEADER_INIT(x, sip_accept_contact_class, sizeof(sip_accept_contact_t))((void)memset((x), 0, (sizeof(sip_accept_contact_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_accept_contact_class
)), (x))
3981#endif
3982
3983/**Test if header object is instance of #sip_accept_contact_t.
3984 *
3985 * Check if the header class is an instance of
3986 * @ref sip_accept_contact "Accept-Contact header" object and return true (nonzero),
3987 * otherwise return false (zero).
3988 *
3989 * @param header pointer to the header structure to be tested
3990 *
3991 * @retval 1 (true) if the @a header is an instance of header accept_contact
3992 * @retval 0 (false) otherwise
3993 *
3994 */
3995#if SU_HAVE_INLINE1
3996su_inlinestatic inline int sip_is_accept_contact(sip_header_t const *header)
3997{
3998 return header && header->sh_classsh_common->h_class->hc_hash == sip_accept_contact_hash;
3999}
4000#else
4001int sip_is_accept_contact(sip_header_t const *header);
4002#endif
4003
4004#define sip_accept_contact_p(h)sip_is_accept_contact((h)) sip_is_accept_contact((h))
4005
4006
4007/**Duplicate a list of @ref sip_accept_contact "Accept-Contact header" header structures #sip_accept_contact_t.
4008 *
4009 * Duplicate a header
4010 * structure @a hdr. If the header structure @a hdr
4011 * contains a reference (@c hdr->x_next) to a list of
4012 * headers, all the headers in the list are duplicated, too.
4013 *
4014 * @param home memory home used to allocate new structure
4015 * @param hdr header structure to be duplicated
4016 *
4017 * When duplicating, all parameter lists and non-constant
4018 * strings attached to the header are copied, too. The
4019 * function uses given memory @a home to allocate all the
4020 * memory areas used to copy the header.
4021 *
4022 * @par Example
4023 * @code
4024 *
4025 * accept_contact = sip_accept_contact_dup(home, sip->sip_accept_contact);
4026 *
4027 * @endcode
4028 *
4029 * @return
4030 * A pointer to the
4031 * newly duplicated #sip_accept_contact_t header structure, or NULL
4032 * upon an error.
4033 *
4034 */
4035#if SU_HAVE_INLINE1
4036su_inlinestatic inline
4037#endif
4038sip_accept_contact_t *sip_accept_contact_dup(su_home_t *home, sip_accept_contact_t const *hdr)
4039 __attribute__((__malloc__));
4040
4041#if SU_HAVE_INLINE1
4042su_inlinestatic inline
4043sip_accept_contact_t *sip_accept_contact_dup(su_home_t *home, sip_accept_contact_t const *hdr)
4044{
4045 return (sip_accept_contact_t *)
4046 msg_header_dup_as(home, sip_accept_contact_class, (msg_header_t const *)hdr);
4047}
4048#endif
4049
4050/**Copy a list of @ref sip_accept_contact "Accept-Contact header" header structures #sip_accept_contact_t.
4051 *
4052 * The function sip_accept_contact_copy() copies a header structure @a
4053 * hdr. If the header structure @a hdr contains a reference (@c
4054 * hdr->h_next) to a list of headers, all the headers in that
4055 * list are copied, too. The function uses given memory @a home
4056 * to allocate all the memory areas used to copy the list of header
4057 * structure @a hdr.
4058 *
4059 * @param home memory home used to allocate new structure
4060 * @param hdr pointer to the header structure to be copied
4061 *
4062 * When copying, only the header structure and parameter lists attached to
4063 * it are duplicated. The new header structure retains all the references to
4064 * the strings within the old @a hdr header, including the encoding of the
4065 * old header, if present.
4066 *
4067 * @par Example
4068 * @code
4069 *
4070 * accept_contact = sip_accept_contact_copy(home, sip->sip_accept_contact);
4071 *
4072 * @endcode
4073 *
4074 * @return
4075 * A pointer to newly copied header structure, or NULL upon an error.
4076 *
4077 */
4078#if SU_HAVE_INLINE1
4079su_inlinestatic inline
4080#endif
4081sip_accept_contact_t *sip_accept_contact_copy(su_home_t *home, sip_accept_contact_t const *hdr)
4082 __attribute__((__malloc__));
4083
4084#if SU_HAVE_INLINE1
4085su_inlinestatic inline
4086sip_accept_contact_t *sip_accept_contact_copy(su_home_t *home, sip_accept_contact_t const *hdr)
4087{
4088 return (sip_accept_contact_t *)
4089 msg_header_copy_as(home, sip_accept_contact_class, (msg_header_t const *)hdr);
4090}
4091#endif
4092
4093/**Make a @ref sip_accept_contact "Accept-Contact header" structure #sip_accept_contact_t.
4094 *
4095 * The function sip_accept_contact_make() makes a new
4096 * #sip_accept_contact_t header structure. It allocates a new
4097 * header structure, and decodes the string @a s as the
4098 * value of the structure.
4099 *
4100 * @param home memory home used to allocate new header structure.
4101 * @param s string to be decoded as value of the new header structure
4102 *
4103 * @return
4104 * A pointer to newly maked #sip_accept_contact_t header structure, or NULL upon an
4105 * error.
4106 *
4107 */
4108#if SU_HAVE_INLINE1
4109su_inlinestatic inline
4110#endif
4111sip_accept_contact_t *sip_accept_contact_make(su_home_t *home, char const *s)
4112 __attribute__((__malloc__));
4113
4114#if SU_HAVE_INLINE1
4115su_inlinestatic inline sip_accept_contact_t *sip_accept_contact_make(su_home_t *home, char const *s)
4116{
4117 return (sip_accept_contact_t *)sip_header_make(home, sip_accept_contact_class, s)((sip_header_t *)msg_header_make((home), (sip_accept_contact_class
), (s)))
;
4118}
4119#endif
4120
4121/**Make a @ref sip_accept_contact "Accept-Contact header" from formatting result.
4122 *
4123 * Make a new #sip_accept_contact_t object using formatting result as its value.
4124 * The function first prints the arguments according to the format @a fmt
4125 * specified. Then it allocates a new header structure, and parses the
4126 * formatting result to the structure #sip_accept_contact_t.
4127 *
4128 * @param home memory home used to allocate new header structure.
4129 * @param fmt string used as a printf()-style format
4130 * @param ... argument list for format
4131 *
4132 * @return
4133 * A pointer to newly
4134 * makes header structure, or NULL upon an error.
4135 *
4136 * @HIDE
4137 *
4138 */
4139#if SU_HAVE_INLINE1
4140su_inlinestatic inline
4141#endif
4142sip_accept_contact_t *sip_accept_contact_format(su_home_t *home, char const *fmt, ...)
4143 __attribute__((__malloc__, __format__ (printf, 2, 3)));
4144
4145#if SU_HAVE_INLINE1
4146su_inlinestatic inline sip_accept_contact_t *sip_accept_contact_format(su_home_t *home, char const *fmt, ...)
4147{
4148 sip_header_t *h;
4149 va_list ap;
4150
4151 va_start(ap, fmt)__builtin_va_start(ap, fmt);
4152 h = sip_header_vformat(home, sip_accept_contact_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_accept_contact_class
), (fmt), (ap)))
;
4153 va_end(ap)__builtin_va_end(ap);
4154
4155 return (sip_accept_contact_t *)h;
4156}
4157#endif
4158
4159/** @} */
4160
4161/**@addtogroup sip_reject_contact
4162 * @{
4163 */
4164
4165/** Parse a SIP @ref sip_reject_contact "Reject-Contact header". @internal */
4166SOFIAPUBFUN issize_t sip_reject_contact_d(su_home_t *, msg_header_t *,
4167 char *s, isize_t slen);
4168
4169/** Print a SIP @ref sip_reject_contact "Reject-Contact header". @internal */
4170SOFIAPUBFUN issize_t sip_reject_contact_e(char b[], isize_t bsiz,
4171 msg_header_t const *h, int flags);
4172
4173/**Access a SIP @ref sip_reject_contact "Reject-Contact header"
4174 * structure #sip_reject_contact_t from #sip_t.
4175 *
4176 */
4177#define sip_reject_contact(sip)((sip_reject_contact_t *)msg_header_access((msg_pub_t*)(sip),
sip_reject_contact_class))
\
4178 ((sip_reject_contact_t *)msg_header_access((msg_pub_t*)(sip), sip_reject_contact_class))
4179
4180/**Initializer for structure #sip_reject_contact_t.
4181 *
4182 * A static #sip_reject_contact_t structure for
4183 * @ref sip_reject_contact "Reject-Contact header" must be initialized with
4184 * the SIP_REJECT_CONTACT_INIT() macro.
4185 * For instance,
4186 * @code
4187 *
4188 * sip_reject_contact_t sip_reject_contact = SIP_REJECT_CONTACT_INIT;
4189 *
4190 * @endcode
4191 * @HI
4192 *
4193 */
4194#define SIP_REJECT_CONTACT_INIT(){{{ 0, 0, sip_reject_contact_class }}} SIP_HDR_INIT(reject_contact){{{ 0, 0, sip_reject_contact_class }}}
4195
4196/**Initialize a structure #sip_reject_contact_t.
4197 *
4198 * An #sip_reject_contact_t structure for
4199 * @ref sip_reject_contact "Reject-Contact header" can be initialized with the
4200 * sip_reject_contact_init() function/macro. For instance,
4201 * @code
4202 *
4203 * sip_reject_contact_t sip_reject_contact;
4204 *
4205 * sip_reject_contact_init(&sip_reject_contact);
4206 *
4207 * @endcode
4208 * @HI
4209 *
4210 */
4211#if SU_HAVE_INLINE1
4212su_inlinestatic inline sip_reject_contact_t *sip_reject_contact_init(sip_reject_contact_t x[1])
4213{
4214 return SIP_HEADER_INIT(x, sip_reject_contact_class, sizeof(sip_reject_contact_t))((void)memset((x), 0, (sizeof(sip_reject_contact_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_reject_contact_class
)), (x))
;
4215}
4216#else
4217#define sip_reject_contact_init(x) \
4218 SIP_HEADER_INIT(x, sip_reject_contact_class, sizeof(sip_reject_contact_t))((void)memset((x), 0, (sizeof(sip_reject_contact_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_reject_contact_class
)), (x))
4219#endif
4220
4221/**Test if header object is instance of #sip_reject_contact_t.
4222 *
4223 * Check if the header class is an instance of
4224 * @ref sip_reject_contact "Reject-Contact header" object and return true (nonzero),
4225 * otherwise return false (zero).
4226 *
4227 * @param header pointer to the header structure to be tested
4228 *
4229 * @retval 1 (true) if the @a header is an instance of header reject_contact
4230 * @retval 0 (false) otherwise
4231 *
4232 */
4233#if SU_HAVE_INLINE1
4234su_inlinestatic inline int sip_is_reject_contact(sip_header_t const *header)
4235{
4236 return header && header->sh_classsh_common->h_class->hc_hash == sip_reject_contact_hash;
4237}
4238#else
4239int sip_is_reject_contact(sip_header_t const *header);
4240#endif
4241
4242#define sip_reject_contact_p(h)sip_is_reject_contact((h)) sip_is_reject_contact((h))
4243
4244
4245/**Duplicate a list of @ref sip_reject_contact "Reject-Contact header" header structures #sip_reject_contact_t.
4246 *
4247 * Duplicate a header
4248 * structure @a hdr. If the header structure @a hdr
4249 * contains a reference (@c hdr->x_next) to a list of
4250 * headers, all the headers in the list are duplicated, too.
4251 *
4252 * @param home memory home used to allocate new structure
4253 * @param hdr header structure to be duplicated
4254 *
4255 * When duplicating, all parameter lists and non-constant
4256 * strings attached to the header are copied, too. The
4257 * function uses given memory @a home to allocate all the
4258 * memory areas used to copy the header.
4259 *
4260 * @par Example
4261 * @code
4262 *
4263 * reject_contact = sip_reject_contact_dup(home, sip->sip_reject_contact);
4264 *
4265 * @endcode
4266 *
4267 * @return
4268 * A pointer to the
4269 * newly duplicated #sip_reject_contact_t header structure, or NULL
4270 * upon an error.
4271 *
4272 */
4273#if SU_HAVE_INLINE1
4274su_inlinestatic inline
4275#endif
4276sip_reject_contact_t *sip_reject_contact_dup(su_home_t *home, sip_reject_contact_t const *hdr)
4277 __attribute__((__malloc__));
4278
4279#if SU_HAVE_INLINE1
4280su_inlinestatic inline
4281sip_reject_contact_t *sip_reject_contact_dup(su_home_t *home, sip_reject_contact_t const *hdr)
4282{
4283 return (sip_reject_contact_t *)
4284 msg_header_dup_as(home, sip_reject_contact_class, (msg_header_t const *)hdr);
4285}
4286#endif
4287
4288/**Copy a list of @ref sip_reject_contact "Reject-Contact header" header structures #sip_reject_contact_t.
4289 *
4290 * The function sip_reject_contact_copy() copies a header structure @a
4291 * hdr. If the header structure @a hdr contains a reference (@c
4292 * hdr->h_next) to a list of headers, all the headers in that
4293 * list are copied, too. The function uses given memory @a home
4294 * to allocate all the memory areas used to copy the list of header
4295 * structure @a hdr.
4296 *
4297 * @param home memory home used to allocate new structure
4298 * @param hdr pointer to the header structure to be copied
4299 *
4300 * When copying, only the header structure and parameter lists attached to
4301 * it are duplicated. The new header structure retains all the references to
4302 * the strings within the old @a hdr header, including the encoding of the
4303 * old header, if present.
4304 *
4305 * @par Example
4306 * @code
4307 *
4308 * reject_contact = sip_reject_contact_copy(home, sip->sip_reject_contact);
4309 *
4310 * @endcode
4311 *
4312 * @return
4313 * A pointer to newly copied header structure, or NULL upon an error.
4314 *
4315 */
4316#if SU_HAVE_INLINE1
4317su_inlinestatic inline
4318#endif
4319sip_reject_contact_t *sip_reject_contact_copy(su_home_t *home, sip_reject_contact_t const *hdr)
4320 __attribute__((__malloc__));
4321
4322#if SU_HAVE_INLINE1
4323su_inlinestatic inline
4324sip_reject_contact_t *sip_reject_contact_copy(su_home_t *home, sip_reject_contact_t const *hdr)
4325{
4326 return (sip_reject_contact_t *)
4327 msg_header_copy_as(home, sip_reject_contact_class, (msg_header_t const *)hdr);
4328}
4329#endif
4330
4331/**Make a @ref sip_reject_contact "Reject-Contact header" structure #sip_reject_contact_t.
4332 *
4333 * The function sip_reject_contact_make() makes a new
4334 * #sip_reject_contact_t header structure. It allocates a new
4335 * header structure, and decodes the string @a s as the
4336 * value of the structure.
4337 *
4338 * @param home memory home used to allocate new header structure.
4339 * @param s string to be decoded as value of the new header structure
4340 *
4341 * @return
4342 * A pointer to newly maked #sip_reject_contact_t header structure, or NULL upon an
4343 * error.
4344 *
4345 */
4346#if SU_HAVE_INLINE1
4347su_inlinestatic inline
4348#endif
4349sip_reject_contact_t *sip_reject_contact_make(su_home_t *home, char const *s)
4350 __attribute__((__malloc__));
4351
4352#if SU_HAVE_INLINE1
4353su_inlinestatic inline sip_reject_contact_t *sip_reject_contact_make(su_home_t *home, char const *s)
4354{
4355 return (sip_reject_contact_t *)sip_header_make(home, sip_reject_contact_class, s)((sip_header_t *)msg_header_make((home), (sip_reject_contact_class
), (s)))
;
4356}
4357#endif
4358
4359/**Make a @ref sip_reject_contact "Reject-Contact header" from formatting result.
4360 *
4361 * Make a new #sip_reject_contact_t object using formatting result as its value.
4362 * The function first prints the arguments according to the format @a fmt
4363 * specified. Then it allocates a new header structure, and parses the
4364 * formatting result to the structure #sip_reject_contact_t.
4365 *
4366 * @param home memory home used to allocate new header structure.
4367 * @param fmt string used as a printf()-style format
4368 * @param ... argument list for format
4369 *
4370 * @return
4371 * A pointer to newly
4372 * makes header structure, or NULL upon an error.
4373 *
4374 * @HIDE
4375 *
4376 */
4377#if SU_HAVE_INLINE1
4378su_inlinestatic inline
4379#endif
4380sip_reject_contact_t *sip_reject_contact_format(su_home_t *home, char const *fmt, ...)
4381 __attribute__((__malloc__, __format__ (printf, 2, 3)));
4382
4383#if SU_HAVE_INLINE1
4384su_inlinestatic inline sip_reject_contact_t *sip_reject_contact_format(su_home_t *home, char const *fmt, ...)
4385{
4386 sip_header_t *h;
4387 va_list ap;
4388
4389 va_start(ap, fmt)__builtin_va_start(ap, fmt);
4390 h = sip_header_vformat(home, sip_reject_contact_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_reject_contact_class
), (fmt), (ap)))
;
4391 va_end(ap)__builtin_va_end(ap);
4392
4393 return (sip_reject_contact_t *)h;
4394}
4395#endif
4396
4397/** @} */
4398
4399/**@addtogroup sip_expires
4400 * @{
4401 */
4402
4403/** Parse a SIP @ref sip_expires "Expires header". @internal */
4404SOFIAPUBFUN issize_t sip_expires_d(su_home_t *, msg_header_t *,
4405 char *s, isize_t slen);
4406
4407/** Print a SIP @ref sip_expires "Expires header". @internal */
4408SOFIAPUBFUN issize_t sip_expires_e(char b[], isize_t bsiz,
4409 msg_header_t const *h, int flags);
4410
4411/**Access a SIP @ref sip_expires "Expires header"
4412 * structure #sip_expires_t from #sip_t.
4413 *
4414 */
4415#define sip_expires(sip)((sip_expires_t *)msg_header_access((msg_pub_t*)(sip), sip_expires_class
))
\
4416 ((sip_expires_t *)msg_header_access((msg_pub_t*)(sip), sip_expires_class))
4417
4418/**Initializer for structure #sip_expires_t.
4419 *
4420 * A static #sip_expires_t structure for
4421 * @ref sip_expires "Expires header" must be initialized with
4422 * the SIP_EXPIRES_INIT() macro.
4423 * For instance,
4424 * @code
4425 *
4426 * sip_expires_t sip_expires = SIP_EXPIRES_INIT;
4427 *
4428 * @endcode
4429 * @HI
4430 *
4431 */
4432#define SIP_EXPIRES_INIT(){{{ 0, 0, sip_expires_class }}} SIP_HDR_INIT(expires){{{ 0, 0, sip_expires_class }}}
4433
4434/**Initialize a structure #sip_expires_t.
4435 *
4436 * An #sip_expires_t structure for
4437 * @ref sip_expires "Expires header" can be initialized with the
4438 * sip_expires_init() function/macro. For instance,
4439 * @code
4440 *
4441 * sip_expires_t sip_expires;
4442 *
4443 * sip_expires_init(&sip_expires);
4444 *
4445 * @endcode
4446 * @HI
4447 *
4448 */
4449#if SU_HAVE_INLINE1
4450su_inlinestatic inline sip_expires_t *sip_expires_init(sip_expires_t x[1])
4451{
4452 return SIP_HEADER_INIT(x, sip_expires_class, sizeof(sip_expires_t))((void)memset((x), 0, (sizeof(sip_expires_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_expires_class)), (x))
;
4453}
4454#else
4455#define sip_expires_init(x) \
4456 SIP_HEADER_INIT(x, sip_expires_class, sizeof(sip_expires_t))((void)memset((x), 0, (sizeof(sip_expires_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_expires_class)), (x))
4457#endif
4458
4459/**Test if header object is instance of #sip_expires_t.
4460 *
4461 * Check if the header class is an instance of
4462 * @ref sip_expires "Expires header" object and return true (nonzero),
4463 * otherwise return false (zero).
4464 *
4465 * @param header pointer to the header structure to be tested
4466 *
4467 * @retval 1 (true) if the @a header is an instance of header expires
4468 * @retval 0 (false) otherwise
4469 *
4470 */
4471#if SU_HAVE_INLINE1
4472su_inlinestatic inline int sip_is_expires(sip_header_t const *header)
4473{
4474 return header && header->sh_classsh_common->h_class->hc_hash == sip_expires_hash;
4475}
4476#else
4477int sip_is_expires(sip_header_t const *header);
4478#endif
4479
4480#define sip_expires_p(h)sip_is_expires((h)) sip_is_expires((h))
4481
4482
4483/**Duplicate a list of @ref sip_expires "Expires header" header structures #sip_expires_t.
4484 *
4485 * Duplicate a header
4486 * structure @a hdr. If the header structure @a hdr
4487 * contains a reference (@c hdr->x_next) to a list of
4488 * headers, all the headers in the list are duplicated, too.
4489 *
4490 * @param home memory home used to allocate new structure
4491 * @param hdr header structure to be duplicated
4492 *
4493 * When duplicating, all parameter lists and non-constant
4494 * strings attached to the header are copied, too. The
4495 * function uses given memory @a home to allocate all the
4496 * memory areas used to copy the header.
4497 *
4498 * @par Example
4499 * @code
4500 *
4501 * expires = sip_expires_dup(home, sip->sip_expires);
4502 *
4503 * @endcode
4504 *
4505 * @return
4506 * A pointer to the
4507 * newly duplicated #sip_expires_t header structure, or NULL
4508 * upon an error.
4509 *
4510 */
4511#if SU_HAVE_INLINE1
4512su_inlinestatic inline
4513#endif
4514sip_expires_t *sip_expires_dup(su_home_t *home, sip_expires_t const *hdr)
4515 __attribute__((__malloc__));
4516
4517#if SU_HAVE_INLINE1
4518su_inlinestatic inline
4519sip_expires_t *sip_expires_dup(su_home_t *home, sip_expires_t const *hdr)
4520{
4521 return (sip_expires_t *)
4522 msg_header_dup_as(home, sip_expires_class, (msg_header_t const *)hdr);
4523}
4524#endif
4525
4526/**Copy a list of @ref sip_expires "Expires header" header structures #sip_expires_t.
4527 *
4528 * The function sip_expires_copy() copies a header structure @a
4529 * hdr. If the header structure @a hdr contains a reference (@c
4530 * hdr->h_next) to a list of headers, all the headers in that
4531 * list are copied, too. The function uses given memory @a home
4532 * to allocate all the memory areas used to copy the list of header
4533 * structure @a hdr.
4534 *
4535 * @param home memory home used to allocate new structure
4536 * @param hdr pointer to the header structure to be copied
4537 *
4538 * When copying, only the header structure and parameter lists attached to
4539 * it are duplicated. The new header structure retains all the references to
4540 * the strings within the old @a hdr header, including the encoding of the
4541 * old header, if present.
4542 *
4543 * @par Example
4544 * @code
4545 *
4546 * expires = sip_expires_copy(home, sip->sip_expires);
4547 *
4548 * @endcode
4549 *
4550 * @return
4551 * A pointer to newly copied header structure, or NULL upon an error.
4552 *
4553 */
4554#if SU_HAVE_INLINE1
4555su_inlinestatic inline
4556#endif
4557sip_expires_t *sip_expires_copy(su_home_t *home, sip_expires_t const *hdr)
4558 __attribute__((__malloc__));
4559
4560#if SU_HAVE_INLINE1
4561su_inlinestatic inline
4562sip_expires_t *sip_expires_copy(su_home_t *home, sip_expires_t const *hdr)
4563{
4564 return (sip_expires_t *)
4565 msg_header_copy_as(home, sip_expires_class, (msg_header_t const *)hdr);
4566}
4567#endif
4568
4569/**Make a @ref sip_expires "Expires header" structure #sip_expires_t.
4570 *
4571 * The function sip_expires_make() makes a new
4572 * #sip_expires_t header structure. It allocates a new
4573 * header structure, and decodes the string @a s as the
4574 * value of the structure.
4575 *
4576 * @param home memory home used to allocate new header structure.
4577 * @param s string to be decoded as value of the new header structure
4578 *
4579 * @return
4580 * A pointer to newly maked #sip_expires_t header structure, or NULL upon an
4581 * error.
4582 *
4583 */
4584#if SU_HAVE_INLINE1
4585su_inlinestatic inline
4586#endif
4587sip_expires_t *sip_expires_make(su_home_t *home, char const *s)
4588 __attribute__((__malloc__));
4589
4590#if SU_HAVE_INLINE1
4591su_inlinestatic inline sip_expires_t *sip_expires_make(su_home_t *home, char const *s)
4592{
4593 return (sip_expires_t *)sip_header_make(home, sip_expires_class, s)((sip_header_t *)msg_header_make((home), (sip_expires_class),
(s)))
;
4594}
4595#endif
4596
4597/**Make a @ref sip_expires "Expires header" from formatting result.
4598 *
4599 * Make a new #sip_expires_t object using formatting result as its value.
4600 * The function first prints the arguments according to the format @a fmt
4601 * specified. Then it allocates a new header structure, and parses the
4602 * formatting result to the structure #sip_expires_t.
4603 *
4604 * @param home memory home used to allocate new header structure.
4605 * @param fmt string used as a printf()-style format
4606 * @param ... argument list for format
4607 *
4608 * @return
4609 * A pointer to newly
4610 * makes header structure, or NULL upon an error.
4611 *
4612 * @HIDE
4613 *
4614 */
4615#if SU_HAVE_INLINE1
4616su_inlinestatic inline
4617#endif
4618sip_expires_t *sip_expires_format(su_home_t *home, char const *fmt, ...)
4619 __attribute__((__malloc__, __format__ (printf, 2, 3)));
4620
4621#if SU_HAVE_INLINE1
4622su_inlinestatic inline sip_expires_t *sip_expires_format(su_home_t *home, char const *fmt, ...)
4623{
4624 sip_header_t *h;
4625 va_list ap;
4626
4627 va_start(ap, fmt)__builtin_va_start(ap, fmt);
4628 h = sip_header_vformat(home, sip_expires_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_expires_class
), (fmt), (ap)))
;
4629 va_end(ap)__builtin_va_end(ap);
4630
4631 return (sip_expires_t *)h;
4632}
4633#endif
4634
4635/** @} */
4636
4637/**@addtogroup sip_date
4638 * @{
4639 */
4640
4641/** Parse a SIP @ref sip_date "Date header". @internal */
4642SOFIAPUBFUN issize_t sip_date_d(su_home_t *, msg_header_t *,
4643 char *s, isize_t slen);
4644
4645/** Print a SIP @ref sip_date "Date header". @internal */
4646SOFIAPUBFUN issize_t sip_date_e(char b[], isize_t bsiz,
4647 msg_header_t const *h, int flags);
4648
4649/**Access a SIP @ref sip_date "Date header"
4650 * structure #sip_date_t from #sip_t.
4651 *
4652 */
4653#define sip_date(sip)((sip_date_t *)msg_header_access((msg_pub_t*)(sip), sip_date_class
))
\
4654 ((sip_date_t *)msg_header_access((msg_pub_t*)(sip), sip_date_class))
4655
4656/**Initializer for structure #sip_date_t.
4657 *
4658 * A static #sip_date_t structure for
4659 * @ref sip_date "Date header" must be initialized with
4660 * the SIP_DATE_INIT() macro.
4661 * For instance,
4662 * @code
4663 *
4664 * sip_date_t sip_date = SIP_DATE_INIT;
4665 *
4666 * @endcode
4667 * @HI
4668 *
4669 */
4670#define SIP_DATE_INIT(){{{ 0, 0, sip_date_class }}} SIP_HDR_INIT(date){{{ 0, 0, sip_date_class }}}
4671
4672/**Initialize a structure #sip_date_t.
4673 *
4674 * An #sip_date_t structure for
4675 * @ref sip_date "Date header" can be initialized with the
4676 * sip_date_init() function/macro. For instance,
4677 * @code
4678 *
4679 * sip_date_t sip_date;
4680 *
4681 * sip_date_init(&sip_date);
4682 *
4683 * @endcode
4684 * @HI
4685 *
4686 */
4687#if SU_HAVE_INLINE1
4688su_inlinestatic inline sip_date_t *sip_date_init(sip_date_t x[1])
4689{
4690 return SIP_HEADER_INIT(x, sip_date_class, sizeof(sip_date_t))((void)memset((x), 0, (sizeof(sip_date_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_date_class)), (x))
;
4691}
4692#else
4693#define sip_date_init(x) \
4694 SIP_HEADER_INIT(x, sip_date_class, sizeof(sip_date_t))((void)memset((x), 0, (sizeof(sip_date_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_date_class)), (x))
4695#endif
4696
4697/**Test if header object is instance of #sip_date_t.
4698 *
4699 * Check if the header class is an instance of
4700 * @ref sip_date "Date header" object and return true (nonzero),
4701 * otherwise return false (zero).
4702 *
4703 * @param header pointer to the header structure to be tested
4704 *
4705 * @retval 1 (true) if the @a header is an instance of header date
4706 * @retval 0 (false) otherwise
4707 *
4708 */
4709#if SU_HAVE_INLINE1
4710su_inlinestatic inline int sip_is_date(sip_header_t const *header)
4711{
4712 return header && header->sh_classsh_common->h_class->hc_hash == sip_date_hash;
4713}
4714#else
4715int sip_is_date(sip_header_t const *header);
4716#endif
4717
4718#define sip_date_p(h)sip_is_date((h)) sip_is_date((h))
4719
4720
4721/**Duplicate a list of @ref sip_date "Date header" header structures #sip_date_t.
4722 *
4723 * Duplicate a header
4724 * structure @a hdr. If the header structure @a hdr
4725 * contains a reference (@c hdr->x_next) to a list of
4726 * headers, all the headers in the list are duplicated, too.
4727 *
4728 * @param home memory home used to allocate new structure
4729 * @param hdr header structure to be duplicated
4730 *
4731 * When duplicating, all parameter lists and non-constant
4732 * strings attached to the header are copied, too. The
4733 * function uses given memory @a home to allocate all the
4734 * memory areas used to copy the header.
4735 *
4736 * @par Example
4737 * @code
4738 *
4739 * date = sip_date_dup(home, sip->sip_date);
4740 *
4741 * @endcode
4742 *
4743 * @return
4744 * A pointer to the
4745 * newly duplicated #sip_date_t header structure, or NULL
4746 * upon an error.
4747 *
4748 */
4749#if SU_HAVE_INLINE1
4750su_inlinestatic inline
4751#endif
4752sip_date_t *sip_date_dup(su_home_t *home, sip_date_t const *hdr)
4753 __attribute__((__malloc__));
4754
4755#if SU_HAVE_INLINE1
4756su_inlinestatic inline
4757sip_date_t *sip_date_dup(su_home_t *home, sip_date_t const *hdr)
4758{
4759 return (sip_date_t *)
4760 msg_header_dup_as(home, sip_date_class, (msg_header_t const *)hdr);
4761}
4762#endif
4763
4764/**Copy a list of @ref sip_date "Date header" header structures #sip_date_t.
4765 *
4766 * The function sip_date_copy() copies a header structure @a
4767 * hdr. If the header structure @a hdr contains a reference (@c
4768 * hdr->h_next) to a list of headers, all the headers in that
4769 * list are copied, too. The function uses given memory @a home
4770 * to allocate all the memory areas used to copy the list of header
4771 * structure @a hdr.
4772 *
4773 * @param home memory home used to allocate new structure
4774 * @param hdr pointer to the header structure to be copied
4775 *
4776 * When copying, only the header structure and parameter lists attached to
4777 * it are duplicated. The new header structure retains all the references to
4778 * the strings within the old @a hdr header, including the encoding of the
4779 * old header, if present.
4780 *
4781 * @par Example
4782 * @code
4783 *
4784 * date = sip_date_copy(home, sip->sip_date);
4785 *
4786 * @endcode
4787 *
4788 * @return
4789 * A pointer to newly copied header structure, or NULL upon an error.
4790 *
4791 */
4792#if SU_HAVE_INLINE1
4793su_inlinestatic inline
4794#endif
4795sip_date_t *sip_date_copy(su_home_t *home, sip_date_t const *hdr)
4796 __attribute__((__malloc__));
4797
4798#if SU_HAVE_INLINE1
4799su_inlinestatic inline
4800sip_date_t *sip_date_copy(su_home_t *home, sip_date_t const *hdr)
4801{
4802 return (sip_date_t *)
4803 msg_header_copy_as(home, sip_date_class, (msg_header_t const *)hdr);
4804}
4805#endif
4806
4807/**Make a @ref sip_date "Date header" structure #sip_date_t.
4808 *
4809 * The function sip_date_make() makes a new
4810 * #sip_date_t header structure. It allocates a new
4811 * header structure, and decodes the string @a s as the
4812 * value of the structure.
4813 *
4814 * @param home memory home used to allocate new header structure.
4815 * @param s string to be decoded as value of the new header structure
4816 *
4817 * @return
4818 * A pointer to newly maked #sip_date_t header structure, or NULL upon an
4819 * error.
4820 *
4821 */
4822#if SU_HAVE_INLINE1
4823su_inlinestatic inline
4824#endif
4825sip_date_t *sip_date_make(su_home_t *home, char const *s)
4826 __attribute__((__malloc__));
4827
4828#if SU_HAVE_INLINE1
4829su_inlinestatic inline sip_date_t *sip_date_make(su_home_t *home, char const *s)
4830{
4831 return (sip_date_t *)sip_header_make(home, sip_date_class, s)((sip_header_t *)msg_header_make((home), (sip_date_class), (s
)))
;
4832}
4833#endif
4834
4835/**Make a @ref sip_date "Date header" from formatting result.
4836 *
4837 * Make a new #sip_date_t object using formatting result as its value.
4838 * The function first prints the arguments according to the format @a fmt
4839 * specified. Then it allocates a new header structure, and parses the
4840 * formatting result to the structure #sip_date_t.
4841 *
4842 * @param home memory home used to allocate new header structure.
4843 * @param fmt string used as a printf()-style format
4844 * @param ... argument list for format
4845 *
4846 * @return
4847 * A pointer to newly
4848 * makes header structure, or NULL upon an error.
4849 *
4850 * @HIDE
4851 *
4852 */
4853#if SU_HAVE_INLINE1
4854su_inlinestatic inline
4855#endif
4856sip_date_t *sip_date_format(su_home_t *home, char const *fmt, ...)
4857 __attribute__((__malloc__, __format__ (printf, 2, 3)));
4858
4859#if SU_HAVE_INLINE1
4860su_inlinestatic inline sip_date_t *sip_date_format(su_home_t *home, char const *fmt, ...)
4861{
4862 sip_header_t *h;
4863 va_list ap;
4864
4865 va_start(ap, fmt)__builtin_va_start(ap, fmt);
4866 h = sip_header_vformat(home, sip_date_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_date_class),
(fmt), (ap)))
;
4867 va_end(ap)__builtin_va_end(ap);
4868
4869 return (sip_date_t *)h;
4870}
4871#endif
4872
4873/** @} */
4874
4875/**@addtogroup sip_retry_after
4876 * @{
4877 */
4878
4879/** Parse a SIP @ref sip_retry_after "Retry-After header". @internal */
4880SOFIAPUBFUN issize_t sip_retry_after_d(su_home_t *, msg_header_t *,
4881 char *s, isize_t slen);
4882
4883/** Print a SIP @ref sip_retry_after "Retry-After header". @internal */
4884SOFIAPUBFUN issize_t sip_retry_after_e(char b[], isize_t bsiz,
4885 msg_header_t const *h, int flags);
4886
4887/**Access a SIP @ref sip_retry_after "Retry-After header"
4888 * structure #sip_retry_after_t from #sip_t.
4889 *
4890 */
4891#define sip_retry_after(sip)((sip_retry_after_t *)msg_header_access((msg_pub_t*)(sip), sip_retry_after_class
))
\
4892 ((sip_retry_after_t *)msg_header_access((msg_pub_t*)(sip), sip_retry_after_class))
4893
4894/**Initializer for structure #sip_retry_after_t.
4895 *
4896 * A static #sip_retry_after_t structure for
4897 * @ref sip_retry_after "Retry-After header" must be initialized with
4898 * the SIP_RETRY_AFTER_INIT() macro.
4899 * For instance,
4900 * @code
4901 *
4902 * sip_retry_after_t sip_retry_after = SIP_RETRY_AFTER_INIT;
4903 *
4904 * @endcode
4905 * @HI
4906 *
4907 */
4908#define SIP_RETRY_AFTER_INIT(){{{ 0, 0, sip_retry_after_class }}} SIP_HDR_INIT(retry_after){{{ 0, 0, sip_retry_after_class }}}
4909
4910/**Initialize a structure #sip_retry_after_t.
4911 *
4912 * An #sip_retry_after_t structure for
4913 * @ref sip_retry_after "Retry-After header" can be initialized with the
4914 * sip_retry_after_init() function/macro. For instance,
4915 * @code
4916 *
4917 * sip_retry_after_t sip_retry_after;
4918 *
4919 * sip_retry_after_init(&sip_retry_after);
4920 *
4921 * @endcode
4922 * @HI
4923 *
4924 */
4925#if SU_HAVE_INLINE1
4926su_inlinestatic inline sip_retry_after_t *sip_retry_after_init(sip_retry_after_t x[1])
4927{
4928 return SIP_HEADER_INIT(x, sip_retry_after_class, sizeof(sip_retry_after_t))((void)memset((x), 0, (sizeof(sip_retry_after_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_retry_after_class)), (
x))
;
4929}
4930#else
4931#define sip_retry_after_init(x) \
4932 SIP_HEADER_INIT(x, sip_retry_after_class, sizeof(sip_retry_after_t))((void)memset((x), 0, (sizeof(sip_retry_after_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_retry_after_class)), (
x))
4933#endif
4934
4935/**Test if header object is instance of #sip_retry_after_t.
4936 *
4937 * Check if the header class is an instance of
4938 * @ref sip_retry_after "Retry-After header" object and return true (nonzero),
4939 * otherwise return false (zero).
4940 *
4941 * @param header pointer to the header structure to be tested
4942 *
4943 * @retval 1 (true) if the @a header is an instance of header retry_after
4944 * @retval 0 (false) otherwise
4945 *
4946 */
4947#if SU_HAVE_INLINE1
4948su_inlinestatic inline int sip_is_retry_after(sip_header_t const *header)
4949{
4950 return header && header->sh_classsh_common->h_class->hc_hash == sip_retry_after_hash;
4951}
4952#else
4953int sip_is_retry_after(sip_header_t const *header);
4954#endif
4955
4956#define sip_retry_after_p(h)sip_is_retry_after((h)) sip_is_retry_after((h))
4957
4958
4959/**Duplicate a list of @ref sip_retry_after "Retry-After header" header structures #sip_retry_after_t.
4960 *
4961 * Duplicate a header
4962 * structure @a hdr. If the header structure @a hdr
4963 * contains a reference (@c hdr->x_next) to a list of
4964 * headers, all the headers in the list are duplicated, too.
4965 *
4966 * @param home memory home used to allocate new structure
4967 * @param hdr header structure to be duplicated
4968 *
4969 * When duplicating, all parameter lists and non-constant
4970 * strings attached to the header are copied, too. The
4971 * function uses given memory @a home to allocate all the
4972 * memory areas used to copy the header.
4973 *
4974 * @par Example
4975 * @code
4976 *
4977 * retry_after = sip_retry_after_dup(home, sip->sip_retry_after);
4978 *
4979 * @endcode
4980 *
4981 * @return
4982 * A pointer to the
4983 * newly duplicated #sip_retry_after_t header structure, or NULL
4984 * upon an error.
4985 *
4986 */
4987#if SU_HAVE_INLINE1
4988su_inlinestatic inline
4989#endif
4990sip_retry_after_t *sip_retry_after_dup(su_home_t *home, sip_retry_after_t const *hdr)
4991 __attribute__((__malloc__));
4992
4993#if SU_HAVE_INLINE1
4994su_inlinestatic inline
4995sip_retry_after_t *sip_retry_after_dup(su_home_t *home, sip_retry_after_t const *hdr)
4996{
4997 return (sip_retry_after_t *)
4998 msg_header_dup_as(home, sip_retry_after_class, (msg_header_t const *)hdr);
4999}
5000#endif
5001
5002/**Copy a list of @ref sip_retry_after "Retry-After header" header structures #sip_retry_after_t.
5003 *
5004 * The function sip_retry_after_copy() copies a header structure @a
5005 * hdr. If the header structure @a hdr contains a reference (@c
5006 * hdr->h_next) to a list of headers, all the headers in that
5007 * list are copied, too. The function uses given memory @a home
5008 * to allocate all the memory areas used to copy the list of header
5009 * structure @a hdr.
5010 *
5011 * @param home memory home used to allocate new structure
5012 * @param hdr pointer to the header structure to be copied
5013 *
5014 * When copying, only the header structure and parameter lists attached to
5015 * it are duplicated. The new header structure retains all the references to
5016 * the strings within the old @a hdr header, including the encoding of the
5017 * old header, if present.
5018 *
5019 * @par Example
5020 * @code
5021 *
5022 * retry_after = sip_retry_after_copy(home, sip->sip_retry_after);
5023 *
5024 * @endcode
5025 *
5026 * @return
5027 * A pointer to newly copied header structure, or NULL upon an error.
5028 *
5029 */
5030#if SU_HAVE_INLINE1
5031su_inlinestatic inline
5032#endif
5033sip_retry_after_t *sip_retry_after_copy(su_home_t *home, sip_retry_after_t const *hdr)
5034 __attribute__((__malloc__));
5035
5036#if SU_HAVE_INLINE1
5037su_inlinestatic inline
5038sip_retry_after_t *sip_retry_after_copy(su_home_t *home, sip_retry_after_t const *hdr)
5039{
5040 return (sip_retry_after_t *)
5041 msg_header_copy_as(home, sip_retry_after_class, (msg_header_t const *)hdr);
5042}
5043#endif
5044
5045/**Make a @ref sip_retry_after "Retry-After header" structure #sip_retry_after_t.
5046 *
5047 * The function sip_retry_after_make() makes a new
5048 * #sip_retry_after_t header structure. It allocates a new
5049 * header structure, and decodes the string @a s as the
5050 * value of the structure.
5051 *
5052 * @param home memory home used to allocate new header structure.
5053 * @param s string to be decoded as value of the new header structure
5054 *
5055 * @return
5056 * A pointer to newly maked #sip_retry_after_t header structure, or NULL upon an
5057 * error.
5058 *
5059 */
5060#if SU_HAVE_INLINE1
5061su_inlinestatic inline
5062#endif
5063sip_retry_after_t *sip_retry_after_make(su_home_t *home, char const *s)
5064 __attribute__((__malloc__));
5065
5066#if SU_HAVE_INLINE1
5067su_inlinestatic inline sip_retry_after_t *sip_retry_after_make(su_home_t *home, char const *s)
5068{
5069 return (sip_retry_after_t *)sip_header_make(home, sip_retry_after_class, s)((sip_header_t *)msg_header_make((home), (sip_retry_after_class
), (s)))
;
5070}
5071#endif
5072
5073/**Make a @ref sip_retry_after "Retry-After header" from formatting result.
5074 *
5075 * Make a new #sip_retry_after_t object using formatting result as its value.
5076 * The function first prints the arguments according to the format @a fmt
5077 * specified. Then it allocates a new header structure, and parses the
5078 * formatting result to the structure #sip_retry_after_t.
5079 *
5080 * @param home memory home used to allocate new header structure.
5081 * @param fmt string used as a printf()-style format
5082 * @param ... argument list for format
5083 *
5084 * @return
5085 * A pointer to newly
5086 * makes header structure, or NULL upon an error.
5087 *
5088 * @HIDE
5089 *
5090 */
5091#if SU_HAVE_INLINE1
5092su_inlinestatic inline
5093#endif
5094sip_retry_after_t *sip_retry_after_format(su_home_t *home, char const *fmt, ...)
5095 __attribute__((__malloc__, __format__ (printf, 2, 3)));
5096
5097#if SU_HAVE_INLINE1
5098su_inlinestatic inline sip_retry_after_t *sip_retry_after_format(su_home_t *home, char const *fmt, ...)
5099{
5100 sip_header_t *h;
5101 va_list ap;
5102
5103 va_start(ap, fmt)__builtin_va_start(ap, fmt);
5104 h = sip_header_vformat(home, sip_retry_after_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_retry_after_class
), (fmt), (ap)))
;
5105 va_end(ap)__builtin_va_end(ap);
5106
5107 return (sip_retry_after_t *)h;
5108}
5109#endif
5110
5111/** @} */
5112
5113/**@addtogroup sip_timestamp
5114 * @{
5115 */
5116
5117/** Parse a SIP @ref sip_timestamp "Timestamp header". @internal */
5118SOFIAPUBFUN issize_t sip_timestamp_d(su_home_t *, msg_header_t *,
5119 char *s, isize_t slen);
5120
5121/** Print a SIP @ref sip_timestamp "Timestamp header". @internal */
5122SOFIAPUBFUN issize_t sip_timestamp_e(char b[], isize_t bsiz,
5123 msg_header_t const *h, int flags);
5124
5125/**Access a SIP @ref sip_timestamp "Timestamp header"
5126 * structure #sip_timestamp_t from #sip_t.
5127 *
5128 */
5129#define sip_timestamp(sip)((sip_timestamp_t *)msg_header_access((msg_pub_t*)(sip), sip_timestamp_class
))
\
5130 ((sip_timestamp_t *)msg_header_access((msg_pub_t*)(sip), sip_timestamp_class))
5131
5132/**Initializer for structure #sip_timestamp_t.
5133 *
5134 * A static #sip_timestamp_t structure for
5135 * @ref sip_timestamp "Timestamp header" must be initialized with
5136 * the SIP_TIMESTAMP_INIT() macro.
5137 * For instance,
5138 * @code
5139 *
5140 * sip_timestamp_t sip_timestamp = SIP_TIMESTAMP_INIT;
5141 *
5142 * @endcode
5143 * @HI
5144 *
5145 */
5146#define SIP_TIMESTAMP_INIT(){{{ 0, 0, sip_timestamp_class }}} SIP_HDR_INIT(timestamp){{{ 0, 0, sip_timestamp_class }}}
5147
5148/**Initialize a structure #sip_timestamp_t.
5149 *
5150 * An #sip_timestamp_t structure for
5151 * @ref sip_timestamp "Timestamp header" can be initialized with the
5152 * sip_timestamp_init() function/macro. For instance,
5153 * @code
5154 *
5155 * sip_timestamp_t sip_timestamp;
5156 *
5157 * sip_timestamp_init(&sip_timestamp);
5158 *
5159 * @endcode
5160 * @HI
5161 *
5162 */
5163#if SU_HAVE_INLINE1
5164su_inlinestatic inline sip_timestamp_t *sip_timestamp_init(sip_timestamp_t x[1])
5165{
5166 return SIP_HEADER_INIT(x, sip_timestamp_class, sizeof(sip_timestamp_t))((void)memset((x), 0, (sizeof(sip_timestamp_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_timestamp_class)), (x))
;
5167}
5168#else
5169#define sip_timestamp_init(x) \
5170 SIP_HEADER_INIT(x, sip_timestamp_class, sizeof(sip_timestamp_t))((void)memset((x), 0, (sizeof(sip_timestamp_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_timestamp_class)), (x))
5171#endif
5172
5173/**Test if header object is instance of #sip_timestamp_t.
5174 *
5175 * Check if the header class is an instance of
5176 * @ref sip_timestamp "Timestamp header" object and return true (nonzero),
5177 * otherwise return false (zero).
5178 *
5179 * @param header pointer to the header structure to be tested
5180 *
5181 * @retval 1 (true) if the @a header is an instance of header timestamp
5182 * @retval 0 (false) otherwise
5183 *
5184 */
5185#if SU_HAVE_INLINE1
5186su_inlinestatic inline int sip_is_timestamp(sip_header_t const *header)
5187{
5188 return header && header->sh_classsh_common->h_class->hc_hash == sip_timestamp_hash;
5189}
5190#else
5191int sip_is_timestamp(sip_header_t const *header);
5192#endif
5193
5194#define sip_timestamp_p(h)sip_is_timestamp((h)) sip_is_timestamp((h))
5195
5196
5197/**Duplicate a list of @ref sip_timestamp "Timestamp header" header structures #sip_timestamp_t.
5198 *
5199 * Duplicate a header
5200 * structure @a hdr. If the header structure @a hdr
5201 * contains a reference (@c hdr->x_next) to a list of
5202 * headers, all the headers in the list are duplicated, too.
5203 *
5204 * @param home memory home used to allocate new structure
5205 * @param hdr header structure to be duplicated
5206 *
5207 * When duplicating, all parameter lists and non-constant
5208 * strings attached to the header are copied, too. The
5209 * function uses given memory @a home to allocate all the
5210 * memory areas used to copy the header.
5211 *
5212 * @par Example
5213 * @code
5214 *
5215 * timestamp = sip_timestamp_dup(home, sip->sip_timestamp);
5216 *
5217 * @endcode
5218 *
5219 * @return
5220 * A pointer to the
5221 * newly duplicated #sip_timestamp_t header structure, or NULL
5222 * upon an error.
5223 *
5224 */
5225#if SU_HAVE_INLINE1
5226su_inlinestatic inline
5227#endif
5228sip_timestamp_t *sip_timestamp_dup(su_home_t *home, sip_timestamp_t const *hdr)
5229 __attribute__((__malloc__));
5230
5231#if SU_HAVE_INLINE1
5232su_inlinestatic inline
5233sip_timestamp_t *sip_timestamp_dup(su_home_t *home, sip_timestamp_t const *hdr)
5234{
5235 return (sip_timestamp_t *)
5236 msg_header_dup_as(home, sip_timestamp_class, (msg_header_t const *)hdr);
5237}
5238#endif
5239
5240/**Copy a list of @ref sip_timestamp "Timestamp header" header structures #sip_timestamp_t.
5241 *
5242 * The function sip_timestamp_copy() copies a header structure @a
5243 * hdr. If the header structure @a hdr contains a reference (@c
5244 * hdr->h_next) to a list of headers, all the headers in that
5245 * list are copied, too. The function uses given memory @a home
5246 * to allocate all the memory areas used to copy the list of header
5247 * structure @a hdr.
5248 *
5249 * @param home memory home used to allocate new structure
5250 * @param hdr pointer to the header structure to be copied
5251 *
5252 * When copying, only the header structure and parameter lists attached to
5253 * it are duplicated. The new header structure retains all the references to
5254 * the strings within the old @a hdr header, including the encoding of the
5255 * old header, if present.
5256 *
5257 * @par Example
5258 * @code
5259 *
5260 * timestamp = sip_timestamp_copy(home, sip->sip_timestamp);
5261 *
5262 * @endcode
5263 *
5264 * @return
5265 * A pointer to newly copied header structure, or NULL upon an error.
5266 *
5267 */
5268#if SU_HAVE_INLINE1
5269su_inlinestatic inline
5270#endif
5271sip_timestamp_t *sip_timestamp_copy(su_home_t *home, sip_timestamp_t const *hdr)
5272 __attribute__((__malloc__));
5273
5274#if SU_HAVE_INLINE1
5275su_inlinestatic inline
5276sip_timestamp_t *sip_timestamp_copy(su_home_t *home, sip_timestamp_t const *hdr)
5277{
5278 return (sip_timestamp_t *)
5279 msg_header_copy_as(home, sip_timestamp_class, (msg_header_t const *)hdr);
5280}
5281#endif
5282
5283/**Make a @ref sip_timestamp "Timestamp header" structure #sip_timestamp_t.
5284 *
5285 * The function sip_timestamp_make() makes a new
5286 * #sip_timestamp_t header structure. It allocates a new
5287 * header structure, and decodes the string @a s as the
5288 * value of the structure.
5289 *
5290 * @param home memory home used to allocate new header structure.
5291 * @param s string to be decoded as value of the new header structure
5292 *
5293 * @return
5294 * A pointer to newly maked #sip_timestamp_t header structure, or NULL upon an
5295 * error.
5296 *
5297 */
5298#if SU_HAVE_INLINE1
5299su_inlinestatic inline
5300#endif
5301sip_timestamp_t *sip_timestamp_make(su_home_t *home, char const *s)
5302 __attribute__((__malloc__));
5303
5304#if SU_HAVE_INLINE1
5305su_inlinestatic inline sip_timestamp_t *sip_timestamp_make(su_home_t *home, char const *s)
5306{
5307 return (sip_timestamp_t *)sip_header_make(home, sip_timestamp_class, s)((sip_header_t *)msg_header_make((home), (sip_timestamp_class
), (s)))
;
5308}
5309#endif
5310
5311/**Make a @ref sip_timestamp "Timestamp header" from formatting result.
5312 *
5313 * Make a new #sip_timestamp_t object using formatting result as its value.
5314 * The function first prints the arguments according to the format @a fmt
5315 * specified. Then it allocates a new header structure, and parses the
5316 * formatting result to the structure #sip_timestamp_t.
5317 *
5318 * @param home memory home used to allocate new header structure.
5319 * @param fmt string used as a printf()-style format
5320 * @param ... argument list for format
5321 *
5322 * @return
5323 * A pointer to newly
5324 * makes header structure, or NULL upon an error.
5325 *
5326 * @HIDE
5327 *
5328 */
5329#if SU_HAVE_INLINE1
5330su_inlinestatic inline
5331#endif
5332sip_timestamp_t *sip_timestamp_format(su_home_t *home, char const *fmt, ...)
5333 __attribute__((__malloc__, __format__ (printf, 2, 3)));
5334
5335#if SU_HAVE_INLINE1
5336su_inlinestatic inline sip_timestamp_t *sip_timestamp_format(su_home_t *home, char const *fmt, ...)
5337{
5338 sip_header_t *h;
5339 va_list ap;
5340
5341 va_start(ap, fmt)__builtin_va_start(ap, fmt);
5342 h = sip_header_vformat(home, sip_timestamp_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_timestamp_class
), (fmt), (ap)))
;
5343 va_end(ap)__builtin_va_end(ap);
5344
5345 return (sip_timestamp_t *)h;
5346}
5347#endif
5348
5349/** @} */
5350
5351/**@addtogroup sip_min_expires
5352 * @{
5353 */
5354
5355/** Parse a SIP @ref sip_min_expires "Min-Expires header". @internal */
5356SOFIAPUBFUN issize_t sip_min_expires_d(su_home_t *, msg_header_t *,
5357 char *s, isize_t slen);
5358
5359/** Print a SIP @ref sip_min_expires "Min-Expires header". @internal */
5360SOFIAPUBFUN issize_t sip_min_expires_e(char b[], isize_t bsiz,
5361 msg_header_t const *h, int flags);
5362
5363/**Access a SIP @ref sip_min_expires "Min-Expires header"
5364 * structure #sip_min_expires_t from #sip_t.
5365 *
5366 */
5367#define sip_min_expires(sip)((sip_min_expires_t *)msg_header_access((msg_pub_t*)(sip), sip_min_expires_class
))
\
5368 ((sip_min_expires_t *)msg_header_access((msg_pub_t*)(sip), sip_min_expires_class))
5369
5370/**Initializer for structure #sip_min_expires_t.
5371 *
5372 * A static #sip_min_expires_t structure for
5373 * @ref sip_min_expires "Min-Expires header" must be initialized with
5374 * the SIP_MIN_EXPIRES_INIT() macro.
5375 * For instance,
5376 * @code
5377 *
5378 * sip_min_expires_t sip_min_expires = SIP_MIN_EXPIRES_INIT;
5379 *
5380 * @endcode
5381 * @HI
5382 *
5383 */
5384#define SIP_MIN_EXPIRES_INIT(){{{ 0, 0, sip_min_expires_class }}} SIP_HDR_INIT(min_expires){{{ 0, 0, sip_min_expires_class }}}
5385
5386/**Initialize a structure #sip_min_expires_t.
5387 *
5388 * An #sip_min_expires_t structure for
5389 * @ref sip_min_expires "Min-Expires header" can be initialized with the
5390 * sip_min_expires_init() function/macro. For instance,
5391 * @code
5392 *
5393 * sip_min_expires_t sip_min_expires;
5394 *
5395 * sip_min_expires_init(&sip_min_expires);
5396 *
5397 * @endcode
5398 * @HI
5399 *
5400 */
5401#if SU_HAVE_INLINE1
5402su_inlinestatic inline sip_min_expires_t *sip_min_expires_init(sip_min_expires_t x[1])
5403{
5404 return SIP_HEADER_INIT(x, sip_min_expires_class, sizeof(sip_min_expires_t))((void)memset((x), 0, (sizeof(sip_min_expires_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_min_expires_class)), (
x))
;
5405}
5406#else
5407#define sip_min_expires_init(x) \
5408 SIP_HEADER_INIT(x, sip_min_expires_class, sizeof(sip_min_expires_t))((void)memset((x), 0, (sizeof(sip_min_expires_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_min_expires_class)), (
x))
5409#endif
5410
5411/**Test if header object is instance of #sip_min_expires_t.
5412 *
5413 * Check if the header class is an instance of
5414 * @ref sip_min_expires "Min-Expires header" object and return true (nonzero),
5415 * otherwise return false (zero).
5416 *
5417 * @param header pointer to the header structure to be tested
5418 *
5419 * @retval 1 (true) if the @a header is an instance of header min_expires
5420 * @retval 0 (false) otherwise
5421 *
5422 */
5423#if SU_HAVE_INLINE1
5424su_inlinestatic inline int sip_is_min_expires(sip_header_t const *header)
5425{
5426 return header && header->sh_classsh_common->h_class->hc_hash == sip_min_expires_hash;
5427}
5428#else
5429int sip_is_min_expires(sip_header_t const *header);
5430#endif
5431
5432#define sip_min_expires_p(h)sip_is_min_expires((h)) sip_is_min_expires((h))
5433
5434
5435/**Duplicate a list of @ref sip_min_expires "Min-Expires header" header structures #sip_min_expires_t.
5436 *
5437 * Duplicate a header
5438 * structure @a hdr. If the header structure @a hdr
5439 * contains a reference (@c hdr->x_next) to a list of
5440 * headers, all the headers in the list are duplicated, too.
5441 *
5442 * @param home memory home used to allocate new structure
5443 * @param hdr header structure to be duplicated
5444 *
5445 * When duplicating, all parameter lists and non-constant
5446 * strings attached to the header are copied, too. The
5447 * function uses given memory @a home to allocate all the
5448 * memory areas used to copy the header.
5449 *
5450 * @par Example
5451 * @code
5452 *
5453 * min_expires = sip_min_expires_dup(home, sip->sip_min_expires);
5454 *
5455 * @endcode
5456 *
5457 * @return
5458 * A pointer to the
5459 * newly duplicated #sip_min_expires_t header structure, or NULL
5460 * upon an error.
5461 *
5462 */
5463#if SU_HAVE_INLINE1
5464su_inlinestatic inline
5465#endif
5466sip_min_expires_t *sip_min_expires_dup(su_home_t *home, sip_min_expires_t const *hdr)
5467 __attribute__((__malloc__));
5468
5469#if SU_HAVE_INLINE1
5470su_inlinestatic inline
5471sip_min_expires_t *sip_min_expires_dup(su_home_t *home, sip_min_expires_t const *hdr)
5472{
5473 return (sip_min_expires_t *)
5474 msg_header_dup_as(home, sip_min_expires_class, (msg_header_t const *)hdr);
5475}
5476#endif
5477
5478/**Copy a list of @ref sip_min_expires "Min-Expires header" header structures #sip_min_expires_t.
5479 *
5480 * The function sip_min_expires_copy() copies a header structure @a
5481 * hdr. If the header structure @a hdr contains a reference (@c
5482 * hdr->h_next) to a list of headers, all the headers in that
5483 * list are copied, too. The function uses given memory @a home
5484 * to allocate all the memory areas used to copy the list of header
5485 * structure @a hdr.
5486 *
5487 * @param home memory home used to allocate new structure
5488 * @param hdr pointer to the header structure to be copied
5489 *
5490 * When copying, only the header structure and parameter lists attached to
5491 * it are duplicated. The new header structure retains all the references to
5492 * the strings within the old @a hdr header, including the encoding of the
5493 * old header, if present.
5494 *
5495 * @par Example
5496 * @code
5497 *
5498 * min_expires = sip_min_expires_copy(home, sip->sip_min_expires);
5499 *
5500 * @endcode
5501 *
5502 * @return
5503 * A pointer to newly copied header structure, or NULL upon an error.
5504 *
5505 */
5506#if SU_HAVE_INLINE1
5507su_inlinestatic inline
5508#endif
5509sip_min_expires_t *sip_min_expires_copy(su_home_t *home, sip_min_expires_t const *hdr)
5510 __attribute__((__malloc__));
5511
5512#if SU_HAVE_INLINE1
5513su_inlinestatic inline
5514sip_min_expires_t *sip_min_expires_copy(su_home_t *home, sip_min_expires_t const *hdr)
5515{
5516 return (sip_min_expires_t *)
5517 msg_header_copy_as(home, sip_min_expires_class, (msg_header_t const *)hdr);
5518}
5519#endif
5520
5521/**Make a @ref sip_min_expires "Min-Expires header" structure #sip_min_expires_t.
5522 *
5523 * The function sip_min_expires_make() makes a new
5524 * #sip_min_expires_t header structure. It allocates a new
5525 * header structure, and decodes the string @a s as the
5526 * value of the structure.
5527 *
5528 * @param home memory home used to allocate new header structure.
5529 * @param s string to be decoded as value of the new header structure
5530 *
5531 * @return
5532 * A pointer to newly maked #sip_min_expires_t header structure, or NULL upon an
5533 * error.
5534 *
5535 */
5536#if SU_HAVE_INLINE1
5537su_inlinestatic inline
5538#endif
5539sip_min_expires_t *sip_min_expires_make(su_home_t *home, char const *s)
5540 __attribute__((__malloc__));
5541
5542#if SU_HAVE_INLINE1
5543su_inlinestatic inline sip_min_expires_t *sip_min_expires_make(su_home_t *home, char const *s)
5544{
5545 return (sip_min_expires_t *)sip_header_make(home, sip_min_expires_class, s)((sip_header_t *)msg_header_make((home), (sip_min_expires_class
), (s)))
;
5546}
5547#endif
5548
5549/**Make a @ref sip_min_expires "Min-Expires header" from formatting result.
5550 *
5551 * Make a new #sip_min_expires_t object using formatting result as its value.
5552 * The function first prints the arguments according to the format @a fmt
5553 * specified. Then it allocates a new header structure, and parses the
5554 * formatting result to the structure #sip_min_expires_t.
5555 *
5556 * @param home memory home used to allocate new header structure.
5557 * @param fmt string used as a printf()-style format
5558 * @param ... argument list for format
5559 *
5560 * @return
5561 * A pointer to newly
5562 * makes header structure, or NULL upon an error.
5563 *
5564 * @HIDE
5565 *
5566 */
5567#if SU_HAVE_INLINE1
5568su_inlinestatic inline
5569#endif
5570sip_min_expires_t *sip_min_expires_format(su_home_t *home, char const *fmt, ...)
5571 __attribute__((__malloc__, __format__ (printf, 2, 3)));
5572
5573#if SU_HAVE_INLINE1
5574su_inlinestatic inline sip_min_expires_t *sip_min_expires_format(su_home_t *home, char const *fmt, ...)
5575{
5576 sip_header_t *h;
5577 va_list ap;
5578
5579 va_start(ap, fmt)__builtin_va_start(ap, fmt);
5580 h = sip_header_vformat(home, sip_min_expires_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_min_expires_class
), (fmt), (ap)))
;
5581 va_end(ap)__builtin_va_end(ap);
5582
5583 return (sip_min_expires_t *)h;
5584}
5585#endif
5586
5587/** @} */
5588
5589/**@addtogroup sip_subject
5590 * @{
5591 */
5592
5593/** Parse a SIP @ref sip_subject "Subject header". @internal */
5594SOFIAPUBFUN issize_t sip_subject_d(su_home_t *, msg_header_t *,
5595 char *s, isize_t slen);
5596
5597/** Print a SIP @ref sip_subject "Subject header". @internal */
5598SOFIAPUBFUN issize_t sip_subject_e(char b[], isize_t bsiz,
5599 msg_header_t const *h, int flags);
5600
5601/**Access a SIP @ref sip_subject "Subject header"
5602 * structure #sip_subject_t from #sip_t.
5603 *
5604 */
5605#define sip_subject(sip)((sip_subject_t *)msg_header_access((msg_pub_t*)(sip), sip_subject_class
))
\
5606 ((sip_subject_t *)msg_header_access((msg_pub_t*)(sip), sip_subject_class))
5607
5608/**Initializer for structure #sip_subject_t.
5609 *
5610 * A static #sip_subject_t structure for
5611 * @ref sip_subject "Subject header" must be initialized with
5612 * the SIP_SUBJECT_INIT() macro.
5613 * For instance,
5614 * @code
5615 *
5616 * sip_subject_t sip_subject = SIP_SUBJECT_INIT;
5617 *
5618 * @endcode
5619 * @HI
5620 *
5621 */
5622#define SIP_SUBJECT_INIT(){{{ 0, 0, sip_subject_class }}} SIP_HDR_INIT(subject){{{ 0, 0, sip_subject_class }}}
5623
5624/**Initialize a structure #sip_subject_t.
5625 *
5626 * An #sip_subject_t structure for
5627 * @ref sip_subject "Subject header" can be initialized with the
5628 * sip_subject_init() function/macro. For instance,
5629 * @code
5630 *
5631 * sip_subject_t sip_subject;
5632 *
5633 * sip_subject_init(&sip_subject);
5634 *
5635 * @endcode
5636 * @HI
5637 *
5638 */
5639#if SU_HAVE_INLINE1
5640su_inlinestatic inline sip_subject_t *sip_subject_init(sip_subject_t x[1])
5641{
5642 return SIP_HEADER_INIT(x, sip_subject_class, sizeof(sip_subject_t))((void)memset((x), 0, (sizeof(sip_subject_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_subject_class)), (x))
;
5643}
5644#else
5645#define sip_subject_init(x) \
5646 SIP_HEADER_INIT(x, sip_subject_class, sizeof(sip_subject_t))((void)memset((x), 0, (sizeof(sip_subject_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_subject_class)), (x))
5647#endif
5648
5649/**Test if header object is instance of #sip_subject_t.
5650 *
5651 * Check if the header class is an instance of
5652 * @ref sip_subject "Subject header" object and return true (nonzero),
5653 * otherwise return false (zero).
5654 *
5655 * @param header pointer to the header structure to be tested
5656 *
5657 * @retval 1 (true) if the @a header is an instance of header subject
5658 * @retval 0 (false) otherwise
5659 *
5660 */
5661#if SU_HAVE_INLINE1
5662su_inlinestatic inline int sip_is_subject(sip_header_t const *header)
5663{
5664 return header && header->sh_classsh_common->h_class->hc_hash == sip_subject_hash;
5665}
5666#else
5667int sip_is_subject(sip_header_t const *header);
5668#endif
5669
5670#define sip_subject_p(h)sip_is_subject((h)) sip_is_subject((h))
5671
5672
5673/**Duplicate a list of @ref sip_subject "Subject header" header structures #sip_subject_t.
5674 *
5675 * Duplicate a header
5676 * structure @a hdr. If the header structure @a hdr
5677 * contains a reference (@c hdr->x_next) to a list of
5678 * headers, all the headers in the list are duplicated, too.
5679 *
5680 * @param home memory home used to allocate new structure
5681 * @param hdr header structure to be duplicated
5682 *
5683 * When duplicating, all parameter lists and non-constant
5684 * strings attached to the header are copied, too. The
5685 * function uses given memory @a home to allocate all the
5686 * memory areas used to copy the header.
5687 *
5688 * @par Example
5689 * @code
5690 *
5691 * subject = sip_subject_dup(home, sip->sip_subject);
5692 *
5693 * @endcode
5694 *
5695 * @return
5696 * A pointer to the
5697 * newly duplicated #sip_subject_t header structure, or NULL
5698 * upon an error.
5699 *
5700 */
5701#if SU_HAVE_INLINE1
5702su_inlinestatic inline
5703#endif
5704sip_subject_t *sip_subject_dup(su_home_t *home, sip_subject_t const *hdr)
5705 __attribute__((__malloc__));
5706
5707#if SU_HAVE_INLINE1
5708su_inlinestatic inline
5709sip_subject_t *sip_subject_dup(su_home_t *home, sip_subject_t const *hdr)
5710{
5711 return (sip_subject_t *)
5712 msg_header_dup_as(home, sip_subject_class, (msg_header_t const *)hdr);
5713}
5714#endif
5715
5716/**Copy a list of @ref sip_subject "Subject header" header structures #sip_subject_t.
5717 *
5718 * The function sip_subject_copy() copies a header structure @a
5719 * hdr. If the header structure @a hdr contains a reference (@c
5720 * hdr->h_next) to a list of headers, all the headers in that
5721 * list are copied, too. The function uses given memory @a home
5722 * to allocate all the memory areas used to copy the list of header
5723 * structure @a hdr.
5724 *
5725 * @param home memory home used to allocate new structure
5726 * @param hdr pointer to the header structure to be copied
5727 *
5728 * When copying, only the header structure and parameter lists attached to
5729 * it are duplicated. The new header structure retains all the references to
5730 * the strings within the old @a hdr header, including the encoding of the
5731 * old header, if present.
5732 *
5733 * @par Example
5734 * @code
5735 *
5736 * subject = sip_subject_copy(home, sip->sip_subject);
5737 *
5738 * @endcode
5739 *
5740 * @return
5741 * A pointer to newly copied header structure, or NULL upon an error.
5742 *
5743 */
5744#if SU_HAVE_INLINE1
5745su_inlinestatic inline
5746#endif
5747sip_subject_t *sip_subject_copy(su_home_t *home, sip_subject_t const *hdr)
5748 __attribute__((__malloc__));
5749
5750#if SU_HAVE_INLINE1
5751su_inlinestatic inline
5752sip_subject_t *sip_subject_copy(su_home_t *home, sip_subject_t const *hdr)
5753{
5754 return (sip_subject_t *)
5755 msg_header_copy_as(home, sip_subject_class, (msg_header_t const *)hdr);
5756}
5757#endif
5758
5759/**Make a @ref sip_subject "Subject header" structure #sip_subject_t.
5760 *
5761 * The function sip_subject_make() makes a new
5762 * #sip_subject_t header structure. It allocates a new
5763 * header structure, and decodes the string @a s as the
5764 * value of the structure.
5765 *
5766 * @param home memory home used to allocate new header structure.
5767 * @param s string to be decoded as value of the new header structure
5768 *
5769 * @return
5770 * A pointer to newly maked #sip_subject_t header structure, or NULL upon an
5771 * error.
5772 *
5773 */
5774#if SU_HAVE_INLINE1
5775su_inlinestatic inline
5776#endif
5777sip_subject_t *sip_subject_make(su_home_t *home, char const *s)
5778 __attribute__((__malloc__));
5779
5780#if SU_HAVE_INLINE1
5781su_inlinestatic inline sip_subject_t *sip_subject_make(su_home_t *home, char const *s)
5782{
5783 return (sip_subject_t *)sip_header_make(home, sip_subject_class, s)((sip_header_t *)msg_header_make((home), (sip_subject_class),
(s)))
;
5784}
5785#endif
5786
5787/**Make a @ref sip_subject "Subject header" from formatting result.
5788 *
5789 * Make a new #sip_subject_t object using formatting result as its value.
5790 * The function first prints the arguments according to the format @a fmt
5791 * specified. Then it allocates a new header structure, and parses the
5792 * formatting result to the structure #sip_subject_t.
5793 *
5794 * @param home memory home used to allocate new header structure.
5795 * @param fmt string used as a printf()-style format
5796 * @param ... argument list for format
5797 *
5798 * @return
5799 * A pointer to newly
5800 * makes header structure, or NULL upon an error.
5801 *
5802 * @HIDE
5803 *
5804 */
5805#if SU_HAVE_INLINE1
5806su_inlinestatic inline
5807#endif
5808sip_subject_t *sip_subject_format(su_home_t *home, char const *fmt, ...)
5809 __attribute__((__malloc__, __format__ (printf, 2, 3)));
5810
5811#if SU_HAVE_INLINE1
5812su_inlinestatic inline sip_subject_t *sip_subject_format(su_home_t *home, char const *fmt, ...)
5813{
5814 sip_header_t *h;
5815 va_list ap;
5816
5817 va_start(ap, fmt)__builtin_va_start(ap, fmt);
5818 h = sip_header_vformat(home, sip_subject_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_subject_class
), (fmt), (ap)))
;
5819 va_end(ap)__builtin_va_end(ap);
5820
5821 return (sip_subject_t *)h;
5822}
5823#endif
5824
5825/** @} */
5826
5827/**@addtogroup sip_priority
5828 * @{
5829 */
5830
5831/** Parse a SIP @ref sip_priority "Priority header". @internal */
5832SOFIAPUBFUN issize_t sip_priority_d(su_home_t *, msg_header_t *,
5833 char *s, isize_t slen);
5834
5835/** Print a SIP @ref sip_priority "Priority header". @internal */
5836SOFIAPUBFUN issize_t sip_priority_e(char b[], isize_t bsiz,
5837 msg_header_t const *h, int flags);
5838
5839/**Access a SIP @ref sip_priority "Priority header"
5840 * structure #sip_priority_t from #sip_t.
5841 *
5842 */
5843#define sip_priority(sip)((sip_priority_t *)msg_header_access((msg_pub_t*)(sip), sip_priority_class
))
\
5844 ((sip_priority_t *)msg_header_access((msg_pub_t*)(sip), sip_priority_class))
5845
5846/**Initializer for structure #sip_priority_t.
5847 *
5848 * A static #sip_priority_t structure for
5849 * @ref sip_priority "Priority header" must be initialized with
5850 * the SIP_PRIORITY_INIT() macro.
5851 * For instance,
5852 * @code
5853 *
5854 * sip_priority_t sip_priority = SIP_PRIORITY_INIT;
5855 *
5856 * @endcode
5857 * @HI
5858 *
5859 */
5860#define SIP_PRIORITY_INIT(){{{ 0, 0, sip_priority_class }}} SIP_HDR_INIT(priority){{{ 0, 0, sip_priority_class }}}
5861
5862/**Initialize a structure #sip_priority_t.
5863 *
5864 * An #sip_priority_t structure for
5865 * @ref sip_priority "Priority header" can be initialized with the
5866 * sip_priority_init() function/macro. For instance,
5867 * @code
5868 *
5869 * sip_priority_t sip_priority;
5870 *
5871 * sip_priority_init(&sip_priority);
5872 *
5873 * @endcode
5874 * @HI
5875 *
5876 */
5877#if SU_HAVE_INLINE1
5878su_inlinestatic inline sip_priority_t *sip_priority_init(sip_priority_t x[1])
5879{
5880 return SIP_HEADER_INIT(x, sip_priority_class, sizeof(sip_priority_t))((void)memset((x), 0, (sizeof(sip_priority_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_priority_class)), (x))
;
5881}
5882#else
5883#define sip_priority_init(x) \
5884 SIP_HEADER_INIT(x, sip_priority_class, sizeof(sip_priority_t))((void)memset((x), 0, (sizeof(sip_priority_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_priority_class)), (x))
5885#endif
5886
5887/**Test if header object is instance of #sip_priority_t.
5888 *
5889 * Check if the header class is an instance of
5890 * @ref sip_priority "Priority header" object and return true (nonzero),
5891 * otherwise return false (zero).
5892 *
5893 * @param header pointer to the header structure to be tested
5894 *
5895 * @retval 1 (true) if the @a header is an instance of header priority
5896 * @retval 0 (false) otherwise
5897 *
5898 */
5899#if SU_HAVE_INLINE1
5900su_inlinestatic inline int sip_is_priority(sip_header_t const *header)
5901{
5902 return header && header->sh_classsh_common->h_class->hc_hash == sip_priority_hash;
5903}
5904#else
5905int sip_is_priority(sip_header_t const *header);
5906#endif
5907
5908#define sip_priority_p(h)sip_is_priority((h)) sip_is_priority((h))
5909
5910
5911/**Duplicate a list of @ref sip_priority "Priority header" header structures #sip_priority_t.
5912 *
5913 * Duplicate a header
5914 * structure @a hdr. If the header structure @a hdr
5915 * contains a reference (@c hdr->x_next) to a list of
5916 * headers, all the headers in the list are duplicated, too.
5917 *
5918 * @param home memory home used to allocate new structure
5919 * @param hdr header structure to be duplicated
5920 *
5921 * When duplicating, all parameter lists and non-constant
5922 * strings attached to the header are copied, too. The
5923 * function uses given memory @a home to allocate all the
5924 * memory areas used to copy the header.
5925 *
5926 * @par Example
5927 * @code
5928 *
5929 * priority = sip_priority_dup(home, sip->sip_priority);
5930 *
5931 * @endcode
5932 *
5933 * @return
5934 * A pointer to the
5935 * newly duplicated #sip_priority_t header structure, or NULL
5936 * upon an error.
5937 *
5938 */
5939#if SU_HAVE_INLINE1
5940su_inlinestatic inline
5941#endif
5942sip_priority_t *sip_priority_dup(su_home_t *home, sip_priority_t const *hdr)
5943 __attribute__((__malloc__));
5944
5945#if SU_HAVE_INLINE1
5946su_inlinestatic inline
5947sip_priority_t *sip_priority_dup(su_home_t *home, sip_priority_t const *hdr)
5948{
5949 return (sip_priority_t *)
5950 msg_header_dup_as(home, sip_priority_class, (msg_header_t const *)hdr);
5951}
5952#endif
5953
5954/**Copy a list of @ref sip_priority "Priority header" header structures #sip_priority_t.
5955 *
5956 * The function sip_priority_copy() copies a header structure @a
5957 * hdr. If the header structure @a hdr contains a reference (@c
5958 * hdr->h_next) to a list of headers, all the headers in that
5959 * list are copied, too. The function uses given memory @a home
5960 * to allocate all the memory areas used to copy the list of header
5961 * structure @a hdr.
5962 *
5963 * @param home memory home used to allocate new structure
5964 * @param hdr pointer to the header structure to be copied
5965 *
5966 * When copying, only the header structure and parameter lists attached to
5967 * it are duplicated. The new header structure retains all the references to
5968 * the strings within the old @a hdr header, including the encoding of the
5969 * old header, if present.
5970 *
5971 * @par Example
5972 * @code
5973 *
5974 * priority = sip_priority_copy(home, sip->sip_priority);
5975 *
5976 * @endcode
5977 *
5978 * @return
5979 * A pointer to newly copied header structure, or NULL upon an error.
5980 *
5981 */
5982#if SU_HAVE_INLINE1
5983su_inlinestatic inline
5984#endif
5985sip_priority_t *sip_priority_copy(su_home_t *home, sip_priority_t const *hdr)
5986 __attribute__((__malloc__));
5987
5988#if SU_HAVE_INLINE1
5989su_inlinestatic inline
5990sip_priority_t *sip_priority_copy(su_home_t *home, sip_priority_t const *hdr)
5991{
5992 return (sip_priority_t *)
5993 msg_header_copy_as(home, sip_priority_class, (msg_header_t const *)hdr);
5994}
5995#endif
5996
5997/**Make a @ref sip_priority "Priority header" structure #sip_priority_t.
5998 *
5999 * The function sip_priority_make() makes a new
6000 * #sip_priority_t header structure. It allocates a new
6001 * header structure, and decodes the string @a s as the
6002 * value of the structure.
6003 *
6004 * @param home memory home used to allocate new header structure.
6005 * @param s string to be decoded as value of the new header structure
6006 *
6007 * @return
6008 * A pointer to newly maked #sip_priority_t header structure, or NULL upon an
6009 * error.
6010 *
6011 */
6012#if SU_HAVE_INLINE1
6013su_inlinestatic inline
6014#endif
6015sip_priority_t *sip_priority_make(su_home_t *home, char const *s)
6016 __attribute__((__malloc__));
6017
6018#if SU_HAVE_INLINE1
6019su_inlinestatic inline sip_priority_t *sip_priority_make(su_home_t *home, char const *s)
6020{
6021 return (sip_priority_t *)sip_header_make(home, sip_priority_class, s)((sip_header_t *)msg_header_make((home), (sip_priority_class)
, (s)))
;
6022}
6023#endif
6024
6025/**Make a @ref sip_priority "Priority header" from formatting result.
6026 *
6027 * Make a new #sip_priority_t object using formatting result as its value.
6028 * The function first prints the arguments according to the format @a fmt
6029 * specified. Then it allocates a new header structure, and parses the
6030 * formatting result to the structure #sip_priority_t.
6031 *
6032 * @param home memory home used to allocate new header structure.
6033 * @param fmt string used as a printf()-style format
6034 * @param ... argument list for format
6035 *
6036 * @return
6037 * A pointer to newly
6038 * makes header structure, or NULL upon an error.
6039 *
6040 * @HIDE
6041 *
6042 */
6043#if SU_HAVE_INLINE1
6044su_inlinestatic inline
6045#endif
6046sip_priority_t *sip_priority_format(su_home_t *home, char const *fmt, ...)
6047 __attribute__((__malloc__, __format__ (printf, 2, 3)));
6048
6049#if SU_HAVE_INLINE1
6050su_inlinestatic inline sip_priority_t *sip_priority_format(su_home_t *home, char const *fmt, ...)
6051{
6052 sip_header_t *h;
6053 va_list ap;
6054
6055 va_start(ap, fmt)__builtin_va_start(ap, fmt);
6056 h = sip_header_vformat(home, sip_priority_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_priority_class
), (fmt), (ap)))
;
6057 va_end(ap)__builtin_va_end(ap);
6058
6059 return (sip_priority_t *)h;
6060}
6061#endif
6062
6063/** @} */
6064
6065/**@addtogroup sip_call_info
6066 * @{
6067 */
6068
6069/** Parse a SIP @ref sip_call_info "Call-Info header". @internal */
6070SOFIAPUBFUN issize_t sip_call_info_d(su_home_t *, msg_header_t *,
6071 char *s, isize_t slen);
6072
6073/** Print a SIP @ref sip_call_info "Call-Info header". @internal */
6074SOFIAPUBFUN issize_t sip_call_info_e(char b[], isize_t bsiz,
6075 msg_header_t const *h, int flags);
6076
6077/**Access a SIP @ref sip_call_info "Call-Info header"
6078 * structure #sip_call_info_t from #sip_t.
6079 *
6080 */
6081#define sip_call_info(sip)((sip_call_info_t *)msg_header_access((msg_pub_t*)(sip), sip_call_info_class
))
\
6082 ((sip_call_info_t *)msg_header_access((msg_pub_t*)(sip), sip_call_info_class))
6083
6084/**Initializer for structure #sip_call_info_t.
6085 *
6086 * A static #sip_call_info_t structure for
6087 * @ref sip_call_info "Call-Info header" must be initialized with
6088 * the SIP_CALL_INFO_INIT() macro.
6089 * For instance,
6090 * @code
6091 *
6092 * sip_call_info_t sip_call_info = SIP_CALL_INFO_INIT;
6093 *
6094 * @endcode
6095 * @HI
6096 *
6097 */
6098#define SIP_CALL_INFO_INIT(){{{ 0, 0, sip_call_info_class }}} SIP_HDR_INIT(call_info){{{ 0, 0, sip_call_info_class }}}
6099
6100/**Initialize a structure #sip_call_info_t.
6101 *
6102 * An #sip_call_info_t structure for
6103 * @ref sip_call_info "Call-Info header" can be initialized with the
6104 * sip_call_info_init() function/macro. For instance,
6105 * @code
6106 *
6107 * sip_call_info_t sip_call_info;
6108 *
6109 * sip_call_info_init(&sip_call_info);
6110 *
6111 * @endcode
6112 * @HI
6113 *
6114 */
6115#if SU_HAVE_INLINE1
6116su_inlinestatic inline sip_call_info_t *sip_call_info_init(sip_call_info_t x[1])
6117{
6118 return SIP_HEADER_INIT(x, sip_call_info_class, sizeof(sip_call_info_t))((void)memset((x), 0, (sizeof(sip_call_info_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_call_info_class)), (x))
;
6119}
6120#else
6121#define sip_call_info_init(x) \
6122 SIP_HEADER_INIT(x, sip_call_info_class, sizeof(sip_call_info_t))((void)memset((x), 0, (sizeof(sip_call_info_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_call_info_class)), (x))
6123#endif
6124
6125/**Test if header object is instance of #sip_call_info_t.
6126 *
6127 * Check if the header class is an instance of
6128 * @ref sip_call_info "Call-Info header" object and return true (nonzero),
6129 * otherwise return false (zero).
6130 *
6131 * @param header pointer to the header structure to be tested
6132 *
6133 * @retval 1 (true) if the @a header is an instance of header call_info
6134 * @retval 0 (false) otherwise
6135 *
6136 */
6137#if SU_HAVE_INLINE1
6138su_inlinestatic inline int sip_is_call_info(sip_header_t const *header)
6139{
6140 return header && header->sh_classsh_common->h_class->hc_hash == sip_call_info_hash;
6141}
6142#else
6143int sip_is_call_info(sip_header_t const *header);
6144#endif
6145
6146#define sip_call_info_p(h)sip_is_call_info((h)) sip_is_call_info((h))
6147
6148
6149/**Duplicate a list of @ref sip_call_info "Call-Info header" header structures #sip_call_info_t.
6150 *
6151 * Duplicate a header
6152 * structure @a hdr. If the header structure @a hdr
6153 * contains a reference (@c hdr->x_next) to a list of
6154 * headers, all the headers in the list are duplicated, too.
6155 *
6156 * @param home memory home used to allocate new structure
6157 * @param hdr header structure to be duplicated
6158 *
6159 * When duplicating, all parameter lists and non-constant
6160 * strings attached to the header are copied, too. The
6161 * function uses given memory @a home to allocate all the
6162 * memory areas used to copy the header.
6163 *
6164 * @par Example
6165 * @code
6166 *
6167 * call_info = sip_call_info_dup(home, sip->sip_call_info);
6168 *
6169 * @endcode
6170 *
6171 * @return
6172 * A pointer to the
6173 * newly duplicated #sip_call_info_t header structure, or NULL
6174 * upon an error.
6175 *
6176 */
6177#if SU_HAVE_INLINE1
6178su_inlinestatic inline
6179#endif
6180sip_call_info_t *sip_call_info_dup(su_home_t *home, sip_call_info_t const *hdr)
6181 __attribute__((__malloc__));
6182
6183#if SU_HAVE_INLINE1
6184su_inlinestatic inline
6185sip_call_info_t *sip_call_info_dup(su_home_t *home, sip_call_info_t const *hdr)
6186{
6187 return (sip_call_info_t *)
6188 msg_header_dup_as(home, sip_call_info_class, (msg_header_t const *)hdr);
6189}
6190#endif
6191
6192/**Copy a list of @ref sip_call_info "Call-Info header" header structures #sip_call_info_t.
6193 *
6194 * The function sip_call_info_copy() copies a header structure @a
6195 * hdr. If the header structure @a hdr contains a reference (@c
6196 * hdr->h_next) to a list of headers, all the headers in that
6197 * list are copied, too. The function uses given memory @a home
6198 * to allocate all the memory areas used to copy the list of header
6199 * structure @a hdr.
6200 *
6201 * @param home memory home used to allocate new structure
6202 * @param hdr pointer to the header structure to be copied
6203 *
6204 * When copying, only the header structure and parameter lists attached to
6205 * it are duplicated. The new header structure retains all the references to
6206 * the strings within the old @a hdr header, including the encoding of the
6207 * old header, if present.
6208 *
6209 * @par Example
6210 * @code
6211 *
6212 * call_info = sip_call_info_copy(home, sip->sip_call_info);
6213 *
6214 * @endcode
6215 *
6216 * @return
6217 * A pointer to newly copied header structure, or NULL upon an error.
6218 *
6219 */
6220#if SU_HAVE_INLINE1
6221su_inlinestatic inline
6222#endif
6223sip_call_info_t *sip_call_info_copy(su_home_t *home, sip_call_info_t const *hdr)
6224 __attribute__((__malloc__));
6225
6226#if SU_HAVE_INLINE1
6227su_inlinestatic inline
6228sip_call_info_t *sip_call_info_copy(su_home_t *home, sip_call_info_t const *hdr)
6229{
6230 return (sip_call_info_t *)
6231 msg_header_copy_as(home, sip_call_info_class, (msg_header_t const *)hdr);
6232}
6233#endif
6234
6235/**Make a @ref sip_call_info "Call-Info header" structure #sip_call_info_t.
6236 *
6237 * The function sip_call_info_make() makes a new
6238 * #sip_call_info_t header structure. It allocates a new
6239 * header structure, and decodes the string @a s as the
6240 * value of the structure.
6241 *
6242 * @param home memory home used to allocate new header structure.
6243 * @param s string to be decoded as value of the new header structure
6244 *
6245 * @return
6246 * A pointer to newly maked #sip_call_info_t header structure, or NULL upon an
6247 * error.
6248 *
6249 */
6250#if SU_HAVE_INLINE1
6251su_inlinestatic inline
6252#endif
6253sip_call_info_t *sip_call_info_make(su_home_t *home, char const *s)
6254 __attribute__((__malloc__));
6255
6256#if SU_HAVE_INLINE1
6257su_inlinestatic inline sip_call_info_t *sip_call_info_make(su_home_t *home, char const *s)
6258{
6259 return (sip_call_info_t *)sip_header_make(home, sip_call_info_class, s)((sip_header_t *)msg_header_make((home), (sip_call_info_class
), (s)))
;
6260}
6261#endif
6262
6263/**Make a @ref sip_call_info "Call-Info header" from formatting result.
6264 *
6265 * Make a new #sip_call_info_t object using formatting result as its value.
6266 * The function first prints the arguments according to the format @a fmt
6267 * specified. Then it allocates a new header structure, and parses the
6268 * formatting result to the structure #sip_call_info_t.
6269 *
6270 * @param home memory home used to allocate new header structure.
6271 * @param fmt string used as a printf()-style format
6272 * @param ... argument list for format
6273 *
6274 * @return
6275 * A pointer to newly
6276 * makes header structure, or NULL upon an error.
6277 *
6278 * @HIDE
6279 *
6280 */
6281#if SU_HAVE_INLINE1
6282su_inlinestatic inline
6283#endif
6284sip_call_info_t *sip_call_info_format(su_home_t *home, char const *fmt, ...)
6285 __attribute__((__malloc__, __format__ (printf, 2, 3)));
6286
6287#if SU_HAVE_INLINE1
6288su_inlinestatic inline sip_call_info_t *sip_call_info_format(su_home_t *home, char const *fmt, ...)
6289{
6290 sip_header_t *h;
6291 va_list ap;
6292
6293 va_start(ap, fmt)__builtin_va_start(ap, fmt);
6294 h = sip_header_vformat(home, sip_call_info_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_call_info_class
), (fmt), (ap)))
;
6295 va_end(ap)__builtin_va_end(ap);
6296
6297 return (sip_call_info_t *)h;
6298}
6299#endif
6300
6301/** @} */
6302
6303/**@addtogroup sip_organization
6304 * @{
6305 */
6306
6307/** Parse a SIP @ref sip_organization "Organization header". @internal */
6308SOFIAPUBFUN issize_t sip_organization_d(su_home_t *, msg_header_t *,
6309 char *s, isize_t slen);
6310
6311/** Print a SIP @ref sip_organization "Organization header". @internal */
6312SOFIAPUBFUN issize_t sip_organization_e(char b[], isize_t bsiz,
6313 msg_header_t const *h, int flags);
6314
6315/**Access a SIP @ref sip_organization "Organization header"
6316 * structure #sip_organization_t from #sip_t.
6317 *
6318 */
6319#define sip_organization(sip)((sip_organization_t *)msg_header_access((msg_pub_t*)(sip), sip_organization_class
))
\
6320 ((sip_organization_t *)msg_header_access((msg_pub_t*)(sip), sip_organization_class))
6321
6322/**Initializer for structure #sip_organization_t.
6323 *
6324 * A static #sip_organization_t structure for
6325 * @ref sip_organization "Organization header" must be initialized with
6326 * the SIP_ORGANIZATION_INIT() macro.
6327 * For instance,
6328 * @code
6329 *
6330 * sip_organization_t sip_organization = SIP_ORGANIZATION_INIT;
6331 *
6332 * @endcode
6333 * @HI
6334 *
6335 */
6336#define SIP_ORGANIZATION_INIT(){{{ 0, 0, sip_organization_class }}} SIP_HDR_INIT(organization){{{ 0, 0, sip_organization_class }}}
6337
6338/**Initialize a structure #sip_organization_t.
6339 *
6340 * An #sip_organization_t structure for
6341 * @ref sip_organization "Organization header" can be initialized with the
6342 * sip_organization_init() function/macro. For instance,
6343 * @code
6344 *
6345 * sip_organization_t sip_organization;
6346 *
6347 * sip_organization_init(&sip_organization);
6348 *
6349 * @endcode
6350 * @HI
6351 *
6352 */
6353#if SU_HAVE_INLINE1
6354su_inlinestatic inline sip_organization_t *sip_organization_init(sip_organization_t x[1])
6355{
6356 return SIP_HEADER_INIT(x, sip_organization_class, sizeof(sip_organization_t))((void)memset((x), 0, (sizeof(sip_organization_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_organization_class)),
(x))
;
6357}
6358#else
6359#define sip_organization_init(x) \
6360 SIP_HEADER_INIT(x, sip_organization_class, sizeof(sip_organization_t))((void)memset((x), 0, (sizeof(sip_organization_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_organization_class)),
(x))
6361#endif
6362
6363/**Test if header object is instance of #sip_organization_t.
6364 *
6365 * Check if the header class is an instance of
6366 * @ref sip_organization "Organization header" object and return true (nonzero),
6367 * otherwise return false (zero).
6368 *
6369 * @param header pointer to the header structure to be tested
6370 *
6371 * @retval 1 (true) if the @a header is an instance of header organization
6372 * @retval 0 (false) otherwise
6373 *
6374 */
6375#if SU_HAVE_INLINE1
6376su_inlinestatic inline int sip_is_organization(sip_header_t const *header)
6377{
6378 return header && header->sh_classsh_common->h_class->hc_hash == sip_organization_hash;
6379}
6380#else
6381int sip_is_organization(sip_header_t const *header);
6382#endif
6383
6384#define sip_organization_p(h)sip_is_organization((h)) sip_is_organization((h))
6385
6386
6387/**Duplicate a list of @ref sip_organization "Organization header" header structures #sip_organization_t.
6388 *
6389 * Duplicate a header
6390 * structure @a hdr. If the header structure @a hdr
6391 * contains a reference (@c hdr->x_next) to a list of
6392 * headers, all the headers in the list are duplicated, too.
6393 *
6394 * @param home memory home used to allocate new structure
6395 * @param hdr header structure to be duplicated
6396 *
6397 * When duplicating, all parameter lists and non-constant
6398 * strings attached to the header are copied, too. The
6399 * function uses given memory @a home to allocate all the
6400 * memory areas used to copy the header.
6401 *
6402 * @par Example
6403 * @code
6404 *
6405 * organization = sip_organization_dup(home, sip->sip_organization);
6406 *
6407 * @endcode
6408 *
6409 * @return
6410 * A pointer to the
6411 * newly duplicated #sip_organization_t header structure, or NULL
6412 * upon an error.
6413 *
6414 */
6415#if SU_HAVE_INLINE1
6416su_inlinestatic inline
6417#endif
6418sip_organization_t *sip_organization_dup(su_home_t *home, sip_organization_t const *hdr)
6419 __attribute__((__malloc__));
6420
6421#if SU_HAVE_INLINE1
6422su_inlinestatic inline
6423sip_organization_t *sip_organization_dup(su_home_t *home, sip_organization_t const *hdr)
6424{
6425 return (sip_organization_t *)
6426 msg_header_dup_as(home, sip_organization_class, (msg_header_t const *)hdr);
6427}
6428#endif
6429
6430/**Copy a list of @ref sip_organization "Organization header" header structures #sip_organization_t.
6431 *
6432 * The function sip_organization_copy() copies a header structure @a
6433 * hdr. If the header structure @a hdr contains a reference (@c
6434 * hdr->h_next) to a list of headers, all the headers in that
6435 * list are copied, too. The function uses given memory @a home
6436 * to allocate all the memory areas used to copy the list of header
6437 * structure @a hdr.
6438 *
6439 * @param home memory home used to allocate new structure
6440 * @param hdr pointer to the header structure to be copied
6441 *
6442 * When copying, only the header structure and parameter lists attached to
6443 * it are duplicated. The new header structure retains all the references to
6444 * the strings within the old @a hdr header, including the encoding of the
6445 * old header, if present.
6446 *
6447 * @par Example
6448 * @code
6449 *
6450 * organization = sip_organization_copy(home, sip->sip_organization);
6451 *
6452 * @endcode
6453 *
6454 * @return
6455 * A pointer to newly copied header structure, or NULL upon an error.
6456 *
6457 */
6458#if SU_HAVE_INLINE1
6459su_inlinestatic inline
6460#endif
6461sip_organization_t *sip_organization_copy(su_home_t *home, sip_organization_t const *hdr)
6462 __attribute__((__malloc__));
6463
6464#if SU_HAVE_INLINE1
6465su_inlinestatic inline
6466sip_organization_t *sip_organization_copy(su_home_t *home, sip_organization_t const *hdr)
6467{
6468 return (sip_organization_t *)
6469 msg_header_copy_as(home, sip_organization_class, (msg_header_t const *)hdr);
6470}
6471#endif
6472
6473/**Make a @ref sip_organization "Organization header" structure #sip_organization_t.
6474 *
6475 * The function sip_organization_make() makes a new
6476 * #sip_organization_t header structure. It allocates a new
6477 * header structure, and decodes the string @a s as the
6478 * value of the structure.
6479 *
6480 * @param home memory home used to allocate new header structure.
6481 * @param s string to be decoded as value of the new header structure
6482 *
6483 * @return
6484 * A pointer to newly maked #sip_organization_t header structure, or NULL upon an
6485 * error.
6486 *
6487 */
6488#if SU_HAVE_INLINE1
6489su_inlinestatic inline
6490#endif
6491sip_organization_t *sip_organization_make(su_home_t *home, char const *s)
6492 __attribute__((__malloc__));
6493
6494#if SU_HAVE_INLINE1
6495su_inlinestatic inline sip_organization_t *sip_organization_make(su_home_t *home, char const *s)
6496{
6497 return (sip_organization_t *)sip_header_make(home, sip_organization_class, s)((sip_header_t *)msg_header_make((home), (sip_organization_class
), (s)))
;
6498}
6499#endif
6500
6501/**Make a @ref sip_organization "Organization header" from formatting result.
6502 *
6503 * Make a new #sip_organization_t object using formatting result as its value.
6504 * The function first prints the arguments according to the format @a fmt
6505 * specified. Then it allocates a new header structure, and parses the
6506 * formatting result to the structure #sip_organization_t.
6507 *
6508 * @param home memory home used to allocate new header structure.
6509 * @param fmt string used as a printf()-style format
6510 * @param ... argument list for format
6511 *
6512 * @return
6513 * A pointer to newly
6514 * makes header structure, or NULL upon an error.
6515 *
6516 * @HIDE
6517 *
6518 */
6519#if SU_HAVE_INLINE1
6520su_inlinestatic inline
6521#endif
6522sip_organization_t *sip_organization_format(su_home_t *home, char const *fmt, ...)
6523 __attribute__((__malloc__, __format__ (printf, 2, 3)));
6524
6525#if SU_HAVE_INLINE1
6526su_inlinestatic inline sip_organization_t *sip_organization_format(su_home_t *home, char const *fmt, ...)
6527{
6528 sip_header_t *h;
6529 va_list ap;
6530
6531 va_start(ap, fmt)__builtin_va_start(ap, fmt);
6532 h = sip_header_vformat(home, sip_organization_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_organization_class
), (fmt), (ap)))
;
6533 va_end(ap)__builtin_va_end(ap);
6534
6535 return (sip_organization_t *)h;
6536}
6537#endif
6538
6539/** @} */
6540
6541/**@addtogroup sip_server
6542 * @{
6543 */
6544
6545/** Parse a SIP @ref sip_server "Server header". @internal */
6546SOFIAPUBFUN issize_t sip_server_d(su_home_t *, msg_header_t *,
6547 char *s, isize_t slen);
6548
6549/** Print a SIP @ref sip_server "Server header". @internal */
6550SOFIAPUBFUN issize_t sip_server_e(char b[], isize_t bsiz,
6551 msg_header_t const *h, int flags);
6552
6553/**Access a SIP @ref sip_server "Server header"
6554 * structure #sip_server_t from #sip_t.
6555 *
6556 */
6557#define sip_server(sip)((sip_server_t *)msg_header_access((msg_pub_t*)(sip), sip_server_class
))
\
6558 ((sip_server_t *)msg_header_access((msg_pub_t*)(sip), sip_server_class))
6559
6560/**Initializer for structure #sip_server_t.
6561 *
6562 * A static #sip_server_t structure for
6563 * @ref sip_server "Server header" must be initialized with
6564 * the SIP_SERVER_INIT() macro.
6565 * For instance,
6566 * @code
6567 *
6568 * sip_server_t sip_server = SIP_SERVER_INIT;
6569 *
6570 * @endcode
6571 * @HI
6572 *
6573 */
6574#define SIP_SERVER_INIT(){{{ 0, 0, sip_server_class }}} SIP_HDR_INIT(server){{{ 0, 0, sip_server_class }}}
6575
6576/**Initialize a structure #sip_server_t.
6577 *
6578 * An #sip_server_t structure for
6579 * @ref sip_server "Server header" can be initialized with the
6580 * sip_server_init() function/macro. For instance,
6581 * @code
6582 *
6583 * sip_server_t sip_server;
6584 *
6585 * sip_server_init(&sip_server);
6586 *
6587 * @endcode
6588 * @HI
6589 *
6590 */
6591#if SU_HAVE_INLINE1
6592su_inlinestatic inline sip_server_t *sip_server_init(sip_server_t x[1])
6593{
6594 return SIP_HEADER_INIT(x, sip_server_class, sizeof(sip_server_t))((void)memset((x), 0, (sizeof(sip_server_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_server_class)), (x))
;
6595}
6596#else
6597#define sip_server_init(x) \
6598 SIP_HEADER_INIT(x, sip_server_class, sizeof(sip_server_t))((void)memset((x), 0, (sizeof(sip_server_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_server_class)), (x))
6599#endif
6600
6601/**Test if header object is instance of #sip_server_t.
6602 *
6603 * Check if the header class is an instance of
6604 * @ref sip_server "Server header" object and return true (nonzero),
6605 * otherwise return false (zero).
6606 *
6607 * @param header pointer to the header structure to be tested
6608 *
6609 * @retval 1 (true) if the @a header is an instance of header server
6610 * @retval 0 (false) otherwise
6611 *
6612 */
6613#if SU_HAVE_INLINE1
6614su_inlinestatic inline int sip_is_server(sip_header_t const *header)
6615{
6616 return header && header->sh_classsh_common->h_class->hc_hash == sip_server_hash;
6617}
6618#else
6619int sip_is_server(sip_header_t const *header);
6620#endif
6621
6622#define sip_server_p(h)sip_is_server((h)) sip_is_server((h))
6623
6624
6625/**Duplicate a list of @ref sip_server "Server header" header structures #sip_server_t.
6626 *
6627 * Duplicate a header
6628 * structure @a hdr. If the header structure @a hdr
6629 * contains a reference (@c hdr->x_next) to a list of
6630 * headers, all the headers in the list are duplicated, too.
6631 *
6632 * @param home memory home used to allocate new structure
6633 * @param hdr header structure to be duplicated
6634 *
6635 * When duplicating, all parameter lists and non-constant
6636 * strings attached to the header are copied, too. The
6637 * function uses given memory @a home to allocate all the
6638 * memory areas used to copy the header.
6639 *
6640 * @par Example
6641 * @code
6642 *
6643 * server = sip_server_dup(home, sip->sip_server);
6644 *
6645 * @endcode
6646 *
6647 * @return
6648 * A pointer to the
6649 * newly duplicated #sip_server_t header structure, or NULL
6650 * upon an error.
6651 *
6652 */
6653#if SU_HAVE_INLINE1
6654su_inlinestatic inline
6655#endif
6656sip_server_t *sip_server_dup(su_home_t *home, sip_server_t const *hdr)
6657 __attribute__((__malloc__));
6658
6659#if SU_HAVE_INLINE1
6660su_inlinestatic inline
6661sip_server_t *sip_server_dup(su_home_t *home, sip_server_t const *hdr)
6662{
6663 return (sip_server_t *)
6664 msg_header_dup_as(home, sip_server_class, (msg_header_t const *)hdr);
6665}
6666#endif
6667
6668/**Copy a list of @ref sip_server "Server header" header structures #sip_server_t.
6669 *
6670 * The function sip_server_copy() copies a header structure @a
6671 * hdr. If the header structure @a hdr contains a reference (@c
6672 * hdr->h_next) to a list of headers, all the headers in that
6673 * list are copied, too. The function uses given memory @a home
6674 * to allocate all the memory areas used to copy the list of header
6675 * structure @a hdr.
6676 *
6677 * @param home memory home used to allocate new structure
6678 * @param hdr pointer to the header structure to be copied
6679 *
6680 * When copying, only the header structure and parameter lists attached to
6681 * it are duplicated. The new header structure retains all the references to
6682 * the strings within the old @a hdr header, including the encoding of the
6683 * old header, if present.
6684 *
6685 * @par Example
6686 * @code
6687 *
6688 * server = sip_server_copy(home, sip->sip_server);
6689 *
6690 * @endcode
6691 *
6692 * @return
6693 * A pointer to newly copied header structure, or NULL upon an error.
6694 *
6695 */
6696#if SU_HAVE_INLINE1
6697su_inlinestatic inline
6698#endif
6699sip_server_t *sip_server_copy(su_home_t *home, sip_server_t const *hdr)
6700 __attribute__((__malloc__));
6701
6702#if SU_HAVE_INLINE1
6703su_inlinestatic inline
6704sip_server_t *sip_server_copy(su_home_t *home, sip_server_t const *hdr)
6705{
6706 return (sip_server_t *)
6707 msg_header_copy_as(home, sip_server_class, (msg_header_t const *)hdr);
6708}
6709#endif
6710
6711/**Make a @ref sip_server "Server header" structure #sip_server_t.
6712 *
6713 * The function sip_server_make() makes a new
6714 * #sip_server_t header structure. It allocates a new
6715 * header structure, and decodes the string @a s as the
6716 * value of the structure.
6717 *
6718 * @param home memory home used to allocate new header structure.
6719 * @param s string to be decoded as value of the new header structure
6720 *
6721 * @return
6722 * A pointer to newly maked #sip_server_t header structure, or NULL upon an
6723 * error.
6724 *
6725 */
6726#if SU_HAVE_INLINE1
6727su_inlinestatic inline
6728#endif
6729sip_server_t *sip_server_make(su_home_t *home, char const *s)
6730 __attribute__((__malloc__));
6731
6732#if SU_HAVE_INLINE1
6733su_inlinestatic inline sip_server_t *sip_server_make(su_home_t *home, char const *s)
6734{
6735 return (sip_server_t *)sip_header_make(home, sip_server_class, s)((sip_header_t *)msg_header_make((home), (sip_server_class), (
s)))
;
6736}
6737#endif
6738
6739/**Make a @ref sip_server "Server header" from formatting result.
6740 *
6741 * Make a new #sip_server_t object using formatting result as its value.
6742 * The function first prints the arguments according to the format @a fmt
6743 * specified. Then it allocates a new header structure, and parses the
6744 * formatting result to the structure #sip_server_t.
6745 *
6746 * @param home memory home used to allocate new header structure.
6747 * @param fmt string used as a printf()-style format
6748 * @param ... argument list for format
6749 *
6750 * @return
6751 * A pointer to newly
6752 * makes header structure, or NULL upon an error.
6753 *
6754 * @HIDE
6755 *
6756 */
6757#if SU_HAVE_INLINE1
6758su_inlinestatic inline
6759#endif
6760sip_server_t *sip_server_format(su_home_t *home, char const *fmt, ...)
6761 __attribute__((__malloc__, __format__ (printf, 2, 3)));
6762
6763#if SU_HAVE_INLINE1
6764su_inlinestatic inline sip_server_t *sip_server_format(su_home_t *home, char const *fmt, ...)
6765{
6766 sip_header_t *h;
6767 va_list ap;
6768
6769 va_start(ap, fmt)__builtin_va_start(ap, fmt);
6770 h = sip_header_vformat(home, sip_server_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_server_class
), (fmt), (ap)))
;
6771 va_end(ap)__builtin_va_end(ap);
6772
6773 return (sip_server_t *)h;
6774}
6775#endif
6776
6777/** @} */
6778
6779/**@addtogroup sip_user_agent
6780 * @{
6781 */
6782
6783/** Parse a SIP @ref sip_user_agent "User-Agent header". @internal */
6784SOFIAPUBFUN issize_t sip_user_agent_d(su_home_t *, msg_header_t *,
6785 char *s, isize_t slen);
6786
6787/** Print a SIP @ref sip_user_agent "User-Agent header". @internal */
6788SOFIAPUBFUN issize_t sip_user_agent_e(char b[], isize_t bsiz,
6789 msg_header_t const *h, int flags);
6790
6791/**Access a SIP @ref sip_user_agent "User-Agent header"
6792 * structure #sip_user_agent_t from #sip_t.
6793 *
6794 */
6795#define sip_user_agent(sip)((sip_user_agent_t *)msg_header_access((msg_pub_t*)(sip), sip_user_agent_class
))
\
6796 ((sip_user_agent_t *)msg_header_access((msg_pub_t*)(sip), sip_user_agent_class))
6797
6798/**Initializer for structure #sip_user_agent_t.
6799 *
6800 * A static #sip_user_agent_t structure for
6801 * @ref sip_user_agent "User-Agent header" must be initialized with
6802 * the SIP_USER_AGENT_INIT() macro.
6803 * For instance,
6804 * @code
6805 *
6806 * sip_user_agent_t sip_user_agent = SIP_USER_AGENT_INIT;
6807 *
6808 * @endcode
6809 * @HI
6810 *
6811 */
6812#define SIP_USER_AGENT_INIT(){{{ 0, 0, sip_user_agent_class }}} SIP_HDR_INIT(user_agent){{{ 0, 0, sip_user_agent_class }}}
6813
6814/**Initialize a structure #sip_user_agent_t.
6815 *
6816 * An #sip_user_agent_t structure for
6817 * @ref sip_user_agent "User-Agent header" can be initialized with the
6818 * sip_user_agent_init() function/macro. For instance,
6819 * @code
6820 *
6821 * sip_user_agent_t sip_user_agent;
6822 *
6823 * sip_user_agent_init(&sip_user_agent);
6824 *
6825 * @endcode
6826 * @HI
6827 *
6828 */
6829#if SU_HAVE_INLINE1
6830su_inlinestatic inline sip_user_agent_t *sip_user_agent_init(sip_user_agent_t x[1])
6831{
6832 return SIP_HEADER_INIT(x, sip_user_agent_class, sizeof(sip_user_agent_t))((void)memset((x), 0, (sizeof(sip_user_agent_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_user_agent_class)), (x))
;
6833}
6834#else
6835#define sip_user_agent_init(x) \
6836 SIP_HEADER_INIT(x, sip_user_agent_class, sizeof(sip_user_agent_t))((void)memset((x), 0, (sizeof(sip_user_agent_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_user_agent_class)), (x))
6837#endif
6838
6839/**Test if header object is instance of #sip_user_agent_t.
6840 *
6841 * Check if the header class is an instance of
6842 * @ref sip_user_agent "User-Agent header" object and return true (nonzero),
6843 * otherwise return false (zero).
6844 *
6845 * @param header pointer to the header structure to be tested
6846 *
6847 * @retval 1 (true) if the @a header is an instance of header user_agent
6848 * @retval 0 (false) otherwise
6849 *
6850 */
6851#if SU_HAVE_INLINE1
6852su_inlinestatic inline int sip_is_user_agent(sip_header_t const *header)
6853{
6854 return header && header->sh_classsh_common->h_class->hc_hash == sip_user_agent_hash;
6855}
6856#else
6857int sip_is_user_agent(sip_header_t const *header);
6858#endif
6859
6860#define sip_user_agent_p(h)sip_is_user_agent((h)) sip_is_user_agent((h))
6861
6862
6863/**Duplicate a list of @ref sip_user_agent "User-Agent header" header structures #sip_user_agent_t.
6864 *
6865 * Duplicate a header
6866 * structure @a hdr. If the header structure @a hdr
6867 * contains a reference (@c hdr->x_next) to a list of
6868 * headers, all the headers in the list are duplicated, too.
6869 *
6870 * @param home memory home used to allocate new structure
6871 * @param hdr header structure to be duplicated
6872 *
6873 * When duplicating, all parameter lists and non-constant
6874 * strings attached to the header are copied, too. The
6875 * function uses given memory @a home to allocate all the
6876 * memory areas used to copy the header.
6877 *
6878 * @par Example
6879 * @code
6880 *
6881 * user_agent = sip_user_agent_dup(home, sip->sip_user_agent);
6882 *
6883 * @endcode
6884 *
6885 * @return
6886 * A pointer to the
6887 * newly duplicated #sip_user_agent_t header structure, or NULL
6888 * upon an error.
6889 *
6890 */
6891#if SU_HAVE_INLINE1
6892su_inlinestatic inline
6893#endif
6894sip_user_agent_t *sip_user_agent_dup(su_home_t *home, sip_user_agent_t const *hdr)
6895 __attribute__((__malloc__));
6896
6897#if SU_HAVE_INLINE1
6898su_inlinestatic inline
6899sip_user_agent_t *sip_user_agent_dup(su_home_t *home, sip_user_agent_t const *hdr)
6900{
6901 return (sip_user_agent_t *)
6902 msg_header_dup_as(home, sip_user_agent_class, (msg_header_t const *)hdr);
6903}
6904#endif
6905
6906/**Copy a list of @ref sip_user_agent "User-Agent header" header structures #sip_user_agent_t.
6907 *
6908 * The function sip_user_agent_copy() copies a header structure @a
6909 * hdr. If the header structure @a hdr contains a reference (@c
6910 * hdr->h_next) to a list of headers, all the headers in that
6911 * list are copied, too. The function uses given memory @a home
6912 * to allocate all the memory areas used to copy the list of header
6913 * structure @a hdr.
6914 *
6915 * @param home memory home used to allocate new structure
6916 * @param hdr pointer to the header structure to be copied
6917 *
6918 * When copying, only the header structure and parameter lists attached to
6919 * it are duplicated. The new header structure retains all the references to
6920 * the strings within the old @a hdr header, including the encoding of the
6921 * old header, if present.
6922 *
6923 * @par Example
6924 * @code
6925 *
6926 * user_agent = sip_user_agent_copy(home, sip->sip_user_agent);
6927 *
6928 * @endcode
6929 *
6930 * @return
6931 * A pointer to newly copied header structure, or NULL upon an error.
6932 *
6933 */
6934#if SU_HAVE_INLINE1
6935su_inlinestatic inline
6936#endif
6937sip_user_agent_t *sip_user_agent_copy(su_home_t *home, sip_user_agent_t const *hdr)
6938 __attribute__((__malloc__));
6939
6940#if SU_HAVE_INLINE1
6941su_inlinestatic inline
6942sip_user_agent_t *sip_user_agent_copy(su_home_t *home, sip_user_agent_t const *hdr)
6943{
6944 return (sip_user_agent_t *)
6945 msg_header_copy_as(home, sip_user_agent_class, (msg_header_t const *)hdr);
6946}
6947#endif
6948
6949/**Make a @ref sip_user_agent "User-Agent header" structure #sip_user_agent_t.
6950 *
6951 * The function sip_user_agent_make() makes a new
6952 * #sip_user_agent_t header structure. It allocates a new
6953 * header structure, and decodes the string @a s as the
6954 * value of the structure.
6955 *
6956 * @param home memory home used to allocate new header structure.
6957 * @param s string to be decoded as value of the new header structure
6958 *
6959 * @return
6960 * A pointer to newly maked #sip_user_agent_t header structure, or NULL upon an
6961 * error.
6962 *
6963 */
6964#if SU_HAVE_INLINE1
6965su_inlinestatic inline
6966#endif
6967sip_user_agent_t *sip_user_agent_make(su_home_t *home, char const *s)
6968 __attribute__((__malloc__));
6969
6970#if SU_HAVE_INLINE1
6971su_inlinestatic inline sip_user_agent_t *sip_user_agent_make(su_home_t *home, char const *s)
6972{
6973 return (sip_user_agent_t *)sip_header_make(home, sip_user_agent_class, s)((sip_header_t *)msg_header_make((home), (sip_user_agent_class
), (s)))
;
6974}
6975#endif
6976
6977/**Make a @ref sip_user_agent "User-Agent header" from formatting result.
6978 *
6979 * Make a new #sip_user_agent_t object using formatting result as its value.
6980 * The function first prints the arguments according to the format @a fmt
6981 * specified. Then it allocates a new header structure, and parses the
6982 * formatting result to the structure #sip_user_agent_t.
6983 *
6984 * @param home memory home used to allocate new header structure.
6985 * @param fmt string used as a printf()-style format
6986 * @param ... argument list for format
6987 *
6988 * @return
6989 * A pointer to newly
6990 * makes header structure, or NULL upon an error.
6991 *
6992 * @HIDE
6993 *
6994 */
6995#if SU_HAVE_INLINE1
6996su_inlinestatic inline
6997#endif
6998sip_user_agent_t *sip_user_agent_format(su_home_t *home, char const *fmt, ...)
6999 __attribute__((__malloc__, __format__ (printf, 2, 3)));
7000
7001#if SU_HAVE_INLINE1
7002su_inlinestatic inline sip_user_agent_t *sip_user_agent_format(su_home_t *home, char const *fmt, ...)
7003{
7004 sip_header_t *h;
7005 va_list ap;
7006
7007 va_start(ap, fmt)__builtin_va_start(ap, fmt);
7008 h = sip_header_vformat(home, sip_user_agent_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_user_agent_class
), (fmt), (ap)))
;
7009 va_end(ap)__builtin_va_end(ap);
7010
7011 return (sip_user_agent_t *)h;
7012}
7013#endif
7014
7015/** @} */
7016
7017/**@addtogroup sip_in_reply_to
7018 * @{
7019 */
7020
7021/** Parse a SIP @ref sip_in_reply_to "In-Reply-To header". @internal */
7022SOFIAPUBFUN issize_t sip_in_reply_to_d(su_home_t *, msg_header_t *,
7023 char *s, isize_t slen);
7024
7025/** Print a SIP @ref sip_in_reply_to "In-Reply-To header". @internal */
7026SOFIAPUBFUN issize_t sip_in_reply_to_e(char b[], isize_t bsiz,
7027 msg_header_t const *h, int flags);
7028
7029/**Access a SIP @ref sip_in_reply_to "In-Reply-To header"
7030 * structure #sip_in_reply_to_t from #sip_t.
7031 *
7032 */
7033#define sip_in_reply_to(sip)((sip_in_reply_to_t *)msg_header_access((msg_pub_t*)(sip), sip_in_reply_to_class
))
\
7034 ((sip_in_reply_to_t *)msg_header_access((msg_pub_t*)(sip), sip_in_reply_to_class))
7035
7036/**Initializer for structure #sip_in_reply_to_t.
7037 *
7038 * A static #sip_in_reply_to_t structure for
7039 * @ref sip_in_reply_to "In-Reply-To header" must be initialized with
7040 * the SIP_IN_REPLY_TO_INIT() macro.
7041 * For instance,
7042 * @code
7043 *
7044 * sip_in_reply_to_t sip_in_reply_to = SIP_IN_REPLY_TO_INIT;
7045 *
7046 * @endcode
7047 * @HI
7048 *
7049 */
7050#define SIP_IN_REPLY_TO_INIT(){{{ 0, 0, sip_in_reply_to_class }}} SIP_HDR_INIT(in_reply_to){{{ 0, 0, sip_in_reply_to_class }}}
7051
7052/**Initialize a structure #sip_in_reply_to_t.
7053 *
7054 * An #sip_in_reply_to_t structure for
7055 * @ref sip_in_reply_to "In-Reply-To header" can be initialized with the
7056 * sip_in_reply_to_init() function/macro. For instance,
7057 * @code
7058 *
7059 * sip_in_reply_to_t sip_in_reply_to;
7060 *
7061 * sip_in_reply_to_init(&sip_in_reply_to);
7062 *
7063 * @endcode
7064 * @HI
7065 *
7066 */
7067#if SU_HAVE_INLINE1
7068su_inlinestatic inline sip_in_reply_to_t *sip_in_reply_to_init(sip_in_reply_to_t x[1])
7069{
7070 return SIP_HEADER_INIT(x, sip_in_reply_to_class, sizeof(sip_in_reply_to_t))((void)memset((x), 0, (sizeof(sip_in_reply_to_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_in_reply_to_class)), (
x))
;
7071}
7072#else
7073#define sip_in_reply_to_init(x) \
7074 SIP_HEADER_INIT(x, sip_in_reply_to_class, sizeof(sip_in_reply_to_t))((void)memset((x), 0, (sizeof(sip_in_reply_to_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_in_reply_to_class)), (
x))
7075#endif
7076
7077/**Test if header object is instance of #sip_in_reply_to_t.
7078 *
7079 * Check if the header class is an instance of
7080 * @ref sip_in_reply_to "In-Reply-To header" object and return true (nonzero),
7081 * otherwise return false (zero).
7082 *
7083 * @param header pointer to the header structure to be tested
7084 *
7085 * @retval 1 (true) if the @a header is an instance of header in_reply_to
7086 * @retval 0 (false) otherwise
7087 *
7088 */
7089#if SU_HAVE_INLINE1
7090su_inlinestatic inline int sip_is_in_reply_to(sip_header_t const *header)
7091{
7092 return header && header->sh_classsh_common->h_class->hc_hash == sip_in_reply_to_hash;
7093}
7094#else
7095int sip_is_in_reply_to(sip_header_t const *header);
7096#endif
7097
7098#define sip_in_reply_to_p(h)sip_is_in_reply_to((h)) sip_is_in_reply_to((h))
7099
7100
7101/**Duplicate a list of @ref sip_in_reply_to "In-Reply-To header" header structures #sip_in_reply_to_t.
7102 *
7103 * Duplicate a header
7104 * structure @a hdr. If the header structure @a hdr
7105 * contains a reference (@c hdr->x_next) to a list of
7106 * headers, all the headers in the list are duplicated, too.
7107 *
7108 * @param home memory home used to allocate new structure
7109 * @param hdr header structure to be duplicated
7110 *
7111 * When duplicating, all parameter lists and non-constant
7112 * strings attached to the header are copied, too. The
7113 * function uses given memory @a home to allocate all the
7114 * memory areas used to copy the header.
7115 *
7116 * @par Example
7117 * @code
7118 *
7119 * in_reply_to = sip_in_reply_to_dup(home, sip->sip_in_reply_to);
7120 *
7121 * @endcode
7122 *
7123 * @return
7124 * A pointer to the
7125 * newly duplicated #sip_in_reply_to_t header structure, or NULL
7126 * upon an error.
7127 *
7128 */
7129#if SU_HAVE_INLINE1
7130su_inlinestatic inline
7131#endif
7132sip_in_reply_to_t *sip_in_reply_to_dup(su_home_t *home, sip_in_reply_to_t const *hdr)
7133 __attribute__((__malloc__));
7134
7135#if SU_HAVE_INLINE1
7136su_inlinestatic inline
7137sip_in_reply_to_t *sip_in_reply_to_dup(su_home_t *home, sip_in_reply_to_t const *hdr)
7138{
7139 return (sip_in_reply_to_t *)
7140 msg_header_dup_as(home, sip_in_reply_to_class, (msg_header_t const *)hdr);
7141}
7142#endif
7143
7144/**Copy a list of @ref sip_in_reply_to "In-Reply-To header" header structures #sip_in_reply_to_t.
7145 *
7146 * The function sip_in_reply_to_copy() copies a header structure @a
7147 * hdr. If the header structure @a hdr contains a reference (@c
7148 * hdr->h_next) to a list of headers, all the headers in that
7149 * list are copied, too. The function uses given memory @a home
7150 * to allocate all the memory areas used to copy the list of header
7151 * structure @a hdr.
7152 *
7153 * @param home memory home used to allocate new structure
7154 * @param hdr pointer to the header structure to be copied
7155 *
7156 * When copying, only the header structure and parameter lists attached to
7157 * it are duplicated. The new header structure retains all the references to
7158 * the strings within the old @a hdr header, including the encoding of the
7159 * old header, if present.
7160 *
7161 * @par Example
7162 * @code
7163 *
7164 * in_reply_to = sip_in_reply_to_copy(home, sip->sip_in_reply_to);
7165 *
7166 * @endcode
7167 *
7168 * @return
7169 * A pointer to newly copied header structure, or NULL upon an error.
7170 *
7171 */
7172#if SU_HAVE_INLINE1
7173su_inlinestatic inline
7174#endif
7175sip_in_reply_to_t *sip_in_reply_to_copy(su_home_t *home, sip_in_reply_to_t const *hdr)
7176 __attribute__((__malloc__));
7177
7178#if SU_HAVE_INLINE1
7179su_inlinestatic inline
7180sip_in_reply_to_t *sip_in_reply_to_copy(su_home_t *home, sip_in_reply_to_t const *hdr)
7181{
7182 return (sip_in_reply_to_t *)
7183 msg_header_copy_as(home, sip_in_reply_to_class, (msg_header_t const *)hdr);
7184}
7185#endif
7186
7187/**Make a @ref sip_in_reply_to "In-Reply-To header" structure #sip_in_reply_to_t.
7188 *
7189 * The function sip_in_reply_to_make() makes a new
7190 * #sip_in_reply_to_t header structure. It allocates a new
7191 * header structure, and decodes the string @a s as the
7192 * value of the structure.
7193 *
7194 * @param home memory home used to allocate new header structure.
7195 * @param s string to be decoded as value of the new header structure
7196 *
7197 * @return
7198 * A pointer to newly maked #sip_in_reply_to_t header structure, or NULL upon an
7199 * error.
7200 *
7201 */
7202#if SU_HAVE_INLINE1
7203su_inlinestatic inline
7204#endif
7205sip_in_reply_to_t *sip_in_reply_to_make(su_home_t *home, char const *s)
7206 __attribute__((__malloc__));
7207
7208#if SU_HAVE_INLINE1
7209su_inlinestatic inline sip_in_reply_to_t *sip_in_reply_to_make(su_home_t *home, char const *s)
7210{
7211 return (sip_in_reply_to_t *)sip_header_make(home, sip_in_reply_to_class, s)((sip_header_t *)msg_header_make((home), (sip_in_reply_to_class
), (s)))
;
7212}
7213#endif
7214
7215/**Make a @ref sip_in_reply_to "In-Reply-To header" from formatting result.
7216 *
7217 * Make a new #sip_in_reply_to_t object using formatting result as its value.
7218 * The function first prints the arguments according to the format @a fmt
7219 * specified. Then it allocates a new header structure, and parses the
7220 * formatting result to the structure #sip_in_reply_to_t.
7221 *
7222 * @param home memory home used to allocate new header structure.
7223 * @param fmt string used as a printf()-style format
7224 * @param ... argument list for format
7225 *
7226 * @return
7227 * A pointer to newly
7228 * makes header structure, or NULL upon an error.
7229 *
7230 * @HIDE
7231 *
7232 */
7233#if SU_HAVE_INLINE1
7234su_inlinestatic inline
7235#endif
7236sip_in_reply_to_t *sip_in_reply_to_format(su_home_t *home, char const *fmt, ...)
7237 __attribute__((__malloc__, __format__ (printf, 2, 3)));
7238
7239#if SU_HAVE_INLINE1
7240su_inlinestatic inline sip_in_reply_to_t *sip_in_reply_to_format(su_home_t *home, char const *fmt, ...)
7241{
7242 sip_header_t *h;
7243 va_list ap;
7244
7245 va_start(ap, fmt)__builtin_va_start(ap, fmt);
7246 h = sip_header_vformat(home, sip_in_reply_to_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_in_reply_to_class
), (fmt), (ap)))
;
7247 va_end(ap)__builtin_va_end(ap);
7248
7249 return (sip_in_reply_to_t *)h;
7250}
7251#endif
7252
7253/** @} */
7254
7255/**@addtogroup sip_accept
7256 * @{
7257 */
7258
7259/** Parse a SIP @ref sip_accept "Accept header". @internal */
7260SOFIAPUBFUN issize_t sip_accept_d(su_home_t *, msg_header_t *,
7261 char *s, isize_t slen);
7262
7263/** Print a SIP @ref sip_accept "Accept header". @internal */
7264SOFIAPUBFUN issize_t sip_accept_e(char b[], isize_t bsiz,
7265 msg_header_t const *h, int flags);
7266
7267/**Access a SIP @ref sip_accept "Accept header"
7268 * structure #sip_accept_t from #sip_t.
7269 *
7270 */
7271#define sip_accept(sip)((sip_accept_t *)msg_header_access((msg_pub_t*)(sip), sip_accept_class
))
\
7272 ((sip_accept_t *)msg_header_access((msg_pub_t*)(sip), sip_accept_class))
7273
7274/**Initializer for structure #sip_accept_t.
7275 *
7276 * A static #sip_accept_t structure for
7277 * @ref sip_accept "Accept header" must be initialized with
7278 * the SIP_ACCEPT_INIT() macro.
7279 * For instance,
7280 * @code
7281 *
7282 * sip_accept_t sip_accept = SIP_ACCEPT_INIT;
7283 *
7284 * @endcode
7285 * @HI
7286 *
7287 */
7288#define SIP_ACCEPT_INIT(){{{ 0, 0, sip_accept_class }}} SIP_HDR_INIT(accept){{{ 0, 0, sip_accept_class }}}
7289
7290/**Initialize a structure #sip_accept_t.
7291 *
7292 * An #sip_accept_t structure for
7293 * @ref sip_accept "Accept header" can be initialized with the
7294 * sip_accept_init() function/macro. For instance,
7295 * @code
7296 *
7297 * sip_accept_t sip_accept;
7298 *
7299 * sip_accept_init(&sip_accept);
7300 *
7301 * @endcode
7302 * @HI
7303 *
7304 */
7305#if SU_HAVE_INLINE1
7306su_inlinestatic inline sip_accept_t *sip_accept_init(sip_accept_t x[1])
7307{
7308 return SIP_HEADER_INIT(x, sip_accept_class, sizeof(sip_accept_t))((void)memset((x), 0, (sizeof(sip_accept_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_accept_class)), (x))
;
7309}
7310#else
7311#define sip_accept_init(x) \
7312 SIP_HEADER_INIT(x, sip_accept_class, sizeof(sip_accept_t))((void)memset((x), 0, (sizeof(sip_accept_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_accept_class)), (x))
7313#endif
7314
7315/**Test if header object is instance of #sip_accept_t.
7316 *
7317 * Check if the header class is an instance of
7318 * @ref sip_accept "Accept header" object and return true (nonzero),
7319 * otherwise return false (zero).
7320 *
7321 * @param header pointer to the header structure to be tested
7322 *
7323 * @retval 1 (true) if the @a header is an instance of header accept
7324 * @retval 0 (false) otherwise
7325 *
7326 */
7327#if SU_HAVE_INLINE1
7328su_inlinestatic inline int sip_is_accept(sip_header_t const *header)
7329{
7330 return header && header->sh_classsh_common->h_class->hc_hash == sip_accept_hash;
7331}
7332#else
7333int sip_is_accept(sip_header_t const *header);
7334#endif
7335
7336#define sip_accept_p(h)sip_is_accept((h)) sip_is_accept((h))
7337
7338
7339/**Duplicate a list of @ref sip_accept "Accept header" header structures #sip_accept_t.
7340 *
7341 * Duplicate a header
7342 * structure @a hdr. If the header structure @a hdr
7343 * contains a reference (@c hdr->x_next) to a list of
7344 * headers, all the headers in the list are duplicated, too.
7345 *
7346 * @param home memory home used to allocate new structure
7347 * @param hdr header structure to be duplicated
7348 *
7349 * When duplicating, all parameter lists and non-constant
7350 * strings attached to the header are copied, too. The
7351 * function uses given memory @a home to allocate all the
7352 * memory areas used to copy the header.
7353 *
7354 * @par Example
7355 * @code
7356 *
7357 * accept = sip_accept_dup(home, sip->sip_accept);
7358 *
7359 * @endcode
7360 *
7361 * @return
7362 * A pointer to the
7363 * newly duplicated #sip_accept_t header structure, or NULL
7364 * upon an error.
7365 *
7366 */
7367#if SU_HAVE_INLINE1
7368su_inlinestatic inline
7369#endif
7370sip_accept_t *sip_accept_dup(su_home_t *home, sip_accept_t const *hdr)
7371 __attribute__((__malloc__));
7372
7373#if SU_HAVE_INLINE1
7374su_inlinestatic inline
7375sip_accept_t *sip_accept_dup(su_home_t *home, sip_accept_t const *hdr)
7376{
7377 return (sip_accept_t *)
7378 msg_header_dup_as(home, sip_accept_class, (msg_header_t const *)hdr);
7379}
7380#endif
7381
7382/**Copy a list of @ref sip_accept "Accept header" header structures #sip_accept_t.
7383 *
7384 * The function sip_accept_copy() copies a header structure @a
7385 * hdr. If the header structure @a hdr contains a reference (@c
7386 * hdr->h_next) to a list of headers, all the headers in that
7387 * list are copied, too. The function uses given memory @a home
7388 * to allocate all the memory areas used to copy the list of header
7389 * structure @a hdr.
7390 *
7391 * @param home memory home used to allocate new structure
7392 * @param hdr pointer to the header structure to be copied
7393 *
7394 * When copying, only the header structure and parameter lists attached to
7395 * it are duplicated. The new header structure retains all the references to
7396 * the strings within the old @a hdr header, including the encoding of the
7397 * old header, if present.
7398 *
7399 * @par Example
7400 * @code
7401 *
7402 * accept = sip_accept_copy(home, sip->sip_accept);
7403 *
7404 * @endcode
7405 *
7406 * @return
7407 * A pointer to newly copied header structure, or NULL upon an error.
7408 *
7409 */
7410#if SU_HAVE_INLINE1
7411su_inlinestatic inline
7412#endif
7413sip_accept_t *sip_accept_copy(su_home_t *home, sip_accept_t const *hdr)
7414 __attribute__((__malloc__));
7415
7416#if SU_HAVE_INLINE1
7417su_inlinestatic inline
7418sip_accept_t *sip_accept_copy(su_home_t *home, sip_accept_t const *hdr)
7419{
7420 return (sip_accept_t *)
7421 msg_header_copy_as(home, sip_accept_class, (msg_header_t const *)hdr);
7422}
7423#endif
7424
7425/**Make a @ref sip_accept "Accept header" structure #sip_accept_t.
7426 *
7427 * The function sip_accept_make() makes a new
7428 * #sip_accept_t header structure. It allocates a new
7429 * header structure, and decodes the string @a s as the
7430 * value of the structure.
7431 *
7432 * @param home memory home used to allocate new header structure.
7433 * @param s string to be decoded as value of the new header structure
7434 *
7435 * @return
7436 * A pointer to newly maked #sip_accept_t header structure, or NULL upon an
7437 * error.
7438 *
7439 */
7440#if SU_HAVE_INLINE1
7441su_inlinestatic inline
7442#endif
7443sip_accept_t *sip_accept_make(su_home_t *home, char const *s)
7444 __attribute__((__malloc__));
7445
7446#if SU_HAVE_INLINE1
7447su_inlinestatic inline sip_accept_t *sip_accept_make(su_home_t *home, char const *s)
7448{
7449 return (sip_accept_t *)sip_header_make(home, sip_accept_class, s)((sip_header_t *)msg_header_make((home), (sip_accept_class), (
s)))
;
7450}
7451#endif
7452
7453/**Make a @ref sip_accept "Accept header" from formatting result.
7454 *
7455 * Make a new #sip_accept_t object using formatting result as its value.
7456 * The function first prints the arguments according to the format @a fmt
7457 * specified. Then it allocates a new header structure, and parses the
7458 * formatting result to the structure #sip_accept_t.
7459 *
7460 * @param home memory home used to allocate new header structure.
7461 * @param fmt string used as a printf()-style format
7462 * @param ... argument list for format
7463 *
7464 * @return
7465 * A pointer to newly
7466 * makes header structure, or NULL upon an error.
7467 *
7468 * @HIDE
7469 *
7470 */
7471#if SU_HAVE_INLINE1
7472su_inlinestatic inline
7473#endif
7474sip_accept_t *sip_accept_format(su_home_t *home, char const *fmt, ...)
7475 __attribute__((__malloc__, __format__ (printf, 2, 3)));
7476
7477#if SU_HAVE_INLINE1
7478su_inlinestatic inline sip_accept_t *sip_accept_format(su_home_t *home, char const *fmt, ...)
7479{
7480 sip_header_t *h;
7481 va_list ap;
7482
7483 va_start(ap, fmt)__builtin_va_start(ap, fmt);
7484 h = sip_header_vformat(home, sip_accept_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_accept_class
), (fmt), (ap)))
;
7485 va_end(ap)__builtin_va_end(ap);
7486
7487 return (sip_accept_t *)h;
7488}
7489#endif
7490
7491/** @} */
7492
7493/**@addtogroup sip_accept_encoding
7494 * @{
7495 */
7496
7497/** Parse a SIP @ref sip_accept_encoding "Accept-Encoding header". @internal */
7498SOFIAPUBFUN issize_t sip_accept_encoding_d(su_home_t *, msg_header_t *,
7499 char *s, isize_t slen);
7500
7501/** Print a SIP @ref sip_accept_encoding "Accept-Encoding header". @internal */
7502SOFIAPUBFUN issize_t sip_accept_encoding_e(char b[], isize_t bsiz,
7503 msg_header_t const *h, int flags);
7504
7505/**Access a SIP @ref sip_accept_encoding "Accept-Encoding header"
7506 * structure #sip_accept_encoding_t from #sip_t.
7507 *
7508 */
7509#define sip_accept_encoding(sip)((sip_accept_encoding_t *)msg_header_access((msg_pub_t*)(sip)
, sip_accept_encoding_class))
\
7510 ((sip_accept_encoding_t *)msg_header_access((msg_pub_t*)(sip), sip_accept_encoding_class))
7511
7512/**Initializer for structure #sip_accept_encoding_t.
7513 *
7514 * A static #sip_accept_encoding_t structure for
7515 * @ref sip_accept_encoding "Accept-Encoding header" must be initialized with
7516 * the SIP_ACCEPT_ENCODING_INIT() macro.
7517 * For instance,
7518 * @code
7519 *
7520 * sip_accept_encoding_t sip_accept_encoding = SIP_ACCEPT_ENCODING_INIT;
7521 *
7522 * @endcode
7523 * @HI
7524 *
7525 */
7526#define SIP_ACCEPT_ENCODING_INIT(){{{ 0, 0, sip_accept_encoding_class }}} SIP_HDR_INIT(accept_encoding){{{ 0, 0, sip_accept_encoding_class }}}
7527
7528/**Initialize a structure #sip_accept_encoding_t.
7529 *
7530 * An #sip_accept_encoding_t structure for
7531 * @ref sip_accept_encoding "Accept-Encoding header" can be initialized with the
7532 * sip_accept_encoding_init() function/macro. For instance,
7533 * @code
7534 *
7535 * sip_accept_encoding_t sip_accept_encoding;
7536 *
7537 * sip_accept_encoding_init(&sip_accept_encoding);
7538 *
7539 * @endcode
7540 * @HI
7541 *
7542 */
7543#if SU_HAVE_INLINE1
7544su_inlinestatic inline sip_accept_encoding_t *sip_accept_encoding_init(sip_accept_encoding_t x[1])
7545{
7546 return SIP_HEADER_INIT(x, sip_accept_encoding_class, sizeof(sip_accept_encoding_t))((void)memset((x), 0, (sizeof(sip_accept_encoding_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_accept_encoding_class
)), (x))
;
7547}
7548#else
7549#define sip_accept_encoding_init(x) \
7550 SIP_HEADER_INIT(x, sip_accept_encoding_class, sizeof(sip_accept_encoding_t))((void)memset((x), 0, (sizeof(sip_accept_encoding_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_accept_encoding_class
)), (x))
7551#endif
7552
7553/**Test if header object is instance of #sip_accept_encoding_t.
7554 *
7555 * Check if the header class is an instance of
7556 * @ref sip_accept_encoding "Accept-Encoding header" object and return true (nonzero),
7557 * otherwise return false (zero).
7558 *
7559 * @param header pointer to the header structure to be tested
7560 *
7561 * @retval 1 (true) if the @a header is an instance of header accept_encoding
7562 * @retval 0 (false) otherwise
7563 *
7564 */
7565#if SU_HAVE_INLINE1
7566su_inlinestatic inline int sip_is_accept_encoding(sip_header_t const *header)
7567{
7568 return header && header->sh_classsh_common->h_class->hc_hash == sip_accept_encoding_hash;
7569}
7570#else
7571int sip_is_accept_encoding(sip_header_t const *header);
7572#endif
7573
7574#define sip_accept_encoding_p(h)sip_is_accept_encoding((h)) sip_is_accept_encoding((h))
7575
7576
7577/**Duplicate a list of @ref sip_accept_encoding "Accept-Encoding header" header structures #sip_accept_encoding_t.
7578 *
7579 * Duplicate a header
7580 * structure @a hdr. If the header structure @a hdr
7581 * contains a reference (@c hdr->x_next) to a list of
7582 * headers, all the headers in the list are duplicated, too.
7583 *
7584 * @param home memory home used to allocate new structure
7585 * @param hdr header structure to be duplicated
7586 *
7587 * When duplicating, all parameter lists and non-constant
7588 * strings attached to the header are copied, too. The
7589 * function uses given memory @a home to allocate all the
7590 * memory areas used to copy the header.
7591 *
7592 * @par Example
7593 * @code
7594 *
7595 * accept_encoding = sip_accept_encoding_dup(home, sip->sip_accept_encoding);
7596 *
7597 * @endcode
7598 *
7599 * @return
7600 * A pointer to the
7601 * newly duplicated #sip_accept_encoding_t header structure, or NULL
7602 * upon an error.
7603 *
7604 */
7605#if SU_HAVE_INLINE1
7606su_inlinestatic inline
7607#endif
7608sip_accept_encoding_t *sip_accept_encoding_dup(su_home_t *home, sip_accept_encoding_t const *hdr)
7609 __attribute__((__malloc__));
7610
7611#if SU_HAVE_INLINE1
7612su_inlinestatic inline
7613sip_accept_encoding_t *sip_accept_encoding_dup(su_home_t *home, sip_accept_encoding_t const *hdr)
7614{
7615 return (sip_accept_encoding_t *)
7616 msg_header_dup_as(home, sip_accept_encoding_class, (msg_header_t const *)hdr);
7617}
7618#endif
7619
7620/**Copy a list of @ref sip_accept_encoding "Accept-Encoding header" header structures #sip_accept_encoding_t.
7621 *
7622 * The function sip_accept_encoding_copy() copies a header structure @a
7623 * hdr. If the header structure @a hdr contains a reference (@c
7624 * hdr->h_next) to a list of headers, all the headers in that
7625 * list are copied, too. The function uses given memory @a home
7626 * to allocate all the memory areas used to copy the list of header
7627 * structure @a hdr.
7628 *
7629 * @param home memory home used to allocate new structure
7630 * @param hdr pointer to the header structure to be copied
7631 *
7632 * When copying, only the header structure and parameter lists attached to
7633 * it are duplicated. The new header structure retains all the references to
7634 * the strings within the old @a hdr header, including the encoding of the
7635 * old header, if present.
7636 *
7637 * @par Example
7638 * @code
7639 *
7640 * accept_encoding = sip_accept_encoding_copy(home, sip->sip_accept_encoding);
7641 *
7642 * @endcode
7643 *
7644 * @return
7645 * A pointer to newly copied header structure, or NULL upon an error.
7646 *
7647 */
7648#if SU_HAVE_INLINE1
7649su_inlinestatic inline
7650#endif
7651sip_accept_encoding_t *sip_accept_encoding_copy(su_home_t *home, sip_accept_encoding_t const *hdr)
7652 __attribute__((__malloc__));
7653
7654#if SU_HAVE_INLINE1
7655su_inlinestatic inline
7656sip_accept_encoding_t *sip_accept_encoding_copy(su_home_t *home, sip_accept_encoding_t const *hdr)
7657{
7658 return (sip_accept_encoding_t *)
7659 msg_header_copy_as(home, sip_accept_encoding_class, (msg_header_t const *)hdr);
7660}
7661#endif
7662
7663/**Make a @ref sip_accept_encoding "Accept-Encoding header" structure #sip_accept_encoding_t.
7664 *
7665 * The function sip_accept_encoding_make() makes a new
7666 * #sip_accept_encoding_t header structure. It allocates a new
7667 * header structure, and decodes the string @a s as the
7668 * value of the structure.
7669 *
7670 * @param home memory home used to allocate new header structure.
7671 * @param s string to be decoded as value of the new header structure
7672 *
7673 * @return
7674 * A pointer to newly maked #sip_accept_encoding_t header structure, or NULL upon an
7675 * error.
7676 *
7677 */
7678#if SU_HAVE_INLINE1
7679su_inlinestatic inline
7680#endif
7681sip_accept_encoding_t *sip_accept_encoding_make(su_home_t *home, char const *s)
7682 __attribute__((__malloc__));
7683
7684#if SU_HAVE_INLINE1
7685su_inlinestatic inline sip_accept_encoding_t *sip_accept_encoding_make(su_home_t *home, char const *s)
7686{
7687 return (sip_accept_encoding_t *)sip_header_make(home, sip_accept_encoding_class, s)((sip_header_t *)msg_header_make((home), (sip_accept_encoding_class
), (s)))
;
7688}
7689#endif
7690
7691/**Make a @ref sip_accept_encoding "Accept-Encoding header" from formatting result.
7692 *
7693 * Make a new #sip_accept_encoding_t object using formatting result as its value.
7694 * The function first prints the arguments according to the format @a fmt
7695 * specified. Then it allocates a new header structure, and parses the
7696 * formatting result to the structure #sip_accept_encoding_t.
7697 *
7698 * @param home memory home used to allocate new header structure.
7699 * @param fmt string used as a printf()-style format
7700 * @param ... argument list for format
7701 *
7702 * @return
7703 * A pointer to newly
7704 * makes header structure, or NULL upon an error.
7705 *
7706 * @HIDE
7707 *
7708 */
7709#if SU_HAVE_INLINE1
7710su_inlinestatic inline
7711#endif
7712sip_accept_encoding_t *sip_accept_encoding_format(su_home_t *home, char const *fmt, ...)
7713 __attribute__((__malloc__, __format__ (printf, 2, 3)));
7714
7715#if SU_HAVE_INLINE1
7716su_inlinestatic inline sip_accept_encoding_t *sip_accept_encoding_format(su_home_t *home, char const *fmt, ...)
7717{
7718 sip_header_t *h;
7719 va_list ap;
7720
7721 va_start(ap, fmt)__builtin_va_start(ap, fmt);
7722 h = sip_header_vformat(home, sip_accept_encoding_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_accept_encoding_class
), (fmt), (ap)))
;
7723 va_end(ap)__builtin_va_end(ap);
7724
7725 return (sip_accept_encoding_t *)h;
7726}
7727#endif
7728
7729/** @} */
7730
7731/**@addtogroup sip_accept_language
7732 * @{
7733 */
7734
7735/** Parse a SIP @ref sip_accept_language "Accept-Language header". @internal */
7736SOFIAPUBFUN issize_t sip_accept_language_d(su_home_t *, msg_header_t *,
7737 char *s, isize_t slen);
7738
7739/** Print a SIP @ref sip_accept_language "Accept-Language header". @internal */
7740SOFIAPUBFUN issize_t sip_accept_language_e(char b[], isize_t bsiz,
7741 msg_header_t const *h, int flags);
7742
7743/**Access a SIP @ref sip_accept_language "Accept-Language header"
7744 * structure #sip_accept_language_t from #sip_t.
7745 *
7746 */
7747#define sip_accept_language(sip)((sip_accept_language_t *)msg_header_access((msg_pub_t*)(sip)
, sip_accept_language_class))
\
7748 ((sip_accept_language_t *)msg_header_access((msg_pub_t*)(sip), sip_accept_language_class))
7749
7750/**Initializer for structure #sip_accept_language_t.
7751 *
7752 * A static #sip_accept_language_t structure for
7753 * @ref sip_accept_language "Accept-Language header" must be initialized with
7754 * the SIP_ACCEPT_LANGUAGE_INIT() macro.
7755 * For instance,
7756 * @code
7757 *
7758 * sip_accept_language_t sip_accept_language = SIP_ACCEPT_LANGUAGE_INIT;
7759 *
7760 * @endcode
7761 * @HI
7762 *
7763 */
7764#define SIP_ACCEPT_LANGUAGE_INIT(){{{ 0, 0, sip_accept_language_class }}} SIP_HDR_INIT(accept_language){{{ 0, 0, sip_accept_language_class }}}
7765
7766/**Initialize a structure #sip_accept_language_t.
7767 *
7768 * An #sip_accept_language_t structure for
7769 * @ref sip_accept_language "Accept-Language header" can be initialized with the
7770 * sip_accept_language_init() function/macro. For instance,
7771 * @code
7772 *
7773 * sip_accept_language_t sip_accept_language;
7774 *
7775 * sip_accept_language_init(&sip_accept_language);
7776 *
7777 * @endcode
7778 * @HI
7779 *
7780 */
7781#if SU_HAVE_INLINE1
7782su_inlinestatic inline sip_accept_language_t *sip_accept_language_init(sip_accept_language_t x[1])
7783{
7784 return SIP_HEADER_INIT(x, sip_accept_language_class, sizeof(sip_accept_language_t))((void)memset((x), 0, (sizeof(sip_accept_language_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_accept_language_class
)), (x))
;
7785}
7786#else
7787#define sip_accept_language_init(x) \
7788 SIP_HEADER_INIT(x, sip_accept_language_class, sizeof(sip_accept_language_t))((void)memset((x), 0, (sizeof(sip_accept_language_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_accept_language_class
)), (x))
7789#endif
7790
7791/**Test if header object is instance of #sip_accept_language_t.
7792 *
7793 * Check if the header class is an instance of
7794 * @ref sip_accept_language "Accept-Language header" object and return true (nonzero),
7795 * otherwise return false (zero).
7796 *
7797 * @param header pointer to the header structure to be tested
7798 *
7799 * @retval 1 (true) if the @a header is an instance of header accept_language
7800 * @retval 0 (false) otherwise
7801 *
7802 */
7803#if SU_HAVE_INLINE1
7804su_inlinestatic inline int sip_is_accept_language(sip_header_t const *header)
7805{
7806 return header && header->sh_classsh_common->h_class->hc_hash == sip_accept_language_hash;
7807}
7808#else
7809int sip_is_accept_language(sip_header_t const *header);
7810#endif
7811
7812#define sip_accept_language_p(h)sip_is_accept_language((h)) sip_is_accept_language((h))
7813
7814
7815/**Duplicate a list of @ref sip_accept_language "Accept-Language header" header structures #sip_accept_language_t.
7816 *
7817 * Duplicate a header
7818 * structure @a hdr. If the header structure @a hdr
7819 * contains a reference (@c hdr->x_next) to a list of
7820 * headers, all the headers in the list are duplicated, too.
7821 *
7822 * @param home memory home used to allocate new structure
7823 * @param hdr header structure to be duplicated
7824 *
7825 * When duplicating, all parameter lists and non-constant
7826 * strings attached to the header are copied, too. The
7827 * function uses given memory @a home to allocate all the
7828 * memory areas used to copy the header.
7829 *
7830 * @par Example
7831 * @code
7832 *
7833 * accept_language = sip_accept_language_dup(home, sip->sip_accept_language);
7834 *
7835 * @endcode
7836 *
7837 * @return
7838 * A pointer to the
7839 * newly duplicated #sip_accept_language_t header structure, or NULL
7840 * upon an error.
7841 *
7842 */
7843#if SU_HAVE_INLINE1
7844su_inlinestatic inline
7845#endif
7846sip_accept_language_t *sip_accept_language_dup(su_home_t *home, sip_accept_language_t const *hdr)
7847 __attribute__((__malloc__));
7848
7849#if SU_HAVE_INLINE1
7850su_inlinestatic inline
7851sip_accept_language_t *sip_accept_language_dup(su_home_t *home, sip_accept_language_t const *hdr)
7852{
7853 return (sip_accept_language_t *)
7854 msg_header_dup_as(home, sip_accept_language_class, (msg_header_t const *)hdr);
7855}
7856#endif
7857
7858/**Copy a list of @ref sip_accept_language "Accept-Language header" header structures #sip_accept_language_t.
7859 *
7860 * The function sip_accept_language_copy() copies a header structure @a
7861 * hdr. If the header structure @a hdr contains a reference (@c
7862 * hdr->h_next) to a list of headers, all the headers in that
7863 * list are copied, too. The function uses given memory @a home
7864 * to allocate all the memory areas used to copy the list of header
7865 * structure @a hdr.
7866 *
7867 * @param home memory home used to allocate new structure
7868 * @param hdr pointer to the header structure to be copied
7869 *
7870 * When copying, only the header structure and parameter lists attached to
7871 * it are duplicated. The new header structure retains all the references to
7872 * the strings within the old @a hdr header, including the encoding of the
7873 * old header, if present.
7874 *
7875 * @par Example
7876 * @code
7877 *
7878 * accept_language = sip_accept_language_copy(home, sip->sip_accept_language);
7879 *
7880 * @endcode
7881 *
7882 * @return
7883 * A pointer to newly copied header structure, or NULL upon an error.
7884 *
7885 */
7886#if SU_HAVE_INLINE1
7887su_inlinestatic inline
7888#endif
7889sip_accept_language_t *sip_accept_language_copy(su_home_t *home, sip_accept_language_t const *hdr)
7890 __attribute__((__malloc__));
7891
7892#if SU_HAVE_INLINE1
7893su_inlinestatic inline
7894sip_accept_language_t *sip_accept_language_copy(su_home_t *home, sip_accept_language_t const *hdr)
7895{
7896 return (sip_accept_language_t *)
7897 msg_header_copy_as(home, sip_accept_language_class, (msg_header_t const *)hdr);
7898}
7899#endif
7900
7901/**Make a @ref sip_accept_language "Accept-Language header" structure #sip_accept_language_t.
7902 *
7903 * The function sip_accept_language_make() makes a new
7904 * #sip_accept_language_t header structure. It allocates a new
7905 * header structure, and decodes the string @a s as the
7906 * value of the structure.
7907 *
7908 * @param home memory home used to allocate new header structure.
7909 * @param s string to be decoded as value of the new header structure
7910 *
7911 * @return
7912 * A pointer to newly maked #sip_accept_language_t header structure, or NULL upon an
7913 * error.
7914 *
7915 */
7916#if SU_HAVE_INLINE1
7917su_inlinestatic inline
7918#endif
7919sip_accept_language_t *sip_accept_language_make(su_home_t *home, char const *s)
7920 __attribute__((__malloc__));
7921
7922#if SU_HAVE_INLINE1
7923su_inlinestatic inline sip_accept_language_t *sip_accept_language_make(su_home_t *home, char const *s)
7924{
7925 return (sip_accept_language_t *)sip_header_make(home, sip_accept_language_class, s)((sip_header_t *)msg_header_make((home), (sip_accept_language_class
), (s)))
;
7926}
7927#endif
7928
7929/**Make a @ref sip_accept_language "Accept-Language header" from formatting result.
7930 *
7931 * Make a new #sip_accept_language_t object using formatting result as its value.
7932 * The function first prints the arguments according to the format @a fmt
7933 * specified. Then it allocates a new header structure, and parses the
7934 * formatting result to the structure #sip_accept_language_t.
7935 *
7936 * @param home memory home used to allocate new header structure.
7937 * @param fmt string used as a printf()-style format
7938 * @param ... argument list for format
7939 *
7940 * @return
7941 * A pointer to newly
7942 * makes header structure, or NULL upon an error.
7943 *
7944 * @HIDE
7945 *
7946 */
7947#if SU_HAVE_INLINE1
7948su_inlinestatic inline
7949#endif
7950sip_accept_language_t *sip_accept_language_format(su_home_t *home, char const *fmt, ...)
7951 __attribute__((__malloc__, __format__ (printf, 2, 3)));
7952
7953#if SU_HAVE_INLINE1
7954su_inlinestatic inline sip_accept_language_t *sip_accept_language_format(su_home_t *home, char const *fmt, ...)
7955{
7956 sip_header_t *h;
7957 va_list ap;
7958
7959 va_start(ap, fmt)__builtin_va_start(ap, fmt);
7960 h = sip_header_vformat(home, sip_accept_language_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_accept_language_class
), (fmt), (ap)))
;
7961 va_end(ap)__builtin_va_end(ap);
7962
7963 return (sip_accept_language_t *)h;
7964}
7965#endif
7966
7967/** @} */
7968
7969/**@addtogroup sip_allow
7970 * @{
7971 */
7972
7973/** Parse a SIP @ref sip_allow "Allow header". @internal */
7974SOFIAPUBFUN issize_t sip_allow_d(su_home_t *, msg_header_t *,
7975 char *s, isize_t slen);
7976
7977/** Print a SIP @ref sip_allow "Allow header". @internal */
7978SOFIAPUBFUN issize_t sip_allow_e(char b[], isize_t bsiz,
7979 msg_header_t const *h, int flags);
7980
7981/**Access a SIP @ref sip_allow "Allow header"
7982 * structure #sip_allow_t from #sip_t.
7983 *
7984 */
7985#define sip_allow(sip)((sip_allow_t *)msg_header_access((msg_pub_t*)(sip), sip_allow_class
))
\
7986 ((sip_allow_t *)msg_header_access((msg_pub_t*)(sip), sip_allow_class))
7987
7988/**Initializer for structure #sip_allow_t.
7989 *
7990 * A static #sip_allow_t structure for
7991 * @ref sip_allow "Allow header" must be initialized with
7992 * the SIP_ALLOW_INIT() macro.
7993 * For instance,
7994 * @code
7995 *
7996 * sip_allow_t sip_allow = SIP_ALLOW_INIT;
7997 *
7998 * @endcode
7999 * @HI
8000 *
8001 */
8002#define SIP_ALLOW_INIT(){{{ 0, 0, sip_allow_class }}} SIP_HDR_INIT(allow){{{ 0, 0, sip_allow_class }}}
8003
8004/**Initialize a structure #sip_allow_t.
8005 *
8006 * An #sip_allow_t structure for
8007 * @ref sip_allow "Allow header" can be initialized with the
8008 * sip_allow_init() function/macro. For instance,
8009 * @code
8010 *
8011 * sip_allow_t sip_allow;
8012 *
8013 * sip_allow_init(&sip_allow);
8014 *
8015 * @endcode
8016 * @HI
8017 *
8018 */
8019#if SU_HAVE_INLINE1
8020su_inlinestatic inline sip_allow_t *sip_allow_init(sip_allow_t x[1])
8021{
8022 return SIP_HEADER_INIT(x, sip_allow_class, sizeof(sip_allow_t))((void)memset((x), 0, (sizeof(sip_allow_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_allow_class)), (x))
;
8023}
8024#else
8025#define sip_allow_init(x) \
8026 SIP_HEADER_INIT(x, sip_allow_class, sizeof(sip_allow_t))((void)memset((x), 0, (sizeof(sip_allow_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_allow_class)), (x))
8027#endif
8028
8029/**Test if header object is instance of #sip_allow_t.
8030 *
8031 * Check if the header class is an instance of
8032 * @ref sip_allow "Allow header" object and return true (nonzero),
8033 * otherwise return false (zero).
8034 *
8035 * @param header pointer to the header structure to be tested
8036 *
8037 * @retval 1 (true) if the @a header is an instance of header allow
8038 * @retval 0 (false) otherwise
8039 *
8040 */
8041#if SU_HAVE_INLINE1
8042su_inlinestatic inline int sip_is_allow(sip_header_t const *header)
8043{
8044 return header && header->sh_classsh_common->h_class->hc_hash == sip_allow_hash;
8045}
8046#else
8047int sip_is_allow(sip_header_t const *header);
8048#endif
8049
8050#define sip_allow_p(h)sip_is_allow((h)) sip_is_allow((h))
8051
8052
8053/**Duplicate a list of @ref sip_allow "Allow header" header structures #sip_allow_t.
8054 *
8055 * Duplicate a header
8056 * structure @a hdr. If the header structure @a hdr
8057 * contains a reference (@c hdr->x_next) to a list of
8058 * headers, all the headers in the list are duplicated, too.
8059 *
8060 * @param home memory home used to allocate new structure
8061 * @param hdr header structure to be duplicated
8062 *
8063 * When duplicating, all parameter lists and non-constant
8064 * strings attached to the header are copied, too. The
8065 * function uses given memory @a home to allocate all the
8066 * memory areas used to copy the header.
8067 *
8068 * @par Example
8069 * @code
8070 *
8071 * allow = sip_allow_dup(home, sip->sip_allow);
8072 *
8073 * @endcode
8074 *
8075 * @return
8076 * A pointer to the
8077 * newly duplicated #sip_allow_t header structure, or NULL
8078 * upon an error.
8079 *
8080 */
8081#if SU_HAVE_INLINE1
8082su_inlinestatic inline
8083#endif
8084sip_allow_t *sip_allow_dup(su_home_t *home, sip_allow_t const *hdr)
8085 __attribute__((__malloc__));
8086
8087#if SU_HAVE_INLINE1
8088su_inlinestatic inline
8089sip_allow_t *sip_allow_dup(su_home_t *home, sip_allow_t const *hdr)
8090{
8091 return (sip_allow_t *)
8092 msg_header_dup_as(home, sip_allow_class, (msg_header_t const *)hdr);
8093}
8094#endif
8095
8096/**Copy a list of @ref sip_allow "Allow header" header structures #sip_allow_t.
8097 *
8098 * The function sip_allow_copy() copies a header structure @a
8099 * hdr. If the header structure @a hdr contains a reference (@c
8100 * hdr->h_next) to a list of headers, all the headers in that
8101 * list are copied, too. The function uses given memory @a home
8102 * to allocate all the memory areas used to copy the list of header
8103 * structure @a hdr.
8104 *
8105 * @param home memory home used to allocate new structure
8106 * @param hdr pointer to the header structure to be copied
8107 *
8108 * When copying, only the header structure and parameter lists attached to
8109 * it are duplicated. The new header structure retains all the references to
8110 * the strings within the old @a hdr header, including the encoding of the
8111 * old header, if present.
8112 *
8113 * @par Example
8114 * @code
8115 *
8116 * allow = sip_allow_copy(home, sip->sip_allow);
8117 *
8118 * @endcode
8119 *
8120 * @return
8121 * A pointer to newly copied header structure, or NULL upon an error.
8122 *
8123 */
8124#if SU_HAVE_INLINE1
8125su_inlinestatic inline
8126#endif
8127sip_allow_t *sip_allow_copy(su_home_t *home, sip_allow_t const *hdr)
8128 __attribute__((__malloc__));
8129
8130#if SU_HAVE_INLINE1
8131su_inlinestatic inline
8132sip_allow_t *sip_allow_copy(su_home_t *home, sip_allow_t const *hdr)
8133{
8134 return (sip_allow_t *)
8135 msg_header_copy_as(home, sip_allow_class, (msg_header_t const *)hdr);
8136}
8137#endif
8138
8139/**Make a @ref sip_allow "Allow header" structure #sip_allow_t.
8140 *
8141 * The function sip_allow_make() makes a new
8142 * #sip_allow_t header structure. It allocates a new
8143 * header structure, and decodes the string @a s as the
8144 * value of the structure.
8145 *
8146 * @param home memory home used to allocate new header structure.
8147 * @param s string to be decoded as value of the new header structure
8148 *
8149 * @return
8150 * A pointer to newly maked #sip_allow_t header structure, or NULL upon an
8151 * error.
8152 *
8153 */
8154#if SU_HAVE_INLINE1
8155su_inlinestatic inline
8156#endif
8157sip_allow_t *sip_allow_make(su_home_t *home, char const *s)
8158 __attribute__((__malloc__));
8159
8160#if SU_HAVE_INLINE1
8161su_inlinestatic inline sip_allow_t *sip_allow_make(su_home_t *home, char const *s)
8162{
8163 return (sip_allow_t *)sip_header_make(home, sip_allow_class, s)((sip_header_t *)msg_header_make((home), (sip_allow_class), (
s)))
;
8164}
8165#endif
8166
8167/**Make a @ref sip_allow "Allow header" from formatting result.
8168 *
8169 * Make a new #sip_allow_t object using formatting result as its value.
8170 * The function first prints the arguments according to the format @a fmt
8171 * specified. Then it allocates a new header structure, and parses the
8172 * formatting result to the structure #sip_allow_t.
8173 *
8174 * @param home memory home used to allocate new header structure.
8175 * @param fmt string used as a printf()-style format
8176 * @param ... argument list for format
8177 *
8178 * @return
8179 * A pointer to newly
8180 * makes header structure, or NULL upon an error.
8181 *
8182 * @HIDE
8183 *
8184 */
8185#if SU_HAVE_INLINE1
8186su_inlinestatic inline
8187#endif
8188sip_allow_t *sip_allow_format(su_home_t *home, char const *fmt, ...)
8189 __attribute__((__malloc__, __format__ (printf, 2, 3)));
8190
8191#if SU_HAVE_INLINE1
8192su_inlinestatic inline sip_allow_t *sip_allow_format(su_home_t *home, char const *fmt, ...)
8193{
8194 sip_header_t *h;
8195 va_list ap;
8196
8197 va_start(ap, fmt)__builtin_va_start(ap, fmt);
8198 h = sip_header_vformat(home, sip_allow_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_allow_class)
, (fmt), (ap)))
;
8199 va_end(ap)__builtin_va_end(ap);
8200
8201 return (sip_allow_t *)h;
8202}
8203#endif
8204
8205/** @} */
8206
8207/**@addtogroup sip_require
8208 * @{
8209 */
8210
8211/** Parse a SIP @ref sip_require "Require header". @internal */
8212SOFIAPUBFUN issize_t sip_require_d(su_home_t *, msg_header_t *,
8213 char *s, isize_t slen);
8214
8215/** Print a SIP @ref sip_require "Require header". @internal */
8216SOFIAPUBFUN issize_t sip_require_e(char b[], isize_t bsiz,
8217 msg_header_t const *h, int flags);
8218
8219/**Access a SIP @ref sip_require "Require header"
8220 * structure #sip_require_t from #sip_t.
8221 *
8222 */
8223#define sip_require(sip)((sip_require_t *)msg_header_access((msg_pub_t*)(sip), sip_require_class
))
\
8224 ((sip_require_t *)msg_header_access((msg_pub_t*)(sip), sip_require_class))
8225
8226/**Initializer for structure #sip_require_t.
8227 *
8228 * A static #sip_require_t structure for
8229 * @ref sip_require "Require header" must be initialized with
8230 * the SIP_REQUIRE_INIT() macro.
8231 * For instance,
8232 * @code
8233 *
8234 * sip_require_t sip_require = SIP_REQUIRE_INIT;
8235 *
8236 * @endcode
8237 * @HI
8238 *
8239 */
8240#define SIP_REQUIRE_INIT(){{{ 0, 0, sip_require_class }}} SIP_HDR_INIT(require){{{ 0, 0, sip_require_class }}}
8241
8242/**Initialize a structure #sip_require_t.
8243 *
8244 * An #sip_require_t structure for
8245 * @ref sip_require "Require header" can be initialized with the
8246 * sip_require_init() function/macro. For instance,
8247 * @code
8248 *
8249 * sip_require_t sip_require;
8250 *
8251 * sip_require_init(&sip_require);
8252 *
8253 * @endcode
8254 * @HI
8255 *
8256 */
8257#if SU_HAVE_INLINE1
8258su_inlinestatic inline sip_require_t *sip_require_init(sip_require_t x[1])
8259{
8260 return SIP_HEADER_INIT(x, sip_require_class, sizeof(sip_require_t))((void)memset((x), 0, (sizeof(sip_require_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_require_class)), (x))
;
8261}
8262#else
8263#define sip_require_init(x) \
8264 SIP_HEADER_INIT(x, sip_require_class, sizeof(sip_require_t))((void)memset((x), 0, (sizeof(sip_require_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_require_class)), (x))
8265#endif
8266
8267/**Test if header object is instance of #sip_require_t.
8268 *
8269 * Check if the header class is an instance of
8270 * @ref sip_require "Require header" object and return true (nonzero),
8271 * otherwise return false (zero).
8272 *
8273 * @param header pointer to the header structure to be tested
8274 *
8275 * @retval 1 (true) if the @a header is an instance of header require
8276 * @retval 0 (false) otherwise
8277 *
8278 */
8279#if SU_HAVE_INLINE1
8280su_inlinestatic inline int sip_is_require(sip_header_t const *header)
8281{
8282 return header && header->sh_classsh_common->h_class->hc_hash == sip_require_hash;
8283}
8284#else
8285int sip_is_require(sip_header_t const *header);
8286#endif
8287
8288#define sip_require_p(h)sip_is_require((h)) sip_is_require((h))
8289
8290
8291/**Duplicate a list of @ref sip_require "Require header" header structures #sip_require_t.
8292 *
8293 * Duplicate a header
8294 * structure @a hdr. If the header structure @a hdr
8295 * contains a reference (@c hdr->x_next) to a list of
8296 * headers, all the headers in the list are duplicated, too.
8297 *
8298 * @param home memory home used to allocate new structure
8299 * @param hdr header structure to be duplicated
8300 *
8301 * When duplicating, all parameter lists and non-constant
8302 * strings attached to the header are copied, too. The
8303 * function uses given memory @a home to allocate all the
8304 * memory areas used to copy the header.
8305 *
8306 * @par Example
8307 * @code
8308 *
8309 * require = sip_require_dup(home, sip->sip_require);
8310 *
8311 * @endcode
8312 *
8313 * @return
8314 * A pointer to the
8315 * newly duplicated #sip_require_t header structure, or NULL
8316 * upon an error.
8317 *
8318 */
8319#if SU_HAVE_INLINE1
8320su_inlinestatic inline
8321#endif
8322sip_require_t *sip_require_dup(su_home_t *home, sip_require_t const *hdr)
8323 __attribute__((__malloc__));
8324
8325#if SU_HAVE_INLINE1
8326su_inlinestatic inline
8327sip_require_t *sip_require_dup(su_home_t *home, sip_require_t const *hdr)
8328{
8329 return (sip_require_t *)
8330 msg_header_dup_as(home, sip_require_class, (msg_header_t const *)hdr);
8331}
8332#endif
8333
8334/**Copy a list of @ref sip_require "Require header" header structures #sip_require_t.
8335 *
8336 * The function sip_require_copy() copies a header structure @a
8337 * hdr. If the header structure @a hdr contains a reference (@c
8338 * hdr->h_next) to a list of headers, all the headers in that
8339 * list are copied, too. The function uses given memory @a home
8340 * to allocate all the memory areas used to copy the list of header
8341 * structure @a hdr.
8342 *
8343 * @param home memory home used to allocate new structure
8344 * @param hdr pointer to the header structure to be copied
8345 *
8346 * When copying, only the header structure and parameter lists attached to
8347 * it are duplicated. The new header structure retains all the references to
8348 * the strings within the old @a hdr header, including the encoding of the
8349 * old header, if present.
8350 *
8351 * @par Example
8352 * @code
8353 *
8354 * require = sip_require_copy(home, sip->sip_require);
8355 *
8356 * @endcode
8357 *
8358 * @return
8359 * A pointer to newly copied header structure, or NULL upon an error.
8360 *
8361 */
8362#if SU_HAVE_INLINE1
8363su_inlinestatic inline
8364#endif
8365sip_require_t *sip_require_copy(su_home_t *home, sip_require_t const *hdr)
8366 __attribute__((__malloc__));
8367
8368#if SU_HAVE_INLINE1
8369su_inlinestatic inline
8370sip_require_t *sip_require_copy(su_home_t *home, sip_require_t const *hdr)
8371{
8372 return (sip_require_t *)
8373 msg_header_copy_as(home, sip_require_class, (msg_header_t const *)hdr);
8374}
8375#endif
8376
8377/**Make a @ref sip_require "Require header" structure #sip_require_t.
8378 *
8379 * The function sip_require_make() makes a new
8380 * #sip_require_t header structure. It allocates a new
8381 * header structure, and decodes the string @a s as the
8382 * value of the structure.
8383 *
8384 * @param home memory home used to allocate new header structure.
8385 * @param s string to be decoded as value of the new header structure
8386 *
8387 * @return
8388 * A pointer to newly maked #sip_require_t header structure, or NULL upon an
8389 * error.
8390 *
8391 */
8392#if SU_HAVE_INLINE1
8393su_inlinestatic inline
8394#endif
8395sip_require_t *sip_require_make(su_home_t *home, char const *s)
8396 __attribute__((__malloc__));
8397
8398#if SU_HAVE_INLINE1
8399su_inlinestatic inline sip_require_t *sip_require_make(su_home_t *home, char const *s)
8400{
8401 return (sip_require_t *)sip_header_make(home, sip_require_class, s)((sip_header_t *)msg_header_make((home), (sip_require_class),
(s)))
;
8402}
8403#endif
8404
8405/**Make a @ref sip_require "Require header" from formatting result.
8406 *
8407 * Make a new #sip_require_t object using formatting result as its value.
8408 * The function first prints the arguments according to the format @a fmt
8409 * specified. Then it allocates a new header structure, and parses the
8410 * formatting result to the structure #sip_require_t.
8411 *
8412 * @param home memory home used to allocate new header structure.
8413 * @param fmt string used as a printf()-style format
8414 * @param ... argument list for format
8415 *
8416 * @return
8417 * A pointer to newly
8418 * makes header structure, or NULL upon an error.
8419 *
8420 * @HIDE
8421 *
8422 */
8423#if SU_HAVE_INLINE1
8424su_inlinestatic inline
8425#endif
8426sip_require_t *sip_require_format(su_home_t *home, char const *fmt, ...)
8427 __attribute__((__malloc__, __format__ (printf, 2, 3)));
8428
8429#if SU_HAVE_INLINE1
8430su_inlinestatic inline sip_require_t *sip_require_format(su_home_t *home, char const *fmt, ...)
8431{
8432 sip_header_t *h;
8433 va_list ap;
8434
8435 va_start(ap, fmt)__builtin_va_start(ap, fmt);
8436 h = sip_header_vformat(home, sip_require_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_require_class
), (fmt), (ap)))
;
8437 va_end(ap)__builtin_va_end(ap);
8438
8439 return (sip_require_t *)h;
8440}
8441#endif
8442
8443/** @} */
8444
8445/**@addtogroup sip_supported
8446 * @{
8447 */
8448
8449/** Parse a SIP @ref sip_supported "Supported header". @internal */
8450SOFIAPUBFUN issize_t sip_supported_d(su_home_t *, msg_header_t *,
8451 char *s, isize_t slen);
8452
8453/** Print a SIP @ref sip_supported "Supported header". @internal */
8454SOFIAPUBFUN issize_t sip_supported_e(char b[], isize_t bsiz,
8455 msg_header_t const *h, int flags);
8456
8457/**Access a SIP @ref sip_supported "Supported header"
8458 * structure #sip_supported_t from #sip_t.
8459 *
8460 */
8461#define sip_supported(sip)((sip_supported_t *)msg_header_access((msg_pub_t*)(sip), sip_supported_class
))
\
8462 ((sip_supported_t *)msg_header_access((msg_pub_t*)(sip), sip_supported_class))
8463
8464/**Initializer for structure #sip_supported_t.
8465 *
8466 * A static #sip_supported_t structure for
8467 * @ref sip_supported "Supported header" must be initialized with
8468 * the SIP_SUPPORTED_INIT() macro.
8469 * For instance,
8470 * @code
8471 *
8472 * sip_supported_t sip_supported = SIP_SUPPORTED_INIT;
8473 *
8474 * @endcode
8475 * @HI
8476 *
8477 */
8478#define SIP_SUPPORTED_INIT(){{{ 0, 0, sip_supported_class }}} SIP_HDR_INIT(supported){{{ 0, 0, sip_supported_class }}}
8479
8480/**Initialize a structure #sip_supported_t.
8481 *
8482 * An #sip_supported_t structure for
8483 * @ref sip_supported "Supported header" can be initialized with the
8484 * sip_supported_init() function/macro. For instance,
8485 * @code
8486 *
8487 * sip_supported_t sip_supported;
8488 *
8489 * sip_supported_init(&sip_supported);
8490 *
8491 * @endcode
8492 * @HI
8493 *
8494 */
8495#if SU_HAVE_INLINE1
8496su_inlinestatic inline sip_supported_t *sip_supported_init(sip_supported_t x[1])
8497{
8498 return SIP_HEADER_INIT(x, sip_supported_class, sizeof(sip_supported_t))((void)memset((x), 0, (sizeof(sip_supported_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_supported_class)), (x))
;
8499}
8500#else
8501#define sip_supported_init(x) \
8502 SIP_HEADER_INIT(x, sip_supported_class, sizeof(sip_supported_t))((void)memset((x), 0, (sizeof(sip_supported_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_supported_class)), (x))
8503#endif
8504
8505/**Test if header object is instance of #sip_supported_t.
8506 *
8507 * Check if the header class is an instance of
8508 * @ref sip_supported "Supported header" object and return true (nonzero),
8509 * otherwise return false (zero).
8510 *
8511 * @param header pointer to the header structure to be tested
8512 *
8513 * @retval 1 (true) if the @a header is an instance of header supported
8514 * @retval 0 (false) otherwise
8515 *
8516 */
8517#if SU_HAVE_INLINE1
8518su_inlinestatic inline int sip_is_supported(sip_header_t const *header)
8519{
8520 return header && header->sh_classsh_common->h_class->hc_hash == sip_supported_hash;
8521}
8522#else
8523int sip_is_supported(sip_header_t const *header);
8524#endif
8525
8526#define sip_supported_p(h)sip_is_supported((h)) sip_is_supported((h))
8527
8528
8529/**Duplicate a list of @ref sip_supported "Supported header" header structures #sip_supported_t.
8530 *
8531 * Duplicate a header
8532 * structure @a hdr. If the header structure @a hdr
8533 * contains a reference (@c hdr->x_next) to a list of
8534 * headers, all the headers in the list are duplicated, too.
8535 *
8536 * @param home memory home used to allocate new structure
8537 * @param hdr header structure to be duplicated
8538 *
8539 * When duplicating, all parameter lists and non-constant
8540 * strings attached to the header are copied, too. The
8541 * function uses given memory @a home to allocate all the
8542 * memory areas used to copy the header.
8543 *
8544 * @par Example
8545 * @code
8546 *
8547 * supported = sip_supported_dup(home, sip->sip_supported);
8548 *
8549 * @endcode
8550 *
8551 * @return
8552 * A pointer to the
8553 * newly duplicated #sip_supported_t header structure, or NULL
8554 * upon an error.
8555 *
8556 */
8557#if SU_HAVE_INLINE1
8558su_inlinestatic inline
8559#endif
8560sip_supported_t *sip_supported_dup(su_home_t *home, sip_supported_t const *hdr)
8561 __attribute__((__malloc__));
8562
8563#if SU_HAVE_INLINE1
8564su_inlinestatic inline
8565sip_supported_t *sip_supported_dup(su_home_t *home, sip_supported_t const *hdr)
8566{
8567 return (sip_supported_t *)
8568 msg_header_dup_as(home, sip_supported_class, (msg_header_t const *)hdr);
8569}
8570#endif
8571
8572/**Copy a list of @ref sip_supported "Supported header" header structures #sip_supported_t.
8573 *
8574 * The function sip_supported_copy() copies a header structure @a
8575 * hdr. If the header structure @a hdr contains a reference (@c
8576 * hdr->h_next) to a list of headers, all the headers in that
8577 * list are copied, too. The function uses given memory @a home
8578 * to allocate all the memory areas used to copy the list of header
8579 * structure @a hdr.
8580 *
8581 * @param home memory home used to allocate new structure
8582 * @param hdr pointer to the header structure to be copied
8583 *
8584 * When copying, only the header structure and parameter lists attached to
8585 * it are duplicated. The new header structure retains all the references to
8586 * the strings within the old @a hdr header, including the encoding of the
8587 * old header, if present.
8588 *
8589 * @par Example
8590 * @code
8591 *
8592 * supported = sip_supported_copy(home, sip->sip_supported);
8593 *
8594 * @endcode
8595 *
8596 * @return
8597 * A pointer to newly copied header structure, or NULL upon an error.
8598 *
8599 */
8600#if SU_HAVE_INLINE1
8601su_inlinestatic inline
8602#endif
8603sip_supported_t *sip_supported_copy(su_home_t *home, sip_supported_t const *hdr)
8604 __attribute__((__malloc__));
8605
8606#if SU_HAVE_INLINE1
8607su_inlinestatic inline
8608sip_supported_t *sip_supported_copy(su_home_t *home, sip_supported_t const *hdr)
8609{
8610 return (sip_supported_t *)
8611 msg_header_copy_as(home, sip_supported_class, (msg_header_t const *)hdr);
8612}
8613#endif
8614
8615/**Make a @ref sip_supported "Supported header" structure #sip_supported_t.
8616 *
8617 * The function sip_supported_make() makes a new
8618 * #sip_supported_t header structure. It allocates a new
8619 * header structure, and decodes the string @a s as the
8620 * value of the structure.
8621 *
8622 * @param home memory home used to allocate new header structure.
8623 * @param s string to be decoded as value of the new header structure
8624 *
8625 * @return
8626 * A pointer to newly maked #sip_supported_t header structure, or NULL upon an
8627 * error.
8628 *
8629 */
8630#if SU_HAVE_INLINE1
8631su_inlinestatic inline
8632#endif
8633sip_supported_t *sip_supported_make(su_home_t *home, char const *s)
8634 __attribute__((__malloc__));
8635
8636#if SU_HAVE_INLINE1
8637su_inlinestatic inline sip_supported_t *sip_supported_make(su_home_t *home, char const *s)
8638{
8639 return (sip_supported_t *)sip_header_make(home, sip_supported_class, s)((sip_header_t *)msg_header_make((home), (sip_supported_class
), (s)))
;
8640}
8641#endif
8642
8643/**Make a @ref sip_supported "Supported header" from formatting result.
8644 *
8645 * Make a new #sip_supported_t object using formatting result as its value.
8646 * The function first prints the arguments according to the format @a fmt
8647 * specified. Then it allocates a new header structure, and parses the
8648 * formatting result to the structure #sip_supported_t.
8649 *
8650 * @param home memory home used to allocate new header structure.
8651 * @param fmt string used as a printf()-style format
8652 * @param ... argument list for format
8653 *
8654 * @return
8655 * A pointer to newly
8656 * makes header structure, or NULL upon an error.
8657 *
8658 * @HIDE
8659 *
8660 */
8661#if SU_HAVE_INLINE1
8662su_inlinestatic inline
8663#endif
8664sip_supported_t *sip_supported_format(su_home_t *home, char const *fmt, ...)
8665 __attribute__((__malloc__, __format__ (printf, 2, 3)));
8666
8667#if SU_HAVE_INLINE1
8668su_inlinestatic inline sip_supported_t *sip_supported_format(su_home_t *home, char const *fmt, ...)
8669{
8670 sip_header_t *h;
8671 va_list ap;
8672
8673 va_start(ap, fmt)__builtin_va_start(ap, fmt);
8674 h = sip_header_vformat(home, sip_supported_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_supported_class
), (fmt), (ap)))
;
8675 va_end(ap)__builtin_va_end(ap);
8676
8677 return (sip_supported_t *)h;
8678}
8679#endif
8680
8681/** @} */
8682
8683/**@addtogroup sip_unsupported
8684 * @{
8685 */
8686
8687/** Parse a SIP @ref sip_unsupported "Unsupported header". @internal */
8688SOFIAPUBFUN issize_t sip_unsupported_d(su_home_t *, msg_header_t *,
8689 char *s, isize_t slen);
8690
8691/** Print a SIP @ref sip_unsupported "Unsupported header". @internal */
8692SOFIAPUBFUN issize_t sip_unsupported_e(char b[], isize_t bsiz,
8693 msg_header_t const *h, int flags);
8694
8695/**Access a SIP @ref sip_unsupported "Unsupported header"
8696 * structure #sip_unsupported_t from #sip_t.
8697 *
8698 */
8699#define sip_unsupported(sip)((sip_unsupported_t *)msg_header_access((msg_pub_t*)(sip), sip_unsupported_class
))
\
8700 ((sip_unsupported_t *)msg_header_access((msg_pub_t*)(sip), sip_unsupported_class))
8701
8702/**Initializer for structure #sip_unsupported_t.
8703 *
8704 * A static #sip_unsupported_t structure for
8705 * @ref sip_unsupported "Unsupported header" must be initialized with
8706 * the SIP_UNSUPPORTED_INIT() macro.
8707 * For instance,
8708 * @code
8709 *
8710 * sip_unsupported_t sip_unsupported = SIP_UNSUPPORTED_INIT;
8711 *
8712 * @endcode
8713 * @HI
8714 *
8715 */
8716#define SIP_UNSUPPORTED_INIT(){{{ 0, 0, sip_unsupported_class }}} SIP_HDR_INIT(unsupported){{{ 0, 0, sip_unsupported_class }}}
8717
8718/**Initialize a structure #sip_unsupported_t.
8719 *
8720 * An #sip_unsupported_t structure for
8721 * @ref sip_unsupported "Unsupported header" can be initialized with the
8722 * sip_unsupported_init() function/macro. For instance,
8723 * @code
8724 *
8725 * sip_unsupported_t sip_unsupported;
8726 *
8727 * sip_unsupported_init(&sip_unsupported);
8728 *
8729 * @endcode
8730 * @HI
8731 *
8732 */
8733#if SU_HAVE_INLINE1
8734su_inlinestatic inline sip_unsupported_t *sip_unsupported_init(sip_unsupported_t x[1])
8735{
8736 return SIP_HEADER_INIT(x, sip_unsupported_class, sizeof(sip_unsupported_t))((void)memset((x), 0, (sizeof(sip_unsupported_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_unsupported_class)), (
x))
;
8737}
8738#else
8739#define sip_unsupported_init(x) \
8740 SIP_HEADER_INIT(x, sip_unsupported_class, sizeof(sip_unsupported_t))((void)memset((x), 0, (sizeof(sip_unsupported_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_unsupported_class)), (
x))
8741#endif
8742
8743/**Test if header object is instance of #sip_unsupported_t.
8744 *
8745 * Check if the header class is an instance of
8746 * @ref sip_unsupported "Unsupported header" object and return true (nonzero),
8747 * otherwise return false (zero).
8748 *
8749 * @param header pointer to the header structure to be tested
8750 *
8751 * @retval 1 (true) if the @a header is an instance of header unsupported
8752 * @retval 0 (false) otherwise
8753 *
8754 */
8755#if SU_HAVE_INLINE1
8756su_inlinestatic inline int sip_is_unsupported(sip_header_t const *header)
8757{
8758 return header && header->sh_classsh_common->h_class->hc_hash == sip_unsupported_hash;
8759}
8760#else
8761int sip_is_unsupported(sip_header_t const *header);
8762#endif
8763
8764#define sip_unsupported_p(h)sip_is_unsupported((h)) sip_is_unsupported((h))
8765
8766
8767/**Duplicate a list of @ref sip_unsupported "Unsupported header" header structures #sip_unsupported_t.
8768 *
8769 * Duplicate a header
8770 * structure @a hdr. If the header structure @a hdr
8771 * contains a reference (@c hdr->x_next) to a list of
8772 * headers, all the headers in the list are duplicated, too.
8773 *
8774 * @param home memory home used to allocate new structure
8775 * @param hdr header structure to be duplicated
8776 *
8777 * When duplicating, all parameter lists and non-constant
8778 * strings attached to the header are copied, too. The
8779 * function uses given memory @a home to allocate all the
8780 * memory areas used to copy the header.
8781 *
8782 * @par Example
8783 * @code
8784 *
8785 * unsupported = sip_unsupported_dup(home, sip->sip_unsupported);
8786 *
8787 * @endcode
8788 *
8789 * @return
8790 * A pointer to the
8791 * newly duplicated #sip_unsupported_t header structure, or NULL
8792 * upon an error.
8793 *
8794 */
8795#if SU_HAVE_INLINE1
8796su_inlinestatic inline
8797#endif
8798sip_unsupported_t *sip_unsupported_dup(su_home_t *home, sip_unsupported_t const *hdr)
8799 __attribute__((__malloc__));
8800
8801#if SU_HAVE_INLINE1
8802su_inlinestatic inline
8803sip_unsupported_t *sip_unsupported_dup(su_home_t *home, sip_unsupported_t const *hdr)
8804{
8805 return (sip_unsupported_t *)
8806 msg_header_dup_as(home, sip_unsupported_class, (msg_header_t const *)hdr);
8807}
8808#endif
8809
8810/**Copy a list of @ref sip_unsupported "Unsupported header" header structures #sip_unsupported_t.
8811 *
8812 * The function sip_unsupported_copy() copies a header structure @a
8813 * hdr. If the header structure @a hdr contains a reference (@c
8814 * hdr->h_next) to a list of headers, all the headers in that
8815 * list are copied, too. The function uses given memory @a home
8816 * to allocate all the memory areas used to copy the list of header
8817 * structure @a hdr.
8818 *
8819 * @param home memory home used to allocate new structure
8820 * @param hdr pointer to the header structure to be copied
8821 *
8822 * When copying, only the header structure and parameter lists attached to
8823 * it are duplicated. The new header structure retains all the references to
8824 * the strings within the old @a hdr header, including the encoding of the
8825 * old header, if present.
8826 *
8827 * @par Example
8828 * @code
8829 *
8830 * unsupported = sip_unsupported_copy(home, sip->sip_unsupported);
8831 *
8832 * @endcode
8833 *
8834 * @return
8835 * A pointer to newly copied header structure, or NULL upon an error.
8836 *
8837 */
8838#if SU_HAVE_INLINE1
8839su_inlinestatic inline
8840#endif
8841sip_unsupported_t *sip_unsupported_copy(su_home_t *home, sip_unsupported_t const *hdr)
8842 __attribute__((__malloc__));
8843
8844#if SU_HAVE_INLINE1
8845su_inlinestatic inline
8846sip_unsupported_t *sip_unsupported_copy(su_home_t *home, sip_unsupported_t const *hdr)
8847{
8848 return (sip_unsupported_t *)
8849 msg_header_copy_as(home, sip_unsupported_class, (msg_header_t const *)hdr);
8850}
8851#endif
8852
8853/**Make a @ref sip_unsupported "Unsupported header" structure #sip_unsupported_t.
8854 *
8855 * The function sip_unsupported_make() makes a new
8856 * #sip_unsupported_t header structure. It allocates a new
8857 * header structure, and decodes the string @a s as the
8858 * value of the structure.
8859 *
8860 * @param home memory home used to allocate new header structure.
8861 * @param s string to be decoded as value of the new header structure
8862 *
8863 * @return
8864 * A pointer to newly maked #sip_unsupported_t header structure, or NULL upon an
8865 * error.
8866 *
8867 */
8868#if SU_HAVE_INLINE1
8869su_inlinestatic inline
8870#endif
8871sip_unsupported_t *sip_unsupported_make(su_home_t *home, char const *s)
8872 __attribute__((__malloc__));
8873
8874#if SU_HAVE_INLINE1
8875su_inlinestatic inline sip_unsupported_t *sip_unsupported_make(su_home_t *home, char const *s)
8876{
8877 return (sip_unsupported_t *)sip_header_make(home, sip_unsupported_class, s)((sip_header_t *)msg_header_make((home), (sip_unsupported_class
), (s)))
;
8878}
8879#endif
8880
8881/**Make a @ref sip_unsupported "Unsupported header" from formatting result.
8882 *
8883 * Make a new #sip_unsupported_t object using formatting result as its value.
8884 * The function first prints the arguments according to the format @a fmt
8885 * specified. Then it allocates a new header structure, and parses the
8886 * formatting result to the structure #sip_unsupported_t.
8887 *
8888 * @param home memory home used to allocate new header structure.
8889 * @param fmt string used as a printf()-style format
8890 * @param ... argument list for format
8891 *
8892 * @return
8893 * A pointer to newly
8894 * makes header structure, or NULL upon an error.
8895 *
8896 * @HIDE
8897 *
8898 */
8899#if SU_HAVE_INLINE1
8900su_inlinestatic inline
8901#endif
8902sip_unsupported_t *sip_unsupported_format(su_home_t *home, char const *fmt, ...)
8903 __attribute__((__malloc__, __format__ (printf, 2, 3)));
8904
8905#if SU_HAVE_INLINE1
8906su_inlinestatic inline sip_unsupported_t *sip_unsupported_format(su_home_t *home, char const *fmt, ...)
8907{
8908 sip_header_t *h;
8909 va_list ap;
8910
8911 va_start(ap, fmt)__builtin_va_start(ap, fmt);
8912 h = sip_header_vformat(home, sip_unsupported_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_unsupported_class
), (fmt), (ap)))
;
8913 va_end(ap)__builtin_va_end(ap);
8914
8915 return (sip_unsupported_t *)h;
8916}
8917#endif
8918
8919/** @} */
8920
8921/**@addtogroup sip_event
8922 * @{
8923 */
8924
8925/** Parse a SIP @ref sip_event "Event header". @internal */
8926SOFIAPUBFUN issize_t sip_event_d(su_home_t *, msg_header_t *,
8927 char *s, isize_t slen);
8928
8929/** Print a SIP @ref sip_event "Event header". @internal */
8930SOFIAPUBFUN issize_t sip_event_e(char b[], isize_t bsiz,
8931 msg_header_t const *h, int flags);
8932
8933/**Access a SIP @ref sip_event "Event header"
8934 * structure #sip_event_t from #sip_t.
8935 *
8936 */
8937#define sip_event(sip)((sip_event_t *)msg_header_access((msg_pub_t*)(sip), sip_event_class
))
\
8938 ((sip_event_t *)msg_header_access((msg_pub_t*)(sip), sip_event_class))
8939
8940/**Initializer for structure #sip_event_t.
8941 *
8942 * A static #sip_event_t structure for
8943 * @ref sip_event "Event header" must be initialized with
8944 * the SIP_EVENT_INIT() macro.
8945 * For instance,
8946 * @code
8947 *
8948 * sip_event_t sip_event = SIP_EVENT_INIT;
8949 *
8950 * @endcode
8951 * @HI
8952 *
8953 */
8954#define SIP_EVENT_INIT(){{{ 0, 0, sip_event_class }}} SIP_HDR_INIT(event){{{ 0, 0, sip_event_class }}}
8955
8956/**Initialize a structure #sip_event_t.
8957 *
8958 * An #sip_event_t structure for
8959 * @ref sip_event "Event header" can be initialized with the
8960 * sip_event_init() function/macro. For instance,
8961 * @code
8962 *
8963 * sip_event_t sip_event;
8964 *
8965 * sip_event_init(&sip_event);
8966 *
8967 * @endcode
8968 * @HI
8969 *
8970 */
8971#if SU_HAVE_INLINE1
8972su_inlinestatic inline sip_event_t *sip_event_init(sip_event_t x[1])
8973{
8974 return SIP_HEADER_INIT(x, sip_event_class, sizeof(sip_event_t))((void)memset((x), 0, (sizeof(sip_event_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_event_class)), (x))
;
8975}
8976#else
8977#define sip_event_init(x) \
8978 SIP_HEADER_INIT(x, sip_event_class, sizeof(sip_event_t))((void)memset((x), 0, (sizeof(sip_event_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_event_class)), (x))
8979#endif
8980
8981/**Test if header object is instance of #sip_event_t.
8982 *
8983 * Check if the header class is an instance of
8984 * @ref sip_event "Event header" object and return true (nonzero),
8985 * otherwise return false (zero).
8986 *
8987 * @param header pointer to the header structure to be tested
8988 *
8989 * @retval 1 (true) if the @a header is an instance of header event
8990 * @retval 0 (false) otherwise
8991 *
8992 */
8993#if SU_HAVE_INLINE1
8994su_inlinestatic inline int sip_is_event(sip_header_t const *header)
8995{
8996 return header && header->sh_classsh_common->h_class->hc_hash == sip_event_hash;
8997}
8998#else
8999int sip_is_event(sip_header_t const *header);
9000#endif
9001
9002#define sip_event_p(h)sip_is_event((h)) sip_is_event((h))
9003
9004
9005/**Duplicate a list of @ref sip_event "Event header" header structures #sip_event_t.
9006 *
9007 * Duplicate a header
9008 * structure @a hdr. If the header structure @a hdr
9009 * contains a reference (@c hdr->x_next) to a list of
9010 * headers, all the headers in the list are duplicated, too.
9011 *
9012 * @param home memory home used to allocate new structure
9013 * @param hdr header structure to be duplicated
9014 *
9015 * When duplicating, all parameter lists and non-constant
9016 * strings attached to the header are copied, too. The
9017 * function uses given memory @a home to allocate all the
9018 * memory areas used to copy the header.
9019 *
9020 * @par Example
9021 * @code
9022 *
9023 * event = sip_event_dup(home, sip->sip_event);
9024 *
9025 * @endcode
9026 *
9027 * @return
9028 * A pointer to the
9029 * newly duplicated #sip_event_t header structure, or NULL
9030 * upon an error.
9031 *
9032 */
9033#if SU_HAVE_INLINE1
9034su_inlinestatic inline
9035#endif
9036sip_event_t *sip_event_dup(su_home_t *home, sip_event_t const *hdr)
9037 __attribute__((__malloc__));
9038
9039#if SU_HAVE_INLINE1
9040su_inlinestatic inline
9041sip_event_t *sip_event_dup(su_home_t *home, sip_event_t const *hdr)
9042{
9043 return (sip_event_t *)
9044 msg_header_dup_as(home, sip_event_class, (msg_header_t const *)hdr);
9045}
9046#endif
9047
9048/**Copy a list of @ref sip_event "Event header" header structures #sip_event_t.
9049 *
9050 * The function sip_event_copy() copies a header structure @a
9051 * hdr. If the header structure @a hdr contains a reference (@c
9052 * hdr->h_next) to a list of headers, all the headers in that
9053 * list are copied, too. The function uses given memory @a home
9054 * to allocate all the memory areas used to copy the list of header
9055 * structure @a hdr.
9056 *
9057 * @param home memory home used to allocate new structure
9058 * @param hdr pointer to the header structure to be copied
9059 *
9060 * When copying, only the header structure and parameter lists attached to
9061 * it are duplicated. The new header structure retains all the references to
9062 * the strings within the old @a hdr header, including the encoding of the
9063 * old header, if present.
9064 *
9065 * @par Example
9066 * @code
9067 *
9068 * event = sip_event_copy(home, sip->sip_event);
9069 *
9070 * @endcode
9071 *
9072 * @return
9073 * A pointer to newly copied header structure, or NULL upon an error.
9074 *
9075 */
9076#if SU_HAVE_INLINE1
9077su_inlinestatic inline
9078#endif
9079sip_event_t *sip_event_copy(su_home_t *home, sip_event_t const *hdr)
9080 __attribute__((__malloc__));
9081
9082#if SU_HAVE_INLINE1
9083su_inlinestatic inline
9084sip_event_t *sip_event_copy(su_home_t *home, sip_event_t const *hdr)
9085{
9086 return (sip_event_t *)
9087 msg_header_copy_as(home, sip_event_class, (msg_header_t const *)hdr);
9088}
9089#endif
9090
9091/**Make a @ref sip_event "Event header" structure #sip_event_t.
9092 *
9093 * The function sip_event_make() makes a new
9094 * #sip_event_t header structure. It allocates a new
9095 * header structure, and decodes the string @a s as the
9096 * value of the structure.
9097 *
9098 * @param home memory home used to allocate new header structure.
9099 * @param s string to be decoded as value of the new header structure
9100 *
9101 * @return
9102 * A pointer to newly maked #sip_event_t header structure, or NULL upon an
9103 * error.
9104 *
9105 */
9106#if SU_HAVE_INLINE1
9107su_inlinestatic inline
9108#endif
9109sip_event_t *sip_event_make(su_home_t *home, char const *s)
9110 __attribute__((__malloc__));
9111
9112#if SU_HAVE_INLINE1
9113su_inlinestatic inline sip_event_t *sip_event_make(su_home_t *home, char const *s)
9114{
9115 return (sip_event_t *)sip_header_make(home, sip_event_class, s)((sip_header_t *)msg_header_make((home), (sip_event_class), (
s)))
;
9116}
9117#endif
9118
9119/**Make a @ref sip_event "Event header" from formatting result.
9120 *
9121 * Make a new #sip_event_t object using formatting result as its value.
9122 * The function first prints the arguments according to the format @a fmt
9123 * specified. Then it allocates a new header structure, and parses the
9124 * formatting result to the structure #sip_event_t.
9125 *
9126 * @param home memory home used to allocate new header structure.
9127 * @param fmt string used as a printf()-style format
9128 * @param ... argument list for format
9129 *
9130 * @return
9131 * A pointer to newly
9132 * makes header structure, or NULL upon an error.
9133 *
9134 * @HIDE
9135 *
9136 */
9137#if SU_HAVE_INLINE1
9138su_inlinestatic inline
9139#endif
9140sip_event_t *sip_event_format(su_home_t *home, char const *fmt, ...)
9141 __attribute__((__malloc__, __format__ (printf, 2, 3)));
9142
9143#if SU_HAVE_INLINE1
9144su_inlinestatic inline sip_event_t *sip_event_format(su_home_t *home, char const *fmt, ...)
9145{
9146 sip_header_t *h;
9147 va_list ap;
9148
9149 va_start(ap, fmt)__builtin_va_start(ap, fmt);
9150 h = sip_header_vformat(home, sip_event_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_event_class)
, (fmt), (ap)))
;
9151 va_end(ap)__builtin_va_end(ap);
9152
9153 return (sip_event_t *)h;
9154}
9155#endif
9156
9157/** @} */
9158
9159/**@addtogroup sip_allow_events
9160 * @{
9161 */
9162
9163/** Parse a SIP @ref sip_allow_events "Allow-Events header". @internal */
9164SOFIAPUBFUN issize_t sip_allow_events_d(su_home_t *, msg_header_t *,
9165 char *s, isize_t slen);
9166
9167/** Print a SIP @ref sip_allow_events "Allow-Events header". @internal */
9168SOFIAPUBFUN issize_t sip_allow_events_e(char b[], isize_t bsiz,
9169 msg_header_t const *h, int flags);
9170
9171/**Access a SIP @ref sip_allow_events "Allow-Events header"
9172 * structure #sip_allow_events_t from #sip_t.
9173 *
9174 */
9175#define sip_allow_events(sip)((sip_allow_events_t *)msg_header_access((msg_pub_t*)(sip), sip_allow_events_class
))
\
9176 ((sip_allow_events_t *)msg_header_access((msg_pub_t*)(sip), sip_allow_events_class))
9177
9178/**Initializer for structure #sip_allow_events_t.
9179 *
9180 * A static #sip_allow_events_t structure for
9181 * @ref sip_allow_events "Allow-Events header" must be initialized with
9182 * the SIP_ALLOW_EVENTS_INIT() macro.
9183 * For instance,
9184 * @code
9185 *
9186 * sip_allow_events_t sip_allow_events = SIP_ALLOW_EVENTS_INIT;
9187 *
9188 * @endcode
9189 * @HI
9190 *
9191 */
9192#define SIP_ALLOW_EVENTS_INIT(){{{ 0, 0, sip_allow_events_class }}} SIP_HDR_INIT(allow_events){{{ 0, 0, sip_allow_events_class }}}
9193
9194/**Initialize a structure #sip_allow_events_t.
9195 *
9196 * An #sip_allow_events_t structure for
9197 * @ref sip_allow_events "Allow-Events header" can be initialized with the
9198 * sip_allow_events_init() function/macro. For instance,
9199 * @code
9200 *
9201 * sip_allow_events_t sip_allow_events;
9202 *
9203 * sip_allow_events_init(&sip_allow_events);
9204 *
9205 * @endcode
9206 * @HI
9207 *
9208 */
9209#if SU_HAVE_INLINE1
9210su_inlinestatic inline sip_allow_events_t *sip_allow_events_init(sip_allow_events_t x[1])
9211{
9212 return SIP_HEADER_INIT(x, sip_allow_events_class, sizeof(sip_allow_events_t))((void)memset((x), 0, (sizeof(sip_allow_events_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_allow_events_class)),
(x))
;
9213}
9214#else
9215#define sip_allow_events_init(x) \
9216 SIP_HEADER_INIT(x, sip_allow_events_class, sizeof(sip_allow_events_t))((void)memset((x), 0, (sizeof(sip_allow_events_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_allow_events_class)),
(x))
9217#endif
9218
9219/**Test if header object is instance of #sip_allow_events_t.
9220 *
9221 * Check if the header class is an instance of
9222 * @ref sip_allow_events "Allow-Events header" object and return true (nonzero),
9223 * otherwise return false (zero).
9224 *
9225 * @param header pointer to the header structure to be tested
9226 *
9227 * @retval 1 (true) if the @a header is an instance of header allow_events
9228 * @retval 0 (false) otherwise
9229 *
9230 */
9231#if SU_HAVE_INLINE1
9232su_inlinestatic inline int sip_is_allow_events(sip_header_t const *header)
9233{
9234 return header && header->sh_classsh_common->h_class->hc_hash == sip_allow_events_hash;
9235}
9236#else
9237int sip_is_allow_events(sip_header_t const *header);
9238#endif
9239
9240#define sip_allow_events_p(h)sip_is_allow_events((h)) sip_is_allow_events((h))
9241
9242
9243/**Duplicate a list of @ref sip_allow_events "Allow-Events header" header structures #sip_allow_events_t.
9244 *
9245 * Duplicate a header
9246 * structure @a hdr. If the header structure @a hdr
9247 * contains a reference (@c hdr->x_next) to a list of
9248 * headers, all the headers in the list are duplicated, too.
9249 *
9250 * @param home memory home used to allocate new structure
9251 * @param hdr header structure to be duplicated
9252 *
9253 * When duplicating, all parameter lists and non-constant
9254 * strings attached to the header are copied, too. The
9255 * function uses given memory @a home to allocate all the
9256 * memory areas used to copy the header.
9257 *
9258 * @par Example
9259 * @code
9260 *
9261 * allow_events = sip_allow_events_dup(home, sip->sip_allow_events);
9262 *
9263 * @endcode
9264 *
9265 * @return
9266 * A pointer to the
9267 * newly duplicated #sip_allow_events_t header structure, or NULL
9268 * upon an error.
9269 *
9270 */
9271#if SU_HAVE_INLINE1
9272su_inlinestatic inline
9273#endif
9274sip_allow_events_t *sip_allow_events_dup(su_home_t *home, sip_allow_events_t const *hdr)
9275 __attribute__((__malloc__));
9276
9277#if SU_HAVE_INLINE1
9278su_inlinestatic inline
9279sip_allow_events_t *sip_allow_events_dup(su_home_t *home, sip_allow_events_t const *hdr)
9280{
9281 return (sip_allow_events_t *)
9282 msg_header_dup_as(home, sip_allow_events_class, (msg_header_t const *)hdr);
9283}
9284#endif
9285
9286/**Copy a list of @ref sip_allow_events "Allow-Events header" header structures #sip_allow_events_t.
9287 *
9288 * The function sip_allow_events_copy() copies a header structure @a
9289 * hdr. If the header structure @a hdr contains a reference (@c
9290 * hdr->h_next) to a list of headers, all the headers in that
9291 * list are copied, too. The function uses given memory @a home
9292 * to allocate all the memory areas used to copy the list of header
9293 * structure @a hdr.
9294 *
9295 * @param home memory home used to allocate new structure
9296 * @param hdr pointer to the header structure to be copied
9297 *
9298 * When copying, only the header structure and parameter lists attached to
9299 * it are duplicated. The new header structure retains all the references to
9300 * the strings within the old @a hdr header, including the encoding of the
9301 * old header, if present.
9302 *
9303 * @par Example
9304 * @code
9305 *
9306 * allow_events = sip_allow_events_copy(home, sip->sip_allow_events);
9307 *
9308 * @endcode
9309 *
9310 * @return
9311 * A pointer to newly copied header structure, or NULL upon an error.
9312 *
9313 */
9314#if SU_HAVE_INLINE1
9315su_inlinestatic inline
9316#endif
9317sip_allow_events_t *sip_allow_events_copy(su_home_t *home, sip_allow_events_t const *hdr)
9318 __attribute__((__malloc__));
9319
9320#if SU_HAVE_INLINE1
9321su_inlinestatic inline
9322sip_allow_events_t *sip_allow_events_copy(su_home_t *home, sip_allow_events_t const *hdr)
9323{
9324 return (sip_allow_events_t *)
9325 msg_header_copy_as(home, sip_allow_events_class, (msg_header_t const *)hdr);
9326}
9327#endif
9328
9329/**Make a @ref sip_allow_events "Allow-Events header" structure #sip_allow_events_t.
9330 *
9331 * The function sip_allow_events_make() makes a new
9332 * #sip_allow_events_t header structure. It allocates a new
9333 * header structure, and decodes the string @a s as the
9334 * value of the structure.
9335 *
9336 * @param home memory home used to allocate new header structure.
9337 * @param s string to be decoded as value of the new header structure
9338 *
9339 * @return
9340 * A pointer to newly maked #sip_allow_events_t header structure, or NULL upon an
9341 * error.
9342 *
9343 */
9344#if SU_HAVE_INLINE1
9345su_inlinestatic inline
9346#endif
9347sip_allow_events_t *sip_allow_events_make(su_home_t *home, char const *s)
9348 __attribute__((__malloc__));
9349
9350#if SU_HAVE_INLINE1
9351su_inlinestatic inline sip_allow_events_t *sip_allow_events_make(su_home_t *home, char const *s)
9352{
9353 return (sip_allow_events_t *)sip_header_make(home, sip_allow_events_class, s)((sip_header_t *)msg_header_make((home), (sip_allow_events_class
), (s)))
;
9354}
9355#endif
9356
9357/**Make a @ref sip_allow_events "Allow-Events header" from formatting result.
9358 *
9359 * Make a new #sip_allow_events_t object using formatting result as its value.
9360 * The function first prints the arguments according to the format @a fmt
9361 * specified. Then it allocates a new header structure, and parses the
9362 * formatting result to the structure #sip_allow_events_t.
9363 *
9364 * @param home memory home used to allocate new header structure.
9365 * @param fmt string used as a printf()-style format
9366 * @param ... argument list for format
9367 *
9368 * @return
9369 * A pointer to newly
9370 * makes header structure, or NULL upon an error.
9371 *
9372 * @HIDE
9373 *
9374 */
9375#if SU_HAVE_INLINE1
9376su_inlinestatic inline
9377#endif
9378sip_allow_events_t *sip_allow_events_format(su_home_t *home, char const *fmt, ...)
9379 __attribute__((__malloc__, __format__ (printf, 2, 3)));
9380
9381#if SU_HAVE_INLINE1
9382su_inlinestatic inline sip_allow_events_t *sip_allow_events_format(su_home_t *home, char const *fmt, ...)
9383{
9384 sip_header_t *h;
9385 va_list ap;
9386
9387 va_start(ap, fmt)__builtin_va_start(ap, fmt);
9388 h = sip_header_vformat(home, sip_allow_events_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_allow_events_class
), (fmt), (ap)))
;
9389 va_end(ap)__builtin_va_end(ap);
9390
9391 return (sip_allow_events_t *)h;
9392}
9393#endif
9394
9395/** @} */
9396
9397/**@addtogroup sip_subscription_state
9398 * @{
9399 */
9400
9401/** Parse a SIP @ref sip_subscription_state "Subscription-State header". @internal */
9402SOFIAPUBFUN issize_t sip_subscription_state_d(su_home_t *, msg_header_t *,
9403 char *s, isize_t slen);
9404
9405/** Print a SIP @ref sip_subscription_state "Subscription-State header". @internal */
9406SOFIAPUBFUN issize_t sip_subscription_state_e(char b[], isize_t bsiz,
9407 msg_header_t const *h, int flags);
9408
9409/**Access a SIP @ref sip_subscription_state "Subscription-State header"
9410 * structure #sip_subscription_state_t from #sip_t.
9411 *
9412 */
9413#define sip_subscription_state(sip)((sip_subscription_state_t *)msg_header_access((msg_pub_t*)(sip
), sip_subscription_state_class))
\
9414 ((sip_subscription_state_t *)msg_header_access((msg_pub_t*)(sip), sip_subscription_state_class))
9415
9416/**Initializer for structure #sip_subscription_state_t.
9417 *
9418 * A static #sip_subscription_state_t structure for
9419 * @ref sip_subscription_state "Subscription-State header" must be initialized with
9420 * the SIP_SUBSCRIPTION_STATE_INIT() macro.
9421 * For instance,
9422 * @code
9423 *
9424 * sip_subscription_state_t sip_subscription_state = SIP_SUBSCRIPTION_STATE_INIT;
9425 *
9426 * @endcode
9427 * @HI
9428 *
9429 */
9430#define SIP_SUBSCRIPTION_STATE_INIT(){{{ 0, 0, sip_subscription_state_class }}} SIP_HDR_INIT(subscription_state){{{ 0, 0, sip_subscription_state_class }}}
9431
9432/**Initialize a structure #sip_subscription_state_t.
9433 *
9434 * An #sip_subscription_state_t structure for
9435 * @ref sip_subscription_state "Subscription-State header" can be initialized with the
9436 * sip_subscription_state_init() function/macro. For instance,
9437 * @code
9438 *
9439 * sip_subscription_state_t sip_subscription_state;
9440 *
9441 * sip_subscription_state_init(&sip_subscription_state);
9442 *
9443 * @endcode
9444 * @HI
9445 *
9446 */
9447#if SU_HAVE_INLINE1
9448su_inlinestatic inline sip_subscription_state_t *sip_subscription_state_init(sip_subscription_state_t x[1])
9449{
9450 return SIP_HEADER_INIT(x, sip_subscription_state_class, sizeof(sip_subscription_state_t))((void)memset((x), 0, (sizeof(sip_subscription_state_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_subscription_state_class
)), (x))
;
9451}
9452#else
9453#define sip_subscription_state_init(x) \
9454 SIP_HEADER_INIT(x, sip_subscription_state_class, sizeof(sip_subscription_state_t))((void)memset((x), 0, (sizeof(sip_subscription_state_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_subscription_state_class
)), (x))
9455#endif
9456
9457/**Test if header object is instance of #sip_subscription_state_t.
9458 *
9459 * Check if the header class is an instance of
9460 * @ref sip_subscription_state "Subscription-State header" object and return true (nonzero),
9461 * otherwise return false (zero).
9462 *
9463 * @param header pointer to the header structure to be tested
9464 *
9465 * @retval 1 (true) if the @a header is an instance of header subscription_state
9466 * @retval 0 (false) otherwise
9467 *
9468 */
9469#if SU_HAVE_INLINE1
9470su_inlinestatic inline int sip_is_subscription_state(sip_header_t const *header)
9471{
9472 return header && header->sh_classsh_common->h_class->hc_hash == sip_subscription_state_hash;
9473}
9474#else
9475int sip_is_subscription_state(sip_header_t const *header);
9476#endif
9477
9478#define sip_subscription_state_p(h)sip_is_subscription_state((h)) sip_is_subscription_state((h))
9479
9480
9481/**Duplicate a list of @ref sip_subscription_state "Subscription-State header" header structures #sip_subscription_state_t.
9482 *
9483 * Duplicate a header
9484 * structure @a hdr. If the header structure @a hdr
9485 * contains a reference (@c hdr->x_next) to a list of
9486 * headers, all the headers in the list are duplicated, too.
9487 *
9488 * @param home memory home used to allocate new structure
9489 * @param hdr header structure to be duplicated
9490 *
9491 * When duplicating, all parameter lists and non-constant
9492 * strings attached to the header are copied, too. The
9493 * function uses given memory @a home to allocate all the
9494 * memory areas used to copy the header.
9495 *
9496 * @par Example
9497 * @code
9498 *
9499 * subscription_state = sip_subscription_state_dup(home, sip->sip_subscription_state);
9500 *
9501 * @endcode
9502 *
9503 * @return
9504 * A pointer to the
9505 * newly duplicated #sip_subscription_state_t header structure, or NULL
9506 * upon an error.
9507 *
9508 */
9509#if SU_HAVE_INLINE1
9510su_inlinestatic inline
9511#endif
9512sip_subscription_state_t *sip_subscription_state_dup(su_home_t *home, sip_subscription_state_t const *hdr)
9513 __attribute__((__malloc__));
9514
9515#if SU_HAVE_INLINE1
9516su_inlinestatic inline
9517sip_subscription_state_t *sip_subscription_state_dup(su_home_t *home, sip_subscription_state_t const *hdr)
9518{
9519 return (sip_subscription_state_t *)
9520 msg_header_dup_as(home, sip_subscription_state_class, (msg_header_t const *)hdr);
9521}
9522#endif
9523
9524/**Copy a list of @ref sip_subscription_state "Subscription-State header" header structures #sip_subscription_state_t.
9525 *
9526 * The function sip_subscription_state_copy() copies a header structure @a
9527 * hdr. If the header structure @a hdr contains a reference (@c
9528 * hdr->h_next) to a list of headers, all the headers in that
9529 * list are copied, too. The function uses given memory @a home
9530 * to allocate all the memory areas used to copy the list of header
9531 * structure @a hdr.
9532 *
9533 * @param home memory home used to allocate new structure
9534 * @param hdr pointer to the header structure to be copied
9535 *
9536 * When copying, only the header structure and parameter lists attached to
9537 * it are duplicated. The new header structure retains all the references to
9538 * the strings within the old @a hdr header, including the encoding of the
9539 * old header, if present.
9540 *
9541 * @par Example
9542 * @code
9543 *
9544 * subscription_state = sip_subscription_state_copy(home, sip->sip_subscription_state);
9545 *
9546 * @endcode
9547 *
9548 * @return
9549 * A pointer to newly copied header structure, or NULL upon an error.
9550 *
9551 */
9552#if SU_HAVE_INLINE1
9553su_inlinestatic inline
9554#endif
9555sip_subscription_state_t *sip_subscription_state_copy(su_home_t *home, sip_subscription_state_t const *hdr)
9556 __attribute__((__malloc__));
9557
9558#if SU_HAVE_INLINE1
9559su_inlinestatic inline
9560sip_subscription_state_t *sip_subscription_state_copy(su_home_t *home, sip_subscription_state_t const *hdr)
9561{
9562 return (sip_subscription_state_t *)
9563 msg_header_copy_as(home, sip_subscription_state_class, (msg_header_t const *)hdr);
9564}
9565#endif
9566
9567/**Make a @ref sip_subscription_state "Subscription-State header" structure #sip_subscription_state_t.
9568 *
9569 * The function sip_subscription_state_make() makes a new
9570 * #sip_subscription_state_t header structure. It allocates a new
9571 * header structure, and decodes the string @a s as the
9572 * value of the structure.
9573 *
9574 * @param home memory home used to allocate new header structure.
9575 * @param s string to be decoded as value of the new header structure
9576 *
9577 * @return
9578 * A pointer to newly maked #sip_subscription_state_t header structure, or NULL upon an
9579 * error.
9580 *
9581 */
9582#if SU_HAVE_INLINE1
9583su_inlinestatic inline
9584#endif
9585sip_subscription_state_t *sip_subscription_state_make(su_home_t *home, char const *s)
9586 __attribute__((__malloc__));
9587
9588#if SU_HAVE_INLINE1
9589su_inlinestatic inline sip_subscription_state_t *sip_subscription_state_make(su_home_t *home, char const *s)
9590{
9591 return (sip_subscription_state_t *)sip_header_make(home, sip_subscription_state_class, s)((sip_header_t *)msg_header_make((home), (sip_subscription_state_class
), (s)))
;
9592}
9593#endif
9594
9595/**Make a @ref sip_subscription_state "Subscription-State header" from formatting result.
9596 *
9597 * Make a new #sip_subscription_state_t object using formatting result as its value.
9598 * The function first prints the arguments according to the format @a fmt
9599 * specified. Then it allocates a new header structure, and parses the
9600 * formatting result to the structure #sip_subscription_state_t.
9601 *
9602 * @param home memory home used to allocate new header structure.
9603 * @param fmt string used as a printf()-style format
9604 * @param ... argument list for format
9605 *
9606 * @return
9607 * A pointer to newly
9608 * makes header structure, or NULL upon an error.
9609 *
9610 * @HIDE
9611 *
9612 */
9613#if SU_HAVE_INLINE1
9614su_inlinestatic inline
9615#endif
9616sip_subscription_state_t *sip_subscription_state_format(su_home_t *home, char const *fmt, ...)
9617 __attribute__((__malloc__, __format__ (printf, 2, 3)));
9618
9619#if SU_HAVE_INLINE1
9620su_inlinestatic inline sip_subscription_state_t *sip_subscription_state_format(su_home_t *home, char const *fmt, ...)
9621{
9622 sip_header_t *h;
9623 va_list ap;
9624
9625 va_start(ap, fmt)__builtin_va_start(ap, fmt);
9626 h = sip_header_vformat(home, sip_subscription_state_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_subscription_state_class
), (fmt), (ap)))
;
9627 va_end(ap)__builtin_va_end(ap);
9628
9629 return (sip_subscription_state_t *)h;
9630}
9631#endif
9632
9633/** @} */
9634
9635/**@addtogroup sip_proxy_authenticate
9636 * @{
9637 */
9638
9639/** Parse a SIP @ref sip_proxy_authenticate "Proxy-Authenticate header". @internal */
9640SOFIAPUBFUN issize_t sip_proxy_authenticate_d(su_home_t *, msg_header_t *,
9641 char *s, isize_t slen);
9642
9643/** Print a SIP @ref sip_proxy_authenticate "Proxy-Authenticate header". @internal */
9644SOFIAPUBFUN issize_t sip_proxy_authenticate_e(char b[], isize_t bsiz,
9645 msg_header_t const *h, int flags);
9646
9647/**Access a SIP @ref sip_proxy_authenticate "Proxy-Authenticate header"
9648 * structure #sip_proxy_authenticate_t from #sip_t.
9649 *
9650 */
9651#define sip_proxy_authenticate(sip)((sip_proxy_authenticate_t *)msg_header_access((msg_pub_t*)(sip
), sip_proxy_authenticate_class))
\
9652 ((sip_proxy_authenticate_t *)msg_header_access((msg_pub_t*)(sip), sip_proxy_authenticate_class))
9653
9654/**Initializer for structure #sip_proxy_authenticate_t.
9655 *
9656 * A static #sip_proxy_authenticate_t structure for
9657 * @ref sip_proxy_authenticate "Proxy-Authenticate header" must be initialized with
9658 * the SIP_PROXY_AUTHENTICATE_INIT() macro.
9659 * For instance,
9660 * @code
9661 *
9662 * sip_proxy_authenticate_t sip_proxy_authenticate = SIP_PROXY_AUTHENTICATE_INIT;
9663 *
9664 * @endcode
9665 * @HI
9666 *
9667 */
9668#define SIP_PROXY_AUTHENTICATE_INIT(){{{ 0, 0, sip_proxy_authenticate_class }}} SIP_HDR_INIT(proxy_authenticate){{{ 0, 0, sip_proxy_authenticate_class }}}
9669
9670/**Initialize a structure #sip_proxy_authenticate_t.
9671 *
9672 * An #sip_proxy_authenticate_t structure for
9673 * @ref sip_proxy_authenticate "Proxy-Authenticate header" can be initialized with the
9674 * sip_proxy_authenticate_init() function/macro. For instance,
9675 * @code
9676 *
9677 * sip_proxy_authenticate_t sip_proxy_authenticate;
9678 *
9679 * sip_proxy_authenticate_init(&sip_proxy_authenticate);
9680 *
9681 * @endcode
9682 * @HI
9683 *
9684 */
9685#if SU_HAVE_INLINE1
9686su_inlinestatic inline sip_proxy_authenticate_t *sip_proxy_authenticate_init(sip_proxy_authenticate_t x[1])
9687{
9688 return SIP_HEADER_INIT(x, sip_proxy_authenticate_class, sizeof(sip_proxy_authenticate_t))((void)memset((x), 0, (sizeof(sip_proxy_authenticate_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_proxy_authenticate_class
)), (x))
;
9689}
9690#else
9691#define sip_proxy_authenticate_init(x) \
9692 SIP_HEADER_INIT(x, sip_proxy_authenticate_class, sizeof(sip_proxy_authenticate_t))((void)memset((x), 0, (sizeof(sip_proxy_authenticate_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_proxy_authenticate_class
)), (x))
9693#endif
9694
9695/**Test if header object is instance of #sip_proxy_authenticate_t.
9696 *
9697 * Check if the header class is an instance of
9698 * @ref sip_proxy_authenticate "Proxy-Authenticate header" object and return true (nonzero),
9699 * otherwise return false (zero).
9700 *
9701 * @param header pointer to the header structure to be tested
9702 *
9703 * @retval 1 (true) if the @a header is an instance of header proxy_authenticate
9704 * @retval 0 (false) otherwise
9705 *
9706 */
9707#if SU_HAVE_INLINE1
9708su_inlinestatic inline int sip_is_proxy_authenticate(sip_header_t const *header)
9709{
9710 return header && header->sh_classsh_common->h_class->hc_hash == sip_proxy_authenticate_hash;
9711}
9712#else
9713int sip_is_proxy_authenticate(sip_header_t const *header);
9714#endif
9715
9716#define sip_proxy_authenticate_p(h)sip_is_proxy_authenticate((h)) sip_is_proxy_authenticate((h))
9717
9718
9719/**Duplicate a list of @ref sip_proxy_authenticate "Proxy-Authenticate header" header structures #sip_proxy_authenticate_t.
9720 *
9721 * Duplicate a header
9722 * structure @a hdr. If the header structure @a hdr
9723 * contains a reference (@c hdr->x_next) to a list of
9724 * headers, all the headers in the list are duplicated, too.
9725 *
9726 * @param home memory home used to allocate new structure
9727 * @param hdr header structure to be duplicated
9728 *
9729 * When duplicating, all parameter lists and non-constant
9730 * strings attached to the header are copied, too. The
9731 * function uses given memory @a home to allocate all the
9732 * memory areas used to copy the header.
9733 *
9734 * @par Example
9735 * @code
9736 *
9737 * proxy_authenticate = sip_proxy_authenticate_dup(home, sip->sip_proxy_authenticate);
9738 *
9739 * @endcode
9740 *
9741 * @return
9742 * A pointer to the
9743 * newly duplicated #sip_proxy_authenticate_t header structure, or NULL
9744 * upon an error.
9745 *
9746 */
9747#if SU_HAVE_INLINE1
9748su_inlinestatic inline
9749#endif
9750sip_proxy_authenticate_t *sip_proxy_authenticate_dup(su_home_t *home, sip_proxy_authenticate_t const *hdr)
9751 __attribute__((__malloc__));
9752
9753#if SU_HAVE_INLINE1
9754su_inlinestatic inline
9755sip_proxy_authenticate_t *sip_proxy_authenticate_dup(su_home_t *home, sip_proxy_authenticate_t const *hdr)
9756{
9757 return (sip_proxy_authenticate_t *)
9758 msg_header_dup_as(home, sip_proxy_authenticate_class, (msg_header_t const *)hdr);
9759}
9760#endif
9761
9762/**Copy a list of @ref sip_proxy_authenticate "Proxy-Authenticate header" header structures #sip_proxy_authenticate_t.
9763 *
9764 * The function sip_proxy_authenticate_copy() copies a header structure @a
9765 * hdr. If the header structure @a hdr contains a reference (@c
9766 * hdr->h_next) to a list of headers, all the headers in that
9767 * list are copied, too. The function uses given memory @a home
9768 * to allocate all the memory areas used to copy the list of header
9769 * structure @a hdr.
9770 *
9771 * @param home memory home used to allocate new structure
9772 * @param hdr pointer to the header structure to be copied
9773 *
9774 * When copying, only the header structure and parameter lists attached to
9775 * it are duplicated. The new header structure retains all the references to
9776 * the strings within the old @a hdr header, including the encoding of the
9777 * old header, if present.
9778 *
9779 * @par Example
9780 * @code
9781 *
9782 * proxy_authenticate = sip_proxy_authenticate_copy(home, sip->sip_proxy_authenticate);
9783 *
9784 * @endcode
9785 *
9786 * @return
9787 * A pointer to newly copied header structure, or NULL upon an error.
9788 *
9789 */
9790#if SU_HAVE_INLINE1
9791su_inlinestatic inline
9792#endif
9793sip_proxy_authenticate_t *sip_proxy_authenticate_copy(su_home_t *home, sip_proxy_authenticate_t const *hdr)
9794 __attribute__((__malloc__));
9795
9796#if SU_HAVE_INLINE1
9797su_inlinestatic inline
9798sip_proxy_authenticate_t *sip_proxy_authenticate_copy(su_home_t *home, sip_proxy_authenticate_t const *hdr)
9799{
9800 return (sip_proxy_authenticate_t *)
9801 msg_header_copy_as(home, sip_proxy_authenticate_class, (msg_header_t const *)hdr);
9802}
9803#endif
9804
9805/**Make a @ref sip_proxy_authenticate "Proxy-Authenticate header" structure #sip_proxy_authenticate_t.
9806 *
9807 * The function sip_proxy_authenticate_make() makes a new
9808 * #sip_proxy_authenticate_t header structure. It allocates a new
9809 * header structure, and decodes the string @a s as the
9810 * value of the structure.
9811 *
9812 * @param home memory home used to allocate new header structure.
9813 * @param s string to be decoded as value of the new header structure
9814 *
9815 * @return
9816 * A pointer to newly maked #sip_proxy_authenticate_t header structure, or NULL upon an
9817 * error.
9818 *
9819 */
9820#if SU_HAVE_INLINE1
9821su_inlinestatic inline
9822#endif
9823sip_proxy_authenticate_t *sip_proxy_authenticate_make(su_home_t *home, char const *s)
9824 __attribute__((__malloc__));
9825
9826#if SU_HAVE_INLINE1
9827su_inlinestatic inline sip_proxy_authenticate_t *sip_proxy_authenticate_make(su_home_t *home, char const *s)
9828{
9829 return (sip_proxy_authenticate_t *)sip_header_make(home, sip_proxy_authenticate_class, s)((sip_header_t *)msg_header_make((home), (sip_proxy_authenticate_class
), (s)))
;
9830}
9831#endif
9832
9833/**Make a @ref sip_proxy_authenticate "Proxy-Authenticate header" from formatting result.
9834 *
9835 * Make a new #sip_proxy_authenticate_t object using formatting result as its value.
9836 * The function first prints the arguments according to the format @a fmt
9837 * specified. Then it allocates a new header structure, and parses the
9838 * formatting result to the structure #sip_proxy_authenticate_t.
9839 *
9840 * @param home memory home used to allocate new header structure.
9841 * @param fmt string used as a printf()-style format
9842 * @param ... argument list for format
9843 *
9844 * @return
9845 * A pointer to newly
9846 * makes header structure, or NULL upon an error.
9847 *
9848 * @HIDE
9849 *
9850 */
9851#if SU_HAVE_INLINE1
9852su_inlinestatic inline
9853#endif
9854sip_proxy_authenticate_t *sip_proxy_authenticate_format(su_home_t *home, char const *fmt, ...)
9855 __attribute__((__malloc__, __format__ (printf, 2, 3)));
9856
9857#if SU_HAVE_INLINE1
9858su_inlinestatic inline sip_proxy_authenticate_t *sip_proxy_authenticate_format(su_home_t *home, char const *fmt, ...)
9859{
9860 sip_header_t *h;
9861 va_list ap;
9862
9863 va_start(ap, fmt)__builtin_va_start(ap, fmt);
9864 h = sip_header_vformat(home, sip_proxy_authenticate_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_proxy_authenticate_class
), (fmt), (ap)))
;
9865 va_end(ap)__builtin_va_end(ap);
9866
9867 return (sip_proxy_authenticate_t *)h;
9868}
9869#endif
9870
9871/** @} */
9872
9873/**@addtogroup sip_proxy_authentication_info
9874 * @{
9875 */
9876
9877/** Parse a SIP @ref sip_proxy_authentication_info "Proxy-Authentication-Info header". @internal */
9878SOFIAPUBFUN issize_t sip_proxy_authentication_info_d(su_home_t *, msg_header_t *,
9879 char *s, isize_t slen);
9880
9881/** Print a SIP @ref sip_proxy_authentication_info "Proxy-Authentication-Info header". @internal */
9882SOFIAPUBFUN issize_t sip_proxy_authentication_info_e(char b[], isize_t bsiz,
9883 msg_header_t const *h, int flags);
9884
9885/**Access a SIP @ref sip_proxy_authentication_info "Proxy-Authentication-Info header"
9886 * structure #sip_proxy_authentication_info_t from #sip_t.
9887 *
9888 */
9889#define sip_proxy_authentication_info(sip)((sip_proxy_authentication_info_t *)msg_header_access((msg_pub_t
*)(sip), sip_proxy_authentication_info_class))
\
9890 ((sip_proxy_authentication_info_t *)msg_header_access((msg_pub_t*)(sip), sip_proxy_authentication_info_class))
9891
9892/**Initializer for structure #sip_proxy_authentication_info_t.
9893 *
9894 * A static #sip_proxy_authentication_info_t structure for
9895 * @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" must be initialized with
9896 * the SIP_PROXY_AUTHENTICATION_INFO_INIT() macro.
9897 * For instance,
9898 * @code
9899 *
9900 * sip_proxy_authentication_info_t sip_proxy_authentication_info = SIP_PROXY_AUTHENTICATION_INFO_INIT;
9901 *
9902 * @endcode
9903 * @HI
9904 *
9905 */
9906#define SIP_PROXY_AUTHENTICATION_INFO_INIT(){{{ 0, 0, sip_proxy_authentication_info_class }}} SIP_HDR_INIT(proxy_authentication_info){{{ 0, 0, sip_proxy_authentication_info_class }}}
9907
9908/**Initialize a structure #sip_proxy_authentication_info_t.
9909 *
9910 * An #sip_proxy_authentication_info_t structure for
9911 * @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" can be initialized with the
9912 * sip_proxy_authentication_info_init() function/macro. For instance,
9913 * @code
9914 *
9915 * sip_proxy_authentication_info_t sip_proxy_authentication_info;
9916 *
9917 * sip_proxy_authentication_info_init(&sip_proxy_authentication_info);
9918 *
9919 * @endcode
9920 * @HI
9921 *
9922 */
9923#if SU_HAVE_INLINE1
9924su_inlinestatic inline sip_proxy_authentication_info_t *sip_proxy_authentication_info_init(sip_proxy_authentication_info_t x[1])
9925{
9926 return SIP_HEADER_INIT(x, sip_proxy_authentication_info_class, sizeof(sip_proxy_authentication_info_t))((void)memset((x), 0, (sizeof(sip_proxy_authentication_info_t
))), (void)(((sip_common_t *)(x))->h_class = (sip_proxy_authentication_info_class
)), (x))
;
9927}
9928#else
9929#define sip_proxy_authentication_info_init(x) \
9930 SIP_HEADER_INIT(x, sip_proxy_authentication_info_class, sizeof(sip_proxy_authentication_info_t))((void)memset((x), 0, (sizeof(sip_proxy_authentication_info_t
))), (void)(((sip_common_t *)(x))->h_class = (sip_proxy_authentication_info_class
)), (x))
9931#endif
9932
9933/**Test if header object is instance of #sip_proxy_authentication_info_t.
9934 *
9935 * Check if the header class is an instance of
9936 * @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" object and return true (nonzero),
9937 * otherwise return false (zero).
9938 *
9939 * @param header pointer to the header structure to be tested
9940 *
9941 * @retval 1 (true) if the @a header is an instance of header proxy_authentication_info
9942 * @retval 0 (false) otherwise
9943 *
9944 */
9945#if SU_HAVE_INLINE1
9946su_inlinestatic inline int sip_is_proxy_authentication_info(sip_header_t const *header)
9947{
9948 return header && header->sh_classsh_common->h_class->hc_hash == sip_proxy_authentication_info_hash;
9949}
9950#else
9951int sip_is_proxy_authentication_info(sip_header_t const *header);
9952#endif
9953
9954#define sip_proxy_authentication_info_p(h)sip_is_proxy_authentication_info((h)) sip_is_proxy_authentication_info((h))
9955
9956
9957/**Duplicate a list of @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" header structures #sip_proxy_authentication_info_t.
9958 *
9959 * Duplicate a header
9960 * structure @a hdr. If the header structure @a hdr
9961 * contains a reference (@c hdr->x_next) to a list of
9962 * headers, all the headers in the list are duplicated, too.
9963 *
9964 * @param home memory home used to allocate new structure
9965 * @param hdr header structure to be duplicated
9966 *
9967 * When duplicating, all parameter lists and non-constant
9968 * strings attached to the header are copied, too. The
9969 * function uses given memory @a home to allocate all the
9970 * memory areas used to copy the header.
9971 *
9972 * @par Example
9973 * @code
9974 *
9975 * proxy_authentication_info = sip_proxy_authentication_info_dup(home, sip->sip_proxy_authentication_info);
9976 *
9977 * @endcode
9978 *
9979 * @return
9980 * A pointer to the
9981 * newly duplicated #sip_proxy_authentication_info_t header structure, or NULL
9982 * upon an error.
9983 *
9984 */
9985#if SU_HAVE_INLINE1
9986su_inlinestatic inline
9987#endif
9988sip_proxy_authentication_info_t *sip_proxy_authentication_info_dup(su_home_t *home, sip_proxy_authentication_info_t const *hdr)
9989 __attribute__((__malloc__));
9990
9991#if SU_HAVE_INLINE1
9992su_inlinestatic inline
9993sip_proxy_authentication_info_t *sip_proxy_authentication_info_dup(su_home_t *home, sip_proxy_authentication_info_t const *hdr)
9994{
9995 return (sip_proxy_authentication_info_t *)
9996 msg_header_dup_as(home, sip_proxy_authentication_info_class, (msg_header_t const *)hdr);
9997}
9998#endif
9999
10000/**Copy a list of @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" header structures #sip_proxy_authentication_info_t.
10001 *
10002 * The function sip_proxy_authentication_info_copy() copies a header structure @a
10003 * hdr. If the header structure @a hdr contains a reference (@c
10004 * hdr->h_next) to a list of headers, all the headers in that
10005 * list are copied, too. The function uses given memory @a home
10006 * to allocate all the memory areas used to copy the list of header
10007 * structure @a hdr.
10008 *
10009 * @param home memory home used to allocate new structure
10010 * @param hdr pointer to the header structure to be copied
10011 *
10012 * When copying, only the header structure and parameter lists attached to
10013 * it are duplicated. The new header structure retains all the references to
10014 * the strings within the old @a hdr header, including the encoding of the
10015 * old header, if present.
10016 *
10017 * @par Example
10018 * @code
10019 *
10020 * proxy_authentication_info = sip_proxy_authentication_info_copy(home, sip->sip_proxy_authentication_info);
10021 *
10022 * @endcode
10023 *
10024 * @return
10025 * A pointer to newly copied header structure, or NULL upon an error.
10026 *
10027 */
10028#if SU_HAVE_INLINE1
10029su_inlinestatic inline
10030#endif
10031sip_proxy_authentication_info_t *sip_proxy_authentication_info_copy(su_home_t *home, sip_proxy_authentication_info_t const *hdr)
10032 __attribute__((__malloc__));
10033
10034#if SU_HAVE_INLINE1
10035su_inlinestatic inline
10036sip_proxy_authentication_info_t *sip_proxy_authentication_info_copy(su_home_t *home, sip_proxy_authentication_info_t const *hdr)
10037{
10038 return (sip_proxy_authentication_info_t *)
10039 msg_header_copy_as(home, sip_proxy_authentication_info_class, (msg_header_t const *)hdr);
10040}
10041#endif
10042
10043/**Make a @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" structure #sip_proxy_authentication_info_t.
10044 *
10045 * The function sip_proxy_authentication_info_make() makes a new
10046 * #sip_proxy_authentication_info_t header structure. It allocates a new
10047 * header structure, and decodes the string @a s as the
10048 * value of the structure.
10049 *
10050 * @param home memory home used to allocate new header structure.
10051 * @param s string to be decoded as value of the new header structure
10052 *
10053 * @return
10054 * A pointer to newly maked #sip_proxy_authentication_info_t header structure, or NULL upon an
10055 * error.
10056 *
10057 */
10058#if SU_HAVE_INLINE1
10059su_inlinestatic inline
10060#endif
10061sip_proxy_authentication_info_t *sip_proxy_authentication_info_make(su_home_t *home, char const *s)
10062 __attribute__((__malloc__));
10063
10064#if SU_HAVE_INLINE1
10065su_inlinestatic inline sip_proxy_authentication_info_t *sip_proxy_authentication_info_make(su_home_t *home, char const *s)
10066{
10067 return (sip_proxy_authentication_info_t *)sip_header_make(home, sip_proxy_authentication_info_class, s)((sip_header_t *)msg_header_make((home), (sip_proxy_authentication_info_class
), (s)))
;
10068}
10069#endif
10070
10071/**Make a @ref sip_proxy_authentication_info "Proxy-Authentication-Info header" from formatting result.
10072 *
10073 * Make a new #sip_proxy_authentication_info_t object using formatting result as its value.
10074 * The function first prints the arguments according to the format @a fmt
10075 * specified. Then it allocates a new header structure, and parses the
10076 * formatting result to the structure #sip_proxy_authentication_info_t.
10077 *
10078 * @param home memory home used to allocate new header structure.
10079 * @param fmt string used as a printf()-style format
10080 * @param ... argument list for format
10081 *
10082 * @return
10083 * A pointer to newly
10084 * makes header structure, or NULL upon an error.
10085 *
10086 * @HIDE
10087 *
10088 */
10089#if SU_HAVE_INLINE1
10090su_inlinestatic inline
10091#endif
10092sip_proxy_authentication_info_t *sip_proxy_authentication_info_format(su_home_t *home, char const *fmt, ...)
10093 __attribute__((__malloc__, __format__ (printf, 2, 3)));
10094
10095#if SU_HAVE_INLINE1
10096su_inlinestatic inline sip_proxy_authentication_info_t *sip_proxy_authentication_info_format(su_home_t *home, char const *fmt, ...)
10097{
10098 sip_header_t *h;
10099 va_list ap;
10100
10101 va_start(ap, fmt)__builtin_va_start(ap, fmt);
10102 h = sip_header_vformat(home, sip_proxy_authentication_info_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_proxy_authentication_info_class
), (fmt), (ap)))
;
10103 va_end(ap)__builtin_va_end(ap);
10104
10105 return (sip_proxy_authentication_info_t *)h;
10106}
10107#endif
10108
10109/** @} */
10110
10111/**@addtogroup sip_proxy_authorization
10112 * @{
10113 */
10114
10115/** Parse a SIP @ref sip_proxy_authorization "Proxy-Authorization header". @internal */
10116SOFIAPUBFUN issize_t sip_proxy_authorization_d(su_home_t *, msg_header_t *,
10117 char *s, isize_t slen);
10118
10119/** Print a SIP @ref sip_proxy_authorization "Proxy-Authorization header". @internal */
10120SOFIAPUBFUN issize_t sip_proxy_authorization_e(char b[], isize_t bsiz,
10121 msg_header_t const *h, int flags);
10122
10123/**Access a SIP @ref sip_proxy_authorization "Proxy-Authorization header"
10124 * structure #sip_proxy_authorization_t from #sip_t.
10125 *
10126 */
10127#define sip_proxy_authorization(sip)((sip_proxy_authorization_t *)msg_header_access((msg_pub_t*)(
sip), sip_proxy_authorization_class))
\
10128 ((sip_proxy_authorization_t *)msg_header_access((msg_pub_t*)(sip), sip_proxy_authorization_class))
10129
10130/**Initializer for structure #sip_proxy_authorization_t.
10131 *
10132 * A static #sip_proxy_authorization_t structure for
10133 * @ref sip_proxy_authorization "Proxy-Authorization header" must be initialized with
10134 * the SIP_PROXY_AUTHORIZATION_INIT() macro.
10135 * For instance,
10136 * @code
10137 *
10138 * sip_proxy_authorization_t sip_proxy_authorization = SIP_PROXY_AUTHORIZATION_INIT;
10139 *
10140 * @endcode
10141 * @HI
10142 *
10143 */
10144#define SIP_PROXY_AUTHORIZATION_INIT(){{{ 0, 0, sip_proxy_authorization_class }}} SIP_HDR_INIT(proxy_authorization){{{ 0, 0, sip_proxy_authorization_class }}}
10145
10146/**Initialize a structure #sip_proxy_authorization_t.
10147 *
10148 * An #sip_proxy_authorization_t structure for
10149 * @ref sip_proxy_authorization "Proxy-Authorization header" can be initialized with the
10150 * sip_proxy_authorization_init() function/macro. For instance,
10151 * @code
10152 *
10153 * sip_proxy_authorization_t sip_proxy_authorization;
10154 *
10155 * sip_proxy_authorization_init(&sip_proxy_authorization);
10156 *
10157 * @endcode
10158 * @HI
10159 *
10160 */
10161#if SU_HAVE_INLINE1
10162su_inlinestatic inline sip_proxy_authorization_t *sip_proxy_authorization_init(sip_proxy_authorization_t x[1])
10163{
10164 return SIP_HEADER_INIT(x, sip_proxy_authorization_class, sizeof(sip_proxy_authorization_t))((void)memset((x), 0, (sizeof(sip_proxy_authorization_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_proxy_authorization_class
)), (x))
;
10165}
10166#else
10167#define sip_proxy_authorization_init(x) \
10168 SIP_HEADER_INIT(x, sip_proxy_authorization_class, sizeof(sip_proxy_authorization_t))((void)memset((x), 0, (sizeof(sip_proxy_authorization_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_proxy_authorization_class
)), (x))
10169#endif
10170
10171/**Test if header object is instance of #sip_proxy_authorization_t.
10172 *
10173 * Check if the header class is an instance of
10174 * @ref sip_proxy_authorization "Proxy-Authorization header" object and return true (nonzero),
10175 * otherwise return false (zero).
10176 *
10177 * @param header pointer to the header structure to be tested
10178 *
10179 * @retval 1 (true) if the @a header is an instance of header proxy_authorization
10180 * @retval 0 (false) otherwise
10181 *
10182 */
10183#if SU_HAVE_INLINE1
10184su_inlinestatic inline int sip_is_proxy_authorization(sip_header_t const *header)
10185{
10186 return header && header->sh_classsh_common->h_class->hc_hash == sip_proxy_authorization_hash;
10187}
10188#else
10189int sip_is_proxy_authorization(sip_header_t const *header);
10190#endif
10191
10192#define sip_proxy_authorization_p(h)sip_is_proxy_authorization((h)) sip_is_proxy_authorization((h))
10193
10194
10195/**Duplicate a list of @ref sip_proxy_authorization "Proxy-Authorization header" header structures #sip_proxy_authorization_t.
10196 *
10197 * Duplicate a header
10198 * structure @a hdr. If the header structure @a hdr
10199 * contains a reference (@c hdr->x_next) to a list of
10200 * headers, all the headers in the list are duplicated, too.
10201 *
10202 * @param home memory home used to allocate new structure
10203 * @param hdr header structure to be duplicated
10204 *
10205 * When duplicating, all parameter lists and non-constant
10206 * strings attached to the header are copied, too. The
10207 * function uses given memory @a home to allocate all the
10208 * memory areas used to copy the header.
10209 *
10210 * @par Example
10211 * @code
10212 *
10213 * proxy_authorization = sip_proxy_authorization_dup(home, sip->sip_proxy_authorization);
10214 *
10215 * @endcode
10216 *
10217 * @return
10218 * A pointer to the
10219 * newly duplicated #sip_proxy_authorization_t header structure, or NULL
10220 * upon an error.
10221 *
10222 */
10223#if SU_HAVE_INLINE1
10224su_inlinestatic inline
10225#endif
10226sip_proxy_authorization_t *sip_proxy_authorization_dup(su_home_t *home, sip_proxy_authorization_t const *hdr)
10227 __attribute__((__malloc__));
10228
10229#if SU_HAVE_INLINE1
10230su_inlinestatic inline
10231sip_proxy_authorization_t *sip_proxy_authorization_dup(su_home_t *home, sip_proxy_authorization_t const *hdr)
10232{
10233 return (sip_proxy_authorization_t *)
10234 msg_header_dup_as(home, sip_proxy_authorization_class, (msg_header_t const *)hdr);
10235}
10236#endif
10237
10238/**Copy a list of @ref sip_proxy_authorization "Proxy-Authorization header" header structures #sip_proxy_authorization_t.
10239 *
10240 * The function sip_proxy_authorization_copy() copies a header structure @a
10241 * hdr. If the header structure @a hdr contains a reference (@c
10242 * hdr->h_next) to a list of headers, all the headers in that
10243 * list are copied, too. The function uses given memory @a home
10244 * to allocate all the memory areas used to copy the list of header
10245 * structure @a hdr.
10246 *
10247 * @param home memory home used to allocate new structure
10248 * @param hdr pointer to the header structure to be copied
10249 *
10250 * When copying, only the header structure and parameter lists attached to
10251 * it are duplicated. The new header structure retains all the references to
10252 * the strings within the old @a hdr header, including the encoding of the
10253 * old header, if present.
10254 *
10255 * @par Example
10256 * @code
10257 *
10258 * proxy_authorization = sip_proxy_authorization_copy(home, sip->sip_proxy_authorization);
10259 *
10260 * @endcode
10261 *
10262 * @return
10263 * A pointer to newly copied header structure, or NULL upon an error.
10264 *
10265 */
10266#if SU_HAVE_INLINE1
10267su_inlinestatic inline
10268#endif
10269sip_proxy_authorization_t *sip_proxy_authorization_copy(su_home_t *home, sip_proxy_authorization_t const *hdr)
10270 __attribute__((__malloc__));
10271
10272#if SU_HAVE_INLINE1
10273su_inlinestatic inline
10274sip_proxy_authorization_t *sip_proxy_authorization_copy(su_home_t *home, sip_proxy_authorization_t const *hdr)
10275{
10276 return (sip_proxy_authorization_t *)
10277 msg_header_copy_as(home, sip_proxy_authorization_class, (msg_header_t const *)hdr);
10278}
10279#endif
10280
10281/**Make a @ref sip_proxy_authorization "Proxy-Authorization header" structure #sip_proxy_authorization_t.
10282 *
10283 * The function sip_proxy_authorization_make() makes a new
10284 * #sip_proxy_authorization_t header structure. It allocates a new
10285 * header structure, and decodes the string @a s as the
10286 * value of the structure.
10287 *
10288 * @param home memory home used to allocate new header structure.
10289 * @param s string to be decoded as value of the new header structure
10290 *
10291 * @return
10292 * A pointer to newly maked #sip_proxy_authorization_t header structure, or NULL upon an
10293 * error.
10294 *
10295 */
10296#if SU_HAVE_INLINE1
10297su_inlinestatic inline
10298#endif
10299sip_proxy_authorization_t *sip_proxy_authorization_make(su_home_t *home, char const *s)
10300 __attribute__((__malloc__));
10301
10302#if SU_HAVE_INLINE1
10303su_inlinestatic inline sip_proxy_authorization_t *sip_proxy_authorization_make(su_home_t *home, char const *s)
10304{
10305 return (sip_proxy_authorization_t *)sip_header_make(home, sip_proxy_authorization_class, s)((sip_header_t *)msg_header_make((home), (sip_proxy_authorization_class
), (s)))
;
10306}
10307#endif
10308
10309/**Make a @ref sip_proxy_authorization "Proxy-Authorization header" from formatting result.
10310 *
10311 * Make a new #sip_proxy_authorization_t object using formatting result as its value.
10312 * The function first prints the arguments according to the format @a fmt
10313 * specified. Then it allocates a new header structure, and parses the
10314 * formatting result to the structure #sip_proxy_authorization_t.
10315 *
10316 * @param home memory home used to allocate new header structure.
10317 * @param fmt string used as a printf()-style format
10318 * @param ... argument list for format
10319 *
10320 * @return
10321 * A pointer to newly
10322 * makes header structure, or NULL upon an error.
10323 *
10324 * @HIDE
10325 *
10326 */
10327#if SU_HAVE_INLINE1
10328su_inlinestatic inline
10329#endif
10330sip_proxy_authorization_t *sip_proxy_authorization_format(su_home_t *home, char const *fmt, ...)
10331 __attribute__((__malloc__, __format__ (printf, 2, 3)));
10332
10333#if SU_HAVE_INLINE1
10334su_inlinestatic inline sip_proxy_authorization_t *sip_proxy_authorization_format(su_home_t *home, char const *fmt, ...)
10335{
10336 sip_header_t *h;
10337 va_list ap;
10338
10339 va_start(ap, fmt)__builtin_va_start(ap, fmt);
10340 h = sip_header_vformat(home, sip_proxy_authorization_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_proxy_authorization_class
), (fmt), (ap)))
;
10341 va_end(ap)__builtin_va_end(ap);
10342
10343 return (sip_proxy_authorization_t *)h;
10344}
10345#endif
10346
10347/** @} */
10348
10349/**@addtogroup sip_authorization
10350 * @{
10351 */
10352
10353/** Parse a SIP @ref sip_authorization "Authorization header". @internal */
10354SOFIAPUBFUN issize_t sip_authorization_d(su_home_t *, msg_header_t *,
10355 char *s, isize_t slen);
10356
10357/** Print a SIP @ref sip_authorization "Authorization header". @internal */
10358SOFIAPUBFUN issize_t sip_authorization_e(char b[], isize_t bsiz,
10359 msg_header_t const *h, int flags);
10360
10361/**Access a SIP @ref sip_authorization "Authorization header"
10362 * structure #sip_authorization_t from #sip_t.
10363 *
10364 */
10365#define sip_authorization(sip)((sip_authorization_t *)msg_header_access((msg_pub_t*)(sip), sip_authorization_class
))
\
10366 ((sip_authorization_t *)msg_header_access((msg_pub_t*)(sip), sip_authorization_class))
10367
10368/**Initializer for structure #sip_authorization_t.
10369 *
10370 * A static #sip_authorization_t structure for
10371 * @ref sip_authorization "Authorization header" must be initialized with
10372 * the SIP_AUTHORIZATION_INIT() macro.
10373 * For instance,
10374 * @code
10375 *
10376 * sip_authorization_t sip_authorization = SIP_AUTHORIZATION_INIT;
10377 *
10378 * @endcode
10379 * @HI
10380 *
10381 */
10382#define SIP_AUTHORIZATION_INIT(){{{ 0, 0, sip_authorization_class }}} SIP_HDR_INIT(authorization){{{ 0, 0, sip_authorization_class }}}
10383
10384/**Initialize a structure #sip_authorization_t.
10385 *
10386 * An #sip_authorization_t structure for
10387 * @ref sip_authorization "Authorization header" can be initialized with the
10388 * sip_authorization_init() function/macro. For instance,
10389 * @code
10390 *
10391 * sip_authorization_t sip_authorization;
10392 *
10393 * sip_authorization_init(&sip_authorization);
10394 *
10395 * @endcode
10396 * @HI
10397 *
10398 */
10399#if SU_HAVE_INLINE1
10400su_inlinestatic inline sip_authorization_t *sip_authorization_init(sip_authorization_t x[1])
10401{
10402 return SIP_HEADER_INIT(x, sip_authorization_class, sizeof(sip_authorization_t))((void)memset((x), 0, (sizeof(sip_authorization_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_authorization_class)
), (x))
;
10403}
10404#else
10405#define sip_authorization_init(x) \
10406 SIP_HEADER_INIT(x, sip_authorization_class, sizeof(sip_authorization_t))((void)memset((x), 0, (sizeof(sip_authorization_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_authorization_class)
), (x))
10407#endif
10408
10409/**Test if header object is instance of #sip_authorization_t.
10410 *
10411 * Check if the header class is an instance of
10412 * @ref sip_authorization "Authorization header" object and return true (nonzero),
10413 * otherwise return false (zero).
10414 *
10415 * @param header pointer to the header structure to be tested
10416 *
10417 * @retval 1 (true) if the @a header is an instance of header authorization
10418 * @retval 0 (false) otherwise
10419 *
10420 */
10421#if SU_HAVE_INLINE1
10422su_inlinestatic inline int sip_is_authorization(sip_header_t const *header)
10423{
10424 return header && header->sh_classsh_common->h_class->hc_hash == sip_authorization_hash;
10425}
10426#else
10427int sip_is_authorization(sip_header_t const *header);
10428#endif
10429
10430#define sip_authorization_p(h)sip_is_authorization((h)) sip_is_authorization((h))
10431
10432
10433/**Duplicate a list of @ref sip_authorization "Authorization header" header structures #sip_authorization_t.
10434 *
10435 * Duplicate a header
10436 * structure @a hdr. If the header structure @a hdr
10437 * contains a reference (@c hdr->x_next) to a list of
10438 * headers, all the headers in the list are duplicated, too.
10439 *
10440 * @param home memory home used to allocate new structure
10441 * @param hdr header structure to be duplicated
10442 *
10443 * When duplicating, all parameter lists and non-constant
10444 * strings attached to the header are copied, too. The
10445 * function uses given memory @a home to allocate all the
10446 * memory areas used to copy the header.
10447 *
10448 * @par Example
10449 * @code
10450 *
10451 * authorization = sip_authorization_dup(home, sip->sip_authorization);
10452 *
10453 * @endcode
10454 *
10455 * @return
10456 * A pointer to the
10457 * newly duplicated #sip_authorization_t header structure, or NULL
10458 * upon an error.
10459 *
10460 */
10461#if SU_HAVE_INLINE1
10462su_inlinestatic inline
10463#endif
10464sip_authorization_t *sip_authorization_dup(su_home_t *home, sip_authorization_t const *hdr)
10465 __attribute__((__malloc__));
10466
10467#if SU_HAVE_INLINE1
10468su_inlinestatic inline
10469sip_authorization_t *sip_authorization_dup(su_home_t *home, sip_authorization_t const *hdr)
10470{
10471 return (sip_authorization_t *)
10472 msg_header_dup_as(home, sip_authorization_class, (msg_header_t const *)hdr);
10473}
10474#endif
10475
10476/**Copy a list of @ref sip_authorization "Authorization header" header structures #sip_authorization_t.
10477 *
10478 * The function sip_authorization_copy() copies a header structure @a
10479 * hdr. If the header structure @a hdr contains a reference (@c
10480 * hdr->h_next) to a list of headers, all the headers in that
10481 * list are copied, too. The function uses given memory @a home
10482 * to allocate all the memory areas used to copy the list of header
10483 * structure @a hdr.
10484 *
10485 * @param home memory home used to allocate new structure
10486 * @param hdr pointer to the header structure to be copied
10487 *
10488 * When copying, only the header structure and parameter lists attached to
10489 * it are duplicated. The new header structure retains all the references to
10490 * the strings within the old @a hdr header, including the encoding of the
10491 * old header, if present.
10492 *
10493 * @par Example
10494 * @code
10495 *
10496 * authorization = sip_authorization_copy(home, sip->sip_authorization);
10497 *
10498 * @endcode
10499 *
10500 * @return
10501 * A pointer to newly copied header structure, or NULL upon an error.
10502 *
10503 */
10504#if SU_HAVE_INLINE1
10505su_inlinestatic inline
10506#endif
10507sip_authorization_t *sip_authorization_copy(su_home_t *home, sip_authorization_t const *hdr)
10508 __attribute__((__malloc__));
10509
10510#if SU_HAVE_INLINE1
10511su_inlinestatic inline
10512sip_authorization_t *sip_authorization_copy(su_home_t *home, sip_authorization_t const *hdr)
10513{
10514 return (sip_authorization_t *)
10515 msg_header_copy_as(home, sip_authorization_class, (msg_header_t const *)hdr);
10516}
10517#endif
10518
10519/**Make a @ref sip_authorization "Authorization header" structure #sip_authorization_t.
10520 *
10521 * The function sip_authorization_make() makes a new
10522 * #sip_authorization_t header structure. It allocates a new
10523 * header structure, and decodes the string @a s as the
10524 * value of the structure.
10525 *
10526 * @param home memory home used to allocate new header structure.
10527 * @param s string to be decoded as value of the new header structure
10528 *
10529 * @return
10530 * A pointer to newly maked #sip_authorization_t header structure, or NULL upon an
10531 * error.
10532 *
10533 */
10534#if SU_HAVE_INLINE1
10535su_inlinestatic inline
10536#endif
10537sip_authorization_t *sip_authorization_make(su_home_t *home, char const *s)
10538 __attribute__((__malloc__));
10539
10540#if SU_HAVE_INLINE1
10541su_inlinestatic inline sip_authorization_t *sip_authorization_make(su_home_t *home, char const *s)
10542{
10543 return (sip_authorization_t *)sip_header_make(home, sip_authorization_class, s)((sip_header_t *)msg_header_make((home), (sip_authorization_class
), (s)))
;
10544}
10545#endif
10546
10547/**Make a @ref sip_authorization "Authorization header" from formatting result.
10548 *
10549 * Make a new #sip_authorization_t object using formatting result as its value.
10550 * The function first prints the arguments according to the format @a fmt
10551 * specified. Then it allocates a new header structure, and parses the
10552 * formatting result to the structure #sip_authorization_t.
10553 *
10554 * @param home memory home used to allocate new header structure.
10555 * @param fmt string used as a printf()-style format
10556 * @param ... argument list for format
10557 *
10558 * @return
10559 * A pointer to newly
10560 * makes header structure, or NULL upon an error.
10561 *
10562 * @HIDE
10563 *
10564 */
10565#if SU_HAVE_INLINE1
10566su_inlinestatic inline
10567#endif
10568sip_authorization_t *sip_authorization_format(su_home_t *home, char const *fmt, ...)
10569 __attribute__((__malloc__, __format__ (printf, 2, 3)));
10570
10571#if SU_HAVE_INLINE1
10572su_inlinestatic inline sip_authorization_t *sip_authorization_format(su_home_t *home, char const *fmt, ...)
10573{
10574 sip_header_t *h;
10575 va_list ap;
10576
10577 va_start(ap, fmt)__builtin_va_start(ap, fmt);
10578 h = sip_header_vformat(home, sip_authorization_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_authorization_class
), (fmt), (ap)))
;
10579 va_end(ap)__builtin_va_end(ap);
10580
10581 return (sip_authorization_t *)h;
10582}
10583#endif
10584
10585/** @} */
10586
10587/**@addtogroup sip_www_authenticate
10588 * @{
10589 */
10590
10591/** Parse a SIP @ref sip_www_authenticate "WWW-Authenticate header". @internal */
10592SOFIAPUBFUN issize_t sip_www_authenticate_d(su_home_t *, msg_header_t *,
10593 char *s, isize_t slen);
10594
10595/** Print a SIP @ref sip_www_authenticate "WWW-Authenticate header". @internal */
10596SOFIAPUBFUN issize_t sip_www_authenticate_e(char b[], isize_t bsiz,
10597 msg_header_t const *h, int flags);
10598
10599/**Access a SIP @ref sip_www_authenticate "WWW-Authenticate header"
10600 * structure #sip_www_authenticate_t from #sip_t.
10601 *
10602 */
10603#define sip_www_authenticate(sip)((sip_www_authenticate_t *)msg_header_access((msg_pub_t*)(sip
), sip_www_authenticate_class))
\
10604 ((sip_www_authenticate_t *)msg_header_access((msg_pub_t*)(sip), sip_www_authenticate_class))
10605
10606/**Initializer for structure #sip_www_authenticate_t.
10607 *
10608 * A static #sip_www_authenticate_t structure for
10609 * @ref sip_www_authenticate "WWW-Authenticate header" must be initialized with
10610 * the SIP_WWW_AUTHENTICATE_INIT() macro.
10611 * For instance,
10612 * @code
10613 *
10614 * sip_www_authenticate_t sip_www_authenticate = SIP_WWW_AUTHENTICATE_INIT;
10615 *
10616 * @endcode
10617 * @HI
10618 *
10619 */
10620#define SIP_WWW_AUTHENTICATE_INIT(){{{ 0, 0, sip_www_authenticate_class }}} SIP_HDR_INIT(www_authenticate){{{ 0, 0, sip_www_authenticate_class }}}
10621
10622/**Initialize a structure #sip_www_authenticate_t.
10623 *
10624 * An #sip_www_authenticate_t structure for
10625 * @ref sip_www_authenticate "WWW-Authenticate header" can be initialized with the
10626 * sip_www_authenticate_init() function/macro. For instance,
10627 * @code
10628 *
10629 * sip_www_authenticate_t sip_www_authenticate;
10630 *
10631 * sip_www_authenticate_init(&sip_www_authenticate);
10632 *
10633 * @endcode
10634 * @HI
10635 *
10636 */
10637#if SU_HAVE_INLINE1
10638su_inlinestatic inline sip_www_authenticate_t *sip_www_authenticate_init(sip_www_authenticate_t x[1])
10639{
10640 return SIP_HEADER_INIT(x, sip_www_authenticate_class, sizeof(sip_www_authenticate_t))((void)memset((x), 0, (sizeof(sip_www_authenticate_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_www_authenticate_class
)), (x))
;
10641}
10642#else
10643#define sip_www_authenticate_init(x) \
10644 SIP_HEADER_INIT(x, sip_www_authenticate_class, sizeof(sip_www_authenticate_t))((void)memset((x), 0, (sizeof(sip_www_authenticate_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_www_authenticate_class
)), (x))
10645#endif
10646
10647/**Test if header object is instance of #sip_www_authenticate_t.
10648 *
10649 * Check if the header class is an instance of
10650 * @ref sip_www_authenticate "WWW-Authenticate header" object and return true (nonzero),
10651 * otherwise return false (zero).
10652 *
10653 * @param header pointer to the header structure to be tested
10654 *
10655 * @retval 1 (true) if the @a header is an instance of header www_authenticate
10656 * @retval 0 (false) otherwise
10657 *
10658 */
10659#if SU_HAVE_INLINE1
10660su_inlinestatic inline int sip_is_www_authenticate(sip_header_t const *header)
10661{
10662 return header && header->sh_classsh_common->h_class->hc_hash == sip_www_authenticate_hash;
10663}
10664#else
10665int sip_is_www_authenticate(sip_header_t const *header);
10666#endif
10667
10668#define sip_www_authenticate_p(h)sip_is_www_authenticate((h)) sip_is_www_authenticate((h))
10669
10670
10671/**Duplicate a list of @ref sip_www_authenticate "WWW-Authenticate header" header structures #sip_www_authenticate_t.
10672 *
10673 * Duplicate a header
10674 * structure @a hdr. If the header structure @a hdr
10675 * contains a reference (@c hdr->x_next) to a list of
10676 * headers, all the headers in the list are duplicated, too.
10677 *
10678 * @param home memory home used to allocate new structure
10679 * @param hdr header structure to be duplicated
10680 *
10681 * When duplicating, all parameter lists and non-constant
10682 * strings attached to the header are copied, too. The
10683 * function uses given memory @a home to allocate all the
10684 * memory areas used to copy the header.
10685 *
10686 * @par Example
10687 * @code
10688 *
10689 * www_authenticate = sip_www_authenticate_dup(home, sip->sip_www_authenticate);
10690 *
10691 * @endcode
10692 *
10693 * @return
10694 * A pointer to the
10695 * newly duplicated #sip_www_authenticate_t header structure, or NULL
10696 * upon an error.
10697 *
10698 */
10699#if SU_HAVE_INLINE1
10700su_inlinestatic inline
10701#endif
10702sip_www_authenticate_t *sip_www_authenticate_dup(su_home_t *home, sip_www_authenticate_t const *hdr)
10703 __attribute__((__malloc__));
10704
10705#if SU_HAVE_INLINE1
10706su_inlinestatic inline
10707sip_www_authenticate_t *sip_www_authenticate_dup(su_home_t *home, sip_www_authenticate_t const *hdr)
10708{
10709 return (sip_www_authenticate_t *)
10710 msg_header_dup_as(home, sip_www_authenticate_class, (msg_header_t const *)hdr);
10711}
10712#endif
10713
10714/**Copy a list of @ref sip_www_authenticate "WWW-Authenticate header" header structures #sip_www_authenticate_t.
10715 *
10716 * The function sip_www_authenticate_copy() copies a header structure @a
10717 * hdr. If the header structure @a hdr contains a reference (@c
10718 * hdr->h_next) to a list of headers, all the headers in that
10719 * list are copied, too. The function uses given memory @a home
10720 * to allocate all the memory areas used to copy the list of header
10721 * structure @a hdr.
10722 *
10723 * @param home memory home used to allocate new structure
10724 * @param hdr pointer to the header structure to be copied
10725 *
10726 * When copying, only the header structure and parameter lists attached to
10727 * it are duplicated. The new header structure retains all the references to
10728 * the strings within the old @a hdr header, including the encoding of the
10729 * old header, if present.
10730 *
10731 * @par Example
10732 * @code
10733 *
10734 * www_authenticate = sip_www_authenticate_copy(home, sip->sip_www_authenticate);
10735 *
10736 * @endcode
10737 *
10738 * @return
10739 * A pointer to newly copied header structure, or NULL upon an error.
10740 *
10741 */
10742#if SU_HAVE_INLINE1
10743su_inlinestatic inline
10744#endif
10745sip_www_authenticate_t *sip_www_authenticate_copy(su_home_t *home, sip_www_authenticate_t const *hdr)
10746 __attribute__((__malloc__));
10747
10748#if SU_HAVE_INLINE1
10749su_inlinestatic inline
10750sip_www_authenticate_t *sip_www_authenticate_copy(su_home_t *home, sip_www_authenticate_t const *hdr)
10751{
10752 return (sip_www_authenticate_t *)
10753 msg_header_copy_as(home, sip_www_authenticate_class, (msg_header_t const *)hdr);
10754}
10755#endif
10756
10757/**Make a @ref sip_www_authenticate "WWW-Authenticate header" structure #sip_www_authenticate_t.
10758 *
10759 * The function sip_www_authenticate_make() makes a new
10760 * #sip_www_authenticate_t header structure. It allocates a new
10761 * header structure, and decodes the string @a s as the
10762 * value of the structure.
10763 *
10764 * @param home memory home used to allocate new header structure.
10765 * @param s string to be decoded as value of the new header structure
10766 *
10767 * @return
10768 * A pointer to newly maked #sip_www_authenticate_t header structure, or NULL upon an
10769 * error.
10770 *
10771 */
10772#if SU_HAVE_INLINE1
10773su_inlinestatic inline
10774#endif
10775sip_www_authenticate_t *sip_www_authenticate_make(su_home_t *home, char const *s)
10776 __attribute__((__malloc__));
10777
10778#if SU_HAVE_INLINE1
10779su_inlinestatic inline sip_www_authenticate_t *sip_www_authenticate_make(su_home_t *home, char const *s)
10780{
10781 return (sip_www_authenticate_t *)sip_header_make(home, sip_www_authenticate_class, s)((sip_header_t *)msg_header_make((home), (sip_www_authenticate_class
), (s)))
;
10782}
10783#endif
10784
10785/**Make a @ref sip_www_authenticate "WWW-Authenticate header" from formatting result.
10786 *
10787 * Make a new #sip_www_authenticate_t object using formatting result as its value.
10788 * The function first prints the arguments according to the format @a fmt
10789 * specified. Then it allocates a new header structure, and parses the
10790 * formatting result to the structure #sip_www_authenticate_t.
10791 *
10792 * @param home memory home used to allocate new header structure.
10793 * @param fmt string used as a printf()-style format
10794 * @param ... argument list for format
10795 *
10796 * @return
10797 * A pointer to newly
10798 * makes header structure, or NULL upon an error.
10799 *
10800 * @HIDE
10801 *
10802 */
10803#if SU_HAVE_INLINE1
10804su_inlinestatic inline
10805#endif
10806sip_www_authenticate_t *sip_www_authenticate_format(su_home_t *home, char const *fmt, ...)
10807 __attribute__((__malloc__, __format__ (printf, 2, 3)));
10808
10809#if SU_HAVE_INLINE1
10810su_inlinestatic inline sip_www_authenticate_t *sip_www_authenticate_format(su_home_t *home, char const *fmt, ...)
10811{
10812 sip_header_t *h;
10813 va_list ap;
10814
10815 va_start(ap, fmt)__builtin_va_start(ap, fmt);
10816 h = sip_header_vformat(home, sip_www_authenticate_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_www_authenticate_class
), (fmt), (ap)))
;
10817 va_end(ap)__builtin_va_end(ap);
10818
10819 return (sip_www_authenticate_t *)h;
10820}
10821#endif
10822
10823/** @} */
10824
10825/**@addtogroup sip_authentication_info
10826 * @{
10827 */
10828
10829/** Parse a SIP @ref sip_authentication_info "Authentication-Info header". @internal */
10830SOFIAPUBFUN issize_t sip_authentication_info_d(su_home_t *, msg_header_t *,
10831 char *s, isize_t slen);
10832
10833/** Print a SIP @ref sip_authentication_info "Authentication-Info header". @internal */
10834SOFIAPUBFUN issize_t sip_authentication_info_e(char b[], isize_t bsiz,
10835 msg_header_t const *h, int flags);
10836
10837/**Access a SIP @ref sip_authentication_info "Authentication-Info header"
10838 * structure #sip_authentication_info_t from #sip_t.
10839 *
10840 */
10841#define sip_authentication_info(sip)((sip_authentication_info_t *)msg_header_access((msg_pub_t*)(
sip), sip_authentication_info_class))
\
10842 ((sip_authentication_info_t *)msg_header_access((msg_pub_t*)(sip), sip_authentication_info_class))
10843
10844/**Initializer for structure #sip_authentication_info_t.
10845 *
10846 * A static #sip_authentication_info_t structure for
10847 * @ref sip_authentication_info "Authentication-Info header" must be initialized with
10848 * the SIP_AUTHENTICATION_INFO_INIT() macro.
10849 * For instance,
10850 * @code
10851 *
10852 * sip_authentication_info_t sip_authentication_info = SIP_AUTHENTICATION_INFO_INIT;
10853 *
10854 * @endcode
10855 * @HI
10856 *
10857 */
10858#define SIP_AUTHENTICATION_INFO_INIT(){{{ 0, 0, sip_authentication_info_class }}} SIP_HDR_INIT(authentication_info){{{ 0, 0, sip_authentication_info_class }}}
10859
10860/**Initialize a structure #sip_authentication_info_t.
10861 *
10862 * An #sip_authentication_info_t structure for
10863 * @ref sip_authentication_info "Authentication-Info header" can be initialized with the
10864 * sip_authentication_info_init() function/macro. For instance,
10865 * @code
10866 *
10867 * sip_authentication_info_t sip_authentication_info;
10868 *
10869 * sip_authentication_info_init(&sip_authentication_info);
10870 *
10871 * @endcode
10872 * @HI
10873 *
10874 */
10875#if SU_HAVE_INLINE1
10876su_inlinestatic inline sip_authentication_info_t *sip_authentication_info_init(sip_authentication_info_t x[1])
10877{
10878 return SIP_HEADER_INIT(x, sip_authentication_info_class, sizeof(sip_authentication_info_t))((void)memset((x), 0, (sizeof(sip_authentication_info_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_authentication_info_class
)), (x))
;
10879}
10880#else
10881#define sip_authentication_info_init(x) \
10882 SIP_HEADER_INIT(x, sip_authentication_info_class, sizeof(sip_authentication_info_t))((void)memset((x), 0, (sizeof(sip_authentication_info_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_authentication_info_class
)), (x))
10883#endif
10884
10885/**Test if header object is instance of #sip_authentication_info_t.
10886 *
10887 * Check if the header class is an instance of
10888 * @ref sip_authentication_info "Authentication-Info header" object and return true (nonzero),
10889 * otherwise return false (zero).
10890 *
10891 * @param header pointer to the header structure to be tested
10892 *
10893 * @retval 1 (true) if the @a header is an instance of header authentication_info
10894 * @retval 0 (false) otherwise
10895 *
10896 */
10897#if SU_HAVE_INLINE1
10898su_inlinestatic inline int sip_is_authentication_info(sip_header_t const *header)
10899{
10900 return header && header->sh_classsh_common->h_class->hc_hash == sip_authentication_info_hash;
10901}
10902#else
10903int sip_is_authentication_info(sip_header_t const *header);
10904#endif
10905
10906#define sip_authentication_info_p(h)sip_is_authentication_info((h)) sip_is_authentication_info((h))
10907
10908
10909/**Duplicate a list of @ref sip_authentication_info "Authentication-Info header" header structures #sip_authentication_info_t.
10910 *
10911 * Duplicate a header
10912 * structure @a hdr. If the header structure @a hdr
10913 * contains a reference (@c hdr->x_next) to a list of
10914 * headers, all the headers in the list are duplicated, too.
10915 *
10916 * @param home memory home used to allocate new structure
10917 * @param hdr header structure to be duplicated
10918 *
10919 * When duplicating, all parameter lists and non-constant
10920 * strings attached to the header are copied, too. The
10921 * function uses given memory @a home to allocate all the
10922 * memory areas used to copy the header.
10923 *
10924 * @par Example
10925 * @code
10926 *
10927 * authentication_info = sip_authentication_info_dup(home, sip->sip_authentication_info);
10928 *
10929 * @endcode
10930 *
10931 * @return
10932 * A pointer to the
10933 * newly duplicated #sip_authentication_info_t header structure, or NULL
10934 * upon an error.
10935 *
10936 */
10937#if SU_HAVE_INLINE1
10938su_inlinestatic inline
10939#endif
10940sip_authentication_info_t *sip_authentication_info_dup(su_home_t *home, sip_authentication_info_t const *hdr)
10941 __attribute__((__malloc__));
10942
10943#if SU_HAVE_INLINE1
10944su_inlinestatic inline
10945sip_authentication_info_t *sip_authentication_info_dup(su_home_t *home, sip_authentication_info_t const *hdr)
10946{
10947 return (sip_authentication_info_t *)
10948 msg_header_dup_as(home, sip_authentication_info_class, (msg_header_t const *)hdr);
10949}
10950#endif
10951
10952/**Copy a list of @ref sip_authentication_info "Authentication-Info header" header structures #sip_authentication_info_t.
10953 *
10954 * The function sip_authentication_info_copy() copies a header structure @a
10955 * hdr. If the header structure @a hdr contains a reference (@c
10956 * hdr->h_next) to a list of headers, all the headers in that
10957 * list are copied, too. The function uses given memory @a home
10958 * to allocate all the memory areas used to copy the list of header
10959 * structure @a hdr.
10960 *
10961 * @param home memory home used to allocate new structure
10962 * @param hdr pointer to the header structure to be copied
10963 *
10964 * When copying, only the header structure and parameter lists attached to
10965 * it are duplicated. The new header structure retains all the references to
10966 * the strings within the old @a hdr header, including the encoding of the
10967 * old header, if present.
10968 *
10969 * @par Example
10970 * @code
10971 *
10972 * authentication_info = sip_authentication_info_copy(home, sip->sip_authentication_info);
10973 *
10974 * @endcode
10975 *
10976 * @return
10977 * A pointer to newly copied header structure, or NULL upon an error.
10978 *
10979 */
10980#if SU_HAVE_INLINE1
10981su_inlinestatic inline
10982#endif
10983sip_authentication_info_t *sip_authentication_info_copy(su_home_t *home, sip_authentication_info_t const *hdr)
10984 __attribute__((__malloc__));
10985
10986#if SU_HAVE_INLINE1
10987su_inlinestatic inline
10988sip_authentication_info_t *sip_authentication_info_copy(su_home_t *home, sip_authentication_info_t const *hdr)
10989{
10990 return (sip_authentication_info_t *)
10991 msg_header_copy_as(home, sip_authentication_info_class, (msg_header_t const *)hdr);
10992}
10993#endif
10994
10995/**Make a @ref sip_authentication_info "Authentication-Info header" structure #sip_authentication_info_t.
10996 *
10997 * The function sip_authentication_info_make() makes a new
10998 * #sip_authentication_info_t header structure. It allocates a new
10999 * header structure, and decodes the string @a s as the
11000 * value of the structure.
11001 *
11002 * @param home memory home used to allocate new header structure.
11003 * @param s string to be decoded as value of the new header structure
11004 *
11005 * @return
11006 * A pointer to newly maked #sip_authentication_info_t header structure, or NULL upon an
11007 * error.
11008 *
11009 */
11010#if SU_HAVE_INLINE1
11011su_inlinestatic inline
11012#endif
11013sip_authentication_info_t *sip_authentication_info_make(su_home_t *home, char const *s)
11014 __attribute__((__malloc__));
11015
11016#if SU_HAVE_INLINE1
11017su_inlinestatic inline sip_authentication_info_t *sip_authentication_info_make(su_home_t *home, char const *s)
11018{
11019 return (sip_authentication_info_t *)sip_header_make(home, sip_authentication_info_class, s)((sip_header_t *)msg_header_make((home), (sip_authentication_info_class
), (s)))
;
11020}
11021#endif
11022
11023/**Make a @ref sip_authentication_info "Authentication-Info header" from formatting result.
11024 *
11025 * Make a new #sip_authentication_info_t object using formatting result as its value.
11026 * The function first prints the arguments according to the format @a fmt
11027 * specified. Then it allocates a new header structure, and parses the
11028 * formatting result to the structure #sip_authentication_info_t.
11029 *
11030 * @param home memory home used to allocate new header structure.
11031 * @param fmt string used as a printf()-style format
11032 * @param ... argument list for format
11033 *
11034 * @return
11035 * A pointer to newly
11036 * makes header structure, or NULL upon an error.
11037 *
11038 * @HIDE
11039 *
11040 */
11041#if SU_HAVE_INLINE1
11042su_inlinestatic inline
11043#endif
11044sip_authentication_info_t *sip_authentication_info_format(su_home_t *home, char const *fmt, ...)
11045 __attribute__((__malloc__, __format__ (printf, 2, 3)));
11046
11047#if SU_HAVE_INLINE1
11048su_inlinestatic inline sip_authentication_info_t *sip_authentication_info_format(su_home_t *home, char const *fmt, ...)
11049{
11050 sip_header_t *h;
11051 va_list ap;
11052
11053 va_start(ap, fmt)__builtin_va_start(ap, fmt);
11054 h = sip_header_vformat(home, sip_authentication_info_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_authentication_info_class
), (fmt), (ap)))
;
11055 va_end(ap)__builtin_va_end(ap);
11056
11057 return (sip_authentication_info_t *)h;
11058}
11059#endif
11060
11061/** @} */
11062
11063/**@addtogroup sip_error_info
11064 * @{
11065 */
11066
11067/** Parse a SIP @ref sip_error_info "Error-Info header". @internal */
11068SOFIAPUBFUN issize_t sip_error_info_d(su_home_t *, msg_header_t *,
11069 char *s, isize_t slen);
11070
11071/** Print a SIP @ref sip_error_info "Error-Info header". @internal */
11072SOFIAPUBFUN issize_t sip_error_info_e(char b[], isize_t bsiz,
11073 msg_header_t const *h, int flags);
11074
11075/**Access a SIP @ref sip_error_info "Error-Info header"
11076 * structure #sip_error_info_t from #sip_t.
11077 *
11078 */
11079#define sip_error_info(sip)((sip_error_info_t *)msg_header_access((msg_pub_t*)(sip), sip_error_info_class
))
\
11080 ((sip_error_info_t *)msg_header_access((msg_pub_t*)(sip), sip_error_info_class))
11081
11082/**Initializer for structure #sip_error_info_t.
11083 *
11084 * A static #sip_error_info_t structure for
11085 * @ref sip_error_info "Error-Info header" must be initialized with
11086 * the SIP_ERROR_INFO_INIT() macro.
11087 * For instance,
11088 * @code
11089 *
11090 * sip_error_info_t sip_error_info = SIP_ERROR_INFO_INIT;
11091 *
11092 * @endcode
11093 * @HI
11094 *
11095 */
11096#define SIP_ERROR_INFO_INIT(){{{ 0, 0, sip_error_info_class }}} SIP_HDR_INIT(error_info){{{ 0, 0, sip_error_info_class }}}
11097
11098/**Initialize a structure #sip_error_info_t.
11099 *
11100 * An #sip_error_info_t structure for
11101 * @ref sip_error_info "Error-Info header" can be initialized with the
11102 * sip_error_info_init() function/macro. For instance,
11103 * @code
11104 *
11105 * sip_error_info_t sip_error_info;
11106 *
11107 * sip_error_info_init(&sip_error_info);
11108 *
11109 * @endcode
11110 * @HI
11111 *
11112 */
11113#if SU_HAVE_INLINE1
11114su_inlinestatic inline sip_error_info_t *sip_error_info_init(sip_error_info_t x[1])
11115{
11116 return SIP_HEADER_INIT(x, sip_error_info_class, sizeof(sip_error_info_t))((void)memset((x), 0, (sizeof(sip_error_info_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_error_info_class)), (x))
;
11117}
11118#else
11119#define sip_error_info_init(x) \
11120 SIP_HEADER_INIT(x, sip_error_info_class, sizeof(sip_error_info_t))((void)memset((x), 0, (sizeof(sip_error_info_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_error_info_class)), (x))
11121#endif
11122
11123/**Test if header object is instance of #sip_error_info_t.
11124 *
11125 * Check if the header class is an instance of
11126 * @ref sip_error_info "Error-Info header" object and return true (nonzero),
11127 * otherwise return false (zero).
11128 *
11129 * @param header pointer to the header structure to be tested
11130 *
11131 * @retval 1 (true) if the @a header is an instance of header error_info
11132 * @retval 0 (false) otherwise
11133 *
11134 */
11135#if SU_HAVE_INLINE1
11136su_inlinestatic inline int sip_is_error_info(sip_header_t const *header)
11137{
11138 return header && header->sh_classsh_common->h_class->hc_hash == sip_error_info_hash;
11139}
11140#else
11141int sip_is_error_info(sip_header_t const *header);
11142#endif
11143
11144#define sip_error_info_p(h)sip_is_error_info((h)) sip_is_error_info((h))
11145
11146
11147/**Duplicate a list of @ref sip_error_info "Error-Info header" header structures #sip_error_info_t.
11148 *
11149 * Duplicate a header
11150 * structure @a hdr. If the header structure @a hdr
11151 * contains a reference (@c hdr->x_next) to a list of
11152 * headers, all the headers in the list are duplicated, too.
11153 *
11154 * @param home memory home used to allocate new structure
11155 * @param hdr header structure to be duplicated
11156 *
11157 * When duplicating, all parameter lists and non-constant
11158 * strings attached to the header are copied, too. The
11159 * function uses given memory @a home to allocate all the
11160 * memory areas used to copy the header.
11161 *
11162 * @par Example
11163 * @code
11164 *
11165 * error_info = sip_error_info_dup(home, sip->sip_error_info);
11166 *
11167 * @endcode
11168 *
11169 * @return
11170 * A pointer to the
11171 * newly duplicated #sip_error_info_t header structure, or NULL
11172 * upon an error.
11173 *
11174 */
11175#if SU_HAVE_INLINE1
11176su_inlinestatic inline
11177#endif
11178sip_error_info_t *sip_error_info_dup(su_home_t *home, sip_error_info_t const *hdr)
11179 __attribute__((__malloc__));
11180
11181#if SU_HAVE_INLINE1
11182su_inlinestatic inline
11183sip_error_info_t *sip_error_info_dup(su_home_t *home, sip_error_info_t const *hdr)
11184{
11185 return (sip_error_info_t *)
11186 msg_header_dup_as(home, sip_error_info_class, (msg_header_t const *)hdr);
11187}
11188#endif
11189
11190/**Copy a list of @ref sip_error_info "Error-Info header" header structures #sip_error_info_t.
11191 *
11192 * The function sip_error_info_copy() copies a header structure @a
11193 * hdr. If the header structure @a hdr contains a reference (@c
11194 * hdr->h_next) to a list of headers, all the headers in that
11195 * list are copied, too. The function uses given memory @a home
11196 * to allocate all the memory areas used to copy the list of header
11197 * structure @a hdr.
11198 *
11199 * @param home memory home used to allocate new structure
11200 * @param hdr pointer to the header structure to be copied
11201 *
11202 * When copying, only the header structure and parameter lists attached to
11203 * it are duplicated. The new header structure retains all the references to
11204 * the strings within the old @a hdr header, including the encoding of the
11205 * old header, if present.
11206 *
11207 * @par Example
11208 * @code
11209 *
11210 * error_info = sip_error_info_copy(home, sip->sip_error_info);
11211 *
11212 * @endcode
11213 *
11214 * @return
11215 * A pointer to newly copied header structure, or NULL upon an error.
11216 *
11217 */
11218#if SU_HAVE_INLINE1
11219su_inlinestatic inline
11220#endif
11221sip_error_info_t *sip_error_info_copy(su_home_t *home, sip_error_info_t const *hdr)
11222 __attribute__((__malloc__));
11223
11224#if SU_HAVE_INLINE1
11225su_inlinestatic inline
11226sip_error_info_t *sip_error_info_copy(su_home_t *home, sip_error_info_t const *hdr)
11227{
11228 return (sip_error_info_t *)
11229 msg_header_copy_as(home, sip_error_info_class, (msg_header_t const *)hdr);
11230}
11231#endif
11232
11233/**Make a @ref sip_error_info "Error-Info header" structure #sip_error_info_t.
11234 *
11235 * The function sip_error_info_make() makes a new
11236 * #sip_error_info_t header structure. It allocates a new
11237 * header structure, and decodes the string @a s as the
11238 * value of the structure.
11239 *
11240 * @param home memory home used to allocate new header structure.
11241 * @param s string to be decoded as value of the new header structure
11242 *
11243 * @return
11244 * A pointer to newly maked #sip_error_info_t header structure, or NULL upon an
11245 * error.
11246 *
11247 */
11248#if SU_HAVE_INLINE1
11249su_inlinestatic inline
11250#endif
11251sip_error_info_t *sip_error_info_make(su_home_t *home, char const *s)
11252 __attribute__((__malloc__));
11253
11254#if SU_HAVE_INLINE1
11255su_inlinestatic inline sip_error_info_t *sip_error_info_make(su_home_t *home, char const *s)
11256{
11257 return (sip_error_info_t *)sip_header_make(home, sip_error_info_class, s)((sip_header_t *)msg_header_make((home), (sip_error_info_class
), (s)))
;
11258}
11259#endif
11260
11261/**Make a @ref sip_error_info "Error-Info header" from formatting result.
11262 *
11263 * Make a new #sip_error_info_t object using formatting result as its value.
11264 * The function first prints the arguments according to the format @a fmt
11265 * specified. Then it allocates a new header structure, and parses the
11266 * formatting result to the structure #sip_error_info_t.
11267 *
11268 * @param home memory home used to allocate new header structure.
11269 * @param fmt string used as a printf()-style format
11270 * @param ... argument list for format
11271 *
11272 * @return
11273 * A pointer to newly
11274 * makes header structure, or NULL upon an error.
11275 *
11276 * @HIDE
11277 *
11278 */
11279#if SU_HAVE_INLINE1
11280su_inlinestatic inline
11281#endif
11282sip_error_info_t *sip_error_info_format(su_home_t *home, char const *fmt, ...)
11283 __attribute__((__malloc__, __format__ (printf, 2, 3)));
11284
11285#if SU_HAVE_INLINE1
11286su_inlinestatic inline sip_error_info_t *sip_error_info_format(su_home_t *home, char const *fmt, ...)
11287{
11288 sip_header_t *h;
11289 va_list ap;
11290
11291 va_start(ap, fmt)__builtin_va_start(ap, fmt);
11292 h = sip_header_vformat(home, sip_error_info_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_error_info_class
), (fmt), (ap)))
;
11293 va_end(ap)__builtin_va_end(ap);
11294
11295 return (sip_error_info_t *)h;
11296}
11297#endif
11298
11299/** @} */
11300
11301/**@addtogroup sip_warning
11302 * @{
11303 */
11304
11305/** Parse a SIP @ref sip_warning "Warning header". @internal */
11306SOFIAPUBFUN issize_t sip_warning_d(su_home_t *, msg_header_t *,
11307 char *s, isize_t slen);
11308
11309/** Print a SIP @ref sip_warning "Warning header". @internal */
11310SOFIAPUBFUN issize_t sip_warning_e(char b[], isize_t bsiz,
11311 msg_header_t const *h, int flags);
11312
11313/**Access a SIP @ref sip_warning "Warning header"
11314 * structure #sip_warning_t from #sip_t.
11315 *
11316 */
11317#define sip_warning(sip)((sip_warning_t *)msg_header_access((msg_pub_t*)(sip), sip_warning_class
))
\
11318 ((sip_warning_t *)msg_header_access((msg_pub_t*)(sip), sip_warning_class))
11319
11320/**Initializer for structure #sip_warning_t.
11321 *
11322 * A static #sip_warning_t structure for
11323 * @ref sip_warning "Warning header" must be initialized with
11324 * the SIP_WARNING_INIT() macro.
11325 * For instance,
11326 * @code
11327 *
11328 * sip_warning_t sip_warning = SIP_WARNING_INIT;
11329 *
11330 * @endcode
11331 * @HI
11332 *
11333 */
11334#define SIP_WARNING_INIT(){{{ 0, 0, sip_warning_class }}} SIP_HDR_INIT(warning){{{ 0, 0, sip_warning_class }}}
11335
11336/**Initialize a structure #sip_warning_t.
11337 *
11338 * An #sip_warning_t structure for
11339 * @ref sip_warning "Warning header" can be initialized with the
11340 * sip_warning_init() function/macro. For instance,
11341 * @code
11342 *
11343 * sip_warning_t sip_warning;
11344 *
11345 * sip_warning_init(&sip_warning);
11346 *
11347 * @endcode
11348 * @HI
11349 *
11350 */
11351#if SU_HAVE_INLINE1
11352su_inlinestatic inline sip_warning_t *sip_warning_init(sip_warning_t x[1])
11353{
11354 return SIP_HEADER_INIT(x, sip_warning_class, sizeof(sip_warning_t))((void)memset((x), 0, (sizeof(sip_warning_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_warning_class)), (x))
;
11355}
11356#else
11357#define sip_warning_init(x) \
11358 SIP_HEADER_INIT(x, sip_warning_class, sizeof(sip_warning_t))((void)memset((x), 0, (sizeof(sip_warning_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_warning_class)), (x))
11359#endif
11360
11361/**Test if header object is instance of #sip_warning_t.
11362 *
11363 * Check if the header class is an instance of
11364 * @ref sip_warning "Warning header" object and return true (nonzero),
11365 * otherwise return false (zero).
11366 *
11367 * @param header pointer to the header structure to be tested
11368 *
11369 * @retval 1 (true) if the @a header is an instance of header warning
11370 * @retval 0 (false) otherwise
11371 *
11372 */
11373#if SU_HAVE_INLINE1
11374su_inlinestatic inline int sip_is_warning(sip_header_t const *header)
11375{
11376 return header && header->sh_classsh_common->h_class->hc_hash == sip_warning_hash;
11377}
11378#else
11379int sip_is_warning(sip_header_t const *header);
11380#endif
11381
11382#define sip_warning_p(h)sip_is_warning((h)) sip_is_warning((h))
11383
11384
11385/**Duplicate a list of @ref sip_warning "Warning header" header structures #sip_warning_t.
11386 *
11387 * Duplicate a header
11388 * structure @a hdr. If the header structure @a hdr
11389 * contains a reference (@c hdr->x_next) to a list of
11390 * headers, all the headers in the list are duplicated, too.
11391 *
11392 * @param home memory home used to allocate new structure
11393 * @param hdr header structure to be duplicated
11394 *
11395 * When duplicating, all parameter lists and non-constant
11396 * strings attached to the header are copied, too. The
11397 * function uses given memory @a home to allocate all the
11398 * memory areas used to copy the header.
11399 *
11400 * @par Example
11401 * @code
11402 *
11403 * warning = sip_warning_dup(home, sip->sip_warning);
11404 *
11405 * @endcode
11406 *
11407 * @return
11408 * A pointer to the
11409 * newly duplicated #sip_warning_t header structure, or NULL
11410 * upon an error.
11411 *
11412 */
11413#if SU_HAVE_INLINE1
11414su_inlinestatic inline
11415#endif
11416sip_warning_t *sip_warning_dup(su_home_t *home, sip_warning_t const *hdr)
11417 __attribute__((__malloc__));
11418
11419#if SU_HAVE_INLINE1
11420su_inlinestatic inline
11421sip_warning_t *sip_warning_dup(su_home_t *home, sip_warning_t const *hdr)
11422{
11423 return (sip_warning_t *)
11424 msg_header_dup_as(home, sip_warning_class, (msg_header_t const *)hdr);
11425}
11426#endif
11427
11428/**Copy a list of @ref sip_warning "Warning header" header structures #sip_warning_t.
11429 *
11430 * The function sip_warning_copy() copies a header structure @a
11431 * hdr. If the header structure @a hdr contains a reference (@c
11432 * hdr->h_next) to a list of headers, all the headers in that
11433 * list are copied, too. The function uses given memory @a home
11434 * to allocate all the memory areas used to copy the list of header
11435 * structure @a hdr.
11436 *
11437 * @param home memory home used to allocate new structure
11438 * @param hdr pointer to the header structure to be copied
11439 *
11440 * When copying, only the header structure and parameter lists attached to
11441 * it are duplicated. The new header structure retains all the references to
11442 * the strings within the old @a hdr header, including the encoding of the
11443 * old header, if present.
11444 *
11445 * @par Example
11446 * @code
11447 *
11448 * warning = sip_warning_copy(home, sip->sip_warning);
11449 *
11450 * @endcode
11451 *
11452 * @return
11453 * A pointer to newly copied header structure, or NULL upon an error.
11454 *
11455 */
11456#if SU_HAVE_INLINE1
11457su_inlinestatic inline
11458#endif
11459sip_warning_t *sip_warning_copy(su_home_t *home, sip_warning_t const *hdr)
11460 __attribute__((__malloc__));
11461
11462#if SU_HAVE_INLINE1
11463su_inlinestatic inline
11464sip_warning_t *sip_warning_copy(su_home_t *home, sip_warning_t const *hdr)
11465{
11466 return (sip_warning_t *)
11467 msg_header_copy_as(home, sip_warning_class, (msg_header_t const *)hdr);
11468}
11469#endif
11470
11471/**Make a @ref sip_warning "Warning header" structure #sip_warning_t.
11472 *
11473 * The function sip_warning_make() makes a new
11474 * #sip_warning_t header structure. It allocates a new
11475 * header structure, and decodes the string @a s as the
11476 * value of the structure.
11477 *
11478 * @param home memory home used to allocate new header structure.
11479 * @param s string to be decoded as value of the new header structure
11480 *
11481 * @return
11482 * A pointer to newly maked #sip_warning_t header structure, or NULL upon an
11483 * error.
11484 *
11485 */
11486#if SU_HAVE_INLINE1
11487su_inlinestatic inline
11488#endif
11489sip_warning_t *sip_warning_make(su_home_t *home, char const *s)
11490 __attribute__((__malloc__));
11491
11492#if SU_HAVE_INLINE1
11493su_inlinestatic inline sip_warning_t *sip_warning_make(su_home_t *home, char const *s)
11494{
11495 return (sip_warning_t *)sip_header_make(home, sip_warning_class, s)((sip_header_t *)msg_header_make((home), (sip_warning_class),
(s)))
;
11496}
11497#endif
11498
11499/**Make a @ref sip_warning "Warning header" from formatting result.
11500 *
11501 * Make a new #sip_warning_t object using formatting result as its value.
11502 * The function first prints the arguments according to the format @a fmt
11503 * specified. Then it allocates a new header structure, and parses the
11504 * formatting result to the structure #sip_warning_t.
11505 *
11506 * @param home memory home used to allocate new header structure.
11507 * @param fmt string used as a printf()-style format
11508 * @param ... argument list for format
11509 *
11510 * @return
11511 * A pointer to newly
11512 * makes header structure, or NULL upon an error.
11513 *
11514 * @HIDE
11515 *
11516 */
11517#if SU_HAVE_INLINE1
11518su_inlinestatic inline
11519#endif
11520sip_warning_t *sip_warning_format(su_home_t *home, char const *fmt, ...)
11521 __attribute__((__malloc__, __format__ (printf, 2, 3)));
11522
11523#if SU_HAVE_INLINE1
11524su_inlinestatic inline sip_warning_t *sip_warning_format(su_home_t *home, char const *fmt, ...)
11525{
11526 sip_header_t *h;
11527 va_list ap;
11528
11529 va_start(ap, fmt)__builtin_va_start(ap, fmt);
11530 h = sip_header_vformat(home, sip_warning_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_warning_class
), (fmt), (ap)))
;
11531 va_end(ap)__builtin_va_end(ap);
11532
11533 return (sip_warning_t *)h;
11534}
11535#endif
11536
11537/** @} */
11538
11539/**@addtogroup sip_refer_to
11540 * @{
11541 */
11542
11543/** Parse a SIP @ref sip_refer_to "Refer-To header". @internal */
11544SOFIAPUBFUN issize_t sip_refer_to_d(su_home_t *, msg_header_t *,
11545 char *s, isize_t slen);
11546
11547/** Print a SIP @ref sip_refer_to "Refer-To header". @internal */
11548SOFIAPUBFUN issize_t sip_refer_to_e(char b[], isize_t bsiz,
11549 msg_header_t const *h, int flags);
11550
11551/**Access a SIP @ref sip_refer_to "Refer-To header"
11552 * structure #sip_refer_to_t from #sip_t.
11553 *
11554 */
11555#define sip_refer_to(sip)((sip_refer_to_t *)msg_header_access((msg_pub_t*)(sip), sip_refer_to_class
))
\
11556 ((sip_refer_to_t *)msg_header_access((msg_pub_t*)(sip), sip_refer_to_class))
11557
11558/**Initializer for structure #sip_refer_to_t.
11559 *
11560 * A static #sip_refer_to_t structure for
11561 * @ref sip_refer_to "Refer-To header" must be initialized with
11562 * the SIP_REFER_TO_INIT() macro.
11563 * For instance,
11564 * @code
11565 *
11566 * sip_refer_to_t sip_refer_to = SIP_REFER_TO_INIT;
11567 *
11568 * @endcode
11569 * @HI
11570 *
11571 */
11572#define SIP_REFER_TO_INIT(){{{ 0, 0, sip_refer_to_class }}} SIP_HDR_INIT(refer_to){{{ 0, 0, sip_refer_to_class }}}
11573
11574/**Initialize a structure #sip_refer_to_t.
11575 *
11576 * An #sip_refer_to_t structure for
11577 * @ref sip_refer_to "Refer-To header" can be initialized with the
11578 * sip_refer_to_init() function/macro. For instance,
11579 * @code
11580 *
11581 * sip_refer_to_t sip_refer_to;
11582 *
11583 * sip_refer_to_init(&sip_refer_to);
11584 *
11585 * @endcode
11586 * @HI
11587 *
11588 */
11589#if SU_HAVE_INLINE1
11590su_inlinestatic inline sip_refer_to_t *sip_refer_to_init(sip_refer_to_t x[1])
11591{
11592 return SIP_HEADER_INIT(x, sip_refer_to_class, sizeof(sip_refer_to_t))((void)memset((x), 0, (sizeof(sip_refer_to_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_refer_to_class)), (x))
;
11593}
11594#else
11595#define sip_refer_to_init(x) \
11596 SIP_HEADER_INIT(x, sip_refer_to_class, sizeof(sip_refer_to_t))((void)memset((x), 0, (sizeof(sip_refer_to_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_refer_to_class)), (x))
11597#endif
11598
11599/**Test if header object is instance of #sip_refer_to_t.
11600 *
11601 * Check if the header class is an instance of
11602 * @ref sip_refer_to "Refer-To header" object and return true (nonzero),
11603 * otherwise return false (zero).
11604 *
11605 * @param header pointer to the header structure to be tested
11606 *
11607 * @retval 1 (true) if the @a header is an instance of header refer_to
11608 * @retval 0 (false) otherwise
11609 *
11610 */
11611#if SU_HAVE_INLINE1
11612su_inlinestatic inline int sip_is_refer_to(sip_header_t const *header)
11613{
11614 return header && header->sh_classsh_common->h_class->hc_hash == sip_refer_to_hash;
11615}
11616#else
11617int sip_is_refer_to(sip_header_t const *header);
11618#endif
11619
11620#define sip_refer_to_p(h)sip_is_refer_to((h)) sip_is_refer_to((h))
11621
11622
11623/**Duplicate a list of @ref sip_refer_to "Refer-To header" header structures #sip_refer_to_t.
11624 *
11625 * Duplicate a header
11626 * structure @a hdr. If the header structure @a hdr
11627 * contains a reference (@c hdr->x_next) to a list of
11628 * headers, all the headers in the list are duplicated, too.
11629 *
11630 * @param home memory home used to allocate new structure
11631 * @param hdr header structure to be duplicated
11632 *
11633 * When duplicating, all parameter lists and non-constant
11634 * strings attached to the header are copied, too. The
11635 * function uses given memory @a home to allocate all the
11636 * memory areas used to copy the header.
11637 *
11638 * @par Example
11639 * @code
11640 *
11641 * refer_to = sip_refer_to_dup(home, sip->sip_refer_to);
11642 *
11643 * @endcode
11644 *
11645 * @return
11646 * A pointer to the
11647 * newly duplicated #sip_refer_to_t header structure, or NULL
11648 * upon an error.
11649 *
11650 */
11651#if SU_HAVE_INLINE1
11652su_inlinestatic inline
11653#endif
11654sip_refer_to_t *sip_refer_to_dup(su_home_t *home, sip_refer_to_t const *hdr)
11655 __attribute__((__malloc__));
11656
11657#if SU_HAVE_INLINE1
11658su_inlinestatic inline
11659sip_refer_to_t *sip_refer_to_dup(su_home_t *home, sip_refer_to_t const *hdr)
11660{
11661 return (sip_refer_to_t *)
11662 msg_header_dup_as(home, sip_refer_to_class, (msg_header_t const *)hdr);
11663}
11664#endif
11665
11666/**Copy a list of @ref sip_refer_to "Refer-To header" header structures #sip_refer_to_t.
11667 *
11668 * The function sip_refer_to_copy() copies a header structure @a
11669 * hdr. If the header structure @a hdr contains a reference (@c
11670 * hdr->h_next) to a list of headers, all the headers in that
11671 * list are copied, too. The function uses given memory @a home
11672 * to allocate all the memory areas used to copy the list of header
11673 * structure @a hdr.
11674 *
11675 * @param home memory home used to allocate new structure
11676 * @param hdr pointer to the header structure to be copied
11677 *
11678 * When copying, only the header structure and parameter lists attached to
11679 * it are duplicated. The new header structure retains all the references to
11680 * the strings within the old @a hdr header, including the encoding of the
11681 * old header, if present.
11682 *
11683 * @par Example
11684 * @code
11685 *
11686 * refer_to = sip_refer_to_copy(home, sip->sip_refer_to);
11687 *
11688 * @endcode
11689 *
11690 * @return
11691 * A pointer to newly copied header structure, or NULL upon an error.
11692 *
11693 */
11694#if SU_HAVE_INLINE1
11695su_inlinestatic inline
11696#endif
11697sip_refer_to_t *sip_refer_to_copy(su_home_t *home, sip_refer_to_t const *hdr)
11698 __attribute__((__malloc__));
11699
11700#if SU_HAVE_INLINE1
11701su_inlinestatic inline
11702sip_refer_to_t *sip_refer_to_copy(su_home_t *home, sip_refer_to_t const *hdr)
11703{
11704 return (sip_refer_to_t *)
11705 msg_header_copy_as(home, sip_refer_to_class, (msg_header_t const *)hdr);
11706}
11707#endif
11708
11709/**Make a @ref sip_refer_to "Refer-To header" structure #sip_refer_to_t.
11710 *
11711 * The function sip_refer_to_make() makes a new
11712 * #sip_refer_to_t header structure. It allocates a new
11713 * header structure, and decodes the string @a s as the
11714 * value of the structure.
11715 *
11716 * @param home memory home used to allocate new header structure.
11717 * @param s string to be decoded as value of the new header structure
11718 *
11719 * @return
11720 * A pointer to newly maked #sip_refer_to_t header structure, or NULL upon an
11721 * error.
11722 *
11723 */
11724#if SU_HAVE_INLINE1
11725su_inlinestatic inline
11726#endif
11727sip_refer_to_t *sip_refer_to_make(su_home_t *home, char const *s)
11728 __attribute__((__malloc__));
11729
11730#if SU_HAVE_INLINE1
11731su_inlinestatic inline sip_refer_to_t *sip_refer_to_make(su_home_t *home, char const *s)
11732{
11733 return (sip_refer_to_t *)sip_header_make(home, sip_refer_to_class, s)((sip_header_t *)msg_header_make((home), (sip_refer_to_class)
, (s)))
;
11734}
11735#endif
11736
11737/**Make a @ref sip_refer_to "Refer-To header" from formatting result.
11738 *
11739 * Make a new #sip_refer_to_t object using formatting result as its value.
11740 * The function first prints the arguments according to the format @a fmt
11741 * specified. Then it allocates a new header structure, and parses the
11742 * formatting result to the structure #sip_refer_to_t.
11743 *
11744 * @param home memory home used to allocate new header structure.
11745 * @param fmt string used as a printf()-style format
11746 * @param ... argument list for format
11747 *
11748 * @return
11749 * A pointer to newly
11750 * makes header structure, or NULL upon an error.
11751 *
11752 * @HIDE
11753 *
11754 */
11755#if SU_HAVE_INLINE1
11756su_inlinestatic inline
11757#endif
11758sip_refer_to_t *sip_refer_to_format(su_home_t *home, char const *fmt, ...)
11759 __attribute__((__malloc__, __format__ (printf, 2, 3)));
11760
11761#if SU_HAVE_INLINE1
11762su_inlinestatic inline sip_refer_to_t *sip_refer_to_format(su_home_t *home, char const *fmt, ...)
11763{
11764 sip_header_t *h;
11765 va_list ap;
11766
11767 va_start(ap, fmt)__builtin_va_start(ap, fmt);
11768 h = sip_header_vformat(home, sip_refer_to_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_refer_to_class
), (fmt), (ap)))
;
11769 va_end(ap)__builtin_va_end(ap);
11770
11771 return (sip_refer_to_t *)h;
11772}
11773#endif
11774
11775/** @} */
11776
11777/**@addtogroup sip_referred_by
11778 * @{
11779 */
11780
11781/** Parse a SIP @ref sip_referred_by "Referred-By header". @internal */
11782SOFIAPUBFUN issize_t sip_referred_by_d(su_home_t *, msg_header_t *,
11783 char *s, isize_t slen);
11784
11785/** Print a SIP @ref sip_referred_by "Referred-By header". @internal */
11786SOFIAPUBFUN issize_t sip_referred_by_e(char b[], isize_t bsiz,
11787 msg_header_t const *h, int flags);
11788
11789/**Access a SIP @ref sip_referred_by "Referred-By header"
11790 * structure #sip_referred_by_t from #sip_t.
11791 *
11792 */
11793#define sip_referred_by(sip)((sip_referred_by_t *)msg_header_access((msg_pub_t*)(sip), sip_referred_by_class
))
\
11794 ((sip_referred_by_t *)msg_header_access((msg_pub_t*)(sip), sip_referred_by_class))
11795
11796/**Initializer for structure #sip_referred_by_t.
11797 *
11798 * A static #sip_referred_by_t structure for
11799 * @ref sip_referred_by "Referred-By header" must be initialized with
11800 * the SIP_REFERRED_BY_INIT() macro.
11801 * For instance,
11802 * @code
11803 *
11804 * sip_referred_by_t sip_referred_by = SIP_REFERRED_BY_INIT;
11805 *
11806 * @endcode
11807 * @HI
11808 *
11809 */
11810#define SIP_REFERRED_BY_INIT(){{{ 0, 0, sip_referred_by_class }}} SIP_HDR_INIT(referred_by){{{ 0, 0, sip_referred_by_class }}}
11811
11812/**Initialize a structure #sip_referred_by_t.
11813 *
11814 * An #sip_referred_by_t structure for
11815 * @ref sip_referred_by "Referred-By header" can be initialized with the
11816 * sip_referred_by_init() function/macro. For instance,
11817 * @code
11818 *
11819 * sip_referred_by_t sip_referred_by;
11820 *
11821 * sip_referred_by_init(&sip_referred_by);
11822 *
11823 * @endcode
11824 * @HI
11825 *
11826 */
11827#if SU_HAVE_INLINE1
11828su_inlinestatic inline sip_referred_by_t *sip_referred_by_init(sip_referred_by_t x[1])
11829{
11830 return SIP_HEADER_INIT(x, sip_referred_by_class, sizeof(sip_referred_by_t))((void)memset((x), 0, (sizeof(sip_referred_by_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_referred_by_class)), (
x))
;
11831}
11832#else
11833#define sip_referred_by_init(x) \
11834 SIP_HEADER_INIT(x, sip_referred_by_class, sizeof(sip_referred_by_t))((void)memset((x), 0, (sizeof(sip_referred_by_t))), (void)(((
sip_common_t *)(x))->h_class = (sip_referred_by_class)), (
x))
11835#endif
11836
11837/**Test if header object is instance of #sip_referred_by_t.
11838 *
11839 * Check if the header class is an instance of
11840 * @ref sip_referred_by "Referred-By header" object and return true (nonzero),
11841 * otherwise return false (zero).
11842 *
11843 * @param header pointer to the header structure to be tested
11844 *
11845 * @retval 1 (true) if the @a header is an instance of header referred_by
11846 * @retval 0 (false) otherwise
11847 *
11848 */
11849#if SU_HAVE_INLINE1
11850su_inlinestatic inline int sip_is_referred_by(sip_header_t const *header)
11851{
11852 return header && header->sh_classsh_common->h_class->hc_hash == sip_referred_by_hash;
11853}
11854#else
11855int sip_is_referred_by(sip_header_t const *header);
11856#endif
11857
11858#define sip_referred_by_p(h)sip_is_referred_by((h)) sip_is_referred_by((h))
11859
11860
11861/**Duplicate a list of @ref sip_referred_by "Referred-By header" header structures #sip_referred_by_t.
11862 *
11863 * Duplicate a header
11864 * structure @a hdr. If the header structure @a hdr
11865 * contains a reference (@c hdr->x_next) to a list of
11866 * headers, all the headers in the list are duplicated, too.
11867 *
11868 * @param home memory home used to allocate new structure
11869 * @param hdr header structure to be duplicated
11870 *
11871 * When duplicating, all parameter lists and non-constant
11872 * strings attached to the header are copied, too. The
11873 * function uses given memory @a home to allocate all the
11874 * memory areas used to copy the header.
11875 *
11876 * @par Example
11877 * @code
11878 *
11879 * referred_by = sip_referred_by_dup(home, sip->sip_referred_by);
11880 *
11881 * @endcode
11882 *
11883 * @return
11884 * A pointer to the
11885 * newly duplicated #sip_referred_by_t header structure, or NULL
11886 * upon an error.
11887 *
11888 */
11889#if SU_HAVE_INLINE1
11890su_inlinestatic inline
11891#endif
11892sip_referred_by_t *sip_referred_by_dup(su_home_t *home, sip_referred_by_t const *hdr)
11893 __attribute__((__malloc__));
11894
11895#if SU_HAVE_INLINE1
11896su_inlinestatic inline
11897sip_referred_by_t *sip_referred_by_dup(su_home_t *home, sip_referred_by_t const *hdr)
11898{
11899 return (sip_referred_by_t *)
11900 msg_header_dup_as(home, sip_referred_by_class, (msg_header_t const *)hdr);
11901}
11902#endif
11903
11904/**Copy a list of @ref sip_referred_by "Referred-By header" header structures #sip_referred_by_t.
11905 *
11906 * The function sip_referred_by_copy() copies a header structure @a
11907 * hdr. If the header structure @a hdr contains a reference (@c
11908 * hdr->h_next) to a list of headers, all the headers in that
11909 * list are copied, too. The function uses given memory @a home
11910 * to allocate all the memory areas used to copy the list of header
11911 * structure @a hdr.
11912 *
11913 * @param home memory home used to allocate new structure
11914 * @param hdr pointer to the header structure to be copied
11915 *
11916 * When copying, only the header structure and parameter lists attached to
11917 * it are duplicated. The new header structure retains all the references to
11918 * the strings within the old @a hdr header, including the encoding of the
11919 * old header, if present.
11920 *
11921 * @par Example
11922 * @code
11923 *
11924 * referred_by = sip_referred_by_copy(home, sip->sip_referred_by);
11925 *
11926 * @endcode
11927 *
11928 * @return
11929 * A pointer to newly copied header structure, or NULL upon an error.
11930 *
11931 */
11932#if SU_HAVE_INLINE1
11933su_inlinestatic inline
11934#endif
11935sip_referred_by_t *sip_referred_by_copy(su_home_t *home, sip_referred_by_t const *hdr)
11936 __attribute__((__malloc__));
11937
11938#if SU_HAVE_INLINE1
11939su_inlinestatic inline
11940sip_referred_by_t *sip_referred_by_copy(su_home_t *home, sip_referred_by_t const *hdr)
11941{
11942 return (sip_referred_by_t *)
11943 msg_header_copy_as(home, sip_referred_by_class, (msg_header_t const *)hdr);
11944}
11945#endif
11946
11947/**Make a @ref sip_referred_by "Referred-By header" structure #sip_referred_by_t.
11948 *
11949 * The function sip_referred_by_make() makes a new
11950 * #sip_referred_by_t header structure. It allocates a new
11951 * header structure, and decodes the string @a s as the
11952 * value of the structure.
11953 *
11954 * @param home memory home used to allocate new header structure.
11955 * @param s string to be decoded as value of the new header structure
11956 *
11957 * @return
11958 * A pointer to newly maked #sip_referred_by_t header structure, or NULL upon an
11959 * error.
11960 *
11961 */
11962#if SU_HAVE_INLINE1
11963su_inlinestatic inline
11964#endif
11965sip_referred_by_t *sip_referred_by_make(su_home_t *home, char const *s)
11966 __attribute__((__malloc__));
11967
11968#if SU_HAVE_INLINE1
11969su_inlinestatic inline sip_referred_by_t *sip_referred_by_make(su_home_t *home, char const *s)
11970{
11971 return (sip_referred_by_t *)sip_header_make(home, sip_referred_by_class, s)((sip_header_t *)msg_header_make((home), (sip_referred_by_class
), (s)))
;
11972}
11973#endif
11974
11975/**Make a @ref sip_referred_by "Referred-By header" from formatting result.
11976 *
11977 * Make a new #sip_referred_by_t object using formatting result as its value.
11978 * The function first prints the arguments according to the format @a fmt
11979 * specified. Then it allocates a new header structure, and parses the
11980 * formatting result to the structure #sip_referred_by_t.
11981 *
11982 * @param home memory home used to allocate new header structure.
11983 * @param fmt string used as a printf()-style format
11984 * @param ... argument list for format
11985 *
11986 * @return
11987 * A pointer to newly
11988 * makes header structure, or NULL upon an error.
11989 *
11990 * @HIDE
11991 *
11992 */
11993#if SU_HAVE_INLINE1
11994su_inlinestatic inline
11995#endif
11996sip_referred_by_t *sip_referred_by_format(su_home_t *home, char const *fmt, ...)
11997 __attribute__((__malloc__, __format__ (printf, 2, 3)));
11998
11999#if SU_HAVE_INLINE1
12000su_inlinestatic inline sip_referred_by_t *sip_referred_by_format(su_home_t *home, char const *fmt, ...)
12001{
12002 sip_header_t *h;
12003 va_list ap;
12004
12005 va_start(ap, fmt)__builtin_va_start(ap, fmt);
12006 h = sip_header_vformat(home, sip_referred_by_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_referred_by_class
), (fmt), (ap)))
;
12007 va_end(ap)__builtin_va_end(ap);
12008
12009 return (sip_referred_by_t *)h;
12010}
12011#endif
12012
12013/** @} */
12014
12015/**@addtogroup sip_replaces
12016 * @{
12017 */
12018
12019/** Parse a SIP @ref sip_replaces "Replaces header". @internal */
12020SOFIAPUBFUN issize_t sip_replaces_d(su_home_t *, msg_header_t *,
12021 char *s, isize_t slen);
12022
12023/** Print a SIP @ref sip_replaces "Replaces header". @internal */
12024SOFIAPUBFUN issize_t sip_replaces_e(char b[], isize_t bsiz,
12025 msg_header_t const *h, int flags);
12026
12027/**Access a SIP @ref sip_replaces "Replaces header"
12028 * structure #sip_replaces_t from #sip_t.
12029 *
12030 */
12031#define sip_replaces(sip)((sip_replaces_t *)msg_header_access((msg_pub_t*)(sip), sip_replaces_class
))
\
12032 ((sip_replaces_t *)msg_header_access((msg_pub_t*)(sip), sip_replaces_class))
12033
12034/**Initializer for structure #sip_replaces_t.
12035 *
12036 * A static #sip_replaces_t structure for
12037 * @ref sip_replaces "Replaces header" must be initialized with
12038 * the SIP_REPLACES_INIT() macro.
12039 * For instance,
12040 * @code
12041 *
12042 * sip_replaces_t sip_replaces = SIP_REPLACES_INIT;
12043 *
12044 * @endcode
12045 * @HI
12046 *
12047 */
12048#define SIP_REPLACES_INIT(){{{ 0, 0, sip_replaces_class }}} SIP_HDR_INIT(replaces){{{ 0, 0, sip_replaces_class }}}
12049
12050/**Initialize a structure #sip_replaces_t.
12051 *
12052 * An #sip_replaces_t structure for
12053 * @ref sip_replaces "Replaces header" can be initialized with the
12054 * sip_replaces_init() function/macro. For instance,
12055 * @code
12056 *
12057 * sip_replaces_t sip_replaces;
12058 *
12059 * sip_replaces_init(&sip_replaces);
12060 *
12061 * @endcode
12062 * @HI
12063 *
12064 */
12065#if SU_HAVE_INLINE1
12066su_inlinestatic inline sip_replaces_t *sip_replaces_init(sip_replaces_t x[1])
12067{
12068 return SIP_HEADER_INIT(x, sip_replaces_class, sizeof(sip_replaces_t))((void)memset((x), 0, (sizeof(sip_replaces_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_replaces_class)), (x))
;
12069}
12070#else
12071#define sip_replaces_init(x) \
12072 SIP_HEADER_INIT(x, sip_replaces_class, sizeof(sip_replaces_t))((void)memset((x), 0, (sizeof(sip_replaces_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_replaces_class)), (x))
12073#endif
12074
12075/**Test if header object is instance of #sip_replaces_t.
12076 *
12077 * Check if the header class is an instance of
12078 * @ref sip_replaces "Replaces header" object and return true (nonzero),
12079 * otherwise return false (zero).
12080 *
12081 * @param header pointer to the header structure to be tested
12082 *
12083 * @retval 1 (true) if the @a header is an instance of header replaces
12084 * @retval 0 (false) otherwise
12085 *
12086 */
12087#if SU_HAVE_INLINE1
12088su_inlinestatic inline int sip_is_replaces(sip_header_t const *header)
12089{
12090 return header && header->sh_classsh_common->h_class->hc_hash == sip_replaces_hash;
12091}
12092#else
12093int sip_is_replaces(sip_header_t const *header);
12094#endif
12095
12096#define sip_replaces_p(h)sip_is_replaces((h)) sip_is_replaces((h))
12097
12098
12099/**Duplicate a list of @ref sip_replaces "Replaces header" header structures #sip_replaces_t.
12100 *
12101 * Duplicate a header
12102 * structure @a hdr. If the header structure @a hdr
12103 * contains a reference (@c hdr->x_next) to a list of
12104 * headers, all the headers in the list are duplicated, too.
12105 *
12106 * @param home memory home used to allocate new structure
12107 * @param hdr header structure to be duplicated
12108 *
12109 * When duplicating, all parameter lists and non-constant
12110 * strings attached to the header are copied, too. The
12111 * function uses given memory @a home to allocate all the
12112 * memory areas used to copy the header.
12113 *
12114 * @par Example
12115 * @code
12116 *
12117 * replaces = sip_replaces_dup(home, sip->sip_replaces);
12118 *
12119 * @endcode
12120 *
12121 * @return
12122 * A pointer to the
12123 * newly duplicated #sip_replaces_t header structure, or NULL
12124 * upon an error.
12125 *
12126 */
12127#if SU_HAVE_INLINE1
12128su_inlinestatic inline
12129#endif
12130sip_replaces_t *sip_replaces_dup(su_home_t *home, sip_replaces_t const *hdr)
12131 __attribute__((__malloc__));
12132
12133#if SU_HAVE_INLINE1
12134su_inlinestatic inline
12135sip_replaces_t *sip_replaces_dup(su_home_t *home, sip_replaces_t const *hdr)
12136{
12137 return (sip_replaces_t *)
12138 msg_header_dup_as(home, sip_replaces_class, (msg_header_t const *)hdr);
12139}
12140#endif
12141
12142/**Copy a list of @ref sip_replaces "Replaces header" header structures #sip_replaces_t.
12143 *
12144 * The function sip_replaces_copy() copies a header structure @a
12145 * hdr. If the header structure @a hdr contains a reference (@c
12146 * hdr->h_next) to a list of headers, all the headers in that
12147 * list are copied, too. The function uses given memory @a home
12148 * to allocate all the memory areas used to copy the list of header
12149 * structure @a hdr.
12150 *
12151 * @param home memory home used to allocate new structure
12152 * @param hdr pointer to the header structure to be copied
12153 *
12154 * When copying, only the header structure and parameter lists attached to
12155 * it are duplicated. The new header structure retains all the references to
12156 * the strings within the old @a hdr header, including the encoding of the
12157 * old header, if present.
12158 *
12159 * @par Example
12160 * @code
12161 *
12162 * replaces = sip_replaces_copy(home, sip->sip_replaces);
12163 *
12164 * @endcode
12165 *
12166 * @return
12167 * A pointer to newly copied header structure, or NULL upon an error.
12168 *
12169 */
12170#if SU_HAVE_INLINE1
12171su_inlinestatic inline
12172#endif
12173sip_replaces_t *sip_replaces_copy(su_home_t *home, sip_replaces_t const *hdr)
12174 __attribute__((__malloc__));
12175
12176#if SU_HAVE_INLINE1
12177su_inlinestatic inline
12178sip_replaces_t *sip_replaces_copy(su_home_t *home, sip_replaces_t const *hdr)
12179{
12180 return (sip_replaces_t *)
12181 msg_header_copy_as(home, sip_replaces_class, (msg_header_t const *)hdr);
12182}
12183#endif
12184
12185/**Make a @ref sip_replaces "Replaces header" structure #sip_replaces_t.
12186 *
12187 * The function sip_replaces_make() makes a new
12188 * #sip_replaces_t header structure. It allocates a new
12189 * header structure, and decodes the string @a s as the
12190 * value of the structure.
12191 *
12192 * @param home memory home used to allocate new header structure.
12193 * @param s string to be decoded as value of the new header structure
12194 *
12195 * @return
12196 * A pointer to newly maked #sip_replaces_t header structure, or NULL upon an
12197 * error.
12198 *
12199 */
12200#if SU_HAVE_INLINE1
12201su_inlinestatic inline
12202#endif
12203sip_replaces_t *sip_replaces_make(su_home_t *home, char const *s)
12204 __attribute__((__malloc__));
12205
12206#if SU_HAVE_INLINE1
12207su_inlinestatic inline sip_replaces_t *sip_replaces_make(su_home_t *home, char const *s)
12208{
12209 return (sip_replaces_t *)sip_header_make(home, sip_replaces_class, s)((sip_header_t *)msg_header_make((home), (sip_replaces_class)
, (s)))
;
12210}
12211#endif
12212
12213/**Make a @ref sip_replaces "Replaces header" from formatting result.
12214 *
12215 * Make a new #sip_replaces_t object using formatting result as its value.
12216 * The function first prints the arguments according to the format @a fmt
12217 * specified. Then it allocates a new header structure, and parses the
12218 * formatting result to the structure #sip_replaces_t.
12219 *
12220 * @param home memory home used to allocate new header structure.
12221 * @param fmt string used as a printf()-style format
12222 * @param ... argument list for format
12223 *
12224 * @return
12225 * A pointer to newly
12226 * makes header structure, or NULL upon an error.
12227 *
12228 * @HIDE
12229 *
12230 */
12231#if SU_HAVE_INLINE1
12232su_inlinestatic inline
12233#endif
12234sip_replaces_t *sip_replaces_format(su_home_t *home, char const *fmt, ...)
12235 __attribute__((__malloc__, __format__ (printf, 2, 3)));
12236
12237#if SU_HAVE_INLINE1
12238su_inlinestatic inline sip_replaces_t *sip_replaces_format(su_home_t *home, char const *fmt, ...)
12239{
12240 sip_header_t *h;
12241 va_list ap;
12242
12243 va_start(ap, fmt)__builtin_va_start(ap, fmt);
12244 h = sip_header_vformat(home, sip_replaces_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_replaces_class
), (fmt), (ap)))
;
12245 va_end(ap)__builtin_va_end(ap);
12246
12247 return (sip_replaces_t *)h;
12248}
12249#endif
12250
12251/** @} */
12252
12253/**@addtogroup sip_session_expires
12254 * @{
12255 */
12256
12257/** Parse a SIP @ref sip_session_expires "Session-Expires header". @internal */
12258SOFIAPUBFUN issize_t sip_session_expires_d(su_home_t *, msg_header_t *,
12259 char *s, isize_t slen);
12260
12261/** Print a SIP @ref sip_session_expires "Session-Expires header". @internal */
12262SOFIAPUBFUN issize_t sip_session_expires_e(char b[], isize_t bsiz,
12263 msg_header_t const *h, int flags);
12264
12265/**Access a SIP @ref sip_session_expires "Session-Expires header"
12266 * structure #sip_session_expires_t from #sip_t.
12267 *
12268 */
12269#define sip_session_expires(sip)((sip_session_expires_t *)msg_header_access((msg_pub_t*)(sip)
, sip_session_expires_class))
\
12270 ((sip_session_expires_t *)msg_header_access((msg_pub_t*)(sip), sip_session_expires_class))
12271
12272/**Initializer for structure #sip_session_expires_t.
12273 *
12274 * A static #sip_session_expires_t structure for
12275 * @ref sip_session_expires "Session-Expires header" must be initialized with
12276 * the SIP_SESSION_EXPIRES_INIT() macro.
12277 * For instance,
12278 * @code
12279 *
12280 * sip_session_expires_t sip_session_expires = SIP_SESSION_EXPIRES_INIT;
12281 *
12282 * @endcode
12283 * @HI
12284 *
12285 */
12286#define SIP_SESSION_EXPIRES_INIT(){{{ 0, 0, sip_session_expires_class }}} SIP_HDR_INIT(session_expires){{{ 0, 0, sip_session_expires_class }}}
12287
12288/**Initialize a structure #sip_session_expires_t.
12289 *
12290 * An #sip_session_expires_t structure for
12291 * @ref sip_session_expires "Session-Expires header" can be initialized with the
12292 * sip_session_expires_init() function/macro. For instance,
12293 * @code
12294 *
12295 * sip_session_expires_t sip_session_expires;
12296 *
12297 * sip_session_expires_init(&sip_session_expires);
12298 *
12299 * @endcode
12300 * @HI
12301 *
12302 */
12303#if SU_HAVE_INLINE1
12304su_inlinestatic inline sip_session_expires_t *sip_session_expires_init(sip_session_expires_t x[1])
12305{
12306 return SIP_HEADER_INIT(x, sip_session_expires_class, sizeof(sip_session_expires_t))((void)memset((x), 0, (sizeof(sip_session_expires_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_session_expires_class
)), (x))
;
12307}
12308#else
12309#define sip_session_expires_init(x) \
12310 SIP_HEADER_INIT(x, sip_session_expires_class, sizeof(sip_session_expires_t))((void)memset((x), 0, (sizeof(sip_session_expires_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_session_expires_class
)), (x))
12311#endif
12312
12313/**Test if header object is instance of #sip_session_expires_t.
12314 *
12315 * Check if the header class is an instance of
12316 * @ref sip_session_expires "Session-Expires header" object and return true (nonzero),
12317 * otherwise return false (zero).
12318 *
12319 * @param header pointer to the header structure to be tested
12320 *
12321 * @retval 1 (true) if the @a header is an instance of header session_expires
12322 * @retval 0 (false) otherwise
12323 *
12324 */
12325#if SU_HAVE_INLINE1
12326su_inlinestatic inline int sip_is_session_expires(sip_header_t const *header)
12327{
12328 return header && header->sh_classsh_common->h_class->hc_hash == sip_session_expires_hash;
12329}
12330#else
12331int sip_is_session_expires(sip_header_t const *header);
12332#endif
12333
12334#define sip_session_expires_p(h)sip_is_session_expires((h)) sip_is_session_expires((h))
12335
12336
12337/**Duplicate a list of @ref sip_session_expires "Session-Expires header" header structures #sip_session_expires_t.
12338 *
12339 * Duplicate a header
12340 * structure @a hdr. If the header structure @a hdr
12341 * contains a reference (@c hdr->x_next) to a list of
12342 * headers, all the headers in the list are duplicated, too.
12343 *
12344 * @param home memory home used to allocate new structure
12345 * @param hdr header structure to be duplicated
12346 *
12347 * When duplicating, all parameter lists and non-constant
12348 * strings attached to the header are copied, too. The
12349 * function uses given memory @a home to allocate all the
12350 * memory areas used to copy the header.
12351 *
12352 * @par Example
12353 * @code
12354 *
12355 * session_expires = sip_session_expires_dup(home, sip->sip_session_expires);
12356 *
12357 * @endcode
12358 *
12359 * @return
12360 * A pointer to the
12361 * newly duplicated #sip_session_expires_t header structure, or NULL
12362 * upon an error.
12363 *
12364 */
12365#if SU_HAVE_INLINE1
12366su_inlinestatic inline
12367#endif
12368sip_session_expires_t *sip_session_expires_dup(su_home_t *home, sip_session_expires_t const *hdr)
12369 __attribute__((__malloc__));
12370
12371#if SU_HAVE_INLINE1
12372su_inlinestatic inline
12373sip_session_expires_t *sip_session_expires_dup(su_home_t *home, sip_session_expires_t const *hdr)
12374{
12375 return (sip_session_expires_t *)
12376 msg_header_dup_as(home, sip_session_expires_class, (msg_header_t const *)hdr);
12377}
12378#endif
12379
12380/**Copy a list of @ref sip_session_expires "Session-Expires header" header structures #sip_session_expires_t.
12381 *
12382 * The function sip_session_expires_copy() copies a header structure @a
12383 * hdr. If the header structure @a hdr contains a reference (@c
12384 * hdr->h_next) to a list of headers, all the headers in that
12385 * list are copied, too. The function uses given memory @a home
12386 * to allocate all the memory areas used to copy the list of header
12387 * structure @a hdr.
12388 *
12389 * @param home memory home used to allocate new structure
12390 * @param hdr pointer to the header structure to be copied
12391 *
12392 * When copying, only the header structure and parameter lists attached to
12393 * it are duplicated. The new header structure retains all the references to
12394 * the strings within the old @a hdr header, including the encoding of the
12395 * old header, if present.
12396 *
12397 * @par Example
12398 * @code
12399 *
12400 * session_expires = sip_session_expires_copy(home, sip->sip_session_expires);
12401 *
12402 * @endcode
12403 *
12404 * @return
12405 * A pointer to newly copied header structure, or NULL upon an error.
12406 *
12407 */
12408#if SU_HAVE_INLINE1
12409su_inlinestatic inline
12410#endif
12411sip_session_expires_t *sip_session_expires_copy(su_home_t *home, sip_session_expires_t const *hdr)
12412 __attribute__((__malloc__));
12413
12414#if SU_HAVE_INLINE1
12415su_inlinestatic inline
12416sip_session_expires_t *sip_session_expires_copy(su_home_t *home, sip_session_expires_t const *hdr)
12417{
12418 return (sip_session_expires_t *)
12419 msg_header_copy_as(home, sip_session_expires_class, (msg_header_t const *)hdr);
12420}
12421#endif
12422
12423/**Make a @ref sip_session_expires "Session-Expires header" structure #sip_session_expires_t.
12424 *
12425 * The function sip_session_expires_make() makes a new
12426 * #sip_session_expires_t header structure. It allocates a new
12427 * header structure, and decodes the string @a s as the
12428 * value of the structure.
12429 *
12430 * @param home memory home used to allocate new header structure.
12431 * @param s string to be decoded as value of the new header structure
12432 *
12433 * @return
12434 * A pointer to newly maked #sip_session_expires_t header structure, or NULL upon an
12435 * error.
12436 *
12437 */
12438#if SU_HAVE_INLINE1
12439su_inlinestatic inline
12440#endif
12441sip_session_expires_t *sip_session_expires_make(su_home_t *home, char const *s)
12442 __attribute__((__malloc__));
12443
12444#if SU_HAVE_INLINE1
12445su_inlinestatic inline sip_session_expires_t *sip_session_expires_make(su_home_t *home, char const *s)
12446{
12447 return (sip_session_expires_t *)sip_header_make(home, sip_session_expires_class, s)((sip_header_t *)msg_header_make((home), (sip_session_expires_class
), (s)))
;
12448}
12449#endif
12450
12451/**Make a @ref sip_session_expires "Session-Expires header" from formatting result.
12452 *
12453 * Make a new #sip_session_expires_t object using formatting result as its value.
12454 * The function first prints the arguments according to the format @a fmt
12455 * specified. Then it allocates a new header structure, and parses the
12456 * formatting result to the structure #sip_session_expires_t.
12457 *
12458 * @param home memory home used to allocate new header structure.
12459 * @param fmt string used as a printf()-style format
12460 * @param ... argument list for format
12461 *
12462 * @return
12463 * A pointer to newly
12464 * makes header structure, or NULL upon an error.
12465 *
12466 * @HIDE
12467 *
12468 */
12469#if SU_HAVE_INLINE1
12470su_inlinestatic inline
12471#endif
12472sip_session_expires_t *sip_session_expires_format(su_home_t *home, char const *fmt, ...)
12473 __attribute__((__malloc__, __format__ (printf, 2, 3)));
12474
12475#if SU_HAVE_INLINE1
12476su_inlinestatic inline sip_session_expires_t *sip_session_expires_format(su_home_t *home, char const *fmt, ...)
12477{
12478 sip_header_t *h;
12479 va_list ap;
12480
12481 va_start(ap, fmt)__builtin_va_start(ap, fmt);
12482 h = sip_header_vformat(home, sip_session_expires_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_session_expires_class
), (fmt), (ap)))
;
12483 va_end(ap)__builtin_va_end(ap);
12484
12485 return (sip_session_expires_t *)h;
12486}
12487#endif
12488
12489/** @} */
12490
12491/**@addtogroup sip_min_se
12492 * @{
12493 */
12494
12495/** Parse a SIP @ref sip_min_se "Min-SE header". @internal */
12496SOFIAPUBFUN issize_t sip_min_se_d(su_home_t *, msg_header_t *,
12497 char *s, isize_t slen);
12498
12499/** Print a SIP @ref sip_min_se "Min-SE header". @internal */
12500SOFIAPUBFUN issize_t sip_min_se_e(char b[], isize_t bsiz,
12501 msg_header_t const *h, int flags);
12502
12503/**Access a SIP @ref sip_min_se "Min-SE header"
12504 * structure #sip_min_se_t from #sip_t.
12505 *
12506 */
12507#define sip_min_se(sip)((sip_min_se_t *)msg_header_access((msg_pub_t*)(sip), sip_min_se_class
))
\
12508 ((sip_min_se_t *)msg_header_access((msg_pub_t*)(sip), sip_min_se_class))
12509
12510/**Initializer for structure #sip_min_se_t.
12511 *
12512 * A static #sip_min_se_t structure for
12513 * @ref sip_min_se "Min-SE header" must be initialized with
12514 * the SIP_MIN_SE_INIT() macro.
12515 * For instance,
12516 * @code
12517 *
12518 * sip_min_se_t sip_min_se = SIP_MIN_SE_INIT;
12519 *
12520 * @endcode
12521 * @HI
12522 *
12523 */
12524#define SIP_MIN_SE_INIT(){{{ 0, 0, sip_min_se_class }}} SIP_HDR_INIT(min_se){{{ 0, 0, sip_min_se_class }}}
12525
12526/**Initialize a structure #sip_min_se_t.
12527 *
12528 * An #sip_min_se_t structure for
12529 * @ref sip_min_se "Min-SE header" can be initialized with the
12530 * sip_min_se_init() function/macro. For instance,
12531 * @code
12532 *
12533 * sip_min_se_t sip_min_se;
12534 *
12535 * sip_min_se_init(&sip_min_se);
12536 *
12537 * @endcode
12538 * @HI
12539 *
12540 */
12541#if SU_HAVE_INLINE1
12542su_inlinestatic inline sip_min_se_t *sip_min_se_init(sip_min_se_t x[1])
12543{
12544 return SIP_HEADER_INIT(x, sip_min_se_class, sizeof(sip_min_se_t))((void)memset((x), 0, (sizeof(sip_min_se_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_min_se_class)), (x))
;
12545}
12546#else
12547#define sip_min_se_init(x) \
12548 SIP_HEADER_INIT(x, sip_min_se_class, sizeof(sip_min_se_t))((void)memset((x), 0, (sizeof(sip_min_se_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_min_se_class)), (x))
12549#endif
12550
12551/**Test if header object is instance of #sip_min_se_t.
12552 *
12553 * Check if the header class is an instance of
12554 * @ref sip_min_se "Min-SE header" object and return true (nonzero),
12555 * otherwise return false (zero).
12556 *
12557 * @param header pointer to the header structure to be tested
12558 *
12559 * @retval 1 (true) if the @a header is an instance of header min_se
12560 * @retval 0 (false) otherwise
12561 *
12562 */
12563#if SU_HAVE_INLINE1
12564su_inlinestatic inline int sip_is_min_se(sip_header_t const *header)
12565{
12566 return header && header->sh_classsh_common->h_class->hc_hash == sip_min_se_hash;
12567}
12568#else
12569int sip_is_min_se(sip_header_t const *header);
12570#endif
12571
12572#define sip_min_se_p(h)sip_is_min_se((h)) sip_is_min_se((h))
12573
12574
12575/**Duplicate a list of @ref sip_min_se "Min-SE header" header structures #sip_min_se_t.
12576 *
12577 * Duplicate a header
12578 * structure @a hdr. If the header structure @a hdr
12579 * contains a reference (@c hdr->x_next) to a list of
12580 * headers, all the headers in the list are duplicated, too.
12581 *
12582 * @param home memory home used to allocate new structure
12583 * @param hdr header structure to be duplicated
12584 *
12585 * When duplicating, all parameter lists and non-constant
12586 * strings attached to the header are copied, too. The
12587 * function uses given memory @a home to allocate all the
12588 * memory areas used to copy the header.
12589 *
12590 * @par Example
12591 * @code
12592 *
12593 * min_se = sip_min_se_dup(home, sip->sip_min_se);
12594 *
12595 * @endcode
12596 *
12597 * @return
12598 * A pointer to the
12599 * newly duplicated #sip_min_se_t header structure, or NULL
12600 * upon an error.
12601 *
12602 */
12603#if SU_HAVE_INLINE1
12604su_inlinestatic inline
12605#endif
12606sip_min_se_t *sip_min_se_dup(su_home_t *home, sip_min_se_t const *hdr)
12607 __attribute__((__malloc__));
12608
12609#if SU_HAVE_INLINE1
12610su_inlinestatic inline
12611sip_min_se_t *sip_min_se_dup(su_home_t *home, sip_min_se_t const *hdr)
12612{
12613 return (sip_min_se_t *)
12614 msg_header_dup_as(home, sip_min_se_class, (msg_header_t const *)hdr);
12615}
12616#endif
12617
12618/**Copy a list of @ref sip_min_se "Min-SE header" header structures #sip_min_se_t.
12619 *
12620 * The function sip_min_se_copy() copies a header structure @a
12621 * hdr. If the header structure @a hdr contains a reference (@c
12622 * hdr->h_next) to a list of headers, all the headers in that
12623 * list are copied, too. The function uses given memory @a home
12624 * to allocate all the memory areas used to copy the list of header
12625 * structure @a hdr.
12626 *
12627 * @param home memory home used to allocate new structure
12628 * @param hdr pointer to the header structure to be copied
12629 *
12630 * When copying, only the header structure and parameter lists attached to
12631 * it are duplicated. The new header structure retains all the references to
12632 * the strings within the old @a hdr header, including the encoding of the
12633 * old header, if present.
12634 *
12635 * @par Example
12636 * @code
12637 *
12638 * min_se = sip_min_se_copy(home, sip->sip_min_se);
12639 *
12640 * @endcode
12641 *
12642 * @return
12643 * A pointer to newly copied header structure, or NULL upon an error.
12644 *
12645 */
12646#if SU_HAVE_INLINE1
12647su_inlinestatic inline
12648#endif
12649sip_min_se_t *sip_min_se_copy(su_home_t *home, sip_min_se_t const *hdr)
12650 __attribute__((__malloc__));
12651
12652#if SU_HAVE_INLINE1
12653su_inlinestatic inline
12654sip_min_se_t *sip_min_se_copy(su_home_t *home, sip_min_se_t const *hdr)
12655{
12656 return (sip_min_se_t *)
12657 msg_header_copy_as(home, sip_min_se_class, (msg_header_t const *)hdr);
12658}
12659#endif
12660
12661/**Make a @ref sip_min_se "Min-SE header" structure #sip_min_se_t.
12662 *
12663 * The function sip_min_se_make() makes a new
12664 * #sip_min_se_t header structure. It allocates a new
12665 * header structure, and decodes the string @a s as the
12666 * value of the structure.
12667 *
12668 * @param home memory home used to allocate new header structure.
12669 * @param s string to be decoded as value of the new header structure
12670 *
12671 * @return
12672 * A pointer to newly maked #sip_min_se_t header structure, or NULL upon an
12673 * error.
12674 *
12675 */
12676#if SU_HAVE_INLINE1
12677su_inlinestatic inline
12678#endif
12679sip_min_se_t *sip_min_se_make(su_home_t *home, char const *s)
12680 __attribute__((__malloc__));
12681
12682#if SU_HAVE_INLINE1
12683su_inlinestatic inline sip_min_se_t *sip_min_se_make(su_home_t *home, char const *s)
12684{
12685 return (sip_min_se_t *)sip_header_make(home, sip_min_se_class, s)((sip_header_t *)msg_header_make((home), (sip_min_se_class), (
s)))
;
12686}
12687#endif
12688
12689/**Make a @ref sip_min_se "Min-SE header" from formatting result.
12690 *
12691 * Make a new #sip_min_se_t object using formatting result as its value.
12692 * The function first prints the arguments according to the format @a fmt
12693 * specified. Then it allocates a new header structure, and parses the
12694 * formatting result to the structure #sip_min_se_t.
12695 *
12696 * @param home memory home used to allocate new header structure.
12697 * @param fmt string used as a printf()-style format
12698 * @param ... argument list for format
12699 *
12700 * @return
12701 * A pointer to newly
12702 * makes header structure, or NULL upon an error.
12703 *
12704 * @HIDE
12705 *
12706 */
12707#if SU_HAVE_INLINE1
12708su_inlinestatic inline
12709#endif
12710sip_min_se_t *sip_min_se_format(su_home_t *home, char const *fmt, ...)
12711 __attribute__((__malloc__, __format__ (printf, 2, 3)));
12712
12713#if SU_HAVE_INLINE1
12714su_inlinestatic inline sip_min_se_t *sip_min_se_format(su_home_t *home, char const *fmt, ...)
12715{
12716 sip_header_t *h;
12717 va_list ap;
12718
12719 va_start(ap, fmt)__builtin_va_start(ap, fmt);
12720 h = sip_header_vformat(home, sip_min_se_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_min_se_class
), (fmt), (ap)))
;
12721 va_end(ap)__builtin_va_end(ap);
12722
12723 return (sip_min_se_t *)h;
12724}
12725#endif
12726
12727/** @} */
12728
12729/**@addtogroup sip_path
12730 * @{
12731 */
12732
12733/** Parse a SIP @ref sip_path "Path header". @internal */
12734SOFIAPUBFUN issize_t sip_path_d(su_home_t *, msg_header_t *,
12735 char *s, isize_t slen);
12736
12737/** Print a SIP @ref sip_path "Path header". @internal */
12738SOFIAPUBFUN issize_t sip_path_e(char b[], isize_t bsiz,
12739 msg_header_t const *h, int flags);
12740
12741/**Access a SIP @ref sip_path "Path header"
12742 * structure #sip_path_t from #sip_t.
12743 *
12744 */
12745#define sip_path(sip)((sip_path_t *)msg_header_access((msg_pub_t*)(sip), sip_path_class
))
\
12746 ((sip_path_t *)msg_header_access((msg_pub_t*)(sip), sip_path_class))
12747
12748/**Initializer for structure #sip_path_t.
12749 *
12750 * A static #sip_path_t structure for
12751 * @ref sip_path "Path header" must be initialized with
12752 * the SIP_PATH_INIT() macro.
12753 * For instance,
12754 * @code
12755 *
12756 * sip_path_t sip_path = SIP_PATH_INIT;
12757 *
12758 * @endcode
12759 * @HI
12760 *
12761 */
12762#define SIP_PATH_INIT(){{{ 0, 0, sip_path_class }}} SIP_HDR_INIT(path){{{ 0, 0, sip_path_class }}}
12763
12764/**Initialize a structure #sip_path_t.
12765 *
12766 * An #sip_path_t structure for
12767 * @ref sip_path "Path header" can be initialized with the
12768 * sip_path_init() function/macro. For instance,
12769 * @code
12770 *
12771 * sip_path_t sip_path;
12772 *
12773 * sip_path_init(&sip_path);
12774 *
12775 * @endcode
12776 * @HI
12777 *
12778 */
12779#if SU_HAVE_INLINE1
12780su_inlinestatic inline sip_path_t *sip_path_init(sip_path_t x[1])
12781{
12782 return SIP_HEADER_INIT(x, sip_path_class, sizeof(sip_path_t))((void)memset((x), 0, (sizeof(sip_path_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_path_class)), (x))
;
12783}
12784#else
12785#define sip_path_init(x) \
12786 SIP_HEADER_INIT(x, sip_path_class, sizeof(sip_path_t))((void)memset((x), 0, (sizeof(sip_path_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_path_class)), (x))
12787#endif
12788
12789/**Test if header object is instance of #sip_path_t.
12790 *
12791 * Check if the header class is an instance of
12792 * @ref sip_path "Path header" object and return true (nonzero),
12793 * otherwise return false (zero).
12794 *
12795 * @param header pointer to the header structure to be tested
12796 *
12797 * @retval 1 (true) if the @a header is an instance of header path
12798 * @retval 0 (false) otherwise
12799 *
12800 */
12801#if SU_HAVE_INLINE1
12802su_inlinestatic inline int sip_is_path(sip_header_t const *header)
12803{
12804 return header && header->sh_classsh_common->h_class->hc_hash == sip_path_hash;
12805}
12806#else
12807int sip_is_path(sip_header_t const *header);
12808#endif
12809
12810#define sip_path_p(h)sip_is_path((h)) sip_is_path((h))
12811
12812
12813/**Duplicate a list of @ref sip_path "Path header" header structures #sip_path_t.
12814 *
12815 * Duplicate a header
12816 * structure @a hdr. If the header structure @a hdr
12817 * contains a reference (@c hdr->x_next) to a list of
12818 * headers, all the headers in the list are duplicated, too.
12819 *
12820 * @param home memory home used to allocate new structure
12821 * @param hdr header structure to be duplicated
12822 *
12823 * When duplicating, all parameter lists and non-constant
12824 * strings attached to the header are copied, too. The
12825 * function uses given memory @a home to allocate all the
12826 * memory areas used to copy the header.
12827 *
12828 * @par Example
12829 * @code
12830 *
12831 * path = sip_path_dup(home, sip->sip_path);
12832 *
12833 * @endcode
12834 *
12835 * @return
12836 * A pointer to the
12837 * newly duplicated #sip_path_t header structure, or NULL
12838 * upon an error.
12839 *
12840 */
12841#if SU_HAVE_INLINE1
12842su_inlinestatic inline
12843#endif
12844sip_path_t *sip_path_dup(su_home_t *home, sip_path_t const *hdr)
12845 __attribute__((__malloc__));
12846
12847#if SU_HAVE_INLINE1
12848su_inlinestatic inline
12849sip_path_t *sip_path_dup(su_home_t *home, sip_path_t const *hdr)
12850{
12851 return (sip_path_t *)
12852 msg_header_dup_as(home, sip_path_class, (msg_header_t const *)hdr);
12853}
12854#endif
12855
12856/**Copy a list of @ref sip_path "Path header" header structures #sip_path_t.
12857 *
12858 * The function sip_path_copy() copies a header structure @a
12859 * hdr. If the header structure @a hdr contains a reference (@c
12860 * hdr->h_next) to a list of headers, all the headers in that
12861 * list are copied, too. The function uses given memory @a home
12862 * to allocate all the memory areas used to copy the list of header
12863 * structure @a hdr.
12864 *
12865 * @param home memory home used to allocate new structure
12866 * @param hdr pointer to the header structure to be copied
12867 *
12868 * When copying, only the header structure and parameter lists attached to
12869 * it are duplicated. The new header structure retains all the references to
12870 * the strings within the old @a hdr header, including the encoding of the
12871 * old header, if present.
12872 *
12873 * @par Example
12874 * @code
12875 *
12876 * path = sip_path_copy(home, sip->sip_path);
12877 *
12878 * @endcode
12879 *
12880 * @return
12881 * A pointer to newly copied header structure, or NULL upon an error.
12882 *
12883 */
12884#if SU_HAVE_INLINE1
12885su_inlinestatic inline
12886#endif
12887sip_path_t *sip_path_copy(su_home_t *home, sip_path_t const *hdr)
12888 __attribute__((__malloc__));
12889
12890#if SU_HAVE_INLINE1
12891su_inlinestatic inline
12892sip_path_t *sip_path_copy(su_home_t *home, sip_path_t const *hdr)
12893{
12894 return (sip_path_t *)
12895 msg_header_copy_as(home, sip_path_class, (msg_header_t const *)hdr);
12896}
12897#endif
12898
12899/**Make a @ref sip_path "Path header" structure #sip_path_t.
12900 *
12901 * The function sip_path_make() makes a new
12902 * #sip_path_t header structure. It allocates a new
12903 * header structure, and decodes the string @a s as the
12904 * value of the structure.
12905 *
12906 * @param home memory home used to allocate new header structure.
12907 * @param s string to be decoded as value of the new header structure
12908 *
12909 * @return
12910 * A pointer to newly maked #sip_path_t header structure, or NULL upon an
12911 * error.
12912 *
12913 */
12914#if SU_HAVE_INLINE1
12915su_inlinestatic inline
12916#endif
12917sip_path_t *sip_path_make(su_home_t *home, char const *s)
12918 __attribute__((__malloc__));
12919
12920#if SU_HAVE_INLINE1
12921su_inlinestatic inline sip_path_t *sip_path_make(su_home_t *home, char const *s)
12922{
12923 return (sip_path_t *)sip_header_make(home, sip_path_class, s)((sip_header_t *)msg_header_make((home), (sip_path_class), (s
)))
;
12924}
12925#endif
12926
12927/**Make a @ref sip_path "Path header" from formatting result.
12928 *
12929 * Make a new #sip_path_t object using formatting result as its value.
12930 * The function first prints the arguments according to the format @a fmt
12931 * specified. Then it allocates a new header structure, and parses the
12932 * formatting result to the structure #sip_path_t.
12933 *
12934 * @param home memory home used to allocate new header structure.
12935 * @param fmt string used as a printf()-style format
12936 * @param ... argument list for format
12937 *
12938 * @return
12939 * A pointer to newly
12940 * makes header structure, or NULL upon an error.
12941 *
12942 * @HIDE
12943 *
12944 */
12945#if SU_HAVE_INLINE1
12946su_inlinestatic inline
12947#endif
12948sip_path_t *sip_path_format(su_home_t *home, char const *fmt, ...)
12949 __attribute__((__malloc__, __format__ (printf, 2, 3)));
12950
12951#if SU_HAVE_INLINE1
12952su_inlinestatic inline sip_path_t *sip_path_format(su_home_t *home, char const *fmt, ...)
12953{
12954 sip_header_t *h;
12955 va_list ap;
12956
12957 va_start(ap, fmt)__builtin_va_start(ap, fmt);
12958 h = sip_header_vformat(home, sip_path_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_path_class),
(fmt), (ap)))
;
12959 va_end(ap)__builtin_va_end(ap);
12960
12961 return (sip_path_t *)h;
12962}
12963#endif
12964
12965/** @} */
12966
12967/**@addtogroup sip_service_route
12968 * @{
12969 */
12970
12971/** Parse a SIP @ref sip_service_route "Service-Route header". @internal */
12972SOFIAPUBFUN issize_t sip_service_route_d(su_home_t *, msg_header_t *,
12973 char *s, isize_t slen);
12974
12975/** Print a SIP @ref sip_service_route "Service-Route header". @internal */
12976SOFIAPUBFUN issize_t sip_service_route_e(char b[], isize_t bsiz,
12977 msg_header_t const *h, int flags);
12978
12979/**Access a SIP @ref sip_service_route "Service-Route header"
12980 * structure #sip_service_route_t from #sip_t.
12981 *
12982 */
12983#define sip_service_route(sip)((sip_service_route_t *)msg_header_access((msg_pub_t*)(sip), sip_service_route_class
))
\
12984 ((sip_service_route_t *)msg_header_access((msg_pub_t*)(sip), sip_service_route_class))
12985
12986/**Initializer for structure #sip_service_route_t.
12987 *
12988 * A static #sip_service_route_t structure for
12989 * @ref sip_service_route "Service-Route header" must be initialized with
12990 * the SIP_SERVICE_ROUTE_INIT() macro.
12991 * For instance,
12992 * @code
12993 *
12994 * sip_service_route_t sip_service_route = SIP_SERVICE_ROUTE_INIT;
12995 *
12996 * @endcode
12997 * @HI
12998 *
12999 */
13000#define SIP_SERVICE_ROUTE_INIT(){{{ 0, 0, sip_service_route_class }}} SIP_HDR_INIT(service_route){{{ 0, 0, sip_service_route_class }}}
13001
13002/**Initialize a structure #sip_service_route_t.
13003 *
13004 * An #sip_service_route_t structure for
13005 * @ref sip_service_route "Service-Route header" can be initialized with the
13006 * sip_service_route_init() function/macro. For instance,
13007 * @code
13008 *
13009 * sip_service_route_t sip_service_route;
13010 *
13011 * sip_service_route_init(&sip_service_route);
13012 *
13013 * @endcode
13014 * @HI
13015 *
13016 */
13017#if SU_HAVE_INLINE1
13018su_inlinestatic inline sip_service_route_t *sip_service_route_init(sip_service_route_t x[1])
13019{
13020 return SIP_HEADER_INIT(x, sip_service_route_class, sizeof(sip_service_route_t))((void)memset((x), 0, (sizeof(sip_service_route_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_service_route_class)
), (x))
;
13021}
13022#else
13023#define sip_service_route_init(x) \
13024 SIP_HEADER_INIT(x, sip_service_route_class, sizeof(sip_service_route_t))((void)memset((x), 0, (sizeof(sip_service_route_t))), (void)(
((sip_common_t *)(x))->h_class = (sip_service_route_class)
), (x))
13025#endif
13026
13027/**Test if header object is instance of #sip_service_route_t.
13028 *
13029 * Check if the header class is an instance of
13030 * @ref sip_service_route "Service-Route header" object and return true (nonzero),
13031 * otherwise return false (zero).
13032 *
13033 * @param header pointer to the header structure to be tested
13034 *
13035 * @retval 1 (true) if the @a header is an instance of header service_route
13036 * @retval 0 (false) otherwise
13037 *
13038 */
13039#if SU_HAVE_INLINE1
13040su_inlinestatic inline int sip_is_service_route(sip_header_t const *header)
13041{
13042 return header && header->sh_classsh_common->h_class->hc_hash == sip_service_route_hash;
13043}
13044#else
13045int sip_is_service_route(sip_header_t const *header);
13046#endif
13047
13048#define sip_service_route_p(h)sip_is_service_route((h)) sip_is_service_route((h))
13049
13050
13051/**Duplicate a list of @ref sip_service_route "Service-Route header" header structures #sip_service_route_t.
13052 *
13053 * Duplicate a header
13054 * structure @a hdr. If the header structure @a hdr
13055 * contains a reference (@c hdr->x_next) to a list of
13056 * headers, all the headers in the list are duplicated, too.
13057 *
13058 * @param home memory home used to allocate new structure
13059 * @param hdr header structure to be duplicated
13060 *
13061 * When duplicating, all parameter lists and non-constant
13062 * strings attached to the header are copied, too. The
13063 * function uses given memory @a home to allocate all the
13064 * memory areas used to copy the header.
13065 *
13066 * @par Example
13067 * @code
13068 *
13069 * service_route = sip_service_route_dup(home, sip->sip_service_route);
13070 *
13071 * @endcode
13072 *
13073 * @return
13074 * A pointer to the
13075 * newly duplicated #sip_service_route_t header structure, or NULL
13076 * upon an error.
13077 *
13078 */
13079#if SU_HAVE_INLINE1
13080su_inlinestatic inline
13081#endif
13082sip_service_route_t *sip_service_route_dup(su_home_t *home, sip_service_route_t const *hdr)
13083 __attribute__((__malloc__));
13084
13085#if SU_HAVE_INLINE1
13086su_inlinestatic inline
13087sip_service_route_t *sip_service_route_dup(su_home_t *home, sip_service_route_t const *hdr)
13088{
13089 return (sip_service_route_t *)
13090 msg_header_dup_as(home, sip_service_route_class, (msg_header_t const *)hdr);
13091}
13092#endif
13093
13094/**Copy a list of @ref sip_service_route "Service-Route header" header structures #sip_service_route_t.
13095 *
13096 * The function sip_service_route_copy() copies a header structure @a
13097 * hdr. If the header structure @a hdr contains a reference (@c
13098 * hdr->h_next) to a list of headers, all the headers in that
13099 * list are copied, too. The function uses given memory @a home
13100 * to allocate all the memory areas used to copy the list of header
13101 * structure @a hdr.
13102 *
13103 * @param home memory home used to allocate new structure
13104 * @param hdr pointer to the header structure to be copied
13105 *
13106 * When copying, only the header structure and parameter lists attached to
13107 * it are duplicated. The new header structure retains all the references to
13108 * the strings within the old @a hdr header, including the encoding of the
13109 * old header, if present.
13110 *
13111 * @par Example
13112 * @code
13113 *
13114 * service_route = sip_service_route_copy(home, sip->sip_service_route);
13115 *
13116 * @endcode
13117 *
13118 * @return
13119 * A pointer to newly copied header structure, or NULL upon an error.
13120 *
13121 */
13122#if SU_HAVE_INLINE1
13123su_inlinestatic inline
13124#endif
13125sip_service_route_t *sip_service_route_copy(su_home_t *home, sip_service_route_t const *hdr)
13126 __attribute__((__malloc__));
13127
13128#if SU_HAVE_INLINE1
13129su_inlinestatic inline
13130sip_service_route_t *sip_service_route_copy(su_home_t *home, sip_service_route_t const *hdr)
13131{
13132 return (sip_service_route_t *)
13133 msg_header_copy_as(home, sip_service_route_class, (msg_header_t const *)hdr);
13134}
13135#endif
13136
13137/**Make a @ref sip_service_route "Service-Route header" structure #sip_service_route_t.
13138 *
13139 * The function sip_service_route_make() makes a new
13140 * #sip_service_route_t header structure. It allocates a new
13141 * header structure, and decodes the string @a s as the
13142 * value of the structure.
13143 *
13144 * @param home memory home used to allocate new header structure.
13145 * @param s string to be decoded as value of the new header structure
13146 *
13147 * @return
13148 * A pointer to newly maked #sip_service_route_t header structure, or NULL upon an
13149 * error.
13150 *
13151 */
13152#if SU_HAVE_INLINE1
13153su_inlinestatic inline
13154#endif
13155sip_service_route_t *sip_service_route_make(su_home_t *home, char const *s)
13156 __attribute__((__malloc__));
13157
13158#if SU_HAVE_INLINE1
13159su_inlinestatic inline sip_service_route_t *sip_service_route_make(su_home_t *home, char const *s)
13160{
13161 return (sip_service_route_t *)sip_header_make(home, sip_service_route_class, s)((sip_header_t *)msg_header_make((home), (sip_service_route_class
), (s)))
;
13162}
13163#endif
13164
13165/**Make a @ref sip_service_route "Service-Route header" from formatting result.
13166 *
13167 * Make a new #sip_service_route_t object using formatting result as its value.
13168 * The function first prints the arguments according to the format @a fmt
13169 * specified. Then it allocates a new header structure, and parses the
13170 * formatting result to the structure #sip_service_route_t.
13171 *
13172 * @param home memory home used to allocate new header structure.
13173 * @param fmt string used as a printf()-style format
13174 * @param ... argument list for format
13175 *
13176 * @return
13177 * A pointer to newly
13178 * makes header structure, or NULL upon an error.
13179 *
13180 * @HIDE
13181 *
13182 */
13183#if SU_HAVE_INLINE1
13184su_inlinestatic inline
13185#endif
13186sip_service_route_t *sip_service_route_format(su_home_t *home, char const *fmt, ...)
13187 __attribute__((__malloc__, __format__ (printf, 2, 3)));
13188
13189#if SU_HAVE_INLINE1
13190su_inlinestatic inline sip_service_route_t *sip_service_route_format(su_home_t *home, char const *fmt, ...)
13191{
13192 sip_header_t *h;
13193 va_list ap;
13194
13195 va_start(ap, fmt)__builtin_va_start(ap, fmt);
13196 h = sip_header_vformat(home, sip_service_route_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_service_route_class
), (fmt), (ap)))
;
13197 va_end(ap)__builtin_va_end(ap);
13198
13199 return (sip_service_route_t *)h;
13200}
13201#endif
13202
13203/** @} */
13204
13205/**@addtogroup sip_reason
13206 * @{
13207 */
13208
13209/** Parse a SIP @ref sip_reason "Reason header". @internal */
13210SOFIAPUBFUN issize_t sip_reason_d(su_home_t *, msg_header_t *,
13211 char *s, isize_t slen);
13212
13213/** Print a SIP @ref sip_reason "Reason header". @internal */
13214SOFIAPUBFUN issize_t sip_reason_e(char b[], isize_t bsiz,
13215 msg_header_t const *h, int flags);
13216
13217/**Access a SIP @ref sip_reason "Reason header"
13218 * structure #sip_reason_t from #sip_t.
13219 *
13220 */
13221#define sip_reason(sip)((sip_reason_t *)msg_header_access((msg_pub_t*)(sip), sip_reason_class
))
\
13222 ((sip_reason_t *)msg_header_access((msg_pub_t*)(sip), sip_reason_class))
13223
13224/**Initializer for structure #sip_reason_t.
13225 *
13226 * A static #sip_reason_t structure for
13227 * @ref sip_reason "Reason header" must be initialized with
13228 * the SIP_REASON_INIT() macro.
13229 * For instance,
13230 * @code
13231 *
13232 * sip_reason_t sip_reason = SIP_REASON_INIT;
13233 *
13234 * @endcode
13235 * @HI
13236 *
13237 */
13238#define SIP_REASON_INIT(){{{ 0, 0, sip_reason_class }}} SIP_HDR_INIT(reason){{{ 0, 0, sip_reason_class }}}
13239
13240/**Initialize a structure #sip_reason_t.
13241 *
13242 * An #sip_reason_t structure for
13243 * @ref sip_reason "Reason header" can be initialized with the
13244 * sip_reason_init() function/macro. For instance,
13245 * @code
13246 *
13247 * sip_reason_t sip_reason;
13248 *
13249 * sip_reason_init(&sip_reason);
13250 *
13251 * @endcode
13252 * @HI
13253 *
13254 */
13255#if SU_HAVE_INLINE1
13256su_inlinestatic inline sip_reason_t *sip_reason_init(sip_reason_t x[1])
13257{
13258 return SIP_HEADER_INIT(x, sip_reason_class, sizeof(sip_reason_t))((void)memset((x), 0, (sizeof(sip_reason_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_reason_class)), (x))
;
13259}
13260#else
13261#define sip_reason_init(x) \
13262 SIP_HEADER_INIT(x, sip_reason_class, sizeof(sip_reason_t))((void)memset((x), 0, (sizeof(sip_reason_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_reason_class)), (x))
13263#endif
13264
13265/**Test if header object is instance of #sip_reason_t.
13266 *
13267 * Check if the header class is an instance of
13268 * @ref sip_reason "Reason header" object and return true (nonzero),
13269 * otherwise return false (zero).
13270 *
13271 * @param header pointer to the header structure to be tested
13272 *
13273 * @retval 1 (true) if the @a header is an instance of header reason
13274 * @retval 0 (false) otherwise
13275 *
13276 */
13277#if SU_HAVE_INLINE1
13278su_inlinestatic inline int sip_is_reason(sip_header_t const *header)
13279{
13280 return header && header->sh_classsh_common->h_class->hc_hash == sip_reason_hash;
13281}
13282#else
13283int sip_is_reason(sip_header_t const *header);
13284#endif
13285
13286#define sip_reason_p(h)sip_is_reason((h)) sip_is_reason((h))
13287
13288
13289/**Duplicate a list of @ref sip_reason "Reason header" header structures #sip_reason_t.
13290 *
13291 * Duplicate a header
13292 * structure @a hdr. If the header structure @a hdr
13293 * contains a reference (@c hdr->x_next) to a list of
13294 * headers, all the headers in the list are duplicated, too.
13295 *
13296 * @param home memory home used to allocate new structure
13297 * @param hdr header structure to be duplicated
13298 *
13299 * When duplicating, all parameter lists and non-constant
13300 * strings attached to the header are copied, too. The
13301 * function uses given memory @a home to allocate all the
13302 * memory areas used to copy the header.
13303 *
13304 * @par Example
13305 * @code
13306 *
13307 * reason = sip_reason_dup(home, sip->sip_reason);
13308 *
13309 * @endcode
13310 *
13311 * @return
13312 * A pointer to the
13313 * newly duplicated #sip_reason_t header structure, or NULL
13314 * upon an error.
13315 *
13316 */
13317#if SU_HAVE_INLINE1
13318su_inlinestatic inline
13319#endif
13320sip_reason_t *sip_reason_dup(su_home_t *home, sip_reason_t const *hdr)
13321 __attribute__((__malloc__));
13322
13323#if SU_HAVE_INLINE1
13324su_inlinestatic inline
13325sip_reason_t *sip_reason_dup(su_home_t *home, sip_reason_t const *hdr)
13326{
13327 return (sip_reason_t *)
13328 msg_header_dup_as(home, sip_reason_class, (msg_header_t const *)hdr);
13329}
13330#endif
13331
13332/**Copy a list of @ref sip_reason "Reason header" header structures #sip_reason_t.
13333 *
13334 * The function sip_reason_copy() copies a header structure @a
13335 * hdr. If the header structure @a hdr contains a reference (@c
13336 * hdr->h_next) to a list of headers, all the headers in that
13337 * list are copied, too. The function uses given memory @a home
13338 * to allocate all the memory areas used to copy the list of header
13339 * structure @a hdr.
13340 *
13341 * @param home memory home used to allocate new structure
13342 * @param hdr pointer to the header structure to be copied
13343 *
13344 * When copying, only the header structure and parameter lists attached to
13345 * it are duplicated. The new header structure retains all the references to
13346 * the strings within the old @a hdr header, including the encoding of the
13347 * old header, if present.
13348 *
13349 * @par Example
13350 * @code
13351 *
13352 * reason = sip_reason_copy(home, sip->sip_reason);
13353 *
13354 * @endcode
13355 *
13356 * @return
13357 * A pointer to newly copied header structure, or NULL upon an error.
13358 *
13359 */
13360#if SU_HAVE_INLINE1
13361su_inlinestatic inline
13362#endif
13363sip_reason_t *sip_reason_copy(su_home_t *home, sip_reason_t const *hdr)
13364 __attribute__((__malloc__));
13365
13366#if SU_HAVE_INLINE1
13367su_inlinestatic inline
13368sip_reason_t *sip_reason_copy(su_home_t *home, sip_reason_t const *hdr)
13369{
13370 return (sip_reason_t *)
13371 msg_header_copy_as(home, sip_reason_class, (msg_header_t const *)hdr);
13372}
13373#endif
13374
13375/**Make a @ref sip_reason "Reason header" structure #sip_reason_t.
13376 *
13377 * The function sip_reason_make() makes a new
13378 * #sip_reason_t header structure. It allocates a new
13379 * header structure, and decodes the string @a s as the
13380 * value of the structure.
13381 *
13382 * @param home memory home used to allocate new header structure.
13383 * @param s string to be decoded as value of the new header structure
13384 *
13385 * @return
13386 * A pointer to newly maked #sip_reason_t header structure, or NULL upon an
13387 * error.
13388 *
13389 */
13390#if SU_HAVE_INLINE1
13391su_inlinestatic inline
13392#endif
13393sip_reason_t *sip_reason_make(su_home_t *home, char const *s)
13394 __attribute__((__malloc__));
13395
13396#if SU_HAVE_INLINE1
13397su_inlinestatic inline sip_reason_t *sip_reason_make(su_home_t *home, char const *s)
13398{
13399 return (sip_reason_t *)sip_header_make(home, sip_reason_class, s)((sip_header_t *)msg_header_make((home), (sip_reason_class), (
s)))
;
13400}
13401#endif
13402
13403/**Make a @ref sip_reason "Reason header" from formatting result.
13404 *
13405 * Make a new #sip_reason_t object using formatting result as its value.
13406 * The function first prints the arguments according to the format @a fmt
13407 * specified. Then it allocates a new header structure, and parses the
13408 * formatting result to the structure #sip_reason_t.
13409 *
13410 * @param home memory home used to allocate new header structure.
13411 * @param fmt string used as a printf()-style format
13412 * @param ... argument list for format
13413 *
13414 * @return
13415 * A pointer to newly
13416 * makes header structure, or NULL upon an error.
13417 *
13418 * @HIDE
13419 *
13420 */
13421#if SU_HAVE_INLINE1
13422su_inlinestatic inline
13423#endif
13424sip_reason_t *sip_reason_format(su_home_t *home, char const *fmt, ...)
13425 __attribute__((__malloc__, __format__ (printf, 2, 3)));
13426
13427#if SU_HAVE_INLINE1
13428su_inlinestatic inline sip_reason_t *sip_reason_format(su_home_t *home, char const *fmt, ...)
13429{
13430 sip_header_t *h;
13431 va_list ap;
13432
13433 va_start(ap, fmt)__builtin_va_start(ap, fmt);
13434 h = sip_header_vformat(home, sip_reason_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_reason_class
), (fmt), (ap)))
;
13435 va_end(ap)__builtin_va_end(ap);
13436
13437 return (sip_reason_t *)h;
13438}
13439#endif
13440
13441/** @} */
13442
13443/**@addtogroup sip_security_client
13444 * @{
13445 */
13446
13447/** Parse a SIP @ref sip_security_client "Security-Client header". @internal */
13448SOFIAPUBFUN issize_t sip_security_client_d(su_home_t *, msg_header_t *,
13449 char *s, isize_t slen);
13450
13451/** Print a SIP @ref sip_security_client "Security-Client header". @internal */
13452SOFIAPUBFUN issize_t sip_security_client_e(char b[], isize_t bsiz,
13453 msg_header_t const *h, int flags);
13454
13455/**Access a SIP @ref sip_security_client "Security-Client header"
13456 * structure #sip_security_client_t from #sip_t.
13457 *
13458 */
13459#define sip_security_client(sip)((sip_security_client_t *)msg_header_access((msg_pub_t*)(sip)
, sip_security_client_class))
\
13460 ((sip_security_client_t *)msg_header_access((msg_pub_t*)(sip), sip_security_client_class))
13461
13462/**Initializer for structure #sip_security_client_t.
13463 *
13464 * A static #sip_security_client_t structure for
13465 * @ref sip_security_client "Security-Client header" must be initialized with
13466 * the SIP_SECURITY_CLIENT_INIT() macro.
13467 * For instance,
13468 * @code
13469 *
13470 * sip_security_client_t sip_security_client = SIP_SECURITY_CLIENT_INIT;
13471 *
13472 * @endcode
13473 * @HI
13474 *
13475 */
13476#define SIP_SECURITY_CLIENT_INIT(){{{ 0, 0, sip_security_client_class }}} SIP_HDR_INIT(security_client){{{ 0, 0, sip_security_client_class }}}
13477
13478/**Initialize a structure #sip_security_client_t.
13479 *
13480 * An #sip_security_client_t structure for
13481 * @ref sip_security_client "Security-Client header" can be initialized with the
13482 * sip_security_client_init() function/macro. For instance,
13483 * @code
13484 *
13485 * sip_security_client_t sip_security_client;
13486 *
13487 * sip_security_client_init(&sip_security_client);
13488 *
13489 * @endcode
13490 * @HI
13491 *
13492 */
13493#if SU_HAVE_INLINE1
13494su_inlinestatic inline sip_security_client_t *sip_security_client_init(sip_security_client_t x[1])
13495{
13496 return SIP_HEADER_INIT(x, sip_security_client_class, sizeof(sip_security_client_t))((void)memset((x), 0, (sizeof(sip_security_client_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_client_class
)), (x))
;
13497}
13498#else
13499#define sip_security_client_init(x) \
13500 SIP_HEADER_INIT(x, sip_security_client_class, sizeof(sip_security_client_t))((void)memset((x), 0, (sizeof(sip_security_client_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_client_class
)), (x))
13501#endif
13502
13503/**Test if header object is instance of #sip_security_client_t.
13504 *
13505 * Check if the header class is an instance of
13506 * @ref sip_security_client "Security-Client header" object and return true (nonzero),
13507 * otherwise return false (zero).
13508 *
13509 * @param header pointer to the header structure to be tested
13510 *
13511 * @retval 1 (true) if the @a header is an instance of header security_client
13512 * @retval 0 (false) otherwise
13513 *
13514 */
13515#if SU_HAVE_INLINE1
13516su_inlinestatic inline int sip_is_security_client(sip_header_t const *header)
13517{
13518 return header && header->sh_classsh_common->h_class->hc_hash == sip_security_client_hash;
13519}
13520#else
13521int sip_is_security_client(sip_header_t const *header);
13522#endif
13523
13524#define sip_security_client_p(h)sip_is_security_client((h)) sip_is_security_client((h))
13525
13526
13527/**Duplicate a list of @ref sip_security_client "Security-Client header" header structures #sip_security_client_t.
13528 *
13529 * Duplicate a header
13530 * structure @a hdr. If the header structure @a hdr
13531 * contains a reference (@c hdr->x_next) to a list of
13532 * headers, all the headers in the list are duplicated, too.
13533 *
13534 * @param home memory home used to allocate new structure
13535 * @param hdr header structure to be duplicated
13536 *
13537 * When duplicating, all parameter lists and non-constant
13538 * strings attached to the header are copied, too. The
13539 * function uses given memory @a home to allocate all the
13540 * memory areas used to copy the header.
13541 *
13542 * @par Example
13543 * @code
13544 *
13545 * security_client = sip_security_client_dup(home, sip->sip_security_client);
13546 *
13547 * @endcode
13548 *
13549 * @return
13550 * A pointer to the
13551 * newly duplicated #sip_security_client_t header structure, or NULL
13552 * upon an error.
13553 *
13554 */
13555#if SU_HAVE_INLINE1
13556su_inlinestatic inline
13557#endif
13558sip_security_client_t *sip_security_client_dup(su_home_t *home, sip_security_client_t const *hdr)
13559 __attribute__((__malloc__));
13560
13561#if SU_HAVE_INLINE1
13562su_inlinestatic inline
13563sip_security_client_t *sip_security_client_dup(su_home_t *home, sip_security_client_t const *hdr)
13564{
13565 return (sip_security_client_t *)
13566 msg_header_dup_as(home, sip_security_client_class, (msg_header_t const *)hdr);
13567}
13568#endif
13569
13570/**Copy a list of @ref sip_security_client "Security-Client header" header structures #sip_security_client_t.
13571 *
13572 * The function sip_security_client_copy() copies a header structure @a
13573 * hdr. If the header structure @a hdr contains a reference (@c
13574 * hdr->h_next) to a list of headers, all the headers in that
13575 * list are copied, too. The function uses given memory @a home
13576 * to allocate all the memory areas used to copy the list of header
13577 * structure @a hdr.
13578 *
13579 * @param home memory home used to allocate new structure
13580 * @param hdr pointer to the header structure to be copied
13581 *
13582 * When copying, only the header structure and parameter lists attached to
13583 * it are duplicated. The new header structure retains all the references to
13584 * the strings within the old @a hdr header, including the encoding of the
13585 * old header, if present.
13586 *
13587 * @par Example
13588 * @code
13589 *
13590 * security_client = sip_security_client_copy(home, sip->sip_security_client);
13591 *
13592 * @endcode
13593 *
13594 * @return
13595 * A pointer to newly copied header structure, or NULL upon an error.
13596 *
13597 */
13598#if SU_HAVE_INLINE1
13599su_inlinestatic inline
13600#endif
13601sip_security_client_t *sip_security_client_copy(su_home_t *home, sip_security_client_t const *hdr)
13602 __attribute__((__malloc__));
13603
13604#if SU_HAVE_INLINE1
13605su_inlinestatic inline
13606sip_security_client_t *sip_security_client_copy(su_home_t *home, sip_security_client_t const *hdr)
13607{
13608 return (sip_security_client_t *)
13609 msg_header_copy_as(home, sip_security_client_class, (msg_header_t const *)hdr);
13610}
13611#endif
13612
13613/**Make a @ref sip_security_client "Security-Client header" structure #sip_security_client_t.
13614 *
13615 * The function sip_security_client_make() makes a new
13616 * #sip_security_client_t header structure. It allocates a new
13617 * header structure, and decodes the string @a s as the
13618 * value of the structure.
13619 *
13620 * @param home memory home used to allocate new header structure.
13621 * @param s string to be decoded as value of the new header structure
13622 *
13623 * @return
13624 * A pointer to newly maked #sip_security_client_t header structure, or NULL upon an
13625 * error.
13626 *
13627 */
13628#if SU_HAVE_INLINE1
13629su_inlinestatic inline
13630#endif
13631sip_security_client_t *sip_security_client_make(su_home_t *home, char const *s)
13632 __attribute__((__malloc__));
13633
13634#if SU_HAVE_INLINE1
13635su_inlinestatic inline sip_security_client_t *sip_security_client_make(su_home_t *home, char const *s)
13636{
13637 return (sip_security_client_t *)sip_header_make(home, sip_security_client_class, s)((sip_header_t *)msg_header_make((home), (sip_security_client_class
), (s)))
;
13638}
13639#endif
13640
13641/**Make a @ref sip_security_client "Security-Client header" from formatting result.
13642 *
13643 * Make a new #sip_security_client_t object using formatting result as its value.
13644 * The function first prints the arguments according to the format @a fmt
13645 * specified. Then it allocates a new header structure, and parses the
13646 * formatting result to the structure #sip_security_client_t.
13647 *
13648 * @param home memory home used to allocate new header structure.
13649 * @param fmt string used as a printf()-style format
13650 * @param ... argument list for format
13651 *
13652 * @return
13653 * A pointer to newly
13654 * makes header structure, or NULL upon an error.
13655 *
13656 * @HIDE
13657 *
13658 */
13659#if SU_HAVE_INLINE1
13660su_inlinestatic inline
13661#endif
13662sip_security_client_t *sip_security_client_format(su_home_t *home, char const *fmt, ...)
13663 __attribute__((__malloc__, __format__ (printf, 2, 3)));
13664
13665#if SU_HAVE_INLINE1
13666su_inlinestatic inline sip_security_client_t *sip_security_client_format(su_home_t *home, char const *fmt, ...)
13667{
13668 sip_header_t *h;
13669 va_list ap;
13670
13671 va_start(ap, fmt)__builtin_va_start(ap, fmt);
13672 h = sip_header_vformat(home, sip_security_client_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_security_client_class
), (fmt), (ap)))
;
13673 va_end(ap)__builtin_va_end(ap);
13674
13675 return (sip_security_client_t *)h;
13676}
13677#endif
13678
13679/** @} */
13680
13681/**@addtogroup sip_security_server
13682 * @{
13683 */
13684
13685/** Parse a SIP @ref sip_security_server "Security-Server header". @internal */
13686SOFIAPUBFUN issize_t sip_security_server_d(su_home_t *, msg_header_t *,
13687 char *s, isize_t slen);
13688
13689/** Print a SIP @ref sip_security_server "Security-Server header". @internal */
13690SOFIAPUBFUN issize_t sip_security_server_e(char b[], isize_t bsiz,
13691 msg_header_t const *h, int flags);
13692
13693/**Access a SIP @ref sip_security_server "Security-Server header"
13694 * structure #sip_security_server_t from #sip_t.
13695 *
13696 */
13697#define sip_security_server(sip)((sip_security_server_t *)msg_header_access((msg_pub_t*)(sip)
, sip_security_server_class))
\
13698 ((sip_security_server_t *)msg_header_access((msg_pub_t*)(sip), sip_security_server_class))
13699
13700/**Initializer for structure #sip_security_server_t.
13701 *
13702 * A static #sip_security_server_t structure for
13703 * @ref sip_security_server "Security-Server header" must be initialized with
13704 * the SIP_SECURITY_SERVER_INIT() macro.
13705 * For instance,
13706 * @code
13707 *
13708 * sip_security_server_t sip_security_server = SIP_SECURITY_SERVER_INIT;
13709 *
13710 * @endcode
13711 * @HI
13712 *
13713 */
13714#define SIP_SECURITY_SERVER_INIT(){{{ 0, 0, sip_security_server_class }}} SIP_HDR_INIT(security_server){{{ 0, 0, sip_security_server_class }}}
13715
13716/**Initialize a structure #sip_security_server_t.
13717 *
13718 * An #sip_security_server_t structure for
13719 * @ref sip_security_server "Security-Server header" can be initialized with the
13720 * sip_security_server_init() function/macro. For instance,
13721 * @code
13722 *
13723 * sip_security_server_t sip_security_server;
13724 *
13725 * sip_security_server_init(&sip_security_server);
13726 *
13727 * @endcode
13728 * @HI
13729 *
13730 */
13731#if SU_HAVE_INLINE1
13732su_inlinestatic inline sip_security_server_t *sip_security_server_init(sip_security_server_t x[1])
13733{
13734 return SIP_HEADER_INIT(x, sip_security_server_class, sizeof(sip_security_server_t))((void)memset((x), 0, (sizeof(sip_security_server_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_server_class
)), (x))
;
13735}
13736#else
13737#define sip_security_server_init(x) \
13738 SIP_HEADER_INIT(x, sip_security_server_class, sizeof(sip_security_server_t))((void)memset((x), 0, (sizeof(sip_security_server_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_server_class
)), (x))
13739#endif
13740
13741/**Test if header object is instance of #sip_security_server_t.
13742 *
13743 * Check if the header class is an instance of
13744 * @ref sip_security_server "Security-Server header" object and return true (nonzero),
13745 * otherwise return false (zero).
13746 *
13747 * @param header pointer to the header structure to be tested
13748 *
13749 * @retval 1 (true) if the @a header is an instance of header security_server
13750 * @retval 0 (false) otherwise
13751 *
13752 */
13753#if SU_HAVE_INLINE1
13754su_inlinestatic inline int sip_is_security_server(sip_header_t const *header)
13755{
13756 return header && header->sh_classsh_common->h_class->hc_hash == sip_security_server_hash;
13757}
13758#else
13759int sip_is_security_server(sip_header_t const *header);
13760#endif
13761
13762#define sip_security_server_p(h)sip_is_security_server((h)) sip_is_security_server((h))
13763
13764
13765/**Duplicate a list of @ref sip_security_server "Security-Server header" header structures #sip_security_server_t.
13766 *
13767 * Duplicate a header
13768 * structure @a hdr. If the header structure @a hdr
13769 * contains a reference (@c hdr->x_next) to a list of
13770 * headers, all the headers in the list are duplicated, too.
13771 *
13772 * @param home memory home used to allocate new structure
13773 * @param hdr header structure to be duplicated
13774 *
13775 * When duplicating, all parameter lists and non-constant
13776 * strings attached to the header are copied, too. The
13777 * function uses given memory @a home to allocate all the
13778 * memory areas used to copy the header.
13779 *
13780 * @par Example
13781 * @code
13782 *
13783 * security_server = sip_security_server_dup(home, sip->sip_security_server);
13784 *
13785 * @endcode
13786 *
13787 * @return
13788 * A pointer to the
13789 * newly duplicated #sip_security_server_t header structure, or NULL
13790 * upon an error.
13791 *
13792 */
13793#if SU_HAVE_INLINE1
13794su_inlinestatic inline
13795#endif
13796sip_security_server_t *sip_security_server_dup(su_home_t *home, sip_security_server_t const *hdr)
13797 __attribute__((__malloc__));
13798
13799#if SU_HAVE_INLINE1
13800su_inlinestatic inline
13801sip_security_server_t *sip_security_server_dup(su_home_t *home, sip_security_server_t const *hdr)
13802{
13803 return (sip_security_server_t *)
13804 msg_header_dup_as(home, sip_security_server_class, (msg_header_t const *)hdr);
13805}
13806#endif
13807
13808/**Copy a list of @ref sip_security_server "Security-Server header" header structures #sip_security_server_t.
13809 *
13810 * The function sip_security_server_copy() copies a header structure @a
13811 * hdr. If the header structure @a hdr contains a reference (@c
13812 * hdr->h_next) to a list of headers, all the headers in that
13813 * list are copied, too. The function uses given memory @a home
13814 * to allocate all the memory areas used to copy the list of header
13815 * structure @a hdr.
13816 *
13817 * @param home memory home used to allocate new structure
13818 * @param hdr pointer to the header structure to be copied
13819 *
13820 * When copying, only the header structure and parameter lists attached to
13821 * it are duplicated. The new header structure retains all the references to
13822 * the strings within the old @a hdr header, including the encoding of the
13823 * old header, if present.
13824 *
13825 * @par Example
13826 * @code
13827 *
13828 * security_server = sip_security_server_copy(home, sip->sip_security_server);
13829 *
13830 * @endcode
13831 *
13832 * @return
13833 * A pointer to newly copied header structure, or NULL upon an error.
13834 *
13835 */
13836#if SU_HAVE_INLINE1
13837su_inlinestatic inline
13838#endif
13839sip_security_server_t *sip_security_server_copy(su_home_t *home, sip_security_server_t const *hdr)
13840 __attribute__((__malloc__));
13841
13842#if SU_HAVE_INLINE1
13843su_inlinestatic inline
13844sip_security_server_t *sip_security_server_copy(su_home_t *home, sip_security_server_t const *hdr)
13845{
13846 return (sip_security_server_t *)
13847 msg_header_copy_as(home, sip_security_server_class, (msg_header_t const *)hdr);
13848}
13849#endif
13850
13851/**Make a @ref sip_security_server "Security-Server header" structure #sip_security_server_t.
13852 *
13853 * The function sip_security_server_make() makes a new
13854 * #sip_security_server_t header structure. It allocates a new
13855 * header structure, and decodes the string @a s as the
13856 * value of the structure.
13857 *
13858 * @param home memory home used to allocate new header structure.
13859 * @param s string to be decoded as value of the new header structure
13860 *
13861 * @return
13862 * A pointer to newly maked #sip_security_server_t header structure, or NULL upon an
13863 * error.
13864 *
13865 */
13866#if SU_HAVE_INLINE1
13867su_inlinestatic inline
13868#endif
13869sip_security_server_t *sip_security_server_make(su_home_t *home, char const *s)
13870 __attribute__((__malloc__));
13871
13872#if SU_HAVE_INLINE1
13873su_inlinestatic inline sip_security_server_t *sip_security_server_make(su_home_t *home, char const *s)
13874{
13875 return (sip_security_server_t *)sip_header_make(home, sip_security_server_class, s)((sip_header_t *)msg_header_make((home), (sip_security_server_class
), (s)))
;
13876}
13877#endif
13878
13879/**Make a @ref sip_security_server "Security-Server header" from formatting result.
13880 *
13881 * Make a new #sip_security_server_t object using formatting result as its value.
13882 * The function first prints the arguments according to the format @a fmt
13883 * specified. Then it allocates a new header structure, and parses the
13884 * formatting result to the structure #sip_security_server_t.
13885 *
13886 * @param home memory home used to allocate new header structure.
13887 * @param fmt string used as a printf()-style format
13888 * @param ... argument list for format
13889 *
13890 * @return
13891 * A pointer to newly
13892 * makes header structure, or NULL upon an error.
13893 *
13894 * @HIDE
13895 *
13896 */
13897#if SU_HAVE_INLINE1
13898su_inlinestatic inline
13899#endif
13900sip_security_server_t *sip_security_server_format(su_home_t *home, char const *fmt, ...)
13901 __attribute__((__malloc__, __format__ (printf, 2, 3)));
13902
13903#if SU_HAVE_INLINE1
13904su_inlinestatic inline sip_security_server_t *sip_security_server_format(su_home_t *home, char const *fmt, ...)
13905{
13906 sip_header_t *h;
13907 va_list ap;
13908
13909 va_start(ap, fmt)__builtin_va_start(ap, fmt);
13910 h = sip_header_vformat(home, sip_security_server_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_security_server_class
), (fmt), (ap)))
;
13911 va_end(ap)__builtin_va_end(ap);
13912
13913 return (sip_security_server_t *)h;
13914}
13915#endif
13916
13917/** @} */
13918
13919/**@addtogroup sip_security_verify
13920 * @{
13921 */
13922
13923/** Parse a SIP @ref sip_security_verify "Security-Verify header". @internal */
13924SOFIAPUBFUN issize_t sip_security_verify_d(su_home_t *, msg_header_t *,
13925 char *s, isize_t slen);
13926
13927/** Print a SIP @ref sip_security_verify "Security-Verify header". @internal */
13928SOFIAPUBFUN issize_t sip_security_verify_e(char b[], isize_t bsiz,
13929 msg_header_t const *h, int flags);
13930
13931/**Access a SIP @ref sip_security_verify "Security-Verify header"
13932 * structure #sip_security_verify_t from #sip_t.
13933 *
13934 */
13935#define sip_security_verify(sip)((sip_security_verify_t *)msg_header_access((msg_pub_t*)(sip)
, sip_security_verify_class))
\
13936 ((sip_security_verify_t *)msg_header_access((msg_pub_t*)(sip), sip_security_verify_class))
13937
13938/**Initializer for structure #sip_security_verify_t.
13939 *
13940 * A static #sip_security_verify_t structure for
13941 * @ref sip_security_verify "Security-Verify header" must be initialized with
13942 * the SIP_SECURITY_VERIFY_INIT() macro.
13943 * For instance,
13944 * @code
13945 *
13946 * sip_security_verify_t sip_security_verify = SIP_SECURITY_VERIFY_INIT;
13947 *
13948 * @endcode
13949 * @HI
13950 *
13951 */
13952#define SIP_SECURITY_VERIFY_INIT(){{{ 0, 0, sip_security_verify_class }}} SIP_HDR_INIT(security_verify){{{ 0, 0, sip_security_verify_class }}}
13953
13954/**Initialize a structure #sip_security_verify_t.
13955 *
13956 * An #sip_security_verify_t structure for
13957 * @ref sip_security_verify "Security-Verify header" can be initialized with the
13958 * sip_security_verify_init() function/macro. For instance,
13959 * @code
13960 *
13961 * sip_security_verify_t sip_security_verify;
13962 *
13963 * sip_security_verify_init(&sip_security_verify);
13964 *
13965 * @endcode
13966 * @HI
13967 *
13968 */
13969#if SU_HAVE_INLINE1
13970su_inlinestatic inline sip_security_verify_t *sip_security_verify_init(sip_security_verify_t x[1])
13971{
13972 return SIP_HEADER_INIT(x, sip_security_verify_class, sizeof(sip_security_verify_t))((void)memset((x), 0, (sizeof(sip_security_verify_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_verify_class
)), (x))
;
13973}
13974#else
13975#define sip_security_verify_init(x) \
13976 SIP_HEADER_INIT(x, sip_security_verify_class, sizeof(sip_security_verify_t))((void)memset((x), 0, (sizeof(sip_security_verify_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_security_verify_class
)), (x))
13977#endif
13978
13979/**Test if header object is instance of #sip_security_verify_t.
13980 *
13981 * Check if the header class is an instance of
13982 * @ref sip_security_verify "Security-Verify header" object and return true (nonzero),
13983 * otherwise return false (zero).
13984 *
13985 * @param header pointer to the header structure to be tested
13986 *
13987 * @retval 1 (true) if the @a header is an instance of header security_verify
13988 * @retval 0 (false) otherwise
13989 *
13990 */
13991#if SU_HAVE_INLINE1
13992su_inlinestatic inline int sip_is_security_verify(sip_header_t const *header)
13993{
13994 return header && header->sh_classsh_common->h_class->hc_hash == sip_security_verify_hash;
13995}
13996#else
13997int sip_is_security_verify(sip_header_t const *header);
13998#endif
13999
14000#define sip_security_verify_p(h)sip_is_security_verify((h)) sip_is_security_verify((h))
14001
14002
14003/**Duplicate a list of @ref sip_security_verify "Security-Verify header" header structures #sip_security_verify_t.
14004 *
14005 * Duplicate a header
14006 * structure @a hdr. If the header structure @a hdr
14007 * contains a reference (@c hdr->x_next) to a list of
14008 * headers, all the headers in the list are duplicated, too.
14009 *
14010 * @param home memory home used to allocate new structure
14011 * @param hdr header structure to be duplicated
14012 *
14013 * When duplicating, all parameter lists and non-constant
14014 * strings attached to the header are copied, too. The
14015 * function uses given memory @a home to allocate all the
14016 * memory areas used to copy the header.
14017 *
14018 * @par Example
14019 * @code
14020 *
14021 * security_verify = sip_security_verify_dup(home, sip->sip_security_verify);
14022 *
14023 * @endcode
14024 *
14025 * @return
14026 * A pointer to the
14027 * newly duplicated #sip_security_verify_t header structure, or NULL
14028 * upon an error.
14029 *
14030 */
14031#if SU_HAVE_INLINE1
14032su_inlinestatic inline
14033#endif
14034sip_security_verify_t *sip_security_verify_dup(su_home_t *home, sip_security_verify_t const *hdr)
14035 __attribute__((__malloc__));
14036
14037#if SU_HAVE_INLINE1
14038su_inlinestatic inline
14039sip_security_verify_t *sip_security_verify_dup(su_home_t *home, sip_security_verify_t const *hdr)
14040{
14041 return (sip_security_verify_t *)
14042 msg_header_dup_as(home, sip_security_verify_class, (msg_header_t const *)hdr);
14043}
14044#endif
14045
14046/**Copy a list of @ref sip_security_verify "Security-Verify header" header structures #sip_security_verify_t.
14047 *
14048 * The function sip_security_verify_copy() copies a header structure @a
14049 * hdr. If the header structure @a hdr contains a reference (@c
14050 * hdr->h_next) to a list of headers, all the headers in that
14051 * list are copied, too. The function uses given memory @a home
14052 * to allocate all the memory areas used to copy the list of header
14053 * structure @a hdr.
14054 *
14055 * @param home memory home used to allocate new structure
14056 * @param hdr pointer to the header structure to be copied
14057 *
14058 * When copying, only the header structure and parameter lists attached to
14059 * it are duplicated. The new header structure retains all the references to
14060 * the strings within the old @a hdr header, including the encoding of the
14061 * old header, if present.
14062 *
14063 * @par Example
14064 * @code
14065 *
14066 * security_verify = sip_security_verify_copy(home, sip->sip_security_verify);
14067 *
14068 * @endcode
14069 *
14070 * @return
14071 * A pointer to newly copied header structure, or NULL upon an error.
14072 *
14073 */
14074#if SU_HAVE_INLINE1
14075su_inlinestatic inline
14076#endif
14077sip_security_verify_t *sip_security_verify_copy(su_home_t *home, sip_security_verify_t const *hdr)
14078 __attribute__((__malloc__));
14079
14080#if SU_HAVE_INLINE1
14081su_inlinestatic inline
14082sip_security_verify_t *sip_security_verify_copy(su_home_t *home, sip_security_verify_t const *hdr)
14083{
14084 return (sip_security_verify_t *)
14085 msg_header_copy_as(home, sip_security_verify_class, (msg_header_t const *)hdr);
14086}
14087#endif
14088
14089/**Make a @ref sip_security_verify "Security-Verify header" structure #sip_security_verify_t.
14090 *
14091 * The function sip_security_verify_make() makes a new
14092 * #sip_security_verify_t header structure. It allocates a new
14093 * header structure, and decodes the string @a s as the
14094 * value of the structure.
14095 *
14096 * @param home memory home used to allocate new header structure.
14097 * @param s string to be decoded as value of the new header structure
14098 *
14099 * @return
14100 * A pointer to newly maked #sip_security_verify_t header structure, or NULL upon an
14101 * error.
14102 *
14103 */
14104#if SU_HAVE_INLINE1
14105su_inlinestatic inline
14106#endif
14107sip_security_verify_t *sip_security_verify_make(su_home_t *home, char const *s)
14108 __attribute__((__malloc__));
14109
14110#if SU_HAVE_INLINE1
14111su_inlinestatic inline sip_security_verify_t *sip_security_verify_make(su_home_t *home, char const *s)
14112{
14113 return (sip_security_verify_t *)sip_header_make(home, sip_security_verify_class, s)((sip_header_t *)msg_header_make((home), (sip_security_verify_class
), (s)))
;
14114}
14115#endif
14116
14117/**Make a @ref sip_security_verify "Security-Verify header" from formatting result.
14118 *
14119 * Make a new #sip_security_verify_t object using formatting result as its value.
14120 * The function first prints the arguments according to the format @a fmt
14121 * specified. Then it allocates a new header structure, and parses the
14122 * formatting result to the structure #sip_security_verify_t.
14123 *
14124 * @param home memory home used to allocate new header structure.
14125 * @param fmt string used as a printf()-style format
14126 * @param ... argument list for format
14127 *
14128 * @return
14129 * A pointer to newly
14130 * makes header structure, or NULL upon an error.
14131 *
14132 * @HIDE
14133 *
14134 */
14135#if SU_HAVE_INLINE1
14136su_inlinestatic inline
14137#endif
14138sip_security_verify_t *sip_security_verify_format(su_home_t *home, char const *fmt, ...)
14139 __attribute__((__malloc__, __format__ (printf, 2, 3)));
14140
14141#if SU_HAVE_INLINE1
14142su_inlinestatic inline sip_security_verify_t *sip_security_verify_format(su_home_t *home, char const *fmt, ...)
14143{
14144 sip_header_t *h;
14145 va_list ap;
14146
14147 va_start(ap, fmt)__builtin_va_start(ap, fmt);
14148 h = sip_header_vformat(home, sip_security_verify_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_security_verify_class
), (fmt), (ap)))
;
14149 va_end(ap)__builtin_va_end(ap);
14150
14151 return (sip_security_verify_t *)h;
14152}
14153#endif
14154
14155/** @} */
14156
14157/**@addtogroup sip_privacy
14158 * @{
14159 */
14160
14161/** Parse a SIP @ref sip_privacy "Privacy header". @internal */
14162SOFIAPUBFUN issize_t sip_privacy_d(su_home_t *, msg_header_t *,
14163 char *s, isize_t slen);
14164
14165/** Print a SIP @ref sip_privacy "Privacy header". @internal */
14166SOFIAPUBFUN issize_t sip_privacy_e(char b[], isize_t bsiz,
14167 msg_header_t const *h, int flags);
14168
14169/**Access a SIP @ref sip_privacy "Privacy header"
14170 * structure #sip_privacy_t from #sip_t.
14171 *
14172 */
14173#define sip_privacy(sip)((sip_privacy_t *)msg_header_access((msg_pub_t*)(sip), sip_privacy_class
))
\
14174 ((sip_privacy_t *)msg_header_access((msg_pub_t*)(sip), sip_privacy_class))
14175
14176/**Initializer for structure #sip_privacy_t.
14177 *
14178 * A static #sip_privacy_t structure for
14179 * @ref sip_privacy "Privacy header" must be initialized with
14180 * the SIP_PRIVACY_INIT() macro.
14181 * For instance,
14182 * @code
14183 *
14184 * sip_privacy_t sip_privacy = SIP_PRIVACY_INIT;
14185 *
14186 * @endcode
14187 * @HI
14188 *
14189 */
14190#define SIP_PRIVACY_INIT(){{{ 0, 0, sip_privacy_class }}} SIP_HDR_INIT(privacy){{{ 0, 0, sip_privacy_class }}}
14191
14192/**Initialize a structure #sip_privacy_t.
14193 *
14194 * An #sip_privacy_t structure for
14195 * @ref sip_privacy "Privacy header" can be initialized with the
14196 * sip_privacy_init() function/macro. For instance,
14197 * @code
14198 *
14199 * sip_privacy_t sip_privacy;
14200 *
14201 * sip_privacy_init(&sip_privacy);
14202 *
14203 * @endcode
14204 * @HI
14205 *
14206 */
14207#if SU_HAVE_INLINE1
14208su_inlinestatic inline sip_privacy_t *sip_privacy_init(sip_privacy_t x[1])
14209{
14210 return SIP_HEADER_INIT(x, sip_privacy_class, sizeof(sip_privacy_t))((void)memset((x), 0, (sizeof(sip_privacy_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_privacy_class)), (x))
;
14211}
14212#else
14213#define sip_privacy_init(x) \
14214 SIP_HEADER_INIT(x, sip_privacy_class, sizeof(sip_privacy_t))((void)memset((x), 0, (sizeof(sip_privacy_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_privacy_class)), (x))
14215#endif
14216
14217/**Test if header object is instance of #sip_privacy_t.
14218 *
14219 * Check if the header class is an instance of
14220 * @ref sip_privacy "Privacy header" object and return true (nonzero),
14221 * otherwise return false (zero).
14222 *
14223 * @param header pointer to the header structure to be tested
14224 *
14225 * @retval 1 (true) if the @a header is an instance of header privacy
14226 * @retval 0 (false) otherwise
14227 *
14228 */
14229#if SU_HAVE_INLINE1
14230su_inlinestatic inline int sip_is_privacy(sip_header_t const *header)
14231{
14232 return header && header->sh_classsh_common->h_class->hc_hash == sip_privacy_hash;
14233}
14234#else
14235int sip_is_privacy(sip_header_t const *header);
14236#endif
14237
14238#define sip_privacy_p(h)sip_is_privacy((h)) sip_is_privacy((h))
14239
14240
14241/**Duplicate a list of @ref sip_privacy "Privacy header" header structures #sip_privacy_t.
14242 *
14243 * Duplicate a header
14244 * structure @a hdr. If the header structure @a hdr
14245 * contains a reference (@c hdr->x_next) to a list of
14246 * headers, all the headers in the list are duplicated, too.
14247 *
14248 * @param home memory home used to allocate new structure
14249 * @param hdr header structure to be duplicated
14250 *
14251 * When duplicating, all parameter lists and non-constant
14252 * strings attached to the header are copied, too. The
14253 * function uses given memory @a home to allocate all the
14254 * memory areas used to copy the header.
14255 *
14256 * @par Example
14257 * @code
14258 *
14259 * privacy = sip_privacy_dup(home, sip->sip_privacy);
14260 *
14261 * @endcode
14262 *
14263 * @return
14264 * A pointer to the
14265 * newly duplicated #sip_privacy_t header structure, or NULL
14266 * upon an error.
14267 *
14268 */
14269#if SU_HAVE_INLINE1
14270su_inlinestatic inline
14271#endif
14272sip_privacy_t *sip_privacy_dup(su_home_t *home, sip_privacy_t const *hdr)
14273 __attribute__((__malloc__));
14274
14275#if SU_HAVE_INLINE1
14276su_inlinestatic inline
14277sip_privacy_t *sip_privacy_dup(su_home_t *home, sip_privacy_t const *hdr)
14278{
14279 return (sip_privacy_t *)
14280 msg_header_dup_as(home, sip_privacy_class, (msg_header_t const *)hdr);
14281}
14282#endif
14283
14284/**Copy a list of @ref sip_privacy "Privacy header" header structures #sip_privacy_t.
14285 *
14286 * The function sip_privacy_copy() copies a header structure @a
14287 * hdr. If the header structure @a hdr contains a reference (@c
14288 * hdr->h_next) to a list of headers, all the headers in that
14289 * list are copied, too. The function uses given memory @a home
14290 * to allocate all the memory areas used to copy the list of header
14291 * structure @a hdr.
14292 *
14293 * @param home memory home used to allocate new structure
14294 * @param hdr pointer to the header structure to be copied
14295 *
14296 * When copying, only the header structure and parameter lists attached to
14297 * it are duplicated. The new header structure retains all the references to
14298 * the strings within the old @a hdr header, including the encoding of the
14299 * old header, if present.
14300 *
14301 * @par Example
14302 * @code
14303 *
14304 * privacy = sip_privacy_copy(home, sip->sip_privacy);
14305 *
14306 * @endcode
14307 *
14308 * @return
14309 * A pointer to newly copied header structure, or NULL upon an error.
14310 *
14311 */
14312#if SU_HAVE_INLINE1
14313su_inlinestatic inline
14314#endif
14315sip_privacy_t *sip_privacy_copy(su_home_t *home, sip_privacy_t const *hdr)
14316 __attribute__((__malloc__));
14317
14318#if SU_HAVE_INLINE1
14319su_inlinestatic inline
14320sip_privacy_t *sip_privacy_copy(su_home_t *home, sip_privacy_t const *hdr)
14321{
14322 return (sip_privacy_t *)
14323 msg_header_copy_as(home, sip_privacy_class, (msg_header_t const *)hdr);
14324}
14325#endif
14326
14327/**Make a @ref sip_privacy "Privacy header" structure #sip_privacy_t.
14328 *
14329 * The function sip_privacy_make() makes a new
14330 * #sip_privacy_t header structure. It allocates a new
14331 * header structure, and decodes the string @a s as the
14332 * value of the structure.
14333 *
14334 * @param home memory home used to allocate new header structure.
14335 * @param s string to be decoded as value of the new header structure
14336 *
14337 * @return
14338 * A pointer to newly maked #sip_privacy_t header structure, or NULL upon an
14339 * error.
14340 *
14341 */
14342#if SU_HAVE_INLINE1
14343su_inlinestatic inline
14344#endif
14345sip_privacy_t *sip_privacy_make(su_home_t *home, char const *s)
14346 __attribute__((__malloc__));
14347
14348#if SU_HAVE_INLINE1
14349su_inlinestatic inline sip_privacy_t *sip_privacy_make(su_home_t *home, char const *s)
14350{
14351 return (sip_privacy_t *)sip_header_make(home, sip_privacy_class, s)((sip_header_t *)msg_header_make((home), (sip_privacy_class),
(s)))
;
14352}
14353#endif
14354
14355/**Make a @ref sip_privacy "Privacy header" from formatting result.
14356 *
14357 * Make a new #sip_privacy_t object using formatting result as its value.
14358 * The function first prints the arguments according to the format @a fmt
14359 * specified. Then it allocates a new header structure, and parses the
14360 * formatting result to the structure #sip_privacy_t.
14361 *
14362 * @param home memory home used to allocate new header structure.
14363 * @param fmt string used as a printf()-style format
14364 * @param ... argument list for format
14365 *
14366 * @return
14367 * A pointer to newly
14368 * makes header structure, or NULL upon an error.
14369 *
14370 * @HIDE
14371 *
14372 */
14373#if SU_HAVE_INLINE1
14374su_inlinestatic inline
14375#endif
14376sip_privacy_t *sip_privacy_format(su_home_t *home, char const *fmt, ...)
14377 __attribute__((__malloc__, __format__ (printf, 2, 3)));
14378
14379#if SU_HAVE_INLINE1
14380su_inlinestatic inline sip_privacy_t *sip_privacy_format(su_home_t *home, char const *fmt, ...)
14381{
14382 sip_header_t *h;
14383 va_list ap;
14384
14385 va_start(ap, fmt)__builtin_va_start(ap, fmt);
14386 h = sip_header_vformat(home, sip_privacy_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_privacy_class
), (fmt), (ap)))
;
14387 va_end(ap)__builtin_va_end(ap);
14388
14389 return (sip_privacy_t *)h;
14390}
14391#endif
14392
14393/** @} */
14394
14395/**@addtogroup sip_etag
14396 * @{
14397 */
14398
14399/** Parse a SIP @ref sip_etag "SIP-ETag header". @internal */
14400SOFIAPUBFUN issize_t sip_etag_d(su_home_t *, msg_header_t *,
14401 char *s, isize_t slen);
14402
14403/** Print a SIP @ref sip_etag "SIP-ETag header". @internal */
14404SOFIAPUBFUN issize_t sip_etag_e(char b[], isize_t bsiz,
14405 msg_header_t const *h, int flags);
14406
14407/**Access a SIP @ref sip_etag "SIP-ETag header"
14408 * structure #sip_etag_t from #sip_t.
14409 *
14410 */
14411#define sip_etag(sip)((sip_etag_t *)msg_header_access((msg_pub_t*)(sip), sip_etag_class
))
\
14412 ((sip_etag_t *)msg_header_access((msg_pub_t*)(sip), sip_etag_class))
14413
14414/**Initializer for structure #sip_etag_t.
14415 *
14416 * A static #sip_etag_t structure for
14417 * @ref sip_etag "SIP-ETag header" must be initialized with
14418 * the SIP_ETAG_INIT() macro.
14419 * For instance,
14420 * @code
14421 *
14422 * sip_etag_t sip_etag = SIP_ETAG_INIT;
14423 *
14424 * @endcode
14425 * @HI
14426 *
14427 */
14428#define SIP_ETAG_INIT(){{{ 0, 0, sip_etag_class }}} SIP_HDR_INIT(etag){{{ 0, 0, sip_etag_class }}}
14429
14430/**Initialize a structure #sip_etag_t.
14431 *
14432 * An #sip_etag_t structure for
14433 * @ref sip_etag "SIP-ETag header" can be initialized with the
14434 * sip_etag_init() function/macro. For instance,
14435 * @code
14436 *
14437 * sip_etag_t sip_etag;
14438 *
14439 * sip_etag_init(&sip_etag);
14440 *
14441 * @endcode
14442 * @HI
14443 *
14444 */
14445#if SU_HAVE_INLINE1
14446su_inlinestatic inline sip_etag_t *sip_etag_init(sip_etag_t x[1])
14447{
14448 return SIP_HEADER_INIT(x, sip_etag_class, sizeof(sip_etag_t))((void)memset((x), 0, (sizeof(sip_etag_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_etag_class)), (x))
;
14449}
14450#else
14451#define sip_etag_init(x) \
14452 SIP_HEADER_INIT(x, sip_etag_class, sizeof(sip_etag_t))((void)memset((x), 0, (sizeof(sip_etag_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_etag_class)), (x))
14453#endif
14454
14455/**Test if header object is instance of #sip_etag_t.
14456 *
14457 * Check if the header class is an instance of
14458 * @ref sip_etag "SIP-ETag header" object and return true (nonzero),
14459 * otherwise return false (zero).
14460 *
14461 * @param header pointer to the header structure to be tested
14462 *
14463 * @retval 1 (true) if the @a header is an instance of header etag
14464 * @retval 0 (false) otherwise
14465 *
14466 */
14467#if SU_HAVE_INLINE1
14468su_inlinestatic inline int sip_is_etag(sip_header_t const *header)
14469{
14470 return header && header->sh_classsh_common->h_class->hc_hash == sip_etag_hash;
14471}
14472#else
14473int sip_is_etag(sip_header_t const *header);
14474#endif
14475
14476#define sip_etag_p(h)sip_is_etag((h)) sip_is_etag((h))
14477
14478
14479/**Duplicate a list of @ref sip_etag "SIP-ETag header" header structures #sip_etag_t.
14480 *
14481 * Duplicate a header
14482 * structure @a hdr. If the header structure @a hdr
14483 * contains a reference (@c hdr->x_next) to a list of
14484 * headers, all the headers in the list are duplicated, too.
14485 *
14486 * @param home memory home used to allocate new structure
14487 * @param hdr header structure to be duplicated
14488 *
14489 * When duplicating, all parameter lists and non-constant
14490 * strings attached to the header are copied, too. The
14491 * function uses given memory @a home to allocate all the
14492 * memory areas used to copy the header.
14493 *
14494 * @par Example
14495 * @code
14496 *
14497 * etag = sip_etag_dup(home, sip->sip_etag);
14498 *
14499 * @endcode
14500 *
14501 * @return
14502 * A pointer to the
14503 * newly duplicated #sip_etag_t header structure, or NULL
14504 * upon an error.
14505 *
14506 */
14507#if SU_HAVE_INLINE1
14508su_inlinestatic inline
14509#endif
14510sip_etag_t *sip_etag_dup(su_home_t *home, sip_etag_t const *hdr)
14511 __attribute__((__malloc__));
14512
14513#if SU_HAVE_INLINE1
14514su_inlinestatic inline
14515sip_etag_t *sip_etag_dup(su_home_t *home, sip_etag_t const *hdr)
14516{
14517 return (sip_etag_t *)
14518 msg_header_dup_as(home, sip_etag_class, (msg_header_t const *)hdr);
14519}
14520#endif
14521
14522/**Copy a list of @ref sip_etag "SIP-ETag header" header structures #sip_etag_t.
14523 *
14524 * The function sip_etag_copy() copies a header structure @a
14525 * hdr. If the header structure @a hdr contains a reference (@c
14526 * hdr->h_next) to a list of headers, all the headers in that
14527 * list are copied, too. The function uses given memory @a home
14528 * to allocate all the memory areas used to copy the list of header
14529 * structure @a hdr.
14530 *
14531 * @param home memory home used to allocate new structure
14532 * @param hdr pointer to the header structure to be copied
14533 *
14534 * When copying, only the header structure and parameter lists attached to
14535 * it are duplicated. The new header structure retains all the references to
14536 * the strings within the old @a hdr header, including the encoding of the
14537 * old header, if present.
14538 *
14539 * @par Example
14540 * @code
14541 *
14542 * etag = sip_etag_copy(home, sip->sip_etag);
14543 *
14544 * @endcode
14545 *
14546 * @return
14547 * A pointer to newly copied header structure, or NULL upon an error.
14548 *
14549 */
14550#if SU_HAVE_INLINE1
14551su_inlinestatic inline
14552#endif
14553sip_etag_t *sip_etag_copy(su_home_t *home, sip_etag_t const *hdr)
14554 __attribute__((__malloc__));
14555
14556#if SU_HAVE_INLINE1
14557su_inlinestatic inline
14558sip_etag_t *sip_etag_copy(su_home_t *home, sip_etag_t const *hdr)
14559{
14560 return (sip_etag_t *)
14561 msg_header_copy_as(home, sip_etag_class, (msg_header_t const *)hdr);
14562}
14563#endif
14564
14565/**Make a @ref sip_etag "SIP-ETag header" structure #sip_etag_t.
14566 *
14567 * The function sip_etag_make() makes a new
14568 * #sip_etag_t header structure. It allocates a new
14569 * header structure, and decodes the string @a s as the
14570 * value of the structure.
14571 *
14572 * @param home memory home used to allocate new header structure.
14573 * @param s string to be decoded as value of the new header structure
14574 *
14575 * @return
14576 * A pointer to newly maked #sip_etag_t header structure, or NULL upon an
14577 * error.
14578 *
14579 */
14580#if SU_HAVE_INLINE1
14581su_inlinestatic inline
14582#endif
14583sip_etag_t *sip_etag_make(su_home_t *home, char const *s)
14584 __attribute__((__malloc__));
14585
14586#if SU_HAVE_INLINE1
14587su_inlinestatic inline sip_etag_t *sip_etag_make(su_home_t *home, char const *s)
14588{
14589 return (sip_etag_t *)sip_header_make(home, sip_etag_class, s)((sip_header_t *)msg_header_make((home), (sip_etag_class), (s
)))
;
14590}
14591#endif
14592
14593/**Make a @ref sip_etag "SIP-ETag header" from formatting result.
14594 *
14595 * Make a new #sip_etag_t object using formatting result as its value.
14596 * The function first prints the arguments according to the format @a fmt
14597 * specified. Then it allocates a new header structure, and parses the
14598 * formatting result to the structure #sip_etag_t.
14599 *
14600 * @param home memory home used to allocate new header structure.
14601 * @param fmt string used as a printf()-style format
14602 * @param ... argument list for format
14603 *
14604 * @return
14605 * A pointer to newly
14606 * makes header structure, or NULL upon an error.
14607 *
14608 * @HIDE
14609 *
14610 */
14611#if SU_HAVE_INLINE1
14612su_inlinestatic inline
14613#endif
14614sip_etag_t *sip_etag_format(su_home_t *home, char const *fmt, ...)
14615 __attribute__((__malloc__, __format__ (printf, 2, 3)));
14616
14617#if SU_HAVE_INLINE1
14618su_inlinestatic inline sip_etag_t *sip_etag_format(su_home_t *home, char const *fmt, ...)
14619{
14620 sip_header_t *h;
14621 va_list ap;
14622
14623 va_start(ap, fmt)__builtin_va_start(ap, fmt);
14624 h = sip_header_vformat(home, sip_etag_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_etag_class),
(fmt), (ap)))
;
14625 va_end(ap)__builtin_va_end(ap);
14626
14627 return (sip_etag_t *)h;
14628}
14629#endif
14630
14631/** @} */
14632
14633/**@addtogroup sip_if_match
14634 * @{
14635 */
14636
14637/** Parse a SIP @ref sip_if_match "SIP-If-Match header". @internal */
14638SOFIAPUBFUN issize_t sip_if_match_d(su_home_t *, msg_header_t *,
14639 char *s, isize_t slen);
14640
14641/** Print a SIP @ref sip_if_match "SIP-If-Match header". @internal */
14642SOFIAPUBFUN issize_t sip_if_match_e(char b[], isize_t bsiz,
14643 msg_header_t const *h, int flags);
14644
14645/**Access a SIP @ref sip_if_match "SIP-If-Match header"
14646 * structure #sip_if_match_t from #sip_t.
14647 *
14648 */
14649#define sip_if_match(sip)((sip_if_match_t *)msg_header_access((msg_pub_t*)(sip), sip_if_match_class
))
\
14650 ((sip_if_match_t *)msg_header_access((msg_pub_t*)(sip), sip_if_match_class))
14651
14652/**Initializer for structure #sip_if_match_t.
14653 *
14654 * A static #sip_if_match_t structure for
14655 * @ref sip_if_match "SIP-If-Match header" must be initialized with
14656 * the SIP_IF_MATCH_INIT() macro.
14657 * For instance,
14658 * @code
14659 *
14660 * sip_if_match_t sip_if_match = SIP_IF_MATCH_INIT;
14661 *
14662 * @endcode
14663 * @HI
14664 *
14665 */
14666#define SIP_IF_MATCH_INIT(){{{ 0, 0, sip_if_match_class }}} SIP_HDR_INIT(if_match){{{ 0, 0, sip_if_match_class }}}
14667
14668/**Initialize a structure #sip_if_match_t.
14669 *
14670 * An #sip_if_match_t structure for
14671 * @ref sip_if_match "SIP-If-Match header" can be initialized with the
14672 * sip_if_match_init() function/macro. For instance,
14673 * @code
14674 *
14675 * sip_if_match_t sip_if_match;
14676 *
14677 * sip_if_match_init(&sip_if_match);
14678 *
14679 * @endcode
14680 * @HI
14681 *
14682 */
14683#if SU_HAVE_INLINE1
14684su_inlinestatic inline sip_if_match_t *sip_if_match_init(sip_if_match_t x[1])
14685{
14686 return SIP_HEADER_INIT(x, sip_if_match_class, sizeof(sip_if_match_t))((void)memset((x), 0, (sizeof(sip_if_match_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_if_match_class)), (x))
;
14687}
14688#else
14689#define sip_if_match_init(x) \
14690 SIP_HEADER_INIT(x, sip_if_match_class, sizeof(sip_if_match_t))((void)memset((x), 0, (sizeof(sip_if_match_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_if_match_class)), (x))
14691#endif
14692
14693/**Test if header object is instance of #sip_if_match_t.
14694 *
14695 * Check if the header class is an instance of
14696 * @ref sip_if_match "SIP-If-Match header" object and return true (nonzero),
14697 * otherwise return false (zero).
14698 *
14699 * @param header pointer to the header structure to be tested
14700 *
14701 * @retval 1 (true) if the @a header is an instance of header if_match
14702 * @retval 0 (false) otherwise
14703 *
14704 */
14705#if SU_HAVE_INLINE1
14706su_inlinestatic inline int sip_is_if_match(sip_header_t const *header)
14707{
14708 return header && header->sh_classsh_common->h_class->hc_hash == sip_if_match_hash;
14709}
14710#else
14711int sip_is_if_match(sip_header_t const *header);
14712#endif
14713
14714#define sip_if_match_p(h)sip_is_if_match((h)) sip_is_if_match((h))
14715
14716
14717/**Duplicate a list of @ref sip_if_match "SIP-If-Match header" header structures #sip_if_match_t.
14718 *
14719 * Duplicate a header
14720 * structure @a hdr. If the header structure @a hdr
14721 * contains a reference (@c hdr->x_next) to a list of
14722 * headers, all the headers in the list are duplicated, too.
14723 *
14724 * @param home memory home used to allocate new structure
14725 * @param hdr header structure to be duplicated
14726 *
14727 * When duplicating, all parameter lists and non-constant
14728 * strings attached to the header are copied, too. The
14729 * function uses given memory @a home to allocate all the
14730 * memory areas used to copy the header.
14731 *
14732 * @par Example
14733 * @code
14734 *
14735 * if_match = sip_if_match_dup(home, sip->sip_if_match);
14736 *
14737 * @endcode
14738 *
14739 * @return
14740 * A pointer to the
14741 * newly duplicated #sip_if_match_t header structure, or NULL
14742 * upon an error.
14743 *
14744 */
14745#if SU_HAVE_INLINE1
14746su_inlinestatic inline
14747#endif
14748sip_if_match_t *sip_if_match_dup(su_home_t *home, sip_if_match_t const *hdr)
14749 __attribute__((__malloc__));
14750
14751#if SU_HAVE_INLINE1
14752su_inlinestatic inline
14753sip_if_match_t *sip_if_match_dup(su_home_t *home, sip_if_match_t const *hdr)
14754{
14755 return (sip_if_match_t *)
14756 msg_header_dup_as(home, sip_if_match_class, (msg_header_t const *)hdr);
14757}
14758#endif
14759
14760/**Copy a list of @ref sip_if_match "SIP-If-Match header" header structures #sip_if_match_t.
14761 *
14762 * The function sip_if_match_copy() copies a header structure @a
14763 * hdr. If the header structure @a hdr contains a reference (@c
14764 * hdr->h_next) to a list of headers, all the headers in that
14765 * list are copied, too. The function uses given memory @a home
14766 * to allocate all the memory areas used to copy the list of header
14767 * structure @a hdr.
14768 *
14769 * @param home memory home used to allocate new structure
14770 * @param hdr pointer to the header structure to be copied
14771 *
14772 * When copying, only the header structure and parameter lists attached to
14773 * it are duplicated. The new header structure retains all the references to
14774 * the strings within the old @a hdr header, including the encoding of the
14775 * old header, if present.
14776 *
14777 * @par Example
14778 * @code
14779 *
14780 * if_match = sip_if_match_copy(home, sip->sip_if_match);
14781 *
14782 * @endcode
14783 *
14784 * @return
14785 * A pointer to newly copied header structure, or NULL upon an error.
14786 *
14787 */
14788#if SU_HAVE_INLINE1
14789su_inlinestatic inline
14790#endif
14791sip_if_match_t *sip_if_match_copy(su_home_t *home, sip_if_match_t const *hdr)
14792 __attribute__((__malloc__));
14793
14794#if SU_HAVE_INLINE1
14795su_inlinestatic inline
14796sip_if_match_t *sip_if_match_copy(su_home_t *home, sip_if_match_t const *hdr)
14797{
14798 return (sip_if_match_t *)
14799 msg_header_copy_as(home, sip_if_match_class, (msg_header_t const *)hdr);
14800}
14801#endif
14802
14803/**Make a @ref sip_if_match "SIP-If-Match header" structure #sip_if_match_t.
14804 *
14805 * The function sip_if_match_make() makes a new
14806 * #sip_if_match_t header structure. It allocates a new
14807 * header structure, and decodes the string @a s as the
14808 * value of the structure.
14809 *
14810 * @param home memory home used to allocate new header structure.
14811 * @param s string to be decoded as value of the new header structure
14812 *
14813 * @return
14814 * A pointer to newly maked #sip_if_match_t header structure, or NULL upon an
14815 * error.
14816 *
14817 */
14818#if SU_HAVE_INLINE1
14819su_inlinestatic inline
14820#endif
14821sip_if_match_t *sip_if_match_make(su_home_t *home, char const *s)
14822 __attribute__((__malloc__));
14823
14824#if SU_HAVE_INLINE1
14825su_inlinestatic inline sip_if_match_t *sip_if_match_make(su_home_t *home, char const *s)
14826{
14827 return (sip_if_match_t *)sip_header_make(home, sip_if_match_class, s)((sip_header_t *)msg_header_make((home), (sip_if_match_class)
, (s)))
;
14828}
14829#endif
14830
14831/**Make a @ref sip_if_match "SIP-If-Match header" from formatting result.
14832 *
14833 * Make a new #sip_if_match_t object using formatting result as its value.
14834 * The function first prints the arguments according to the format @a fmt
14835 * specified. Then it allocates a new header structure, and parses the
14836 * formatting result to the structure #sip_if_match_t.
14837 *
14838 * @param home memory home used to allocate new header structure.
14839 * @param fmt string used as a printf()-style format
14840 * @param ... argument list for format
14841 *
14842 * @return
14843 * A pointer to newly
14844 * makes header structure, or NULL upon an error.
14845 *
14846 * @HIDE
14847 *
14848 */
14849#if SU_HAVE_INLINE1
14850su_inlinestatic inline
14851#endif
14852sip_if_match_t *sip_if_match_format(su_home_t *home, char const *fmt, ...)
14853 __attribute__((__malloc__, __format__ (printf, 2, 3)));
14854
14855#if SU_HAVE_INLINE1
14856su_inlinestatic inline sip_if_match_t *sip_if_match_format(su_home_t *home, char const *fmt, ...)
14857{
14858 sip_header_t *h;
14859 va_list ap;
14860
14861 va_start(ap, fmt)__builtin_va_start(ap, fmt);
14862 h = sip_header_vformat(home, sip_if_match_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_if_match_class
), (fmt), (ap)))
;
14863 va_end(ap)__builtin_va_end(ap);
14864
14865 return (sip_if_match_t *)h;
14866}
14867#endif
14868
14869/** @} */
14870
14871/**@addtogroup sip_mime_version
14872 * @{
14873 */
14874
14875/** Parse a SIP @ref sip_mime_version "MIME-Version header". @internal */
14876SOFIAPUBFUN issize_t sip_mime_version_d(su_home_t *, msg_header_t *,
14877 char *s, isize_t slen);
14878
14879/** Print a SIP @ref sip_mime_version "MIME-Version header". @internal */
14880SOFIAPUBFUN issize_t sip_mime_version_e(char b[], isize_t bsiz,
14881 msg_header_t const *h, int flags);
14882
14883/**Access a SIP @ref sip_mime_version "MIME-Version header"
14884 * structure #sip_mime_version_t from #sip_t.
14885 *
14886 */
14887#define sip_mime_version(sip)((sip_mime_version_t *)msg_header_access((msg_pub_t*)(sip), sip_mime_version_class
))
\
14888 ((sip_mime_version_t *)msg_header_access((msg_pub_t*)(sip), sip_mime_version_class))
14889
14890/**Initializer for structure #sip_mime_version_t.
14891 *
14892 * A static #sip_mime_version_t structure for
14893 * @ref sip_mime_version "MIME-Version header" must be initialized with
14894 * the SIP_MIME_VERSION_INIT() macro.
14895 * For instance,
14896 * @code
14897 *
14898 * sip_mime_version_t sip_mime_version = SIP_MIME_VERSION_INIT;
14899 *
14900 * @endcode
14901 * @HI
14902 *
14903 */
14904#define SIP_MIME_VERSION_INIT(){{{ 0, 0, sip_mime_version_class }}} SIP_HDR_INIT(mime_version){{{ 0, 0, sip_mime_version_class }}}
14905
14906/**Initialize a structure #sip_mime_version_t.
14907 *
14908 * An #sip_mime_version_t structure for
14909 * @ref sip_mime_version "MIME-Version header" can be initialized with the
14910 * sip_mime_version_init() function/macro. For instance,
14911 * @code
14912 *
14913 * sip_mime_version_t sip_mime_version;
14914 *
14915 * sip_mime_version_init(&sip_mime_version);
14916 *
14917 * @endcode
14918 * @HI
14919 *
14920 */
14921#if SU_HAVE_INLINE1
14922su_inlinestatic inline sip_mime_version_t *sip_mime_version_init(sip_mime_version_t x[1])
14923{
14924 return SIP_HEADER_INIT(x, sip_mime_version_class, sizeof(sip_mime_version_t))((void)memset((x), 0, (sizeof(sip_mime_version_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_mime_version_class)),
(x))
;
14925}
14926#else
14927#define sip_mime_version_init(x) \
14928 SIP_HEADER_INIT(x, sip_mime_version_class, sizeof(sip_mime_version_t))((void)memset((x), 0, (sizeof(sip_mime_version_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_mime_version_class)),
(x))
14929#endif
14930
14931/**Test if header object is instance of #sip_mime_version_t.
14932 *
14933 * Check if the header class is an instance of
14934 * @ref sip_mime_version "MIME-Version header" object and return true (nonzero),
14935 * otherwise return false (zero).
14936 *
14937 * @param header pointer to the header structure to be tested
14938 *
14939 * @retval 1 (true) if the @a header is an instance of header mime_version
14940 * @retval 0 (false) otherwise
14941 *
14942 */
14943#if SU_HAVE_INLINE1
14944su_inlinestatic inline int sip_is_mime_version(sip_header_t const *header)
14945{
14946 return header && header->sh_classsh_common->h_class->hc_hash == sip_mime_version_hash;
14947}
14948#else
14949int sip_is_mime_version(sip_header_t const *header);
14950#endif
14951
14952#define sip_mime_version_p(h)sip_is_mime_version((h)) sip_is_mime_version((h))
14953
14954
14955/**Duplicate a list of @ref sip_mime_version "MIME-Version header" header structures #sip_mime_version_t.
14956 *
14957 * Duplicate a header
14958 * structure @a hdr. If the header structure @a hdr
14959 * contains a reference (@c hdr->x_next) to a list of
14960 * headers, all the headers in the list are duplicated, too.
14961 *
14962 * @param home memory home used to allocate new structure
14963 * @param hdr header structure to be duplicated
14964 *
14965 * When duplicating, all parameter lists and non-constant
14966 * strings attached to the header are copied, too. The
14967 * function uses given memory @a home to allocate all the
14968 * memory areas used to copy the header.
14969 *
14970 * @par Example
14971 * @code
14972 *
14973 * mime_version = sip_mime_version_dup(home, sip->sip_mime_version);
14974 *
14975 * @endcode
14976 *
14977 * @return
14978 * A pointer to the
14979 * newly duplicated #sip_mime_version_t header structure, or NULL
14980 * upon an error.
14981 *
14982 */
14983#if SU_HAVE_INLINE1
14984su_inlinestatic inline
14985#endif
14986sip_mime_version_t *sip_mime_version_dup(su_home_t *home, sip_mime_version_t const *hdr)
14987 __attribute__((__malloc__));
14988
14989#if SU_HAVE_INLINE1
14990su_inlinestatic inline
14991sip_mime_version_t *sip_mime_version_dup(su_home_t *home, sip_mime_version_t const *hdr)
14992{
14993 return (sip_mime_version_t *)
14994 msg_header_dup_as(home, sip_mime_version_class, (msg_header_t const *)hdr);
14995}
14996#endif
14997
14998/**Copy a list of @ref sip_mime_version "MIME-Version header" header structures #sip_mime_version_t.
14999 *
15000 * The function sip_mime_version_copy() copies a header structure @a
15001 * hdr. If the header structure @a hdr contains a reference (@c
15002 * hdr->h_next) to a list of headers, all the headers in that
15003 * list are copied, too. The function uses given memory @a home
15004 * to allocate all the memory areas used to copy the list of header
15005 * structure @a hdr.
15006 *
15007 * @param home memory home used to allocate new structure
15008 * @param hdr pointer to the header structure to be copied
15009 *
15010 * When copying, only the header structure and parameter lists attached to
15011 * it are duplicated. The new header structure retains all the references to
15012 * the strings within the old @a hdr header, including the encoding of the
15013 * old header, if present.
15014 *
15015 * @par Example
15016 * @code
15017 *
15018 * mime_version = sip_mime_version_copy(home, sip->sip_mime_version);
15019 *
15020 * @endcode
15021 *
15022 * @return
15023 * A pointer to newly copied header structure, or NULL upon an error.
15024 *
15025 */
15026#if SU_HAVE_INLINE1
15027su_inlinestatic inline
15028#endif
15029sip_mime_version_t *sip_mime_version_copy(su_home_t *home, sip_mime_version_t const *hdr)
15030 __attribute__((__malloc__));
15031
15032#if SU_HAVE_INLINE1
15033su_inlinestatic inline
15034sip_mime_version_t *sip_mime_version_copy(su_home_t *home, sip_mime_version_t const *hdr)
15035{
15036 return (sip_mime_version_t *)
15037 msg_header_copy_as(home, sip_mime_version_class, (msg_header_t const *)hdr);
15038}
15039#endif
15040
15041/**Make a @ref sip_mime_version "MIME-Version header" structure #sip_mime_version_t.
15042 *
15043 * The function sip_mime_version_make() makes a new
15044 * #sip_mime_version_t header structure. It allocates a new
15045 * header structure, and decodes the string @a s as the
15046 * value of the structure.
15047 *
15048 * @param home memory home used to allocate new header structure.
15049 * @param s string to be decoded as value of the new header structure
15050 *
15051 * @return
15052 * A pointer to newly maked #sip_mime_version_t header structure, or NULL upon an
15053 * error.
15054 *
15055 */
15056#if SU_HAVE_INLINE1
15057su_inlinestatic inline
15058#endif
15059sip_mime_version_t *sip_mime_version_make(su_home_t *home, char const *s)
15060 __attribute__((__malloc__));
15061
15062#if SU_HAVE_INLINE1
15063su_inlinestatic inline sip_mime_version_t *sip_mime_version_make(su_home_t *home, char const *s)
15064{
15065 return (sip_mime_version_t *)sip_header_make(home, sip_mime_version_class, s)((sip_header_t *)msg_header_make((home), (sip_mime_version_class
), (s)))
;
15066}
15067#endif
15068
15069/**Make a @ref sip_mime_version "MIME-Version header" from formatting result.
15070 *
15071 * Make a new #sip_mime_version_t object using formatting result as its value.
15072 * The function first prints the arguments according to the format @a fmt
15073 * specified. Then it allocates a new header structure, and parses the
15074 * formatting result to the structure #sip_mime_version_t.
15075 *
15076 * @param home memory home used to allocate new header structure.
15077 * @param fmt string used as a printf()-style format
15078 * @param ... argument list for format
15079 *
15080 * @return
15081 * A pointer to newly
15082 * makes header structure, or NULL upon an error.
15083 *
15084 * @HIDE
15085 *
15086 */
15087#if SU_HAVE_INLINE1
15088su_inlinestatic inline
15089#endif
15090sip_mime_version_t *sip_mime_version_format(su_home_t *home, char const *fmt, ...)
15091 __attribute__((__malloc__, __format__ (printf, 2, 3)));
15092
15093#if SU_HAVE_INLINE1
15094su_inlinestatic inline sip_mime_version_t *sip_mime_version_format(su_home_t *home, char const *fmt, ...)
15095{
15096 sip_header_t *h;
15097 va_list ap;
15098
15099 va_start(ap, fmt)__builtin_va_start(ap, fmt);
15100 h = sip_header_vformat(home, sip_mime_version_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_mime_version_class
), (fmt), (ap)))
;
15101 va_end(ap)__builtin_va_end(ap);
15102
15103 return (sip_mime_version_t *)h;
15104}
15105#endif
15106
15107/** @} */
15108
15109/**@addtogroup sip_content_type
15110 * @{
15111 */
15112
15113/** Parse a SIP @ref sip_content_type "Content-Type header". @internal */
15114SOFIAPUBFUN issize_t sip_content_type_d(su_home_t *, msg_header_t *,
15115 char *s, isize_t slen);
15116
15117/** Print a SIP @ref sip_content_type "Content-Type header". @internal */
15118SOFIAPUBFUN issize_t sip_content_type_e(char b[], isize_t bsiz,
15119 msg_header_t const *h, int flags);
15120
15121/**Access a SIP @ref sip_content_type "Content-Type header"
15122 * structure #sip_content_type_t from #sip_t.
15123 *
15124 */
15125#define sip_content_type(sip)((sip_content_type_t *)msg_header_access((msg_pub_t*)(sip), sip_content_type_class
))
\
15126 ((sip_content_type_t *)msg_header_access((msg_pub_t*)(sip), sip_content_type_class))
15127
15128/**Initializer for structure #sip_content_type_t.
15129 *
15130 * A static #sip_content_type_t structure for
15131 * @ref sip_content_type "Content-Type header" must be initialized with
15132 * the SIP_CONTENT_TYPE_INIT() macro.
15133 * For instance,
15134 * @code
15135 *
15136 * sip_content_type_t sip_content_type = SIP_CONTENT_TYPE_INIT;
15137 *
15138 * @endcode
15139 * @HI
15140 *
15141 */
15142#define SIP_CONTENT_TYPE_INIT(){{{ 0, 0, sip_content_type_class }}} SIP_HDR_INIT(content_type){{{ 0, 0, sip_content_type_class }}}
15143
15144/**Initialize a structure #sip_content_type_t.
15145 *
15146 * An #sip_content_type_t structure for
15147 * @ref sip_content_type "Content-Type header" can be initialized with the
15148 * sip_content_type_init() function/macro. For instance,
15149 * @code
15150 *
15151 * sip_content_type_t sip_content_type;
15152 *
15153 * sip_content_type_init(&sip_content_type);
15154 *
15155 * @endcode
15156 * @HI
15157 *
15158 */
15159#if SU_HAVE_INLINE1
15160su_inlinestatic inline sip_content_type_t *sip_content_type_init(sip_content_type_t x[1])
15161{
15162 return SIP_HEADER_INIT(x, sip_content_type_class, sizeof(sip_content_type_t))((void)memset((x), 0, (sizeof(sip_content_type_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_content_type_class)),
(x))
;
15163}
15164#else
15165#define sip_content_type_init(x) \
15166 SIP_HEADER_INIT(x, sip_content_type_class, sizeof(sip_content_type_t))((void)memset((x), 0, (sizeof(sip_content_type_t))), (void)((
(sip_common_t *)(x))->h_class = (sip_content_type_class)),
(x))
15167#endif
15168
15169/**Test if header object is instance of #sip_content_type_t.
15170 *
15171 * Check if the header class is an instance of
15172 * @ref sip_content_type "Content-Type header" object and return true (nonzero),
15173 * otherwise return false (zero).
15174 *
15175 * @param header pointer to the header structure to be tested
15176 *
15177 * @retval 1 (true) if the @a header is an instance of header content_type
15178 * @retval 0 (false) otherwise
15179 *
15180 */
15181#if SU_HAVE_INLINE1
15182su_inlinestatic inline int sip_is_content_type(sip_header_t const *header)
15183{
15184 return header && header->sh_classsh_common->h_class->hc_hash == sip_content_type_hash;
15185}
15186#else
15187int sip_is_content_type(sip_header_t const *header);
15188#endif
15189
15190#define sip_content_type_p(h)sip_is_content_type((h)) sip_is_content_type((h))
15191
15192
15193/**Duplicate a list of @ref sip_content_type "Content-Type header" header structures #sip_content_type_t.
15194 *
15195 * Duplicate a header
15196 * structure @a hdr. If the header structure @a hdr
15197 * contains a reference (@c hdr->x_next) to a list of
15198 * headers, all the headers in the list are duplicated, too.
15199 *
15200 * @param home memory home used to allocate new structure
15201 * @param hdr header structure to be duplicated
15202 *
15203 * When duplicating, all parameter lists and non-constant
15204 * strings attached to the header are copied, too. The
15205 * function uses given memory @a home to allocate all the
15206 * memory areas used to copy the header.
15207 *
15208 * @par Example
15209 * @code
15210 *
15211 * content_type = sip_content_type_dup(home, sip->sip_content_type);
15212 *
15213 * @endcode
15214 *
15215 * @return
15216 * A pointer to the
15217 * newly duplicated #sip_content_type_t header structure, or NULL
15218 * upon an error.
15219 *
15220 */
15221#if SU_HAVE_INLINE1
15222su_inlinestatic inline
15223#endif
15224sip_content_type_t *sip_content_type_dup(su_home_t *home, sip_content_type_t const *hdr)
15225 __attribute__((__malloc__));
15226
15227#if SU_HAVE_INLINE1
15228su_inlinestatic inline
15229sip_content_type_t *sip_content_type_dup(su_home_t *home, sip_content_type_t const *hdr)
15230{
15231 return (sip_content_type_t *)
15232 msg_header_dup_as(home, sip_content_type_class, (msg_header_t const *)hdr);
15233}
15234#endif
15235
15236/**Copy a list of @ref sip_content_type "Content-Type header" header structures #sip_content_type_t.
15237 *
15238 * The function sip_content_type_copy() copies a header structure @a
15239 * hdr. If the header structure @a hdr contains a reference (@c
15240 * hdr->h_next) to a list of headers, all the headers in that
15241 * list are copied, too. The function uses given memory @a home
15242 * to allocate all the memory areas used to copy the list of header
15243 * structure @a hdr.
15244 *
15245 * @param home memory home used to allocate new structure
15246 * @param hdr pointer to the header structure to be copied
15247 *
15248 * When copying, only the header structure and parameter lists attached to
15249 * it are duplicated. The new header structure retains all the references to
15250 * the strings within the old @a hdr header, including the encoding of the
15251 * old header, if present.
15252 *
15253 * @par Example
15254 * @code
15255 *
15256 * content_type = sip_content_type_copy(home, sip->sip_content_type);
15257 *
15258 * @endcode
15259 *
15260 * @return
15261 * A pointer to newly copied header structure, or NULL upon an error.
15262 *
15263 */
15264#if SU_HAVE_INLINE1
15265su_inlinestatic inline
15266#endif
15267sip_content_type_t *sip_content_type_copy(su_home_t *home, sip_content_type_t const *hdr)
15268 __attribute__((__malloc__));
15269
15270#if SU_HAVE_INLINE1
15271su_inlinestatic inline
15272sip_content_type_t *sip_content_type_copy(su_home_t *home, sip_content_type_t const *hdr)
15273{
15274 return (sip_content_type_t *)
15275 msg_header_copy_as(home, sip_content_type_class, (msg_header_t const *)hdr);
15276}
15277#endif
15278
15279/**Make a @ref sip_content_type "Content-Type header" structure #sip_content_type_t.
15280 *
15281 * The function sip_content_type_make() makes a new
15282 * #sip_content_type_t header structure. It allocates a new
15283 * header structure, and decodes the string @a s as the
15284 * value of the structure.
15285 *
15286 * @param home memory home used to allocate new header structure.
15287 * @param s string to be decoded as value of the new header structure
15288 *
15289 * @return
15290 * A pointer to newly maked #sip_content_type_t header structure, or NULL upon an
15291 * error.
15292 *
15293 */
15294#if SU_HAVE_INLINE1
15295su_inlinestatic inline
15296#endif
15297sip_content_type_t *sip_content_type_make(su_home_t *home, char const *s)
15298 __attribute__((__malloc__));
15299
15300#if SU_HAVE_INLINE1
15301su_inlinestatic inline sip_content_type_t *sip_content_type_make(su_home_t *home, char const *s)
15302{
15303 return (sip_content_type_t *)sip_header_make(home, sip_content_type_class, s)((sip_header_t *)msg_header_make((home), (sip_content_type_class
), (s)))
;
15304}
15305#endif
15306
15307/**Make a @ref sip_content_type "Content-Type header" from formatting result.
15308 *
15309 * Make a new #sip_content_type_t object using formatting result as its value.
15310 * The function first prints the arguments according to the format @a fmt
15311 * specified. Then it allocates a new header structure, and parses the
15312 * formatting result to the structure #sip_content_type_t.
15313 *
15314 * @param home memory home used to allocate new header structure.
15315 * @param fmt string used as a printf()-style format
15316 * @param ... argument list for format
15317 *
15318 * @return
15319 * A pointer to newly
15320 * makes header structure, or NULL upon an error.
15321 *
15322 * @HIDE
15323 *
15324 */
15325#if SU_HAVE_INLINE1
15326su_inlinestatic inline
15327#endif
15328sip_content_type_t *sip_content_type_format(su_home_t *home, char const *fmt, ...)
15329 __attribute__((__malloc__, __format__ (printf, 2, 3)));
15330
15331#if SU_HAVE_INLINE1
15332su_inlinestatic inline sip_content_type_t *sip_content_type_format(su_home_t *home, char const *fmt, ...)
15333{
15334 sip_header_t *h;
15335 va_list ap;
15336
15337 va_start(ap, fmt)__builtin_va_start(ap, fmt);
15338 h = sip_header_vformat(home, sip_content_type_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_content_type_class
), (fmt), (ap)))
;
15339 va_end(ap)__builtin_va_end(ap);
15340
15341 return (sip_content_type_t *)h;
15342}
15343#endif
15344
15345/** @} */
15346
15347/**@addtogroup sip_content_encoding
15348 * @{
15349 */
15350
15351/** Parse a SIP @ref sip_content_encoding "Content-Encoding header". @internal */
15352SOFIAPUBFUN issize_t sip_content_encoding_d(su_home_t *, msg_header_t *,
15353 char *s, isize_t slen);
15354
15355/** Print a SIP @ref sip_content_encoding "Content-Encoding header". @internal */
15356SOFIAPUBFUN issize_t sip_content_encoding_e(char b[], isize_t bsiz,
15357 msg_header_t const *h, int flags);
15358
15359/**Access a SIP @ref sip_content_encoding "Content-Encoding header"
15360 * structure #sip_content_encoding_t from #sip_t.
15361 *
15362 */
15363#define sip_content_encoding(sip)((sip_content_encoding_t *)msg_header_access((msg_pub_t*)(sip
), sip_content_encoding_class))
\
15364 ((sip_content_encoding_t *)msg_header_access((msg_pub_t*)(sip), sip_content_encoding_class))
15365
15366/**Initializer for structure #sip_content_encoding_t.
15367 *
15368 * A static #sip_content_encoding_t structure for
15369 * @ref sip_content_encoding "Content-Encoding header" must be initialized with
15370 * the SIP_CONTENT_ENCODING_INIT() macro.
15371 * For instance,
15372 * @code
15373 *
15374 * sip_content_encoding_t sip_content_encoding = SIP_CONTENT_ENCODING_INIT;
15375 *
15376 * @endcode
15377 * @HI
15378 *
15379 */
15380#define SIP_CONTENT_ENCODING_INIT(){{{ 0, 0, sip_content_encoding_class }}} SIP_HDR_INIT(content_encoding){{{ 0, 0, sip_content_encoding_class }}}
15381
15382/**Initialize a structure #sip_content_encoding_t.
15383 *
15384 * An #sip_content_encoding_t structure for
15385 * @ref sip_content_encoding "Content-Encoding header" can be initialized with the
15386 * sip_content_encoding_init() function/macro. For instance,
15387 * @code
15388 *
15389 * sip_content_encoding_t sip_content_encoding;
15390 *
15391 * sip_content_encoding_init(&sip_content_encoding);
15392 *
15393 * @endcode
15394 * @HI
15395 *
15396 */
15397#if SU_HAVE_INLINE1
15398su_inlinestatic inline sip_content_encoding_t *sip_content_encoding_init(sip_content_encoding_t x[1])
15399{
15400 return SIP_HEADER_INIT(x, sip_content_encoding_class, sizeof(sip_content_encoding_t))((void)memset((x), 0, (sizeof(sip_content_encoding_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_content_encoding_class
)), (x))
;
15401}
15402#else
15403#define sip_content_encoding_init(x) \
15404 SIP_HEADER_INIT(x, sip_content_encoding_class, sizeof(sip_content_encoding_t))((void)memset((x), 0, (sizeof(sip_content_encoding_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_content_encoding_class
)), (x))
15405#endif
15406
15407/**Test if header object is instance of #sip_content_encoding_t.
15408 *
15409 * Check if the header class is an instance of
15410 * @ref sip_content_encoding "Content-Encoding header" object and return true (nonzero),
15411 * otherwise return false (zero).
15412 *
15413 * @param header pointer to the header structure to be tested
15414 *
15415 * @retval 1 (true) if the @a header is an instance of header content_encoding
15416 * @retval 0 (false) otherwise
15417 *
15418 */
15419#if SU_HAVE_INLINE1
15420su_inlinestatic inline int sip_is_content_encoding(sip_header_t const *header)
15421{
15422 return header && header->sh_classsh_common->h_class->hc_hash == sip_content_encoding_hash;
15423}
15424#else
15425int sip_is_content_encoding(sip_header_t const *header);
15426#endif
15427
15428#define sip_content_encoding_p(h)sip_is_content_encoding((h)) sip_is_content_encoding((h))
15429
15430
15431/**Duplicate a list of @ref sip_content_encoding "Content-Encoding header" header structures #sip_content_encoding_t.
15432 *
15433 * Duplicate a header
15434 * structure @a hdr. If the header structure @a hdr
15435 * contains a reference (@c hdr->x_next) to a list of
15436 * headers, all the headers in the list are duplicated, too.
15437 *
15438 * @param home memory home used to allocate new structure
15439 * @param hdr header structure to be duplicated
15440 *
15441 * When duplicating, all parameter lists and non-constant
15442 * strings attached to the header are copied, too. The
15443 * function uses given memory @a home to allocate all the
15444 * memory areas used to copy the header.
15445 *
15446 * @par Example
15447 * @code
15448 *
15449 * content_encoding = sip_content_encoding_dup(home, sip->sip_content_encoding);
15450 *
15451 * @endcode
15452 *
15453 * @return
15454 * A pointer to the
15455 * newly duplicated #sip_content_encoding_t header structure, or NULL
15456 * upon an error.
15457 *
15458 */
15459#if SU_HAVE_INLINE1
15460su_inlinestatic inline
15461#endif
15462sip_content_encoding_t *sip_content_encoding_dup(su_home_t *home, sip_content_encoding_t const *hdr)
15463 __attribute__((__malloc__));
15464
15465#if SU_HAVE_INLINE1
15466su_inlinestatic inline
15467sip_content_encoding_t *sip_content_encoding_dup(su_home_t *home, sip_content_encoding_t const *hdr)
15468{
15469 return (sip_content_encoding_t *)
15470 msg_header_dup_as(home, sip_content_encoding_class, (msg_header_t const *)hdr);
15471}
15472#endif
15473
15474/**Copy a list of @ref sip_content_encoding "Content-Encoding header" header structures #sip_content_encoding_t.
15475 *
15476 * The function sip_content_encoding_copy() copies a header structure @a
15477 * hdr. If the header structure @a hdr contains a reference (@c
15478 * hdr->h_next) to a list of headers, all the headers in that
15479 * list are copied, too. The function uses given memory @a home
15480 * to allocate all the memory areas used to copy the list of header
15481 * structure @a hdr.
15482 *
15483 * @param home memory home used to allocate new structure
15484 * @param hdr pointer to the header structure to be copied
15485 *
15486 * When copying, only the header structure and parameter lists attached to
15487 * it are duplicated. The new header structure retains all the references to
15488 * the strings within the old @a hdr header, including the encoding of the
15489 * old header, if present.
15490 *
15491 * @par Example
15492 * @code
15493 *
15494 * content_encoding = sip_content_encoding_copy(home, sip->sip_content_encoding);
15495 *
15496 * @endcode
15497 *
15498 * @return
15499 * A pointer to newly copied header structure, or NULL upon an error.
15500 *
15501 */
15502#if SU_HAVE_INLINE1
15503su_inlinestatic inline
15504#endif
15505sip_content_encoding_t *sip_content_encoding_copy(su_home_t *home, sip_content_encoding_t const *hdr)
15506 __attribute__((__malloc__));
15507
15508#if SU_HAVE_INLINE1
15509su_inlinestatic inline
15510sip_content_encoding_t *sip_content_encoding_copy(su_home_t *home, sip_content_encoding_t const *hdr)
15511{
15512 return (sip_content_encoding_t *)
15513 msg_header_copy_as(home, sip_content_encoding_class, (msg_header_t const *)hdr);
15514}
15515#endif
15516
15517/**Make a @ref sip_content_encoding "Content-Encoding header" structure #sip_content_encoding_t.
15518 *
15519 * The function sip_content_encoding_make() makes a new
15520 * #sip_content_encoding_t header structure. It allocates a new
15521 * header structure, and decodes the string @a s as the
15522 * value of the structure.
15523 *
15524 * @param home memory home used to allocate new header structure.
15525 * @param s string to be decoded as value of the new header structure
15526 *
15527 * @return
15528 * A pointer to newly maked #sip_content_encoding_t header structure, or NULL upon an
15529 * error.
15530 *
15531 */
15532#if SU_HAVE_INLINE1
15533su_inlinestatic inline
15534#endif
15535sip_content_encoding_t *sip_content_encoding_make(su_home_t *home, char const *s)
15536 __attribute__((__malloc__));
15537
15538#if SU_HAVE_INLINE1
15539su_inlinestatic inline sip_content_encoding_t *sip_content_encoding_make(su_home_t *home, char const *s)
15540{
15541 return (sip_content_encoding_t *)sip_header_make(home, sip_content_encoding_class, s)((sip_header_t *)msg_header_make((home), (sip_content_encoding_class
), (s)))
;
15542}
15543#endif
15544
15545/**Make a @ref sip_content_encoding "Content-Encoding header" from formatting result.
15546 *
15547 * Make a new #sip_content_encoding_t object using formatting result as its value.
15548 * The function first prints the arguments according to the format @a fmt
15549 * specified. Then it allocates a new header structure, and parses the
15550 * formatting result to the structure #sip_content_encoding_t.
15551 *
15552 * @param home memory home used to allocate new header structure.
15553 * @param fmt string used as a printf()-style format
15554 * @param ... argument list for format
15555 *
15556 * @return
15557 * A pointer to newly
15558 * makes header structure, or NULL upon an error.
15559 *
15560 * @HIDE
15561 *
15562 */
15563#if SU_HAVE_INLINE1
15564su_inlinestatic inline
15565#endif
15566sip_content_encoding_t *sip_content_encoding_format(su_home_t *home, char const *fmt, ...)
15567 __attribute__((__malloc__, __format__ (printf, 2, 3)));
15568
15569#if SU_HAVE_INLINE1
15570su_inlinestatic inline sip_content_encoding_t *sip_content_encoding_format(su_home_t *home, char const *fmt, ...)
15571{
15572 sip_header_t *h;
15573 va_list ap;
15574
15575 va_start(ap, fmt)__builtin_va_start(ap, fmt);
15576 h = sip_header_vformat(home, sip_content_encoding_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_content_encoding_class
), (fmt), (ap)))
;
15577 va_end(ap)__builtin_va_end(ap);
15578
15579 return (sip_content_encoding_t *)h;
15580}
15581#endif
15582
15583/** @} */
15584
15585/**@addtogroup sip_content_language
15586 * @{
15587 */
15588
15589/** Parse a SIP @ref sip_content_language "Content-Language header". @internal */
15590SOFIAPUBFUN issize_t sip_content_language_d(su_home_t *, msg_header_t *,
15591 char *s, isize_t slen);
15592
15593/** Print a SIP @ref sip_content_language "Content-Language header". @internal */
15594SOFIAPUBFUN issize_t sip_content_language_e(char b[], isize_t bsiz,
15595 msg_header_t const *h, int flags);
15596
15597/**Access a SIP @ref sip_content_language "Content-Language header"
15598 * structure #sip_content_language_t from #sip_t.
15599 *
15600 */
15601#define sip_content_language(sip)((sip_content_language_t *)msg_header_access((msg_pub_t*)(sip
), sip_content_language_class))
\
15602 ((sip_content_language_t *)msg_header_access((msg_pub_t*)(sip), sip_content_language_class))
15603
15604/**Initializer for structure #sip_content_language_t.
15605 *
15606 * A static #sip_content_language_t structure for
15607 * @ref sip_content_language "Content-Language header" must be initialized with
15608 * the SIP_CONTENT_LANGUAGE_INIT() macro.
15609 * For instance,
15610 * @code
15611 *
15612 * sip_content_language_t sip_content_language = SIP_CONTENT_LANGUAGE_INIT;
15613 *
15614 * @endcode
15615 * @HI
15616 *
15617 */
15618#define SIP_CONTENT_LANGUAGE_INIT(){{{ 0, 0, sip_content_language_class }}} SIP_HDR_INIT(content_language){{{ 0, 0, sip_content_language_class }}}
15619
15620/**Initialize a structure #sip_content_language_t.
15621 *
15622 * An #sip_content_language_t structure for
15623 * @ref sip_content_language "Content-Language header" can be initialized with the
15624 * sip_content_language_init() function/macro. For instance,
15625 * @code
15626 *
15627 * sip_content_language_t sip_content_language;
15628 *
15629 * sip_content_language_init(&sip_content_language);
15630 *
15631 * @endcode
15632 * @HI
15633 *
15634 */
15635#if SU_HAVE_INLINE1
15636su_inlinestatic inline sip_content_language_t *sip_content_language_init(sip_content_language_t x[1])
15637{
15638 return SIP_HEADER_INIT(x, sip_content_language_class, sizeof(sip_content_language_t))((void)memset((x), 0, (sizeof(sip_content_language_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_content_language_class
)), (x))
;
15639}
15640#else
15641#define sip_content_language_init(x) \
15642 SIP_HEADER_INIT(x, sip_content_language_class, sizeof(sip_content_language_t))((void)memset((x), 0, (sizeof(sip_content_language_t))), (void
)(((sip_common_t *)(x))->h_class = (sip_content_language_class
)), (x))
15643#endif
15644
15645/**Test if header object is instance of #sip_content_language_t.
15646 *
15647 * Check if the header class is an instance of
15648 * @ref sip_content_language "Content-Language header" object and return true (nonzero),
15649 * otherwise return false (zero).
15650 *
15651 * @param header pointer to the header structure to be tested
15652 *
15653 * @retval 1 (true) if the @a header is an instance of header content_language
15654 * @retval 0 (false) otherwise
15655 *
15656 */
15657#if SU_HAVE_INLINE1
15658su_inlinestatic inline int sip_is_content_language(sip_header_t const *header)
15659{
15660 return header && header->sh_classsh_common->h_class->hc_hash == sip_content_language_hash;
15661}
15662#else
15663int sip_is_content_language(sip_header_t const *header);
15664#endif
15665
15666#define sip_content_language_p(h)sip_is_content_language((h)) sip_is_content_language((h))
15667
15668
15669/**Duplicate a list of @ref sip_content_language "Content-Language header" header structures #sip_content_language_t.
15670 *
15671 * Duplicate a header
15672 * structure @a hdr. If the header structure @a hdr
15673 * contains a reference (@c hdr->x_next) to a list of
15674 * headers, all the headers in the list are duplicated, too.
15675 *
15676 * @param home memory home used to allocate new structure
15677 * @param hdr header structure to be duplicated
15678 *
15679 * When duplicating, all parameter lists and non-constant
15680 * strings attached to the header are copied, too. The
15681 * function uses given memory @a home to allocate all the
15682 * memory areas used to copy the header.
15683 *
15684 * @par Example
15685 * @code
15686 *
15687 * content_language = sip_content_language_dup(home, sip->sip_content_language);
15688 *
15689 * @endcode
15690 *
15691 * @return
15692 * A pointer to the
15693 * newly duplicated #sip_content_language_t header structure, or NULL
15694 * upon an error.
15695 *
15696 */
15697#if SU_HAVE_INLINE1
15698su_inlinestatic inline
15699#endif
15700sip_content_language_t *sip_content_language_dup(su_home_t *home, sip_content_language_t const *hdr)
15701 __attribute__((__malloc__));
15702
15703#if SU_HAVE_INLINE1
15704su_inlinestatic inline
15705sip_content_language_t *sip_content_language_dup(su_home_t *home, sip_content_language_t const *hdr)
15706{
15707 return (sip_content_language_t *)
15708 msg_header_dup_as(home, sip_content_language_class, (msg_header_t const *)hdr);
15709}
15710#endif
15711
15712/**Copy a list of @ref sip_content_language "Content-Language header" header structures #sip_content_language_t.
15713 *
15714 * The function sip_content_language_copy() copies a header structure @a
15715 * hdr. If the header structure @a hdr contains a reference (@c
15716 * hdr->h_next) to a list of headers, all the headers in that
15717 * list are copied, too. The function uses given memory @a home
15718 * to allocate all the memory areas used to copy the list of header
15719 * structure @a hdr.
15720 *
15721 * @param home memory home used to allocate new structure
15722 * @param hdr pointer to the header structure to be copied
15723 *
15724 * When copying, only the header structure and parameter lists attached to
15725 * it are duplicated. The new header structure retains all the references to
15726 * the strings within the old @a hdr header, including the encoding of the
15727 * old header, if present.
15728 *
15729 * @par Example
15730 * @code
15731 *
15732 * content_language = sip_content_language_copy(home, sip->sip_content_language);
15733 *
15734 * @endcode
15735 *
15736 * @return
15737 * A pointer to newly copied header structure, or NULL upon an error.
15738 *
15739 */
15740#if SU_HAVE_INLINE1
15741su_inlinestatic inline
15742#endif
15743sip_content_language_t *sip_content_language_copy(su_home_t *home, sip_content_language_t const *hdr)
15744 __attribute__((__malloc__));
15745
15746#if SU_HAVE_INLINE1
15747su_inlinestatic inline
15748sip_content_language_t *sip_content_language_copy(su_home_t *home, sip_content_language_t const *hdr)
15749{
15750 return (sip_content_language_t *)
15751 msg_header_copy_as(home, sip_content_language_class, (msg_header_t const *)hdr);
15752}
15753#endif
15754
15755/**Make a @ref sip_content_language "Content-Language header" structure #sip_content_language_t.
15756 *
15757 * The function sip_content_language_make() makes a new
15758 * #sip_content_language_t header structure. It allocates a new
15759 * header structure, and decodes the string @a s as the
15760 * value of the structure.
15761 *
15762 * @param home memory home used to allocate new header structure.
15763 * @param s string to be decoded as value of the new header structure
15764 *
15765 * @return
15766 * A pointer to newly maked #sip_content_language_t header structure, or NULL upon an
15767 * error.
15768 *
15769 */
15770#if SU_HAVE_INLINE1
15771su_inlinestatic inline
15772#endif
15773sip_content_language_t *sip_content_language_make(su_home_t *home, char const *s)
15774 __attribute__((__malloc__));
15775
15776#if SU_HAVE_INLINE1
15777su_inlinestatic inline sip_content_language_t *sip_content_language_make(su_home_t *home, char const *s)
15778{
15779 return (sip_content_language_t *)sip_header_make(home, sip_content_language_class, s)((sip_header_t *)msg_header_make((home), (sip_content_language_class
), (s)))
;
15780}
15781#endif
15782
15783/**Make a @ref sip_content_language "Content-Language header" from formatting result.
15784 *
15785 * Make a new #sip_content_language_t object using formatting result as its value.
15786 * The function first prints the arguments according to the format @a fmt
15787 * specified. Then it allocates a new header structure, and parses the
15788 * formatting result to the structure #sip_content_language_t.
15789 *
15790 * @param home memory home used to allocate new header structure.
15791 * @param fmt string used as a printf()-style format
15792 * @param ... argument list for format
15793 *
15794 * @return
15795 * A pointer to newly
15796 * makes header structure, or NULL upon an error.
15797 *
15798 * @HIDE
15799 *
15800 */
15801#if SU_HAVE_INLINE1
15802su_inlinestatic inline
15803#endif
15804sip_content_language_t *sip_content_language_format(su_home_t *home, char const *fmt, ...)
15805 __attribute__((__malloc__, __format__ (printf, 2, 3)));
15806
15807#if SU_HAVE_INLINE1
15808su_inlinestatic inline sip_content_language_t *sip_content_language_format(su_home_t *home, char const *fmt, ...)
15809{
15810 sip_header_t *h;
15811 va_list ap;
15812
15813 va_start(ap, fmt)__builtin_va_start(ap, fmt);
15814 h = sip_header_vformat(home, sip_content_language_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_content_language_class
), (fmt), (ap)))
;
15815 va_end(ap)__builtin_va_end(ap);
15816
15817 return (sip_content_language_t *)h;
15818}
15819#endif
15820
15821/** @} */
15822
15823/**@addtogroup sip_content_disposition
15824 * @{
15825 */
15826
15827/** Parse a SIP @ref sip_content_disposition "Content-Disposition header". @internal */
15828SOFIAPUBFUN issize_t sip_content_disposition_d(su_home_t *, msg_header_t *,
15829 char *s, isize_t slen);
15830
15831/** Print a SIP @ref sip_content_disposition "Content-Disposition header". @internal */
15832SOFIAPUBFUN issize_t sip_content_disposition_e(char b[], isize_t bsiz,
15833 msg_header_t const *h, int flags);
15834
15835/**Access a SIP @ref sip_content_disposition "Content-Disposition header"
15836 * structure #sip_content_disposition_t from #sip_t.
15837 *
15838 */
15839#define sip_content_disposition(sip)((sip_content_disposition_t *)msg_header_access((msg_pub_t*)(
sip), sip_content_disposition_class))
\
15840 ((sip_content_disposition_t *)msg_header_access((msg_pub_t*)(sip), sip_content_disposition_class))
15841
15842/**Initializer for structure #sip_content_disposition_t.
15843 *
15844 * A static #sip_content_disposition_t structure for
15845 * @ref sip_content_disposition "Content-Disposition header" must be initialized with
15846 * the SIP_CONTENT_DISPOSITION_INIT() macro.
15847 * For instance,
15848 * @code
15849 *
15850 * sip_content_disposition_t sip_content_disposition = SIP_CONTENT_DISPOSITION_INIT;
15851 *
15852 * @endcode
15853 * @HI
15854 *
15855 */
15856#define SIP_CONTENT_DISPOSITION_INIT(){{{ 0, 0, sip_content_disposition_class }}} SIP_HDR_INIT(content_disposition){{{ 0, 0, sip_content_disposition_class }}}
15857
15858/**Initialize a structure #sip_content_disposition_t.
15859 *
15860 * An #sip_content_disposition_t structure for
15861 * @ref sip_content_disposition "Content-Disposition header" can be initialized with the
15862 * sip_content_disposition_init() function/macro. For instance,
15863 * @code
15864 *
15865 * sip_content_disposition_t sip_content_disposition;
15866 *
15867 * sip_content_disposition_init(&sip_content_disposition);
15868 *
15869 * @endcode
15870 * @HI
15871 *
15872 */
15873#if SU_HAVE_INLINE1
15874su_inlinestatic inline sip_content_disposition_t *sip_content_disposition_init(sip_content_disposition_t x[1])
15875{
15876 return SIP_HEADER_INIT(x, sip_content_disposition_class, sizeof(sip_content_disposition_t))((void)memset((x), 0, (sizeof(sip_content_disposition_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_content_disposition_class
)), (x))
;
15877}
15878#else
15879#define sip_content_disposition_init(x) \
15880 SIP_HEADER_INIT(x, sip_content_disposition_class, sizeof(sip_content_disposition_t))((void)memset((x), 0, (sizeof(sip_content_disposition_t))), (
void)(((sip_common_t *)(x))->h_class = (sip_content_disposition_class
)), (x))
15881#endif
15882
15883/**Test if header object is instance of #sip_content_disposition_t.
15884 *
15885 * Check if the header class is an instance of
15886 * @ref sip_content_disposition "Content-Disposition header" object and return true (nonzero),
15887 * otherwise return false (zero).
15888 *
15889 * @param header pointer to the header structure to be tested
15890 *
15891 * @retval 1 (true) if the @a header is an instance of header content_disposition
15892 * @retval 0 (false) otherwise
15893 *
15894 */
15895#if SU_HAVE_INLINE1
15896su_inlinestatic inline int sip_is_content_disposition(sip_header_t const *header)
15897{
15898 return header && header->sh_classsh_common->h_class->hc_hash == sip_content_disposition_hash;
15899}
15900#else
15901int sip_is_content_disposition(sip_header_t const *header);
15902#endif
15903
15904#define sip_content_disposition_p(h)sip_is_content_disposition((h)) sip_is_content_disposition((h))
15905
15906
15907/**Duplicate a list of @ref sip_content_disposition "Content-Disposition header" header structures #sip_content_disposition_t.
15908 *
15909 * Duplicate a header
15910 * structure @a hdr. If the header structure @a hdr
15911 * contains a reference (@c hdr->x_next) to a list of
15912 * headers, all the headers in the list are duplicated, too.
15913 *
15914 * @param home memory home used to allocate new structure
15915 * @param hdr header structure to be duplicated
15916 *
15917 * When duplicating, all parameter lists and non-constant
15918 * strings attached to the header are copied, too. The
15919 * function uses given memory @a home to allocate all the
15920 * memory areas used to copy the header.
15921 *
15922 * @par Example
15923 * @code
15924 *
15925 * content_disposition = sip_content_disposition_dup(home, sip->sip_content_disposition);
15926 *
15927 * @endcode
15928 *
15929 * @return
15930 * A pointer to the
15931 * newly duplicated #sip_content_disposition_t header structure, or NULL
15932 * upon an error.
15933 *
15934 */
15935#if SU_HAVE_INLINE1
15936su_inlinestatic inline
15937#endif
15938sip_content_disposition_t *sip_content_disposition_dup(su_home_t *home, sip_content_disposition_t const *hdr)
15939 __attribute__((__malloc__));
15940
15941#if SU_HAVE_INLINE1
15942su_inlinestatic inline
15943sip_content_disposition_t *sip_content_disposition_dup(su_home_t *home, sip_content_disposition_t const *hdr)
15944{
15945 return (sip_content_disposition_t *)
15946 msg_header_dup_as(home, sip_content_disposition_class, (msg_header_t const *)hdr);
15947}
15948#endif
15949
15950/**Copy a list of @ref sip_content_disposition "Content-Disposition header" header structures #sip_content_disposition_t.
15951 *
15952 * The function sip_content_disposition_copy() copies a header structure @a
15953 * hdr. If the header structure @a hdr contains a reference (@c
15954 * hdr->h_next) to a list of headers, all the headers in that
15955 * list are copied, too. The function uses given memory @a home
15956 * to allocate all the memory areas used to copy the list of header
15957 * structure @a hdr.
15958 *
15959 * @param home memory home used to allocate new structure
15960 * @param hdr pointer to the header structure to be copied
15961 *
15962 * When copying, only the header structure and parameter lists attached to
15963 * it are duplicated. The new header structure retains all the references to
15964 * the strings within the old @a hdr header, including the encoding of the
15965 * old header, if present.
15966 *
15967 * @par Example
15968 * @code
15969 *
15970 * content_disposition = sip_content_disposition_copy(home, sip->sip_content_disposition);
15971 *
15972 * @endcode
15973 *
15974 * @return
15975 * A pointer to newly copied header structure, or NULL upon an error.
15976 *
15977 */
15978#if SU_HAVE_INLINE1
15979su_inlinestatic inline
15980#endif
15981sip_content_disposition_t *sip_content_disposition_copy(su_home_t *home, sip_content_disposition_t const *hdr)
15982 __attribute__((__malloc__));
15983
15984#if SU_HAVE_INLINE1
15985su_inlinestatic inline
15986sip_content_disposition_t *sip_content_disposition_copy(su_home_t *home, sip_content_disposition_t const *hdr)
15987{
15988 return (sip_content_disposition_t *)
15989 msg_header_copy_as(home, sip_content_disposition_class, (msg_header_t const *)hdr);
15990}
15991#endif
15992
15993/**Make a @ref sip_content_disposition "Content-Disposition header" structure #sip_content_disposition_t.
15994 *
15995 * The function sip_content_disposition_make() makes a new
15996 * #sip_content_disposition_t header structure. It allocates a new
15997 * header structure, and decodes the string @a s as the
15998 * value of the structure.
15999 *
16000 * @param home memory home used to allocate new header structure.
16001 * @param s string to be decoded as value of the new header structure
16002 *
16003 * @return
16004 * A pointer to newly maked #sip_content_disposition_t header structure, or NULL upon an
16005 * error.
16006 *
16007 */
16008#if SU_HAVE_INLINE1
16009su_inlinestatic inline
16010#endif
16011sip_content_disposition_t *sip_content_disposition_make(su_home_t *home, char const *s)
16012 __attribute__((__malloc__));
16013
16014#if SU_HAVE_INLINE1
16015su_inlinestatic inline sip_content_disposition_t *sip_content_disposition_make(su_home_t *home, char const *s)
16016{
16017 return (sip_content_disposition_t *)sip_header_make(home, sip_content_disposition_class, s)((sip_header_t *)msg_header_make((home), (sip_content_disposition_class
), (s)))
;
16018}
16019#endif
16020
16021/**Make a @ref sip_content_disposition "Content-Disposition header" from formatting result.
16022 *
16023 * Make a new #sip_content_disposition_t object using formatting result as its value.
16024 * The function first prints the arguments according to the format @a fmt
16025 * specified. Then it allocates a new header structure, and parses the
16026 * formatting result to the structure #sip_content_disposition_t.
16027 *
16028 * @param home memory home used to allocate new header structure.
16029 * @param fmt string used as a printf()-style format
16030 * @param ... argument list for format
16031 *
16032 * @return
16033 * A pointer to newly
16034 * makes header structure, or NULL upon an error.
16035 *
16036 * @HIDE
16037 *
16038 */
16039#if SU_HAVE_INLINE1
16040su_inlinestatic inline
16041#endif
16042sip_content_disposition_t *sip_content_disposition_format(su_home_t *home, char const *fmt, ...)
16043 __attribute__((__malloc__, __format__ (printf, 2, 3)));
16044
16045#if SU_HAVE_INLINE1
16046su_inlinestatic inline sip_content_disposition_t *sip_content_disposition_format(su_home_t *home, char const *fmt, ...)
16047{
16048 sip_header_t *h;
16049 va_list ap;
16050
16051 va_start(ap, fmt)__builtin_va_start(ap, fmt);
16052 h = sip_header_vformat(home, sip_content_disposition_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_content_disposition_class
), (fmt), (ap)))
;
16053 va_end(ap)__builtin_va_end(ap);
16054
16055 return (sip_content_disposition_t *)h;
16056}
16057#endif
16058
16059/** @} */
16060
16061/**@addtogroup sip_content_length
16062 * @{
16063 */
16064
16065/** Parse a SIP @ref sip_content_length "Content-Length header". @internal */
16066SOFIAPUBFUN issize_t sip_content_length_d(su_home_t *, msg_header_t *,
16067 char *s, isize_t slen);
16068
16069/** Print a SIP @ref sip_content_length "Content-Length header". @internal */
16070SOFIAPUBFUN issize_t sip_content_length_e(char b[], isize_t bsiz,
16071 msg_header_t const *h, int flags);
16072
16073/**Access a SIP @ref sip_content_length "Content-Length header"
16074 * structure #sip_content_length_t from #sip_t.
16075 *
16076 */
16077#define sip_content_length(sip)((sip_content_length_t *)msg_header_access((msg_pub_t*)(sip),
sip_content_length_class))
\
16078 ((sip_content_length_t *)msg_header_access((msg_pub_t*)(sip), sip_content_length_class))
16079
16080/**Initializer for structure #sip_content_length_t.
16081 *
16082 * A static #sip_content_length_t structure for
16083 * @ref sip_content_length "Content-Length header" must be initialized with
16084 * the SIP_CONTENT_LENGTH_INIT() macro.
16085 * For instance,
16086 * @code
16087 *
16088 * sip_content_length_t sip_content_length = SIP_CONTENT_LENGTH_INIT;
16089 *
16090 * @endcode
16091 * @HI
16092 *
16093 */
16094#define SIP_CONTENT_LENGTH_INIT(){{{ 0, 0, sip_content_length_class }}} SIP_HDR_INIT(content_length){{{ 0, 0, sip_content_length_class }}}
16095
16096/**Initialize a structure #sip_content_length_t.
16097 *
16098 * An #sip_content_length_t structure for
16099 * @ref sip_content_length "Content-Length header" can be initialized with the
16100 * sip_content_length_init() function/macro. For instance,
16101 * @code
16102 *
16103 * sip_content_length_t sip_content_length;
16104 *
16105 * sip_content_length_init(&sip_content_length);
16106 *
16107 * @endcode
16108 * @HI
16109 *
16110 */
16111#if SU_HAVE_INLINE1
16112su_inlinestatic inline sip_content_length_t *sip_content_length_init(sip_content_length_t x[1])
16113{
16114 return SIP_HEADER_INIT(x, sip_content_length_class, sizeof(sip_content_length_t))((void)memset((x), 0, (sizeof(sip_content_length_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_content_length_class
)), (x))
;
16115}
16116#else
16117#define sip_content_length_init(x) \
16118 SIP_HEADER_INIT(x, sip_content_length_class, sizeof(sip_content_length_t))((void)memset((x), 0, (sizeof(sip_content_length_t))), (void)
(((sip_common_t *)(x))->h_class = (sip_content_length_class
)), (x))
16119#endif
16120
16121/**Test if header object is instance of #sip_content_length_t.
16122 *
16123 * Check if the header class is an instance of
16124 * @ref sip_content_length "Content-Length header" object and return true (nonzero),
16125 * otherwise return false (zero).
16126 *
16127 * @param header pointer to the header structure to be tested
16128 *
16129 * @retval 1 (true) if the @a header is an instance of header content_length
16130 * @retval 0 (false) otherwise
16131 *
16132 */
16133#if SU_HAVE_INLINE1
16134su_inlinestatic inline int sip_is_content_length(sip_header_t const *header)
16135{
16136 return header && header->sh_classsh_common->h_class->hc_hash == sip_content_length_hash;
16137}
16138#else
16139int sip_is_content_length(sip_header_t const *header);
16140#endif
16141
16142#define sip_content_length_p(h)sip_is_content_length((h)) sip_is_content_length((h))
16143
16144
16145/**Duplicate a list of @ref sip_content_length "Content-Length header" header structures #sip_content_length_t.
16146 *
16147 * Duplicate a header
16148 * structure @a hdr. If the header structure @a hdr
16149 * contains a reference (@c hdr->x_next) to a list of
16150 * headers, all the headers in the list are duplicated, too.
16151 *
16152 * @param home memory home used to allocate new structure
16153 * @param hdr header structure to be duplicated
16154 *
16155 * When duplicating, all parameter lists and non-constant
16156 * strings attached to the header are copied, too. The
16157 * function uses given memory @a home to allocate all the
16158 * memory areas used to copy the header.
16159 *
16160 * @par Example
16161 * @code
16162 *
16163 * content_length = sip_content_length_dup(home, sip->sip_content_length);
16164 *
16165 * @endcode
16166 *
16167 * @return
16168 * A pointer to the
16169 * newly duplicated #sip_content_length_t header structure, or NULL
16170 * upon an error.
16171 *
16172 */
16173#if SU_HAVE_INLINE1
16174su_inlinestatic inline
16175#endif
16176sip_content_length_t *sip_content_length_dup(su_home_t *home, sip_content_length_t const *hdr)
16177 __attribute__((__malloc__));
16178
16179#if SU_HAVE_INLINE1
16180su_inlinestatic inline
16181sip_content_length_t *sip_content_length_dup(su_home_t *home, sip_content_length_t const *hdr)
16182{
16183 return (sip_content_length_t *)
16184 msg_header_dup_as(home, sip_content_length_class, (msg_header_t const *)hdr);
16185}
16186#endif
16187
16188/**Copy a list of @ref sip_content_length "Content-Length header" header structures #sip_content_length_t.
16189 *
16190 * The function sip_content_length_copy() copies a header structure @a
16191 * hdr. If the header structure @a hdr contains a reference (@c
16192 * hdr->h_next) to a list of headers, all the headers in that
16193 * list are copied, too. The function uses given memory @a home
16194 * to allocate all the memory areas used to copy the list of header
16195 * structure @a hdr.
16196 *
16197 * @param home memory home used to allocate new structure
16198 * @param hdr pointer to the header structure to be copied
16199 *
16200 * When copying, only the header structure and parameter lists attached to
16201 * it are duplicated. The new header structure retains all the references to
16202 * the strings within the old @a hdr header, including the encoding of the
16203 * old header, if present.
16204 *
16205 * @par Example
16206 * @code
16207 *
16208 * content_length = sip_content_length_copy(home, sip->sip_content_length);
16209 *
16210 * @endcode
16211 *
16212 * @return
16213 * A pointer to newly copied header structure, or NULL upon an error.
16214 *
16215 */
16216#if SU_HAVE_INLINE1
16217su_inlinestatic inline
16218#endif
16219sip_content_length_t *sip_content_length_copy(su_home_t *home, sip_content_length_t const *hdr)
16220 __attribute__((__malloc__));
16221
16222#if SU_HAVE_INLINE1
16223su_inlinestatic inline
16224sip_content_length_t *sip_content_length_copy(su_home_t *home, sip_content_length_t const *hdr)
16225{
16226 return (sip_content_length_t *)
16227 msg_header_copy_as(home, sip_content_length_class, (msg_header_t const *)hdr);
16228}
16229#endif
16230
16231/**Make a @ref sip_content_length "Content-Length header" structure #sip_content_length_t.
16232 *
16233 * The function sip_content_length_make() makes a new
16234 * #sip_content_length_t header structure. It allocates a new
16235 * header structure, and decodes the string @a s as the
16236 * value of the structure.
16237 *
16238 * @param home memory home used to allocate new header structure.
16239 * @param s string to be decoded as value of the new header structure
16240 *
16241 * @return
16242 * A pointer to newly maked #sip_content_length_t header structure, or NULL upon an
16243 * error.
16244 *
16245 */
16246#if SU_HAVE_INLINE1
16247su_inlinestatic inline
16248#endif
16249sip_content_length_t *sip_content_length_make(su_home_t *home, char const *s)
16250 __attribute__((__malloc__));
16251
16252#if SU_HAVE_INLINE1
16253su_inlinestatic inline sip_content_length_t *sip_content_length_make(su_home_t *home, char const *s)
16254{
16255 return (sip_content_length_t *)sip_header_make(home, sip_content_length_class, s)((sip_header_t *)msg_header_make((home), (sip_content_length_class
), (s)))
;
16256}
16257#endif
16258
16259/**Make a @ref sip_content_length "Content-Length header" from formatting result.
16260 *
16261 * Make a new #sip_content_length_t object using formatting result as its value.
16262 * The function first prints the arguments according to the format @a fmt
16263 * specified. Then it allocates a new header structure, and parses the
16264 * formatting result to the structure #sip_content_length_t.
16265 *
16266 * @param home memory home used to allocate new header structure.
16267 * @param fmt string used as a printf()-style format
16268 * @param ... argument list for format
16269 *
16270 * @return
16271 * A pointer to newly
16272 * makes header structure, or NULL upon an error.
16273 *
16274 * @HIDE
16275 *
16276 */
16277#if SU_HAVE_INLINE1
16278su_inlinestatic inline
16279#endif
16280sip_content_length_t *sip_content_length_format(su_home_t *home, char const *fmt, ...)
16281 __attribute__((__malloc__, __format__ (printf, 2, 3)));
16282
16283#if SU_HAVE_INLINE1
16284su_inlinestatic inline sip_content_length_t *sip_content_length_format(su_home_t *home, char const *fmt, ...)
16285{
16286 sip_header_t *h;
16287 va_list ap;
16288
16289 va_start(ap, fmt)__builtin_va_start(ap, fmt);
16290 h = sip_header_vformat(home, sip_content_length_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_content_length_class
), (fmt), (ap)))
;
16291 va_end(ap)__builtin_va_end(ap);
16292
16293 return (sip_content_length_t *)h;
16294}
16295#endif
16296
16297/** @} */
16298
16299/**@addtogroup sip_unknown
16300 * @{
16301 */
16302
16303/** Parse a SIP @ref sip_unknown "unknown headers". @internal */
16304SOFIAPUBFUN issize_t sip_unknown_d(su_home_t *, msg_header_t *,
16305 char *s, isize_t slen);
16306
16307/** Print a SIP @ref sip_unknown "unknown headers". @internal */
16308SOFIAPUBFUN issize_t sip_unknown_e(char b[], isize_t bsiz,
16309 msg_header_t const *h, int flags);
16310
16311/**Access a SIP @ref sip_unknown "unknown headers"
16312 * structure #sip_unknown_t from #sip_t.
16313 *
16314 */
16315#define sip_unknown(sip)((sip_unknown_t *)msg_header_access((msg_pub_t*)(sip), sip_unknown_class
))
\
16316 ((sip_unknown_t *)msg_header_access((msg_pub_t*)(sip), sip_unknown_class))
16317
16318/**Initializer for structure #sip_unknown_t.
16319 *
16320 * A static #sip_unknown_t structure for
16321 * @ref sip_unknown "unknown headers" must be initialized with
16322 * the SIP_UNKNOWN_INIT() macro.
16323 * For instance,
16324 * @code
16325 *
16326 * sip_unknown_t sip_unknown = SIP_UNKNOWN_INIT;
16327 *
16328 * @endcode
16329 * @HI
16330 *
16331 */
16332#define SIP_UNKNOWN_INIT(){{{ 0, 0, sip_unknown_class }}} SIP_HDR_INIT(unknown){{{ 0, 0, sip_unknown_class }}}
16333
16334/**Initialize a structure #sip_unknown_t.
16335 *
16336 * An #sip_unknown_t structure for
16337 * @ref sip_unknown "unknown headers" can be initialized with the
16338 * sip_unknown_init() function/macro. For instance,
16339 * @code
16340 *
16341 * sip_unknown_t sip_unknown;
16342 *
16343 * sip_unknown_init(&sip_unknown);
16344 *
16345 * @endcode
16346 * @HI
16347 *
16348 */
16349#if SU_HAVE_INLINE1
16350su_inlinestatic inline sip_unknown_t *sip_unknown_init(sip_unknown_t x[1])
16351{
16352 return SIP_HEADER_INIT(x, sip_unknown_class, sizeof(sip_unknown_t))((void)memset((x), 0, (sizeof(sip_unknown_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_unknown_class)), (x))
;
16353}
16354#else
16355#define sip_unknown_init(x) \
16356 SIP_HEADER_INIT(x, sip_unknown_class, sizeof(sip_unknown_t))((void)memset((x), 0, (sizeof(sip_unknown_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_unknown_class)), (x))
16357#endif
16358
16359/**Test if header object is instance of #sip_unknown_t.
16360 *
16361 * Check if the header class is an instance of
16362 * @ref sip_unknown "unknown headers" object and return true (nonzero),
16363 * otherwise return false (zero).
16364 *
16365 * @param header pointer to the header structure to be tested
16366 *
16367 * @retval 1 (true) if the @a header is an instance of header unknown
16368 * @retval 0 (false) otherwise
16369 *
16370 */
16371#if SU_HAVE_INLINE1
16372su_inlinestatic inline int sip_is_unknown(sip_header_t const *header)
16373{
16374 return header && header->sh_classsh_common->h_class->hc_hash == sip_unknown_hash;
16375}
16376#else
16377int sip_is_unknown(sip_header_t const *header);
16378#endif
16379
16380#define sip_unknown_p(h)sip_is_unknown((h)) sip_is_unknown((h))
16381
16382
16383/**Duplicate a list of @ref sip_unknown "unknown headers" header structures #sip_unknown_t.
16384 *
16385 * Duplicate a header
16386 * structure @a hdr. If the header structure @a hdr
16387 * contains a reference (@c hdr->x_next) to a list of
16388 * headers, all the headers in the list are duplicated, too.
16389 *
16390 * @param home memory home used to allocate new structure
16391 * @param hdr header structure to be duplicated
16392 *
16393 * When duplicating, all parameter lists and non-constant
16394 * strings attached to the header are copied, too. The
16395 * function uses given memory @a home to allocate all the
16396 * memory areas used to copy the header.
16397 *
16398 * @par Example
16399 * @code
16400 *
16401 * unknown = sip_unknown_dup(home, sip->sip_unknown);
16402 *
16403 * @endcode
16404 *
16405 * @return
16406 * A pointer to the
16407 * newly duplicated #sip_unknown_t header structure, or NULL
16408 * upon an error.
16409 *
16410 */
16411#if SU_HAVE_INLINE1
16412su_inlinestatic inline
16413#endif
16414sip_unknown_t *sip_unknown_dup(su_home_t *home, sip_unknown_t const *hdr)
16415 __attribute__((__malloc__));
16416
16417#if SU_HAVE_INLINE1
16418su_inlinestatic inline
16419sip_unknown_t *sip_unknown_dup(su_home_t *home, sip_unknown_t const *hdr)
16420{
16421 return (sip_unknown_t *)
16422 msg_header_dup_as(home, sip_unknown_class, (msg_header_t const *)hdr);
16423}
16424#endif
16425
16426/**Copy a list of @ref sip_unknown "unknown headers" header structures #sip_unknown_t.
16427 *
16428 * The function sip_unknown_copy() copies a header structure @a
16429 * hdr. If the header structure @a hdr contains a reference (@c
16430 * hdr->h_next) to a list of headers, all the headers in that
16431 * list are copied, too. The function uses given memory @a home
16432 * to allocate all the memory areas used to copy the list of header
16433 * structure @a hdr.
16434 *
16435 * @param home memory home used to allocate new structure
16436 * @param hdr pointer to the header structure to be copied
16437 *
16438 * When copying, only the header structure and parameter lists attached to
16439 * it are duplicated. The new header structure retains all the references to
16440 * the strings within the old @a hdr header, including the encoding of the
16441 * old header, if present.
16442 *
16443 * @par Example
16444 * @code
16445 *
16446 * unknown = sip_unknown_copy(home, sip->sip_unknown);
16447 *
16448 * @endcode
16449 *
16450 * @return
16451 * A pointer to newly copied header structure, or NULL upon an error.
16452 *
16453 */
16454#if SU_HAVE_INLINE1
16455su_inlinestatic inline
16456#endif
16457sip_unknown_t *sip_unknown_copy(su_home_t *home, sip_unknown_t const *hdr)
16458 __attribute__((__malloc__));
16459
16460#if SU_HAVE_INLINE1
16461su_inlinestatic inline
16462sip_unknown_t *sip_unknown_copy(su_home_t *home, sip_unknown_t const *hdr)
16463{
16464 return (sip_unknown_t *)
16465 msg_header_copy_as(home, sip_unknown_class, (msg_header_t const *)hdr);
16466}
16467#endif
16468
16469/**Make a @ref sip_unknown "unknown headers" structure #sip_unknown_t.
16470 *
16471 * The function sip_unknown_make() makes a new
16472 * #sip_unknown_t header structure. It allocates a new
16473 * header structure, and decodes the string @a s as the
16474 * value of the structure.
16475 *
16476 * @param home memory home used to allocate new header structure.
16477 * @param s string to be decoded as value of the new header structure
16478 *
16479 * @return
16480 * A pointer to newly maked #sip_unknown_t header structure, or NULL upon an
16481 * error.
16482 *
16483 */
16484#if SU_HAVE_INLINE1
16485su_inlinestatic inline
16486#endif
16487sip_unknown_t *sip_unknown_make(su_home_t *home, char const *s)
16488 __attribute__((__malloc__));
16489
16490#if SU_HAVE_INLINE1
16491su_inlinestatic inline sip_unknown_t *sip_unknown_make(su_home_t *home, char const *s)
16492{
16493 return (sip_unknown_t *)sip_header_make(home, sip_unknown_class, s)((sip_header_t *)msg_header_make((home), (sip_unknown_class),
(s)))
;
16494}
16495#endif
16496
16497/**Make a @ref sip_unknown "unknown headers" from formatting result.
16498 *
16499 * Make a new #sip_unknown_t object using formatting result as its value.
16500 * The function first prints the arguments according to the format @a fmt
16501 * specified. Then it allocates a new header structure, and parses the
16502 * formatting result to the structure #sip_unknown_t.
16503 *
16504 * @param home memory home used to allocate new header structure.
16505 * @param fmt string used as a printf()-style format
16506 * @param ... argument list for format
16507 *
16508 * @return
16509 * A pointer to newly
16510 * makes header structure, or NULL upon an error.
16511 *
16512 * @HIDE
16513 *
16514 */
16515#if SU_HAVE_INLINE1
16516su_inlinestatic inline
16517#endif
16518sip_unknown_t *sip_unknown_format(su_home_t *home, char const *fmt, ...)
16519 __attribute__((__malloc__, __format__ (printf, 2, 3)));
16520
16521#if SU_HAVE_INLINE1
16522su_inlinestatic inline sip_unknown_t *sip_unknown_format(su_home_t *home, char const *fmt, ...)
16523{
16524 sip_header_t *h;
16525 va_list ap;
16526
16527 va_start(ap, fmt)__builtin_va_start(ap, fmt);
16528 h = sip_header_vformat(home, sip_unknown_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_unknown_class
), (fmt), (ap)))
;
16529 va_end(ap)__builtin_va_end(ap);
16530
16531 return (sip_unknown_t *)h;
16532}
16533#endif
16534
16535/** @} */
16536
16537/**@addtogroup sip_error
16538 * @{
16539 */
16540
16541/** Parse a SIP @ref sip_error "erroneous headers". @internal */
16542SOFIAPUBFUN issize_t sip_error_d(su_home_t *, msg_header_t *,
16543 char *s, isize_t slen);
16544
16545/** Print a SIP @ref sip_error "erroneous headers". @internal */
16546SOFIAPUBFUN issize_t sip_error_e(char b[], isize_t bsiz,
16547 msg_header_t const *h, int flags);
16548
16549/**Access a SIP @ref sip_error "erroneous headers"
16550 * structure #sip_error_t from #sip_t.
16551 *
16552 */
16553#define sip_error(sip)((sip_error_t *)msg_header_access((msg_pub_t*)(sip), sip_error_class
))
\
16554 ((sip_error_t *)msg_header_access((msg_pub_t*)(sip), sip_error_class))
16555
16556/**Initializer for structure #sip_error_t.
16557 *
16558 * A static #sip_error_t structure for
16559 * @ref sip_error "erroneous headers" must be initialized with
16560 * the SIP_ERROR_INIT() macro.
16561 * For instance,
16562 * @code
16563 *
16564 * sip_error_t sip_error = SIP_ERROR_INIT;
16565 *
16566 * @endcode
16567 * @HI
16568 *
16569 */
16570#define SIP_ERROR_INIT(){{{ 0, 0, sip_error_class }}} SIP_HDR_INIT(error){{{ 0, 0, sip_error_class }}}
16571
16572/**Initialize a structure #sip_error_t.
16573 *
16574 * An #sip_error_t structure for
16575 * @ref sip_error "erroneous headers" can be initialized with the
16576 * sip_error_init() function/macro. For instance,
16577 * @code
16578 *
16579 * sip_error_t sip_error;
16580 *
16581 * sip_error_init(&sip_error);
16582 *
16583 * @endcode
16584 * @HI
16585 *
16586 */
16587#if SU_HAVE_INLINE1
16588su_inlinestatic inline sip_error_t *sip_error_init(sip_error_t x[1])
16589{
16590 return SIP_HEADER_INIT(x, sip_error_class, sizeof(sip_error_t))((void)memset((x), 0, (sizeof(sip_error_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_error_class)), (x))
;
16591}
16592#else
16593#define sip_error_init(x) \
16594 SIP_HEADER_INIT(x, sip_error_class, sizeof(sip_error_t))((void)memset((x), 0, (sizeof(sip_error_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_error_class)), (x))
16595#endif
16596
16597/**Test if header object is instance of #sip_error_t.
16598 *
16599 * Check if the header class is an instance of
16600 * @ref sip_error "erroneous headers" object and return true (nonzero),
16601 * otherwise return false (zero).
16602 *
16603 * @param header pointer to the header structure to be tested
16604 *
16605 * @retval 1 (true) if the @a header is an instance of header error
16606 * @retval 0 (false) otherwise
16607 *
16608 */
16609#if SU_HAVE_INLINE1
16610su_inlinestatic inline int sip_is_error(sip_header_t const *header)
16611{
16612 return header && header->sh_classsh_common->h_class->hc_hash == sip_error_hash;
16613}
16614#else
16615int sip_is_error(sip_header_t const *header);
16616#endif
16617
16618#define sip_error_p(h)sip_is_error((h)) sip_is_error((h))
16619
16620
16621/**Duplicate a list of @ref sip_error "erroneous headers" header structures #sip_error_t.
16622 *
16623 * Duplicate a header
16624 * structure @a hdr. If the header structure @a hdr
16625 * contains a reference (@c hdr->x_next) to a list of
16626 * headers, all the headers in the list are duplicated, too.
16627 *
16628 * @param home memory home used to allocate new structure
16629 * @param hdr header structure to be duplicated
16630 *
16631 * When duplicating, all parameter lists and non-constant
16632 * strings attached to the header are copied, too. The
16633 * function uses given memory @a home to allocate all the
16634 * memory areas used to copy the header.
16635 *
16636 * @par Example
16637 * @code
16638 *
16639 * error = sip_error_dup(home, sip->sip_error);
16640 *
16641 * @endcode
16642 *
16643 * @return
16644 * A pointer to the
16645 * newly duplicated #sip_error_t header structure, or NULL
16646 * upon an error.
16647 *
16648 */
16649#if SU_HAVE_INLINE1
16650su_inlinestatic inline
16651#endif
16652sip_error_t *sip_error_dup(su_home_t *home, sip_error_t const *hdr)
16653 __attribute__((__malloc__));
16654
16655#if SU_HAVE_INLINE1
16656su_inlinestatic inline
16657sip_error_t *sip_error_dup(su_home_t *home, sip_error_t const *hdr)
16658{
16659 return (sip_error_t *)
16660 msg_header_dup_as(home, sip_error_class, (msg_header_t const *)hdr);
16661}
16662#endif
16663
16664/**Copy a list of @ref sip_error "erroneous headers" header structures #sip_error_t.
16665 *
16666 * The function sip_error_copy() copies a header structure @a
16667 * hdr. If the header structure @a hdr contains a reference (@c
16668 * hdr->h_next) to a list of headers, all the headers in that
16669 * list are copied, too. The function uses given memory @a home
16670 * to allocate all the memory areas used to copy the list of header
16671 * structure @a hdr.
16672 *
16673 * @param home memory home used to allocate new structure
16674 * @param hdr pointer to the header structure to be copied
16675 *
16676 * When copying, only the header structure and parameter lists attached to
16677 * it are duplicated. The new header structure retains all the references to
16678 * the strings within the old @a hdr header, including the encoding of the
16679 * old header, if present.
16680 *
16681 * @par Example
16682 * @code
16683 *
16684 * error = sip_error_copy(home, sip->sip_error);
16685 *
16686 * @endcode
16687 *
16688 * @return
16689 * A pointer to newly copied header structure, or NULL upon an error.
16690 *
16691 */
16692#if SU_HAVE_INLINE1
16693su_inlinestatic inline
16694#endif
16695sip_error_t *sip_error_copy(su_home_t *home, sip_error_t const *hdr)
16696 __attribute__((__malloc__));
16697
16698#if SU_HAVE_INLINE1
16699su_inlinestatic inline
16700sip_error_t *sip_error_copy(su_home_t *home, sip_error_t const *hdr)
16701{
16702 return (sip_error_t *)
16703 msg_header_copy_as(home, sip_error_class, (msg_header_t const *)hdr);
16704}
16705#endif
16706
16707/**Make a @ref sip_error "erroneous headers" structure #sip_error_t.
16708 *
16709 * The function sip_error_make() makes a new
16710 * #sip_error_t header structure. It allocates a new
16711 * header structure, and decodes the string @a s as the
16712 * value of the structure.
16713 *
16714 * @param home memory home used to allocate new header structure.
16715 * @param s string to be decoded as value of the new header structure
16716 *
16717 * @return
16718 * A pointer to newly maked #sip_error_t header structure, or NULL upon an
16719 * error.
16720 *
16721 */
16722#if SU_HAVE_INLINE1
16723su_inlinestatic inline
16724#endif
16725sip_error_t *sip_error_make(su_home_t *home, char const *s)
16726 __attribute__((__malloc__));
16727
16728#if SU_HAVE_INLINE1
16729su_inlinestatic inline sip_error_t *sip_error_make(su_home_t *home, char const *s)
16730{
16731 return (sip_error_t *)sip_header_make(home, sip_error_class, s)((sip_header_t *)msg_header_make((home), (sip_error_class), (
s)))
;
16732}
16733#endif
16734
16735/**Make a @ref sip_error "erroneous headers" from formatting result.
16736 *
16737 * Make a new #sip_error_t object using formatting result as its value.
16738 * The function first prints the arguments according to the format @a fmt
16739 * specified. Then it allocates a new header structure, and parses the
16740 * formatting result to the structure #sip_error_t.
16741 *
16742 * @param home memory home used to allocate new header structure.
16743 * @param fmt string used as a printf()-style format
16744 * @param ... argument list for format
16745 *
16746 * @return
16747 * A pointer to newly
16748 * makes header structure, or NULL upon an error.
16749 *
16750 * @HIDE
16751 *
16752 */
16753#if SU_HAVE_INLINE1
16754su_inlinestatic inline
16755#endif
16756sip_error_t *sip_error_format(su_home_t *home, char const *fmt, ...)
16757 __attribute__((__malloc__, __format__ (printf, 2, 3)));
16758
16759#if SU_HAVE_INLINE1
16760su_inlinestatic inline sip_error_t *sip_error_format(su_home_t *home, char const *fmt, ...)
16761{
16762 sip_header_t *h;
16763 va_list ap;
16764
16765 va_start(ap, fmt)__builtin_va_start(ap, fmt);
16766 h = sip_header_vformat(home, sip_error_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_error_class)
, (fmt), (ap)))
;
16767 va_end(ap)__builtin_va_end(ap);
16768
16769 return (sip_error_t *)h;
16770}
16771#endif
16772
16773/** @} */
16774
16775/**@addtogroup sip_separator
16776 * @{
16777 */
16778
16779/** Parse a SIP @ref sip_separator "separator line between headers and body". @internal */
16780SOFIAPUBFUN issize_t sip_separator_d(su_home_t *, msg_header_t *,
16781 char *s, isize_t slen);
16782
16783/** Print a SIP @ref sip_separator "separator line between headers and body". @internal */
16784SOFIAPUBFUN issize_t sip_separator_e(char b[], isize_t bsiz,
16785 msg_header_t const *h, int flags);
16786
16787/**Access a SIP @ref sip_separator "separator line between headers and body"
16788 * structure #sip_separator_t from #sip_t.
16789 *
16790 */
16791#define sip_separator(sip)((sip_separator_t *)msg_header_access((msg_pub_t*)(sip), sip_separator_class
))
\
16792 ((sip_separator_t *)msg_header_access((msg_pub_t*)(sip), sip_separator_class))
16793
16794/**Initializer for structure #sip_separator_t.
16795 *
16796 * A static #sip_separator_t structure for
16797 * @ref sip_separator "separator line between headers and body" must be initialized with
16798 * the SIP_SEPARATOR_INIT() macro.
16799 * For instance,
16800 * @code
16801 *
16802 * sip_separator_t sip_separator = SIP_SEPARATOR_INIT;
16803 *
16804 * @endcode
16805 * @HI
16806 *
16807 */
16808#define SIP_SEPARATOR_INIT(){{{ 0, 0, sip_separator_class }}} SIP_HDR_INIT(separator){{{ 0, 0, sip_separator_class }}}
16809
16810/**Initialize a structure #sip_separator_t.
16811 *
16812 * An #sip_separator_t structure for
16813 * @ref sip_separator "separator line between headers and body" can be initialized with the
16814 * sip_separator_init() function/macro. For instance,
16815 * @code
16816 *
16817 * sip_separator_t sip_separator;
16818 *
16819 * sip_separator_init(&sip_separator);
16820 *
16821 * @endcode
16822 * @HI
16823 *
16824 */
16825#if SU_HAVE_INLINE1
16826su_inlinestatic inline sip_separator_t *sip_separator_init(sip_separator_t x[1])
16827{
16828 return SIP_HEADER_INIT(x, sip_separator_class, sizeof(sip_separator_t))((void)memset((x), 0, (sizeof(sip_separator_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_separator_class)), (x))
;
16829}
16830#else
16831#define sip_separator_init(x) \
16832 SIP_HEADER_INIT(x, sip_separator_class, sizeof(sip_separator_t))((void)memset((x), 0, (sizeof(sip_separator_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_separator_class)), (x))
16833#endif
16834
16835/**Test if header object is instance of #sip_separator_t.
16836 *
16837 * Check if the header class is an instance of
16838 * @ref sip_separator "separator line between headers and body" object and return true (nonzero),
16839 * otherwise return false (zero).
16840 *
16841 * @param header pointer to the header structure to be tested
16842 *
16843 * @retval 1 (true) if the @a header is an instance of header separator
16844 * @retval 0 (false) otherwise
16845 *
16846 */
16847#if SU_HAVE_INLINE1
16848su_inlinestatic inline int sip_is_separator(sip_header_t const *header)
16849{
16850 return header && header->sh_classsh_common->h_class->hc_hash == sip_separator_hash;
16851}
16852#else
16853int sip_is_separator(sip_header_t const *header);
16854#endif
16855
16856#define sip_separator_p(h)sip_is_separator((h)) sip_is_separator((h))
16857
16858
16859/**Duplicate a list of @ref sip_separator "separator line between headers and body" header structures #sip_separator_t.
16860 *
16861 * Duplicate a header
16862 * structure @a hdr. If the header structure @a hdr
16863 * contains a reference (@c hdr->x_next) to a list of
16864 * headers, all the headers in the list are duplicated, too.
16865 *
16866 * @param home memory home used to allocate new structure
16867 * @param hdr header structure to be duplicated
16868 *
16869 * When duplicating, all parameter lists and non-constant
16870 * strings attached to the header are copied, too. The
16871 * function uses given memory @a home to allocate all the
16872 * memory areas used to copy the header.
16873 *
16874 * @par Example
16875 * @code
16876 *
16877 * separator = sip_separator_dup(home, sip->sip_separator);
16878 *
16879 * @endcode
16880 *
16881 * @return
16882 * A pointer to the
16883 * newly duplicated #sip_separator_t header structure, or NULL
16884 * upon an error.
16885 *
16886 */
16887#if SU_HAVE_INLINE1
16888su_inlinestatic inline
16889#endif
16890sip_separator_t *sip_separator_dup(su_home_t *home, sip_separator_t const *hdr)
16891 __attribute__((__malloc__));
16892
16893#if SU_HAVE_INLINE1
16894su_inlinestatic inline
16895sip_separator_t *sip_separator_dup(su_home_t *home, sip_separator_t const *hdr)
16896{
16897 return (sip_separator_t *)
16898 msg_header_dup_as(home, sip_separator_class, (msg_header_t const *)hdr);
16899}
16900#endif
16901
16902/**Copy a list of @ref sip_separator "separator line between headers and body" header structures #sip_separator_t.
16903 *
16904 * The function sip_separator_copy() copies a header structure @a
16905 * hdr. If the header structure @a hdr contains a reference (@c
16906 * hdr->h_next) to a list of headers, all the headers in that
16907 * list are copied, too. The function uses given memory @a home
16908 * to allocate all the memory areas used to copy the list of header
16909 * structure @a hdr.
16910 *
16911 * @param home memory home used to allocate new structure
16912 * @param hdr pointer to the header structure to be copied
16913 *
16914 * When copying, only the header structure and parameter lists attached to
16915 * it are duplicated. The new header structure retains all the references to
16916 * the strings within the old @a hdr header, including the encoding of the
16917 * old header, if present.
16918 *
16919 * @par Example
16920 * @code
16921 *
16922 * separator = sip_separator_copy(home, sip->sip_separator);
16923 *
16924 * @endcode
16925 *
16926 * @return
16927 * A pointer to newly copied header structure, or NULL upon an error.
16928 *
16929 */
16930#if SU_HAVE_INLINE1
16931su_inlinestatic inline
16932#endif
16933sip_separator_t *sip_separator_copy(su_home_t *home, sip_separator_t const *hdr)
16934 __attribute__((__malloc__));
16935
16936#if SU_HAVE_INLINE1
16937su_inlinestatic inline
16938sip_separator_t *sip_separator_copy(su_home_t *home, sip_separator_t const *hdr)
16939{
16940 return (sip_separator_t *)
16941 msg_header_copy_as(home, sip_separator_class, (msg_header_t const *)hdr);
16942}
16943#endif
16944
16945/**Make a @ref sip_separator "separator line between headers and body" structure #sip_separator_t.
16946 *
16947 * The function sip_separator_make() makes a new
16948 * #sip_separator_t header structure. It allocates a new
16949 * header structure, and decodes the string @a s as the
16950 * value of the structure.
16951 *
16952 * @param home memory home used to allocate new header structure.
16953 * @param s string to be decoded as value of the new header structure
16954 *
16955 * @return
16956 * A pointer to newly maked #sip_separator_t header structure, or NULL upon an
16957 * error.
16958 *
16959 */
16960#if SU_HAVE_INLINE1
16961su_inlinestatic inline
16962#endif
16963sip_separator_t *sip_separator_make(su_home_t *home, char const *s)
16964 __attribute__((__malloc__));
16965
16966#if SU_HAVE_INLINE1
16967su_inlinestatic inline sip_separator_t *sip_separator_make(su_home_t *home, char const *s)
16968{
16969 return (sip_separator_t *)sip_header_make(home, sip_separator_class, s)((sip_header_t *)msg_header_make((home), (sip_separator_class
), (s)))
;
16970}
16971#endif
16972
16973/**Make a @ref sip_separator "separator line between headers and body" from formatting result.
16974 *
16975 * Make a new #sip_separator_t object using formatting result as its value.
16976 * The function first prints the arguments according to the format @a fmt
16977 * specified. Then it allocates a new header structure, and parses the
16978 * formatting result to the structure #sip_separator_t.
16979 *
16980 * @param home memory home used to allocate new header structure.
16981 * @param fmt string used as a printf()-style format
16982 * @param ... argument list for format
16983 *
16984 * @return
16985 * A pointer to newly
16986 * makes header structure, or NULL upon an error.
16987 *
16988 * @HIDE
16989 *
16990 */
16991#if SU_HAVE_INLINE1
16992su_inlinestatic inline
16993#endif
16994sip_separator_t *sip_separator_format(su_home_t *home, char const *fmt, ...)
16995 __attribute__((__malloc__, __format__ (printf, 2, 3)));
16996
16997#if SU_HAVE_INLINE1
16998su_inlinestatic inline sip_separator_t *sip_separator_format(su_home_t *home, char const *fmt, ...)
16999{
17000 sip_header_t *h;
17001 va_list ap;
17002
17003 va_start(ap, fmt)__builtin_va_start(ap, fmt);
17004 h = sip_header_vformat(home, sip_separator_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_separator_class
), (fmt), (ap)))
;
17005 va_end(ap)__builtin_va_end(ap);
17006
17007 return (sip_separator_t *)h;
17008}
17009#endif
17010
17011/** @} */
17012
17013/**@addtogroup sip_payload
17014 * @{
17015 */
17016
17017/** Parse a SIP @ref sip_payload "message payload". @internal */
17018SOFIAPUBFUN issize_t sip_payload_d(su_home_t *, msg_header_t *,
17019 char *s, isize_t slen);
17020
17021/** Print a SIP @ref sip_payload "message payload". @internal */
17022SOFIAPUBFUN issize_t sip_payload_e(char b[], isize_t bsiz,
17023 msg_header_t const *h, int flags);
17024
17025/**Access a SIP @ref sip_payload "message payload"
17026 * structure #sip_payload_t from #sip_t.
17027 *
17028 */
17029#define sip_payload(sip)((sip_payload_t *)msg_header_access((msg_pub_t*)(sip), sip_payload_class
))
\
17030 ((sip_payload_t *)msg_header_access((msg_pub_t*)(sip), sip_payload_class))
17031
17032/**Initializer for structure #sip_payload_t.
17033 *
17034 * A static #sip_payload_t structure for
17035 * @ref sip_payload "message payload" must be initialized with
17036 * the SIP_PAYLOAD_INIT() macro.
17037 * For instance,
17038 * @code
17039 *
17040 * sip_payload_t sip_payload = SIP_PAYLOAD_INIT;
17041 *
17042 * @endcode
17043 * @HI
17044 *
17045 */
17046#define SIP_PAYLOAD_INIT(){{{ 0, 0, sip_payload_class }}} SIP_HDR_INIT(payload){{{ 0, 0, sip_payload_class }}}
17047
17048/**Initialize a structure #sip_payload_t.
17049 *
17050 * An #sip_payload_t structure for
17051 * @ref sip_payload "message payload" can be initialized with the
17052 * sip_payload_init() function/macro. For instance,
17053 * @code
17054 *
17055 * sip_payload_t sip_payload;
17056 *
17057 * sip_payload_init(&sip_payload);
17058 *
17059 * @endcode
17060 * @HI
17061 *
17062 */
17063#if SU_HAVE_INLINE1
17064su_inlinestatic inline sip_payload_t *sip_payload_init(sip_payload_t x[1])
17065{
17066 return SIP_HEADER_INIT(x, sip_payload_class, sizeof(sip_payload_t))((void)memset((x), 0, (sizeof(sip_payload_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_payload_class)), (x))
;
17067}
17068#else
17069#define sip_payload_init(x) \
17070 SIP_HEADER_INIT(x, sip_payload_class, sizeof(sip_payload_t))((void)memset((x), 0, (sizeof(sip_payload_t))), (void)(((sip_common_t
*)(x))->h_class = (sip_payload_class)), (x))
17071#endif
17072
17073/**Test if header object is instance of #sip_payload_t.
17074 *
17075 * Check if the header class is an instance of
17076 * @ref sip_payload "message payload" object and return true (nonzero),
17077 * otherwise return false (zero).
17078 *
17079 * @param header pointer to the header structure to be tested
17080 *
17081 * @retval 1 (true) if the @a header is an instance of header payload
17082 * @retval 0 (false) otherwise
17083 *
17084 */
17085#if SU_HAVE_INLINE1
17086su_inlinestatic inline int sip_is_payload(sip_header_t const *header)
17087{
17088 return header && header->sh_classsh_common->h_class->hc_hash == sip_payload_hash;
17089}
17090#else
17091int sip_is_payload(sip_header_t const *header);
17092#endif
17093
17094#define sip_payload_p(h)sip_is_payload((h)) sip_is_payload((h))
17095
17096
17097/**Duplicate a list of @ref sip_payload "message payload" header structures #sip_payload_t.
17098 *
17099 * Duplicate a header
17100 * structure @a hdr. If the header structure @a hdr
17101 * contains a reference (@c hdr->x_next) to a list of
17102 * headers, all the headers in the list are duplicated, too.
17103 *
17104 * @param home memory home used to allocate new structure
17105 * @param hdr header structure to be duplicated
17106 *
17107 * When duplicating, all parameter lists and non-constant
17108 * strings attached to the header are copied, too. The
17109 * function uses given memory @a home to allocate all the
17110 * memory areas used to copy the header.
17111 *
17112 * @par Example
17113 * @code
17114 *
17115 * payload = sip_payload_dup(home, sip->sip_payload);
17116 *
17117 * @endcode
17118 *
17119 * @return
17120 * A pointer to the
17121 * newly duplicated #sip_payload_t header structure, or NULL
17122 * upon an error.
17123 *
17124 */
17125#if SU_HAVE_INLINE1
17126su_inlinestatic inline
17127#endif
17128sip_payload_t *sip_payload_dup(su_home_t *home, sip_payload_t const *hdr)
17129 __attribute__((__malloc__));
17130
17131#if SU_HAVE_INLINE1
17132su_inlinestatic inline
17133sip_payload_t *sip_payload_dup(su_home_t *home, sip_payload_t const *hdr)
17134{
17135 return (sip_payload_t *)
17136 msg_header_dup_as(home, sip_payload_class, (msg_header_t const *)hdr);
17137}
17138#endif
17139
17140/**Copy a list of @ref sip_payload "message payload" header structures #sip_payload_t.
17141 *
17142 * The function sip_payload_copy() copies a header structure @a
17143 * hdr. If the header structure @a hdr contains a reference (@c
17144 * hdr->h_next) to a list of headers, all the headers in that
17145 * list are copied, too. The function uses given memory @a home
17146 * to allocate all the memory areas used to copy the list of header
17147 * structure @a hdr.
17148 *
17149 * @param home memory home used to allocate new structure
17150 * @param hdr pointer to the header structure to be copied
17151 *
17152 * When copying, only the header structure and parameter lists attached to
17153 * it are duplicated. The new header structure retains all the references to
17154 * the strings within the old @a hdr header, including the encoding of the
17155 * old header, if present.
17156 *
17157 * @par Example
17158 * @code
17159 *
17160 * payload = sip_payload_copy(home, sip->sip_payload);
17161 *
17162 * @endcode
17163 *
17164 * @return
17165 * A pointer to newly copied header structure, or NULL upon an error.
17166 *
17167 */
17168#if SU_HAVE_INLINE1
17169su_inlinestatic inline
17170#endif
17171sip_payload_t *sip_payload_copy(su_home_t *home, sip_payload_t const *hdr)
17172 __attribute__((__malloc__));
17173
17174#if SU_HAVE_INLINE1
17175su_inlinestatic inline
17176sip_payload_t *sip_payload_copy(su_home_t *home, sip_payload_t const *hdr)
17177{
17178 return (sip_payload_t *)
17179 msg_header_copy_as(home, sip_payload_class, (msg_header_t const *)hdr);
17180}
17181#endif
17182
17183/**Make a @ref sip_payload "message payload" structure #sip_payload_t.
17184 *
17185 * The function sip_payload_make() makes a new
17186 * #sip_payload_t header structure. It allocates a new
17187 * header structure, and decodes the string @a s as the
17188 * value of the structure.
17189 *
17190 * @param home memory home used to allocate new header structure.
17191 * @param s string to be decoded as value of the new header structure
17192 *
17193 * @return
17194 * A pointer to newly maked #sip_payload_t header structure, or NULL upon an
17195 * error.
17196 *
17197 */
17198#if SU_HAVE_INLINE1
17199su_inlinestatic inline
17200#endif
17201sip_payload_t *sip_payload_make(su_home_t *home, char const *s)
17202 __attribute__((__malloc__));
17203
17204#if SU_HAVE_INLINE1
17205su_inlinestatic inline sip_payload_t *sip_payload_make(su_home_t *home, char const *s)
17206{
17207 return (sip_payload_t *)sip_header_make(home, sip_payload_class, s)((sip_header_t *)msg_header_make((home), (sip_payload_class),
(s)))
;
17208}
17209#endif
17210
17211/**Make a @ref sip_payload "message payload" from formatting result.
17212 *
17213 * Make a new #sip_payload_t object using formatting result as its value.
17214 * The function first prints the arguments according to the format @a fmt
17215 * specified. Then it allocates a new header structure, and parses the
17216 * formatting result to the structure #sip_payload_t.
17217 *
17218 * @param home memory home used to allocate new header structure.
17219 * @param fmt string used as a printf()-style format
17220 * @param ... argument list for format
17221 *
17222 * @return
17223 * A pointer to newly
17224 * makes header structure, or NULL upon an error.
17225 *
17226 * @HIDE
17227 *
17228 */
17229#if SU_HAVE_INLINE1
17230su_inlinestatic inline
17231#endif
17232sip_payload_t *sip_payload_format(su_home_t *home, char const *fmt, ...)
17233 __attribute__((__malloc__, __format__ (printf, 2, 3)));
17234
17235#if SU_HAVE_INLINE1
17236su_inlinestatic inline sip_payload_t *sip_payload_format(su_home_t *home, char const *fmt, ...)
17237{
17238 sip_header_t *h;
17239 va_list ap;
17240
17241 va_start(ap, fmt)__builtin_va_start(ap, fmt);
17242 h = sip_header_vformat(home, sip_payload_class, fmt, ap)((sip_header_t *)msg_header_vformat((home), (sip_payload_class
), (fmt), (ap)))
;
17243 va_end(ap)__builtin_va_end(ap);
17244
17245 return (sip_payload_t *)h;
17246}
17247#endif
17248
17249/** @} */
17250
17251SOFIA_END_DECLS
17252#endif /* !defined(SIP_PROTOS_H) */