~noskcaj/ubuntu/saucy/sflphone/merge-1.2.3-2

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/pjlib/src/pj/sock_common.c

  • Committer: Jackson Doak
  • Date: 2013-07-10 21:04:46 UTC
  • mfrom: (20.1.3 sid)
  • Revision ID: noskcaj@ubuntu.com-20130710210446-y8f587vza807icr9
Properly merged from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: sock_common.c 3841 2011-10-24 09:28:13Z ming $ */
 
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 <pj/sock.h>
 
21
#include <pj/assert.h>
 
22
#include <pj/ctype.h>
 
23
#include <pj/errno.h>
 
24
#include <pj/ip_helper.h>
 
25
#include <pj/os.h>
 
26
#include <pj/addr_resolv.h>
 
27
#include <pj/string.h>
 
28
#include <pj/compat/socket.h>
 
29
 
 
30
#if 0
 
31
    /* Enable some tracing */
 
32
    #include <pj/log.h>
 
33
    #define THIS_FILE   "sock_common.c"
 
34
    #define TRACE_(arg) PJ_LOG(4,arg)
 
35
#else
 
36
    #define TRACE_(arg)
 
37
#endif
 
38
 
 
39
 
 
40
/*
 
41
 * Convert address string with numbers and dots to binary IP address.
 
42
 */
 
43
PJ_DEF(pj_in_addr) pj_inet_addr(const pj_str_t *cp)
 
44
{
 
45
    pj_in_addr addr;
 
46
 
 
47
    pj_inet_aton(cp, &addr);
 
48
    return addr;
 
49
}
 
50
 
 
51
/*
 
52
 * Convert address string with numbers and dots to binary IP address.
 
53
 */
 
54
PJ_DEF(pj_in_addr) pj_inet_addr2(const char *cp)
 
55
{
 
56
    pj_str_t str = pj_str((char*)cp);
 
57
    return pj_inet_addr(&str);
 
58
}
 
59
 
 
60
/*
 
61
 * Get text representation.
 
62
 */
 
63
PJ_DEF(char*) pj_inet_ntop2( int af, const void *src,
 
64
                             char *dst, int size)
 
65
{
 
66
    pj_status_t status;
 
67
 
 
68
    status = pj_inet_ntop(af, src, dst, size);
 
69
    return (status==PJ_SUCCESS)? dst : NULL;
 
70
}
 
71
 
 
72
/*
 
73
 * Print socket address.
 
74
 */
 
75
PJ_DEF(char*) pj_sockaddr_print( const pj_sockaddr_t *addr,
 
76
                                 char *buf, int size,
 
77
                                 unsigned flags)
 
78
{
 
79
    enum {
 
80
        WITH_PORT = 1,
 
81
        WITH_BRACKETS = 2
 
82
    };
 
83
 
 
84
    char txt[PJ_INET6_ADDRSTRLEN];
 
85
    char port[32];
 
86
    const pj_addr_hdr *h = (const pj_addr_hdr*)addr;
 
87
    char *bquote, *equote;
 
88
    pj_status_t status;
 
89
 
 
90
    status = pj_inet_ntop(h->sa_family, pj_sockaddr_get_addr(addr),
 
91
                          txt, sizeof(txt));
 
92
    if (status != PJ_SUCCESS)
 
93
        return "";
 
94
 
 
95
    if (h->sa_family != PJ_AF_INET6 || (flags & WITH_BRACKETS)==0) {
 
96
        bquote = ""; equote = "";
 
97
    } else {
 
98
        bquote = "["; equote = "]";
 
99
    }
 
100
 
 
101
    if (flags & WITH_PORT) {
 
102
        pj_ansi_snprintf(port, sizeof(port), ":%d",
 
103
                         pj_sockaddr_get_port(addr));
 
104
    } else {
 
105
        port[0] = '\0';
 
106
    }
 
107
 
 
108
    pj_ansi_snprintf(buf, size, "%s%s%s%s",
 
109
                     bquote, txt, equote, port);
 
110
 
 
111
    return buf;
 
112
}
 
113
 
 
114
/*
 
115
 * Set the IP address of an IP socket address from string address,
 
116
 * with resolving the host if necessary. The string address may be in a
 
117
 * standard numbers and dots notation or may be a hostname. If hostname
 
118
 * is specified, then the function will resolve the host into the IP
 
119
 * address.
 
120
 */
 
121
PJ_DEF(pj_status_t) pj_sockaddr_in_set_str_addr( pj_sockaddr_in *addr,
 
122
                                                 const pj_str_t *str_addr)
 
