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

« back to all changes in this revision

Viewing changes to external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.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) 2007, 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
package java.net;
 
26
 
 
27
import java.io.FileDescriptor;
 
28
import static ikvm.internal.JNI.*;
 
29
import static ikvm.internal.Winsock.*;
 
30
import static java.net.net_util_md.*;
 
31
 
 
32
final class DualStackPlainSocketImpl_c
 
33
{
 
34
private static final int JVM_IO_ERR = -1;
 
35
private static final int JVM_IO_INTR = -2;
 
36
 
 
37
private static final int SET_BLOCKING = 0;
 
38
private static final int SET_NONBLOCKING = 1;
 
39
/*
 
40
#include <windows.h>
 
41
#include <winsock2.h>
 
42
#include "jni.h"
 
43
#include "net_util.h"
 
44
#include "java_net_DualStackPlainSocketImpl.h"
 
45
 
 
46
#define SET_BLOCKING 0
 
47
#define SET_NONBLOCKING 1
 
48
 
 
49
static jclass isa_class;        /* java.net.InetSocketAddress *-/
 
50
static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) *-/
 
51
 
 
52
/*
 
53
 * Class:     java_net_DualStackPlainSocketImpl
 
54
 * Method:    initIDs
 
55
 * Signature: ()V
 
56
 *-/
 
57
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
 
58
  (JNIEnv *env, jclass clazz) {
 
59
 
 
60
    jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
 
61
    isa_class = (*env)->NewGlobalRef(env, cls);
 
62
    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
 
63
                                     "(Ljava/net/InetAddress;I)V");
 
64
 
 
65
    // implement read timeout with select.
 
66
    isRcvTimeoutSupported = 0;
 
67
}
 
68
 
 
69
/*
 
70
 * Class:     java_net_DualStackPlainSocketImpl
 
71
 * Method:    socket0
 
72
 * Signature: (ZZ)I
 
73
 */
 
74
static cli.System.Net.Sockets.Socket socket0
 
75
  (JNIEnv env, boolean stream, boolean v6Only /*unused*/) {
 
76
    cli.System.Net.Sockets.Socket fd;
 
77
    int rv, opt=0;
 
78
 
 
79
    fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
 
80
    if (fd == INVALID_SOCKET) {
 
81
        NET_ThrowNew(env, WSAGetLastError(), "create");
 
82
        return null;
 
83
    }
 
84
 
 
85
    rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt);
 
86
    if (rv == SOCKET_ERROR) {
 
87
        NET_ThrowNew(env, WSAGetLastError(), "create");
 
88
    }
 
89
 
 
90
 
 
91
    return fd;
 
92
}
 
93
 
 
94
/*
 
95
 * Class:     java_net_DualStackPlainSocketImpl
 
96
 * Method:    bind0
 
97
 * Signature: (ILjava/net/InetAddress;I)V
 
98
 */
 
99
static void bind0
 
100
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
 
101
    SOCKETADDRESS sa;
 
102
    sa = new SOCKETADDRESS();
 
103
    int rv;
 
104
 
 
105
    if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
 
106
                                 JNI_TRUE) != 0) {
 
107
      return;
 
108
    }
 
109
 
 
110
    rv = NET_Bind(fd, sa);
 
111
 
 
112
    if (rv == SOCKET_ERROR)
 
113
        NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind");
 
114
}
 
115
 
 
116
/*
 
117
 * Class:     java_net_DualStackPlainSocketImpl
 
118
 * Method:    connect0
 
119
 * Signature: (ILjava/net/InetAddress;I)I
 
120
 */
 
121
static int connect0
 
122
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
 
123
    SOCKETADDRESS sa;
 
124
    sa = new SOCKETADDRESS();
 
125
    int rv;
 
126
 
 
127
    if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
 
128
                                 JNI_TRUE) != 0) {
 
129
      return -1;
 
130
    }
 
131
 
 
132
    rv = connect(fd, sa);
 
