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

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjsip/src/pjsip/sip_uri.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_uri.c 4228 2012-08-13 07:26:03Z bennylp $ */
 
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_uri.h>
 
21
#include <pjsip/sip_msg.h>
 
22
#include <pjsip/sip_parser.h>
 
23
#include <pjsip/print_util.h>
 
24
#include <pjsip/sip_errno.h>
 
25
#include <pjlib-util/string.h>
 
26
#include <pj/string.h>
 
27
#include <pj/pool.h>
 
28
#include <pj/assert.h>
 
29
 
 
30
/*
 
31
 * Generic parameter manipulation.
 
32
 */
 
33
PJ_DEF(pjsip_param*) pjsip_param_find(  const pjsip_param *param_list,
 
34
                                        const pj_str_t *name )
 
35
{
 
36
    pjsip_param *p = (pjsip_param*)param_list->next;
 
37
    while (p != param_list) {
 
38
        if (pj_stricmp(&p->name, name)==0)
 
39
            return p;
 
40
        p = p->next;
 
41
    }
 
42
    return NULL;
 
43
}
 
44
 
 
45
PJ_DEF(int) pjsip_param_cmp( const pjsip_param *param_list1,
 
46
                             const pjsip_param *param_list2,
 
47
                             pj_bool_t ig_nf)
 
48
{
 
49
    const pjsip_param *p1;
 
50
 
 
51
    if ((ig_nf & 1)==0 && pj_list_size(param_list1)!=pj_list_size(param_list2))
 
52
        return 1;
 
53
 
 
54
    p1 = param_list1->next;
 
55
    while (p1 != param_list1) {
 
56
        const pjsip_param *p2;
 
57
        p2 = pjsip_param_find(param_list2, &p1->name);
 
58
        if (p2 ) {
 
59
            int rc = pj_stricmp(&p1->value, &p2->value);
 
60
            if (rc != 0)
 
61
                return rc;
 
62
        } else if ((ig_nf & 1)==0)
 
63
            return 1;
 
64
 
 
65
        p1 = p1->next;
 
66
    }
 
67
 
 
68
    return 0;
 
69
}
 
70
 
 
71
PJ_DEF(void) pjsip_param_clone( pj_pool_t *pool, pjsip_param *dst_list,
 
72
                                const pjsip_param *src_list)
 
73
{
 
74
    const pjsip_param *p = src_list->next;
 
75
 
 
76
    pj_list_init(dst_list);
 
77
    while (p && p != src_list) {
 
78
        pjsip_param *new_param = PJ_POOL_ALLOC_T(pool, pjsip_param);
 
79
        pj_strdup(pool, &new_param->name, &p->name);
 
80
        pj_strdup(pool, &new_param->value, &p->value);
 
81
        pj_list_insert_before(dst_list, new_param);
 
82
        p = p->next;
 
83
    }
 
84
}
 
85
 
 
86
 
 
87
PJ_DEF(void) pjsip_param_shallow_clone( pj_pool_t *pool, 
 
88
                                        pjsip_param *dst_list,
 
89
                                        const pjsip_param *src_list)
 
90
{
 
91
    const pjsip_param *p = src_list->next;
 
92
 
 
93
    pj_list_init(dst_list);
 
94
    while (p != src_list) {
 
95
        pjsip_param *new_param = PJ_POOL_ALLOC_T(pool, pjsip_param);
 
96
        new_param->name = p->name;
 
97
        new_param->value = p->value;
 
98
        pj_list_insert_before(dst_list, new_param);
 
99
        p = p->next;
 
100
    }
 
101
}
 
102
 
 
103
PJ_DEF(pj_ssize_t) pjsip_param_print_on( const pjsip_param *param_list,
 
104
                                         char *buf, pj_size_t size,
 
105
                                         const pj_cis_t *pname_spec,
 
106
                                         const pj_cis_t *pvalue_spec,
 
107
                                         int sep)
 