123
{
 
124
    PJ_CHECK_STACK();
 
125
 
 
126
    PJ_ASSERT_RETURN(!str_addr || str_addr->slen < PJ_MAX_HOSTNAME,
 
127
                     (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
 
128
 
 
129
    PJ_SOCKADDR_RESET_LEN(addr);
 
130
    addr->sin_family = AF_INET;
 
131
    pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
 
132
 
 
133
    if (str_addr && str_addr->slen) {
 
134
        addr->sin_addr = pj_inet_addr(str_addr);
 
135
        if (addr->sin_addr.s_addr == PJ_INADDR_NONE) {
 
136
            pj_hostent he;
 
137
            pj_status_t rc;
 
138
 
 
139
            rc = pj_gethostbyname(str_addr, &he);
 
140
            if (rc == 0) {
 
141
                addr->sin_addr.s_addr = *(pj_uint32_t*)he.h_addr;
 
142
            } else {
 
143
                addr->sin_addr.s_addr = PJ_INADDR_NONE;
 
144
                return rc;
 
145
            }
 
146
        }
 
147
 
 
148
    } else {
 
149
        addr->sin_addr.s_addr = 0;
 
150
    }
 
151
 
 
152
    return PJ_SUCCESS;
 
153
}
 
154
 
 
155
/* Set address from a name */
 
156
PJ_DEF(pj_status_t) pj_sockaddr_set_str_addr(int af,
 
157
                                             pj_sockaddr *addr,
 
158
                                             const pj_str_t *str_addr)
 
159
{
 
160
    pj_status_t status;
 
161
 
 
162
    if (af == PJ_AF_INET) {
 
163
        return pj_sockaddr_in_set_str_addr(&addr->ipv4, str_addr);
 
164
    }
 
165
 
 
166
    PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
 
167
 
 
168
    /* IPv6 specific */
 
169
 
 
170
    addr->ipv6.sin6_family = PJ_AF_INET6;
 
171
    PJ_SOCKADDR_RESET_LEN(addr);
 
172
 
 
173
    if (str_addr && str_addr->slen) {
 
174
        status = pj_inet_pton(PJ_AF_INET6, str_addr, &addr->ipv6.sin6_addr);
 
175
        if (status != PJ_SUCCESS) {
 
176
            pj_addrinfo ai;
 
177
            unsigned count = 1;
 
178
 
 
179
            status = pj_getaddrinfo(PJ_AF_INET6, str_addr, &count, &ai);
 
180
            if (status==PJ_SUCCESS) {
 
181
                pj_memcpy(&addr->ipv6.sin6_addr, &ai.ai_addr.ipv6.sin6_addr,
 
182
                          sizeof(pj_sockaddr_in6));
 
183
            }
 
184
        }
 
185
    } else {
 
186
        status = PJ_SUCCESS;
 
187
    }
 
188
 
 
189
    return status;
 
190
}
 
191
 
 
192
/*
 
193
 * Set the IP address and port of an IP socket address.
 
194
 * The string address may be in a standard numbers and dots notation or
 
195
 * may be a hostname. If hostname is specified, then the function will
 
196
 * resolve the host into the IP address.
 
197
 */
 
198
PJ_DEF(pj_status_t) pj_sockaddr_in_init( pj_sockaddr_in *addr,
 
199
                                         const pj_str_t *str_addr,
 
200
                                         pj_uint16_t port)
 
201
{
 
202
    PJ_ASSERT_RETURN(addr, (addr->sin_addr.s_addr=PJ_INADDR_NONE, PJ_EINVAL));
 
203
 
 
204
    PJ_SOCKADDR_RESET_LEN(addr);
 
205
    addr->sin_family = PJ_AF_INET;
 
206
    pj_bzero(addr->sin_zero, sizeof(addr->sin_zero));
 
207
    pj_sockaddr_in_set_port(addr, port);
 
208
    return pj_sockaddr_in_set_str_addr(addr, str_addr);
 
209
}
 
210
 
 
211
/*
 
212
 * Initialize IP socket address based on the address and port info.
 
213
 */
 
214
PJ_DEF(pj_status_t) pj_sockaddr_init(int af,
 
215
                                     pj_sockaddr *addr,
 
216
                                     const pj_str_t *cp,
 
217
                                     pj_uint16_t port)
 
218
{
 
219
    pj_status_t status;
 
220
 
 
221
    if (af == PJ_AF_INET) {
 
222
        return pj_sockaddr_in_init(&addr->ipv4, cp, port);
 
223
    }
 
224
 
 
225
    /* IPv6 specific */
 
226
    PJ_ASSERT_RETURN(af==PJ_AF_INET6, PJ_EAFNOTSUP);
 
227
 
 
228
    pj_bzero(addr, sizeof(pj_sockaddr_in6));
 
229
    addr->addr.sa_family = PJ_AF_INET6;
 
230
 
 
231
    status = pj_sockaddr_set_str_addr(af, addr, cp);
 
232
    if (status != PJ_SUCCESS)
 
233
        return status;
 
234
 
 
235
    addr->ipv6.sin6_port = pj_htons(port);
 
236
    return PJ_SUCCESS;
 
237
}
 
238
 
 
239
/*
 
240
 * Compare two socket addresses.
 
241
 */
 
242
PJ_DEF(int) pj_sockaddr_cmp( const pj_sockaddr_t *addr1,
 
243
                             const pj_sockaddr_t *addr2)
 
244
{
 
245
    const pj_sockaddr *a1 = (const pj_sockaddr*) addr1;
 
246
    const pj_sockaddr *a2 = (const pj_sockaddr*) addr2;
 
247
    int port1, port2;
 
248
    int result;
 
249
 
 
250
    /* Compare address family */
 
251
    if (a1->addr.sa_family < a2->addr.sa_family)
 
252
        return -1;
 
253
    else if (a1->addr.sa_family > a2->addr.sa_family)
 
254
        return 1;
 
255
 
 
256
    /* Compare addresses */
 
257
    result = pj_memcmp(pj_sockaddr_get_addr(a1),
 
258
                       pj_sockaddr_get_addr(a2),
 
259
                       pj_sockaddr_get_addr_len(a1));
 
260
    if (result != 0)
 
261
        return result;
 
262
 
 
263
    /* Compare port number */
 
264
    port1 = pj_sockaddr_get_port(a1);
 
265
    port2 = pj_sockaddr_get_port(a2);
 
266
 
 
267
    if (port1 < port2)
 
268
        return -1;
 
269
    else if (port1 > port2)
 
270
        return 1;
 
271
 
 
272
    /* TODO:
 
273
     *  Do we need to compare flow label and scope id in IPv6?
 
274
     */
 
275
 
 
276
    /* Looks equal */
 
277
    return 0;
 
278
}
 
279
 
 
280
/*
 
281
 * Get first IP address associated with the hostname.
 
282
 */
 
283
PJ_DEF(pj_in_addr) pj_gethostaddr(void)
 
284
{
 
285
    pj_sockaddr_in addr;
 
286
    const pj_str_t *hostname = pj_gethostname();
 
287
 
 
288
    pj_sockaddr_in_set_str_addr(&addr, hostname);
 
289
    return addr.sin_addr;
 
290
}
 
291
 
 
292
/*
 
293
 * Get port number of a pj_sockaddr_in
 
294
 */
 
295
PJ_DEF(pj_uint16_t) pj_sockaddr_in_get_port(const pj_sockaddr_in *addr)
 
296
{
 
297
    return pj_ntohs(addr->sin_port);
 
298
}
 
299
 
 
300
/*
 
301
 * Get the address part
 
302
 */
 
303
PJ_DEF(void*) pj_sockaddr_get_addr(const pj_sockaddr_t *addr)
 
304
{
 
305
    const pj_sockaddr *a = (const pj_sockaddr*)addr;
 
306
 
 
307
    PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
 
308
                     a->addr.sa_family == PJ_AF_INET6, NULL);
 
309
 
 
310
    if (a->addr.sa_family == PJ_AF_INET6)
 
311
        return (void*) &a->ipv6.sin6_addr;
 
312
    else
 
313
        return (void*) &a->ipv4.sin_addr;
 
314
}
 
315
 
 
316
/*
 
317
 * Check if sockaddr contains a non-zero address
 
318
 */
 
319
PJ_DEF(pj_bool_t) pj_sockaddr_has_addr(const pj_sockaddr_t *addr)
 
320
{
 
321
    const pj_sockaddr *a = (const pj_sockaddr*)addr;
 
322
 
 
323
    /* It's probably not wise to raise assertion here if
 
324
     * the address doesn't contain a valid address family, and
 
325
     * just return PJ_FALSE instead.
 
326
     *
 
327
     * The reason is because application may need to distinguish
 
328
     * these three conditions with sockaddr:
 
329
     *  a) sockaddr is not initialized. This is by convention
 
330
     *     indicated by sa_family==0.
 
331
     *  b) sockaddr is initialized with zero address. This is
 
332
     *     indicated with the address field having zero address.
 
333
     *  c) sockaddr is initialized with valid address/port.
 
334
     *
 
335
     * If we enable this assertion, then application will loose
 
336
     * the capability to specify condition a), since it will be
 
337
     * forced to always initialize sockaddr (even with zero address).
 
338
     * This may break some parts of upper layer libraries.
 
339
     */
 
340
    //PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
 
341
    //               a->addr.sa_family == PJ_AF_INET6, PJ_FALSE);
 
342
 
 
343
    if (a->addr.sa_family!=PJ_AF_INET && a->addr.sa_family!=PJ_AF_INET6) {
 
344
        return PJ_FALSE;
 
345
    } else if (a->addr.sa_family == PJ_AF_INET6) {
 
346
        pj_uint8_t zero[24];
 
347
        pj_bzero(zero, sizeof(zero));
 
348
        return pj_memcmp(a->ipv6.sin6_addr.s6_addr, zero,
 
349
                         sizeof(pj_in6_addr)) != 0;
 
350
    } else
 
351
        return a->ipv4.sin_addr.s_addr != PJ_INADDR_ANY;
 
352
}
 
353
 
 
354
/*
 
355
 * Get port number
 
356
 */
 
357
PJ_DEF(pj_uint16_t) pj_sockaddr_get_port(const pj_sockaddr_t *addr)
 
358
{
 
359
    const pj_sockaddr *a = (const pj_sockaddr*) addr;
 
360
 
 
361
    PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
 
362
                     a->addr.sa_family == PJ_AF_INET6, (pj_uint16_t)0xFFFF);
 
363
 
 
364
    return pj_ntohs((pj_uint16_t)(a->addr.sa_family == PJ_AF_INET6 ?
 
365
                                    a->ipv6.sin6_port : a->ipv4.sin_port));
 
366
}
 
