~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/net/net_util_md.java

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
 
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
4
 *
 
5
 * This code is free software; you can redistribute it and/or modify it
 
6
 * under the terms of the GNU General Public License version 2 only, as
 
7
 * published by the Free Software Foundation.  Oracle designates this
 
8
 * particular file as subject to the "Classpath" exception as provided
 
9
 * by Oracle in the LICENSE file that accompanied this code.
 
10
 *
 
11
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
14
 * version 2 for more details (a copy is included in the LICENSE file that
 
15
 * accompanied this code).
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License version
 
18
 * 2 along with this work; if not, write to the Free Software Foundation,
 
19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 *
 
21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
22
 * or visit www.oracle.com if you need additional information or have any
 
23
 * questions.
 
24
 */
 
25
 
 
26
package java.net;
 
27
 
 
28
import java.io.FileDescriptor;
 
29
import cli.System.Net.IPAddress;
 
30
import cli.System.Net.IPEndPoint;
 
31
import static ikvm.internal.JNI.*;
 
32
import static ikvm.internal.Winsock.*;
 
33
 
 
34
final class net_util_md
 
35
{
 
36
    private net_util_md() { }
 
37
 
 
38
    static final int INADDR_ANY = 0;
 
39
 
 
40
    static final int IPTOS_TOS_MASK = 0x1e;
 
41
    static final int IPTOS_PREC_MASK = 0xe0;
 
42
 
 
43
    static boolean isRcvTimeoutSupported = true;
 
44
 
 
45
    /*
 
46
     * Table of Windows Sockets errors, the specific exception we
 
47
     * throw for the error, and the error text.
 
48
     *
 
49
     * Note that this table excludes OS dependent errors.
 
50
     *
 
51
     * Latest list of Windows Sockets errors can be found at :-
 
52
     * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm
 
53
     */
 
54
    private static class WinsockError
 
55
    {
 
56
        final int errCode;
 
57
        final int exc;
 
58
        final String errString;
 
59
 
 
60
        WinsockError(int errCode, int exc, String errString)
 
61
        {
 
62
            this.errCode = errCode;
 
63
            this.exc = exc;
 
64
            this.errString = errString;
 
65
        }
 
66
    }
 
67
 
 
68
    private static final int Exception_BindException = 1;
 
69
    private static final int Exception_ConnectException = 2;
 
70
    private static final int Exception_NoRouteToHostException = 3;
 
71
 
 
72
    private static final WinsockError[] winsock_errors = {
 
73
        new WinsockError(WSAEACCES,                0,      "Permission denied"),
 
74
        new WinsockError(WSAEADDRINUSE,            Exception_BindException,        "Address already in use"),
 
75
        new WinsockError(WSAEADDRNOTAVAIL,         Exception_BindException,        "Cannot assign requested address"),
 
76
        new WinsockError(WSAEAFNOSUPPORT,          0,      "Address family not supported by protocol family"),
 
77
        new WinsockError(WSAEALREADY,              0,      "Operation already in progress"),
 
78
        new WinsockError(WSAECONNABORTED,          0,      "Software caused connection abort"),
 
79
        new WinsockError(WSAECONNREFUSED,          Exception_ConnectException,     "Connection refused"),
 
80
        new WinsockError(WSAECONNRESET,            0,      "Connection reset by peer"),
 
81
        new WinsockError(WSAEDESTADDRREQ,          0,      "Destination address required"),
 
82
        new WinsockError(WSAEFAULT,                0,      "Bad address"),
 
83
        new WinsockError(WSAEHOSTDOWN,             0,      "Host is down"),
 
84
        new WinsockError(WSAEHOSTUNREACH,          Exception_NoRouteToHostException,       "No route to host"),
 
85
        new WinsockError(WSAEINPROGRESS,           0,      "Operation now in progress"),
 
86
        new WinsockError(WSAEINTR,                 0,      "Interrupted function call"),
 
87
        new WinsockError(WSAEINVAL,                0,      "Invalid argument"),
 
88
        new WinsockError(WSAEISCONN,               0,      "Socket is already connected"),
 
89
        new WinsockError(WSAEMFILE,                0,      "Too many open files"),
 
90
        new WinsockError(WSAEMSGSIZE,              0,      "The message is larger than the maximum supported by the underlying transport"),
 
91
        new WinsockError(WSAENETDOWN,              0,      "Network is down"),
 
92
        new WinsockError(WSAENETRESET,             0,      "Network dropped connection on reset"),
 
93
        new WinsockError(WSAENETUNREACH,           0,      "Network is unreachable"),
 
94
        new WinsockError(WSAENOBUFS,               0,      "No buffer space available (maximum connections reached?)"),
 
95
        new WinsockError(WSAENOPROTOOPT,           0,      "Bad protocol option"),
 
96
        new WinsockError(WSAENOTCONN,              0,      "Socket is not connected"),
 
97
        new WinsockError(WSAENOTSOCK,              0,      "Socket operation on nonsocket"),
 
98
        new WinsockError(WSAEOPNOTSUPP,            0,      "Operation not supported"),
 
99
        new WinsockError(WSAEPFNOSUPPORT,          0,      "Protocol family not supported"),
 
100
        new WinsockError(WSAEPROCLIM,              0,      "Too many processes"),
 
101
        new WinsockError(WSAEPROTONOSUPPORT,       0,      "Protocol not supported"),
 
102
        new WinsockError(WSAEPROTOTYPE,            0,      "Protocol wrong type for socket"),
 
103
        new WinsockError(WSAESHUTDOWN,             0,      "Cannot send after socket shutdown"),
 
104
        new WinsockError(WSAESOCKTNOSUPPORT,       0,      "Socket type not supported"),
 
105
        new WinsockError(WSAETIMEDOUT,             Exception_ConnectException,     "Connection timed out"),
 
106
        new WinsockError(WSATYPE_NOT_FOUND,        0,      "Class type not found"),
 
107
        new WinsockError(WSAEWOULDBLOCK,           0,      "Resource temporarily unavailable"),
 
108
        new WinsockError(WSAHOST_NOT_FOUND,        0,      "Host not found"),
 
109
        new WinsockError(WSA_NOT_ENOUGH_MEMORY,    0,      "Insufficient memory available"),
 
110
        new WinsockError(WSANOTINITIALISED,        0,      "Successful WSAStartup not yet performed"),
 
111
        new WinsockError(WSANO_DATA,               0,      "Valid name, no data record of requested type"),
 
112
        new WinsockError(WSANO_RECOVERY,           0,      "This is a nonrecoverable error"),
 
113
        new WinsockError(WSASYSNOTREADY,           0,      "Network subsystem is unavailable"),
 
114
        new WinsockError(WSATRY_AGAIN,             0,      "Nonauthoritative host not found"),
 
115
        new WinsockError(WSAVERNOTSUPPORTED,       0,      "Winsock.dll version out of range"),
 
116
        new WinsockError(WSAEDISCON,               0,      "Graceful shutdown in progress"),
 
117
        new WinsockError(WSA_OPERATION_ABORTED,    0,      "Overlapped operation aborted")
 
118
    };
 
119
 
 
120
    /*
 
121
     * Since winsock doesn't have the equivalent of strerror(errno)
 
122
     * use table to lookup error text for the error.
 
123
     */
 
124
    static SocketException NET_ThrowNew(int errorNum, String msg)
 
125
    {
 
126
        int i;
 
127
        int table_size = winsock_errors.length;
 
128
        int excP = 0;
 
129
        String fullMsg;
 
130
 
 
131
        if (msg == null) {
 
132
            msg = "no further information";
 
133
        }
 
134
 
 
135
        /*
 
136
         * Check table for known winsock errors
 
137
         */
 
138
        i=0;
 
139
        while (i < table_size) {
 
140
            if (errorNum == winsock_errors[i].errCode) {
 
141
                break;
 
142
            }
 
143
            i++;
 
144
        }
 
145
 
 
146
        /*
 
147
         * If found get pick the specific exception and error
 
148
         * message corresponding to this error.
 
149
         */
 
150
        if (i < table_size) {
 
151
            excP = winsock_errors[i].exc;
 
152
            fullMsg = winsock_errors[i].errString + ": " + msg;
 
153
        } else {
 
154
            fullMsg = "Unrecognized Windows Sockets error: " + errorNum + ": " + msg;
 
155
        }
 
156
 
 
157
        /*
 
158
         * Throw SocketException if no specific exception for this
 
159
         * error.
 
160
         */
 
161
        switch (excP) {
 
162
            case Exception_BindException:
 
163
                return new BindException(fullMsg);
 
164
            case Exception_ConnectException:
 
165
                return new ConnectException(fullMsg);
 
166
            case Exception_NoRouteToHostException:
 
167
                return new NoRouteToHostException(fullMsg);
 
168
            default:
 
169
                return new SocketException(fullMsg);
 
170
        }
 
171
    }
 
172
 
 
173
    static void NET_ThrowNew(JNIEnv env, int errorNum, String msg)
 
174
    {
 
175
        env.Throw(NET_ThrowNew(errorNum, msg));
 
176
    }
 
177
 
 
178
    static SocketException NET_ThrowCurrent(String msg)
 
179
    {
 
180
        return NET_ThrowNew(WSAGetLastError(), msg);
 
181
    }
 
182
 
 
183
    static void NET_ThrowCurrent(JNIEnv env, String msg)
 
184
    {
 
185
        env.Throw(NET_ThrowCurrent(msg));
 
186
    }
 
187
 
 
188
    /*
 
189
     * Return the default TOS value
 
190
     */
 
191
    static int NET_GetDefaultTOS() {
 
192
        // we always use the "default" default...
 
193
        return 0;
 
194
    }
 
195
 
 
196
    /*
 
197
     * Map the Java level socket option to the platform specific
 
198
     * level and option name.
 
199
     */
 
200
 
 
201
    private static final class sockopts {
 
202
        int cmd;
 
203
        int level;
 
204
        int optname;
 
205
 
 
206
        sockopts(int cmd, int level, int optname) {
 
207
            this.cmd = cmd;
 
208
            this.level = level;
 
209
            this.optname = optname;
 
210
        }
 
211
    }
 
212
 
 
213
    private static final sockopts opts[] = {
 
214
        new sockopts(SocketOptions.TCP_NODELAY,   IPPROTO_TCP,    TCP_NODELAY ),
 
215
        new sockopts(SocketOptions.SO_OOBINLINE,  SOL_SOCKET,     SO_OOBINLINE ),
 
216
        new sockopts(SocketOptions.SO_LINGER,     SOL_SOCKET,     SO_LINGER ),
 
217
        new sockopts(SocketOptions.SO_SNDBUF,     SOL_SOCKET,     SO_SNDBUF ),
 
218
        new sockopts(SocketOptions.SO_RCVBUF,     SOL_SOCKET,     SO_RCVBUF ),
 
219
        new sockopts(SocketOptions.SO_KEEPALIVE,  SOL_SOCKET,     SO_KEEPALIVE ),
 
220
        new sockopts(SocketOptions.SO_REUSEADDR,  SOL_SOCKET,     SO_REUSEADDR ),
 
221
        new sockopts(SocketOptions.SO_BROADCAST,  SOL_SOCKET,     SO_BROADCAST ),
 
222
        new sockopts(SocketOptions.IP_MULTICAST_IF,   IPPROTO_IP, IP_MULTICAST_IF ),
 
223
        new sockopts(SocketOptions.IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP ),
 
224
        new sockopts(SocketOptions.IP_TOS,            IPPROTO_IP, IP_TOS ),
 
225
 
 
226
    };
 
227
 
 
228
    /* call NET_MapSocketOptionV6 for the IPv6 fd only
 
229
     * and NET_MapSocketOption for the IPv4 fd
 
230
     */
 
231
    static int NET_MapSocketOptionV6(int cmd, int[] level, int[] optname) {
 
232
 
 
233
        switch (cmd) {
 
234
            case SocketOptions.IP_MULTICAST_IF:
 
235
            case SocketOptions.IP_MULTICAST_IF2:
 
236
                level[0] = IPPROTO_IPV6;
 
237
                optname[0] = IPV6_MULTICAST_IF;
 
238
                return 0;
 
239
 
 
240
            case SocketOptions.IP_MULTICAST_LOOP:
 
241
                level[0] = IPPROTO_IPV6;
 
242
                optname[0] = IPV6_MULTICAST_LOOP;
 
243
                return 0;
 
244
        }
 
245
        return NET_MapSocketOption (cmd, level, optname);
 
246
    }
 
247
 
 
248
    static int NET_MapSocketOption(int cmd, int[] level, int[] optname) {
 
249
        /*
 
250
         * Map the Java level option to the native level
 
251
         */
 
252
        for (int i=0; i<opts.length; i++) {
 
253
            if (cmd == opts[i].cmd) {
 
254
                level[0] = opts[i].level;
 
255
                optname[0] = opts[i].optname;
 
256
                return 0;
 
257
            }
 
258
        }
 
259
 
 
260
        /* not found */
 
261
        return -1;
 
262
    }
 
263
 
 
264
    static int NET_SetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval)
 
