~ubuntu-branches/ubuntu/raring/sflphone/raring

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject/pjlib/src/pj/sock_bsd.c

  • Committer: Package Import Robot
  • Author(s): Francois Marier
  • Date: 2011-11-25 13:24:12 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20111125132412-dc4qvhyosk74cd42
Tags: 1.0.1-4
Don't assume that arch:all packages will get built (closes: #649726)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: sock_bsd.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 <pj/sock.h>
 
21
#include <pj/os.h>
 
22
#include <pj/assert.h>
 
23
#include <pj/string.h>
 
24
#include <pj/compat/socket.h>
 
25
#include <pj/addr_resolv.h>
 
26
#include <pj/errno.h>
 
27
#include <pj/unicode.h>
 
28
 
 
29
/*
 
30
 * Address families conversion.
 
31
 * The values here are indexed based on pj_addr_family.
 
32
 */
 
33
const pj_uint16_t PJ_AF_UNSPEC  = AF_UNSPEC;
 
34
const pj_uint16_t PJ_AF_UNIX    = AF_UNIX;
 
35
const pj_uint16_t PJ_AF_INET    = AF_INET;
 
36
const pj_uint16_t PJ_AF_INET6   = AF_INET6;
 
37
#ifdef AF_PACKET
 
38
const pj_uint16_t PJ_AF_PACKET  = AF_PACKET;
 
39
#else
 
40
const pj_uint16_t PJ_AF_PACKET  = 0xFFFF;
 
41
#endif
 
42
#ifdef AF_IRDA
 
43
const pj_uint16_t PJ_AF_IRDA    = AF_IRDA;
 
44
#else
 
45
const pj_uint16_t PJ_AF_IRDA    = 0xFFFF;
 
46
#endif
 
47
 
 
48
/*
 
49
 * Socket types conversion.
 
50
 * The values here are indexed based on pj_sock_type
 
51
 */
 
52
const pj_uint16_t PJ_SOCK_STREAM= SOCK_STREAM;
 
53
const pj_uint16_t PJ_SOCK_DGRAM = SOCK_DGRAM;
 
54
const pj_uint16_t PJ_SOCK_RAW   = SOCK_RAW;
 
55
const pj_uint16_t PJ_SOCK_RDM   = SOCK_RDM;
 
56
 
 
57
/*
 
58
 * Socket level values.
 
59
 */
 
60
const pj_uint16_t PJ_SOL_SOCKET = SOL_SOCKET;
 
61
#ifdef SOL_IP
 
62
const pj_uint16_t PJ_SOL_IP     = SOL_IP;
 
63
#elif defined(PJ_WIN32) && PJ_WIN32
 
64
const pj_uint16_t PJ_SOL_IP     = IPPROTO_IP;
 
65
#else
 
66
const pj_uint16_t PJ_SOL_IP     = 0;
 
67
#endif /* SOL_IP */
 
68
 
 
69
#if defined(SOL_TCP)
 
70
const pj_uint16_t PJ_SOL_TCP    = SOL_TCP;
 
71
#elif defined(IPPROTO_TCP)
 
72
const pj_uint16_t PJ_SOL_TCP    = IPPROTO_TCP;
 
73
#elif defined(PJ_WIN32) && PJ_WIN32
 
74
const pj_uint16_t PJ_SOL_TCP    = IPPROTO_TCP;
 
75
#else
 
76
const pj_uint16_t PJ_SOL_TCP    = 6;
 
77
#endif /* SOL_TCP */
 
78
 
 
79
#ifdef SOL_UDP
 
80
const pj_uint16_t PJ_SOL_UDP    = SOL_UDP;
 
81
#elif defined(IPPROTO_UDP)
 
82
const pj_uint16_t PJ_SOL_UDP    = IPPROTO_UDP;
 
83
#elif defined(PJ_WIN32) && PJ_WIN32
 
84
const pj_uint16_t PJ_SOL_UDP    = IPPROTO_UDP;
 
85
#else
 
86
const pj_uint16_t PJ_SOL_UDP    = 17;
 
87
#endif /* SOL_UDP */
 
88
 
 
89
#ifdef SOL_IPV6
 
90
const pj_uint16_t PJ_SOL_IPV6   = SOL_IPV6;
 
91
#elif defined(PJ_WIN32) && PJ_WIN32
 
92
#   if defined(IPPROTO_IPV6) || (_WIN32_WINNT >= 0x0501)
 
93
        const pj_uint16_t PJ_SOL_IPV6   = IPPROTO_IPV6;
 