108
{
 
109
    const pjsip_param *p;
 
110
    char *startbuf;
 
111
    char *endbuf;
 
112
    int printed;
 
113
 
 
114
    p = param_list->next;
 
115
    if (p == NULL || p == param_list)
 
116
        return 0;
 
117
 
 
118
    startbuf = buf;
 
119
    endbuf = buf + size;
 
120
 
 
121
    PJ_UNUSED_ARG(pname_spec);
 
122
 
 
123
    do {
 
124
        *buf++ = (char)sep;
 
125
        copy_advance_escape(buf, p->name, (*pname_spec));
 
126
        if (p->value.slen) {
 
127
            *buf++ = '=';
 
128
            if (*p->value.ptr == '"')
 
129
                copy_advance(buf, p->value);
 
130
            else
 
131
                copy_advance_escape(buf, p->value, (*pvalue_spec));
 
132
        }
 
133
        p = p->next;
 
134
        if (sep == '?') sep = '&';
 
135
    } while (p != param_list);
 
136
 
 
137
    return buf-startbuf;
 
138
}
 
139
 
 
140
 
 
141
/*
 
142
 * URI stuffs
 
143
 */
 
144
#define IS_SIPS(url)    ((url)->vptr==&sips_url_vptr)
 
145
 
 
146
static const pj_str_t *pjsip_url_get_scheme( const pjsip_sip_uri* );
 
147
static const pj_str_t *pjsips_url_get_scheme( const pjsip_sip_uri* );
 
148
static const pj_str_t *pjsip_name_addr_get_scheme( const pjsip_name_addr * );
 
149
static void *pjsip_get_uri( pjsip_uri *uri );
 
150
static void *pjsip_name_addr_get_uri( pjsip_name_addr *name );
 
151
 
 
152
static pj_str_t sip_str = { "sip", 3 };
 
153
static pj_str_t sips_str = { "sips", 4 };
 
154
 
 
155
static pjsip_name_addr* pjsip_name_addr_clone( pj_pool_t *pool, 
 
156
                                               const pjsip_name_addr *rhs);
 
157
static pj_ssize_t pjsip_name_addr_print(pjsip_uri_context_e context,
 
158
                                        const pjsip_name_addr *name, 
 
159
                                        char *buf, pj_size_t size);
 
160
static int pjsip_name_addr_compare(  pjsip_uri_context_e context,
 
161
                                     const pjsip_name_addr *naddr1,
 
162
                                     const pjsip_name_addr *naddr2);
 
163
static pj_ssize_t pjsip_url_print(  pjsip_uri_context_e context,
 
164
                                    const pjsip_sip_uri *url, 
 
165
                                    char *buf, pj_size_t size);
 
166
static int pjsip_url_compare( pjsip_uri_context_e context,
 
167
                              const pjsip_sip_uri *url1, 
 
168
                              const pjsip_sip_uri *url2);
 
169
static pjsip_sip_uri* pjsip_url_clone(pj_pool_t *pool, 
 
170
                                      const pjsip_sip_uri *rhs);
 
171
 
 
172
typedef const pj_str_t* (*P_GET_SCHEME)(const void*);
 
173
typedef void*           (*P_GET_URI)(void*);
 
174
typedef pj_ssize_t      (*P_PRINT_URI)(pjsip_uri_context_e,const void *,
 
175
                                       char*,pj_size_t);
 
176
typedef int             (*P_CMP_URI)(pjsip_uri_context_e, const void*, 
 
177
                                     const void*);
 
178
typedef void*           (*P_CLONE)(pj_pool_t*, const void*);
 
179
 
 
180
 
 
181
static pjsip_uri_vptr sip_url_vptr = 
 
182
{
 
183
    (P_GET_SCHEME)      &pjsip_url_get_scheme,
 
184
    (P_GET_URI)         &pjsip_get_uri,
 
185
    (P_PRINT_URI)       &pjsip_url_print,
 
186
    (P_CMP_URI)         &pjsip_url_compare,
 
187
    (P_CLONE)           &pjsip_url_clone
 
188
};
 
189
 
 
190
static pjsip_uri_vptr sips_url_vptr = 
 
191
{
 
192
    (P_GET_SCHEME)      &pjsips_url_get_scheme,
 
193
    (P_GET_URI)         &pjsip_get_uri,
 
194
    (P_PRINT_URI)       &pjsip_url_print,
 
195
    (P_CMP_URI)         &pjsip_url_compare,
 
196
    (P_CLONE)           &pjsip_url_clone
 
197
};
 