367
 
 
368
/*
 
369
 * Get the length of the address part.
 
370
 */
 
371
PJ_DEF(unsigned) pj_sockaddr_get_addr_len(const pj_sockaddr_t *addr)
 
372
{
 
373
    const pj_sockaddr *a = (const pj_sockaddr*) addr;
 
374
    PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
 
375
                     a->addr.sa_family == PJ_AF_INET6, 0);
 
376
    return a->addr.sa_family == PJ_AF_INET6 ?
 
377
            sizeof(pj_in6_addr) : sizeof(pj_in_addr);
 
378
}
 
379
 
 
380
/*
 
381
 * Get socket address length.
 
382
 */
 
383
PJ_DEF(unsigned) pj_sockaddr_get_len(const pj_sockaddr_t *addr)
 
384
{
 
385
    const pj_sockaddr *a = (const pj_sockaddr*) addr;
 
386
    PJ_ASSERT_RETURN(a->addr.sa_family == PJ_AF_INET ||
 
387
                     a->addr.sa_family == PJ_AF_INET6, 0);
 
388
    return a->addr.sa_family == PJ_AF_INET6 ?
 
389
            sizeof(pj_sockaddr_in6) : sizeof(pj_sockaddr_in);
 
390
}
 
391
 
 
392
/*
 
393
 * Copy only the address part (sin_addr/sin6_addr) of a socket address.
 
394
 */
 
395
PJ_DEF(void) pj_sockaddr_copy_addr( pj_sockaddr *dst,
 
396
                                    const pj_sockaddr *src)
 
397
{
 
398
    /* Destination sockaddr might not be initialized */
 
399
    const char *srcbuf = (char*)pj_sockaddr_get_addr(src);
 
400
    char *dstbuf = ((char*)dst) + (srcbuf - (char*)src);
 
401
    pj_memcpy(dstbuf, srcbuf, pj_sockaddr_get_addr_len(src));
 
402
}
 
403
 
 
404
/*
 
405
 * Copy socket address.
 
406
 */
 
407
PJ_DEF(void) pj_sockaddr_cp(pj_sockaddr_t *dst, const pj_sockaddr_t *src)
 
408
{
 
409
    pj_memcpy(dst, src, pj_sockaddr_get_len(src));
 
410
}
 
411
 
 
412
/*
 
413
 * Set port number of pj_sockaddr_in
 
414
 */
 
415
PJ_DEF(void) pj_sockaddr_in_set_port(pj_sockaddr_in *addr,
 
416
                                     pj_uint16_t hostport)
 
417
{
 
418
    addr->sin_port = pj_htons(hostport);
 
419
}
 
420
 
 
421
/*
 
422
 * Set port number of pj_sockaddr
 
423
 */
 
424
PJ_DEF(pj_status_t) pj_sockaddr_set_port(pj_sockaddr *addr,
 
425
                                         pj_uint16_t hostport)
 
426
{
 
427
    int af = addr->addr.sa_family;
 
428
 
 
429
    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EINVAL);
 
430
 
 
431
    if (af == PJ_AF_INET6)
 
432
        addr->ipv6.sin6_port = pj_htons(hostport);
 
433
    else
 
434
        addr->ipv4.sin_port = pj_htons(hostport);
 
435
 
 
436
    return PJ_SUCCESS;
 
437
}
 
438
 
 
439
/*
 
440
 * Get IPv4 address
 
441
 */
 
442
PJ_DEF(pj_in_addr) pj_sockaddr_in_get_addr(const pj_sockaddr_in *addr)
 
