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