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