133
    if (rv == SOCKET_ERROR) {
 
134
        int err = WSAGetLastError();
 
135
        if (err == WSAEWOULDBLOCK) {
 
136
            return java.net.DualStackPlainSocketImpl.WOULDBLOCK;
 
137
        } else if (err == WSAEADDRNOTAVAIL) {
 
138
            JNU_ThrowByName(env, JNU_JAVANETPKG+"ConnectException",
 
139
                "connect: Address is invalid on local machine, or port is not valid on remote machine");
 
140
        } else {
 
141
            NET_ThrowNew(env, err, "connect");
 
142
        }
 
143
        return -1;  // return value not important.
 
144
    }
 
145
    return rv;
 
146
}
 
147
 
 
148
/*
 
149
 * Class:     java_net_DualStackPlainSocketImpl
 
150
 * Method:    waitForConnect
 
151
 * Signature: (II)V
 
152
 */
 
153
static void waitForConnect
 
154
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
 
155
    int rv, retry;
 
156
    fd_set wr, ex;
 
157
    wr = new fd_set(); ex = new fd_set();
 
158
    timeval t = new timeval();
 
159
 
 
160
    FD_ZERO(wr);
 
161
    FD_ZERO(ex);
 
162
    FD_SET(fd, wr);
 
163
    FD_SET(fd, ex);
 
164
    t.tv_sec = timeout / 1000;
 
165
    t.tv_usec = (timeout % 1000) * 1000;
 
166
 
 
167
    /*
 
168
     * Wait for timeout, connection established or
 
169
     * connection failed.
 
170
     */
 
171
    rv = select(null, wr, ex, t);
 
172
 
 
173
    /*
 
174
     * Timeout before connection is established/failed so
 
175
     * we throw exception and shutdown input/output to prevent
 
176
     * socket from being used.
 
177
     * The socket should be closed immediately by the caller.
 
178
     */
 
179
    if (rv == 0) {
 
180
        JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
 
181
                        "connect timed out");
 
182
        shutdown( fd, SD_BOTH );
 
183
        return;
 
184
    }
 
185
 
 
186
    /*
 
187
     * Socket is writable or error occured. On some Windows editions
 
188
     * the socket will appear writable when the connect fails so we
 
189
     * check for error rather than writable.
 
190
     */
 
191
    if (!FD_ISSET(fd, ex)) {
 
192
        return;         /* connection established */
 
193
    }
 
194
 
 
195
    /*
 
196
     * Connection failed. The logic here is designed to work around
 
197
     * bug on Windows NT whereby using getsockopt to obtain the
 
198
     * last error (SO_ERROR) indicates there is no error. The workaround
 
199
     * on NT is to allow winsock to be scheduled and this is done by
 
200
     * yielding and retrying. As yielding is problematic in heavy
 
201
     * load conditions we attempt up to 3 times to get the error reason.
 
202
     */
 
203
    for (retry=0; retry<3; retry++) {
 
204
        int[] tmp = { 0 };
 
205
        NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
 
206
                       tmp);
 
207
        rv = tmp[0];
 
208
        if (rv != 0) {
 
209
            break;
 
210
        }
 
211
        Sleep(0);
 
212
    }
 
213
 
 
214
    if (rv == 0) {
 
215
        JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
 
216
                        "Unable to establish connection");
 
217
    } else {
 
218
        NET_ThrowNew(env, rv, "connect");
 
219
    }
 
220
}
 
221
 
 
222
/*
 
223
 * Class:     java_net_DualStackPlainSocketImpl
 
224
 * Method:    localPort0
 
225
 * Signature: (I)I
 
226
 */
 
227
static int localPort0
 
228
  (JNIEnv env, cli.System.Net.Sockets.Socket fd) {
 
229
    SOCKETADDRESS sa;
 
230
    sa = new SOCKETADDRESS();
 
231
 
 
232
    if (getsockname(fd, sa) == SOCKET_ERROR) {
 
233
        if (WSAGetLastError() == WSAENOTSOCK) {
 
234
            JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
 
235
                    "Socket closed");
 
236
        } else {
 
237
            NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
 
238
        }
 
239
        return -1;
 
240
    }
 
241
    return ntohs(GET_PORT(sa));
 
242
}
 
243
 
 
244
/*
 
245
 * Class:     java_net_DualStackPlainSocketImpl
 
246
 * Method:    localAddress
 
247
 * Signature: (ILjava/net/InetAddressContainer;)V
 
248
 */
 
249
static void localAddress
 