198
 
 
199
static pjsip_uri_vptr name_addr_vptr = 
 
200
{
 
201
    (P_GET_SCHEME)      &pjsip_name_addr_get_scheme,
 
202
    (P_GET_URI)         &pjsip_name_addr_get_uri,
 
203
    (P_PRINT_URI)       &pjsip_name_addr_print,
 
204
    (P_CMP_URI)         &pjsip_name_addr_compare,
 
205
    (P_CLONE)           &pjsip_name_addr_clone
 
206
};
 
207
 
 
208
static const pj_str_t *pjsip_url_get_scheme(const pjsip_sip_uri *url)
 
209
{
 
210
    PJ_UNUSED_ARG(url);
 
211
    return &sip_str;
 
212
}
 
213
 
 
214
static const pj_str_t *pjsips_url_get_scheme(const pjsip_sip_uri *url)
 
215
{
 
216
    PJ_UNUSED_ARG(url);
 
217
    return &sips_str;
 
218
}
 
219
 
 
220
static void *pjsip_get_uri( pjsip_uri *uri )
 
221
{
 
222
    return uri;
 
223
}
 
224
 
 
225
static void *pjsip_name_addr_get_uri( pjsip_name_addr *name )
 
226
{
 
227
    return pjsip_uri_get_uri(name->uri);
 
228
}
 
229
 
 
230
PJ_DEF(void) pjsip_sip_uri_set_secure( pjsip_sip_uri *url, 
 
231
                                       pj_bool_t secure )
 
232
{
 
233
    url->vptr = secure ? &sips_url_vptr : &sip_url_vptr;
 
234
}
 
235
 
 
236
PJ_DEF(void) pjsip_sip_uri_init(pjsip_sip_uri *url, pj_bool_t secure)
 
237
{
 
238
    pj_bzero(url, sizeof(*url));
 
239
    url->ttl_param = -1;
 
240
    pjsip_sip_uri_set_secure(url, secure);
 
241
    pj_list_init(&url->other_param);
 
242
    pj_list_init(&url->header_param);
 
243
}
 
244
 
 
245
PJ_DEF(pjsip_sip_uri*) pjsip_sip_uri_create( pj_pool_t *pool, 
 
246
                                             pj_bool_t secure )
 
247
{
 
248
    pjsip_sip_uri *url = PJ_POOL_ALLOC_T(pool, pjsip_sip_uri);
 
249
    pjsip_sip_uri_init(url, secure);
 
250
    return url;
 
251
}
 
252
 
 
253
static pj_ssize_t pjsip_url_print(  pjsip_uri_context_e context,
 
254
                                    const pjsip_sip_uri *url, 
 
255
                                    char *buf, pj_size_t size)
 