265
    {
 
266
        int rv;
 
267
 
 
268
        if (level == IPPROTO_IP && optname == IP_TOS) {
 
269
            int tos = (Integer)optval;
 
270
            tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
 
271
            optval = tos;
 
272
        }
 
273
 
 
274
        rv = setsockopt(s, level, optname, optval);
 
275
 
 
276
        if (rv == SOCKET_ERROR) {
 
277
            /*
 
278
             * IP_TOS & IP_MULTICAST_LOOP can't be set on some versions
 
279
             * of Windows.
 
280
             */
 
281
            if ((WSAGetLastError() == WSAENOPROTOOPT) &&
 
282
                (level == IPPROTO_IP) &&
 
283
                (optname == IP_TOS || optname == IP_MULTICAST_LOOP)) {
 
284
                rv = 0;
 
285
            }
 
286
 
 
287
            /*
 
288
             * IP_TOS can't be set on unbound UDP sockets.
 
289
             */
 
290
            if ((WSAGetLastError() == WSAEINVAL) &&
 
291
                (level == IPPROTO_IP) &&
 
292
                (optname == IP_TOS)) {
 
293
                rv = 0;
 
294
            }
 
295
        }
 
296
 
 
297
        return rv;
 
298
    }
 
299
 
 
300
    /*
 
301
     * Wrapper for setsockopt dealing with Windows specific issues :-
 
302
     *
 
303
     * IP_TOS is not supported on some versions of Windows so
 
304
     * instead return the default value for the OS.
 
305
     */
 