94
#   else
 
95
        const pj_uint16_t PJ_SOL_IPV6   = 41;
 
96
#   endif
 
97
#else
 
98
const pj_uint16_t PJ_SOL_IPV6   = 41;
 
99
#endif /* SOL_IPV6 */
 
100
 
 
101
/* IP_TOS */
 
102
#ifdef IP_TOS
 
103
const pj_uint16_t PJ_IP_TOS     = IP_TOS;
 
104
#else
 
105
const pj_uint16_t PJ_IP_TOS     = 1;
 
106
#endif
 
107
 
 
108
 
 
109
/* TOS settings (declared in netinet/ip.h) */
 
110
#ifdef IPTOS_LOWDELAY
 
111
const pj_uint16_t PJ_IPTOS_LOWDELAY     = IPTOS_LOWDELAY;
 
112
#else
 
113
const pj_uint16_t PJ_IPTOS_LOWDELAY     = 0x10;
 
114
#endif
 
115
#ifdef IPTOS_THROUGHPUT
 
116
const pj_uint16_t PJ_IPTOS_THROUGHPUT   = IPTOS_THROUGHPUT;
 
117
#else
 
118
const pj_uint16_t PJ_IPTOS_THROUGHPUT   = 0x08;
 
119
#endif
 
120
#ifdef IPTOS_RELIABILITY
 
121
const pj_uint16_t PJ_IPTOS_RELIABILITY  = IPTOS_RELIABILITY;
 
122
#else
 
123
const pj_uint16_t PJ_IPTOS_RELIABILITY  = 0x04;
 
124
#endif
 
125
#ifdef IPTOS_MINCOST
 
126
const pj_uint16_t PJ_IPTOS_MINCOST      = IPTOS_MINCOST;
 
127
#else
 
128
const pj_uint16_t PJ_IPTOS_MINCOST      = 0x02;
 
129
#endif
 
130
 
 
131
 
 
132
/* optname values. */
 
133
const pj_uint16_t PJ_SO_TYPE    = SO_TYPE;
 
134
const pj_uint16_t PJ_SO_RCVBUF  = SO_RCVBUF;
 
135
const pj_uint16_t PJ_SO_SNDBUF  = SO_SNDBUF;
 
136
const pj_uint16_t PJ_TCP_NODELAY= TCP_NODELAY;
 
137
const pj_uint16_t PJ_SO_REUSEADDR= SO_REUSEADDR;
 
138
#ifdef SO_NOSIGPIPE
 
139
const pj_uint16_t PJ_SO_NOSIGPIPE = SO_NOSIGPIPE;
 
140
#else
 
141
const pj_uint16_t PJ_SO_NOSIGPIPE = 0xFFFF;
 
142
#endif
 
143
#if defined(SO_PRIORITY)
 
144
const pj_uint16_t PJ_SO_PRIORITY = SO_PRIORITY;
 
145
#else
 
146
/* This is from Linux, YMMV */
 
147
const pj_uint16_t PJ_SO_PRIORITY = 12;
 
148
#endif
 
149
 
 
150
/* Multicasting is not supported e.g. in PocketPC 2003 SDK */
 
151
#ifdef IP_MULTICAST_IF
 
152
const pj_uint16_t PJ_IP_MULTICAST_IF    = IP_MULTICAST_IF;
 
153
const pj_uint16_t PJ_IP_MULTICAST_TTL   = IP_MULTICAST_TTL;
 
154
const pj_uint16_t PJ_IP_MULTICAST_LOOP  = IP_MULTICAST_LOOP;
 
155
const pj_uint16_t PJ_IP_ADD_MEMBERSHIP  = IP_ADD_MEMBERSHIP;
 
156
const pj_uint16_t PJ_IP_DROP_MEMBERSHIP = IP_DROP_MEMBERSHIP;
 
157
#else
 
158
const pj_uint16_t PJ_IP_MULTICAST_IF    = 0xFFFF;
 
159
const pj_uint16_t PJ_IP_MULTICAST_TTL   = 0xFFFF;
 
160
const pj_uint16_t PJ_IP_MULTICAST_LOOP  = 0xFFFF;
 
161
const pj_uint16_t PJ_IP_ADD_MEMBERSHIP  = 0xFFFF;
 
162
const pj_uint16_t PJ_IP_DROP_MEMBERSHIP = 0xFFFF;
 
163
#endif
 
164
 
 
165
/* recv() and send() flags */
 