256
{
 
257
    int printed;
 
258
    char *startbuf = buf;
 
259
    char *endbuf = buf+size;
 
260
    const pj_str_t *scheme;
 
261
    const pjsip_parser_const_t *pc = pjsip_parser_const();
 
262
 
 
263
    *buf = '\0';
 
264
 
 
265
    /* Print scheme ("sip:" or "sips:") */
 
266
    scheme = pjsip_uri_get_scheme(url);
 
267
    copy_advance_check(buf, *scheme);
 
268
    *buf++ = ':';
 
269
 
 
270
    /* Print "user:password@", if any. */
 
271
    if (url->user.slen) {
 
272
        const pj_cis_t *spec = pjsip_cfg()->endpt.allow_tx_hash_in_uri ?
 
273
                                &pc->pjsip_USER_SPEC_LENIENT :
 
274
                                &pc->pjsip_USER_SPEC;
 
275
        copy_advance_escape(buf, url->user, *spec);
 
276
        if (url->passwd.slen) {
 
277
            *buf++ = ':';
 
278
            copy_advance_escape(buf, url->passwd, pc->pjsip_PASSWD_SPEC);
 
279
        }
 
280
 
 
281
        *buf++ = '@';
 
282
    }
 
283
 
 
284
    /* Print host. */
 
285
    pj_assert(url->host.slen != 0);
 
286
    /* Detect IPv6 IP address */
 
287
    if (pj_memchr(url->host.ptr, ':', url->host.slen)) {
 
288
        copy_advance_pair_quote_cond(buf, "", 0, url->host, '[', ']');
 
289
    } else {
 
290
        copy_advance_check(buf, url->host);
 
291
    }
 
292
 
 
293
    /* Only print port if it is explicitly specified. 
 
294
     * Port is not allowed in To and From header, see Table 1 in
 
295
     * RFC 3261 Section 19.1.1
 
296
     */
 
297
    /* Note: ticket #1141 adds run-time setting to allow port number to
 
298
     * appear in From/To header. Default is still false.
 
299
     */
 
300
    if (url->port &&
 
301
        (context != PJSIP_URI_IN_FROMTO_HDR ||
 
302
         pjsip_cfg()->endpt.allow_port_in_fromto_hdr))
 
303
    {
 
304
        if (endbuf - buf < 10)
 
305
            return -1;
 
306
 
 
307
        *buf++ = ':';
 
308
        printed = pj_utoa(url->port, buf);
 
309
        buf += printed;
 
310
    }
 
311
 
 
312
    /* User param is allowed in all contexes */
 
313
    copy_advance_pair_check(buf, ";user=", 6, url->user_param);
 
314
 
 
315
    /* Method param is only allowed in external/other context. */
 
316
    if (context == PJSIP_URI_IN_OTHER) {
 
317
        copy_advance_pair_escape(buf, ";method=", 8, url->method_param, 
 
318
                                 pc->pjsip_PARAM_CHAR_SPEC);
 
319
    }
 
320
 
 
321
    /* Transport is not allowed in From/To header. */
 
322
    if (context != PJSIP_URI_IN_FROMTO_HDR) {
 
323
        copy_advance_pair_escape(buf, ";transport=", 11, url->transport_param,
 
324
                                 pc->pjsip_PARAM_CHAR_SPEC);
 
325
    }
 
326
 
 
327
    /* TTL param is not allowed in From, To, Route, and Record-Route header. */
 
328
    if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR &&
 
329
        context != PJSIP_URI_IN_ROUTING_HDR) 
 
330
    {
 
331
        if (endbuf - buf < 15)
 
332
            return -1;
 
333
        pj_memcpy(buf, ";ttl=", 5);
 
334
        printed = pj_utoa(url->ttl_param, buf+5);
 
335
        buf += printed + 5;
 
336
    }
 
337
 
 
338
    /* maddr param is not allowed in From and To header. */
 
339
    if (context != PJSIP_URI_IN_FROMTO_HDR && url->maddr_param.slen) {
 
340
        /* Detect IPv6 IP address */
 
341
        if (pj_memchr(url->maddr_param.ptr, ':', url->maddr_param.slen)) {
 
342
            copy_advance_pair_quote_cond(buf, ";maddr=", 7, url->maddr_param,
 
343
                                         '[', ']');
 
344
        } else {
 
345
            copy_advance_pair_escape(buf, ";maddr=", 7, url->maddr_param,
 
346
                                     pc->pjsip_PARAM_CHAR_SPEC);
 
347
        }
 
348
    }
 
349
 
 
350
    /* lr param is not allowed in From, To, and Contact header. */
 
351
    if (url->lr_param && context != PJSIP_URI_IN_FROMTO_HDR &&
 
352
        context != PJSIP_URI_IN_CONTACT_HDR) 
 
353
    {
 
354
        pj_str_t lr = { ";lr", 3 };
 
355
        if (endbuf - buf < 3)
 
356
            return -1;
 
357
        copy_advance_check(buf, lr);
 
358
    }
 
359
 
 
360
    /* Other param. */
 
361
    printed = pjsip_param_print_on(&url->other_param, buf, endbuf-buf, 
 
362
                                   &pc->pjsip_PARAM_CHAR_SPEC, 
 
363
                                   &pc->pjsip_PARAM_CHAR_SPEC, ';');
 
364
    if (printed < 0)
 
365
        return -1;
 
366
    buf += printed;
 
367
 
 
368
    /* Header param. 
 
369
     * Header param is only allowed in these contexts:
 
370
     *  - PJSIP_URI_IN_CONTACT_HDR
 
371
     *  - PJSIP_URI_IN_OTHER
 
372
     */
 