306
    static int NET_GetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval)
 
307
    {
 
308
        int rv;
 
309
 
 
310
        rv = getsockopt(s, level, optname, optval);
 
311
 
 
312
 
 
313
        /*
 
314
         * IPPROTO_IP/IP_TOS is not supported on some Windows
 
315
         * editions so return the default type-of-service
 
316
         * value.
 
317
         */
 
318
        if (rv == SOCKET_ERROR) {
 
319
 
 
320
            if (WSAGetLastError() == WSAENOPROTOOPT &&
 
321
                level == IPPROTO_IP && optname == IP_TOS) {
 
322
 
 
323
                ((int[])optval)[0] = NET_GetDefaultTOS();
 
324
 
 
325
                rv = 0;
 
326
            }
 
327
        }
 
328
 
 
329
        return rv;
 
330
    }
 
331
 
 
332
    /*
 
333
     * Wrapper for bind winsock call - transparent converts an
 
334
     * error related to binding to a port that has exclusive access
 
335
     * into an error indicating the port is in use (facilitates
 
336
     * better error reporting).
 
337
     */
 
338
    static int NET_Bind(cli.System.Net.Sockets.Socket s, SOCKETADDRESS him)
 
339
    {
 
340
        int rv = bind(s, him);
 
341
 
 
342
        if (rv == SOCKET_ERROR) {
 
343
            /*
 
344
             * If bind fails with WSAEACCES it means that a privileged
 
345
             * process has done an exclusive bind (NT SP4/2000/XP only).
 
346
             */
 
347
            if (WSAGetLastError() == WSAEACCES) {
 
348
                WSASetLastError(WSAEADDRINUSE);
 
349
            }
 
350
        }
 
351
 
 
352
        return rv;
 
353
    }
 