166
const int PJ_MSG_OOB            = MSG_OOB;
 
167
const int PJ_MSG_PEEK           = MSG_PEEK;
 
168
const int PJ_MSG_DONTROUTE      = MSG_DONTROUTE;
 
169
 
 
170
 
 
171
#if 0
 
172
static void CHECK_ADDR_LEN(const pj_sockaddr *addr, int len)
 
173
{
 
174
    pj_sockaddr *a = (pj_sockaddr*)addr;
 
175
    pj_assert((a->addr.sa_family==PJ_AF_INET && len==sizeof(pj_sockaddr_in)) ||
 
176
              (a->addr.sa_family==PJ_AF_INET6 && len==sizeof(pj_sockaddr_in6)));
 
177
 
 
178
}
 
179
#else
 
180
#define CHECK_ADDR_LEN(addr,len)
 
181
#endif
 
182
 
 
183
/*
 
184
 * Convert 16-bit value from network byte order to host byte order.
 
185
 */
 
186
PJ_DEF(pj_uint16_t) pj_ntohs(pj_uint16_t netshort)
 
187
{
 
188
    return ntohs(netshort);
 
189
}
 
190
 
 
191
/*
 
192
 * Convert 16-bit value from host byte order to network byte order.
 
193
 */
 
194
PJ_DEF(pj_uint16_t) pj_htons(pj_uint16_t hostshort)
 
195
{
 
196
    return htons(hostshort);
 
197
}
 
198
 
 
199
/*
 
200
 * Convert 32-bit value from network byte order to host byte order.
 
201
 */
 
202
PJ_DEF(pj_uint32_t) pj_ntohl(pj_uint32_t netlong)
 
203
{
 
204
    return ntohl(netlong);
 
205
}
 
206
 
 
207
/*
 
208
 * Convert 32-bit value from host byte order to network byte order.
 
209
 */
 
210
PJ_DEF(pj_uint32_t) pj_htonl(pj_uint32_t hostlong)
 
211
{
 
212
    return htonl(hostlong);
 
213
}
 
214
 
 
215
/*
 
216
 * Convert an Internet host address given in network byte order
 
217
 * to string in standard numbers and dots notation.
 
218
 */
 
219
PJ_DEF(char*) pj_inet_ntoa(pj_in_addr inaddr)
 
220
{
 
221
#if !defined(PJ_LINUX) && !defined(PJ_LINUX_KERNEL)
 
222
    return inet_ntoa(*(struct in_addr*)&inaddr);
 
223
#else
 
224
    struct in_addr addr;
 
225
    addr.s_addr = inaddr.s_addr;
 
226
    return inet_ntoa(addr);
 
227
#endif
 
228
}
 
229
 
 
230
/*
 
231
 * This function converts the Internet host address cp from the standard
 
232
 * numbers-and-dots notation into binary data and stores it in the structure
 
233
 * that inp points to. 
 
234
 */
 
235
PJ_DEF(int) pj_inet_aton(const pj_str_t *cp, struct pj_in_addr *inp)
 
236
{
 
237
    char tempaddr[PJ_INET_ADDRSTRLEN];
 
238
 
 
239
    /* Initialize output with PJ_INADDR_NONE.
 
240
     * Some apps relies on this instead of the return value
 
241
     * (and anyway the return value is quite confusing!)
 
242
     */
 
243
    inp->s_addr = PJ_INADDR_NONE;
 
244
 
 
245
    /* Caution:
 
246
     *  this function might be called with cp->slen >= 16
 
247
     *  (i.e. when called with hostname to check if it's an IP addr).
 
248
     */
 
249
    PJ_ASSERT_RETURN(cp && cp->slen && inp, 0);
 
250
    if (cp->slen >= PJ_INET_ADDRSTRLEN) {
 
251
        return 0;
 
252
    }
 
253
 
 
254
    pj_memcpy(tempaddr, cp->ptr, cp->slen);
 
255
    tempaddr[cp->slen] = '\0';
 
256
 
 
257
#if defined(PJ_SOCK_HAS_INET_ATON) && PJ_SOCK_HAS_INET_ATON != 0
 
258
    return inet_aton(tempaddr, (struct in_addr*)inp);
 
259
#else
 
260
    inp->s_addr = inet_addr(tempaddr);
 
261
    return inp->s_addr == PJ_INADDR_NONE ? 0 : 1;
 
262
#endif
 
263
}
 
264
 
 
265
/*
 
266
 * Convert text to IPv4/IPv6 address.
 
267
 */
 