373
    if (context == PJSIP_URI_IN_CONTACT_HDR || context == PJSIP_URI_IN_OTHER) {
 
374
        printed = pjsip_param_print_on(&url->header_param, buf, endbuf-buf,
 
375
                                       &pc->pjsip_HDR_CHAR_SPEC, 
 
376
                                       &pc->pjsip_HDR_CHAR_SPEC, '?');
 
377
        if (printed < 0)
 
378
            return -1;
 
379
        buf += printed;
 
380
    }
 
381
 
 
382
    *buf = '\0';
 
383
    return buf-startbuf;
 
384
}
 
385
 
 
386
static pj_status_t pjsip_url_compare( pjsip_uri_context_e context,
 
387
                                      const pjsip_sip_uri *url1, 
 
388
                                      const pjsip_sip_uri *url2)
 
389
{
 
390
    const pjsip_param *p1;
 
391
 
 
392
    /*
 
393
     * Compare two SIP URL's according to Section 19.1.4 of RFC 3261.
 
394
     */
 
395
 
 
396
    /* SIP and SIPS URI are never equivalent. 
 
397
     * Note: just compare the vptr to avoid string comparison. 
 
398
     *       Pretty neat huh!!
 
399
     */
 
400
    if (url1->vptr != url2->vptr)
 
401
        return PJSIP_ECMPSCHEME;
 
402
 
 
403
    /* Comparison of the userinfo of SIP and SIPS URIs is case-sensitive. 
 
404
     * This includes userinfo containing passwords or formatted as 
 
405
     * telephone-subscribers.
 
406
     */
 
407
    if (pj_strcmp(&url1->user, &url2->user) != 0)
 
408
        return PJSIP_ECMPUSER;
 
409
    if (pj_strcmp(&url1->passwd, &url2->passwd) != 0)
 
410
        return PJSIP_ECMPPASSWD;
 
411
    
 
412
    /* Comparison of all other components of the URI is
 
413
     * case-insensitive unless explicitly defined otherwise.
 
414
     */
 
415
 
 
416
    /* The ordering of parameters and header fields is not significant 
 
417
     * in comparing SIP and SIPS URIs.
 
418
     */
 
419
 
 
420
    /* Characters other than those in the reserved set (see RFC 2396 [5])
 
421
     * are equivalent to their encoding.
 
422
     */
 
423
 
 
424
    /* An IP address that is the result of a DNS lookup of a host name 
 
425
     * does not match that host name.
 
426
     */
 
427
    if (pj_stricmp(&url1->host, &url2->host) != 0)
 
428
        return PJSIP_ECMPHOST;
 
429
 
 
430
    /* A URI omitting any component with a default value will not match a URI
 
431
     * explicitly containing that component with its default value. 
 
432
     * For instance, a URI omitting the optional port component will not match
 
433
     * a URI explicitly declaring port 5060. 
 
434
     * The same is true for the transport-parameter, ttl-parameter, 
 
435
     * user-parameter, and method components.
 
436
     */
 
437
 
 
438
    /* Port is not allowed in To and From header.
 
439
     */
 
440
    if (context != PJSIP_URI_IN_FROMTO_HDR) {
 
441
        if (url1->port != url2->port)
 
442
            return PJSIP_ECMPPORT;
 
443
    }
 
444
    /* Transport is not allowed in From/To header. */
 
445
    if (context != PJSIP_URI_IN_FROMTO_HDR) {
 
446
        if (pj_stricmp(&url1->transport_param, &url2->transport_param) != 0)
 
447
            return PJSIP_ECMPTRANSPORTPRM;
 
448
    }
 
449
    /* TTL param is not allowed in From, To, Route, and Record-Route header. */
 
450
    if (context != PJSIP_URI_IN_FROMTO_HDR &&
 
451
        context != PJSIP_URI_IN_ROUTING_HDR)
 
452
    {
 
453
        if (url1->ttl_param != url2->ttl_param)
 
454
            return PJSIP_ECMPTTLPARAM;
 
455
    }
 
456
    /* User param is allowed in all contexes */
 
457
    if (pj_stricmp(&url1->user_param, &url2->user_param) != 0)
 
458
        return PJSIP_ECMPUSERPARAM;
 
459
    /* Method param is only allowed in external/other context. */
 
460
    if (context == PJSIP_URI_IN_OTHER) {
 
461
        if (pj_stricmp(&url1->method_param, &url2->method_param) != 0)
 
462
            return PJSIP_ECMPMETHODPARAM;
 
463
    }
 
464
    /* maddr param is not allowed in From and To header. */
 
465
    if (context != PJSIP_URI_IN_FROMTO_HDR) {
 
466
        if (pj_stricmp(&url1->maddr_param, &url2->maddr_param) != 0)
 
467
            return PJSIP_ECMPMADDRPARAM;
 
468
    }
 
469
 
 
470
    /* lr parameter is ignored (?) */
 
471
    /* lr param is not allowed in From, To, and Contact header. */
 
472
 
 
473
 
 
474
    /* All other uri-parameters appearing in only one URI are ignored when 
 
475
     * comparing the URIs.
 
476
     */
 
477
    if (pjsip_param_cmp(&url1->other_param, &url2->other_param, 1)!=0)
 
478
        return PJSIP_ECMPOTHERPARAM;
 
479
 
 
480
    /* URI header components are never ignored. Any present header component
 
481
     * MUST be present in both URIs and match for the URIs to match. 
 
482
     * The matching rules are defined for each header field in Section 20.
 
483
     */
 
484
    p1 = url1->header_param.next;
 
485
    while (p1 != &url1->header_param) {
 
486
        const pjsip_param *p2;
 
487
        p2 = pjsip_param_find(&url2->header_param, &p1->name);
 
488
        if (p2) {
 
489
            /* It seems too much to compare two header params according to
 
490
             * the rule of each header. We'll just compare them string to
 
491
             * string..
 
492
             */
 
493
            if (pj_stricmp(&p1->value, &p2->value) != 0)
 
494
                return PJSIP_ECMPHEADERPARAM;
 
495
        } else {
 
496
            return PJSIP_ECMPHEADERPARAM;
 
497
        }
 
498
        p1 = p1->next;
 
499
    }
 
500
 
 
501
    /* Equal!! Pheuww.. */
 
502
    return PJ_SUCCESS;
 
503
}
 