354
 
 
355
    static int NET_SocketClose(cli.System.Net.Sockets.Socket fd) {
 
356
        linger l = new linger();
 
357
        int ret;
 
358
        if (getsockopt(fd, SOL_SOCKET, SO_LINGER, l) == 0) {
 
359
            if (l.l_onoff == 0) {
 
360
                WSASendDisconnect(fd);
 
361
            }
 
362
        }
 
363
        ret = closesocket (fd);
 
364
        return ret;
 
365
    }
 
366
 
 
367
    static int NET_Timeout(cli.System.Net.Sockets.Socket fd, long timeout) {
 
368
        int ret;
 
369
        fd_set tbl = new fd_set();
 
370
        timeval t = new timeval();
 
371
        t.tv_sec = timeout / 1000;
 
372
        t.tv_usec = (timeout % 1000) * 1000;
 
373
        FD_ZERO(tbl);
 
374
        FD_SET(fd, tbl);
 
375
        ret = select (tbl, null, null, t);
 
376
        return ret;
 
377
    }
 
378
 
 
379
    /*
 
380
     * differs from NET_Timeout() as follows:
 
381
     *
 
382
     * If timeout = -1, it blocks forever.
 
383
     *
 
384
     * returns 1 or 2 depending if only one or both sockets
 
385
     * fire at same time.
 
386
     *
 
387
     * *fdret is (one of) the active fds. If both sockets
 
388
     * fire at same time, *fdret = fd always.
 
389
     */
 