250
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddressContainer iaContainerObj) {
 
251
    int[] port = { 0 };
 
252
    SOCKETADDRESS sa;
 
253
    sa = new SOCKETADDRESS();
 
254
    InetAddress iaObj;
 
255
 
 
256
    if (getsockname(fd, sa) == SOCKET_ERROR) {
 
257
        NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
 
258
        return;
 
259
    }
 
260
    iaObj = NET_SockaddrToInetAddress(env, sa, port);
 
261
 
 
262
    iaContainerObj.addr = iaObj;
 
263
}
 
264
 
 
265
 
 
266
/*
 
267
 * Class:     java_net_DualStackPlainSocketImpl
 
268
 * Method:    listen0
 
269
 * Signature: (II)V
 
270
 */
 
271
static void listen0
 
272
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int backlog) {
 
273
    if (listen(fd, backlog) == SOCKET_ERROR) {
 
274
        NET_ThrowNew(env, WSAGetLastError(), "listen failed");
 
275
    }
 
276
}
 
277
 
 
278
/*
 
279
 * Class:     java_net_DualStackPlainSocketImpl
 
280
 * Method:    accept0
 
281
 * Signature: (I[Ljava/net/InetSocketAddress;)I
 
282
 */
 
283
static cli.System.Net.Sockets.Socket accept0
 
284
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) {
 
285
    cli.System.Net.Sockets.Socket newfd;
 
286
    int[] port = { 0 };
 
287
    InetSocketAddress isa;
 
288
    InetAddress ia;
 
289
    SOCKETADDRESS sa;
 
290
    sa = new SOCKETADDRESS();
 
291
 
 
292
    newfd = accept(fd, sa);
 
293
 
 
294
    if (newfd == INVALID_SOCKET) {
 
295
        if (WSAGetLastError() == -2) {
 
296
            JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
 
297
                            "operation interrupted");
 
298
        } else {
 
299
            JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
 
300
                            "socket closed");
 
301
        }
 
302
        return null;
 
303
    }
 
304
 
 
305
    ia = NET_SockaddrToInetAddress(env, sa, port);
 
306
    isa = new InetSocketAddress(ia, port[0]);
 
307
    isaa[0] = isa;
 
308
 
 
309
    return newfd;
 
310
}
 
311
 
 
312
/*
 
313
 * Class:     java_net_DualStackPlainSocketImpl
 
314
 * Method:    waitForNewConnection
 
315
 * Signature: (II)V
 
316
 */
 
317
static void waitForNewConnection
 
318
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
 
319
    int rv;
 
320
 
 
321
    rv = NET_Timeout(fd, timeout);
 
322
    if (rv == 0) {
 
323
        JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
 
324
                        "Accept timed out");
 
325
    } else if (rv == -1) {
 
326
        JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed");
 
327
    } else if (rv == -2) {
 
328
        JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
 
329
                        "operation interrupted");
 
330
    }
 
331
}
 
332
 
 
333
/*
 
334
 * Class:     java_net_DualStackPlainSocketImpl
 
335
 * Method:    available0
 
336
 * Signature: (I)I
 
337
 */
 
338
static int available0
 
339
  (JNIEnv env, cli.System.Net.Sockets.Socket fd) {
 
340
    int[] available = { -1 };
 
341
 
 
342
    if ((ioctlsocket(fd, FIONREAD, available)) == SOCKET_ERROR) {
 
343
        NET_ThrowNew(env, WSAGetLastError(), "socket available");
 
344
    }
 
345
 
 
346
    return available[0];
 
347
}
 
348
 
 
349
/*
 
350
 * Class:     java_net_DualStackPlainSocketImpl
 
351
 * Method:    close0
 
352
 * Signature: (I)V
 
353
 */
 
354
static void close0
 
355
  (JNIEnv env, cli.System.Net.Sockets.Socket fd) {
 
356
     NET_SocketClose(fd);
 
357
}
 
358
 
 
359
/*
 
360
 * Class:     java_net_DualStackPlainSocketImpl
 
361
 * Method:    shutdown0
 
362
 * Signature: (II)V
 
363
 */
 
364
static void shutdown0
 
365
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int howto) {
 
366
    shutdown(fd, howto);
 
367
}
 