504
 
 
505
 
 
506
PJ_DEF(void) pjsip_sip_uri_assign(pj_pool_t *pool, pjsip_sip_uri *url, 
 
507
                                  const pjsip_sip_uri *rhs)
 
508
{
 
509
    pj_strdup( pool, &url->user, &rhs->user);
 
510
    pj_strdup( pool, &url->passwd, &rhs->passwd);
 
511
    pj_strdup( pool, &url->host, &rhs->host);
 
512
    url->port = rhs->port;
 
513
    pj_strdup( pool, &url->user_param, &rhs->user_param);
 
514
    pj_strdup( pool, &url->method_param, &rhs->method_param);
 
515
    pj_strdup( pool, &url->transport_param, &rhs->transport_param);
 
516
    url->ttl_param = rhs->ttl_param;
 
517
    pj_strdup( pool, &url->maddr_param, &rhs->maddr_param);
 
518
    pjsip_param_clone(pool, &url->other_param, &rhs->other_param);
 
519
    pjsip_param_clone(pool, &url->header_param, &rhs->header_param);
 
520
    url->lr_param = rhs->lr_param;
 
521
}
 
522
 
 
523
static pjsip_sip_uri* pjsip_url_clone(pj_pool_t *pool, const pjsip_sip_uri *rhs)
 
524
{
 
525
    pjsip_sip_uri *url = PJ_POOL_ALLOC_T(pool, pjsip_sip_uri);
 
526
    if (!url)
 
527
        return NULL;
 
528
 
 
529
    pjsip_sip_uri_init(url, IS_SIPS(rhs));
 
530
    pjsip_sip_uri_assign(pool, url, rhs);
 
531
    return url;
 
532
}
 
533
 
 
534
static const pj_str_t *pjsip_name_addr_get_scheme(const pjsip_name_addr *name)
 