390
    static int NET_Timeout2(cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, long timeout, cli.System.Net.Sockets.Socket[] fdret) {
 
391
        int ret;
 
392
        fd_set tbl = new fd_set();
 
393
        timeval t = new timeval();
 
394
        if (timeout == -1) {
 
395
            t = null;
 
396
        } else {
 
397
            t.tv_sec = timeout / 1000;
 
398
            t.tv_usec = (timeout % 1000) * 1000;
 
399
        }
 
400
        FD_ZERO(tbl);
 
401
        FD_SET(fd, tbl);
 
402
        FD_SET(fd1, tbl);
 
403
        ret = select (tbl, null, null, t);
 
404
        switch (ret) {
 
405
        case 0:
 
406
            return 0; /* timeout */
 
407
        case 1:
 
408
            if (FD_ISSET (fd, tbl)) {
 
409
                fdret[0]= fd;
 
410
            } else {
 
411
                fdret[0]= fd1;
 
412
            }
 
413
            return 1;
 
414
        case 2:
 
415
            fdret[0]= fd;
 
416
            return 2;
 
417
        }
 
418
        return -1;
 
419
    }
 
420
 
 
421
    /*
 
422
     * if ipv6 is available, call NET_BindV6 to bind to the required address/port.
 
423
     * Because the same port number may need to be reserved in both v4 and v6 space,
 
424
     * this may require socket(s) to be re-opened. Therefore, all of this information
 
425
     * is passed in and returned through the ipv6bind structure.
 
426
     *
 
427
     * If the request is to bind to a specific address, then this (by definition) means
 
428
     * only bind in either v4 or v6, and this is just the same as normal. ie. a single
 
429
     * call to bind() will suffice. The other socket is closed in this case.
 
430
     *
 
431
     * The more complicated case is when the requested address is ::0 or 0.0.0.0.
 
432
     *
 
433
     * Two further cases:
 
434
     * 2. If the reqeusted port is 0 (ie. any port) then we try to bind in v4 space
 
435
     *    first with a wild-card port argument. We then try to bind in v6 space
 
436
     *    using the returned port number. If this fails, we repeat the process
 
437
     *    until a free port common to both spaces becomes available.
 
438
     *
 
439
     * 3. If the requested port is a specific port, then we just try to get that
 
440
     *    port in both spaces, and if it is not free in both, then the bind fails.
 
441
     *
 
442
     * On failure, sockets are closed and an error returned with CLOSE_SOCKETS_AND_RETURN
 
443
     */
 
444
 
 
445
    static class ipv6bind {
 
446
        SOCKETADDRESS addr;
 
447
        cli.System.Net.Sockets.Socket ipv4_fd;
 
448
        cli.System.Net.Sockets.Socket ipv6_fd;
 
449
    }
 
450
 
 
451
    private static int CLOSE_SOCKETS_AND_RETURN(
 
452
        cli.System.Net.Sockets.Socket fd,
 
453
        cli.System.Net.Sockets.Socket ofd,
 
454
        cli.System.Net.Sockets.Socket close_fd,
 
455
        cli.System.Net.Sockets.Socket close_ofd,
 
456
        ipv6bind b) {
 
457
        if (fd != null) {
 
458
            closesocket (fd);
 
459
        }
 
460
        if (ofd != null) {
 
461
            closesocket (ofd);
 
462
        }
 
463
        if (close_fd != null) {
 
464
            closesocket (close_fd);
 
465
        }
 
466
        if (close_ofd != null) {
 
467
            closesocket (close_ofd);
 
468
        }
 
469
        b.ipv4_fd = b.ipv6_fd = null;
 
470
        return SOCKET_ERROR;
 
471
    }
 