268
PJ_DEF(pj_status_t) pj_inet_pton(int af, const pj_str_t *src, void *dst)
 
269
{
 
270
    char tempaddr[PJ_INET6_ADDRSTRLEN];
 
271
 
 
272
    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EAFNOTSUP);
 
273
    PJ_ASSERT_RETURN(src && src->slen && dst, PJ_EINVAL);
 
274
 
 
275
    /* Initialize output with PJ_IN_ADDR_NONE for IPv4 (to be 
 
276
     * compatible with pj_inet_aton()
 
277
     */
 
278
    if (af==PJ_AF_INET) {
 
279
        ((pj_in_addr*)dst)->s_addr = PJ_INADDR_NONE;
 
280
    }
 
281
 
 
282
    /* Caution:
 
283
     *  this function might be called with cp->slen >= 46
 
284
     *  (i.e. when called with hostname to check if it's an IP addr).
 
285
     */
 
286
    if (src->slen >= PJ_INET6_ADDRSTRLEN) {
 
287
        return PJ_ENAMETOOLONG;
 
288
    }
 
289
 
 
290
    pj_memcpy(tempaddr, src->ptr, src->slen);
 
291
    tempaddr[src->slen] = '\0';
 
292
 
 
293
#if defined(PJ_SOCK_HAS_INET_PTON) && PJ_SOCK_HAS_INET_PTON != 0
 
294
    /*
 
295
     * Implementation using inet_pton()
 
296
     */
 
297
    if (inet_pton(af, tempaddr, dst) != 1) {
 
298
        pj_status_t status = pj_get_netos_error();
 
299
        if (status == PJ_SUCCESS)
 
300
            status = PJ_EUNKNOWN;
 
301
 
 
302
        return status;
 
303
    }
 
304
 
 
305
    return PJ_SUCCESS;
 
306
 
 
307
#elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE)
 
308
    /*
 
309
     * Implementation on Windows, using WSAStringToAddress().
 
310
     * Should also work on Unicode systems.
 
311
     */
 
312
    {
 
313
        PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN)
 
314
        pj_sockaddr sock_addr;
 
315
        int addr_len = sizeof(sock_addr);
 
316
        int rc;
 
317
 
 
318
        sock_addr.addr.sa_family = (pj_uint16_t)af;
 
319
        rc = WSAStringToAddress(
 
320
                PJ_STRING_TO_NATIVE(tempaddr,wtempaddr,sizeof(wtempaddr)), 
 
321
                af, NULL, (LPSOCKADDR)&sock_addr, &addr_len);
 
322
        if (rc != 0) {
 
323
            /* If you get rc 130022 Invalid argument (WSAEINVAL) with IPv6,
 
324
             * check that you have IPv6 enabled (install it in the network
 
325
             * adapter).
 
326
             */
 
327
            pj_status_t status = pj_get_netos_error();
 
328
            if (status == PJ_SUCCESS)
 
329
                status = PJ_EUNKNOWN;
 
330
 
 
331
            return status;
 
332
        }
 
333
 
 
334
        if (sock_addr.addr.sa_family == PJ_AF_INET) {
 
335
            pj_memcpy(dst, &sock_addr.ipv4.sin_addr, 4);
 
336
            return PJ_SUCCESS;
 
337
        } else if (sock_addr.addr.sa_family == PJ_AF_INET6) {
 
338
            pj_memcpy(dst, &sock_addr.ipv6.sin6_addr, 16);
 
339
            return PJ_SUCCESS;
 
340
        } else {
 
341
            pj_assert(!"Shouldn't happen");
 
342
            return PJ_EBUG;
 
343
        }
 
344
    }
 
345
#elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0
 
346
    /* IPv6 support is disabled, just return error without raising assertion */
 
347
    return PJ_EIPV6NOTSUP;
 
348
#else
 
349
    pj_assert(!"Not supported");
 
350
    return PJ_EIPV6NOTSUP;
 
351
#endif
 
352
}
 
353
 
 
354
/*
 
355
 * Convert IPv4/IPv6 address to text.
 
356
 */
 
357
PJ_DEF(pj_status_t) pj_inet_ntop(int af, const void *src,
 
358
                                 char *dst, int size)
 
