1
/* $Id: sip_msg.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
20
#include <pjsip/sip_msg.h>
21
#include <pjsip/sip_parser.h>
22
#include <pjsip/print_util.h>
23
#include <pjsip/sip_errno.h>
26
#include <pj/string.h>
28
#include <pj/assert.h>
29
#include <pjlib-util/string.h>
31
PJ_DEF_DATA(const pjsip_method) pjsip_invite_method =
32
{ PJSIP_INVITE_METHOD, { "INVITE",6 }};
34
PJ_DEF_DATA(const pjsip_method) pjsip_cancel_method =
35
{ PJSIP_CANCEL_METHOD, { "CANCEL",6 }};
37
PJ_DEF_DATA(const pjsip_method) pjsip_ack_method =
38
{ PJSIP_ACK_METHOD, { "ACK",3}};
40
PJ_DEF_DATA(const pjsip_method) pjsip_bye_method =
41
{ PJSIP_BYE_METHOD, { "BYE",3}};
43
PJ_DEF_DATA(const pjsip_method) pjsip_register_method =
44
{ PJSIP_REGISTER_METHOD, { "REGISTER", 8}};
46
PJ_DEF_DATA(const pjsip_method) pjsip_options_method =
47
{ PJSIP_OPTIONS_METHOD, { "OPTIONS",7}};
50
/** INVITE method constant. */
51
PJ_DEF(const pjsip_method*) pjsip_get_invite_method(void)
53
return &pjsip_invite_method;
56
/** CANCEL method constant. */
57
PJ_DEF(const pjsip_method*) pjsip_get_cancel_method(void)
59
return &pjsip_cancel_method;
62
/** ACK method constant. */
63
PJ_DEF(const pjsip_method*) pjsip_get_ack_method(void)
65
return &pjsip_ack_method;
68
/** BYE method constant. */
69
PJ_DEF(const pjsip_method*) pjsip_get_bye_method(void)
71
return &pjsip_bye_method;
74
/** REGISTER method constant.*/
75
PJ_DEF(const pjsip_method*) pjsip_get_register_method(void)
77
return &pjsip_register_method;
80
/** OPTIONS method constant. */
81
PJ_DEF(const pjsip_method*) pjsip_get_options_method(void)
83
return &pjsip_options_method;
87
static const pj_str_t *method_names[] =
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
97
const pjsip_hdr_name_info_t pjsip_hdr_names[] =
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,
144
{ "_Unknown-Header", 15, NULL }, // PJSIP_H_OTHER,
147
pj_bool_t pjsip_use_compact_form = PJSIP_ENCODE_SHORT_HNAME;
149
static pj_str_t status_phrase[710];
150
static int print_media_type(char *buf, unsigned len,
151
const pjsip_media_type *media);
153
static int init_status_phrase()
156
pj_str_t default_reason_phrase = { "Default status message", 22};
158
for (i=0; i<PJ_ARRAY_SIZE(status_phrase); ++i)
159
status_phrase[i] = default_reason_phrase;
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");
167
pj_strset2( &status_phrase[200], "OK");
168
pj_strset2( &status_phrase[202], "Accepted");
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");
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");
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");
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");
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");
229
///////////////////////////////////////////////////////////////////////////////
234
PJ_DEF(void) pjsip_method_init( pjsip_method *m,
239
pjsip_method_init_np(m, pj_strdup(pool, &dup, str));
242
PJ_DEF(void) pjsip_method_set( pjsip_method *m, pjsip_method_e me )
244
pj_assert(me < PJSIP_OTHER_METHOD);
246
m->name = *method_names[me];
249
PJ_DEF(void) pjsip_method_init_np(pjsip_method *m,
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)
257
m->id = (pjsip_method_e)i;
258
m->name = *method_names[i];
262
m->id = PJSIP_OTHER_METHOD;
266
PJ_DEF(void) pjsip_method_copy( pj_pool_t *pool,
267
pjsip_method *method,
268
const pjsip_method *rhs )
270
method->id = rhs->id;
271
if (rhs->id != PJSIP_OTHER_METHOD) {
272
method->name = rhs->name;
274
pj_strdup(pool, &method->name, &rhs->name);
279
PJ_DEF(int) pjsip_method_cmp( const pjsip_method *m1, const pjsip_method *m2)
281
if (m1->id == m2->id) {
282
if (m1->id != PJSIP_OTHER_METHOD)
284
/* Method comparison is case sensitive! */
285
return pj_strcmp(&m1->name, &m2->name);
288
return ( m1->id < m2->id ) ? -1 : 1;
291
///////////////////////////////////////////////////////////////////////////////
296
PJ_DEF(pjsip_msg*) pjsip_msg_create( pj_pool_t *pool, pjsip_msg_type_e type)
298
pjsip_msg *msg = PJ_POOL_ALLOC_T(pool, pjsip_msg);
299
pj_list_init(&msg->hdr);
305
PJ_DEF(pjsip_msg*) pjsip_msg_clone( pj_pool_t *pool, const pjsip_msg *src)
310
dst = pjsip_msg_create(pool, src->type);
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,
318
dst->line.status.code = src->line.status.code;
319
pj_strdup(pool, &dst->line.status.reason, &src->line.status.reason);
324
while (sh != &src->hdr) {
325
pjsip_hdr *dh = (pjsip_hdr*) pjsip_hdr_clone(pool, sh);
326
pjsip_msg_add_hdr(dst, dh);
330
/* Clone message body */
332
dst->body = pjsip_msg_body_clone(pool, src->body);
338
PJ_DEF(void*) pjsip_msg_find_hdr( const pjsip_msg *msg,
339
pjsip_hdr_e hdr_type, const void *start)
341
const pjsip_hdr *hdr=(const pjsip_hdr*) start, *end=&msg->hdr;
346
for (; hdr!=end; hdr = hdr->next) {
347
if (hdr->type == hdr_type)
353
PJ_DEF(void*) pjsip_msg_find_hdr_by_name( const pjsip_msg *msg,
354
const pj_str_t *name,
357
const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
362
for (; hdr!=end; hdr = hdr->next) {
363
if (pj_stricmp(&hdr->name, name) == 0)
369
PJ_DEF(void*) pjsip_msg_find_hdr_by_names( const pjsip_msg *msg,
370
const pj_str_t *name,
371
const pj_str_t *sname,
374
const pjsip_hdr *hdr=(const pjsip_hdr*)start, *end=&msg->hdr;
379
for (; hdr!=end; hdr = hdr->next) {
380
if (pj_stricmp(&hdr->name, name) == 0)
382
if (pj_stricmp(&hdr->name, sname) == 0)
388
PJ_DEF(void*) pjsip_msg_find_remove_hdr( pjsip_msg *msg,
389
pjsip_hdr_e hdr_type, void *start)
391
pjsip_hdr *hdr = (pjsip_hdr*) pjsip_msg_find_hdr(msg, hdr_type, start);
398
PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg,
399
char *buf, pj_size_t size)
401
char *p=buf, *end=buf+size;
404
pj_str_t clen_hdr = { "Content-Length: ", 16};
406
if (pjsip_use_compact_form) {
407
clen_hdr.ptr = "l: ";
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.
417
/* Print request line or status line depending on message type */
418
if (msg->type == PJSIP_REQUEST_MSG) {
422
len = msg->line.req.method.name.slen;
423
pj_memcpy(p, msg->line.req.method.name.ptr, len);
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);
437
pj_memcpy(p, " SIP/2.0\r\n", 10);
443
pj_memcpy(p, "SIP/2.0 ", 8);
446
/* Add status code. */
447
len = pj_utoa(msg->line.status.code, p);
451
/* Add reason text. */
452
len = msg->line.status.reason.slen;
453
pj_memcpy(p, msg->line.status.reason.ptr, len );
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);
477
/* Process message body. */
479
enum { CLEN_SPACE = 5 };
480
char *clen_pos = NULL;
482
/* Automaticly adds Content-Type and Content-Length headers, only
483
* if content_type is set in the message body.
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;
489
if (pjsip_use_compact_form) {
490
ctype_hdr.ptr = "c: ";
494
/* Add Content-Type header. */
495
if ( (end-p) < 24 + media->type.slen + media->subtype.slen) {
498
pj_memcpy(p, ctype_hdr.ptr, ctype_hdr.slen);
500
p += print_media_type(p, end-p, media);
504
/* Add Content-Length header. */
505
if ((end-p) < clen_hdr.slen + 12 + 2) {
508
pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);
511
/* Print blanks after "Content-Length:", this is where we'll put
512
* the content length value after we know the length of the
515
pj_memset(p, ' ', CLEN_SPACE);
522
/* Add blank newline. */
526
/* Print the message body itself. */
527
len = (*msg->body->print_body)(msg->body, p, end-p);
533
/* Now that we have the length of the body, print this to the
534
* Content-Length header.
538
len = pj_utoa(len, tmp);
539
if (len > CLEN_SPACE) len = CLEN_SPACE;
540
pj_memcpy(clen_pos+CLEN_SPACE-len, tmp, len);
544
/* There's no message body.
545
* Add Content-Length with zero value.
547
if ((end-p) < clen_hdr.slen+8) {
550
pj_memcpy(p, clen_hdr.ptr, clen_hdr.slen);
564
///////////////////////////////////////////////////////////////////////////////
565
PJ_DEF(void*) pjsip_hdr_clone( pj_pool_t *pool, const void *hdr_ptr )
567
const pjsip_hdr *hdr = (const pjsip_hdr*) hdr_ptr;
568
return (*hdr->vptr->clone)(pool, hdr_ptr);
572
PJ_DEF(void*) pjsip_hdr_shallow_clone( pj_pool_t *pool, const void *hdr_ptr )
574
const pjsip_hdr *hdr = (const pjsip_hdr*) hdr_ptr;
575
return (*hdr->vptr->shallow_clone)(pool, hdr_ptr);
578
PJ_DEF(int) pjsip_hdr_print_on( void *hdr_ptr, char *buf, pj_size_t len)
580
pjsip_hdr *hdr = (pjsip_hdr*) hdr_ptr;
581
return (*hdr->vptr->print_on)(hdr_ptr, buf, len);
584
///////////////////////////////////////////////////////////////////////////////
586
* Status/Reason Phrase
589
PJ_DEF(const pj_str_t*) pjsip_get_status_text(int code)
591
static int is_initialized;
592
if (is_initialized == 0) {
594
init_status_phrase();
598
code<(int)(sizeof(status_phrase)/sizeof(status_phrase[0]))) ?
599
&status_phrase[code] : &status_phrase[0];
602
///////////////////////////////////////////////////////////////////////////////
609
PJ_DEF(void) pjsip_media_type_init( pjsip_media_type *mt,
613
pj_bzero(mt, sizeof(*mt));
614
pj_list_init(&mt->param);
618
mt->subtype = *subtype;
621
PJ_DEF(void) pjsip_media_type_init2( pjsip_media_type *mt,
625
pj_str_t s_type, s_subtype;
628
s_type = pj_str(type);
635
s_subtype = pj_str(subtype);
637
s_subtype.ptr = NULL;
641
pjsip_media_type_init(mt, &s_type, &s_subtype);
645
* Compare two media types.
647
PJ_DEF(int) pjsip_media_type_cmp( const pjsip_media_type *mt1,
648
const pjsip_media_type *mt2,
653
PJ_ASSERT_RETURN(mt1 && mt2, 1);
655
rc = pj_stricmp(&mt1->type, &mt2->type);
658
rc = pj_stricmp(&mt1->subtype, &mt2->subtype);
662
rc = pjsip_param_cmp(&mt1->param, &mt2->param, (cmp_param==1));
668
PJ_DEF(void) pjsip_media_type_cp( pj_pool_t *pool,
669
pjsip_media_type *dst,
670
const pjsip_media_type *src)
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);
678
///////////////////////////////////////////////////////////////////////////////
680
* Generic pjsip_hdr_names/hvalue header.
683
static int pjsip_generic_string_hdr_print( pjsip_generic_string_hdr *hdr,
684
char *buf, pj_size_t size);
685
static pjsip_generic_string_hdr* pjsip_generic_string_hdr_clone( pj_pool_t *pool,
686
const pjsip_generic_string_hdr *hdr);
687
static pjsip_generic_string_hdr* pjsip_generic_string_hdr_shallow_clone( pj_pool_t *pool,
688
const pjsip_generic_string_hdr *hdr );
690
static pjsip_hdr_vptr generic_hdr_vptr =
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,
698
PJ_DEF(void) pjsip_generic_string_hdr_init2(pjsip_generic_string_hdr *hdr,
702
init_hdr(hdr, PJSIP_H_OTHER, &generic_hdr_vptr);
708
hdr->hvalue = *hvalue;
710
hdr->hvalue.ptr = NULL;
711
hdr->hvalue.slen = 0;
716
PJ_DEF(pjsip_generic_string_hdr*) pjsip_generic_string_hdr_init(pj_pool_t *pool,
718
const pj_str_t *hnames,
719
const pj_str_t *hvalue)
721
pjsip_generic_string_hdr *hdr = (pjsip_generic_string_hdr*) mem;
722
pj_str_t dup_hname, dup_hval;
725
pj_strdup(pool, &dup_hname, hnames);
731
pj_strdup(pool, &dup_hval, hvalue);
736
pjsip_generic_string_hdr_init2(hdr, &dup_hname, &dup_hval);
740
PJ_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)
744
void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_string_hdr));
745
return pjsip_generic_string_hdr_init(pool, mem, hnames, hvalue);
748
static int pjsip_generic_string_hdr_print( pjsip_generic_string_hdr *hdr,
749
char *buf, pj_size_t size)
752
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
754
if ((pj_ssize_t)size < hname->slen + hdr->hvalue.slen + 5)
757
pj_memcpy(p, hname->ptr, hname->slen);
761
pj_memcpy(p, hdr->hvalue.ptr, hdr->hvalue.slen);
762
p += hdr->hvalue.slen;
768
static pjsip_generic_string_hdr* pjsip_generic_string_hdr_clone( pj_pool_t *pool,
769
const pjsip_generic_string_hdr *rhs)
771
pjsip_generic_string_hdr *hdr;
773
hdr = pjsip_generic_string_hdr_create(pool, &rhs->name, &rhs->hvalue);
775
hdr->type = rhs->type;
776
pj_strdup(pool, &hdr->sname, &rhs->sname);
780
static pjsip_generic_string_hdr* pjsip_generic_string_hdr_shallow_clone( pj_pool_t *pool,
781
const pjsip_generic_string_hdr *rhs )
783
pjsip_generic_string_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_string_hdr);
784
pj_memcpy(hdr, rhs, sizeof(*hdr));
788
///////////////////////////////////////////////////////////////////////////////
790
* Generic pjsip_hdr_names/integer value header.
793
static int pjsip_generic_int_hdr_print( pjsip_generic_int_hdr *hdr,
794
char *buf, pj_size_t size);
795
static pjsip_generic_int_hdr* pjsip_generic_int_hdr_clone( pj_pool_t *pool,
796
const pjsip_generic_int_hdr *hdr);
797
static pjsip_generic_int_hdr* pjsip_generic_int_hdr_shallow_clone( pj_pool_t *pool,
798
const pjsip_generic_int_hdr *hdr );
800
static pjsip_hdr_vptr generic_int_hdr_vptr =
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,
807
PJ_DEF(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_init( pj_pool_t *pool,
809
const pj_str_t *hnames,
812
pjsip_generic_int_hdr *hdr = (pjsip_generic_int_hdr*) mem;
814
init_hdr(hdr, PJSIP_H_OTHER, &generic_int_hdr_vptr);
816
pj_strdup(pool, &hdr->name, hnames);
817
hdr->sname = hdr->name;
823
PJ_DEF(pjsip_generic_int_hdr*) pjsip_generic_int_hdr_create( pj_pool_t *pool,
824
const pj_str_t *hnames,
827
void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_int_hdr));
828
return pjsip_generic_int_hdr_init(pool, mem, hnames, value);
831
static int pjsip_generic_int_hdr_print( pjsip_generic_int_hdr *hdr,
832
char *buf, pj_size_t size)
835
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
837
if ((pj_ssize_t)size < hname->slen + 15)
840
pj_memcpy(p, hname->ptr, hname->slen);
845
p += pj_utoa(hdr->ivalue, p);
850
static pjsip_generic_int_hdr* pjsip_generic_int_hdr_clone( pj_pool_t *pool,
851
const pjsip_generic_int_hdr *rhs)
853
pjsip_generic_int_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_int_hdr);
854
pj_memcpy(hdr, rhs, sizeof(*hdr));
858
static pjsip_generic_int_hdr* pjsip_generic_int_hdr_shallow_clone( pj_pool_t *pool,
859
const pjsip_generic_int_hdr *rhs )
861
pjsip_generic_int_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_int_hdr);
862
pj_memcpy(hdr, rhs, sizeof(*hdr));
866
///////////////////////////////////////////////////////////////////////////////
868
* Generic array header.
870
static int pjsip_generic_array_hdr_print( pjsip_generic_array_hdr *hdr, char *buf, pj_size_t size);
871
static pjsip_generic_array_hdr* pjsip_generic_array_hdr_clone( pj_pool_t *pool,
872
const pjsip_generic_array_hdr *hdr);
873
static pjsip_generic_array_hdr* pjsip_generic_array_hdr_shallow_clone( pj_pool_t *pool,
874
const pjsip_generic_array_hdr *hdr);
876
static pjsip_hdr_vptr generic_array_hdr_vptr =
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,
884
PJ_DEF(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_init( pj_pool_t *pool,
886
const pj_str_t *hnames)
888
pjsip_generic_array_hdr *hdr = (pjsip_generic_array_hdr*) mem;
890
init_hdr(hdr, PJSIP_H_OTHER, &generic_array_hdr_vptr);
892
pj_strdup(pool, &hdr->name, hnames);
893
hdr->sname = hdr->name;
899
PJ_DEF(pjsip_generic_array_hdr*) pjsip_generic_array_hdr_create( pj_pool_t *pool,
900
const pj_str_t *hnames)
902
void *mem = pj_pool_alloc(pool, sizeof(pjsip_generic_array_hdr));
903
return pjsip_generic_array_hdr_init(pool, mem, hnames);
907
static int pjsip_generic_array_hdr_print( pjsip_generic_array_hdr *hdr,
908
char *buf, pj_size_t size)
910
char *p = buf, *endbuf = buf+size;
911
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
913
copy_advance(p, (*hname));
917
if (hdr->count > 0) {
920
copy_advance(p, hdr->values[0]);
921
for (i=1; i<hdr->count; ++i) {
922
copy_advance_pair(p, ", ", 2, hdr->values[i]);
929
static pjsip_generic_array_hdr* pjsip_generic_array_hdr_clone( pj_pool_t *pool,
930
const pjsip_generic_array_hdr *rhs)
933
pjsip_generic_array_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_array_hdr);
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]);
944
static pjsip_generic_array_hdr* pjsip_generic_array_hdr_shallow_clone( pj_pool_t *pool,
945
const pjsip_generic_array_hdr *rhs)
947
pjsip_generic_array_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_generic_array_hdr);
948
pj_memcpy(hdr, rhs, sizeof(*hdr));
952
///////////////////////////////////////////////////////////////////////////////
956
PJ_DEF(pjsip_accept_hdr*) pjsip_accept_hdr_init( pj_pool_t *pool,
959
pjsip_accept_hdr *hdr = (pjsip_accept_hdr*) mem;
963
init_hdr(hdr, PJSIP_H_ACCEPT, &generic_array_hdr_vptr);
968
PJ_DEF(pjsip_accept_hdr*) pjsip_accept_hdr_create(pj_pool_t *pool)
970
void *mem = pj_pool_alloc(pool, sizeof(pjsip_accept_hdr));
971
return pjsip_accept_hdr_init(pool, mem);
975
///////////////////////////////////////////////////////////////////////////////
980
PJ_DEF(pjsip_allow_hdr*) pjsip_allow_hdr_init( pj_pool_t *pool,
983
pjsip_allow_hdr *hdr = (pjsip_allow_hdr*) mem;
987
init_hdr(hdr, PJSIP_H_ALLOW, &generic_array_hdr_vptr);
992
PJ_DEF(pjsip_allow_hdr*) pjsip_allow_hdr_create(pj_pool_t *pool)
994
void *mem = pj_pool_alloc(pool, sizeof(pjsip_allow_hdr));
995
return pjsip_allow_hdr_init(pool, mem);
998
///////////////////////////////////////////////////////////////////////////////
1003
PJ_DEF(pjsip_cid_hdr*) pjsip_cid_hdr_init( pj_pool_t *pool,
1006
pjsip_cid_hdr *hdr = (pjsip_cid_hdr*) mem;
1008
PJ_UNUSED_ARG(pool);
1010
init_hdr(hdr, PJSIP_H_CALL_ID, &generic_hdr_vptr);
1015
PJ_DEF(pjsip_cid_hdr*) pjsip_cid_hdr_create( pj_pool_t *pool )
1017
void *mem = pj_pool_alloc(pool, sizeof(pjsip_cid_hdr));
1018
return pjsip_cid_hdr_init(pool, mem);
1022
///////////////////////////////////////////////////////////////////////////////
1024
* Content-Length header.
1026
static int pjsip_clen_hdr_print( pjsip_clen_hdr *hdr, char *buf, pj_size_t size);
1027
static 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
1030
static pjsip_hdr_vptr clen_hdr_vptr =
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,
1037
PJ_DEF(pjsip_clen_hdr*) pjsip_clen_hdr_init( pj_pool_t *pool,
1040
pjsip_clen_hdr *hdr = (pjsip_clen_hdr*) mem;
1042
PJ_UNUSED_ARG(pool);
1044
init_hdr(hdr, PJSIP_H_CONTENT_LENGTH, &clen_hdr_vptr);
1049
PJ_DEF(pjsip_clen_hdr*) pjsip_clen_hdr_create( pj_pool_t *pool )
1051
void *mem = pj_pool_alloc(pool, sizeof(pjsip_clen_hdr));
1052
return pjsip_clen_hdr_init(pool, mem);
1055
static int pjsip_clen_hdr_print( pjsip_clen_hdr *hdr,
1056
char *buf, pj_size_t size)
1060
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1062
if ((pj_ssize_t)size < hname->slen + 14)
1065
pj_memcpy(p, hname->ptr, hname->slen);
1070
len = pj_utoa(hdr->len, p);
1077
static pjsip_clen_hdr* pjsip_clen_hdr_clone( pj_pool_t *pool, const pjsip_clen_hdr *rhs)
1079
pjsip_clen_hdr *hdr = pjsip_clen_hdr_create(pool);
1080
hdr->len = rhs->len;
1085
///////////////////////////////////////////////////////////////////////////////
1089
static int pjsip_cseq_hdr_print( pjsip_cseq_hdr *hdr, char *buf, pj_size_t size);
1090
static pjsip_cseq_hdr* pjsip_cseq_hdr_clone( pj_pool_t *pool, const pjsip_cseq_hdr *hdr);
1091
static pjsip_cseq_hdr* pjsip_cseq_hdr_shallow_clone( pj_pool_t *pool, const pjsip_cseq_hdr *hdr );
1093
static pjsip_hdr_vptr cseq_hdr_vptr =
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,
1100
PJ_DEF(pjsip_cseq_hdr*) pjsip_cseq_hdr_init( pj_pool_t *pool,
1103
pjsip_cseq_hdr *hdr = (pjsip_cseq_hdr*) mem;
1105
PJ_UNUSED_ARG(pool);
1107
init_hdr(hdr, PJSIP_H_CSEQ, &cseq_hdr_vptr);
1109
hdr->method.id = PJSIP_OTHER_METHOD;
1110
hdr->method.name.ptr = NULL;
1111
hdr->method.name.slen = 0;
1115
PJ_DEF(pjsip_cseq_hdr*) pjsip_cseq_hdr_create( pj_pool_t *pool )
1117
void *mem = pj_pool_alloc(pool, sizeof(pjsip_cseq_hdr));
1118
return pjsip_cseq_hdr_init(pool, mem);
1121
static int pjsip_cseq_hdr_print( pjsip_cseq_hdr *hdr, char *buf, pj_size_t size)
1125
/* CSeq doesn't have compact form */
1127
if ((pj_ssize_t)size < hdr->name.slen + hdr->method.name.slen + 15)
1130
pj_memcpy(p, hdr->name.ptr, hdr->name.slen);
1131
p += hdr->name.slen;
1135
len = pj_utoa(hdr->cseq, p);
1139
pj_memcpy(p, hdr->method.name.ptr, hdr->method.name.slen);
1140
p += hdr->method.name.slen;
1147
static pjsip_cseq_hdr* pjsip_cseq_hdr_clone( pj_pool_t *pool,
1148
const pjsip_cseq_hdr *rhs)
1150
pjsip_cseq_hdr *hdr = pjsip_cseq_hdr_create(pool);
1151
hdr->cseq = rhs->cseq;
1152
pjsip_method_copy(pool, &hdr->method, &rhs->method);
1156
static pjsip_cseq_hdr* pjsip_cseq_hdr_shallow_clone( pj_pool_t *pool,
1157
const pjsip_cseq_hdr *rhs )
1159
pjsip_cseq_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_cseq_hdr);
1160
pj_memcpy(hdr, rhs, sizeof(*hdr));
1165
///////////////////////////////////////////////////////////////////////////////
1169
static int pjsip_contact_hdr_print( pjsip_contact_hdr *hdr, char *buf, pj_size_t size);
1170
static pjsip_contact_hdr* pjsip_contact_hdr_clone( pj_pool_t *pool, const pjsip_contact_hdr *hdr);
1171
static pjsip_contact_hdr* pjsip_contact_hdr_shallow_clone( pj_pool_t *pool, const pjsip_contact_hdr *);
1173
static pjsip_hdr_vptr contact_hdr_vptr =
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,
1180
PJ_DEF(pjsip_contact_hdr*) pjsip_contact_hdr_init( pj_pool_t *pool,
1183
pjsip_contact_hdr *hdr = (pjsip_contact_hdr*) mem;
1185
PJ_UNUSED_ARG(pool);
1187
pj_bzero(mem, sizeof(pjsip_contact_hdr));
1188
init_hdr(hdr, PJSIP_H_CONTACT, &contact_hdr_vptr);
1190
pj_list_init(&hdr->other_param);
1194
PJ_DEF(pjsip_contact_hdr*) pjsip_contact_hdr_create( pj_pool_t *pool )
1196
void *mem = pj_pool_alloc(pool, sizeof(pjsip_contact_hdr));
1197
return pjsip_contact_hdr_init(pool, mem);
1200
static int pjsip_contact_hdr_print( pjsip_contact_hdr *hdr, char *buf,
1203
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1204
const pjsip_parser_const_t *pc = pjsip_parser_const();
1208
if ((pj_ssize_t)size < hname->slen + 6)
1210
pj_memcpy(p, hname->ptr, hname->slen);
1219
char *startbuf = buf;
1220
char *endbuf = buf + size;
1222
copy_advance(buf, (*hname));
1226
printed = pjsip_uri_print(PJSIP_URI_IN_CONTACT_HDR, hdr->uri,
1236
if (buf+19 >= endbuf)
1240
printed = sprintf(buf, ";q=%u.%03u",
1241
hdr->q1000/1000, hdr->q1000 % 1000);
1243
pj_memcpy(buf, ";q=", 3);
1244
printed = pj_utoa(hdr->q1000/1000, buf+3);
1246
frac = hdr->q1000 % 1000;
1249
if ((frac % 100)==0) frac /= 100;
1250
if ((frac % 10)==0) frac /= 10;
1251
printed = pj_utoa(frac, buf);
1256
if (hdr->expires >= 0) {
1257
if (buf+23 >= endbuf)
1260
pj_memcpy(buf, ";expires=", 9);
1261
printed = pj_utoa(hdr->expires, buf+9);
1265
printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1266
&pc->pjsip_TOKEN_SPEC,
1267
&pc->pjsip_TOKEN_SPEC,
1273
return buf-startbuf;
1277
static pjsip_contact_hdr* pjsip_contact_hdr_clone(pj_pool_t *pool,
1278
const pjsip_contact_hdr *rhs)
1280
pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(pool);
1282
hdr->star = rhs->star;
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);
1293
static pjsip_contact_hdr*
1294
pjsip_contact_hdr_shallow_clone( pj_pool_t *pool,
1295
const pjsip_contact_hdr *rhs)
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);
1303
///////////////////////////////////////////////////////////////////////////////
1305
* Content-Type header..
1307
static int pjsip_ctype_hdr_print( pjsip_ctype_hdr *hdr, char *buf,
1309
static 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
1313
static pjsip_hdr_vptr ctype_hdr_vptr =
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,
1320
PJ_DEF(pjsip_ctype_hdr*) pjsip_ctype_hdr_init( pj_pool_t *pool,
1323
pjsip_ctype_hdr *hdr = (pjsip_ctype_hdr*) mem;
1325
PJ_UNUSED_ARG(pool);
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);
1334
PJ_DEF(pjsip_ctype_hdr*) pjsip_ctype_hdr_create( pj_pool_t *pool )
1336
void *mem = pj_pool_alloc(pool, sizeof(pjsip_ctype_hdr));
1337
return pjsip_ctype_hdr_init(pool, mem);
1340
static int print_media_type(char *buf, unsigned len,
1341
const pjsip_media_type *media)
1345
const pjsip_parser_const_t *pc;
1347
pj_memcpy(p, media->type.ptr, media->type.slen);
1348
p += media->type.slen;
1350
pj_memcpy(p, media->subtype.ptr, media->subtype.slen);
1351
p += media->subtype.slen;
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, ';');
1366
PJ_DEF(int) pjsip_media_type_print(char *buf, unsigned len,
1367
const pjsip_media_type *media)
1369
return print_media_type(buf, len, media);
1372
static int pjsip_ctype_hdr_print( pjsip_ctype_hdr *hdr,
1373
char *buf, pj_size_t size)
1377
const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
1379
if ((pj_ssize_t)size < hname->slen +
1380
hdr->media.type.slen + hdr->media.subtype.slen + 8)
1385
pj_memcpy(p, hname->ptr, hname->slen);
1390
len = print_media_type(p, buf+size-p, &hdr->media);
1397
static pjsip_ctype_hdr* pjsip_ctype_hdr_clone( pj_pool_t *pool,
1398
const pjsip_ctype_hdr *rhs)
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);
1408
///////////////////////////////////////////////////////////////////////////////
1412
PJ_DEF(pjsip_expires_hdr*) pjsip_expires_hdr_init( pj_pool_t *pool,
1416
pjsip_expires_hdr *hdr = (pjsip_expires_hdr*) mem;
1418
PJ_UNUSED_ARG(pool);
1420
init_hdr(hdr, PJSIP_H_EXPIRES, &generic_int_hdr_vptr);
1421
hdr->ivalue = value;
1426
PJ_DEF(pjsip_expires_hdr*) pjsip_expires_hdr_create( pj_pool_t *pool,
1429
void *mem = pj_pool_alloc(pool, sizeof(pjsip_expires_hdr));
1430
return pjsip_expires_hdr_init(pool, mem, value);
1433
///////////////////////////////////////////////////////////////////////////////
1435
* To or From header.
1437
static int pjsip_fromto_hdr_print( pjsip_fromto_hdr *hdr,
1438
char *buf, pj_size_t size);
1439
static pjsip_fromto_hdr* pjsip_fromto_hdr_clone( pj_pool_t *pool,
1440
const pjsip_fromto_hdr *hdr);
1441
static pjsip_fromto_hdr* pjsip_fromto_hdr_shallow_clone( pj_pool_t *pool,
1442
const pjsip_fromto_hdr *hdr);
1445
static pjsip_hdr_vptr fromto_hdr_vptr =
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,
1452
PJ_DEF(pjsip_from_hdr*) pjsip_from_hdr_init( pj_pool_t *pool,
1455
pjsip_from_hdr *hdr = (pjsip_from_hdr*) mem;
1457
PJ_UNUSED_ARG(pool);
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);
1465
PJ_DEF(pjsip_from_hdr*) pjsip_from_hdr_create( pj_pool_t *pool )
1467
void *mem = pj_pool_alloc(pool, sizeof(pjsip_from_hdr));
1468
return pjsip_from_hdr_init(pool, mem);
1471
PJ_DEF(pjsip_to_hdr*) pjsip_to_hdr_init( pj_pool_t *pool,
1474
pjsip_to_hdr *hdr = (pjsip_to_hdr*) mem;
1476
PJ_UNUSED_ARG(pool);
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);
1485
PJ_DEF(pjsip_to_hdr*) pjsip_to_hdr_create( pj_pool_t *pool )
1487
void *mem = pj_pool_alloc(pool, sizeof(pjsip_to_hdr));
1488
return pjsip_to_hdr_init(pool, mem);
1491
PJ_DEF(pjsip_from_hdr*) pjsip_fromto_hdr_set_from( pjsip_fromto_hdr *hdr )
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;
1501
PJ_DEF(pjsip_to_hdr*) pjsip_fromto_hdr_set_to( pjsip_fromto_hdr *hdr )
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;
1511
static int pjsip_fromto_hdr_print( pjsip_fromto_hdr *hdr,
1512
char *buf, pj_size_t size)
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();
1520
copy_advance(buf, (*hname));
1524
printed = pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, hdr->uri,
1531
copy_advance_pair_escape(buf, ";tag=", 5, hdr->tag,
1532
pc->pjsip_TOKEN_SPEC);
1534
printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1535
&pc->pjsip_TOKEN_SPEC,
1536
&pc->pjsip_TOKEN_SPEC, ';');
1541
return buf-startbuf;
1544
static pjsip_fromto_hdr* pjsip_fromto_hdr_clone( pj_pool_t *pool,
1545
const pjsip_fromto_hdr *rhs)
1547
pjsip_fromto_hdr *hdr = pjsip_from_hdr_create(pool);
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);
1559
static pjsip_fromto_hdr*
1560
pjsip_fromto_hdr_shallow_clone( pj_pool_t *pool,
1561
const pjsip_fromto_hdr *rhs)
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);
1570
///////////////////////////////////////////////////////////////////////////////
1572
* Max-Forwards header.
1574
PJ_DEF(pjsip_max_fwd_hdr*) pjsip_max_fwd_hdr_init( pj_pool_t *pool,
1578
pjsip_max_fwd_hdr *hdr = (pjsip_max_fwd_hdr*) mem;
1580
PJ_UNUSED_ARG(pool);
1582
init_hdr(hdr, PJSIP_H_MAX_FORWARDS, &generic_int_hdr_vptr);
1583
hdr->ivalue = value;
1588
PJ_DEF(pjsip_max_fwd_hdr*) pjsip_max_fwd_hdr_create(pj_pool_t *pool,
1591
void *mem = pj_pool_alloc(pool, sizeof(pjsip_max_fwd_hdr));
1592
return pjsip_max_fwd_hdr_init(pool, mem, value);
1596
///////////////////////////////////////////////////////////////////////////////
1598
* Min-Expires header.
1600
PJ_DEF(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_init( pj_pool_t *pool,
1604
pjsip_min_expires_hdr *hdr = (pjsip_min_expires_hdr*) mem;
1606
PJ_UNUSED_ARG(pool);
1608
init_hdr(hdr, PJSIP_H_MIN_EXPIRES, &generic_int_hdr_vptr);
1609
hdr->ivalue = value;
1613
PJ_DEF(pjsip_min_expires_hdr*) pjsip_min_expires_hdr_create(pj_pool_t *pool,
1616
void *mem = pj_pool_alloc(pool, sizeof(pjsip_min_expires_hdr));
1617
return pjsip_min_expires_hdr_init(pool, mem, value );
1620
///////////////////////////////////////////////////////////////////////////////
1622
* Record-Route and Route header.
1624
static int pjsip_routing_hdr_print( pjsip_routing_hdr *r, char *buf, pj_size_t size );
1625
static pjsip_routing_hdr* pjsip_routing_hdr_clone( pj_pool_t *pool, const pjsip_routing_hdr *r );
1626
static pjsip_routing_hdr* pjsip_routing_hdr_shallow_clone( pj_pool_t *pool, const pjsip_routing_hdr *r );
1628
static pjsip_hdr_vptr routing_hdr_vptr =
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,
1635
PJ_DEF(pjsip_rr_hdr*) pjsip_rr_hdr_init( pj_pool_t *pool,
1638
pjsip_rr_hdr *hdr = (pjsip_rr_hdr*) mem;
1640
PJ_UNUSED_ARG(pool);
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);
1649
PJ_DEF(pjsip_rr_hdr*) pjsip_rr_hdr_create( pj_pool_t *pool )
1651
void *mem = pj_pool_alloc(pool, sizeof(pjsip_rr_hdr));
1652
return pjsip_rr_hdr_init(pool, mem);
1655
PJ_DEF(pjsip_route_hdr*) pjsip_route_hdr_init( pj_pool_t *pool,
1658
pjsip_route_hdr *hdr = (pjsip_route_hdr*) mem;
1660
PJ_UNUSED_ARG(pool);
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);
1668
PJ_DEF(pjsip_route_hdr*) pjsip_route_hdr_create( pj_pool_t *pool )
1670
void *mem = pj_pool_alloc(pool, sizeof(pjsip_route_hdr));
1671
return pjsip_route_hdr_init(pool, mem);
1674
PJ_DEF(pjsip_rr_hdr*) pjsip_routing_hdr_set_rr( pjsip_routing_hdr *hdr )
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;
1683
PJ_DEF(pjsip_route_hdr*) pjsip_routing_hdr_set_route( pjsip_routing_hdr *hdr )
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;
1692
static int pjsip_routing_hdr_print( pjsip_routing_hdr *hdr,
1693
char *buf, pj_size_t size )
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;
1702
/* Check the proprietary param 'hide', don't print this header
1703
* if it exists in the route URI.
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};
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);
1718
/* Route and Record-Route don't compact forms */
1720
copy_advance(buf, hdr->name);
1724
printed = pjsip_uri_print(PJSIP_URI_IN_ROUTING_HDR, &hdr->name_addr, buf,
1730
printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
1731
&pc->pjsip_TOKEN_SPEC,
1732
&pc->pjsip_TOKEN_SPEC, ';');
1737
return buf-startbuf;
1740
static pjsip_routing_hdr* pjsip_routing_hdr_clone( pj_pool_t *pool,
1741
const pjsip_routing_hdr *rhs )
1743
pjsip_routing_hdr *hdr = PJ_POOL_ALLOC_T(pool, pjsip_routing_hdr);
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);
1752
static pjsip_routing_hdr* pjsip_routing_hdr_shallow_clone( pj_pool_t *pool,
1753
const pjsip_routing_hdr *rhs )
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);
1762
///////////////////////////////////////////////////////////////////////////////
1766
PJ_DEF(pjsip_require_hdr*) pjsip_require_hdr_init( pj_pool_t *pool,
1769
pjsip_require_hdr *hdr = (pjsip_require_hdr*) mem;
1771
PJ_UNUSED_ARG(pool);
1773
init_hdr(hdr, PJSIP_H_REQUIRE, &generic_array_hdr_vptr);
1778
PJ_DEF(pjsip_require_hdr*) pjsip_require_hdr_create(pj_pool_t *pool)
1780
void *mem = pj_pool_alloc(pool, sizeof(pjsip_require_hdr));
1781
return pjsip_require_hdr_init(pool, mem);
1784
///////////////////////////////////////////////////////////////////////////////
1786
* Retry-After header.
1788
static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *r,
1789
char *buf, pj_size_t size );
1790
static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool,
1791
const pjsip_retry_after_hdr *r);
1792
static pjsip_retry_after_hdr*
1793
pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool,
1794
const pjsip_retry_after_hdr *r );
1796
static pjsip_hdr_vptr retry_after_hdr_vptr =
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,
1804
PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_init( pj_pool_t *pool,
1808
pjsip_retry_after_hdr *hdr = (pjsip_retry_after_hdr*) mem;
1810
PJ_UNUSED_ARG(pool);
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);
1819
PJ_DEF(pjsip_retry_after_hdr*) pjsip_retry_after_hdr_create(pj_pool_t *pool,
1822
void *mem = pj_pool_alloc(pool, sizeof(pjsip_retry_after_hdr));
1823
return pjsip_retry_after_hdr_init(pool, mem, value );
1827
static int pjsip_retry_after_hdr_print(pjsip_retry_after_hdr *hdr,
1828
char *buf, pj_size_t size)
1831
char *endbuf = buf + size;
1832
const pj_str_t *hname = &hdr->name;
1833
const pjsip_parser_const_t *pc = pjsip_parser_const();
1836
if ((pj_ssize_t)size < hdr->name.slen + 2+11)
1839
pj_memcpy(p, hdr->name.ptr, hdr->name.slen);
1844
p += pj_utoa(hdr->ivalue, p);
1846
if (hdr->comment.slen) {
1849
if (endbuf-p < hdr->comment.slen + 3)
1852
enclosed = (*hdr->comment.ptr == '(');
1855
pj_memcpy(p, hdr->comment.ptr, hdr->comment.slen);
1856
p += hdr->comment.slen;
1860
if (!pj_list_empty(&hdr->param))
1864
printed = pjsip_param_print_on(&hdr->param, p, endbuf-p,
1865
&pc->pjsip_TOKEN_SPEC,
1866
&pc->pjsip_TOKEN_SPEC,
1876
static pjsip_retry_after_hdr* pjsip_retry_after_hdr_clone(pj_pool_t *pool,
1877
const pjsip_retry_after_hdr *rhs)
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);
1885
static pjsip_retry_after_hdr*
1886
pjsip_retry_after_hdr_shallow_clone(pj_pool_t *pool,
1887
const pjsip_retry_after_hdr *rhs)
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);
1895
///////////////////////////////////////////////////////////////////////////////
1899
PJ_DEF(pjsip_supported_hdr*) pjsip_supported_hdr_init( pj_pool_t *pool,
1902
pjsip_supported_hdr *hdr = (pjsip_supported_hdr*) mem;
1904
PJ_UNUSED_ARG(pool);
1905
init_hdr(hdr, PJSIP_H_SUPPORTED, &generic_array_hdr_vptr);
1910
PJ_DEF(pjsip_supported_hdr*) pjsip_supported_hdr_create(pj_pool_t *pool)
1912
void *mem = pj_pool_alloc(pool, sizeof(pjsip_supported_hdr));
1913
return pjsip_supported_hdr_init(pool, mem);
1917
///////////////////////////////////////////////////////////////////////////////
1919
* Unsupported header.
1921
PJ_DEF(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_init( pj_pool_t *pool,
1924
pjsip_unsupported_hdr *hdr = (pjsip_unsupported_hdr*) mem;
1926
PJ_UNUSED_ARG(pool);
1928
init_hdr(hdr, PJSIP_H_UNSUPPORTED, &generic_array_hdr_vptr);
1933
PJ_DEF(pjsip_unsupported_hdr*) pjsip_unsupported_hdr_create(pj_pool_t *pool)
1935
void *mem = pj_pool_alloc(pool, sizeof(pjsip_unsupported_hdr));
1936
return pjsip_unsupported_hdr_init(pool, mem);
1939
///////////////////////////////////////////////////////////////////////////////
1943
static int pjsip_via_hdr_print( pjsip_via_hdr *hdr, char *buf, pj_size_t size);
1944
static pjsip_via_hdr* pjsip_via_hdr_clone( pj_pool_t *pool, const pjsip_via_hdr *hdr);
1945
static pjsip_via_hdr* pjsip_via_hdr_shallow_clone( pj_pool_t *pool, const pjsip_via_hdr *hdr );
1947
static pjsip_hdr_vptr via_hdr_vptr =
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,
1954
PJ_DEF(pjsip_via_hdr*) pjsip_via_hdr_init( pj_pool_t *pool,
1957
pjsip_via_hdr *hdr = (pjsip_via_hdr*) mem;
1959
PJ_UNUSED_ARG(pool);
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);
1970
PJ_DEF(pjsip_via_hdr*) pjsip_via_hdr_create( pj_pool_t *pool )
1972
void *mem = pj_pool_alloc(pool, sizeof(pjsip_via_hdr));
1973
return pjsip_via_hdr_init(pool, mem);
1976
static int pjsip_via_hdr_print( pjsip_via_hdr *hdr,
1977
char *buf, pj_size_t size)
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();
1986
if ((pj_ssize_t)size < hname->slen + sip_ver.slen +
1987
hdr->transport.slen + hdr->sent_by.host.slen + 12)
1992
/* pjsip_hdr_names */
1993
copy_advance(buf, (*hname));
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) */
2004
for (i=0; i<hdr->transport.slen; ++i) {
2005
buf[i] = (char)pj_toupper(hdr->transport.ptr[i]);
2008
buf += hdr->transport.slen;
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, '[', ']');
2015
copy_advance_check(buf, hdr->sent_by.host);
2018
if (hdr->sent_by.port != 0) {
2020
printed = pj_utoa(hdr->sent_by.port, buf);
2024
if (hdr->ttl_param >= 0) {
2028
pj_memcpy(buf, ";ttl=", 5);
2029
printed = pj_utoa(hdr->ttl_param, buf+5);
2033
if (hdr->rport_param >= 0) {
2037
pj_memcpy(buf, ";rport", 6);
2039
if (hdr->rport_param > 0) {
2041
buf += pj_utoa(hdr->rport_param, buf);
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,
2052
copy_advance_pair(buf, ";maddr=", 7, hdr->maddr_param);
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);
2060
printed = pjsip_param_print_on(&hdr->other_param, buf, endbuf-buf,
2061
&pc->pjsip_TOKEN_SPEC,
2062
&pc->pjsip_TOKEN_SPEC, ';');
2067
return buf-startbuf;
2070
static pjsip_via_hdr* pjsip_via_hdr_clone( pj_pool_t *pool,
2071
const pjsip_via_hdr *rhs)
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);
2086
static pjsip_via_hdr* pjsip_via_hdr_shallow_clone( pj_pool_t *pool,
2087
const pjsip_via_hdr *rhs )
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);
2095
///////////////////////////////////////////////////////////////////////////////
2099
PJ_DEF(pjsip_warning_hdr*) pjsip_warning_hdr_create( pj_pool_t *pool,
2101
const pj_str_t *host,
2102
const pj_str_t *text)
2104
const pj_str_t str_warning = { "Warning", 7 };
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);
2114
return pjsip_generic_string_hdr_create(pool, &str_warning, &hvalue);
2117
PJ_DEF(pjsip_warning_hdr*) pjsip_warning_hdr_create_from_status(pj_pool_t *pool,
2118
const pj_str_t *host,
2121
char errbuf[PJ_ERR_MSG_SIZE];
2124
text = pj_strerror(status, errbuf, sizeof(errbuf));
2125
return pjsip_warning_hdr_create(pool, 399, host, &text);
2128
///////////////////////////////////////////////////////////////////////////////
2130
* Message body manipulations.
2132
PJ_DEF(int) pjsip_print_text_body(pjsip_msg_body *msg_body, char *buf, pj_size_t size)
2134
if (size < msg_body->len)
2136
pj_memcpy(buf, msg_body->data, msg_body->len);
2137
return msg_body->len;
2140
PJ_DEF(void*) pjsip_clone_text_data( pj_pool_t *pool, const void *data,
2146
newdata = (char*) pj_pool_alloc(pool, len);
2147
pj_memcpy(newdata, data, len);
2152
PJ_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 )
2156
/* First check if clone_data field is initialized. */
2157
PJ_ASSERT_RETURN( src_body->clone_data!=NULL, PJ_EINVAL );
2159
/* Duplicate content-type */
2160
pjsip_media_type_cp(pool, &dst_body->content_type,
2161
&src_body->content_type);
2163
/* Duplicate data. */
2164
dst_body->data = (*src_body->clone_data)(pool, src_body->data,
2168
dst_body->len = src_body->len;
2170
/* Function pointers. */
2171
dst_body->print_body = src_body->print_body;
2172
dst_body->clone_data = src_body->clone_data;
2178
PJ_DEF(pjsip_msg_body*) pjsip_msg_body_clone( pj_pool_t *pool,
2179
const pjsip_msg_body *body )
2181
pjsip_msg_body *new_body;
2184
new_body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body);
2185
PJ_ASSERT_RETURN(new_body, NULL);
2187
status = pjsip_msg_body_copy(pool, new_body, body);
2189
return (status==PJ_SUCCESS) ? new_body : NULL;
2193
PJ_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 )
2198
pjsip_msg_body *body;
2200
PJ_ASSERT_RETURN(pool && type && subtype && text, NULL);
2202
body = PJ_POOL_ZALLOC_T(pool, pjsip_msg_body);
2203
PJ_ASSERT_RETURN(body != NULL, NULL);
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);
2209
body->data = pj_pool_alloc(pool, text->slen);
2210
pj_memcpy(body->data, text->ptr, text->slen);
2211
body->len = text->slen;
2213
body->clone_data = &pjsip_clone_text_data;
2214
body->print_body = &pjsip_print_text_body;