472
 
 
473
    static int NET_BindV6(ipv6bind b) {
 
474
        cli.System.Net.Sockets.Socket fd = null;
 
475
        cli.System.Net.Sockets.Socket ofd = null;
 
476
        int rv;
 
477
        /* need to defer close until new sockets created */
 
478
        cli.System.Net.Sockets.Socket close_fd = null;
 
479
        cli.System.Net.Sockets.Socket close_ofd = null;
 
480
 
 
481
        SOCKETADDRESS oaddr = new SOCKETADDRESS();
 
482
        int family = b.addr.him.sa_family;
 
483
        int ofamily;
 
484
        int port;
 
485
        int bound_port;
 
486
 
 
487
        if (family == AF_INET && (b.addr.him4.sin_addr.s_addr != INADDR_ANY)) {
 
488
            /* bind to v4 only */
 
489
            int ret;
 
490
            ret = NET_Bind (b.ipv4_fd, b.addr);
 
491
            if (ret == SOCKET_ERROR) {
 
492
                return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
493
            }
 
494
            closesocket (b.ipv6_fd);
 
495
            b.ipv6_fd = null;
 
496
            return 0;
 
497
        }
 
498
        if (family == AF_INET6 && (!IN6ADDR_ISANY(b.addr))) {
 
499
            /* bind to v6 only */
 
500
            int ret;
 
501
            ret = NET_Bind (b.ipv6_fd, b.addr);
 
502
            if (ret == SOCKET_ERROR) {
 
503
                return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
504
            }
 
505
            closesocket (b.ipv4_fd);
 
506
            b.ipv4_fd = null;
 
507
            return 0;
 
508
        }
 
509
 
 
510
        /* We need to bind on both stacks, with the same port number */
 
511
 
 
512
        if (family == AF_INET) {
 
513
            ofamily = AF_INET6;
 
514
            fd = b.ipv4_fd;
 
515
            ofd = b.ipv6_fd;
 
516
            port = GET_PORT (b.addr);
 
517
            oaddr.set(new IPEndPoint(IPAddress.IPv6Any, htons(port)));
 
518
        } else {
 
519
            ofamily = AF_INET;
 
520
            ofd = b.ipv4_fd;
 
521
            fd = b.ipv6_fd;
 
522
            port = GET_PORT (b.addr);
 
523
            oaddr.set(new IPEndPoint(IPAddress.Any, htons(port)));
 
524
        }
 
525
 
 
526
        rv = NET_Bind (fd, b.addr);
 
527
        if (rv == SOCKET_ERROR) {
 
528
            return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
529
        }
 
530
 
 
531
        /* get the port and set it in the other address */
 
532
        if (getsockname(fd, b.addr) == -1) {
 
533
            return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
534
        }
 
535
        bound_port = b.addr.sin_port;
 
536
        oaddr.sin_port = bound_port;
 
537
        if ((rv=NET_Bind (ofd, oaddr)) == SOCKET_ERROR) {
 
538
 
 
539
            /* no retries unless, the request was for any free port */
 
540
 
 
541
            if (port != 0) {
 
542
                return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
543
            }
 
544
 
 
545
            int sotype = fd.get_SocketType().Value;
 
546
 
 
547
            /* 50 is an arbitrary limit, just to ensure that this
 
548
             * cannot be an endless loop. Would expect socket creation to
 
549
             * succeed sooner.
 
550
             */
 
551
            for (int retries = 0; retries < 50 /*SOCK_RETRIES*/; retries ++) {
 
552
                close_fd = fd;
 
553
                fd = null;
 
554
                close_ofd = ofd;
 
555
                ofd = null;
 
556
                b.ipv4_fd = null;
 
557
                b.ipv6_fd = null;
 
558
 
 
559
                /* create two new sockets */
 
560
                fd = socket (family, sotype, 0);
 
561
                if (fd == INVALID_SOCKET) {
 
562
                    return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
563
                }
 
564
                ofd = socket (ofamily, sotype, 0);
 
565
                if (ofd == INVALID_SOCKET) {
 
566
                    return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
567
                }
 
568
 
 
569
                /* bind random port on first socket */
 
570
                oaddr.sin_port = 0;
 
571
                rv = NET_Bind (ofd, oaddr);
 
572
                if (rv == SOCKET_ERROR) {
 
573
                    return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
574
                }
 
575
                /* close the original pair of sockets before continuing */
 
576
                closesocket (close_fd);
 
577
                closesocket (close_ofd);
 
578
                close_fd = close_ofd = null;
 
579
 
 
580
                /* bind new port on second socket */
 
581
                if (getsockname(ofd, oaddr) == -1) {
 
582
                    return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
583
                }
 
584
                bound_port = oaddr.sin_port;
 
585
                b.addr.sin_port = bound_port;
 
586
                rv = NET_Bind (fd, b.addr);
 
587
 
 
588
                if (rv != SOCKET_ERROR) {
 
589
                    if (family == AF_INET) {
 
590
                        b.ipv4_fd = fd;
 
591
                        b.ipv6_fd = ofd;
 
592
                    } else {
 
593
                        b.ipv4_fd = ofd;
 
594
                        b.ipv6_fd = fd;
 
595
                    }
 
596
                    return 0;
 
597
                }
 
598
            }
 
599
            return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b);
 
600
        }
 
601
        return 0;
 
602
    }
 
603
 
 
604
    /* If address types is IPv6, then IPv6 must be available. Otherwise
 
605
     * no address can be generated. In the case of an IPv4 Inetaddress this
 
606
     * method will return an IPv4 mapped address where IPv6 is available and
 
607
     * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in
 
608
     * structure for an IPv4 InetAddress.
 
609
    */
 
610
    static int NET_InetAddressToSockaddr(JNIEnv env, InetAddress iaObj, int port, SOCKETADDRESS him, boolean v4MappedAddress) {
 
611
        if (iaObj.family == InetAddress.IPv4) {
 
612
            him.set(new IPEndPoint(new IPAddress(htonl(iaObj.address) & 0xFFFFFFFFL), port));
 
613
            return 0;
 
614
        } else {
 
615
            Inet6Address v6addr = (Inet6Address)iaObj;
 
616
            int scope = v6addr.getScopeId();
 
617
            if (scope == 0) {
 
618
                him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress), port));
 