359
 
 
360
{
 
361
    PJ_ASSERT_RETURN(src && dst && size, PJ_EINVAL);
 
362
 
 
363
    *dst = '\0';
 
364
 
 
365
    PJ_ASSERT_RETURN(af==PJ_AF_INET || af==PJ_AF_INET6, PJ_EAFNOTSUP);
 
366
 
 
367
#if defined(PJ_SOCK_HAS_INET_NTOP) && PJ_SOCK_HAS_INET_NTOP != 0
 
368
    /*
 
369
     * Implementation using inet_ntop()
 
370
     */
 
371
    if (inet_ntop(af, src, dst, size) == NULL) {
 
372
        pj_status_t status = pj_get_netos_error();
 
373
        if (status == PJ_SUCCESS)
 
374
            status = PJ_EUNKNOWN;
 
375
 
 
376
        return status;
 
377
    }
 
378
 
 
379
    return PJ_SUCCESS;
 
380
 
 
381
#elif defined(PJ_WIN32) || defined(PJ_WIN32_WINCE)
 
382
    /*
 
383
     * Implementation on Windows, using WSAAddressToString().
 
384
     * Should also work on Unicode systems.
 
385
     */
 
386
    {
 
387
        PJ_DECL_UNICODE_TEMP_BUF(wtempaddr,PJ_INET6_ADDRSTRLEN)
 
388
        pj_sockaddr sock_addr;
 
389
        DWORD addr_len, addr_str_len;
 
390
        int rc;
 
391
 
 
392
        pj_bzero(&sock_addr, sizeof(sock_addr));
 
393
        sock_addr.addr.sa_family = (pj_uint16_t)af;
 
394
        if (af == PJ_AF_INET) {
 
395
            if (size < PJ_INET_ADDRSTRLEN)
 
396
                return PJ_ETOOSMALL;
 
397
            pj_memcpy(&sock_addr.ipv4.sin_addr, src, 4);
 
398
            addr_len = sizeof(pj_sockaddr_in);
 
399
            addr_str_len = PJ_INET_ADDRSTRLEN;
 
400
        } else if (af == PJ_AF_INET6) {
 
401
            if (size < PJ_INET6_ADDRSTRLEN)
 
402
                return PJ_ETOOSMALL;
 
403
            pj_memcpy(&sock_addr.ipv6.sin6_addr, src, 16);
 
404
            addr_len = sizeof(pj_sockaddr_in6);
 
405
            addr_str_len = PJ_INET6_ADDRSTRLEN;
 
406
        } else {
 
407
            pj_assert(!"Unsupported address family");
 
408
            return PJ_EAFNOTSUP;
 
409
        }
 
410
 
 
411
#if PJ_NATIVE_STRING_IS_UNICODE
 
412
        rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len,
 
413
                                NULL, wtempaddr, &addr_str_len);
 
414
        if (rc == 0) {
 
415
            pj_unicode_to_ansi(wtempaddr, wcslen(wtempaddr), dst, size);
 
416
        }
 
417
#else
 
418
        rc = WSAAddressToString((LPSOCKADDR)&sock_addr, addr_len,
 
419
                                NULL, dst, &addr_str_len);
 
420
#endif
 
421
 
 
422
        if (rc != 0) {
 
423
            pj_status_t status = pj_get_netos_error();
 
424
            if (status == PJ_SUCCESS)
 
425
                status = PJ_EUNKNOWN;
 
426
 
 
427
            return status;
 
428
        }
 
429
 
 
430
        return PJ_SUCCESS;
 
431
    }
 
432
 
 
433
#elif !defined(PJ_HAS_IPV6) || PJ_HAS_IPV6==0
 
434
    /* IPv6 support is disabled, just return error without raising assertion */
 
435
    return PJ_EIPV6NOTSUP;
 
436
#else
 
437
    pj_assert(!"Not supported");
 
438
    return PJ_EIPV6NOTSUP;
 
439
#endif
 
440
}
 
441
 
 
442
/*
 
443
 * Get hostname.
 
444
 */
 
445
PJ_DEF(const pj_str_t*) pj_gethostname(void)
 
446
{
 
447
    static char buf[PJ_MAX_HOSTNAME];
 
448
    static pj_str_t hostname;
 
449
 
 
450
    PJ_CHECK_STACK();
 
451
 
 
452
    if (hostname.ptr == NULL) {
 
453
        hostname.ptr = buf;
 
454
        if (gethostname(buf, sizeof(buf)) != 0) {
 
455
            hostname.ptr[0] = '\0';
 
456
            hostname.slen = 0;
 
457
        } else {
 
458
            hostname.slen = strlen(buf);
 
459
        }
 
460
    }
 
461
    return &hostname;
 
462
}
 