368
 
 
369
 
 
370
/*
 
371
 * Class:     java_net_DualStackPlainSocketImpl
 
372
 * Method:    setIntOption
 
373
 * Signature: (III)V
 
374
 */
 
375
static void setIntOption
 
376
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd, int value) {
 
377
 
 
378
    int[] level = { 0 };
 
379
    int[] opt = { 0 };
 
380
    linger linger;
 
381
    Object optval;
 
382
 
 
383
    if (NET_MapSocketOption(cmd, level, opt) < 0) {
 
384
        JNU_ThrowByName(env,
 
385
                                     JNU_JAVANETPKG+"SocketException",
 
386
                                     "Invalid option");
 
387
        return;
 
388
    }
 
389
 
 
390
    if (opt[0] == java.net.SocketOptions.SO_LINGER) {
 
391
        linger = new linger();
 
392
        if (value >= 0) {
 
393
            linger.l_onoff = 1;
 
394
            linger.l_linger = value & 0xFFFF;
 
395
        } else {
 
396
            linger.l_onoff = 0;
 
397
            linger.l_linger = 0;
 
398
        }
 
399
        optval = linger;
 
400
    } else {
 
401
        optval = value;
 
402
    }
 
403
 
 
404
    if (NET_SetSockOpt(fd, level[0], opt[0], optval) < 0) {
 
405
        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
 
406
    }
 
407
}
 
408
 
 
409
/*
 
410
 * Class:     java_net_DualStackPlainSocketImpl
 
411
 * Method:    getIntOption
 
412
 * Signature: (II)I
 
413
 */
 
414
static int getIntOption
 
415
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) {
 
416
 
 
417
    int[] level = { 0 };
 
418
    int[] opt = { 0 };
 
419
    int[] result = { 0 };
 
420
    linger linger;
 
421
    Object optval;
 
422
 
 
423
    if (NET_MapSocketOption(cmd, level, opt) < 0) {
 
424
        JNU_ThrowByName(env,
 
425
                                     JNU_JAVANETPKG+"SocketException",
 
426
                                     "Unsupported socket option");
 
427
        return -1;
 
428
    }
 
429
 
 
430
    if (opt[0] == java.net.SocketOptions.SO_LINGER) {
 
431
        linger = new linger();
 
432
        optval = linger;
 
433
    } else {
 
434
        linger = null;
 
435
        optval = result;
 
436
    }
 
437
 
 
438
    if (NET_GetSockOpt(fd, level[0], opt[0], optval) < 0) {
 
439
        NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
 
440
        return -1;
 
441
    }
 
442
 
 
443
    if (opt[0] == java.net.SocketOptions.SO_LINGER)
 
444
        return linger.l_onoff != 0 ? linger.l_linger : -1;
 
445
    else
 
446
        return result[0];
 
447
}
 
448
 
 
449
 
 
450
/*
 
451
 * Class:     java_net_DualStackPlainSocketImpl
 
452
 * Method:    sendOOB
 
453
 * Signature: (II)V
 
454
 */
 
455
static void sendOOB
 
456
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, int data) {
 
457
    int n;
 
458
 
 
459
    n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB);
 
460
    if (n == JVM_IO_ERR) {
 
461
        NET_ThrowNew(env, WSAGetLastError(), "send");
 
462
    } else if (n == JVM_IO_INTR) {
 
463
        JNU_ThrowByName(env, "java.io.InterruptedIOException", null);
 
464
    }
 
465
}
 
466
 
 
467
/*
 
468
 * Class:     java_net_DualStackPlainSocketImpl
 
469
 * Method:    configureBlocking
 
470
 * Signature: (IZ)V
 
471
 */
 
472
static void configureBlocking
 
473
  (JNIEnv env, cli.System.Net.Sockets.Socket fd, boolean blocking) {
 
474
    int arg;
 
475
    int result;
 
476
 
 
477
    if (blocking == JNI_TRUE) {
 
478
        arg = SET_BLOCKING;    // 0
 
479
    } else {
 
480
        arg = SET_NONBLOCKING;   // 1
 
481
    }
 
482
 
 
483
    result = ioctlsocket(fd, FIONBIO, arg);
 
484
    if (result == SOCKET_ERROR) {
 
485
        NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
 
486
    }
 
487
}
 
488
}