blob: 0ec56adef97b28843f9b1bd78b1ff7f12963677c [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pjsip/sip_msg.h>
21#include <pjsip/sip_parser.h>
22#include <pjsip/print_util.h>
23#include <pjsip/sip_errno.h>
24#include <pj/ctype.h>
25#include <pj/guid.h>
26#include <pj/string.h>
27#include <pj/pool.h>
28#include <pj/assert.h>
29#include <pjlib-util/string.h>
30
31PJ_DEF_DATA(const pjsip_method) pjsip_invite_method =
32 { PJSIP_INVITE_METHOD, { "INVITE",6 }};
33
34PJ_DEF_DATA(const pjsip_method) pjsip_cancel_method =
35 { PJSIP_CANCEL_METHOD, { "CANCEL",6 }};
36
37PJ_DEF_DATA(const pjsip_method) pjsip_ack_method =
38 { PJSIP_ACK_METHOD, { "ACK",3}};
39
40PJ_DEF_DATA(const pjsip_method) pjsip_bye_method =
41 { PJSIP_BYE_METHOD, { "BYE",3}};
42
43PJ_DEF_DATA(const pjsip_method) pjsip_register_method =
44 { PJSIP_REGISTER_METHOD, { "REGISTER", 8}};
45
46PJ_DEF_DATA(const pjsip_method) pjsip_options_method =
47 { PJSIP_OPTIONS_METHOD, { "OPTIONS",7}};
48
49
50/** INVITE method constant. */
51PJ_DEF(const pjsip_method*) pjsip_get_invite_method(void)
52{
53 return &pjsip_invite_method;
54}
55
56/** CANCEL method constant. */
57PJ_DEF(const pjsip_method*) pjsip_get_cancel_method(void)
58{
59 return &pjsip_cancel_method;
60}
61
62/** ACK method constant. */
63PJ_DEF(const pjsip_method*) pjsip_get_ack_method(void)
64{
65 return &pjsip_ack_method;
66}
67
68/** BYE method constant. */
69PJ_DEF(const pjsip_method*) pjsip_get_bye_method(void)
70{
71 return &pjsip_bye_method;
72}
73
74/** REGISTER method constant.*/
75PJ_DEF(const pjsip_method*) pjsip_get_register_method(void)
76{
77 return &pjsip_register_method;
78}
79
80/** OPTIONS method constant. */
81PJ_DEF(const pjsip_method*) pjsip_get_options_method(void)
82{
83 return &pjsip_options_method;
84}
85
86
87static const pj_str_t *method_names[] =
88{
89 &pjsip_invite_method.name,
90 &pjsip_cancel_method.name,
91 &pjsip_ack_method.name,
92 &pjsip_bye_method.name,
93 &pjsip_register_method.name,
94 &pjsip_options_method.name
95};
96
97const pjsip_hdr_name_info_t pjsip_hdr_names[] =
98{
99 { "Accept", 6, NULL }, // PJSIP_H_ACCEPT,
100 { "Accept-Encoding", 15, NULL }, // PJSIP_H_ACCEPT_ENCODING,
101 { "Accept-Language", 15, NULL }, // PJSIP_H_ACCEPT_LANGUAGE,
102 { "Alert-Info", 10, NULL }, // PJSIP_H_ALERT_INFO,
103 { "Allow", 5, NULL }, // PJSIP_H_ALLOW,
104 { "Authentication-Info",19, NULL }, // PJSIP_H_AUTHENTICATION_INFO,
105 { "Authorization", 13, NULL }, // PJSIP_H_AUTHORIZATION,
106 { "Call-ID", 7, "i" }, // PJSIP_H_CALL_ID,
107 { "Call-Info", 9, NULL }, // PJSIP_H_CALL_INFO,
108 { "Contact", 7, "m" }, // PJSIP_H_CONTACT,
109 { "Content-Disposition",19, NULL }, // PJSIP_H_CONTENT_DISPOSITION,
110 { "Content-Encoding", 16, "e" }, // PJSIP_H_CONTENT_ENCODING,
111 { "Content-Language", 16, NULL }, // PJSIP_H_CONTENT_LANGUAGE,
112 { "Content-Length", 14, "l" }, // PJSIP_H_CONTENT_LENGTH,
113 { "Content-Type", 12, "c" }, // PJSIP_H_CONTENT_TYPE,
114 { "CSeq", 4, NULL }, // PJSIP_H_CSEQ,
115 { "Date", 4, NULL }, // PJSIP_H_DATE,
116 { "Error-Info", 10, NULL }, // PJSIP_H_ERROR_INFO,
117 { "Expires", 7, NULL }, // PJSIP_H_EXPIRES,
118 { "From", 4, "f" }, // PJSIP_H_FROM,
119 { "In-Reply-To", 11, NULL }, // PJSIP_H_IN_REPLY_TO,
120 { "Max-Forwards", 12, NULL }, // PJSIP_H_MAX_FORWARDS,
121 { "MIME-Version", 12, NULL }, // PJSIP_H_MIME_VERSION,
122 { "Min-Expires", 11, NULL }, // PJSIP_H_MIN_EXPIRES,
123 { "Organization", 12, NULL }, // PJSIP_H_ORGANIZATION,
124 { "Priority", 8, NULL }, // PJSIP_H_PRIORITY,
125 { "Proxy-Authenticate", 18, NULL }, // PJSIP_H_PROXY_AUTHENTICATE,
126 { "Proxy-Authorization",19, NULL }, // PJSIP_H_PROXY_AUTHORIZATION,
127 { "Proxy-Require", 13, NULL }, // PJSIP_H_PROXY_REQUIRE,
128 { "Record-Route", 12, NULL }, // PJSIP_H_RECORD_ROUTE,
129 { "Reply-To", 8, NULL }, // PJSIP_H_REPLY_TO,
130 { "Require", 7, NULL }, // PJSIP_H_REQUIRE,
131 { "Retry-After", 11, NULL }, // PJSIP_H_RETRY_AFTER,
132 { "Route", 5, NULL }, // PJSIP_H_ROUTE,
133 { "Server", 6, NULL }, // PJSIP_H_SERVER,
134 { "Subject", 7, "s" }, // PJSIP_H_SUBJECT,
135 { "Supported", 9, "k" }, // PJSIP_H_SUPPORTED,
136 { "Timestamp", 9, NULL }, // PJSIP_H_TIMESTAMP,
137 { "To", 2, "t" }, // PJSIP_H_TO,
138 { "Unsupported", 11, NULL }, // PJSIP_H_UNSUPPORTED,
139 { "User-Agent", 10, NULL }, // PJSIP_H_USER_AGENT,
140 { "Via", 3, "v" }, // PJSIP_H_VIA,
141 { "Warning", 7, NULL }, // PJSIP_H_WARNING,
142 { "WWW-Authenticate", 16, NULL }, // PJSIP_H_WWW_AUTHENTICATE,
143
144 { "_Unknown-Header", 15, NULL }, // PJSIP_H_OTHER,
145};
146
147pj_bool_t pjsip_use_compact_form = PJSIP_ENCODE_SHORT_HNAME;
148
149static pj_str_t status_phrase[710];
150static int print_media_type(char *buf, unsigned len,
151 const pjsip_media_type *media);
152
153static int init_status_phrase()
154{
155 unsigned i;
156 pj_str_t default_reason_phrase = { "Default status message", 22};
157
158 for (i=0; i<PJ_ARRAY_SIZE(status_phrase); ++i)
159 status_phrase[i] = default_reason_phrase;
160
161 pj_strset2( &status_phrase[100], "Trying");
162 pj_strset2( &status_phrase[180], "Ringing");
163 pj_strset2( &status_phrase[181], "Call Is Being Forwarded");
164 pj_strset2( &status_phrase[182], "Queued");
165 pj_strset2( &status_phrase[183], "Session Progress");
166
167 pj_strset2( &status_phrase[200], "OK");
168 pj_strset2( &status_phrase[202], "Accepted");
169
170 pj_strset2( &status_phrase[300], "Multiple Choices");
171 pj_strset2( &status_phrase[301], "Moved Permanently");
172 pj_strset2( &status_phrase[302], "Moved Temporarily");
173 pj_strset2( &status_phrase[305], "Use Proxy");
174 pj_strset2( &status_phrase[380], "Alternative Service");
175
176 pj_strset2( &status_phrase[400], "Bad Request");
177 pj_strset2( &status_phrase[401], "Unauthorized");
178 pj_strset2( &status_phrase[402], "Payment Required");
179 pj_strset2( &status_phrase[403], "Forbidden");
180 pj_strset2( &status_phrase[404], "Not Found");
181 pj_strset2( &status_phrase[405], "Method Not Allowed");
182 pj_strset2( &status_phrase[406], "Not Acceptable");
183 pj_strset2( &status_phrase[407], "Proxy Authentication Required");
184 pj_strset2( &status_phrase[408], "Request Timeout");
185 pj_strset2( &status_phrase[410], "Gone");
186 pj_strset2( &status_phrase[413], "Request Entity Too Large");
187 pj_strset2( &status_phrase[414], "Request URI Too Long");
188 pj_strset2( &status_phrase[415], "Unsupported Media Type");
189 pj_strset2( &status_phrase[416], "Unsupported URI Scheme");
190 pj_strset2( &status_phrase[420], "Bad Extension");
191 pj_strset2( &status_phrase[421], "Extension Required");
192 pj_strset2( &status_phrase[422], "Session Timer Too Small");
193 pj_strset2( &status_phrase[423], "Interval Too Brief");
194 pj_strset2( &status_phrase[480], "Temporarily Unavailable");
195 pj_strset2( &status_phrase[481], "Call/Transaction Does Not Exist");
196 pj_strset2( &status_phrase[482], "Loop Detected");
197 pj_strset2( &status_phrase[483], "Too Many Hops");
198 pj_strset2( &status_phrase[484], "Address Incompleted");
199 pj_strset2( &status_phrase[485], "Ambiguous");
200 pj_strset2( &status_phrase[486], "Busy Here");
201 pj_strset2( &status_phrase[487], "Request Terminated");
202 pj_strset2( &status_phrase[488], "Not Acceptable Here");
203 pj_strset2( &status_phrase[489], "Bad Event");
204 pj_strset2( &status_phrase[490], "Request Updated");
205 pj_strset2( &status_phrase[491], "Request Pending");
206 pj_strset2( &status_phrase[493], "Undecipherable");
207
208 pj_strset2( &status_phrase[500], "Internal Server Error");
209 pj_strset2( &status_phrase[501], "Not Implemented");
210 pj_strset2( &status_phrase[502], "Bad Gateway");
211 pj_strset2( &status_phrase[503], "Service Unavailable");
212 pj_strset2( &status_phrase[504], "Server Timeout");
213 pj_strset2( &status_phrase[505], "Version Not Supported");
214 pj_strset2( &status_phrase[513], "Message Too Large");
215 pj_strset2( &status_phrase[580], "Precondition Failure");
216
217 pj_strset2( &status_phrase[600], "Busy Everywhere");
218 pj_strset2( &status_phrase[603], "Decline");
219 pj_strset2( &status_phrase[604], "Does Not Exist Anywhere");
220 pj_strset2( &status_phrase[606], "Not Acceptable");
221
222 pj_strset2( &status_phrase[701], "No response from destination server");
223 pj_strset2( &status_phrase[702], "Unable to resolve destination server");
224 pj_strset2( &status_phrase[703], "Error sending message to destination server");
225
226 return 1;
227}
228
229///////////////////////////////////////////////////////////////////////////////
230/*
231 * Method.
232 */
233
234PJ_DEF(void) pjsip_method_init( pjsip_method *m,
235 pj_pool_t *pool,
236 const pj_str_t *str)
237{
238 pj_str_t dup;
239 pjsip_method_init_np(m, pj_strdup(pool, &dup, str));
240}
241
242PJ_DEF(void) pjsip_method_set( pjsip_method *m, pjsip_method_e me )
243{
244 pj_assert(me < PJSIP_OTHER_METHOD);
245 m->id = me;
246 m->name = *method_names[me];
247}
248
249PJ_DEF(void) pjsip_method_init_np(pjsip_method *m,
250 pj_str_t *str)
251{
252 unsigned i;
253 for (i=0; i<PJ_ARRAY_SIZE(method_names); ++i) {
254 if (pj_memcmp(str->ptr, method_names[i]->ptr, str->slen)==0 ||
255 pj_stricmp(str, method_names[i])==0)
256 {
257 m->id = (pjsip_method_e)i;
258 m->name = *method_names[i];
259 return;
260 }
261 }
262 m->id = PJSIP_OTHER_METHOD;
263 m->name = *str;
264}
265
266PJ_DEF(void) pjsip_method_copy( pj_pool_t *pool,
267 pjsip_method *method,
268 const pjsip_method *rhs )
269{
270 method->id = rhs->id;
271 if (rhs->id != PJSIP_OTHER_METHOD) {
272 method->name = rhs->name;
273 } else {
274 pj_strdup(pool, &method->name, &rhs->name);
275 }
276}
277
278
279PJ_DEF(int) pjsip_method_cmp( const pjsip_method *m1, const pjsip_method *m2)
280{
281 if (m1->id == m2->id) {
282 if (m1->id != PJSIP_OTHER_METHOD)
283 return 0;
284 /* Method comparison is case sensitive! */
285 return pj_strcmp(&m1->name, &m2->name);
286 }
287
288 return ( m1->id < m2->id ) ? -1 : 1;
289}
290
291///////////////////////////////////////////////////////////////////////////////
292/*
293 * Message.
294 */
295
296PJ_DEF(pjsip_msg*) pjsip_msg_create( pj_pool_t *pool, pjsip_msg_type_e type)
297{
298 pjsip_msg *msg = PJ_POOL_ALLOC_T(pool, pjsip_msg);
299 pj_list_init(&msg->hdr);
300 msg->type = type;
301 msg->body = NULL;
302 return msg;
303}
304
305PJ_DEF(pjsip_msg*) pjsip_msg_clone( pj_pool_t *pool, const pjsip_msg *src)
306{
307 pjsip_msg *dst;
308 const pjsip_hdr *sh;
309
310 dst = pjsip_msg_create(pool, src->type);
311
312 /* Clone request/status line */
313 if (src->type == PJSIP_REQUEST_MSG) {
314 pjsip_method_copy(pool, &dst->line.req.method, &src->line.req.method);
315 dst->line.req.uri = (pjsip_uri*) pjsip_uri_clone(pool,
316 src->line.req.uri);
317 } else {
318 dst->line.status.code = src->line.status.code;
319 pj_strdup(pool, &dst->line.status.reason, &src->line.status.reason);
320 }
321
322 /* Clone headers */
323 sh = src->hdr.next;
324 while (sh != &src->hdr) {
325 pjsip_hdr *dh = (pjsip_hdr*) pjsip_hdr_clone(pool, sh);
326 pjsip_msg_add_hdr(dst, dh);
327 sh = sh->next;
328 }
329
330 /* Clone message body */
331 if (src->body) {
332 dst->body = pjsip_msg_body_clone(pool, src->body);
333 }
334
335 return dst;
336}
337
338PJ_DEF(void*) pjsip_msg_find_hdr( const pjsip_msg *msg,
339 pjsip_hdr_e hdr_type, const void *start)
340{
341 const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=&msg->hdr;
342
343 if (hdr == NULL) {
344 hdr = msg->hdr.next;
345 }
346 for (; hdr!=end; hdr = hdr->next) {
347 if (hdr->type == hdr_type)
348 return (void*)hdr;
349 }
350 return NULL;
351}
352
353PJ_DEF(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
354 const pj_str_t *name,
355 const void *start)
356{
357 const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
358
359 if (hdr == NULL) {
360 hdr = msg->hdr.next;
361 }
362 for (; hdr!=end; hdr = hdr->next) {
363 if (pj_stricmp(&hdr->name, name) == 0)
364 return (void*)hdr;
365 }
366 return NULL;
367}
368
369PJ_DEF(void*) pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
370 const pj_str_t *name,
371 const pj_str_t *sname,
372 const void *start)
373{
374 const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
375
376 if (hdr == NULL) {
377 hdr = msg->hdr.next;
378 }
379 for (; hdr!=end; hdr = hdr->next) {
380 if (pj_stricmp(&hdr->name, name) == 0)
381 return (void*)hdr;
382 if (pj_stricmp(&hdr->name, sname) == 0)
383 return (void*)hdr;
384 }
385 return NULL;
386}
387
388PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg,
389 pjsip_hdr_e hdr_type, void *start)
390{
391 pjsip_hdr *hdr = (pjsip_hdr*) pjsip_msg_find_hdr(msg, hdr_type, start);
392 if (hdr) {
393 pj_list_erase(hdr);
394 }
395 return hdr;
396}
397
398PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg,
399 char *buf, pj_size_t size)
400{
401 char *p=buf, *end=buf+size;
402 pj_ssize_t len;
403 pjsip_hdr *hdr;
404 pj_str_t clen_hdr = { "Content-Length: ", 16};
405
406 if (pjsip_use_compact_form) {
407 clen_hdr.ptr = "l: ";
408 clen_hdr.slen = 3;
409 }
410
411 /* Get a wild guess on how many bytes are typically needed.
412 * We'll check this later in detail, but this serves as a quick check.
413 */
414 if (size < 256)
415 return -1;
416
417 /* Print request line or status line depending on message type */
418 if (msg->type == PJSIP_REQUEST_MSG) {
419 pjsip_uri *uri;
420
421 /* Add method. */
422 len = msg->line.req.method.name.slen;
423 pj_memcpy(p, msg->line.req.method.name.ptr, len);
424 p += len;
425 *p++ = ' ';
426
427 /* Add URI */
428 uri = (pjsip_uri*) pjsip_uri_get_uri(msg->line.req.uri);
429 len = pjsip_uri_print( PJSIP_URI_IN_REQ_URI, uri, p, end-p);
430 if (len < 1)
431 return -1;
432 p += len;
433
434 /* Add ' SIP/2.0' */
435 if (end-p < 16)
436 return -1;
437 pj_memcpy(p, " SIP/2.0\r\n", 10);
438 p += 10;
439
440 } else {
441
442 /* Add 'SIP/2.0 ' */
443 pj_memcpy(p, "SIP/2.0 ", 8);
444 p += 8;
445
446 /* Add status code. */
447 len = pj_utoa(msg->line.status.code, p);
448 p += len;
449 *p++ = ' ';
450
451 /* Add reason text. */
452 len = msg->line.status.reason.slen;
453 pj_memcpy(p, msg->line.status.reason.ptr, len );
454 p += len;
455
456 /* Add newline. */
457 *p++ = '\r';
458 *p++ = '\n';
459 }
460
461 /* Print each of the headers. */
462 for (hdr=msg->hdr.next; hdr!=&msg->hdr; hdr=hdr->next) {
463 len = pjsip_hdr_print_on(hdr, p, end-p);
464 if (len < 0)
465 return -1;
466
467 if (len > 0) {
468 p += len;
469 if (p+3 >= end)
470 return -1;
471
472 *p++ = '\r';
473 *p++ = '\n';
474 }
475 }
476
477 /* Process message body. */
478 if (msg->body) {
479 enum { CLEN_SPACE = 5 };
480 char *clen_pos = NULL;
481
482 /* Automaticly adds Content-Type and Content-Length headers, only
483 * if content_type is set in the message body.
484 */
485 if (msg->body->content_type.type.slen) {
486 pj_str_t ctype_hdr = { "Content-Type: ", 14};
487 const pjsip_media_type *media = &msg->body->content_type;
488
489 if (pjsip_use_compact_form) {
490 ctype_hdr.ptr = "c: ";
491 ctype_hdr.slen = 3;
492 }
493
494 /* Add Content-Type header. */
495 if ( (end-p) < 24 + media->type.slen + media->subtype.slen) {
496 return -1;
497 }
498 pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen);
499 p += ctype_hdr.slen;
500 p += print_media_type(p, (unsigned)(end-p), media);
501 *p++ = '\r';
502 *p++ = '\n';
503
504 /* Add Content-Length header. */
505 if ((end-p) < clen_hdr.slen + 12 + 2) {
506 return -1;
507 }
508 pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);
509 p += clen_hdr.slen;
510
511 /* Print blanks after "Content-Length:", this is where we'll put
512 * the content length value after we know the length of the
513 * body.
514 */
515 pj_memset(p, ' ', CLEN_SPACE);
516 clen_pos = p;
517 p += CLEN_SPACE;
518 *p++ = '\r';
519 *p++ = '\n';
520 }
521
522 /* Add blank newline. */
523 *p++ = '\r';
524 *p++ = '\n';
525
526 /* Print the message body itself. */
527 len = (*msg->body->print_body)(msg->body, p, end-p);
528 if (len < 0) {
529 return -1;
530 }
531 p += len;
532
533 /* Now that we have the length of the body, print this to the
534 * Content-Length header.
535 */
536 if (clen_pos) {
537 char tmp[16];
538 len = pj_utoa((unsigned long)len, tmp);
539 if (len > CLEN_SPACE) len = CLEN_SPACE;
540 pj_memcpy(clen_pos+CLEN_SPACE-len, tmp, len);
541 }
542
543 } else {
544 /* There's no message body.
545 * Add Content-Length with zero value.
546 */
547 if ((end-p) < clen_hdr.slen+8) {
548 return -1;
549 }
550 pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);
551 p += clen_hdr.slen;
552 *p++ = ' ';
553 *p++ = '0';
554 *p++ = '\r';
555 *p++ = '\n';
556 *p++ = '\r';
557 *p++ = '\n';
558 }
559
560 *p = '\0';
561 return p-buf;
562}
563
564///////////////////////////////////////////////////////////////////////////////
565PJ_DEF(void*) pjsip_hdr_clone( pj_pool_t *pool, const void *hdr_ptr )
566{
567 const pjsip_hdr *hdr = (const pjsip_hdr*) hdr_ptr;
568 return (*hdr->vptr->clone)(pool, hdr_ptr);
569}
570
571
572PJ_DEF(void*) pjsip_hdr_shallow_clone( pj_pool_t *pool, const void *hdr_ptr )
573{
574 const pjsip_hdr *hdr = (const pjsip_hdr*) hdr_ptr;
575 return (*hdr->vptr->shallow_clone)(pool, hdr_ptr);
576}
577
578PJ_DEF(int) pjsip_hdr_print_on( void *hdr_ptr, char *buf, pj_size_t len)
579{
580 pjsip_hdr *hdr = (pjsip_hdr*) hdr_ptr;
581 return (*hdr->vptr->print_on)(hdr_ptr, buf, len);
582}
583
584///////////////////////////////////////////////////////////////////////////////
585/*
586 * Status/Reason Phrase
587 */
588
589PJ_DEF(const pj_str_t*) pjsip_get_status_text(int code)
590{
591 static int is_initialized;
592 if (is_initialized == 0) {
593 is_initialized = 1;
594 init_status_phrase();
595 }
596
597 return (code>=100 &&
598 code<(int)(sizeof(status_phrase)/sizeof(status_phrase[0]))) ?
599 &status_phrase[code] : &status_phrase[0];
600}
601
602///////////////////////////////////////////////////////////////////////////////
603/*
604 * Media type
605 */
606/*
607 * Init media type.
608 */
609PJ_DEF(void) pjsip_media_type_init( pjsip_media_type *mt,
610 pj_str_t *type,
611 pj_str_t *subtype)
612{
613 pj_bzero(mt, sizeof(*mt));
614 pj_list_init(&mt->param);
615 if (type)
616 mt->type = *type;
617 if (subtype)
618 mt->subtype = *subtype;
619}
620
621PJ_DEF(void) pjsip_media_type_init2( pjsip_media_type *mt,
622 char *type,
623 char *subtype)
624{
625 pj_str_t s_type, s_subtype;
626
627 if (type) {
628 s_type = pj_str(type);
629 } else {
630 s_type.ptr = NULL;
631 s_type.slen = 0;
632 }
633
634 if (subtype) {
635 s_subtype = pj_str(subtype);
636 } else {
637 s_subtype.ptr = NULL;
638 s_subtype.slen = 0;
639 }
640
641 pjsip_media_type_init(mt, &s_type, &s_subtype);
642}
643
644/*
645 * Compare two media types.
646 */
647PJ_DEF(int) pjsip_media_type_cmp( const pjsip_media_type *mt1,
648 const pjsip_media_type *mt2,
649 pj_bool_t cmp_param)
650{
651 int rc;
652
653 PJ_ASSERT_RETURN(mt1 && mt2, 1);
654
655 rc = pj_stricmp(&mt1->type, &mt2->type);
656 if (rc) return rc;
657
658 rc = pj_stricmp(&mt1->subtype, &mt2->subtype);
659 if (rc) return rc;
660
661 if (cmp_param) {
662 rc = pjsip_param_cmp(&mt1->param, &mt2->param, (cmp_param==1));
663 }
664
665 return rc;
666}
667
668PJ_DEF(void) pjsip_media_type_cp( pj_pool_t *pool,
669 pjsip_media_type *dst,
670 const pjsip_media_type *src)
671{
672 PJ_ASSERT_ON_FAIL(pool && dst && src, return);
673 pj_strdup(pool, &dst->type, &src->type);
674 pj_strdup(pool, &dst->subtype, &src->subtype);
675 pjsip_param_clone(pool, &dst->param, &src->param);
676}
677
678///////////////////////////////////////////////////////////////////////////////
679/*
680 * Generic pjsip_hdr_names/hvalue header.
681 */
682
683static int pjsip_generic_string_hdr_print( pjsip_generic_string_hdr *hdr,
684 char *buf, pj_size_t size);
685static pjsip_generic_string_hdr* pjsip_generic_string_hdr_clone( pj_pool_t *pool,
686 const pjsip_generic_string_hdr *hdr);
687static pjsip_generic_string_hdr* pjsip_generic_string_hdr_shallow_clone( pj_pool_t *pool,
688 const pjsip_generic_string_hdr *hdr );
689
690static pjsip_hdr_vptr generic_hdr_vptr =
691{
692 (pjsip_hdr_clone_fptr) &pjsip_generic_string_hdr_clone,
693 (pjsip_hdr_clone_fptr) &pjsip_generic_string_hdr_shallow_clone,
694 (pjsip_hdr_print_fptr) &pjsip_generic_string_hdr_print,
695};
696
697
698PJ_DEF(void) pjsip_generic_string_hdr_init2(pjsip_generic_string_hdr *hdr,
699 pj_str_t *hname,
700 pj_str_t *hvalue)
701{
702 init_hdr(hdr, PJSIP_H_OTHER, &generic_hdr_vptr);
703 if (hname) {
704 hdr->name = *hname;
705 hdr->sname = *hname;
706 }
707 if (hvalue) {
708 hdr->hvalue = *hvalue;
709 } else {
710 hdr->hvalue.ptr = NULL;
711 hdr->hvalue.slen = 0;
712 }
713}
714
715
716PJ_DEF(pjsip_generic_string_hdr*) pjsip_generic_string_hdr_init(pj_pool_t *pool,
717 void *mem,
718 const pj_str_t *hnames,
719 const pj_str_t *hvalue)
720{
721 pjsip_generic_string_hdr *hdr = (pjsip_generic_string_hdr*) mem;
722 pj_str_t dup_hname, dup_hval;
723
724 if (hnames) {
725 pj_strdup(pool, &dup_hname, hnames);
726 } else {
727 dup_hname.slen = 0;
728 }
729
730 if (hvalue) {
731 pj_strdup(pool, &dup_hval, hvalue);
732 } else {
733 dup_hval.slen = 0;
734 }
735
736 pjsip_generic_string_hdr_init2(hdr, &dup_hname, &dup_hval);
737 return hdr;
738}
739
740PJ_DEF(pjsip_generic_string_hdr*) pjsip_generic_string_hdr_create(pj_pool_t *pool,
741 const pj_str_t *hnames,
742 const pj_str_t *hvalue)
743{
744 void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_string_hdr));
745 return pjsip_generic_string_hdr_init(pool, mem, hnames, hvalue);
746}
747
748static int pjsip_generic_string_hdr_print( pjsip_generic_string_hdr *hdr,
749 char *buf, pj_size_t size)
750{
751 char *p = buf;
752 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
753
754 if ((pj_ssize_t)size < hname->slen + hdr->hvalue.slen + 5)
755 return -1;
756
757 pj_memcpy(p, hname->ptr, hname->slen);
758 p += hname->slen;
759 *p++ = ':';
760 *p++ = ' ';
761 pj_memcpy(p, hdr->hvalue.ptr, hdr->hvalue.slen);
762 p += hdr->hvalue.slen;
763 *p = '\0';
764
765 return (int)(p - buf);
766}
767
768static pjsip_generic_string_hdr* pjsip_generic_string_hdr_clone( pj_pool_t *pool,
769 const pjsip_generic_string_hdr *rhs)
770{
771 pjsip_generic_string_hdr *hdr;
772
773 hdr = pjsip_generic_string_hdr_create(pool, &rhs->name, &rhs->hvalue);
774
775 hdr->type = rhs->type;
776 pj_strdup(pool, &hdr->sname, &rhs->sname);
777 return hdr;
778}
779
780static pjsip_generic_string_hdr* pjsip_generic_string_hdr_shallow_clone( pj_pool_t *pool,
781 const pjsip_generic_string_hdr *rhs )
782{
783 pjsip_generic_string_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_string_hdr);
784 pj_memcpy(hdr, rhs, sizeof(*hdr));
785 return hdr;
786}
787
788///////////////////////////////////////////////////////////////////////////////
789/*
790 * Generic pjsip_hdr_names/integer value header.
791 */
792
793static int pjsip_generic_int_hdr_print( pjsip_generic_int_hdr *hdr,
794 char *buf, pj_size_t size);
795static pjsip_generic_int_hdr* pjsip_generic_int_hdr_clone( pj_pool_t *pool,
796 const pjsip_generic_int_hdr *hdr);
797static pjsip_generic_int_hdr* pjsip_generic_int_hdr_shallow_clone( pj_pool_t *pool,
798 const pjsip_generic_int_hdr *hdr );
799
800static pjsip_hdr_vptr generic_int_hdr_vptr =
801{
802 (pjsip_hdr_clone_fptr) &pjsip_generic_int_hdr_clone,
803 (pjsip_hdr_clone_fptr) &pjsip_generic_int_hdr_shallow_clone,
804 (pjsip_hdr_print_fptr) &pjsip_generic_int_hdr_print,
805};
806
807PJ_DEF(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_init( pj_pool_t *pool,
808 void *mem,
809 const pj_str_t *hnames,
810 int value)
811{
812 pjsip_generic_int_hdr *hdr = (pjsip_generic_int_hdr*) mem;
813
814 init_hdr(hdr, PJSIP_H_OTHER, &generic_int_hdr_vptr);
815 if (hnames) {
816 pj_strdup(pool, &hdr->name, hnames);
817 hdr->sname = hdr->name;
818 }
819 hdr->ivalue = value;
820 return hdr;
821}
822
823PJ_DEF(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_create( pj_pool_t *pool,
824 const pj_str_t *hnames,
825 int value)
826{
827 void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_int_hdr));
828 return pjsip_generic_int_hdr_init(pool, mem, hnames, value);
829}
830
831static int pjsip_generic_int_hdr_print( pjsip_generic_int_hdr *hdr,
832 char *buf, pj_size_t size)
833{
834 char *p = buf;
835 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
836
837 if ((pj_ssize_t)size < hname->slen + 15)
838 return -1;
839
840 pj_memcpy(p, hname->ptr, hname->slen);
841 p += hname->slen;
842 *p++ = ':';
843 *p++ = ' ';
844
845 p += pj_utoa(hdr->ivalue, p);
846
847 return (int)(p - buf);
848}
849
850static pjsip_generic_int_hdr* pjsip_generic_int_hdr_clone( pj_pool_t *pool,
851 const pjsip_generic_int_hdr *rhs)
852{
853 pjsip_generic_int_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_int_hdr);
854 pj_memcpy(hdr, rhs, sizeof(*hdr));
855 return hdr;
856}
857
858static pjsip_generic_int_hdr* pjsip_generic_int_hdr_shallow_clone( pj_pool_t *pool,
859 const pjsip_generic_int_hdr *rhs )
860{
861 pjsip_generic_int_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_int_hdr);
862 pj_memcpy(hdr, rhs, sizeof(*hdr));
863 return hdr;
864}
865
866///////////////////////////////////////////////////////////////////////////////
867/*
868 * Generic array header.
869 */
870static int pjsip_generic_array_hdr_print( pjsip_generic_array_hdr *hdr, char *buf, pj_size_t size);
871static pjsip_generic_array_hdr* pjsip_generic_array_hdr_clone( pj_pool_t *pool,
872 const pjsip_generic_array_hdr *hdr);
873static pjsip_generic_array_hdr* pjsip_generic_array_hdr_shallow_clone( pj_pool_t *pool,
874 const pjsip_generic_array_hdr *hdr);
875
876static pjsip_hdr_vptr generic_array_hdr_vptr =
877{
878 (pjsip_hdr_clone_fptr) &pjsip_generic_array_hdr_clone,
879 (pjsip_hdr_clone_fptr) &pjsip_generic_array_hdr_shallow_clone,
880 (pjsip_hdr_print_fptr) &pjsip_generic_array_hdr_print,
881};
882
883
884PJ_DEF(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_init( pj_pool_t *pool,
885 void *mem,
886 const pj_str_t *hnames)
887{
888 pjsip_generic_array_hdr *hdr = (pjsip_generic_array_hdr*) mem;
889
890 init_hdr(hdr, PJSIP_H_OTHER, &generic_array_hdr_vptr);
891 if (hnames) {
892 pj_strdup(pool, &hdr->name, hnames);
893 hdr->sname = hdr->name;
894 }
895 hdr->count = 0;
896 return hdr;
897}
898
899PJ_DEF(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_create( pj_pool_t *pool,
900 const pj_str_t *hnames)
901{
902 void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_array_hdr));
903 return pjsip_generic_array_hdr_init(pool, mem, hnames);
904
905}
906
907static int pjsip_generic_array_hdr_print( pjsip_generic_array_hdr *hdr,
908 char *buf, pj_size_t size)
909{
910 char *p = buf, *endbuf = buf+size;
911 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
912
913 copy_advance(p, (*hname));
914 *p++ = ':';
915 *p++ = ' ';
916
917 if (hdr->count > 0) {
918 unsigned i;
919 int printed;
920 copy_advance(p, hdr->values[0]);
921 for (i=1; i<hdr->count; ++i) {
922 copy_advance_pair(p, ", ", 2, hdr->values[i]);
923 }
924 }
925
926 return (int)(p - buf);
927}
928
929static pjsip_generic_array_hdr* pjsip_generic_array_hdr_clone( pj_pool_t *pool,
930 const pjsip_generic_array_hdr *rhs)
931{
932 unsigned i;
933 pjsip_generic_array_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_array_hdr);
934
935 pj_memcpy(hdr, rhs, sizeof(*hdr));
936 for (i=0; i<rhs->count; ++i) {
937 pj_strdup(pool, &hdr->values[i], &rhs->values[i]);
938 }
939
940 return hdr;
941}
942
943
944static pjsip_generic_array_hdr* pjsip_generic_array_hdr_shallow_clone( pj_pool_t *pool,
945 const pjsip_generic_array_hdr *rhs)
946{
947 pjsip_generic_array_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_array_hdr);
948 pj_memcpy(hdr, rhs, sizeof(*hdr));
949 return hdr;
950}
951
952///////////////////////////////////////////////////////////////////////////////
953/*
954 * Accept header.
955 */
956PJ_DEF(pjsip_accept_hdr*) pjsip_accept_hdr_init( pj_pool_t *pool,
957 void *mem )
958{
959 pjsip_accept_hdr *hdr = (pjsip_accept_hdr*) mem;
960
961 PJ_UNUSED_ARG(pool);
962
963 init_hdr(hdr, PJSIP_H_ACCEPT, &generic_array_hdr_vptr);
964 hdr->count = 0;
965 return hdr;
966}
967
968PJ_DEF(pjsip_accept_hdr*) pjsip_accept_hdr_create(pj_pool_t *pool)
969{
970 void *mem = pj_pool_alloc(pool, sizeof(pjsip_accept_hdr));
971 return pjsip_accept_hdr_init(pool, mem);
972}
973
974
975///////////////////////////////////////////////////////////////////////////////
976/*
977 * Allow header.
978 */
979
980PJ_DEF(pjsip_allow_hdr*) pjsip_allow_hdr_init( pj_pool_t *pool,
981 void *mem )
982{
983 pjsip_allow_hdr *hdr = (pjsip_allow_hdr*) mem;
984
985 PJ_UNUSED_ARG(pool);
986
987 init_hdr(hdr, PJSIP_H_ALLOW, &generic_array_hdr_vptr);
988 hdr->count = 0;
989 return hdr;
990}
991
992PJ_DEF(pjsip_allow_hdr*) pjsip_allow_hdr_create(pj_pool_t *pool)
993{
994 void *mem = pj_pool_alloc(pool, sizeof(pjsip_allow_hdr));
995 return pjsip_allow_hdr_init(pool, mem);
996}
997
998///////////////////////////////////////////////////////////////////////////////
999/*
1000 * Call-ID header.
1001 */
1002
1003PJ_DEF(pjsip_cid_hdr*) pjsip_cid_hdr_init( pj_pool_t *pool,
1004 void *mem )
1005{
1006 pjsip_cid_hdr *hdr = (pjsip_cid_hdr*) mem;
1007
1008 PJ_UNUSED_ARG(pool);
1009
1010 init_hdr(hdr, PJSIP_H_CALL_ID, &generic_hdr_vptr);
1011 return hdr;
1012
1013}
1014
1015PJ_DEF(pjsip_cid_hdr*) pjsip_cid_hdr_create( pj_pool_t *pool )
1016{
1017 void *mem = pj_pool_alloc(pool, sizeof(pjsip_cid_hdr));
1018 return pjsip_cid_hdr_init(pool, mem);
1019}
1020
1021
1022///////////////////////////////////////////////////////////////////////////////
1023/*
1024 * Content-Length header.
1025 */
1026static int pjsip_clen_hdr_print( pjsip_clen_hdr *hdr, char *buf, pj_size_t size);
1027static pjsip_clen_hdr* pjsip_clen_hdr_clone( pj_pool_t *pool, const pjsip_clen_hdr *hdr);
1028#define pjsip_clen_hdr_shallow_clone pjsip_clen_hdr_clone
1029
1030static pjsip_hdr_vptr clen_hdr_vptr =
1031{
1032 (pjsip_hdr_clone_fptr) &pjsip_clen_hdr_clone,
1033 (pjsip_hdr_clone_fptr) &pjsip_clen_hdr_shallow_clone,
1034 (pjsip_hdr_print_fptr) &pjsip_clen_hdr_print,
1035};
1036
1037PJ_DEF(pjsip_clen_hdr*) pjsip_clen_hdr_init( pj_pool_t *pool,
1038 void *mem )
1039{
1040 pjsip_clen_hdr *hdr = (pjsip_clen_hdr*) mem;
1041
1042 PJ_UNUSED_ARG(pool);
1043
1044 init_hdr(hdr, PJSIP_H_CONTENT_LENGTH, &clen_hdr_vptr);
1045 hdr->len = 0;
1046 return hdr;
1047}
1048
1049PJ_DEF(pjsip_clen_hdr*) pjsip_clen_hdr_create( pj_pool_t *pool )
1050{
1051 void *mem = pj_pool_alloc(pool, sizeof(pjsip_clen_hdr));
1052 return pjsip_clen_hdr_init(pool, mem);
1053}
1054
1055static int pjsip_clen_hdr_print( pjsip_clen_hdr *hdr,
1056 char *buf, pj_size_t size)
1057{
1058 char *p = buf;
1059 int len;
1060 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1061
1062 if ((pj_ssize_t)size < hname->slen + 14)
1063 return -1;
1064
1065 pj_memcpy(p, hname->ptr, hname->slen);
1066 p += hname->slen;
1067 *p++ = ':';
1068 *p++ = ' ';
1069
1070 len = pj_utoa(hdr->len, p);
1071 p += len;
1072 *p = '\0';
1073
1074 return (int)(p-buf);
1075}
1076
1077static pjsip_clen_hdr* pjsip_clen_hdr_clone( pj_pool_t *pool, const pjsip_clen_hdr *rhs)
1078{
1079 pjsip_clen_hdr *hdr = pjsip_clen_hdr_create(pool);
1080 hdr->len = rhs->len;
1081 return hdr;
1082}
1083
1084
1085///////////////////////////////////////////////////////////////////////////////
1086/*
1087 * CSeq header.
1088 */
1089static int pjsip_cseq_hdr_print( pjsip_cseq_hdr *hdr, char *buf, pj_size_t size);
1090static pjsip_cseq_hdr* pjsip_cseq_hdr_clone( pj_pool_t *pool, const pjsip_cseq_hdr *hdr);
1091static pjsip_cseq_hdr* pjsip_cseq_hdr_shallow_clone( pj_pool_t *pool, const pjsip_cseq_hdr *hdr );
1092
1093static pjsip_hdr_vptr cseq_hdr_vptr =
1094{
1095 (pjsip_hdr_clone_fptr) &pjsip_cseq_hdr_clone,
1096 (pjsip_hdr_clone_fptr) &pjsip_cseq_hdr_shallow_clone,
1097 (pjsip_hdr_print_fptr) &pjsip_cseq_hdr_print,
1098};
1099
1100PJ_DEF(pjsip_cseq_hdr*) pjsip_cseq_hdr_init( pj_pool_t *pool,
1101 void *mem )
1102{
1103 pjsip_cseq_hdr *hdr = (pjsip_cseq_hdr*) mem;
1104
1105 PJ_UNUSED_ARG(pool);
1106
1107 init_hdr(hdr, PJSIP_H_CSEQ, &cseq_hdr_vptr);
1108 hdr->cseq = 0;
1109 hdr->method.id = PJSIP_OTHER_METHOD;
1110 hdr->method.name.ptr = NULL;
1111 hdr->method.name.slen = 0;
1112 return hdr;
1113}
1114
1115PJ_DEF(pjsip_cseq_hdr*) pjsip_cseq_hdr_create( pj_pool_t *pool )
1116{
1117 void *mem = pj_pool_alloc(pool, sizeof(pjsip_cseq_hdr));
1118 return pjsip_cseq_hdr_init(pool, mem);
1119}
1120
1121static int pjsip_cseq_hdr_print( pjsip_cseq_hdr *hdr, char *buf, pj_size_t size)
1122{
1123 char *p = buf;
1124 int len;
1125 /* CSeq doesn't have compact form */
1126
1127 if ((pj_ssize_t)size < hdr->name.slen + hdr->method.name.slen + 15)
1128 return -1;
1129
1130 pj_memcpy(p, hdr->name.ptr, hdr->name.slen);
1131 p += hdr->name.slen;
1132 *p++ = ':';
1133 *p++ = ' ';
1134
1135 len = pj_utoa(hdr->cseq, p);
1136 p += len;
1137 *p++ = ' ';
1138
1139 pj_memcpy(p, hdr->method.name.ptr, hdr->method.name.slen);
1140 p += hdr->method.name.slen;
1141
1142 *p = '\0';
1143
1144 return (int)(p-buf);
1145}
1146
1147static pjsip_cseq_hdr* pjsip_cseq_hdr_clone( pj_pool_t *pool,
1148 const pjsip_cseq_hdr *rhs)
1149{
1150 pjsip_cseq_hdr *hdr = pjsip_cseq_hdr_create(pool);
1151 hdr->cseq = rhs->cseq;
1152 pjsip_method_copy(pool, &hdr->method, &rhs->method);
1153 return hdr;
1154}
1155
1156static pjsip_cseq_hdr* pjsip_cseq_hdr_shallow_clone( pj_pool_t *pool,
1157 const pjsip_cseq_hdr *rhs )
1158{
1159 pjsip_cseq_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_cseq_hdr);
1160 pj_memcpy(hdr, rhs, sizeof(*hdr));
1161 return hdr;
1162}
1163
1164
1165///////////////////////////////////////////////////////////////////////////////
1166/*
1167 * Contact header.
1168 */
1169static int pjsip_contact_hdr_print( pjsip_contact_hdr *hdr, char *buf, pj_size_t size);
1170static pjsip_contact_hdr* pjsip_contact_hdr_clone( pj_pool_t *pool, const pjsip_contact_hdr *hdr);
1171static pjsip_contact_hdr* pjsip_contact_hdr_shallow_clone( pj_pool_t *pool, const pjsip_contact_hdr *);
1172
1173static pjsip_hdr_vptr contact_hdr_vptr =
1174{
1175 (pjsip_hdr_clone_fptr) &pjsip_contact_hdr_clone,
1176 (pjsip_hdr_clone_fptr) &pjsip_contact_hdr_shallow_clone,
1177 (pjsip_hdr_print_fptr) &pjsip_contact_hdr_print,
1178};
1179
1180PJ_DEF(pjsip_contact_hdr*) pjsip_contact_hdr_init( pj_pool_t *pool,
1181 void *mem )
1182{
1183 pjsip_contact_hdr *hdr = (pjsip_contact_hdr*) mem;
1184
1185 PJ_UNUSED_ARG(pool);
1186
1187 pj_bzero(mem, sizeof(pjsip_contact_hdr));
1188 init_hdr(hdr, PJSIP_H_CONTACT, &contact_hdr_vptr);
1189 hdr->expires = -1;
1190 pj_list_init(&hdr->other_param);
1191 return hdr;
1192}
1193
1194PJ_DEF(pjsip_contact_hdr*) pjsip_contact_hdr_create( pj_pool_t *pool )
1195{
1196 void *mem = pj_pool_alloc(pool, sizeof(pjsip_contact_hdr));
1197 return pjsip_contact_hdr_init(pool, mem);
1198}
1199
1200static int pjsip_contact_hdr_print( pjsip_contact_hdr *hdr, char *buf,
1201 pj_size_t size)
1202{
1203 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1204 const pjsip_parser_const_t *pc = pjsip_parser_const();
1205
1206 if (hdr->star) {
1207 char *p = buf;
1208 if ((pj_ssize_t)size < hname->slen + 6)
1209 return -1;
1210 pj_memcpy(p, hname->ptr, hname->slen);
1211 p += hname->slen;
1212 *p++ = ':';
1213 *p++ = ' ';
1214 *p++ = '*';
1215 return (int)(p - buf);
1216
1217 } else {
1218 int printed;
1219 char *startbuf = buf;
1220 char *endbuf = buf + size;
1221
1222 copy_advance(buf, (*hname));
1223 *buf++ = ':';
1224 *buf++ = ' ';
1225
1226 printed = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, hdr->uri,
1227 buf, endbuf-buf);
1228 if (printed < 1)
1229 return -1;
1230
1231 buf += printed;
1232
1233 if (hdr->q1000) {
1234 unsigned frac;
1235
1236 if (buf+19 >= endbuf)
1237 return -1;
1238
1239 /*
1240 printed = sprintf(buf, ";q=%u.%03u",
1241 hdr->q1000/1000, hdr->q1000 % 1000);
1242 */
1243 pj_memcpy(buf, ";q=", 3);
1244 printed = pj_utoa(hdr->q1000/1000, buf+3);
1245 buf += printed + 3;
1246 frac = hdr->q1000 % 1000;
1247 if (frac != 0) {
1248 *buf++ = '.';
1249 if ((frac % 100)==0) frac /= 100;
1250 if ((frac % 10)==0) frac /= 10;
1251 printed = pj_utoa(frac, buf);
1252 buf += printed;
1253 }
1254 }
1255
1256 if (hdr->expires >= 0) {
1257 if (buf+23 >= endbuf)
1258 return -1;
1259
1260 pj_memcpy(buf, ";expires=", 9);
1261 printed = pj_utoa(hdr->expires, buf+9);
1262 buf += printed + 9;
1263 }
1264
1265 printed = (int)pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1266 &pc->pjsip_TOKEN_SPEC,
1267 &pc->pjsip_TOKEN_SPEC,
1268 ';');
1269 if (printed < 0)
1270 return printed;
1271 buf += printed;
1272
1273 return (int)(buf-startbuf);
1274 }
1275}
1276
1277static pjsip_contact_hdr* pjsip_contact_hdr_clone(pj_pool_t *pool,
1278 const pjsip_contact_hdr *rhs)
1279{
1280 pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(pool);
1281
1282 hdr->star = rhs->star;
1283 if (hdr->star)
1284 return hdr;
1285
1286 hdr->uri = (pjsip_uri*) pjsip_uri_clone(pool, rhs->uri);
1287 hdr->q1000 = rhs->q1000;
1288 hdr->expires = rhs->expires;
1289 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
1290 return hdr;
1291}
1292
1293static pjsip_contact_hdr*
1294pjsip_contact_hdr_shallow_clone( pj_pool_t *pool,
1295 const pjsip_contact_hdr *rhs)
1296{
1297 pjsip_contact_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_contact_hdr);
1298 pj_memcpy(hdr, rhs, sizeof(*hdr));
1299 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
1300 return hdr;
1301}
1302
1303///////////////////////////////////////////////////////////////////////////////
1304/*
1305 * Content-Type header..
1306 */
1307static int pjsip_ctype_hdr_print( pjsip_ctype_hdr *hdr, char *buf,
1308 pj_size_t size);
1309static pjsip_ctype_hdr* pjsip_ctype_hdr_clone(pj_pool_t *pool,
1310 const pjsip_ctype_hdr *hdr);
1311#define pjsip_ctype_hdr_shallow_clone pjsip_ctype_hdr_clone
1312
1313static pjsip_hdr_vptr ctype_hdr_vptr =
1314{
1315 (pjsip_hdr_clone_fptr) &pjsip_ctype_hdr_clone,
1316 (pjsip_hdr_clone_fptr) &pjsip_ctype_hdr_shallow_clone,
1317 (pjsip_hdr_print_fptr) &pjsip_ctype_hdr_print,
1318};
1319
1320PJ_DEF(pjsip_ctype_hdr*) pjsip_ctype_hdr_init( pj_pool_t *pool,
1321 void *mem )
1322{
1323 pjsip_ctype_hdr *hdr = (pjsip_ctype_hdr*) mem;
1324
1325 PJ_UNUSED_ARG(pool);
1326
1327 pj_bzero(mem, sizeof(pjsip_ctype_hdr));
1328 init_hdr(hdr, PJSIP_H_CONTENT_TYPE, &ctype_hdr_vptr);
1329 pj_list_init(&hdr->media.param);
1330 return hdr;
1331
1332}
1333
1334PJ_DEF(pjsip_ctype_hdr*) pjsip_ctype_hdr_create( pj_pool_t *pool )
1335{
1336 void *mem = pj_pool_alloc(pool, sizeof(pjsip_ctype_hdr));
1337 return pjsip_ctype_hdr_init(pool, mem);
1338}
1339
1340static int print_media_type(char *buf, unsigned len,
1341 const pjsip_media_type *media)
1342{
1343 char *p = buf;
1344 pj_ssize_t printed;
1345 const pjsip_parser_const_t *pc;
1346
1347 pj_memcpy(p, media->type.ptr, media->type.slen);
1348 p += media->type.slen;
1349 *p++ = '/';
1350 pj_memcpy(p, media->subtype.ptr, media->subtype.slen);
1351 p += media->subtype.slen;
1352
1353 pc = pjsip_parser_const();
1354 printed = pjsip_param_print_on(&media->param, p, buf+len-p,
1355 &pc->pjsip_TOKEN_SPEC,
1356 &pc->pjsip_TOKEN_SPEC, ';');
1357 if (printed < 0)
1358 return -1;
1359
1360 p += printed;
1361
1362 return (int)(p-buf);
1363}
1364
1365
1366PJ_DEF(int) pjsip_media_type_print(char *buf, unsigned len,
1367 const pjsip_media_type *media)
1368{
1369 return print_media_type(buf, len, media);
1370}
1371
1372static int pjsip_ctype_hdr_print( pjsip_ctype_hdr *hdr,
1373 char *buf, pj_size_t size)
1374{
1375 char *p = buf;
1376 int len;
1377 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1378
1379 if ((pj_ssize_t)size < hname->slen +
1380 hdr->media.type.slen + hdr->media.subtype.slen + 8)
1381 {
1382 return -1;
1383 }
1384
1385 pj_memcpy(p, hname->ptr, hname->slen);
1386 p += hname->slen;
1387 *p++ = ':';
1388 *p++ = ' ';
1389
1390 len = print_media_type(p, (unsigned)(buf+size-p), &hdr->media);
1391 p += len;
1392
1393 *p = '\0';
1394 return (int)(p-buf);
1395}
1396
1397static pjsip_ctype_hdr* pjsip_ctype_hdr_clone( pj_pool_t *pool,
1398 const pjsip_ctype_hdr *rhs)
1399{
1400 pjsip_ctype_hdr *hdr = pjsip_ctype_hdr_create(pool);
1401 pj_strdup(pool, &hdr->media.type, &rhs->media.type);
1402 pj_strdup(pool, &hdr->media.subtype, &rhs->media.subtype);
1403 pjsip_param_clone(pool, &hdr->media.param, &rhs->media.param);
1404 return hdr;
1405}
1406
1407
1408///////////////////////////////////////////////////////////////////////////////
1409/*
1410 * Expires header.
1411 */
1412PJ_DEF(pjsip_expires_hdr*) pjsip_expires_hdr_init( pj_pool_t *pool,
1413 void *mem,
1414 int value)
1415{
1416 pjsip_expires_hdr *hdr = (pjsip_expires_hdr*) mem;
1417
1418 PJ_UNUSED_ARG(pool);
1419
1420 init_hdr(hdr, PJSIP_H_EXPIRES, &generic_int_hdr_vptr);
1421 hdr->ivalue = value;
1422 return hdr;
1423
1424}
1425
1426PJ_DEF(pjsip_expires_hdr*) pjsip_expires_hdr_create( pj_pool_t *pool,
1427 int value )
1428{
1429 void *mem = pj_pool_alloc(pool, sizeof(pjsip_expires_hdr));
1430 return pjsip_expires_hdr_init(pool, mem, value);
1431}
1432
1433///////////////////////////////////////////////////////////////////////////////
1434/*
1435 * To or From header.
1436 */
1437static int pjsip_fromto_hdr_print( pjsip_fromto_hdr *hdr,
1438 char *buf, pj_size_t size);
1439static pjsip_fromto_hdr* pjsip_fromto_hdr_clone( pj_pool_t *pool,
1440 const pjsip_fromto_hdr *hdr);
1441static pjsip_fromto_hdr* pjsip_fromto_hdr_shallow_clone( pj_pool_t *pool,
1442 const pjsip_fromto_hdr *hdr);
1443
1444
1445static pjsip_hdr_vptr fromto_hdr_vptr =
1446{
1447 (pjsip_hdr_clone_fptr) &pjsip_fromto_hdr_clone,
1448 (pjsip_hdr_clone_fptr) &pjsip_fromto_hdr_shallow_clone,
1449 (pjsip_hdr_print_fptr) &pjsip_fromto_hdr_print,
1450};
1451
1452PJ_DEF(pjsip_from_hdr*) pjsip_from_hdr_init( pj_pool_t *pool,
1453 void *mem )
1454{
1455 pjsip_from_hdr *hdr = (pjsip_from_hdr*) mem;
1456
1457 PJ_UNUSED_ARG(pool);
1458
1459 pj_bzero(mem, sizeof(pjsip_from_hdr));
1460 init_hdr(hdr, PJSIP_H_FROM, &fromto_hdr_vptr);
1461 pj_list_init(&hdr->other_param);
1462 return hdr;
1463}
1464
1465PJ_DEF(pjsip_from_hdr*) pjsip_from_hdr_create( pj_pool_t *pool )
1466{
1467 void *mem = pj_pool_alloc(pool, sizeof(pjsip_from_hdr));
1468 return pjsip_from_hdr_init(pool, mem);
1469}
1470
1471PJ_DEF(pjsip_to_hdr*) pjsip_to_hdr_init( pj_pool_t *pool,
1472 void *mem )
1473{
1474 pjsip_to_hdr *hdr = (pjsip_to_hdr*) mem;
1475
1476 PJ_UNUSED_ARG(pool);
1477
1478 pj_bzero(mem, sizeof(pjsip_to_hdr));
1479 init_hdr(hdr, PJSIP_H_TO, &fromto_hdr_vptr);
1480 pj_list_init(&hdr->other_param);
1481 return hdr;
1482
1483}
1484
1485PJ_DEF(pjsip_to_hdr*) pjsip_to_hdr_create( pj_pool_t *pool )
1486{
1487 void *mem = pj_pool_alloc(pool, sizeof(pjsip_to_hdr));
1488 return pjsip_to_hdr_init(pool, mem);
1489}
1490
1491PJ_DEF(pjsip_from_hdr*) pjsip_fromto_hdr_set_from( pjsip_fromto_hdr *hdr )
1492{
1493 hdr->type = PJSIP_H_FROM;
1494 hdr->name.ptr = pjsip_hdr_names[PJSIP_H_FROM].name;
1495 hdr->name.slen = pjsip_hdr_names[PJSIP_H_FROM].name_len;
1496 hdr->sname.ptr = pjsip_hdr_names[PJSIP_H_FROM].sname;
1497 hdr->sname.slen = 1;
1498 return hdr;
1499}
1500
1501PJ_DEF(pjsip_to_hdr*) pjsip_fromto_hdr_set_to( pjsip_fromto_hdr *hdr )
1502{
1503 hdr->type = PJSIP_H_TO;
1504 hdr->name.ptr = pjsip_hdr_names[PJSIP_H_TO].name;
1505 hdr->name.slen = pjsip_hdr_names[PJSIP_H_TO].name_len;
1506 hdr->sname.ptr = pjsip_hdr_names[PJSIP_H_TO].sname;
1507 hdr->sname.slen = 1;
1508 return hdr;
1509}
1510
1511static int pjsip_fromto_hdr_print( pjsip_fromto_hdr *hdr,
1512 char *buf, pj_size_t size)
1513{
1514 pj_ssize_t printed;
1515 char *startbuf = buf;
1516 char *endbuf = buf + size;
1517 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1518 const pjsip_parser_const_t *pc = pjsip_parser_const();
1519
1520 copy_advance(buf, (*hname));
1521 *buf++ = ':';
1522 *buf++ = ' ';
1523
1524 printed = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, hdr->uri,
1525 buf, endbuf-buf);
1526 if (printed < 1)
1527 return -1;
1528
1529 buf += printed;
1530
1531 copy_advance_pair_escape(buf, ";tag=", 5, hdr->tag,
1532 pc->pjsip_TOKEN_SPEC);
1533
1534 printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1535 &pc->pjsip_TOKEN_SPEC,
1536 &pc->pjsip_TOKEN_SPEC, ';');
1537 if (printed < 0)
1538 return -1;
1539 buf += printed;
1540
1541 return (int)(buf-startbuf);
1542}
1543
1544static pjsip_fromto_hdr* pjsip_fromto_hdr_clone( pj_pool_t *pool,
1545 const pjsip_fromto_hdr *rhs)
1546{
1547 pjsip_fromto_hdr *hdr = pjsip_from_hdr_create(pool);
1548
1549 hdr->type = rhs->type;
1550 hdr->name = rhs->name;
1551 hdr->sname = rhs->sname;
1552 hdr->uri = (pjsip_uri*) pjsip_uri_clone(pool, rhs->uri);
1553 pj_strdup( pool, &hdr->tag, &rhs->tag);
1554 pjsip_param_clone( pool, &hdr->other_param, &rhs->other_param);
1555
1556 return hdr;
1557}
1558
1559static pjsip_fromto_hdr*
1560pjsip_fromto_hdr_shallow_clone( pj_pool_t *pool,
1561 const pjsip_fromto_hdr *rhs)
1562{
1563 pjsip_fromto_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_fromto_hdr);
1564 pj_memcpy(hdr, rhs, sizeof(*hdr));
1565 pjsip_param_shallow_clone( pool, &hdr->other_param, &rhs->other_param);
1566 return hdr;
1567}
1568
1569
1570///////////////////////////////////////////////////////////////////////////////
1571/*
1572 * Max-Forwards header.
1573 */
1574PJ_DEF(pjsip_max_fwd_hdr*) pjsip_max_fwd_hdr_init( pj_pool_t *pool,
1575 void *mem,
1576 int value)
1577{
1578 pjsip_max_fwd_hdr *hdr = (pjsip_max_fwd_hdr*) mem;
1579
1580 PJ_UNUSED_ARG(pool);
1581
1582 init_hdr(hdr, PJSIP_H_MAX_FORWARDS, &generic_int_hdr_vptr);
1583 hdr->ivalue = value;
1584 return hdr;
1585
1586}
1587
1588PJ_DEF(pjsip_max_fwd_hdr*) pjsip_max_fwd_hdr_create(pj_pool_t *pool,
1589 int value)
1590{
1591 void *mem = pj_pool_alloc(pool, sizeof(pjsip_max_fwd_hdr));
1592 return pjsip_max_fwd_hdr_init(pool, mem, value);
1593}
1594
1595
1596///////////////////////////////////////////////////////////////////////////////
1597/*
1598 * Min-Expires header.
1599 */
1600PJ_DEF(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_init( pj_pool_t *pool,
1601 void *mem,
1602 int value )
1603{
1604 pjsip_min_expires_hdr *hdr = (pjsip_min_expires_hdr*) mem;
1605
1606 PJ_UNUSED_ARG(pool);
1607
1608 init_hdr(hdr, PJSIP_H_MIN_EXPIRES, &generic_int_hdr_vptr);
1609 hdr->ivalue = value;
1610 return hdr;
1611}
1612
1613PJ_DEF(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_create(pj_pool_t *pool,
1614 int value )
1615{
1616 void *mem = pj_pool_alloc(pool, sizeof(pjsip_min_expires_hdr));
1617 return pjsip_min_expires_hdr_init(pool, mem, value );
1618}
1619
1620///////////////////////////////////////////////////////////////////////////////
1621/*
1622 * Record-Route and Route header.
1623 */
1624static int pjsip_routing_hdr_print( pjsip_routing_hdr *r, char *buf, pj_size_t size );
1625static pjsip_routing_hdr* pjsip_routing_hdr_clone( pj_pool_t *pool, const pjsip_routing_hdr *r );
1626static pjsip_routing_hdr* pjsip_routing_hdr_shallow_clone( pj_pool_t *pool, const pjsip_routing_hdr *r );
1627
1628static pjsip_hdr_vptr routing_hdr_vptr =
1629{
1630 (pjsip_hdr_clone_fptr) &pjsip_routing_hdr_clone,
1631 (pjsip_hdr_clone_fptr) &pjsip_routing_hdr_shallow_clone,
1632 (pjsip_hdr_print_fptr) &pjsip_routing_hdr_print,
1633};
1634
1635PJ_DEF(pjsip_rr_hdr*) pjsip_rr_hdr_init( pj_pool_t *pool,
1636 void *mem )
1637{
1638 pjsip_rr_hdr *hdr = (pjsip_rr_hdr*) mem;
1639
1640 PJ_UNUSED_ARG(pool);
1641
1642 init_hdr(hdr, PJSIP_H_RECORD_ROUTE, &routing_hdr_vptr);
1643 pjsip_name_addr_init(&hdr->name_addr);
1644 pj_list_init(&hdr->other_param);
1645 return hdr;
1646
1647}
1648
1649PJ_DEF(pjsip_rr_hdr*) pjsip_rr_hdr_create( pj_pool_t *pool )
1650{
1651 void *mem = pj_pool_alloc(pool, sizeof(pjsip_rr_hdr));
1652 return pjsip_rr_hdr_init(pool, mem);
1653}
1654
1655PJ_DEF(pjsip_route_hdr*) pjsip_route_hdr_init( pj_pool_t *pool,
1656 void *mem )
1657{
1658 pjsip_route_hdr *hdr = (pjsip_route_hdr*) mem;
1659
1660 PJ_UNUSED_ARG(pool);
1661
1662 init_hdr(hdr, PJSIP_H_ROUTE, &routing_hdr_vptr);
1663 pjsip_name_addr_init(&hdr->name_addr);
1664 pj_list_init(&hdr->other_param);
1665 return hdr;
1666}
1667
1668PJ_DEF(pjsip_route_hdr*) pjsip_route_hdr_create( pj_pool_t *pool )
1669{
1670 void *mem = pj_pool_alloc(pool, sizeof(pjsip_route_hdr));
1671 return pjsip_route_hdr_init(pool, mem);
1672}
1673
1674PJ_DEF(pjsip_rr_hdr*) pjsip_routing_hdr_set_rr( pjsip_routing_hdr *hdr )
1675{
1676 hdr->type = PJSIP_H_RECORD_ROUTE;
1677 hdr->name.ptr = pjsip_hdr_names[PJSIP_H_RECORD_ROUTE].name;
1678 hdr->name.slen = pjsip_hdr_names[PJSIP_H_RECORD_ROUTE].name_len;
1679 hdr->sname = hdr->name;
1680 return hdr;
1681}
1682
1683PJ_DEF(pjsip_route_hdr*) pjsip_routing_hdr_set_route( pjsip_routing_hdr *hdr )
1684{
1685 hdr->type = PJSIP_H_ROUTE;
1686 hdr->name.ptr = pjsip_hdr_names[PJSIP_H_ROUTE].name;
1687 hdr->name.slen = pjsip_hdr_names[PJSIP_H_ROUTE].name_len;
1688 hdr->sname = hdr->name;
1689 return hdr;
1690}
1691
1692static int pjsip_routing_hdr_print( pjsip_routing_hdr *hdr,
1693 char *buf, pj_size_t size )
1694{
1695 pj_ssize_t printed;
1696 char *startbuf = buf;
1697 char *endbuf = buf + size;
1698 const pjsip_parser_const_t *pc = pjsip_parser_const();
1699 pjsip_sip_uri *sip_uri;
1700 pjsip_param *p;
1701
1702 /* Check the proprietary param 'hide', don't print this header
1703 * if it exists in the route URI.
1704 */
1705 sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri(hdr->name_addr.uri);
1706 p = sip_uri->other_param.next;
1707 while (p != &sip_uri->other_param) {
1708 const pj_str_t st_hide = {"hide", 4};
1709
1710 if (pj_stricmp(&p->name, &st_hide) == 0) {
1711 /* Check if param 'hide' is specified without 'lr'. */
1712 pj_assert(sip_uri->lr_param != 0);
1713 return 0;
1714 }
1715 p = p->next;
1716 }
1717
1718 /* Route and Record-Route don't compact forms */
1719
1720 copy_advance(buf, hdr->name);
1721 *buf++ = ':';
1722 *buf++ = ' ';
1723
1724 printed = pjsip_uri_print(PJSIP_URI_IN_ROUTING_HDR, &hdr->name_addr, buf,
1725 endbuf-buf);
1726 if (printed < 1)
1727 return -1;
1728 buf += printed;
1729
1730 printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1731 &pc->pjsip_TOKEN_SPEC,
1732 &pc->pjsip_TOKEN_SPEC, ';');
1733 if (printed < 0)
1734 return -1;
1735 buf += printed;
1736
1737 return (int)(buf-startbuf);
1738}
1739
1740static pjsip_routing_hdr* pjsip_routing_hdr_clone( pj_pool_t *pool,
1741 const pjsip_routing_hdr *rhs )
1742{
1743 pjsip_routing_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_routing_hdr);
1744
1745 init_hdr(hdr, rhs->type, rhs->vptr);
1746 pjsip_name_addr_init(&hdr->name_addr);
1747 pjsip_name_addr_assign(pool, &hdr->name_addr, &rhs->name_addr);
1748 pjsip_param_clone( pool, &hdr->other_param, &rhs->other_param);
1749 return hdr;
1750}
1751
1752static pjsip_routing_hdr* pjsip_routing_hdr_shallow_clone( pj_pool_t *pool,
1753 const pjsip_routing_hdr *rhs )
1754{
1755 pjsip_routing_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_routing_hdr);
1756 pj_memcpy(hdr, rhs, sizeof(*hdr));
1757 pjsip_param_shallow_clone( pool, &hdr->other_param, &rhs->other_param);
1758 return hdr;
1759}
1760
1761
1762///////////////////////////////////////////////////////////////////////////////
1763/*
1764 * Require header.
1765 */
1766PJ_DEF(pjsip_require_hdr*) pjsip_require_hdr_init( pj_pool_t *pool,
1767 void *mem )
1768{
1769 pjsip_require_hdr *hdr = (pjsip_require_hdr*) mem;
1770
1771 PJ_UNUSED_ARG(pool);
1772
1773 init_hdr(hdr, PJSIP_H_REQUIRE, &generic_array_hdr_vptr);
1774 hdr->count = 0;
1775 return hdr;
1776}
1777
1778PJ_DEF(pjsip_require_hdr*) pjsip_require_hdr_create(pj_pool_t *pool)
1779{
1780 void *mem = pj_pool_alloc(pool, sizeof(pjsip_require_hdr));
1781 return pjsip_require_hdr_init(pool, mem);
1782}
1783
1784///////////////////////////////////////////////////////////////////////////////
1785/*
1786 * Retry-After header.
1787 */
1788static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *r,
1789 char *buf, pj_size_t size );
1790static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool,
1791 const pjsip_retry_after_hdr *r);
1792static pjsip_retry_after_hdr*
1793pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool,
1794 const pjsip_retry_after_hdr *r );
1795
1796static pjsip_hdr_vptr retry_after_hdr_vptr =
1797{
1798 (pjsip_hdr_clone_fptr) &pjsip_retry_after_hdr_clone,
1799 (pjsip_hdr_clone_fptr) &pjsip_retry_after_hdr_shallow_clone,
1800 (pjsip_hdr_print_fptr) &pjsip_retry_after_hdr_print,
1801};
1802
1803
1804PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_init( pj_pool_t *pool,
1805 void *mem,
1806 int value )
1807{
1808 pjsip_retry_after_hdr *hdr = (pjsip_retry_after_hdr*) mem;
1809
1810 PJ_UNUSED_ARG(pool);
1811
1812 init_hdr(hdr, PJSIP_H_RETRY_AFTER, &retry_after_hdr_vptr);
1813 hdr->ivalue = value;
1814 hdr->comment.slen = 0;
1815 pj_list_init(&hdr->param);
1816 return hdr;
1817}
1818
1819PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_create(pj_pool_t *pool,
1820 int value )
1821{
1822 void *mem = pj_pool_alloc(pool, sizeof(pjsip_retry_after_hdr));
1823 return pjsip_retry_after_hdr_init(pool, mem, value );
1824}
1825
1826
1827static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *hdr,
1828 char *buf, pj_size_t size)
1829{
1830 char *p = buf;
1831 char *endbuf = buf + size;
1832 const pj_str_t *hname = &hdr->name;
1833 const pjsip_parser_const_t *pc = pjsip_parser_const();
1834 pj_ssize_t printed;
1835
1836 if ((pj_ssize_t)size < hdr->name.slen + 2+11)
1837 return -1;
1838
1839 pj_memcpy(p, hdr->name.ptr, hdr->name.slen);
1840 p += hname->slen;
1841 *p++ = ':';
1842 *p++ = ' ';
1843
1844 p += pj_utoa(hdr->ivalue, p);
1845
1846 if (hdr->comment.slen) {
1847 pj_bool_t enclosed;
1848
1849 if (endbuf-p < hdr->comment.slen + 3)
1850 return -1;
1851
1852 enclosed = (*hdr->comment.ptr == '(');
1853 if (!enclosed)
1854 *p++ = '(';
1855 pj_memcpy(p, hdr->comment.ptr, hdr->comment.slen);
1856 p += hdr->comment.slen;
1857 if (!enclosed)
1858 *p++ = ')';
1859
1860 if (!pj_list_empty(&hdr->param))
1861 *p++ = ' ';
1862 }
1863
1864 printed = pjsip_param_print_on(&hdr->param, p, endbuf-p,
1865 &pc->pjsip_TOKEN_SPEC,
1866 &pc->pjsip_TOKEN_SPEC,
1867 ';');
1868 if (printed < 0)
1869 return (int)printed;
1870
1871 p += printed;
1872
1873 return (int)(p - buf);
1874}
1875
1876static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool,
1877 const pjsip_retry_after_hdr *rhs)
1878{
1879 pjsip_retry_after_hdr *hdr = pjsip_retry_after_hdr_create(pool, rhs->ivalue);
1880 pj_strdup(pool, &hdr->comment, &rhs->comment);
1881 pjsip_param_clone(pool, &hdr->param, &rhs->param);
1882 return hdr;
1883}
1884
1885static pjsip_retry_after_hdr*
1886pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool,
1887 const pjsip_retry_after_hdr *rhs)
1888{
1889 pjsip_retry_after_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_retry_after_hdr);
1890 pj_memcpy(hdr, rhs, sizeof(*hdr));
1891 pjsip_param_shallow_clone(pool, &hdr->param, &rhs->param);
1892 return hdr;
1893}
1894
1895///////////////////////////////////////////////////////////////////////////////
1896/*
1897 * Supported header.
1898 */
1899PJ_DEF(pjsip_supported_hdr*) pjsip_supported_hdr_init( pj_pool_t *pool,
1900 void *mem )
1901{
1902 pjsip_supported_hdr *hdr = (pjsip_supported_hdr*) mem;
1903
1904 PJ_UNUSED_ARG(pool);
1905 init_hdr(hdr, PJSIP_H_SUPPORTED, &generic_array_hdr_vptr);
1906 hdr->count = 0;
1907 return hdr;
1908}
1909
1910PJ_DEF(pjsip_supported_hdr*) pjsip_supported_hdr_create(pj_pool_t *pool)
1911{
1912 void *mem = pj_pool_alloc(pool, sizeof(pjsip_supported_hdr));
1913 return pjsip_supported_hdr_init(pool, mem);
1914}
1915
1916
1917///////////////////////////////////////////////////////////////////////////////
1918/*
1919 * Unsupported header.
1920 */
1921PJ_DEF(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_init( pj_pool_t *pool,
1922 void *mem )
1923{
1924 pjsip_unsupported_hdr *hdr = (pjsip_unsupported_hdr*) mem;
1925
1926 PJ_UNUSED_ARG(pool);
1927
1928 init_hdr(hdr, PJSIP_H_UNSUPPORTED, &generic_array_hdr_vptr);
1929 hdr->count = 0;
1930 return hdr;
1931}
1932
1933PJ_DEF(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_create(pj_pool_t *pool)
1934{
1935 void *mem = pj_pool_alloc(pool, sizeof(pjsip_unsupported_hdr));
1936 return pjsip_unsupported_hdr_init(pool, mem);
1937}
1938
1939///////////////////////////////////////////////////////////////////////////////
1940/*
1941 * Via header.
1942 */
1943static int pjsip_via_hdr_print( pjsip_via_hdr *hdr, char *buf, pj_size_t size);
1944static pjsip_via_hdr* pjsip_via_hdr_clone( pj_pool_t *pool, const pjsip_via_hdr *hdr);
1945static pjsip_via_hdr* pjsip_via_hdr_shallow_clone( pj_pool_t *pool, const pjsip_via_hdr *hdr );
1946
1947static pjsip_hdr_vptr via_hdr_vptr =
1948{
1949 (pjsip_hdr_clone_fptr) &pjsip_via_hdr_clone,
1950 (pjsip_hdr_clone_fptr) &pjsip_via_hdr_shallow_clone,
1951 (pjsip_hdr_print_fptr) &pjsip_via_hdr_print,
1952};
1953
1954PJ_DEF(pjsip_via_hdr*) pjsip_via_hdr_init( pj_pool_t *pool,
1955 void *mem )
1956{
1957 pjsip_via_hdr *hdr = (pjsip_via_hdr*) mem;
1958
1959 PJ_UNUSED_ARG(pool);
1960
1961 pj_bzero(mem, sizeof(pjsip_via_hdr));
1962 init_hdr(hdr, PJSIP_H_VIA, &via_hdr_vptr);
1963 hdr->ttl_param = -1;
1964 hdr->rport_param = -1;
1965 pj_list_init(&hdr->other_param);
1966 return hdr;
1967
1968}
1969
1970PJ_DEF(pjsip_via_hdr*) pjsip_via_hdr_create( pj_pool_t *pool )
1971{
1972 void *mem = pj_pool_alloc(pool, sizeof(pjsip_via_hdr));
1973 return pjsip_via_hdr_init(pool, mem);
1974}
1975
1976static int pjsip_via_hdr_print( pjsip_via_hdr *hdr,
1977 char *buf, pj_size_t size)
1978{
1979 pj_ssize_t printed;
1980 char *startbuf = buf;
1981 char *endbuf = buf + size;
1982 pj_str_t sip_ver = { "SIP/2.0/", 8 };
1983 const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1984 const pjsip_parser_const_t *pc = pjsip_parser_const();
1985
1986 if ((pj_ssize_t)size < hname->slen + sip_ver.slen +
1987 hdr->transport.slen + hdr->sent_by.host.slen + 12)
1988 {
1989 return -1;
1990 }
1991
1992 /* pjsip_hdr_names */
1993 copy_advance(buf, (*hname));
1994 *buf++ = ':';
1995 *buf++ = ' ';
1996
1997 /* SIP/2.0/transport host:port */
1998 pj_memcpy(buf, sip_ver.ptr, sip_ver.slen);
1999 buf += sip_ver.slen;
2000 //pj_memcpy(buf, hdr->transport.ptr, hdr->transport.slen);
2001 /* Convert transport type to UPPERCASE (some endpoints want that) */
2002 {
2003 int i;
2004 for (i=0; i<hdr->transport.slen; ++i) {
2005 buf[i] = (char)pj_toupper(hdr->transport.ptr[i]);
2006 }
2007 }
2008 buf += hdr->transport.slen;
2009 *buf++ = ' ';
2010
2011 /* Check if host contains IPv6 */
2012 if (pj_memchr(hdr->sent_by.host.ptr, ':', hdr->sent_by.host.slen)) {
2013 copy_advance_pair_quote_cond(buf, "", 0, hdr->sent_by.host, '[', ']');
2014 } else {
2015 copy_advance_check(buf, hdr->sent_by.host);
2016 }
2017
2018 if (hdr->sent_by.port != 0) {
2019 *buf++ = ':';
2020 printed = pj_utoa(hdr->sent_by.port, buf);
2021 buf += printed;
2022 }
2023
2024 if (hdr->ttl_param >= 0) {
2025 size = endbuf-buf;
2026 if (size < 14)
2027 return -1;
2028 pj_memcpy(buf, ";ttl=", 5);
2029 printed = pj_utoa(hdr->ttl_param, buf+5);
2030 buf += printed + 5;
2031 }
2032
2033 if (hdr->rport_param >= 0) {
2034 size = endbuf-buf;
2035 if (size < 14)
2036 return -1;
2037 pj_memcpy(buf, ";rport", 6);
2038 buf += 6;
2039 if (hdr->rport_param > 0) {
2040 *buf++ = '=';
2041 buf += pj_utoa(hdr->rport_param, buf);
2042 }
2043 }
2044
2045
2046 if (hdr->maddr_param.slen) {
2047 /* Detect IPv6 IP address */
2048 if (pj_memchr(hdr->maddr_param.ptr, ':', hdr->maddr_param.slen)) {
2049 copy_advance_pair_quote_cond(buf, ";maddr=", 7, hdr->maddr_param,
2050 '[', ']');
2051 } else {
2052 copy_advance_pair(buf, ";maddr=", 7, hdr->maddr_param);
2053 }
2054 }
2055
2056 copy_advance_pair(buf, ";received=", 10, hdr->recvd_param);
2057 copy_advance_pair_escape(buf, ";branch=", 8, hdr->branch_param,
2058 pc->pjsip_TOKEN_SPEC);
2059
2060 printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
2061 &pc->pjsip_TOKEN_SPEC,
2062 &pc->pjsip_TOKEN_SPEC, ';');
2063 if (printed < 0)
2064 return -1;
2065 buf += printed;
2066
2067 return (int)(buf-startbuf);
2068}
2069
2070static pjsip_via_hdr* pjsip_via_hdr_clone( pj_pool_t *pool,
2071 const pjsip_via_hdr *rhs)
2072{
2073 pjsip_via_hdr *hdr = pjsip_via_hdr_create(pool);
2074 pj_strdup(pool, &hdr->transport, &rhs->transport);
2075 pj_strdup(pool, &hdr->sent_by.host, &rhs->sent_by.host);
2076 hdr->sent_by.port = rhs->sent_by.port;
2077 hdr->ttl_param = rhs->ttl_param;
2078 hdr->rport_param = rhs->rport_param;
2079 pj_strdup(pool, &hdr->maddr_param, &rhs->maddr_param);
2080 pj_strdup(pool, &hdr->recvd_param, &rhs->recvd_param);
2081 pj_strdup(pool, &hdr->branch_param, &rhs->branch_param);
2082 pjsip_param_clone(pool, &hdr->other_param, &rhs->other_param);
2083 return hdr;
2084}
2085
2086static pjsip_via_hdr* pjsip_via_hdr_shallow_clone( pj_pool_t *pool,
2087 const pjsip_via_hdr *rhs )
2088{
2089 pjsip_via_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_via_hdr);
2090 pj_memcpy(hdr, rhs, sizeof(*hdr));
2091 pjsip_param_shallow_clone(pool, &hdr->other_param, &rhs->other_param);
2092 return hdr;
2093}
2094
2095///////////////////////////////////////////////////////////////////////////////
2096/*
2097 * Warning header.
2098 */
2099PJ_DEF(pjsip_warning_hdr*) pjsip_warning_hdr_create( pj_pool_t *pool,
2100 int code,
2101 const pj_str_t *host,
2102 const pj_str_t *text)
2103{
2104 const pj_str_t str_warning = { "Warning", 7 };
2105 pj_str_t hvalue;
2106
2107 hvalue.ptr = (char*) pj_pool_alloc(pool, 10 + /* code */
2108 host->slen + 2 + /* host */
2109 text->slen + 2); /* text */
2110 hvalue.slen = pj_ansi_sprintf(hvalue.ptr, "%u %.*s \"%.*s\"",
2111 code, (int)host->slen, host->ptr,
2112 (int)text->slen, text->ptr);
2113
2114 return pjsip_generic_string_hdr_create(pool, &str_warning, &hvalue);
2115}
2116
2117PJ_DEF(pjsip_warning_hdr*) pjsip_warning_hdr_create_from_status(pj_pool_t *pool,
2118 const pj_str_t *host,
2119 pj_status_t status)
2120{
2121 char errbuf[PJ_ERR_MSG_SIZE];
2122 pj_str_t text;
2123
2124 text = pj_strerror(status, errbuf, sizeof(errbuf));
2125 return pjsip_warning_hdr_create(pool, 399, host, &text);
2126}
2127
2128///////////////////////////////////////////////////////////////////////////////
2129/*
2130 * Message body manipulations.
2131 */
2132PJ_DEF(int) pjsip_print_text_body(pjsip_msg_body *msg_body, char *buf, pj_size_t size)
2133{
2134 if (size < msg_body->len)
2135 return -1;
2136 pj_memcpy(buf, msg_body->data, msg_body->len);
2137 return msg_body->len;
2138}
2139
2140PJ_DEF(void*) pjsip_clone_text_data( pj_pool_t *pool, const void *data,
2141 unsigned len)
2142{
2143 char *newdata = "";
2144
2145 if (len) {
2146 newdata = (char*) pj_pool_alloc(pool, len);
2147 pj_memcpy(newdata, data, len);
2148 }
2149 return newdata;
2150}
2151
2152PJ_DEF(pj_status_t) pjsip_msg_body_copy( pj_pool_t *pool,
2153 pjsip_msg_body *dst_body,
2154 const pjsip_msg_body *src_body )
2155{
2156 /* First check if clone_data field is initialized. */
2157 PJ_ASSERT_RETURN( src_body->clone_data!=NULL, PJ_EINVAL );
2158
2159 /* Duplicate content-type */
2160 pjsip_media_type_cp(pool, &dst_body->content_type,
2161 &src_body->content_type);
2162
2163 /* Duplicate data. */
2164 dst_body->data = (*src_body->clone_data)(pool, src_body->data,
2165 src_body->len );
2166
2167 /* Length. */
2168 dst_body->len = src_body->len;
2169
2170 /* Function pointers. */
2171 dst_body->print_body = src_body->print_body;
2172 dst_body->clone_data = src_body->clone_data;
2173
2174 return PJ_SUCCESS;
2175}
2176
2177
2178PJ_DEF(pjsip_msg_body*) pjsip_msg_body_clone( pj_pool_t *pool,
2179 const pjsip_msg_body *body )
2180{
2181 pjsip_msg_body *new_body;
2182 pj_status_t status;
2183
2184 new_body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body);
2185 PJ_ASSERT_RETURN(new_body, NULL);
2186
2187 status = pjsip_msg_body_copy(pool, new_body, body);
2188
2189 return (status==PJ_SUCCESS) ? new_body : NULL;
2190}
2191
2192
2193PJ_DEF(pjsip_msg_body*) pjsip_msg_body_create( pj_pool_t *pool,
2194 const pj_str_t *type,
2195 const pj_str_t *subtype,
2196 const pj_str_t *text )
2197{
2198 pjsip_msg_body *body;
2199
2200 PJ_ASSERT_RETURN(pool && type && subtype && text, NULL);
2201
2202 body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
2203 PJ_ASSERT_RETURN(body != NULL, NULL);
2204
2205 pj_strdup(pool, &body->content_type.type, type);
2206 pj_strdup(pool, &body->content_type.subtype, subtype);
2207 pj_list_init(&body->content_type.param);
2208
2209 body->data = pj_pool_alloc(pool, text->slen);
2210 pj_memcpy(body->data, text->ptr, text->slen);
2211 body->len = (unsigned)text->slen;
2212
2213 body->clone_data = &pjsip_clone_text_data;
2214 body->print_body = &pjsip_print_text_body;
2215
2216 return body;
2217}
2218