463
 
 
464
#if defined(PJ_WIN32)
 
465
/*
 
466
 * Create new socket/endpoint for communication and returns a descriptor.
 
467
 */
 
468
PJ_DEF(pj_status_t) pj_sock_socket(int af, 
 
469
                                   int type, 
 
470
                                   int proto,
 
471
                                   pj_sock_t *sock)
 
472
{
 
473
    PJ_CHECK_STACK();
 
474
 
 
475
    /* Sanity checks. */
 
476
    PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
 
477
    PJ_ASSERT_RETURN((unsigned)PJ_INVALID_SOCKET==INVALID_SOCKET, 
 
478
                     (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
 
479
 
 
480
    *sock = WSASocket(af, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED);
 
481
 
 
482
    if (*sock == PJ_INVALID_SOCKET) 
 
483
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
484
    
 
485
#if PJ_SOCK_DISABLE_WSAECONNRESET && \
 
486
    (!defined(PJ_WIN32_WINCE) || PJ_WIN32_WINCE==0)
 
487
 
 
488
#ifndef SIO_UDP_CONNRESET
 
489
    #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
 
490
#endif
 
491
 
 
492
    /* Disable WSAECONNRESET for UDP.
 
493
     * See https://trac.pjsip.org/repos/ticket/1197
 
494
     */
 
495
    if (type==PJ_SOCK_DGRAM) {
 
496
        DWORD dwBytesReturned = 0;
 
497
        BOOL bNewBehavior = FALSE;
 
498
        DWORD rc;
 
499
 
 
500
        rc = WSAIoctl(*sock, SIO_UDP_CONNRESET,
 
501
                      &bNewBehavior, sizeof(bNewBehavior),
 
502
                      NULL, 0, &dwBytesReturned,
 
503
                      NULL, NULL);
 
504
 
 
505
        if (rc==SOCKET_ERROR) {
 
506
            // Ignored..
 
507
        }
 
508
    }
 
509
#endif
 
510
 
 
511
    return PJ_SUCCESS;
 
512
}
 
513
 
 
514
#else
 
515
/*
 
516
 * Create new socket/endpoint for communication and returns a descriptor.
 
517
 */
 
518
PJ_DEF(pj_status_t) pj_sock_socket(int af, 
 
519
                                   int type, 
 
520
                                   int proto, 
 
521
                                   pj_sock_t *sock)
 
522
{
 
523
 
 
524
    PJ_CHECK_STACK();
 
525
 
 
526
    /* Sanity checks. */
 
527
    PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
 
528
    PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1, 
 
529
                     (*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
 
530
    
 
531
    *sock = socket(af, type, proto);
 
532
    if (*sock == PJ_INVALID_SOCKET)
 
533
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
534
    else {
 
535
        pj_int32_t val = 1;
 
536
        if (type == pj_SOCK_STREAM()) {
 
537
            pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), pj_SO_NOSIGPIPE(),
 
538
                               &val, sizeof(val));
 
539
        }
 
540
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
 
541
    PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
 
542
        if (type == pj_SOCK_DGRAM()) {
 
543
            pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), SO_NOSIGPIPE, 
 
544
                               &val, sizeof(val));
 
545
        }
 
546
#endif
 
547
        return PJ_SUCCESS;
 
548
    }
 
549
}
 
550
#endif
 
551
 
 
552
/*
 
553
 * Bind socket.
 
554
 */
 
555
PJ_DEF(pj_status_t) pj_sock_bind( pj_sock_t sock, 
 
556
                                  const pj_sockaddr_t *addr,
 
557
                                  int len)
 
558
{
 
559
    PJ_CHECK_STACK();
 
560
 
 
561
    PJ_ASSERT_RETURN(addr && len >= (int)sizeof(struct sockaddr_in), PJ_EINVAL);
 
562
 
 
563
    CHECK_ADDR_LEN(addr, len);
 
564
 
 
565
    if (bind(sock, (struct sockaddr*)addr, len) != 0)
 
566
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
567
    else
 
568
        return PJ_SUCCESS;
 
569
}
 
570
 
 
571
 
 
572
/*
 
573
 * Bind socket.
 
574
 */
 
575
PJ_DEF(pj_status_t) pj_sock_bind_in( pj_sock_t sock, 
 
576
                                     pj_uint32_t addr32,
 
577
                                     pj_uint16_t port)
 