619
                return 0;
 
620
            } else {
 
621
                him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress, scope & 0xFFFFFFFFL), port));
 
622
                return 0;
 
623
            }
 
624
        }
 
625
    }
 
626
 
 
627
    static int NET_GetPortFromSockaddr(SOCKETADDRESS him) {
 
628
        return ntohs(GET_PORT(him));
 
629
    }
 
630
 
 
631
    static boolean NET_IsIPv4Mapped(byte[] caddr) {
 
632
        int i;
 
633
        for (i = 0; i < 10; i++) {
 
634
            if (caddr[i] != 0x00) {
 
635
                return false;
 
636
            }
 
637
        }
 
638
 
 
639
        if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
 
640
            return true;
 
641
        }
 
642
        return false;
 
643
    }
 
644
 
 
645
    static int NET_IPv4MappedToIPv4(byte[] caddr) {
 
646
        return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
 
647
            | (caddr[15] & 0xff);
 
648
    }
 
649
 
 
650
    static boolean NET_IsEqual(byte[] caddr1, byte[] caddr2) {
 
651
        int i;
 
652
        for (i = 0; i < 16; i++) {
 
653
            if (caddr1[i] != caddr2[i]) {
 
654
                return false;
 
655
            }
 
656
        }
 
657
        return true;
 
658
    }
 
659
 
 
660
    static int getScopeID (SOCKETADDRESS him) {
 
661
        return him.him6.sin6_scope_id;
 
662
    }
 
663
 
 
664
    static boolean cmpScopeID (int scope, SOCKETADDRESS him) {
 
665
        return him.him6.sin6_scope_id == scope;
 
666
    }
 
667
 
 
668
    /* these methods are not from net_util_md.c */
 
669
 
 
670
    static boolean ipv6_available() {
 
671
        return InetAddressImplFactory.isIPv6Supported();
 
672
    }
 
673
 
 
674
    static boolean IS_NULL(Object obj) {
 
675
        return obj == null;
 
676
    }
 
677
 
 
678
    static boolean IN6ADDR_ISANY(SOCKETADDRESS him) {
 
679
        if (him.sa_family != AF_INET6) {
 
680
            return false;
 
681
        }
 
682
        byte[] addr = him.him6.sin6_addr;
 
683
        byte b = 0;
 
684
        for (int i = 0; i < addr.length; i++) {
 
685
            b |= addr[i];
 
686
        }
 
687
        return b == 0;
 
688
    }
 
689
 
 
690
    static boolean NET_SockaddrEqualsInetAddress(SOCKETADDRESS him, InetAddress iaObj) {
 
691
        int family = iaObj.family == InetAddress.IPv4 ? AF_INET : AF_INET6;
 
692
 
 
693
        if (him.sa_family == AF_INET6) {
 
694
            byte[] caddrNew = him.him6.sin6_addr;
 
695
                if (NET_IsIPv4Mapped(caddrNew)) {
 
696
                    int addrNew;
 
697
                    int addrCur;
 
698
                    if (family == AF_INET6) {
 
699
                        return false;
 
700
                    }
 
701
                    addrNew = NET_IPv4MappedToIPv4(caddrNew);
 
702
                    addrCur = iaObj.address;
 
703
                    if (addrNew == addrCur) {
 
704
                        return true;
 
705
                    } else {
 
706
                        return false;
 
707
                    }
 
708
                } else {
 
709
                    byte[] caddrCur;
 
710
                    int scope;
 
711
 
 
712
                    if (family == AF_INET) {
 
713
                        return false;
 
714
                    }
 
715
                    scope = ((Inet6Address)iaObj).getScopeId();
 
716
                    caddrCur = ((Inet6Address)iaObj).ipaddress;
 
717
                    if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
 
718
                        return true;
 
719
                    } else {
 
720
                        return false;
 
721
                    }
 
722
                }
 
723
        } else {
 
724
            int addrNew, addrCur;
 
725
            if (family != AF_INET) {
 
726
                return false;
 
727
            }
 
728
            addrNew = ntohl(him.him4.sin_addr.s_addr);
 
729
            addrCur = iaObj.address;
 
730
            if (addrNew == addrCur) {
 
731
                return true;
 
732
            } else {
 
733
                return false;
 
734
            }
 
735
        }
 
736
    }
 