443
{
 
444
    pj_in_addr in_addr;
 
445
    in_addr.s_addr = pj_ntohl(addr->sin_addr.s_addr);
 
446
    return in_addr;
 
447
}
 
448
 
 
449
/*
 
450
 * Set IPv4 address
 
451
 */
 
452
PJ_DEF(void) pj_sockaddr_in_set_addr(pj_sockaddr_in *addr,
 
453
                                     pj_uint32_t hostaddr)
 
454
{
 
455
    addr->sin_addr.s_addr = pj_htonl(hostaddr);
 
456
}
 
457
 
 
458
/*
 
459
 * Parse address
 
460
 */
 
461
PJ_DEF(pj_status_t) pj_sockaddr_parse2(int af, unsigned options,
 
462
                                       const pj_str_t *str,
 
463
                                       pj_str_t *p_hostpart,
 
464
                                       pj_uint16_t *p_port,
 
465
                                       int *raf)
 
466
{
 
467
    const char *end = str->ptr + str->slen;
 
468
    const char *last_colon_pos = NULL;
 
469
    unsigned colon_cnt = 0;
 
470
    const char *p;
 
471
 
 
472
    PJ_ASSERT_RETURN((af==PJ_AF_INET || af==PJ_AF_INET6 || af==PJ_AF_UNSPEC) &&
 
473
                     options==0 &&
 
474
                     str!=NULL, PJ_EINVAL);
 
475
 
 
476
    /* Special handling for empty input */
 
477
    if (str->slen==0 || str->ptr==NULL) {
 
478
        if (p_hostpart)
 
479
            p_hostpart->slen = 0;
 
480
        if (p_port)
 
481
            *p_port = 0;
 
482
        if (raf)
 
483
            *raf = PJ_AF_INET;
 
484
        return PJ_SUCCESS;
 
485
    }
 
486
 
 
487
    /* Count the colon and get the last colon */
 
488
    for (p=str->ptr; p!=end; ++p) {
 
489
        if (*p == ':') {
 
490
            ++colon_cnt;
 
491
            last_colon_pos = p;
 
492
        }
 
493
    }
 
494
 
 
495
    /* Deduce address family if it's not given */
 
496
    if (af == PJ_AF_UNSPEC) {
 
497
        if (colon_cnt > 1)
 
498
            af = PJ_AF_INET6;
 
499
        else
 
500
            af = PJ_AF_INET;
 
501
    } else if (af == PJ_AF_INET && colon_cnt > 1)
 
502
        return PJ_EINVAL;
 
503
 
 
504
    if (raf)
 
505
        *raf = af;
 
506
 
 
507
    if (af == PJ_AF_INET) {
 
508
        /* Parse as IPv4. Supported formats:
 
509
         *  - "10.0.0.1:80"
 
510
         *  - "10.0.0.1"
 
511
         *  - "10.0.0.1:"
 
512
         *  - ":80"
 
513
         *  - ":"
 
514
         */
 
515
        pj_str_t hostpart;
 
516
        unsigned long port;
 
517
 
 
518
        hostpart.ptr = (char*)str->ptr;
 
519
 
 
520
        if (last_colon_pos) {
 
521
            pj_str_t port_part;
 
522
            int i;
 
523
 
 
524
            hostpart.slen = last_colon_pos - str->ptr;
 
525
 
 
526
            port_part.ptr = (char*)last_colon_pos + 1;
 
527
            port_part.slen = end - port_part.ptr;
 
528
 
 
529
            /* Make sure port number is valid */
 
530
            for (i=0; i<port_part.slen; ++i) {
 
531
                if (!pj_isdigit(port_part.ptr[i]))
 
532
                    return PJ_EINVAL;
 
533
            }
 
534
            port = pj_strtoul(&port_part);
 
535
            if (port > 65535)
 
536
                return PJ_EINVAL;
 
537
        } else {
 
538
            hostpart.slen = str->slen;
 
539
            port = 0;
 
540
        }
 
541
 
 
542
        if (p_hostpart)
 
543
            *p_hostpart = hostpart;
 
544
        if (p_port)
 
545
            *p_port = (pj_uint16_t)port;
 
546
 
 
547
        return PJ_SUCCESS;
 
548
 
 
549
    } else if (af == PJ_AF_INET6) {
 
550
 
 
551
        /* Parse as IPv6. Supported formats:
 
552
         *  - "fe::01:80"  ==> note: port number is zero in this case, not 80!
 
553
         *  - "[fe::01]:80"
 
554
         *  - "fe::01"
 
555
         *  - "fe::01:"
 
556
         *  - "[fe::01]"
 
557
         *  - "[fe::01]:"
 
558
         *  - "[::]:80"
 
559
         *  - ":::80"
 
560
         *  - "[::]"
 
561
         *  - "[::]:"
 
562
         *  - ":::"
 
563
         *  - "::"
 
564
         */
 
565
        pj_str_t hostpart, port_part;
 
566
 
 
567
        if (*str->ptr == '[') {
 
568
            char *end_bracket;
 
569
            int i;
 
570
            unsigned long port;
 
571
 
 
572
            if (last_colon_pos == NULL)
 
573
                return PJ_EINVAL;
 
574
 
 
575
            end_bracket = pj_strchr(str, ']');
 
576
            if (end_bracket == NULL)
 
577
                return PJ_EINVAL;
 
578
 
 
579
            hostpart.ptr = (char*)str->ptr + 1;
 
580
            hostpart.slen = end_bracket - hostpart.ptr;
 
581
 
 
582
            if (last_colon_pos < end_bracket) {
 
583
                port_part.ptr = NULL;
 
584
                port_part.slen = 0;
 
585
            } else {
 
586
                port_part.ptr = (char*)last_colon_pos + 1;
 
587
                port_part.slen = end - port_part.ptr;
 
588
            }
 
589
 
 
590
            /* Make sure port number is valid */
 
591
            for (i=0; i<port_part.slen; ++i) {
 
592
                if (!pj_isdigit(port_part.ptr[i]))
 
593
                    return PJ_EINVAL;
 
594
            }
 
595
            port = pj_strtoul(&port_part);
 
596
            if (port > 65535)
 
597
                return PJ_EINVAL;
 
598
 
 
599
            if (p_hostpart)
 
600
                *p_hostpart = hostpart;
 
601
            if (p_port)
 
602
                *p_port = (pj_uint16_t)port;
 
603
 
 
604
            return PJ_SUCCESS;
 
605
 
 
606
        } else {
 
607
            /* Treat everything as part of the IPv6 IP address */
 
608
            if (p_hostpart)
 
609
                *p_hostpart = *str;
 
610
            if (p_port)
 
611
                *p_port = 0;
 
612
 
 
613
            return PJ_SUCCESS;
 
614
        }
 
615
 
 
616
    } else {
 
617
        return PJ_EAFNOTSUP;
 
618
    }
 
619
 
 
620
}
 