535
{
 
536
    pj_assert(name->uri != NULL);
 
537
    return pjsip_uri_get_scheme(name->uri);
 
538
}
 
539
 
 
540
PJ_DEF(void) pjsip_name_addr_init(pjsip_name_addr *name)
 
541
{
 
542
    name->vptr = &name_addr_vptr;
 
543
    name->uri = NULL;
 
544
    name->display.slen = 0;
 
545
    name->display.ptr = NULL;
 
546
}
 
547
 
 
548
PJ_DEF(pjsip_name_addr*) pjsip_name_addr_create(pj_pool_t *pool)
 
549
{
 
550
    pjsip_name_addr *name_addr = PJ_POOL_ALLOC_T(pool, pjsip_name_addr);
 
551
    pjsip_name_addr_init(name_addr);
 
552
    return name_addr;
 
553
}
 
554
 
 
555
static pj_ssize_t pjsip_name_addr_print(pjsip_uri_context_e context,
 
556
                                        const pjsip_name_addr *name, 
 
557
                                        char *buf, pj_size_t size)
 
558
{
 
559
    int printed;
 
560
    char *startbuf = buf;
 
561
    char *endbuf = buf + size;
 
562
    pjsip_uri *uri;
 
563
 
 
564
    uri = (pjsip_uri*) pjsip_uri_get_uri(name->uri);
 
565
    pj_assert(uri != NULL);
 
566
 
 
567
    if (context != PJSIP_URI_IN_REQ_URI) {
 
568
        if (name->display.slen) {
 
569
            if (endbuf-buf < 8) return -1;
 
570
            *buf++ = '"';
 
571
            copy_advance(buf, name->display);
 
572
            *buf++ = '"';
 
573
            *buf++ = ' ';
 
574
        }
 
575
        *buf++ = '<';
 
576
    }
 
577
 
 
578
    printed = pjsip_uri_print(context,uri, buf, size-(buf-startbuf));
 
579
    if (printed < 1)
 
580
        return -1;
 
581
    buf += printed;
 
582
 
 
583
    if (context != PJSIP_URI_IN_REQ_URI) {
 
584
        *buf++ = '>';
 
585
    }
 
586
 
 
587
    *buf = '\0';
 
588
    return buf-startbuf;
 
589
}
 
590
 
 
591
PJ_DEF(void) pjsip_name_addr_assign(pj_pool_t *pool, pjsip_name_addr *dst,
 
592
                                    const pjsip_name_addr *src)
 
593
{
 
594
    pj_strdup( pool, &dst->display, &src->display);
 
595
    dst->uri = (pjsip_uri*) pjsip_uri_clone(pool, src->uri);
 
596
}
 
597
 
 
598
static pjsip_name_addr* pjsip_name_addr_clone( pj_pool_t *pool, 
 
599
                                               const pjsip_name_addr *rhs)
 
600
{
 
601
    pjsip_name_addr *addr = PJ_POOL_ALLOC_T(pool, pjsip_name_addr);
 
602
    if (!addr)
 
603
        return NULL;
 
604
 
 
605
    pjsip_name_addr_init(addr);
 
606
    pjsip_name_addr_assign(pool, addr, rhs);
 
607
    return addr;
 
608
}
 
609
 
 
610
static int pjsip_name_addr_compare(  pjsip_uri_context_e context,
 
611
                                     const pjsip_name_addr *naddr1,
 
612
                                     const pjsip_name_addr *naddr2)
 
613
{
 
614
    int d;
 
615
 
 
616
    /* Check that naddr2 is also a name_addr */
 
617
    if (naddr1->vptr != naddr2->vptr)
 
618
        return -1;
 
619
 
 
620
    /* I'm not sure whether display name is included in the comparison. */
 
621
    if (pj_strcmp(&naddr1->display, &naddr2->display) != 0) {
 
622
        return -1;
 
623
    }
 
624
 
 
625
    pj_assert( naddr1->uri != NULL );
 
626
    pj_assert( naddr2->uri != NULL );
 
627
 
 
628
    /* Compare name-addr as URL */
 
629
    d = pjsip_uri_cmp( context, naddr1->uri, naddr2->uri);
 
630
    if (d)
 
631
        return d;
 
632
 
 
633
    return 0;
 
634
}
 