578
{
 
579
    pj_sockaddr_in addr;
 
580
 
 
581
    PJ_CHECK_STACK();
 
582
 
 
583
    PJ_SOCKADDR_SET_LEN(&addr, sizeof(pj_sockaddr_in));
 
584
    addr.sin_family = PJ_AF_INET;
 
585
    pj_bzero(addr.sin_zero, sizeof(addr.sin_zero));
 
586
    addr.sin_addr.s_addr = pj_htonl(addr32);
 
587
    addr.sin_port = pj_htons(port);
 
588
 
 
589
    return pj_sock_bind(sock, &addr, sizeof(pj_sockaddr_in));
 
590
}
 
591
 
 
592
 
 
593
/*
 
594
 * Close socket.
 
595
 */
 
596
PJ_DEF(pj_status_t) pj_sock_close(pj_sock_t sock)
 
597
{
 
598
    int rc;
 
599
 
 
600
    PJ_CHECK_STACK();
 
601
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
 
602
    defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
 
603
    rc = closesocket(sock);
 
604
#else
 
605
    rc = close(sock);
 
606
#endif
 
607
 
 
608
    if (rc != 0)
 
609
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
610
    else
 
611
        return PJ_SUCCESS;
 
612
}
 
613
 
 
614
/*
 
615
 * Get remote's name.
 
616
 */
 
617
PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock,
 
618
                                         pj_sockaddr_t *addr,
 
619
                                         int *namelen)
 
620
{
 
621
    PJ_CHECK_STACK();
 
622
    if (getpeername(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
 
623
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
624
    else {
 
625
        PJ_SOCKADDR_RESET_LEN(addr);
 
626
        return PJ_SUCCESS;
 
627
    }
 
628
}
 
629
 
 
630
/*
 
631
 * Get socket name.
 
632
 */
 
633
PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock,
 
634
                                         pj_sockaddr_t *addr,
 
635
                                         int *namelen)
 
636
{
 
637
    PJ_CHECK_STACK();
 
638
    if (getsockname(sock, (struct sockaddr*)addr, (socklen_t*)namelen) != 0)
 
639
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
640
    else {
 
641
        PJ_SOCKADDR_RESET_LEN(addr);
 
642
        return PJ_SUCCESS;
 
643
    }
 
644
}
 
645
 
 
646
/*
 
647
 * Send data
 
648
 */
 
649
PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock,
 
650
                                 const void *buf,
 
651
                                 pj_ssize_t *len,
 
652
                                 unsigned flags)
 
653
{
 
654
    PJ_CHECK_STACK();
 
655
    PJ_ASSERT_RETURN(len, PJ_EINVAL);
 
656
 
 
657
    *len = send(sock, (const char*)buf, *len, flags);
 
658
 
 
659
    if (*len < 0)
 
660
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
661
    else
 
662
        return PJ_SUCCESS;
 
663
}
 
664
 
 
665
 
 
666
/*
 
667
 * Send data.
 
668
 */
 
669
PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock,
 
670
                                   const void *buf,
 
671
                                   pj_ssize_t *len,
 
672
                                   unsigned flags,
 
673
                                   const pj_sockaddr_t *to,
 
674
                                   int tolen)
 
675
{
 
676
    PJ_CHECK_STACK();
 
677
    PJ_ASSERT_RETURN(len, PJ_EINVAL);
 
678
    
 
679
    CHECK_ADDR_LEN(to, tolen);
 
680
 
 
681
    *len = sendto(sock, (const char*)buf, *len, flags, 
 
682
                  (const struct sockaddr*)to, tolen);
 
683
 
 
684
    if (*len < 0) 
 
685
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
686
    else 
 
687
        return PJ_SUCCESS;
 
688
}
 
689
 
 
690
/*
 
691
 * Receive data.
 
692
 */
 
693
PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock,
 
694
                                 void *buf,
 
695
                                 pj_ssize_t *len,
 
696
                                 unsigned flags)
 
697
{
 
698
    PJ_CHECK_STACK();
 
699
    PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
 
700
 
 
701
    *len = recv(sock, (char*)buf, *len, flags);
 
702
 
 
703
    if (*len < 0) 
 
704
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
705
    else
 
706
        return PJ_SUCCESS;
 
707
}
 
708
 
 
709
/*
 
710
 * Receive data.
 
711
 */
 
712
PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock,
 
713
                                     void *buf,
 
714
                                     pj_ssize_t *len,
 
715
                                     unsigned flags,
 
716
                                     pj_sockaddr_t *from,
 
717
                                     int *fromlen)
 
