~ubuntu-branches/ubuntu/trusty/sflphone/trusty

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjsip/src/pjsip/sip_msg.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (4.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20140128182336-jrsv0k9u6cawc068
Tags: 1.3.0-1
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

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