621
 
 
622
/*
 
623
 * Parse address
 
624
 */
 
625
PJ_DEF(pj_status_t) pj_sockaddr_parse( int af, unsigned options,
 
626
                                       const pj_str_t *str,
 
627
                                       pj_sockaddr *addr)
 
628
{
 
629
    pj_str_t hostpart;
 
630
    pj_uint16_t port;
 
631
    pj_status_t status;
 
632
 
 
633
    PJ_ASSERT_RETURN(addr, PJ_EINVAL);
 
634
    PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC ||
 
635
                     af==PJ_AF_INET ||
 
636
                     af==PJ_AF_INET6, PJ_EINVAL);
 
637
    PJ_ASSERT_RETURN(options == 0, PJ_EINVAL);
 
638
 
 
639
    status = pj_sockaddr_parse2(af, options, str, &hostpart, &port, &af);
 
640
    if (status != PJ_SUCCESS)
 
641
        return status;
 
642
 
 
643
#if !defined(PJ_HAS_IPV6) || !PJ_HAS_IPV6
 
644
    if (af==PJ_AF_INET6)
 
645
        return PJ_EIPV6NOTSUP;
 
646
#endif
 
647
 
 
648
    status = pj_sockaddr_init(af, addr, &hostpart, port);
 
649
#if defined(PJ_HAS_IPV6) && PJ_HAS_IPV6
 
650
    if (status != PJ_SUCCESS && af == PJ_AF_INET6) {
 
651
        /* Parsing does not yield valid address. Try to treat the last
 
652
         * portion after the colon as port number.
 
653
         */
 
654
        const char *last_colon_pos=NULL, *p;
 
655
        const char *end = str->ptr + str->slen;
 
656
        unsigned long long_port;
 
657
        pj_str_t port_part;
 
658
        int i;
 
659
 
 
660
        /* Parse as IPv6:port */
 
661
        for (p=str->ptr; p!=end; ++p) {
 
662
            if (*p == ':')
 
663
                last_colon_pos = p;
 
664
        }
 
665
 
 
666
        if (last_colon_pos == NULL)
 
667
            return status;
 
668
 
 
669
        hostpart.ptr = (char*)str->ptr;
 
670
        hostpart.slen = last_colon_pos - str->ptr;
 
671
 
 
672
        port_part.ptr = (char*)last_colon_pos + 1;
 
673
        port_part.slen = end - port_part.ptr;
 
674
 
 
675
        /* Make sure port number is valid */
 
676
        for (i=0; i<port_part.slen; ++i) {
 
677
            if (!pj_isdigit(port_part.ptr[i]))
 
678
                return status;
 
679
        }
 
680
        long_port = pj_strtoul(&port_part);
 
681
        if (long_port > 65535)
 
682
            return status;
 
683
 
 
684
        port = (pj_uint16_t)long_port;
 
685
 
 
686
        status = pj_sockaddr_init(PJ_AF_INET6, addr, &hostpart, port);
 
687
    }
 
688
#endif
 
689
 
 
690
    return status;
 
691
}
 
692
 
 
693
/* Resolve the IP address of local machine */
 
694
PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr)
 