635
 
 
636
///////////////////////////////////////////////////////////////////////////////
 
637
 
 
638
static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri*);
 
639
static void *other_uri_get_uri( pjsip_other_uri*);
 
640
static pj_ssize_t other_uri_print( pjsip_uri_context_e context,
 
641
                                   const pjsip_other_uri *url, 
 
642
                                   char *buf, pj_size_t size);
 
643
static int other_uri_cmp( pjsip_uri_context_e context,
 
644
                          const pjsip_other_uri *url1, 
 
645
                          const pjsip_other_uri *url2);
 
646
static pjsip_other_uri* other_uri_clone( pj_pool_t *pool, 
 
647
                                         const pjsip_other_uri *rhs);
 
648
 
 
649
static pjsip_uri_vptr other_uri_vptr = 
 
650
{
 
651
    (P_GET_SCHEME)  &other_uri_get_scheme,
 
652
    (P_GET_URI)     &other_uri_get_uri,
 
653
    (P_PRINT_URI)   &other_uri_print,
 
654
    (P_CMP_URI)     &other_uri_cmp,
 
655
    (P_CLONE)       &other_uri_clone
 
656
};
 
657
 
 
658
 
 
659
PJ_DEF(pjsip_other_uri*) pjsip_other_uri_create(pj_pool_t *pool) 
 
660
{
 
661
    pjsip_other_uri *uri = PJ_POOL_ZALLOC_T(pool, pjsip_other_uri);
 
662
    uri->vptr = &other_uri_vptr;
 
663
    return uri;
 
664
}
 
665
 
 
666
static const pj_str_t *other_uri_get_scheme( const pjsip_other_uri *uri )
 
667
{
 
668
        return &uri->scheme;
 
669
}
 
670
 
 
671
static void *other_uri_get_uri( pjsip_other_uri *uri )
 
672
{
 
673
    return uri;
 
674
}
 
675
 
 
676
static pj_ssize_t other_uri_print(pjsip_uri_context_e context,
 
677
                                  const pjsip_other_uri *uri, 
 
678
                                  char *buf, pj_size_t size)
 
679
{
 
680
    char *startbuf = buf;
 
681
    char *endbuf = buf + size;
 
682
    
 
683
    PJ_UNUSED_ARG(context);
 
684
    
 
685
    if (uri->scheme.slen + uri->content.slen + 1 > (int)size)
 
686
        return -1;
 
687
 
 
688
    /* Print scheme. */
 
689
    copy_advance(buf, uri->scheme);
 
690
    *buf++ = ':';
 
691
    
 
692
    /* Print content. */
 
693
    copy_advance(buf, uri->content);
 
694
    
 
695
    return (buf - startbuf);
 
696
}
 
697
 
 
698
static int other_uri_cmp(pjsip_uri_context_e context,
 
699
                         const pjsip_other_uri *uri1,
 
700
                         const pjsip_other_uri *uri2)
 
701
{
 
702
    PJ_UNUSED_ARG(context);
 
703
 
 
704
    /* Check that uri2 is also an other_uri */
 
705
    if (uri1->vptr != uri2->vptr)
 
706
        return -1;
 
707
    
 
708
    /* Scheme must match. */
 
709
    if (pj_stricmp(&uri1->scheme, &uri2->scheme) != 0) {
 
710
        return PJSIP_ECMPSCHEME;
 
711
    }
 
712
    
 
713
    /* Content must match. */
 
714
    if(pj_stricmp(&uri1->content, &uri2->content) != 0) {
 
715
        return -1;
 
716
    }
 
717
    
 
718
    /* Equal. */
 
719
    return 0;
 
720
}
 
721
 
 
722
/* Clone *: URI */
 
723
static pjsip_other_uri* other_uri_clone(pj_pool_t *pool, 
 
724
                                        const pjsip_other_uri *rhs) 
 
725
{
 
726
    pjsip_other_uri *uri = pjsip_other_uri_create(pool);
 
727
    pj_strdup(pool, &uri->scheme, &rhs->scheme);
 
728
    pj_strdup(pool, &uri->content, &rhs->content);
 
729
 
 
730
    return uri;
 
731
}
 
732