718
{
 
719
    PJ_CHECK_STACK();
 
720
    PJ_ASSERT_RETURN(buf && len, PJ_EINVAL);
 
721
    PJ_ASSERT_RETURN(from && fromlen, (*len=-1, PJ_EINVAL));
 
722
 
 
723
    *len = recvfrom(sock, (char*)buf, *len, flags, 
 
724
                    (struct sockaddr*)from, (socklen_t*)fromlen);
 
725
 
 
726
    if (*len < 0) 
 
727
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
728
    else {
 
729
        PJ_SOCKADDR_RESET_LEN(from);
 
730
        return PJ_SUCCESS;
 
731
    }
 
732
}
 
733
 
 
734
/*
 
735
 * Get socket option.
 
736
 */
 
737
PJ_DEF(pj_status_t) pj_sock_getsockopt( pj_sock_t sock,
 
738
                                        pj_uint16_t level,
 
739
                                        pj_uint16_t optname,
 
740
                                        void *optval,
 
741
                                        int *optlen)
 
742
{
 
743
    PJ_CHECK_STACK();
 
744
    PJ_ASSERT_RETURN(optval && optlen, PJ_EINVAL);
 
745
 
 
746
    if (getsockopt(sock, level, optname, (char*)optval, (socklen_t*)optlen)!=0)
 
747
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
748
    else
 
749
        return PJ_SUCCESS;
 
750
}
 
751
 
 
752
/*
 
753
 * Set socket option.
 
754
 */
 
755
PJ_DEF(pj_status_t) pj_sock_setsockopt( pj_sock_t sock,
 
756
                                        pj_uint16_t level,
 
757
                                        pj_uint16_t optname,
 
758
                                        const void *optval,
 
759
                                        int optlen)
 
760
{
 
761
    PJ_CHECK_STACK();
 
762
    if (setsockopt(sock, level, optname, (const char*)optval, optlen) != 0)
 
763
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
764
    else
 
765
        return PJ_SUCCESS;
 
766
}
 
767
 
 
768
/*
 
769
 * Connect socket.
 
770
 */
 
771
PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock,
 
772
                                     const pj_sockaddr_t *addr,
 
773
                                     int namelen)
 
774
{
 
775
    PJ_CHECK_STACK();
 
776
    if (connect(sock, (struct sockaddr*)addr, namelen) != 0)
 
777
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
778
    else
 
779
        return PJ_SUCCESS;
 
780
}
 
781
 
 
782
 
 
783
/*
 
784
 * Shutdown socket.
 
785
 */
 
786
#if PJ_HAS_TCP
 
787
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock,
 
788
                                      int how)
 
789
{
 
790
    PJ_CHECK_STACK();
 
791
    if (shutdown(sock, how) != 0)
 
792
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
793
    else
 
794
        return PJ_SUCCESS;
 
795
}
 
796
 
 
797
/*
 
798
 * Start listening to incoming connections.
 
799
 */
 
800
PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock,
 
801
                                    int backlog)
 
802
{
 
803
    PJ_CHECK_STACK();
 
804
    if (listen(sock, backlog) != 0)
 
805
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
806
    else
 
807
        return PJ_SUCCESS;
 
808
}
 
809
 
 
810
/*
 
811
 * Accept incoming connections
 
812
 */
 
813
PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
 
814
                                    pj_sock_t *newsock,
 
815
                                    pj_sockaddr_t *addr,
 
816
                                    int *addrlen)
 
817
{
 
818
    PJ_CHECK_STACK();
 
819
    PJ_ASSERT_RETURN(newsock != NULL, PJ_EINVAL);
 
820
 
 
821
#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
 
822
    if (addr) {
 
823
        PJ_SOCKADDR_SET_LEN(addr, *addrlen);
 
824
    }
 
825
#endif
 
826
    
 
827
    *newsock = accept(serverfd, (struct sockaddr*)addr, (socklen_t*)addrlen);
 
828
    if (*newsock==PJ_INVALID_SOCKET)
 
829
        return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
 
830
    else {
 
831
        
 
832
#if defined(PJ_SOCKADDR_HAS_LEN) && PJ_SOCKADDR_HAS_LEN!=0
 
833
        if (addr) {
 
834
            PJ_SOCKADDR_RESET_LEN(addr);
 
835
        }
 
836
#endif
 
837
            
 
838
        return PJ_SUCCESS;
 
839
    }
 
840
}
 
841
#endif  /* PJ_HAS_TCP */
 
842
 
 
843