695
{
 
696
    unsigned i, count, cand_cnt;
 
697
    enum {
 
698
        CAND_CNT = 8,
 
699
 
 
700
        /* Weighting to be applied to found addresses */
 
701
        WEIGHT_HOSTNAME = 1,    /* hostname IP is not always valid! */
 
702
        WEIGHT_DEF_ROUTE = 2,
 
703
        WEIGHT_INTERFACE = 1,
 
704
        WEIGHT_LOOPBACK = -5,
 
705
        WEIGHT_LINK_LOCAL = -4,
 
706
        WEIGHT_DISABLED = -50,
 
707
 
 
708
        MIN_WEIGHT = WEIGHT_DISABLED+1  /* minimum weight to use */
 
709
    };
 
710
    /* candidates: */
 
711
    pj_sockaddr cand_addr[CAND_CNT];
 
712
    int         cand_weight[CAND_CNT];
 
713
    int         selected_cand;
 
714
    char        strip[PJ_INET6_ADDRSTRLEN+10];
 
715
    /* Special IPv4 addresses. */
 
716
    struct spec_ipv4_t
 
717
    {
 
718
        pj_uint32_t addr;
 
719
        pj_uint32_t mask;
 
720
        int         weight;
 
721
    } spec_ipv4[] =
 
722
    {
 
723
        /* 127.0.0.0/8, loopback addr will be used if there is no other
 
724
         * addresses.
 
725
         */
 
726
        { 0x7f000000, 0xFF000000, WEIGHT_LOOPBACK },
 
727
 
 
728
        /* 0.0.0.0/8, special IP that doesn't seem to be practically useful */
 
729
        { 0x00000000, 0xFF000000, WEIGHT_DISABLED },
 
730
 
 
731
        /* 169.254.0.0/16, a zeroconf/link-local address, which has higher
 
732
         * priority than loopback and will be used if there is no other
 
733
         * valid addresses.
 
734
         */
 
735
        { 0xa9fe0000, 0xFFFF0000, WEIGHT_LINK_LOCAL }
 
736
    };
 
737
    /* Special IPv6 addresses */
 
738
    struct spec_ipv6_t
 
739
    {
 
740
        pj_uint8_t addr[16];
 
741
        pj_uint8_t mask[16];
 
742
        int        weight;
 
743
    } spec_ipv6[] =
 
744
    {
 
745
        /* Loopback address, ::1/128 */
 
746
        { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
 
747
          {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 
748
           0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
 
749
          WEIGHT_LOOPBACK
 
750
        },
 
751
 
 
752
        /* Link local, fe80::/10 */
 
753
        { {0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
754
          {0xff,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
755
          WEIGHT_LINK_LOCAL
 
756
        },
 
757
 
 
758
        /* Disabled, ::/128 */
 
759
        { {0x0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
 
760
        { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 
761
          0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
 
762
          WEIGHT_DISABLED
 
763
        }
 
764
    };
 
765
    pj_addrinfo ai;
 
766
    pj_status_t status;
 
767
 
 
768
    /* May not be used if TRACE_ is disabled */
 
769
    PJ_UNUSED_ARG(strip);
 
770
 
 
771
#ifdef _MSC_VER
 
772
    /* Get rid of "uninitialized he variable" with MS compilers */
 
773
    pj_bzero(&ai, sizeof(ai));
 
774
#endif
 
775
 
 
776
    cand_cnt = 0;
 
777
    pj_bzero(cand_addr, sizeof(cand_addr));
 
778
    pj_bzero(cand_weight, sizeof(cand_weight));
 
779
    for (i=0; i<PJ_ARRAY_SIZE(cand_addr); ++i) {
 
780
        cand_addr[i].addr.sa_family = (pj_uint16_t)af;
 
781
        PJ_SOCKADDR_RESET_LEN(&cand_addr[i]);
 
782
    }
 
783
 
 
784
    addr->addr.sa_family = (pj_uint16_t)af;
 
785
    PJ_SOCKADDR_RESET_LEN(addr);
 
786
 
 
787
#if !defined(PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION) || \
 
788
    PJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION == 0
 
789
    /* Get hostname's IP address */
 
790
    count = 1;
 
791
    status = pj_getaddrinfo(af, pj_gethostname(), &count, &ai);
 
792
    if (status == PJ_SUCCESS) {
 
793
        pj_assert(ai.ai_addr.addr.sa_family == (pj_uint16_t)af);
 
794
        pj_sockaddr_copy_addr(&cand_addr[cand_cnt], &ai.ai_addr);
 
795
        pj_sockaddr_set_port(&cand_addr[cand_cnt], 0);
 
796
        cand_weight[cand_cnt] += WEIGHT_HOSTNAME;
 
797
        ++cand_cnt;
 
798
 
 
799
        TRACE_((THIS_FILE, "hostname IP is %s",
 
800
                pj_sockaddr_print(&ai.ai_addr, strip, sizeof(strip), 0)));
 
801
    }
 
802
#else
 
803
    PJ_UNUSED_ARG(ai);
 
804
    PJ_UNUSED_ARG(count);
 
805
#endif
 
806
 
 
807
    /* Get default interface (interface for default route) */
 
808
    if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) {
 
809
        status = pj_getdefaultipinterface(af, addr);
 
810
        if (status == PJ_SUCCESS) {
 
811
            TRACE_((THIS_FILE, "default IP is %s",
 
812
                    pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
 
813
 
 
814
            pj_sockaddr_set_port(addr, 0);
 
815
            for (i=0; i<cand_cnt; ++i) {
 
816
                if (pj_sockaddr_cmp(&cand_addr[i], addr)==0)
 
817
                    break;
 
818
            }
 
819
 
 
820
            cand_weight[i] += WEIGHT_DEF_ROUTE;
 
821
            if (i >= cand_cnt) {
 
822
                pj_sockaddr_copy_addr(&cand_addr[i], addr);
 
823
                ++cand_cnt;
 
824
            }
 
825
        }
 
826
    }
 
827
 
 
828
 
 
829
    /* Enumerate IP interfaces */
 
830
    if (cand_cnt < PJ_ARRAY_SIZE(cand_addr)) {
 
831
        unsigned start_if = cand_cnt;
 
832
        unsigned count = PJ_ARRAY_SIZE(cand_addr) - start_if;
 
833
 
 
834
        status = pj_enum_ip_interface(af, &count, &cand_addr[start_if]);
 
835
        if (status == PJ_SUCCESS && count) {
 
836
            /* Clear the port number */
 
837
            for (i=0; i<count; ++i)
 
838
                pj_sockaddr_set_port(&cand_addr[start_if+i], 0);
 
839
 
 
840
            /* For each candidate that we found so far (that is the hostname
 
841
             * address and default interface address, check if they're found
 
842
             * in the interface list. If found, add the weight, and if not,
 
843
             * decrease the weight.
 
844
             */
 
845
            for (i=0; i<cand_cnt; ++i) {
 
846
                unsigned j;
 
847
                for (j=0; j<count; ++j) {
 
848
                    if (pj_sockaddr_cmp(&cand_addr[i],
 
849
                                        &cand_addr[start_if+j])==0)
 
850
                        break;
 
851
                }
 
852
 
 
853
                if (j == count) {
 
854
                    /* Not found */
 
855
                    cand_weight[i] -= WEIGHT_INTERFACE;
 
856
                } else {
 
857
                    cand_weight[i] += WEIGHT_INTERFACE;
 
858
                }
 
859
            }
 
860
 
 
861
            /* Add remaining interface to candidate list. */
 
862
            for (i=0; i<count; ++i) {
 
863
                unsigned j;
 
864
                for (j=0; j<cand_cnt; ++j) {
 
865
                    if (pj_sockaddr_cmp(&cand_addr[start_if+i],
 
866
                                        &cand_addr[j])==0)
 
867
                        break;
 
868
                }
 
869
 
 
870
                if (j == cand_cnt) {
 
871
                    pj_sockaddr_copy_addr(&cand_addr[cand_cnt],
 
872
                                          &cand_addr[start_if+i]);
 
873
                    cand_weight[cand_cnt] += WEIGHT_INTERFACE;
 
874
                    ++cand_cnt;
 
875
                }
 
876
            }
 
877
        }
 
878
    }
 
879
 
 
880
    /* Apply weight adjustment for special IPv4/IPv6 addresses
 
881
     * See http://trac.pjsip.org/repos/ticket/1046
 
882
     */
 
883
    if (af == PJ_AF_INET) {
 
884
        for (i=0; i<cand_cnt; ++i) {
 
885
            unsigned j;
 
886
            for (j=0; j<PJ_ARRAY_SIZE(spec_ipv4); ++j) {
 
887
                    pj_uint32_t a = pj_ntohl(cand_addr[i].ipv4.sin_addr.s_addr);
 
888
                    pj_uint32_t pa = spec_ipv4[j].addr;
 
889
                    pj_uint32_t pm = spec_ipv4[j].mask;
 
890
 
 
891
                    if ((a & pm) == pa) {
 
892
                        cand_weight[i] += spec_ipv4[j].weight;
 
893
                        break;
 
894
                    }
 
895
            }
 
896
        }
 
897
    } else if (af == PJ_AF_INET6) {
 
898
        for (i=0; i<PJ_ARRAY_SIZE(spec_ipv6); ++i) {
 
899
                unsigned j;
 
900
                for (j=0; j<cand_cnt; ++j) {
 
901
                    pj_uint8_t *a = cand_addr[j].ipv6.sin6_addr.s6_addr;
 
902
                    pj_uint8_t am[16];
 
903
                    pj_uint8_t *pa = spec_ipv6[i].addr;
 
904
                    pj_uint8_t *pm = spec_ipv6[i].mask;
 
905
                    unsigned k;
 
906
 
 
907
                    for (k=0; k<16; ++k) {
 
908
                        am[k] = (pj_uint8_t)((a[k] & pm[k]) & 0xFF);
 
909
                    }
 
910
 
 
911
                    if (pj_memcmp(am, pa, 16)==0) {
 
912
                        cand_weight[j] += spec_ipv6[i].weight;
 
913
                    }
 
914
                }
 
915
        }
 
916
    } else {
 
917
        return PJ_EAFNOTSUP;
 
918
    }
 
919
 
 
920
    /* Enumerate candidates to get the best IP address to choose */
 
921
    selected_cand = -1;
 
922
    for (i=0; i<cand_cnt; ++i) {
 
923
        TRACE_((THIS_FILE, "Checking candidate IP %s, weight=%d",
 
924
                pj_sockaddr_print(&cand_addr[i], strip, sizeof(strip), 0),
 
925
                cand_weight[i]));
 
926
 
 
927
        if (cand_weight[i] < MIN_WEIGHT) {
 
928
            continue;
 
929
        }
 
930
 
 
931
        if (selected_cand == -1)
 
932
            selected_cand = i;
 
933
        else if (cand_weight[i] > cand_weight[selected_cand])
 
934
            selected_cand = i;
 
935
    }
 
936
 
 
937
    /* If else fails, returns loopback interface as the last resort */
 
938
    if (selected_cand == -1) {
 
939
        if (af==PJ_AF_INET) {
 
940
            addr->ipv4.sin_addr.s_addr = pj_htonl (0x7f000001);
 
941
        } else {
 
942
            pj_in6_addr *s6_addr;
 
943
 
 
944
            s6_addr = (pj_in6_addr*) pj_sockaddr_get_addr(addr);
 
945
            pj_bzero(s6_addr, sizeof(pj_in6_addr));
 
946
            s6_addr->s6_addr[15] = 1;
 
947
        }
 
948
        TRACE_((THIS_FILE, "Loopback IP %s returned",
 
949
                pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
 
950
    } else {
 
951
        pj_sockaddr_copy_addr(addr, &cand_addr[selected_cand]);
 
952
        TRACE_((THIS_FILE, "Candidate %s selected",
 
953
                pj_sockaddr_print(addr, strip, sizeof(strip), 0)));
 
954
    }
 
955
 
 
956
    return PJ_SUCCESS;
 
957
}
 
958
 
 
959
/* Get the default IP interface */
 
960
PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
 
961
{
 
962
    pj_sock_t fd;
 
963
    pj_str_t cp;
 
964
    pj_sockaddr a;
 
965
    int len;
 
966
    pj_uint8_t zero[64];
 
967
    pj_status_t status;
 
968
 
 
969
    addr->addr.sa_family = (pj_uint16_t)af;
 
970
 
 
971
    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd);
 
972
    if (status != PJ_SUCCESS) {
 
973
        return status;
 
974
    }
 
975
 
 
976
    if (af == PJ_AF_INET) {
 
977
        cp = pj_str("1.1.1.1");
 
978
    } else {
 
979
        cp = pj_str("1::1");
 
980
    }
 
981
    status = pj_sockaddr_init(af, &a, &cp, 53);
 
982
    if (status != PJ_SUCCESS) {
 
983
        pj_sock_close(fd);
 
984
        return status;
 
985
    }
 
986
 
 
987
    status = pj_sock_connect(fd, &a, pj_sockaddr_get_len(&a));
 
988
    if (status != PJ_SUCCESS) {
 
989
        pj_sock_close(fd);
 
990
        return status;
 
991
    }
 
992
 
 
993
    len = sizeof(a);
 
994
    status = pj_sock_getsockname(fd, &a, &len);
 
995
    if (status != PJ_SUCCESS) {
 
996
        pj_sock_close(fd);
 
997
        return status;
 
998
    }
 
999
 
 
1000
    pj_sock_close(fd);
 
1001
 
 
1002
    /* Check that the address returned is not zero */
 
1003
    pj_bzero(zero, sizeof(zero));
 
1004
    if (pj_memcmp(pj_sockaddr_get_addr(&a), zero,
 
1005
                  pj_sockaddr_get_addr_len(&a))==0)
 
1006
    {
 
1007
        return PJ_ENOTFOUND;
 
1008
    }
 
1009
 
 
1010
    pj_sockaddr_copy_addr(addr, &a);
 
1011
 
 
1012
    /* Success */
 
1013
    return PJ_SUCCESS;
 
1014
}
 
1015
 
 
1016
 
 
1017
/* Only need to implement these in DLL build */
 
1018
#if defined(PJ_DLL)
 
1019
 
 
1020
PJ_DEF(pj_uint16_t) pj_AF_UNSPEC(void)
 
1021
{
 
1022
    return PJ_AF_UNSPEC;
 
1023
}
 
1024
 
 
1025
PJ_DEF(pj_uint16_t) pj_AF_UNIX(void)
 
1026
{
 
1027
    return PJ_AF_UNIX;
 
1028
}
 
1029
 
 
1030
PJ_DEF(pj_uint16_t) pj_AF_INET(void)
 
1031
{
 
1032
    return PJ_AF_INET;
 
1033
}
 
1034
 
 
1035
PJ_DEF(pj_uint16_t) pj_AF_INET6(void)
 
1036
{
 
1037
    return PJ_AF_INET6;
 
1038
}
 
1039
 
 
1040
PJ_DEF(pj_uint16_t) pj_AF_PACKET(void)
 
1041
{
 
1042
    return PJ_AF_PACKET;
 
1043
}
 
1044
 
 
1045
PJ_DEF(pj_uint16_t) pj_AF_IRDA(void)
 
1046
{
 
1047
    return PJ_AF_IRDA;
 
1048
}
 
1049
 
 
1050
PJ_DEF(int) pj_SOCK_STREAM(void)
 
1051
{
 
1052
    return PJ_SOCK_STREAM;
 
1053
}
 
1054
 
 
1055
PJ_DEF(int) pj_SOCK_DGRAM(void)
 
1056
{
 
1057
    return PJ_SOCK_DGRAM;
 
1058
}
 
1059
 
 
1060
PJ_DEF(int) pj_SOCK_RAW(void)
 
1061
{
 
1062
    return PJ_SOCK_RAW;
 
1063
}
 
1064
 
 
1065
PJ_DEF(int) pj_SOCK_RDM(void)
 
1066
{
 
1067
    return PJ_SOCK_RDM;
 
1068
}
 
1069
 
 
1070
PJ_DEF(pj_uint16_t) pj_SOL_SOCKET(void)
 
1071
{
 
1072
    return PJ_SOL_SOCKET;
 
1073
}
 
1074
 
 
1075
PJ_DEF(pj_uint16_t) pj_SOL_IP(void)
 
1076
{
 
1077
    return PJ_SOL_IP;
 
1078
}
 
1079
 
 
1080
PJ_DEF(pj_uint16_t) pj_SOL_TCP(void)
 
1081
{
 
1082
    return PJ_SOL_TCP;
 
1083
}
 
1084
 
 
1085
PJ_DEF(pj_uint16_t) pj_SOL_UDP(void)
 
1086
{
 
1087
    return PJ_SOL_UDP;
 
1088
}
 
1089
 
 
1090
PJ_DEF(pj_uint16_t) pj_SOL_IPV6(void)
 
1091
{
 
1092
    return PJ_SOL_IPV6;
 
1093
}
 
1094
 
 
1095
PJ_DEF(int) pj_IP_TOS(void)
 
1096
{
 
1097
    return PJ_IP_TOS;
 
1098
}
 
1099
 
 
1100
PJ_DEF(int) pj_IPTOS_LOWDELAY(void)
 
1101
{
 
1102
    return PJ_IPTOS_LOWDELAY;
 
1103
}
 
1104
 
 
1105
PJ_DEF(int) pj_IPTOS_THROUGHPUT(void)
 
1106
{
 
1107
    return PJ_IPTOS_THROUGHPUT;
 
1108
}
 
1109
 
 
1110
PJ_DEF(int) pj_IPTOS_RELIABILITY(void)
 
1111
{
 
1112
    return PJ_IPTOS_RELIABILITY;
 
1113
}
 
1114
 
 
1115
PJ_DEF(int) pj_IPTOS_MINCOST(void)
 
1116
{
 
1117
    return PJ_IPTOS_MINCOST;
 
1118
}
 
1119
 
 
1120
PJ_DEF(pj_uint16_t) pj_SO_TYPE(void)
 
1121
{
 
1122
    return PJ_SO_TYPE;
 
1123
}
 
1124
 
 
1125
PJ_DEF(pj_uint16_t) pj_SO_RCVBUF(void)
 
1126
{
 
1127
    return PJ_SO_RCVBUF;
 
1128
}
 
1129
 
 
1130
PJ_DEF(pj_uint16_t) pj_SO_SNDBUF(void)
 
1131
{
 
1132
    return PJ_SO_SNDBUF;
 
1133
}
 
1134
 
 
1135
PJ_DEF(pj_uint16_t) pj_TCP_NODELAY(void)
 
1136
{
 
1137
    return PJ_TCP_NODELAY;
 
1138
}
 
1139
 
 
1140
PJ_DEF(pj_uint16_t) pj_SO_REUSEADDR(void)
 
1141
{
 
1142
    return PJ_SO_REUSEADDR;
 
1143
}
 
1144
 
 
1145
PJ_DEF(pj_uint16_t) pj_SO_NOSIGPIPE(void)
 
1146
{
 
1147
    return PJ_SO_NOSIGPIPE;
 
1148
}
 
1149
 
 
1150
PJ_DEF(pj_uint16_t) pj_SO_PRIORITY(void)
 
1151
{
 
1152
    return PJ_SO_PRIORITY;
 
1153
}
 
1154
 
 
1155
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_IF(void)
 
1156
{
 
1157
    return PJ_IP_MULTICAST_IF;
 
1158
}
 
1159
 
 
1160
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_TTL(void)
 
1161
{
 
1162
    return PJ_IP_MULTICAST_TTL;
 
1163
}
 
1164
 
 
1165
PJ_DEF(pj_uint16_t) pj_IP_MULTICAST_LOOP(void)
 
1166
{
 
1167
    return PJ_IP_MULTICAST_LOOP;
 
1168
}
 
1169
 
 
1170
PJ_DEF(pj_uint16_t) pj_IP_ADD_MEMBERSHIP(void)
 
1171
{
 
1172
    return PJ_IP_ADD_MEMBERSHIP;
 
1173
}
 
1174
 
 
1175
PJ_DEF(pj_uint16_t) pj_IP_DROP_MEMBERSHIP(void)
 
1176
{
 
1177
    return PJ_IP_DROP_MEMBERSHIP;
 
1178
}
 
1179
 
 
1180
PJ_DEF(int) pj_MSG_OOB(void)
 
1181
{
 
1182
    return PJ_MSG_OOB;
 
1183
}
 
1184
 
 
1185
PJ_DEF(int) pj_MSG_PEEK(void)
 
1186
{
 
1187
    return PJ_MSG_PEEK;
 
1188
}
 
1189
 
 
1190
PJ_DEF(int) pj_MSG_DONTROUTE(void)
 
1191
{
 
1192
    return PJ_MSG_DONTROUTE;
 
1193
}
 
1194
 
 
1195
#endif  /* PJ_DLL */