737
 
 
738
    static InetAddress NET_SockaddrToInetAddress(JNIEnv env, SOCKETADDRESS him, int[] port) {
 
739
        return NET_SockaddrToInetAddress(him, port);
 
740
    }
 
741
 
 
742
    static InetAddress NET_SockaddrToInetAddress(SOCKETADDRESS him, int[] port) {
 
743
        InetAddress iaObj;
 
744
        if (him.sa_family == AF_INET6) {
 
745
            byte[] caddr = him.him6.sin6_addr;
 
746
            if (NET_IsIPv4Mapped(caddr)) {
 
747
                iaObj = new Inet4Address(null, NET_IPv4MappedToIPv4(caddr));
 
748
            } else {
 
749
                int scope = getScopeID(him);
 
750
                iaObj = new Inet6Address(null, caddr, scope > 0 ? scope : -1);
 
751
            }
 
752
            port[0] = ntohs(him.him6.sin_port);
 
753
        } else {
 
754
            iaObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr));
 
755
            port[0] = ntohs(him.him4.sin_port);
 
756
        }
 
757
        return iaObj;
 
758
    }
 
759
 
 
760
    static void NET_ThrowByNameWithLastError(JNIEnv env, String exceptionClass, String message) {
 
761
        JNU_ThrowByName(env, exceptionClass, "errno: " + WSAGetLastError() + ", error: " + message + "\n");
 
762
    }
 
763
 
 
764
    static boolean IN_MULTICAST(int ipv4address) {
 
765
        return ((ipv4address >> 24) & 0xf0) == 0xe0;
 
766
    }
 
767
 
 
768
    static boolean IN6_IS_ADDR_MULTICAST(in6_addr address) {
 
769
        return (address.s6_bytes()[0] & 0xff) == 0xff;
 
770
    }
 
771
 
 
772
    static final class SOCKETADDRESS implements IIPEndPointWrapper {
 
773
        final SOCKETADDRESS him = this;
 
774
        final SOCKETADDRESS him4 = this;
 
775
        final SOCKETADDRESS him6 = this;
 
776
        final SOCKETADDRESS sin_addr = this;
 
777
        int sa_family;
 
778
        int sin_port;
 
779
        int s_addr;
 
780
        byte[] sin6_addr;
 
781
        int sin6_scope_id;
 
782
 
 
783
        public void set(IPEndPoint ep) {
 
784
            if (ep == null) {
 
785
                sa_family = 0;
 
786
                sin_port = 0;
 
787
                s_addr = 0;
 
788
                sin6_addr = null;
 
789
                sin6_scope_id = 0;
 
790
            } else {
 
791
                sa_family = ep.get_AddressFamily().Value;
 
792
                sin_port = htons(ep.get_Port());
 
793
                if (sa_family == AF_INET) {
 
794
                    s_addr = (int)ep.get_Address().get_Address();
 
795
                    sin6_addr = null;
 
796
                    sin6_scope_id = 0;
 
797
                } else {
 
798
                    s_addr = 0;
 
799
                    IPAddress addr = ep.get_Address();
 
800
                    sin6_addr = addr.GetAddressBytes();
 
801
                    sin6_scope_id = (int)addr.get_ScopeId();
 
802
                }
 
803
            }
 
804
        }
 
805
 
 
806
        public IPEndPoint get() {
 
807
            if (sa_family == AF_INET) {
 
808
                return new IPEndPoint(new IPAddress(s_addr & 0xFFFFFFFFL), ntohs(sin_port));
 
809
            } else if (sa_family == AF_INET6) {
 
810
                IPAddress addr;
 
811
                if (sin6_addr == null) {
 
812
                    addr = IPAddress.IPv6Any;
 
813
                } else {
 
814
                    addr = new IPAddress(sin6_addr, sin6_scope_id & 0xFFFFFFFFL);
 
815
                }
 
816
                return new IPEndPoint(addr, ntohs(sin_port));
 
817
            } else {
 
818
                return null;
 
819
            }
 
820
        }
 
821
    }
 
822
 
 
823
    static int GET_PORT(SOCKETADDRESS sockaddr) {
 
824
        return sockaddr.sin_port;
 
825
    }
 
826
 
 
827
    static void Sleep(int ms) {
 
828
        cli.System.Threading.Thread.Sleep(ms);
 
829
    }
 
830
 
 
831
    static cli.System.Net.Sockets.Socket NET_Socket (int domain, int type, int protocol) {
 
832
        cli.System.Net.Sockets.Socket sock;
 
833
        sock = socket (domain, type, protocol);
 
834
        if (sock != INVALID_SOCKET) {
 
835
            //SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);
 
836
        }
 
837
        return sock;
 
838
    }
 
839
}