2
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
27
import java.io.IOException;
28
import java.io.FileDescriptor;
31
* This class defines the plain SocketImpl that is used on Windows platforms
32
* greater or equal to Windows Vista. These platforms have a dual
33
* layer TCP/IP stack and can handle both IPv4 and IPV6 through a
34
* single file descriptor.
36
* @author Chris Hegarty
37
* @author Jeroen Frijters
40
class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
42
public DualStackPlainSocketImpl() {}
44
public DualStackPlainSocketImpl(FileDescriptor fd) {
48
void socketCreate(boolean stream) throws IOException {
50
throw new SocketException("Socket closed");
52
cli.System.Net.Sockets.Socket newfd = socket0(stream, false /*v6 Only*/);
57
void socketConnect(InetAddress address, int port, int timeout)
59
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
62
throw new NullPointerException("inet address argument is null.");
66
connectResult = connect0(nativefd, address, port);
68
configureBlocking(nativefd, false);
70
connectResult = connect0(nativefd, address, port);
71
if (connectResult == WOULDBLOCK) {
72
waitForConnect(nativefd, timeout);
75
configureBlocking(nativefd, true);
79
* We need to set the local port field. If bind was called
80
* previous to the connect (by the client) then localport field
81
* will already be set.
84
localport = localPort0(nativefd);
87
void socketBind(InetAddress address, int port) throws IOException {
88
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
91
throw new NullPointerException("inet address argument is null.");
93
bind0(nativefd, address, port);
95
localport = localPort0(nativefd);
100
this.address = address;
103
void socketListen(int backlog) throws IOException {
104
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
106
listen0(nativefd, backlog);
109
void socketAccept(SocketImpl s) throws IOException {
110
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
113
throw new NullPointerException("socket is null");
115
cli.System.Net.Sockets.Socket newfd = null;
116
InetSocketAddress[] isaa = new InetSocketAddress[1];
118
newfd = accept0(nativefd, isaa);
120
configureBlocking(nativefd, false);
122
waitForNewConnection(nativefd, timeout);
123
newfd = accept0(nativefd, isaa);
125
configureBlocking(newfd, true);
128
configureBlocking(nativefd, true);
131
/* Update (SocketImpl)s' fd */
132
s.fd.setSocket(newfd);
133
/* Update socketImpls remote port, address and localport */
134
InetSocketAddress isa = isaa[0];
135
s.port = isa.getPort();
136
s.address = isa.getAddress();
137
s.localport = localport;
140
int socketAvailable() throws IOException {
141
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
142
return available0(nativefd);
145
void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
147
throw new SocketException("Socket closed");
152
close0(fd.getSocket());
156
void socketShutdown(int howto) throws IOException {
157
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
158
shutdown0(nativefd, howto);
161
void socketSetOption(int opt, boolean on, Object value)
162
throws SocketException {
163
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
165
if (opt == SO_TIMEOUT) { // timeout implemented through select.
176
optionValue = on ? 1 : 0;
181
optionValue = ((Integer)value).intValue();
185
optionValue = ((Integer)value).intValue();
190
default :/* shouldn't get here */
191
throw new SocketException("Option not supported");
194
setIntOption(nativefd, opt, optionValue);
197
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
198
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
200
// SO_BINDADDR is not a socket option.
201
if (opt == SO_BINDADDR) {
202
localAddress(nativefd, (InetAddressContainer)iaContainerObj);
203
return 0; // return value doesn't matter.
206
int value = getIntOption(nativefd, opt);
213
return (value == 0) ? -1 : 1;
218
void socketSendUrgentData(int data) throws IOException {
219
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
220
sendOOB(nativefd, data);
223
private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException {
224
if (fd == null || !fd.valid())
225
throw new SocketException("Socket closed");
227
return fd.getSocket();
230
static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
234
static cli.System.Net.Sockets.Socket socket0(boolean stream, boolean v6Only) throws IOException {
235
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
236
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.socket0(env, stream, v6Only);
237
env.ThrowPendingException();
241
static void bind0(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport)
243
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
244
DualStackPlainSocketImpl_c.bind0(env, fd, localAddress, localport);
245
env.ThrowPendingException();
248
static int connect0(cli.System.Net.Sockets.Socket fd, InetAddress remote, int remotePort)
250
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
251
int ret = DualStackPlainSocketImpl_c.connect0(env, fd, remote, remotePort);
252
env.ThrowPendingException();
256
static void waitForConnect(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
257
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
258
DualStackPlainSocketImpl_c.waitForConnect(env, fd, timeout);
259
env.ThrowPendingException();
262
static int localPort0(cli.System.Net.Sockets.Socket fd) throws IOException {
263
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
264
int ret = DualStackPlainSocketImpl_c.localPort0(env, fd);
265
env.ThrowPendingException();
269
static void localAddress(cli.System.Net.Sockets.Socket fd, InetAddressContainer in) throws SocketException {
270
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
271
DualStackPlainSocketImpl_c.localAddress(env, fd, in);
272
env.ThrowPendingException();
275
static void listen0(cli.System.Net.Sockets.Socket fd, int backlog) throws IOException {
276
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
277
DualStackPlainSocketImpl_c.listen0(env, fd, backlog);
278
env.ThrowPendingException();
281
static cli.System.Net.Sockets.Socket accept0(cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) throws IOException {
282
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
283
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.accept0(env, fd, isaa);
284
env.ThrowPendingException();
288
static void waitForNewConnection(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
289
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
290
DualStackPlainSocketImpl_c.waitForNewConnection(env, fd, timeout);
291
env.ThrowPendingException();
294
static int available0(cli.System.Net.Sockets.Socket fd) throws IOException {
295
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
296
int ret = DualStackPlainSocketImpl_c.available0(env, fd);
297
env.ThrowPendingException();
301
static void close0(cli.System.Net.Sockets.Socket fd) throws IOException {
302
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
303
DualStackPlainSocketImpl_c.close0(env, fd);
304
env.ThrowPendingException();
307
static void shutdown0(cli.System.Net.Sockets.Socket fd, int howto) throws IOException {
308
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
309
DualStackPlainSocketImpl_c.shutdown0(env, fd, howto);
310
env.ThrowPendingException();
313
static void setIntOption(cli.System.Net.Sockets.Socket fd, int cmd, int optionValue) throws SocketException {
314
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
315
DualStackPlainSocketImpl_c.setIntOption(env, fd, cmd, optionValue);
316
env.ThrowPendingException();
319
static int getIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException {
320
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
321
int ret = DualStackPlainSocketImpl_c.getIntOption(env, fd, cmd);
322
env.ThrowPendingException();
326
static void sendOOB(cli.System.Net.Sockets.Socket fd, int data) throws IOException {
327
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
328
DualStackPlainSocketImpl_c.sendOOB(env, fd, data);
329
env.ThrowPendingException();
332
static void configureBlocking(cli.System.Net.Sockets.Socket fd, boolean blocking) throws IOException {
333
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
334
DualStackPlainSocketImpl_c.configureBlocking(env, fd, blocking);
335
env.ThrowPendingException();