2
* Copyright (c) 2000, 2011, 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
30
import java.nio.channels.*;
32
import java.security.AccessController;
33
import java.security.PrivilegedAction;
36
class Net { // package-private
40
// unspecified protocol family
41
static final ProtocolFamily UNSPEC = new ProtocolFamily() {
42
public String name() {
47
// -- Miscellaneous utilities --
49
private static volatile boolean checkedIPv6 = false;
50
private static volatile boolean isIPv6Available;
53
* Tells whether dual-IPv4/IPv6 sockets should be used.
55
static boolean isIPv6Available() {
57
isIPv6Available = isIPv6Available0();
60
return isIPv6Available;
64
* Tells whether IPv6 sockets can join IPv4 multicast groups
66
static boolean canIPv6SocketJoinIPv4Group() {
67
return canIPv6SocketJoinIPv4Group0();
71
* Tells whether {@link #join6} can be used to join an IPv4
72
* multicast group (IPv4 group as IPv4-mapped IPv6 address)
74
static boolean canJoin6WithIPv4Group() {
75
return canJoin6WithIPv4Group0();
78
static InetSocketAddress checkAddress(SocketAddress sa) {
80
throw new NullPointerException();
81
if (!(sa instanceof InetSocketAddress))
82
throw new UnsupportedAddressTypeException(); // ## needs arg
83
InetSocketAddress isa = (InetSocketAddress)sa;
84
if (isa.isUnresolved())
85
throw new UnresolvedAddressException(); // ## needs arg
86
InetAddress addr = isa.getAddress();
87
if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
88
throw new IllegalArgumentException("Invalid address type");
92
static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
93
if (!(sa instanceof InetSocketAddress))
94
throw new UnsupportedAddressTypeException();
95
return (InetSocketAddress)sa;
98
static void translateToSocketException(Exception x)
99
throws SocketException
101
if (x instanceof SocketException)
102
throw (SocketException)x;
104
if (x instanceof ClosedChannelException)
105
nx = new SocketException("Socket is closed");
106
else if (x instanceof NotYetConnectedException)
107
nx = new SocketException("Socket is not connected");
108
else if (x instanceof AlreadyBoundException)
109
nx = new SocketException("Already bound");
110
else if (x instanceof NotYetBoundException)
111
nx = new SocketException("Socket is not bound yet");
112
else if (x instanceof UnsupportedAddressTypeException)
113
nx = new SocketException("Unsupported address type");
114
else if (x instanceof UnresolvedAddressException) {
115
nx = new SocketException("Unresolved address");
120
if (nx instanceof SocketException)
121
throw (SocketException)nx;
122
else if (nx instanceof RuntimeException)
123
throw (RuntimeException)nx;
125
throw new Error("Untranslated exception", nx);
128
static void translateException(Exception x,
129
boolean unknownHostForUnresolved)
132
if (x instanceof IOException)
133
throw (IOException)x;
134
// Throw UnknownHostException from here since it cannot
135
// be thrown as a SocketException
136
if (unknownHostForUnresolved &&
137
(x instanceof UnresolvedAddressException))
139
throw new UnknownHostException();
141
translateToSocketException(x);
144
static void translateException(Exception x)
147
translateException(x, false);
151
* Returns any IPv4 address of the given network interface, or
152
* null if the interface does not have any IPv4 addresses.
154
static Inet4Address anyInet4Address(final NetworkInterface interf) {
155
return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
156
public Inet4Address run() {
157
Enumeration<InetAddress> addrs = interf.getInetAddresses();
158
while (addrs.hasMoreElements()) {
159
InetAddress addr = addrs.nextElement();
160
if (addr instanceof Inet4Address) {
161
return (Inet4Address)addr;
170
* Returns an IPv4 address as an int.
172
static int inet4AsInt(InetAddress ia) {
173
if (ia instanceof Inet4Address) {
174
byte[] addr = ia.getAddress();
175
int address = addr[3] & 0xFF;
176
address |= ((addr[2] << 8) & 0xFF00);
177
address |= ((addr[1] << 16) & 0xFF0000);
178
address |= ((addr[0] << 24) & 0xFF000000);
181
throw new AssertionError("Should not reach here");
185
* Returns an InetAddress from the given IPv4 address
186
* represented as an int.
188
static InetAddress inet4FromInt(int address) {
189
byte[] addr = new byte[4];
190
addr[0] = (byte) ((address >>> 24) & 0xFF);
191
addr[1] = (byte) ((address >>> 16) & 0xFF);
192
addr[2] = (byte) ((address >>> 8) & 0xFF);
193
addr[3] = (byte) (address & 0xFF);
195
return InetAddress.getByAddress(addr);
196
} catch (UnknownHostException uhe) {
197
throw new AssertionError("Should not reach here");
202
* Returns an IPv6 address as a byte array
204
static byte[] inet6AsByteArray(InetAddress ia) {
205
if (ia instanceof Inet6Address) {
206
return ia.getAddress();
209
// need to construct IPv4-mapped address
210
if (ia instanceof Inet4Address) {
211
byte[] ip4address = ia.getAddress();
212
byte[] address = new byte[16];
213
address[10] = (byte)0xff;
214
address[11] = (byte)0xff;
215
address[12] = ip4address[0];
216
address[13] = ip4address[1];
217
address[14] = ip4address[2];
218
address[15] = ip4address[3];
222
throw new AssertionError("Should not reach here");
227
static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
228
SocketOption<?> name, Object value)
232
throw new IllegalArgumentException("Invalid option value");
234
// only simple values supported by this method
235
Class<?> type = name.type();
236
if (type != Integer.class && type != Boolean.class)
237
throw new AssertionError("Should not reach here");
240
if (name == StandardSocketOptions.SO_RCVBUF ||
241
name == StandardSocketOptions.SO_SNDBUF)
243
int i = ((Integer)value).intValue();
245
throw new IllegalArgumentException("Invalid send/receive buffer size");
247
if (name == StandardSocketOptions.SO_LINGER) {
248
int i = ((Integer)value).intValue();
250
value = Integer.valueOf(-1);
252
value = Integer.valueOf(65535);
254
if (name == StandardSocketOptions.IP_TOS) {
255
int i = ((Integer)value).intValue();
256
if (i < 0 || i > 255)
257
throw new IllegalArgumentException("Invalid IP_TOS value");
259
if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
260
int i = ((Integer)value).intValue();
261
if (i < 0 || i > 255)
262
throw new IllegalArgumentException("Invalid TTL/hop value");
265
// map option name to platform level/name
266
OptionKey key = SocketOptionRegistry.findOption(name, family);
268
throw new AssertionError("Option not found");
271
if (type == Integer.class) {
272
arg = ((Integer)value).intValue();
274
boolean b = ((Boolean)value).booleanValue();
278
boolean mayNeedConversion = (family == UNSPEC);
279
setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg);
282
static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
283
SocketOption<?> name)
286
Class<?> type = name.type();
288
// only simple values supported by this method
289
if (type != Integer.class && type != Boolean.class)
290
throw new AssertionError("Should not reach here");
292
// map option name to platform level/name
293
OptionKey key = SocketOptionRegistry.findOption(name, family);
295
throw new AssertionError("Option not found");
297
boolean mayNeedConversion = (family == UNSPEC);
298
int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
300
if (type == Integer.class) {
301
return Integer.valueOf(value);
303
return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
307
// -- Socket operations --
309
private static native boolean isIPv6Available0();
311
private static native boolean canIPv6SocketJoinIPv4Group0();
313
private static native boolean canJoin6WithIPv4Group0();
315
static FileDescriptor socket(boolean stream) throws IOException {
316
return socket(UNSPEC, stream);
319
static FileDescriptor socket(ProtocolFamily family, boolean stream)
321
boolean preferIPv6 = isIPv6Available() &&
322
(family != StandardProtocolFamily.INET);
323
return socket0(preferIPv6, stream, false);
326
static FileDescriptor serverSocket(boolean stream) {
327
return socket0(isIPv6Available(), stream, true);
330
// Due to oddities SO_REUSEADDR on windows reuse is ignored
331
private static native FileDescriptor socket0(boolean preferIPv6, boolean stream, boolean reuse);
333
static void bind(FileDescriptor fd, InetAddress addr, int port)
336
bind(UNSPEC, fd, addr, port);
339
static void bind(ProtocolFamily family, FileDescriptor fd,
340
InetAddress addr, int port) throws IOException
342
boolean preferIPv6 = isIPv6Available() &&
343
(family != StandardProtocolFamily.INET);
344
bind0(preferIPv6, fd, addr, port);
347
private static native void bind0(boolean preferIPv6, FileDescriptor fd,
348
InetAddress addr, int port)
351
static native void listen(FileDescriptor fd, int backlog) throws IOException;
353
static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
356
return connect(UNSPEC, fd, remote, remotePort);
359
static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
362
boolean preferIPv6 = isIPv6Available() &&
363
(family != StandardProtocolFamily.INET);
364
return connect0(preferIPv6, fd, remote, remotePort);
367
private static native int connect0(boolean preferIPv6,
374
public final static int SHUT_RD = 0;
375
public final static int SHUT_WR = 1;
376
public final static int SHUT_RDWR = 2;
378
static native void shutdown(FileDescriptor fd, int how) throws IOException;
380
private static native int localPort(FileDescriptor fd)
383
private static native InetAddress localInetAddress(FileDescriptor fd)
386
static InetSocketAddress localAddress(FileDescriptor fd)
389
return new InetSocketAddress(localInetAddress(fd), localPort(fd));
392
private static native int remotePort(FileDescriptor fd)
395
private static native InetAddress remoteInetAddress(FileDescriptor fd)
398
static InetSocketAddress remoteAddress(FileDescriptor fd)
401
return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
404
private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
408
private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
409
int level, int opt, int arg)
412
// -- Multicast support --
416
* Join IPv4 multicast group
418
static int join4(FileDescriptor fd, int group, int interf, int source)
421
return joinOrDrop4(true, fd, group, interf, source);
425
* Drop membership of IPv4 multicast group
427
static void drop4(FileDescriptor fd, int group, int interf, int source)
430
joinOrDrop4(false, fd, group, interf, source);
433
private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
439
static int block4(FileDescriptor fd, int group, int interf, int source)
442
return blockOrUnblock4(true, fd, group, interf, source);
446
* Unblock IPv6 source
448
static void unblock4(FileDescriptor fd, int group, int interf, int source)
451
blockOrUnblock4(false, fd, group, interf, source);
454
private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
455
int interf, int source)
459
* Join IPv6 multicast group
461
static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
464
return joinOrDrop6(true, fd, group, index, source);
468
* Drop membership of IPv6 multicast group
470
static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
473
joinOrDrop6(false, fd, group, index, source);
476
private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
482
static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
485
return blockOrUnblock6(true, fd, group, index, source);
489
* Unblock IPv6 source
491
static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
494
blockOrUnblock6(false, fd, group, index, source);
497
static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
500
static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
502
static native int getInterface4(FileDescriptor fd) throws IOException;
504
static native void setInterface6(FileDescriptor fd, int index) throws IOException;
506
static native int getInterface6(FileDescriptor fd) throws IOException;