mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-27 19:33:39 +00:00
8253119: Remove the legacy PlainSocketImpl and PlainDatagramSocketImpl implementation
Reviewed-by: alanb, dfuchs, chegar
This commit is contained in:
parent
f485171ce8
commit
326b2e1344
@ -1,530 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* Abstract datagram and multicast socket implementation base class.
|
||||
* Note: This is not a public class, so that applets cannot call
|
||||
* into the implementation directly and hence cannot bypass the
|
||||
* security checks present in the DatagramSocket and MulticastSocket
|
||||
* classes.
|
||||
*
|
||||
* @author Pavani Diwanji
|
||||
*/
|
||||
|
||||
abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
{
|
||||
/* timeout value for receive() */
|
||||
int timeout = 0;
|
||||
boolean connected = false;
|
||||
private int trafficClass = 0;
|
||||
protected InetAddress connectedAddress = null;
|
||||
private int connectedPort = -1;
|
||||
private final boolean isMulticast;
|
||||
|
||||
private static final String os =
|
||||
GetPropertyAction.privilegedGetProperty("os.name");
|
||||
|
||||
/**
|
||||
* flag set if the native connect() call not to be used
|
||||
*/
|
||||
private static final boolean connectDisabled = os.contains("OS X");
|
||||
|
||||
/**
|
||||
* Load net library into runtime.
|
||||
*/
|
||||
static {
|
||||
jdk.internal.loader.BootLoader.loadLibrary("net");
|
||||
}
|
||||
|
||||
private static volatile boolean checkedReusePort;
|
||||
private static volatile boolean isReusePortAvailable;
|
||||
|
||||
/**
|
||||
* Tells whether SO_REUSEPORT is supported.
|
||||
*/
|
||||
static boolean isReusePortAvailable() {
|
||||
if (!checkedReusePort) {
|
||||
isReusePortAvailable = isReusePortAvailable0();
|
||||
checkedReusePort = true;
|
||||
}
|
||||
return isReusePortAvailable;
|
||||
}
|
||||
|
||||
AbstractPlainDatagramSocketImpl(boolean isMulticast) {
|
||||
this.isMulticast = isMulticast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a datagram socket
|
||||
*/
|
||||
protected synchronized void create() throws SocketException {
|
||||
ResourceManager.beforeUdpCreate();
|
||||
fd = new FileDescriptor();
|
||||
try {
|
||||
datagramSocketCreate();
|
||||
SocketCleanable.register(fd, false);
|
||||
} catch (SocketException ioe) {
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a datagram socket to a local port.
|
||||
*/
|
||||
protected synchronized void bind(int lport, InetAddress laddr)
|
||||
throws SocketException {
|
||||
if (laddr.isLinkLocalAddress()) {
|
||||
laddr = IPAddressUtil.toScopedAddress(laddr);
|
||||
}
|
||||
bind0(lport, laddr);
|
||||
}
|
||||
|
||||
protected abstract void bind0(int lport, InetAddress laddr)
|
||||
throws SocketException;
|
||||
|
||||
/**
|
||||
* Sends a datagram packet. The packet contains the data and the
|
||||
* destination address to send the packet to.
|
||||
* @param p the packet to be sent.
|
||||
*/
|
||||
protected void send(DatagramPacket p) throws IOException {
|
||||
InetAddress orig = p.getAddress();
|
||||
if (orig.isLinkLocalAddress()) {
|
||||
InetAddress scoped = IPAddressUtil.toScopedAddress(orig);
|
||||
if (orig != scoped) {
|
||||
p = new DatagramPacket(p.getData(), p.getOffset(),
|
||||
p.getLength(), scoped, p.getPort());
|
||||
}
|
||||
}
|
||||
send0(p);
|
||||
}
|
||||
|
||||
protected abstract void send0(DatagramPacket p) throws IOException;
|
||||
|
||||
/**
|
||||
* Connects a datagram socket to a remote destination. This associates the remote
|
||||
* address with the local socket so that datagrams may only be sent to this destination
|
||||
* and received from this destination.
|
||||
* @param address the remote InetAddress to connect to
|
||||
* @param port the remote port number
|
||||
*/
|
||||
protected void connect(InetAddress address, int port) throws SocketException {
|
||||
if (address.isLinkLocalAddress()) {
|
||||
address = IPAddressUtil.toScopedAddress(address);
|
||||
}
|
||||
connect0(address, port);
|
||||
connectedAddress = address;
|
||||
connectedPort = port;
|
||||
connected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects a previously connected socket. Does nothing if the socket was
|
||||
* not connected already.
|
||||
*/
|
||||
protected void disconnect() {
|
||||
disconnect0(connectedAddress.holder().getFamily());
|
||||
connected = false;
|
||||
connectedAddress = null;
|
||||
connectedPort = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Peek at the packet to see who it is from.
|
||||
* @param i the address to populate with the sender address
|
||||
*/
|
||||
protected abstract int peek(InetAddress i) throws IOException;
|
||||
protected abstract int peekData(DatagramPacket p) throws IOException;
|
||||
/**
|
||||
* Receive the datagram packet.
|
||||
* @param p the packet to receive into
|
||||
*/
|
||||
protected synchronized void receive(DatagramPacket p)
|
||||
throws IOException {
|
||||
receive0(p);
|
||||
}
|
||||
|
||||
protected abstract void receive0(DatagramPacket p)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Set the TTL (time-to-live) option.
|
||||
* @param ttl TTL to be set.
|
||||
*/
|
||||
protected abstract void setTimeToLive(int ttl) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the TTL (time-to-live) option.
|
||||
*/
|
||||
protected abstract int getTimeToLive() throws IOException;
|
||||
|
||||
/**
|
||||
* Set the TTL (time-to-live) option.
|
||||
* @param ttl TTL to be set.
|
||||
*/
|
||||
@Deprecated
|
||||
protected abstract void setTTL(byte ttl) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the TTL (time-to-live) option.
|
||||
*/
|
||||
@Deprecated
|
||||
protected abstract byte getTTL() throws IOException;
|
||||
|
||||
/**
|
||||
* Join the multicast group.
|
||||
* @param inetaddr multicast address to join.
|
||||
*/
|
||||
protected void join(InetAddress inetaddr) throws IOException {
|
||||
join(inetaddr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leave the multicast group.
|
||||
* @param inetaddr multicast address to leave.
|
||||
*/
|
||||
protected void leave(InetAddress inetaddr) throws IOException {
|
||||
leave(inetaddr, null);
|
||||
}
|
||||
/**
|
||||
* Join the multicast group.
|
||||
* @param mcastaddr multicast address to join.
|
||||
* @param netIf specifies the local interface to receive multicast
|
||||
* datagram packets
|
||||
* @throws IllegalArgumentException if mcastaddr is null or is a
|
||||
* SocketAddress subclass not supported by this socket
|
||||
* @since 1.4
|
||||
*/
|
||||
|
||||
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)
|
||||
throws IOException {
|
||||
if (!(mcastaddr instanceof InetSocketAddress addr))
|
||||
throw new IllegalArgumentException("Unsupported address type");
|
||||
join(addr.getAddress(), netIf);
|
||||
}
|
||||
|
||||
protected abstract void join(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Leave the multicast group.
|
||||
* @param mcastaddr multicast address to leave.
|
||||
* @param netIf specified the local interface to leave the group at
|
||||
* @throws IllegalArgumentException if mcastaddr is null or is a
|
||||
* SocketAddress subclass not supported by this socket
|
||||
* @since 1.4
|
||||
*/
|
||||
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf)
|
||||
throws IOException {
|
||||
if (!(mcastaddr instanceof InetSocketAddress addr))
|
||||
throw new IllegalArgumentException("Unsupported address type");
|
||||
leave(addr.getAddress(), netIf);
|
||||
}
|
||||
|
||||
protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Close the socket.
|
||||
*/
|
||||
protected void close() {
|
||||
if (fd != null) {
|
||||
SocketCleanable.unregister(fd);
|
||||
datagramSocketClose();
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isClosed() {
|
||||
return (fd == null) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a value - since we only support (setting) binary options
|
||||
* here, o must be a Boolean
|
||||
*/
|
||||
|
||||
public void setOption(int optID, Object o) throws SocketException {
|
||||
if (isClosed()) {
|
||||
throw new SocketException("Socket Closed");
|
||||
}
|
||||
switch (optID) {
|
||||
/* check type safety b4 going native. These should never
|
||||
* fail, since only java.Socket* has access to
|
||||
* PlainSocketImpl.setOption().
|
||||
*/
|
||||
case SO_TIMEOUT:
|
||||
if (!(o instanceof Integer)) {
|
||||
throw new SocketException("bad argument for SO_TIMEOUT");
|
||||
}
|
||||
int tmp = ((Integer) o).intValue();
|
||||
if (tmp < 0)
|
||||
throw new IllegalArgumentException("timeout < 0");
|
||||
timeout = tmp;
|
||||
return;
|
||||
case IP_TOS:
|
||||
if (!(o instanceof Integer)) {
|
||||
throw new SocketException("bad argument for IP_TOS");
|
||||
}
|
||||
trafficClass = ((Integer)o).intValue();
|
||||
break;
|
||||
case SO_REUSEADDR:
|
||||
if (!(o instanceof Boolean)) {
|
||||
throw new SocketException("bad argument for SO_REUSEADDR");
|
||||
}
|
||||
break;
|
||||
case SO_BROADCAST:
|
||||
if (!(o instanceof Boolean)) {
|
||||
throw new SocketException("bad argument for SO_BROADCAST");
|
||||
}
|
||||
break;
|
||||
case SO_BINDADDR:
|
||||
throw new SocketException("Cannot re-bind Socket");
|
||||
case SO_RCVBUF:
|
||||
case SO_SNDBUF:
|
||||
if (!(o instanceof Integer) ||
|
||||
((Integer)o).intValue() < 0) {
|
||||
throw new SocketException("bad argument for SO_SNDBUF or " +
|
||||
"SO_RCVBUF");
|
||||
}
|
||||
break;
|
||||
case IP_MULTICAST_IF:
|
||||
if (!(o instanceof InetAddress))
|
||||
throw new SocketException("bad argument for IP_MULTICAST_IF");
|
||||
break;
|
||||
case IP_MULTICAST_IF2:
|
||||
if (!(o instanceof NetworkInterface))
|
||||
throw new SocketException("bad argument for IP_MULTICAST_IF2");
|
||||
break;
|
||||
case IP_MULTICAST_LOOP:
|
||||
if (!(o instanceof Boolean))
|
||||
throw new SocketException("bad argument for IP_MULTICAST_LOOP");
|
||||
break;
|
||||
case SO_REUSEPORT:
|
||||
if (!(o instanceof Boolean)) {
|
||||
throw new SocketException("bad argument for SO_REUSEPORT");
|
||||
}
|
||||
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new SocketException("invalid option: " + optID);
|
||||
}
|
||||
socketSetOption(optID, o);
|
||||
}
|
||||
|
||||
/*
|
||||
* get option's state - set or not
|
||||
*/
|
||||
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
if (isClosed()) {
|
||||
throw new SocketException("Socket Closed");
|
||||
}
|
||||
|
||||
Object result;
|
||||
|
||||
switch (optID) {
|
||||
case SO_TIMEOUT:
|
||||
result = timeout;
|
||||
break;
|
||||
|
||||
case IP_TOS:
|
||||
result = socketGetOption(optID);
|
||||
if ( ((Integer)result).intValue() == -1) {
|
||||
result = trafficClass;
|
||||
}
|
||||
break;
|
||||
|
||||
case SO_BINDADDR:
|
||||
case IP_MULTICAST_IF:
|
||||
case IP_MULTICAST_IF2:
|
||||
case SO_RCVBUF:
|
||||
case SO_SNDBUF:
|
||||
case IP_MULTICAST_LOOP:
|
||||
case SO_REUSEADDR:
|
||||
case SO_BROADCAST:
|
||||
result = socketGetOption(optID);
|
||||
break;
|
||||
|
||||
case SO_REUSEPORT:
|
||||
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
result = socketGetOption(optID);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new SocketException("invalid option: " + optID);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static final ExtendedSocketOptions extendedOptions =
|
||||
ExtendedSocketOptions.getInstance();
|
||||
|
||||
private static final Set<SocketOption<?>> datagramSocketOptions = datagramSocketOptions();
|
||||
|
||||
private static Set<SocketOption<?>> datagramSocketOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet<>();
|
||||
options.add(StandardSocketOptions.SO_SNDBUF);
|
||||
options.add(StandardSocketOptions.SO_RCVBUF);
|
||||
options.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
options.add(StandardSocketOptions.SO_BROADCAST);
|
||||
options.add(StandardSocketOptions.IP_TOS);
|
||||
options.add(StandardSocketOptions.IP_MULTICAST_IF);
|
||||
options.add(StandardSocketOptions.IP_MULTICAST_TTL);
|
||||
options.add(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
if (isReusePortAvailable())
|
||||
options.add(StandardSocketOptions.SO_REUSEPORT);
|
||||
options.addAll(ExtendedSocketOptions.datagramSocketOptions());
|
||||
return Collections.unmodifiableSet(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
return datagramSocketOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||
Objects.requireNonNull(name);
|
||||
if (!supportedOptions().contains(name))
|
||||
throw new UnsupportedOperationException("'" + name + "' not supported");
|
||||
|
||||
if (!name.type().isInstance(value))
|
||||
throw new IllegalArgumentException("Invalid value '" + value + "'");
|
||||
|
||||
if (isClosed())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
if (name == StandardSocketOptions.SO_SNDBUF) {
|
||||
if (((Integer)value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid send buffer size:" + value);
|
||||
setOption(SocketOptions.SO_SNDBUF, value);
|
||||
} else if (name == StandardSocketOptions.SO_RCVBUF) {
|
||||
if (((Integer)value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid recv buffer size:" + value);
|
||||
setOption(SocketOptions.SO_RCVBUF, value);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
|
||||
setOption(SocketOptions.SO_REUSEADDR, value);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEPORT) {
|
||||
setOption(SocketOptions.SO_REUSEPORT, value);
|
||||
} else if (name == StandardSocketOptions.SO_BROADCAST) {
|
||||
setOption(SocketOptions.SO_BROADCAST, value);
|
||||
} else if (name == StandardSocketOptions.IP_TOS) {
|
||||
int i = ((Integer)value).intValue();
|
||||
if (i < 0 || i > 255)
|
||||
throw new IllegalArgumentException("Invalid IP_TOS value: " + value);
|
||||
setOption(SocketOptions.IP_TOS, value);
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_IF ) {
|
||||
setOption(SocketOptions.IP_MULTICAST_IF2, value);
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
|
||||
int i = ((Integer)value).intValue();
|
||||
if (i < 0 || i > 255)
|
||||
throw new IllegalArgumentException("Invalid TTL/hop value: " + value);
|
||||
setTimeToLive((Integer)value);
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean enable = (boolean) value;
|
||||
// Legacy setOption expects true to mean 'disabled'
|
||||
setOption(SocketOptions.IP_MULTICAST_LOOP, !enable);
|
||||
} else if (extendedOptions.isOptionSupported(name)) {
|
||||
extendedOptions.setOption(fd, name, value);
|
||||
} else {
|
||||
throw new AssertionError("unknown option :" + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
Objects.requireNonNull(name);
|
||||
if (!supportedOptions().contains(name))
|
||||
throw new UnsupportedOperationException("'" + name + "' not supported");
|
||||
|
||||
if (isClosed())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
if (name == StandardSocketOptions.SO_SNDBUF) {
|
||||
return (T) getOption(SocketOptions.SO_SNDBUF);
|
||||
} else if (name == StandardSocketOptions.SO_RCVBUF) {
|
||||
return (T) getOption(SocketOptions.SO_RCVBUF);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
|
||||
return (T) getOption(SocketOptions.SO_REUSEADDR);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEPORT) {
|
||||
return (T) getOption(SocketOptions.SO_REUSEPORT);
|
||||
} else if (name == StandardSocketOptions.SO_BROADCAST) {
|
||||
return (T) getOption(SocketOptions.SO_BROADCAST);
|
||||
} else if (name == StandardSocketOptions.IP_TOS) {
|
||||
return (T) getOption(SocketOptions.IP_TOS);
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_IF) {
|
||||
return (T) getOption(SocketOptions.IP_MULTICAST_IF2);
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
|
||||
return (T) ((Integer) getTimeToLive());
|
||||
} else if (name == StandardSocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean disabled = (boolean) getOption(SocketOptions.IP_MULTICAST_LOOP);
|
||||
// Legacy getOption returns true when disabled
|
||||
return (T) Boolean.valueOf(!disabled);
|
||||
} else if (extendedOptions.isOptionSupported(name)) {
|
||||
return (T) extendedOptions.getOption(fd, name);
|
||||
} else {
|
||||
throw new AssertionError("unknown option: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void datagramSocketCreate() throws SocketException;
|
||||
protected abstract void datagramSocketClose();
|
||||
protected abstract void socketSetOption(int opt, Object val)
|
||||
throws SocketException;
|
||||
protected abstract Object socketGetOption(int opt) throws SocketException;
|
||||
|
||||
protected abstract void connect0(InetAddress address, int port) throws SocketException;
|
||||
protected abstract void disconnect0(int family);
|
||||
|
||||
protected boolean nativeConnectDisabled() {
|
||||
return connectDisabled;
|
||||
}
|
||||
|
||||
abstract int dataAvailable();
|
||||
private static native boolean isReusePortAvailable0();
|
||||
}
|
||||
@ -1,875 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.ConnectionResetException;
|
||||
import sun.net.NetHooks;
|
||||
import sun.net.PlatformSocketImpl;
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
import sun.net.util.SocketExceptions;
|
||||
|
||||
/**
|
||||
* Default Socket Implementation. This implementation does
|
||||
* not implement any security checks.
|
||||
* Note this class should <b>NOT</b> be public.
|
||||
*
|
||||
* @author Steven B. Byrne
|
||||
*/
|
||||
abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSocketImpl {
|
||||
/* instance variable for SO_TIMEOUT */
|
||||
int timeout; // timeout in millisec
|
||||
// traffic class
|
||||
private int trafficClass;
|
||||
|
||||
private boolean shut_rd = false;
|
||||
private boolean shut_wr = false;
|
||||
|
||||
private SocketInputStream socketInputStream = null;
|
||||
private SocketOutputStream socketOutputStream = null;
|
||||
|
||||
/* number of threads using the FileDescriptor */
|
||||
protected int fdUseCount = 0;
|
||||
|
||||
/* lock when increment/decrementing fdUseCount */
|
||||
protected final Object fdLock = new Object();
|
||||
|
||||
/* indicates a close is pending on the file descriptor */
|
||||
protected boolean closePending = false;
|
||||
|
||||
/* indicates connection reset state */
|
||||
private volatile boolean connectionReset;
|
||||
|
||||
/* indicates whether impl is bound */
|
||||
boolean isBound;
|
||||
|
||||
/* indicates whether impl is connected */
|
||||
volatile boolean isConnected;
|
||||
|
||||
/* whether this Socket is a stream (TCP) socket or not (UDP)
|
||||
*/
|
||||
protected boolean stream;
|
||||
|
||||
/* whether this is a server or not */
|
||||
final boolean isServer;
|
||||
|
||||
/**
|
||||
* Load net library into runtime.
|
||||
*/
|
||||
static {
|
||||
jdk.internal.loader.BootLoader.loadLibrary("net");
|
||||
}
|
||||
|
||||
private static volatile boolean checkedReusePort;
|
||||
private static volatile boolean isReusePortAvailable;
|
||||
|
||||
/**
|
||||
* Tells whether SO_REUSEPORT is supported.
|
||||
*/
|
||||
static boolean isReusePortAvailable() {
|
||||
if (!checkedReusePort) {
|
||||
isReusePortAvailable = isReusePortAvailable0();
|
||||
checkedReusePort = true;
|
||||
}
|
||||
return isReusePortAvailable;
|
||||
}
|
||||
|
||||
AbstractPlainSocketImpl(boolean isServer) {
|
||||
this.isServer = isServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket with a boolean that specifies whether this
|
||||
* is a stream socket (true) or an unconnected UDP socket (false).
|
||||
*/
|
||||
protected synchronized void create(boolean stream) throws IOException {
|
||||
this.stream = stream;
|
||||
if (!stream) {
|
||||
ResourceManager.beforeUdpCreate();
|
||||
// only create the fd after we know we will be able to create the socket
|
||||
fd = new FileDescriptor();
|
||||
try {
|
||||
socketCreate(false);
|
||||
SocketCleanable.register(fd, false);
|
||||
} catch (IOException ioe) {
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
throw ioe;
|
||||
}
|
||||
} else {
|
||||
fd = new FileDescriptor();
|
||||
socketCreate(true);
|
||||
SocketCleanable.register(fd, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the specified port on
|
||||
* the specified host.
|
||||
* @param host the specified host
|
||||
* @param port the specified port
|
||||
*/
|
||||
protected void connect(String host, int port)
|
||||
throws UnknownHostException, IOException
|
||||
{
|
||||
boolean connected = false;
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(host);
|
||||
// recording this.address as supplied by caller before calling connect
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
if (address.isLinkLocalAddress()) {
|
||||
address = IPAddressUtil.toScopedAddress(address);
|
||||
}
|
||||
|
||||
connectToAddress(address, port, timeout);
|
||||
connected = true;
|
||||
} finally {
|
||||
if (!connected) {
|
||||
try {
|
||||
close();
|
||||
} catch (IOException ioe) {
|
||||
/* Do nothing. If connect threw an exception then
|
||||
it will be passed up the call stack */
|
||||
}
|
||||
}
|
||||
isConnected = connected;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the specified address on
|
||||
* the specified port.
|
||||
* @param address the address
|
||||
* @param port the specified port
|
||||
*/
|
||||
protected void connect(InetAddress address, int port) throws IOException {
|
||||
// recording this.address as supplied by caller before calling connect
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
if (address.isLinkLocalAddress()) {
|
||||
address = IPAddressUtil.toScopedAddress(address);
|
||||
}
|
||||
|
||||
try {
|
||||
connectToAddress(address, port, timeout);
|
||||
isConnected = true;
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
// everything failed
|
||||
close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and connects it to the specified address on
|
||||
* the specified port.
|
||||
* @param address the address
|
||||
* @param timeout the timeout value in milliseconds, or zero for no timeout.
|
||||
* @throws IOException if connection fails
|
||||
* @throws IllegalArgumentException if address is null or is a
|
||||
* SocketAddress subclass not supported by this socket
|
||||
* @since 1.4
|
||||
*/
|
||||
protected void connect(SocketAddress address, int timeout)
|
||||
throws IOException {
|
||||
boolean connected = false;
|
||||
try {
|
||||
if (!(address instanceof InetSocketAddress addr))
|
||||
throw new IllegalArgumentException("unsupported address type");
|
||||
if (addr.isUnresolved())
|
||||
throw new UnknownHostException(addr.getHostName());
|
||||
// recording this.address as supplied by caller before calling connect
|
||||
InetAddress ia = addr.getAddress();
|
||||
this.address = ia;
|
||||
this.port = addr.getPort();
|
||||
if (ia.isLinkLocalAddress()) {
|
||||
ia = IPAddressUtil.toScopedAddress(ia);
|
||||
}
|
||||
connectToAddress(ia, port, timeout);
|
||||
connected = true;
|
||||
} finally {
|
||||
if (!connected) {
|
||||
try {
|
||||
close();
|
||||
} catch (IOException ioe) {
|
||||
/* Do nothing. If connect threw an exception then
|
||||
it will be passed up the call stack */
|
||||
}
|
||||
}
|
||||
isConnected = connected;
|
||||
}
|
||||
}
|
||||
|
||||
private void connectToAddress(InetAddress address, int port, int timeout) throws IOException {
|
||||
if (address.isAnyLocalAddress()) {
|
||||
doConnect(InetAddress.getLocalHost(), port, timeout);
|
||||
} else {
|
||||
doConnect(address, port, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
public void setOption(int opt, Object val) throws SocketException {
|
||||
if (isClosedOrPending()) {
|
||||
throw new SocketException("Socket Closed");
|
||||
}
|
||||
boolean on = true;
|
||||
switch (opt) {
|
||||
/* check type safety b4 going native. These should never
|
||||
* fail, since only java.Socket* has access to
|
||||
* PlainSocketImpl.setOption().
|
||||
*/
|
||||
case SO_LINGER:
|
||||
if (!(val instanceof Integer) && !(val instanceof Boolean))
|
||||
throw new SocketException("Bad parameter for option");
|
||||
if (val instanceof Boolean) {
|
||||
/* true only if disabling - enabling should be Integer */
|
||||
on = false;
|
||||
}
|
||||
break;
|
||||
case SO_TIMEOUT:
|
||||
if (!(val instanceof Integer))
|
||||
throw new SocketException("Bad parameter for SO_TIMEOUT");
|
||||
int tmp = ((Integer) val).intValue();
|
||||
if (tmp < 0)
|
||||
throw new IllegalArgumentException("timeout < 0");
|
||||
timeout = tmp;
|
||||
break;
|
||||
case IP_TOS:
|
||||
if (!(val instanceof Integer)) {
|
||||
throw new SocketException("bad argument for IP_TOS");
|
||||
}
|
||||
trafficClass = ((Integer)val).intValue();
|
||||
break;
|
||||
case SO_BINDADDR:
|
||||
throw new SocketException("Cannot re-bind socket");
|
||||
case TCP_NODELAY:
|
||||
if (!(val instanceof Boolean))
|
||||
throw new SocketException("bad parameter for TCP_NODELAY");
|
||||
on = ((Boolean)val).booleanValue();
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
case SO_RCVBUF:
|
||||
if (!(val instanceof Integer) ||
|
||||
!(((Integer)val).intValue() > 0)) {
|
||||
throw new SocketException("bad parameter for SO_SNDBUF " +
|
||||
"or SO_RCVBUF");
|
||||
}
|
||||
break;
|
||||
case SO_KEEPALIVE:
|
||||
if (!(val instanceof Boolean))
|
||||
throw new SocketException("bad parameter for SO_KEEPALIVE");
|
||||
on = ((Boolean)val).booleanValue();
|
||||
break;
|
||||
case SO_OOBINLINE:
|
||||
if (!(val instanceof Boolean))
|
||||
throw new SocketException("bad parameter for SO_OOBINLINE");
|
||||
on = ((Boolean)val).booleanValue();
|
||||
break;
|
||||
case SO_REUSEADDR:
|
||||
if (!(val instanceof Boolean))
|
||||
throw new SocketException("bad parameter for SO_REUSEADDR");
|
||||
on = ((Boolean)val).booleanValue();
|
||||
break;
|
||||
case SO_REUSEPORT:
|
||||
if (!(val instanceof Boolean))
|
||||
throw new SocketException("bad parameter for SO_REUSEPORT");
|
||||
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
on = ((Boolean)val).booleanValue();
|
||||
break;
|
||||
default:
|
||||
throw new SocketException("unrecognized TCP option: " + opt);
|
||||
}
|
||||
socketSetOption(opt, on, val);
|
||||
}
|
||||
public Object getOption(int opt) throws SocketException {
|
||||
if (isClosedOrPending()) {
|
||||
throw new SocketException("Socket Closed");
|
||||
}
|
||||
if (opt == SO_TIMEOUT) {
|
||||
return timeout;
|
||||
}
|
||||
int ret = 0;
|
||||
/*
|
||||
* The native socketGetOption() knows about 3 options.
|
||||
* The 32 bit value it returns will be interpreted according
|
||||
* to what we're asking. A return of -1 means it understands
|
||||
* the option but its turned off. It will raise a SocketException
|
||||
* if "opt" isn't one it understands.
|
||||
*/
|
||||
|
||||
switch (opt) {
|
||||
case TCP_NODELAY:
|
||||
ret = socketGetOption(opt, null);
|
||||
return Boolean.valueOf(ret != -1);
|
||||
case SO_OOBINLINE:
|
||||
ret = socketGetOption(opt, null);
|
||||
return Boolean.valueOf(ret != -1);
|
||||
case SO_LINGER:
|
||||
ret = socketGetOption(opt, null);
|
||||
return (ret == -1) ? Boolean.FALSE: (Object)(ret);
|
||||
case SO_REUSEADDR:
|
||||
ret = socketGetOption(opt, null);
|
||||
return Boolean.valueOf(ret != -1);
|
||||
case SO_BINDADDR:
|
||||
InetAddressContainer in = new InetAddressContainer();
|
||||
ret = socketGetOption(opt, in);
|
||||
return in.addr;
|
||||
case SO_SNDBUF:
|
||||
case SO_RCVBUF:
|
||||
ret = socketGetOption(opt, null);
|
||||
return ret;
|
||||
case IP_TOS:
|
||||
try {
|
||||
ret = socketGetOption(opt, null);
|
||||
if (ret == -1) { // ipv6 tos
|
||||
return trafficClass;
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
} catch (SocketException se) {
|
||||
// TODO - should make better effort to read TOS or TCLASS
|
||||
return trafficClass; // ipv6 tos
|
||||
}
|
||||
case SO_KEEPALIVE:
|
||||
ret = socketGetOption(opt, null);
|
||||
return Boolean.valueOf(ret != -1);
|
||||
case SO_REUSEPORT:
|
||||
if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
ret = socketGetOption(opt, null);
|
||||
return Boolean.valueOf(ret != -1);
|
||||
// should never get here
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final ExtendedSocketOptions extendedOptions =
|
||||
ExtendedSocketOptions.getInstance();
|
||||
|
||||
private static final Set<SocketOption<?>> clientSocketOptions = clientSocketOptions();
|
||||
private static final Set<SocketOption<?>> serverSocketOptions = serverSocketOptions();
|
||||
|
||||
private static Set<SocketOption<?>> clientSocketOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet<>();
|
||||
options.add(StandardSocketOptions.SO_KEEPALIVE);
|
||||
options.add(StandardSocketOptions.SO_SNDBUF);
|
||||
options.add(StandardSocketOptions.SO_RCVBUF);
|
||||
options.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
options.add(StandardSocketOptions.SO_LINGER);
|
||||
options.add(StandardSocketOptions.IP_TOS);
|
||||
options.add(StandardSocketOptions.TCP_NODELAY);
|
||||
if (isReusePortAvailable())
|
||||
options.add(StandardSocketOptions.SO_REUSEPORT);
|
||||
options.addAll(ExtendedSocketOptions.clientSocketOptions());
|
||||
return Collections.unmodifiableSet(options);
|
||||
}
|
||||
|
||||
private static Set<SocketOption<?>> serverSocketOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet<>();
|
||||
options.add(StandardSocketOptions.SO_RCVBUF);
|
||||
options.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
options.add(StandardSocketOptions.IP_TOS);
|
||||
if (isReusePortAvailable())
|
||||
options.add(StandardSocketOptions.SO_REUSEPORT);
|
||||
options.addAll(ExtendedSocketOptions.serverSocketOptions());
|
||||
return Collections.unmodifiableSet(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
if (isServer)
|
||||
return serverSocketOptions;
|
||||
else
|
||||
return clientSocketOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
|
||||
Objects.requireNonNull(name);
|
||||
if (!supportedOptions().contains(name))
|
||||
throw new UnsupportedOperationException("'" + name + "' not supported");
|
||||
|
||||
if (!name.type().isInstance(value))
|
||||
throw new IllegalArgumentException("Invalid value '" + value + "'");
|
||||
|
||||
if (isClosedOrPending())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
if (name == StandardSocketOptions.SO_KEEPALIVE) {
|
||||
setOption(SocketOptions.SO_KEEPALIVE, value);
|
||||
} else if (name == StandardSocketOptions.SO_SNDBUF) {
|
||||
if (((Integer)value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid send buffer size:" + value);
|
||||
setOption(SocketOptions.SO_SNDBUF, value);
|
||||
} else if (name == StandardSocketOptions.SO_RCVBUF) {
|
||||
if (((Integer)value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid recv buffer size:" + value);
|
||||
setOption(SocketOptions.SO_RCVBUF, value);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
|
||||
setOption(SocketOptions.SO_REUSEADDR, value);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEPORT) {
|
||||
setOption(SocketOptions.SO_REUSEPORT, value);
|
||||
} else if (name == StandardSocketOptions.SO_LINGER ) {
|
||||
if (((Integer)value).intValue() < 0)
|
||||
setOption(SocketOptions.SO_LINGER, false);
|
||||
else
|
||||
setOption(SocketOptions.SO_LINGER, value);
|
||||
} else if (name == StandardSocketOptions.IP_TOS) {
|
||||
int i = ((Integer)value).intValue();
|
||||
if (i < 0 || i > 255)
|
||||
throw new IllegalArgumentException("Invalid IP_TOS value: " + value);
|
||||
setOption(SocketOptions.IP_TOS, value);
|
||||
} else if (name == StandardSocketOptions.TCP_NODELAY) {
|
||||
setOption(SocketOptions.TCP_NODELAY, value);
|
||||
} else if (extendedOptions.isOptionSupported(name)) {
|
||||
extendedOptions.setOption(fd, name, value);
|
||||
} else {
|
||||
throw new AssertionError("unknown option: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getOption(SocketOption<T> name) throws IOException {
|
||||
Objects.requireNonNull(name);
|
||||
if (!supportedOptions().contains(name))
|
||||
throw new UnsupportedOperationException("'" + name + "' not supported");
|
||||
|
||||
if (isClosedOrPending())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
if (name == StandardSocketOptions.SO_KEEPALIVE) {
|
||||
return (T)getOption(SocketOptions.SO_KEEPALIVE);
|
||||
} else if (name == StandardSocketOptions.SO_SNDBUF) {
|
||||
return (T)getOption(SocketOptions.SO_SNDBUF);
|
||||
} else if (name == StandardSocketOptions.SO_RCVBUF) {
|
||||
return (T)getOption(SocketOptions.SO_RCVBUF);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEADDR) {
|
||||
return (T)getOption(SocketOptions.SO_REUSEADDR);
|
||||
} else if (name == StandardSocketOptions.SO_REUSEPORT) {
|
||||
return (T)getOption(SocketOptions.SO_REUSEPORT);
|
||||
} else if (name == StandardSocketOptions.SO_LINGER) {
|
||||
Object value = getOption(SocketOptions.SO_LINGER);
|
||||
if (value instanceof Boolean) {
|
||||
assert ((Boolean)value).booleanValue() == false;
|
||||
value = -1;
|
||||
}
|
||||
return (T)value;
|
||||
} else if (name == StandardSocketOptions.IP_TOS) {
|
||||
return (T)getOption(SocketOptions.IP_TOS);
|
||||
} else if (name == StandardSocketOptions.TCP_NODELAY) {
|
||||
return (T)getOption(SocketOptions.TCP_NODELAY);
|
||||
} else if (extendedOptions.isOptionSupported(name)) {
|
||||
return (T) extendedOptions.getOption(fd, name);
|
||||
} else {
|
||||
throw new AssertionError("unknown option: " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The workhorse of the connection operation. Tries several times to
|
||||
* establish a connection to the given <host, port>. If unsuccessful,
|
||||
* throws an IOException indicating what went wrong.
|
||||
*/
|
||||
|
||||
synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
|
||||
synchronized (fdLock) {
|
||||
if (!closePending && !isBound) {
|
||||
NetHooks.beforeTcpConnect(fd, address, port);
|
||||
}
|
||||
}
|
||||
try {
|
||||
acquireFD();
|
||||
try {
|
||||
socketConnect(address, port, timeout);
|
||||
/* socket may have been closed during poll/select */
|
||||
synchronized (fdLock) {
|
||||
if (closePending) {
|
||||
throw new SocketException ("Socket closed");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
releaseFD();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
close();
|
||||
throw SocketExceptions.of(e, new InetSocketAddress(address, port));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the socket to the specified address of the specified local port.
|
||||
* @param address the address
|
||||
* @param lport the port
|
||||
*/
|
||||
protected synchronized void bind(InetAddress address, int lport)
|
||||
throws IOException
|
||||
{
|
||||
synchronized (fdLock) {
|
||||
if (!closePending && !isBound) {
|
||||
NetHooks.beforeTcpBind(fd, address, lport);
|
||||
}
|
||||
}
|
||||
if (address.isLinkLocalAddress()) {
|
||||
address = IPAddressUtil.toScopedAddress(address);
|
||||
}
|
||||
socketBind(address, lport);
|
||||
isBound = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens, for a specified amount of time, for connections.
|
||||
* @param count the amount of time to listen for connections
|
||||
*/
|
||||
protected synchronized void listen(int count) throws IOException {
|
||||
socketListen(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts connections.
|
||||
* @param si the socket impl
|
||||
*/
|
||||
protected void accept(SocketImpl si) throws IOException {
|
||||
si.fd = new FileDescriptor();
|
||||
acquireFD();
|
||||
try {
|
||||
socketAccept(si);
|
||||
} finally {
|
||||
releaseFD();
|
||||
}
|
||||
SocketCleanable.register(si.fd, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an InputStream for this socket.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
protected synchronized InputStream getInputStream() throws IOException {
|
||||
synchronized (fdLock) {
|
||||
if (isClosedOrPending())
|
||||
throw new IOException("Socket Closed");
|
||||
if (shut_rd)
|
||||
throw new IOException("Socket input is shutdown");
|
||||
if (socketInputStream == null) {
|
||||
PrivilegedExceptionAction<SocketInputStream> pa = () -> new SocketInputStream(this);
|
||||
try {
|
||||
socketInputStream = AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (IOException) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
return socketInputStream;
|
||||
}
|
||||
|
||||
void setInputStream(SocketInputStream in) {
|
||||
socketInputStream = in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an OutputStream for this socket.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
protected synchronized OutputStream getOutputStream() throws IOException {
|
||||
synchronized (fdLock) {
|
||||
if (isClosedOrPending())
|
||||
throw new IOException("Socket Closed");
|
||||
if (shut_wr)
|
||||
throw new IOException("Socket output is shutdown");
|
||||
if (socketOutputStream == null) {
|
||||
PrivilegedExceptionAction<SocketOutputStream> pa = () -> new SocketOutputStream(this);
|
||||
try {
|
||||
socketOutputStream = AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw (IOException) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
return socketOutputStream;
|
||||
}
|
||||
|
||||
void setFileDescriptor(FileDescriptor fd) {
|
||||
this.fd = fd;
|
||||
}
|
||||
|
||||
void setAddress(InetAddress address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
void setLocalPort(int localport) {
|
||||
this.localport = localport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that can be read without blocking.
|
||||
*/
|
||||
protected synchronized int available() throws IOException {
|
||||
if (isClosedOrPending()) {
|
||||
throw new IOException("Stream closed.");
|
||||
}
|
||||
|
||||
/*
|
||||
* If connection has been reset or shut down for input, then return 0
|
||||
* to indicate there are no buffered bytes.
|
||||
*/
|
||||
if (isConnectionReset() || shut_rd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no bytes available and we were previously notified
|
||||
* of a connection reset then we move to the reset state.
|
||||
*
|
||||
* If are notified of a connection reset then check
|
||||
* again if there are bytes buffered on the socket.
|
||||
*/
|
||||
int n = 0;
|
||||
try {
|
||||
n = socketAvailable();
|
||||
} catch (ConnectionResetException exc1) {
|
||||
setConnectionReset();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the socket.
|
||||
*/
|
||||
protected void close() throws IOException {
|
||||
synchronized(fdLock) {
|
||||
if (fd != null) {
|
||||
if (fdUseCount == 0) {
|
||||
if (closePending) {
|
||||
return;
|
||||
}
|
||||
closePending = true;
|
||||
/*
|
||||
* We close the FileDescriptor in two-steps - first the
|
||||
* "pre-close" which closes the socket but doesn't
|
||||
* release the underlying file descriptor. This operation
|
||||
* may be lengthy due to untransmitted data and a long
|
||||
* linger interval. Once the pre-close is done we do the
|
||||
* actual socket to release the fd.
|
||||
*/
|
||||
try {
|
||||
socketPreClose();
|
||||
} finally {
|
||||
socketClose();
|
||||
}
|
||||
fd = null;
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* If a thread has acquired the fd and a close
|
||||
* isn't pending then use a deferred close.
|
||||
* Also decrement fdUseCount to signal the last
|
||||
* thread that releases the fd to close it.
|
||||
*/
|
||||
if (!closePending) {
|
||||
closePending = true;
|
||||
fdUseCount--;
|
||||
socketPreClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
throw new InternalError("should not get here");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown read-half of the socket connection;
|
||||
*/
|
||||
protected void shutdownInput() throws IOException {
|
||||
if (fd != null) {
|
||||
socketShutdown(SHUT_RD);
|
||||
if (socketInputStream != null) {
|
||||
socketInputStream.setEOF(true);
|
||||
}
|
||||
shut_rd = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown write-half of the socket connection;
|
||||
*/
|
||||
protected void shutdownOutput() throws IOException {
|
||||
if (fd != null) {
|
||||
socketShutdown(SHUT_WR);
|
||||
shut_wr = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean supportsUrgentData () {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void sendUrgentData (int data) throws IOException {
|
||||
if (fd == null) {
|
||||
throw new IOException("Socket Closed");
|
||||
}
|
||||
socketSendUrgentData (data);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Acquires" and returns the FileDescriptor for this impl
|
||||
*
|
||||
* A corresponding releaseFD is required to "release" the
|
||||
* FileDescriptor.
|
||||
*/
|
||||
FileDescriptor acquireFD() {
|
||||
synchronized (fdLock) {
|
||||
fdUseCount++;
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "Release" the FileDescriptor for this impl.
|
||||
*
|
||||
* If the use count goes to -1 then the socket is closed.
|
||||
*/
|
||||
void releaseFD() {
|
||||
synchronized (fdLock) {
|
||||
fdUseCount--;
|
||||
if (fdUseCount == -1) {
|
||||
if (fd != null) {
|
||||
try {
|
||||
socketClose();
|
||||
} catch (IOException e) {
|
||||
} finally {
|
||||
fd = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isConnectionReset() {
|
||||
return connectionReset;
|
||||
}
|
||||
|
||||
void setConnectionReset() {
|
||||
connectionReset = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if already closed or close is pending
|
||||
*/
|
||||
public boolean isClosedOrPending() {
|
||||
/*
|
||||
* Lock on fdLock to ensure that we wait if a
|
||||
* close is in progress.
|
||||
*/
|
||||
synchronized (fdLock) {
|
||||
if (closePending || (fd == null)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the current value of SO_TIMEOUT
|
||||
*/
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* "Pre-close" a socket by dup'ing the file descriptor - this enables
|
||||
* the socket to be closed without releasing the file descriptor.
|
||||
*/
|
||||
private void socketPreClose() throws IOException {
|
||||
socketClose0(true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the socket (and release the file descriptor).
|
||||
*/
|
||||
protected void socketClose() throws IOException {
|
||||
SocketCleanable.unregister(fd);
|
||||
try {
|
||||
socketClose0(false);
|
||||
} finally {
|
||||
if (!stream) {
|
||||
ResourceManager.afterUdpClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract void socketCreate(boolean stream) throws IOException;
|
||||
abstract void socketConnect(InetAddress address, int port, int timeout)
|
||||
throws IOException;
|
||||
abstract void socketBind(InetAddress address, int port)
|
||||
throws IOException;
|
||||
abstract void socketListen(int count)
|
||||
throws IOException;
|
||||
abstract void socketAccept(SocketImpl s)
|
||||
throws IOException;
|
||||
abstract int socketAvailable()
|
||||
throws IOException;
|
||||
abstract void socketClose0(boolean useDeferredClose)
|
||||
throws IOException;
|
||||
abstract void socketShutdown(int howto)
|
||||
throws IOException;
|
||||
abstract void socketSetOption(int cmd, boolean on, Object value)
|
||||
throws SocketException;
|
||||
abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
|
||||
abstract void socketSendUrgentData(int data)
|
||||
throws IOException;
|
||||
|
||||
public static final int SHUT_RD = 0;
|
||||
public static final int SHUT_WR = 1;
|
||||
|
||||
private static native boolean isReusePortAvailable0();
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,14 +52,6 @@ package java.net;
|
||||
public final
|
||||
class DatagramPacket {
|
||||
|
||||
/**
|
||||
* Perform class initialization
|
||||
*/
|
||||
static {
|
||||
jdk.internal.loader.BootLoader.loadLibrary("net");
|
||||
init();
|
||||
}
|
||||
|
||||
/*
|
||||
* The fields of this class are package-private since DatagramSocketImpl
|
||||
* classes needs to access them.
|
||||
@ -424,9 +416,4 @@ class DatagramPacket {
|
||||
this.length = length;
|
||||
this.bufLength = this.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform class load-time initializations.
|
||||
*/
|
||||
private static native void init();
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.MulticastChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import sun.net.NetProperties;
|
||||
import sun.nio.ch.DefaultSelectorProvider;
|
||||
@ -1338,14 +1339,6 @@ public class DatagramSocket implements java.io.Closeable {
|
||||
|
||||
// Temporary solution until JDK-8237352 is addressed
|
||||
private static final SocketAddress NO_DELEGATE = new SocketAddress() {};
|
||||
private static final boolean USE_PLAINDATAGRAMSOCKET = usePlainDatagramSocketImpl();
|
||||
|
||||
private static boolean usePlainDatagramSocketImpl() {
|
||||
PrivilegedAction<String> pa = () -> NetProperties.get("jdk.net.usePlainDatagramSocketImpl");
|
||||
@SuppressWarnings("removal")
|
||||
String s = AccessController.doPrivileged(pa);
|
||||
return (s != null) && (s.isEmpty() || s.equalsIgnoreCase("true"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Best effort to convert an {@link IOException}
|
||||
@ -1398,14 +1391,11 @@ public class DatagramSocket implements java.io.Closeable {
|
||||
boolean initialized = false;
|
||||
try {
|
||||
DatagramSocketImplFactory factory = DatagramSocket.factory;
|
||||
if (USE_PLAINDATAGRAMSOCKET || factory != null) {
|
||||
if (factory != null) {
|
||||
// create legacy DatagramSocket delegate
|
||||
DatagramSocketImpl impl;
|
||||
if (factory != null) {
|
||||
impl = factory.createDatagramSocketImpl();
|
||||
} else {
|
||||
impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(multicast);
|
||||
}
|
||||
DatagramSocketImpl impl = factory.createDatagramSocketImpl();
|
||||
Objects.requireNonNull(impl,
|
||||
"Implementation returned by installed DatagramSocketImplFactory is null");
|
||||
delegate = new NetMulticastSocket(impl);
|
||||
((NetMulticastSocket) delegate).getImpl(); // ensure impl.create() is called.
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,24 +33,6 @@ import java.util.Set;
|
||||
/**
|
||||
* Abstract datagram and multicast socket implementation base class.
|
||||
*
|
||||
* @implNote Sockets created with the {@code DatagramSocket} and {@code
|
||||
* MulticastSocket} public constructors historically delegated all socket
|
||||
* operations to a {@code DatagramSocketImpl} implementation named
|
||||
* "PlainDatagramSocketImpl". {@code DatagramSocket} and {@code MulticastSocket}
|
||||
* have since been changed to a new implementation based on {@code DatagramChannel}.
|
||||
* The JDK continues to ship with the older implementation to allow code to run
|
||||
* that depends on unspecified behavior that differs between the old and new
|
||||
* implementations. The old implementation will be used if the Java virtual
|
||||
* machine is started with the system property {@systemProperty
|
||||
* jdk.net.usePlainDatagramSocketImpl} set to use the old implementation. It may
|
||||
* also be set in the JDK's network configuration file, located in {@code
|
||||
* ${java.home}/conf/net.properties}. The value of the property is the string
|
||||
* representation of a boolean. If set without a value then it defaults to {@code
|
||||
* true}, hence running with {@code -Djdk.net.usePlainDatagramSocketImpl} or
|
||||
* {@code -Djdk.net.usePlainDatagramSocketImpl=true} will configure the Java
|
||||
* virtual machine to use the old implementation. The property and old
|
||||
* implementation will be removed in a future version.
|
||||
*
|
||||
* @author Pavani Diwanji
|
||||
* @since 1.1
|
||||
*/
|
||||
|
||||
@ -136,8 +136,7 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||
bind(new InetSocketAddress(0));
|
||||
|
||||
// old impls do not support connect/disconnect
|
||||
if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
|
||||
((AbstractPlainDatagramSocketImpl) impl).nativeConnectDisabled())) {
|
||||
if (oldImpl) {
|
||||
connectState = ST_CONNECTED_NO_IMPL;
|
||||
} else {
|
||||
try {
|
||||
|
||||
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.ref.CleanerFactory;
|
||||
import jdk.internal.ref.PhantomCleanable;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
import sun.net.ResourceManager;
|
||||
|
||||
/**
|
||||
* Cleanable for a socket/datagramsocket FileDescriptor when it becomes phantom reachable.
|
||||
* Create a cleanup if the raw fd != -1. Windows closes sockets using the fd.
|
||||
* Subclassed from {@code PhantomCleanable} so that {@code clear} can be
|
||||
* called to disable the cleanup when the socket fd is closed by any means
|
||||
* other than calling {@link FileDescriptor#close}.
|
||||
* Otherwise, it might incorrectly close the handle or fd after it has been reused.
|
||||
*/
|
||||
final class SocketCleanable extends PhantomCleanable<FileDescriptor> {
|
||||
|
||||
// Access to FileDescriptor private fields
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
// Native function to call NET_SocketClose(fd)
|
||||
// Used only for last chance cleanup.
|
||||
private static native void cleanupClose0(int fd) throws IOException;
|
||||
|
||||
// The raw fd to close
|
||||
private final int fd;
|
||||
|
||||
// true for socket, false for datagram socket
|
||||
private final boolean stream;
|
||||
|
||||
/**
|
||||
* Register a socket specific Cleanable with the FileDescriptor
|
||||
* if the FileDescriptor is non-null and the raw fd is != -1.
|
||||
*
|
||||
* @param fdo the FileDescriptor; may be null
|
||||
* @param stream false for datagram socket
|
||||
*/
|
||||
static void register(FileDescriptor fdo, boolean stream) {
|
||||
if (fdo != null && fdo.valid()) {
|
||||
int fd = fdAccess.get(fdo);
|
||||
fdAccess.registerCleanup(fdo,
|
||||
new SocketCleanable(fdo, CleanerFactory.cleaner(),
|
||||
fd, stream));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Cleanable from the FileDescriptor.
|
||||
* @param fdo the FileDescriptor; may be null
|
||||
*/
|
||||
static void unregister(FileDescriptor fdo) {
|
||||
if (fdo != null) {
|
||||
fdAccess.unregisterCleanup(fdo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a phantom cleanable reference.
|
||||
*
|
||||
* @param obj the object to monitor
|
||||
* @param cleaner the cleaner
|
||||
* @param fd file descriptor to close
|
||||
* @param stream false for datagram socket
|
||||
*/
|
||||
private SocketCleanable(FileDescriptor obj, Cleaner cleaner,
|
||||
int fd, boolean stream) {
|
||||
super(obj, cleaner);
|
||||
this.fd = fd;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the native handle or fd.
|
||||
*/
|
||||
@Override
|
||||
protected void performCleanup() {
|
||||
try {
|
||||
cleanupClose0(fd);
|
||||
} catch (IOException ioe) {
|
||||
throw new UncheckedIOException("close", ioe);
|
||||
} finally {
|
||||
if (!stream) {
|
||||
ResourceManager.afterUdpClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,12 +29,9 @@ import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import sun.net.NetProperties;
|
||||
import sun.net.PlatformSocketImpl;
|
||||
import sun.nio.ch.NioSocketImpl;
|
||||
|
||||
@ -43,45 +40,16 @@ import sun.nio.ch.NioSocketImpl;
|
||||
* of all classes that actually implement sockets. It is used to
|
||||
* create both client and server sockets.
|
||||
*
|
||||
* @implNote Client and server sockets created with the {@code Socket} and
|
||||
* {@code SocketServer} public constructors create a system-default
|
||||
* {@code SocketImpl}. The JDK historically used a {@code SocketImpl}
|
||||
* implementation type named "PlainSocketImpl" that has since been replaced by a
|
||||
* newer implementation. The JDK continues to ship with the older implementation
|
||||
* to allow code to run that depends on unspecified behavior that differs between
|
||||
* the old and new implementations. The old implementation will be used if the
|
||||
* Java virtual machine is started with the system property {@systemProperty
|
||||
* jdk.net.usePlainSocketImpl} set to use the old implementation. It may also be
|
||||
* set in the JDK's network configuration file, located in {@code
|
||||
* ${java.home}/conf/net.properties}. The value of the property is the string
|
||||
* representation of a boolean. If set without a value then it defaults to {@code
|
||||
* true}, hence running with {@code -Djdk.net.usePlainSocketImpl} or {@code
|
||||
* -Djdk.net.usePlainSocketImpl=true} will configure the Java virtual machine
|
||||
* to use the old implementation. The property and old implementation will be
|
||||
* removed in a future version.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public abstract class SocketImpl implements SocketOptions {
|
||||
private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl();
|
||||
|
||||
private static boolean usePlainSocketImpl() {
|
||||
PrivilegedAction<String> pa = () -> NetProperties.get("jdk.net.usePlainSocketImpl");
|
||||
@SuppressWarnings("removal")
|
||||
String s = AccessController.doPrivileged(pa);
|
||||
return (s != null) && !s.equalsIgnoreCase("false");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of platform's SocketImpl
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
|
||||
if (USE_PLAINSOCKETIMPL) {
|
||||
return (S) new PlainSocketImpl(server);
|
||||
} else {
|
||||
return (S) new NioSocketImpl(server);
|
||||
}
|
||||
return (S) new NioSocketImpl(server);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import sun.net.ConnectionResetException;
|
||||
|
||||
/**
|
||||
* This stream extends FileInputStream to implement a
|
||||
* SocketInputStream. Note that this class should <b>NOT</b> be
|
||||
* public.
|
||||
*
|
||||
* @author Jonathan Payne
|
||||
* @author Arthur van Hoff
|
||||
*/
|
||||
class SocketInputStream extends FileInputStream {
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
private boolean eof;
|
||||
private AbstractPlainSocketImpl impl = null;
|
||||
private byte temp[];
|
||||
|
||||
/**
|
||||
* Creates a new SocketInputStream. Can only be called
|
||||
* by a Socket. This method needs to hang on to the owner Socket so
|
||||
* that the fd will not be closed.
|
||||
* @param impl the implemented socket input stream
|
||||
*/
|
||||
SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
|
||||
super(impl.getFileDescriptor());
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
|
||||
* object associated with this file input stream.</p>
|
||||
*
|
||||
* The {@code getChannel} method of {@code SocketInputStream}
|
||||
* returns {@code null} since it is a socket based stream.</p>
|
||||
*
|
||||
* @return the file channel associated with this file input stream
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public final FileChannel getChannel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads into an array of bytes at the specified offset using
|
||||
* the received socket primitive.
|
||||
* @param fd the FileDescriptor
|
||||
* @param b the buffer into which the data is read
|
||||
* @param off the start offset of the data
|
||||
* @param len the maximum number of bytes read
|
||||
* @param timeout the read timeout in ms
|
||||
* @return the actual number of bytes read, -1 is
|
||||
* returned when the end of the stream is reached.
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
private native int socketRead0(FileDescriptor fd,
|
||||
byte b[], int off, int len,
|
||||
int timeout)
|
||||
throws IOException;
|
||||
|
||||
// wrap native call to allow instrumentation
|
||||
/**
|
||||
* Reads into an array of bytes at the specified offset using
|
||||
* the received socket primitive.
|
||||
* @param fd the FileDescriptor
|
||||
* @param b the buffer into which the data is read
|
||||
* @param off the start offset of the data
|
||||
* @param len the maximum number of bytes read
|
||||
* @param timeout the read timeout in ms
|
||||
* @return the actual number of bytes read, -1 is
|
||||
* returned when the end of the stream is reached.
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
private int socketRead(FileDescriptor fd,
|
||||
byte b[], int off, int len,
|
||||
int timeout)
|
||||
throws IOException {
|
||||
return socketRead0(fd, b, off, len, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads into a byte array data from the socket.
|
||||
* @param b the buffer into which the data is read
|
||||
* @return the actual number of bytes read, -1 is
|
||||
* returned when the end of the stream is reached.
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
public int read(byte b[]) throws IOException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads into a byte array <i>b</i> at offset <i>off</i>,
|
||||
* <i>length</i> bytes of data.
|
||||
* @param b the buffer into which the data is read
|
||||
* @param off the start offset of the data
|
||||
* @param length the maximum number of bytes read
|
||||
* @return the actual number of bytes read, -1 is
|
||||
* returned when the end of the stream is reached.
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
public int read(byte b[], int off, int length) throws IOException {
|
||||
return read(b, off, length, impl.getTimeout());
|
||||
}
|
||||
|
||||
int read(byte b[], int off, int length, int timeout) throws IOException {
|
||||
int n;
|
||||
|
||||
// EOF already encountered
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// connection reset
|
||||
if (impl.isConnectionReset()) {
|
||||
throw new SocketException("Connection reset");
|
||||
}
|
||||
|
||||
// bounds check
|
||||
if (length <= 0 || off < 0 || length > b.length - off) {
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
}
|
||||
throw new ArrayIndexOutOfBoundsException("length == " + length
|
||||
+ " off == " + off + " buffer length == " + b.length);
|
||||
}
|
||||
|
||||
// acquire file descriptor and do the read
|
||||
FileDescriptor fd = impl.acquireFD();
|
||||
try {
|
||||
n = socketRead(fd, b, off, length, timeout);
|
||||
if (n > 0) {
|
||||
return n;
|
||||
}
|
||||
} catch (ConnectionResetException rstExc) {
|
||||
impl.setConnectionReset();
|
||||
} finally {
|
||||
impl.releaseFD();
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here we are at EOF, the socket has been closed,
|
||||
* or the connection has been reset.
|
||||
*/
|
||||
if (impl.isClosedOrPending()) {
|
||||
throw new SocketException("Socket closed");
|
||||
}
|
||||
if (impl.isConnectionReset()) {
|
||||
throw new SocketException("Connection reset");
|
||||
}
|
||||
eof = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a single byte from the socket.
|
||||
*/
|
||||
public int read() throws IOException {
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
temp = new byte[1];
|
||||
int n = read(temp, 0, 1);
|
||||
if (n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
return temp[0] & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips n bytes of input.
|
||||
* @param numbytes the number of bytes to skip
|
||||
* @return the actual number of bytes skipped.
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
public long skip(long numbytes) throws IOException {
|
||||
if (numbytes <= 0) {
|
||||
return 0;
|
||||
}
|
||||
long n = numbytes;
|
||||
int buflen = (int) Math.min(1024, n);
|
||||
byte data[] = new byte[buflen];
|
||||
while (n > 0) {
|
||||
int r = read(data, 0, (int) Math.min((long) buflen, n));
|
||||
if (r < 0) {
|
||||
break;
|
||||
}
|
||||
n -= r;
|
||||
}
|
||||
return numbytes - n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bytes that can be read without blocking.
|
||||
* @return the number of immediately available bytes
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
int available = impl.available();
|
||||
return eof ? 0 : available;
|
||||
}
|
||||
|
||||
void setEOF(boolean eof) {
|
||||
this.eof = eof;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
// No longer used. Socket.getInputStream returns an
|
||||
// InputStream which calls Socket.close directly
|
||||
assert false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform class load-time initializations.
|
||||
*/
|
||||
private static native void init();
|
||||
}
|
||||
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
/**
|
||||
* This stream extends FileOutputStream to implement a
|
||||
* SocketOutputStream. Note that this class should <b>NOT</b> be
|
||||
* public.
|
||||
*
|
||||
* @author Jonathan Payne
|
||||
* @author Arthur van Hoff
|
||||
*/
|
||||
class SocketOutputStream extends FileOutputStream {
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
private AbstractPlainSocketImpl impl = null;
|
||||
private byte temp[] = new byte[1];
|
||||
|
||||
/**
|
||||
* Creates a new SocketOutputStream. Can only be called
|
||||
* by a Socket. This method needs to hang on to the owner Socket so
|
||||
* that the fd will not be closed.
|
||||
* @param impl the socket output stream implemented
|
||||
*/
|
||||
SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
|
||||
super(impl.getFileDescriptor());
|
||||
this.impl = impl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
|
||||
* object associated with this file output stream. </p>
|
||||
*
|
||||
* The {@code getChannel} method of {@code SocketOutputStream}
|
||||
* returns {@code null} since it is a socket based stream.</p>
|
||||
*
|
||||
* @return the file channel associated with this file output stream
|
||||
*
|
||||
* @since 1.4
|
||||
*/
|
||||
public final FileChannel getChannel() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes to the socket.
|
||||
* @param fd the FileDescriptor
|
||||
* @param b the data to be written
|
||||
* @param off the start offset in the data
|
||||
* @param len the number of bytes that are written
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
private native void socketWrite0(FileDescriptor fd, byte[] b, int off,
|
||||
int len) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes to the socket with appropriate locking of the
|
||||
* FileDescriptor.
|
||||
* @param b the data to be written
|
||||
* @param off the start offset in the data
|
||||
* @param len the number of bytes that are written
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
private void socketWrite(byte b[], int off, int len) throws IOException {
|
||||
|
||||
|
||||
if (len <= 0 || off < 0 || len > b.length - off) {
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
throw new ArrayIndexOutOfBoundsException("len == " + len
|
||||
+ " off == " + off + " buffer length == " + b.length);
|
||||
}
|
||||
|
||||
FileDescriptor fd = impl.acquireFD();
|
||||
try {
|
||||
socketWrite0(fd, b, off, len);
|
||||
} catch (SocketException se) {
|
||||
if (impl.isClosedOrPending()) {
|
||||
throw new SocketException("Socket closed");
|
||||
} else {
|
||||
throw se;
|
||||
}
|
||||
} finally {
|
||||
impl.releaseFD();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a byte to the socket.
|
||||
* @param b the data to be written
|
||||
* @throws IOException If an I/O error has occurred.
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
temp[0] = (byte)b;
|
||||
socketWrite(temp, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the contents of the buffer <i>b</i> to the socket.
|
||||
* @param b the data to be written
|
||||
* @throws SocketException If an I/O error has occurred.
|
||||
*/
|
||||
public void write(byte b[]) throws IOException {
|
||||
socketWrite(b, 0, b.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes <i>length</i> bytes from buffer <i>b</i> starting at
|
||||
* offset <i>len</i>.
|
||||
* @param b the data to be written
|
||||
* @param off the start offset in the data
|
||||
* @param len the number of bytes that are written
|
||||
* @throws SocketException If an I/O error has occurred.
|
||||
*/
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
socketWrite(b, off, len);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
// No longer used. Socket.getOutputStream returns an
|
||||
// OutputStream which calls Socket.close directly
|
||||
assert false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform class load-time initializations.
|
||||
*/
|
||||
private static native void init();
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -252,7 +252,7 @@ public abstract class SocketFactory
|
||||
// out through firewalls (e.g. SOCKS V4 or V5) or in through them
|
||||
// (e.g. using SSL), or that some ports are reserved for use with SSL.
|
||||
//
|
||||
// Note that at least JDK 1.1 has a low level "plainSocketImpl" that
|
||||
// Note that at least JDK 1.1 has a low level "SocketImpl" that
|
||||
// knows about SOCKS V4 tunneling, so this isn't a totally bogus default.
|
||||
//
|
||||
// ALSO: we may want to expose this class somewhere so other folk
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -64,9 +64,6 @@ import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
/**
|
||||
* NIO based SocketImpl.
|
||||
*
|
||||
* This implementation attempts to be compatible with legacy PlainSocketImpl,
|
||||
* including behavior and exceptions that are not specified by SocketImpl.
|
||||
*
|
||||
* The underlying socket used by this SocketImpl is initially configured
|
||||
* blocking. If the connect method is used to establish a connection with a
|
||||
* timeout then the socket is configured non-blocking for the connect attempt,
|
||||
@ -641,8 +638,8 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
|
||||
throw new SocketException("Already bound");
|
||||
NetHooks.beforeTcpBind(fd, host, port);
|
||||
Net.bind(fd, host, port);
|
||||
// set the address field to the given host address to keep
|
||||
// compatibility with PlainSocketImpl. When binding to 0.0.0.0
|
||||
// set the address field to the given host address to
|
||||
// maintain long standing behavior. When binding to 0.0.0.0
|
||||
// then the actual local address will be ::0 when IPv6 is enabled.
|
||||
address = host;
|
||||
localport = Net.localAddress(fd).getPort();
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include "java_net_DatagramPacket.h"
|
||||
#include "net_util.h"
|
||||
|
||||
/************************************************************************
|
||||
* DatagramPacket
|
||||
*/
|
||||
|
||||
jfieldID dp_addressID;
|
||||
jfieldID dp_portID;
|
||||
jfieldID dp_bufID;
|
||||
jfieldID dp_offsetID;
|
||||
jfieldID dp_lengthID;
|
||||
jfieldID dp_bufLengthID;
|
||||
|
||||
/*
|
||||
* Class: java_net_DatagramPacket
|
||||
* Method: init
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_DatagramPacket_init (JNIEnv *env, jclass cls) {
|
||||
dp_addressID = (*env)->GetFieldID(env, cls, "address",
|
||||
"Ljava/net/InetAddress;");
|
||||
CHECK_NULL(dp_addressID);
|
||||
dp_portID = (*env)->GetFieldID(env, cls, "port", "I");
|
||||
CHECK_NULL(dp_portID);
|
||||
dp_bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
|
||||
CHECK_NULL(dp_bufID);
|
||||
dp_offsetID = (*env)->GetFieldID(env, cls, "offset", "I");
|
||||
CHECK_NULL(dp_offsetID);
|
||||
dp_lengthID = (*env)->GetFieldID(env, cls, "length", "I");
|
||||
CHECK_NULL(dp_lengthID);
|
||||
dp_bufLengthID = (*env)->GetFieldID(env, cls, "bufLength", "I");
|
||||
CHECK_NULL(dp_bufLengthID);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,7 +45,6 @@
|
||||
*
|
||||
* The naming convention for field IDs is
|
||||
* <class abbrv>_<fieldName>ID
|
||||
* i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID.
|
||||
*/
|
||||
extern jclass ia_class;
|
||||
extern jfieldID iac_addressID;
|
||||
@ -84,13 +83,6 @@ extern jfieldID ni_addrsID;
|
||||
extern jfieldID ni_descID;
|
||||
extern jmethodID ni_ctrID;
|
||||
|
||||
/* PlainSocketImpl fields */
|
||||
extern jfieldID psi_timeoutID;
|
||||
extern jfieldID psi_fdID;
|
||||
extern jfieldID psi_addressID;
|
||||
extern jfieldID psi_portID;
|
||||
extern jfieldID psi_localportID;
|
||||
|
||||
/* DatagramPacket fields */
|
||||
extern jfieldID dp_addressID;
|
||||
extern jfieldID dp_portID;
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.net;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* This class defines a factory for creating DatagramSocketImpls. It defaults
|
||||
* to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls
|
||||
* by setting the impl.prefix system property.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class DefaultDatagramSocketImplFactory {
|
||||
static Class<?> prefixImplClass = null;
|
||||
|
||||
static {
|
||||
String prefix = null;
|
||||
try {
|
||||
prefix = GetPropertyAction.privilegedGetProperty("impl.prefix");
|
||||
if (prefix != null)
|
||||
prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Can't find class: java.net." +
|
||||
prefix +
|
||||
"DatagramSocketImpl: check impl.prefix property");
|
||||
//prefixImplClass = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>DatagramSocketImpl</code> instance.
|
||||
*
|
||||
* @param isMulticast true if this impl if for a MutlicastSocket
|
||||
* @return a new instance of a <code>DatagramSocketImpl</code>.
|
||||
*/
|
||||
static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast /*unused on unix*/)
|
||||
throws SocketException {
|
||||
if (prefixImplClass != null) {
|
||||
try {
|
||||
@SuppressWarnings("deprecation")
|
||||
DatagramSocketImpl result = (DatagramSocketImpl)prefixImplClass.newInstance();
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new SocketException("can't instantiate DatagramSocketImpl");
|
||||
}
|
||||
} else {
|
||||
return new java.net.PlainDatagramSocketImpl(isMulticast);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
/*
|
||||
* On Unix systems we simply delegate to native methods.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
||||
{
|
||||
PlainDatagramSocketImpl(boolean isMulticast) {
|
||||
super(isMulticast);
|
||||
}
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
protected void socketSetOption(int opt, Object val) throws SocketException {
|
||||
if (opt == SocketOptions.SO_REUSEPORT &&
|
||||
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
try {
|
||||
socketSetOption0(opt, val);
|
||||
} catch (SocketException se) {
|
||||
if (!connected)
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized native void bind0(int lport, InetAddress laddr)
|
||||
throws SocketException;
|
||||
|
||||
protected native void send0(DatagramPacket p) throws IOException;
|
||||
|
||||
protected synchronized native int peek(InetAddress i) throws IOException;
|
||||
|
||||
protected synchronized native int peekData(DatagramPacket p) throws IOException;
|
||||
|
||||
protected synchronized native void receive0(DatagramPacket p)
|
||||
throws IOException;
|
||||
|
||||
protected native void setTimeToLive(int ttl) throws IOException;
|
||||
|
||||
protected native int getTimeToLive() throws IOException;
|
||||
|
||||
@Deprecated
|
||||
protected native void setTTL(byte ttl) throws IOException;
|
||||
|
||||
@Deprecated
|
||||
protected native byte getTTL() throws IOException;
|
||||
|
||||
protected native void join(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
protected native void leave(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
protected native void datagramSocketCreate() throws SocketException;
|
||||
|
||||
protected native void datagramSocketClose();
|
||||
|
||||
protected native void socketSetOption0(int opt, Object val)
|
||||
throws SocketException;
|
||||
|
||||
protected native Object socketGetOption(int opt) throws SocketException;
|
||||
|
||||
protected native void connect0(InetAddress address, int port) throws SocketException;
|
||||
|
||||
protected native void disconnect0(int family);
|
||||
|
||||
native int dataAvailable();
|
||||
|
||||
/**
|
||||
* Perform class load-time initializations.
|
||||
*/
|
||||
private static native void init();
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
/*
|
||||
* On Unix systems we simply delegate to native methods.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class PlainSocketImpl extends AbstractPlainSocketImpl
|
||||
{
|
||||
static {
|
||||
initProto();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty instance.
|
||||
*/
|
||||
PlainSocketImpl(boolean isServer) {
|
||||
super(isServer);
|
||||
}
|
||||
|
||||
protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
|
||||
if (opt == SocketOptions.SO_REUSEPORT &&
|
||||
!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
try {
|
||||
socketSetOption0(opt, b, val);
|
||||
} catch (SocketException se) {
|
||||
if (!isConnected)
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
|
||||
void socketCreate(boolean stream) throws IOException {
|
||||
socketCreate(stream, isServer);
|
||||
}
|
||||
|
||||
native void socketCreate(boolean stream, boolean isServer) throws IOException;
|
||||
|
||||
native void socketConnect(InetAddress address, int port, int timeout)
|
||||
throws IOException;
|
||||
|
||||
native void socketBind(InetAddress address, int port)
|
||||
throws IOException;
|
||||
|
||||
native void socketListen(int count) throws IOException;
|
||||
|
||||
native void socketAccept(SocketImpl s) throws IOException;
|
||||
|
||||
native int socketAvailable() throws IOException;
|
||||
|
||||
native void socketClose0(boolean useDeferredClose) throws IOException;
|
||||
|
||||
native void socketShutdown(int howto) throws IOException;
|
||||
|
||||
static native void initProto();
|
||||
|
||||
native void socketSetOption0(int cmd, boolean on, Object value)
|
||||
throws SocketException;
|
||||
|
||||
native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
|
||||
|
||||
native void socketSendUrgentData(int data) throws IOException;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,994 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
#include "jvm.h"
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_SocketOptions.h"
|
||||
#include "java_net_PlainSocketImpl.h"
|
||||
|
||||
/************************************************************************
|
||||
* PlainSocketImpl
|
||||
*/
|
||||
|
||||
static jfieldID IO_fd_fdID;
|
||||
|
||||
jfieldID psi_fdID;
|
||||
jfieldID psi_addressID;
|
||||
jfieldID psi_ipaddressID;
|
||||
jfieldID psi_portID;
|
||||
jfieldID psi_localportID;
|
||||
jfieldID psi_timeoutID;
|
||||
jfieldID psi_trafficClassID;
|
||||
jfieldID psi_fdLockID;
|
||||
jfieldID psi_closePendingID;
|
||||
|
||||
/*
|
||||
* file descriptor used for dup2
|
||||
*/
|
||||
static int marker_fd = -1;
|
||||
|
||||
|
||||
#define SET_NONBLOCKING(fd) { \
|
||||
int flags = fcntl(fd, F_GETFL); \
|
||||
flags |= O_NONBLOCK; \
|
||||
fcntl(fd, F_SETFL, flags); \
|
||||
}
|
||||
|
||||
#define SET_BLOCKING(fd) { \
|
||||
int flags = fcntl(fd, F_GETFL); \
|
||||
flags &= ~O_NONBLOCK; \
|
||||
fcntl(fd, F_SETFL, flags); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the marker file descriptor by establishing a loopback connection
|
||||
* which we shutdown but do not close the fd. The result is an fd that
|
||||
* can be used for read/write.
|
||||
*/
|
||||
static int getMarkerFD()
|
||||
{
|
||||
int sv[2];
|
||||
|
||||
#ifdef AF_UNIX
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Finally shutdown sv[0] (any reads to this fd will get
|
||||
* EOF; any writes will get an error).
|
||||
*/
|
||||
shutdown(sv[0], 2);
|
||||
close(sv[1]);
|
||||
|
||||
return sv[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the file descriptor given a PlainSocketImpl
|
||||
*/
|
||||
static int getFD(JNIEnv *env, jobject this) {
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
CHECK_NULL_RETURN(fdObj, -1);
|
||||
return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
|
||||
/*
|
||||
* The initroto function is called whenever PlainSocketImpl is
|
||||
* loaded, to cache field IDs for efficiency. This is called every time
|
||||
* the Java class is loaded.
|
||||
*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: initProto
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
|
||||
psi_fdID = (*env)->GetFieldID(env, cls , "fd",
|
||||
"Ljava/io/FileDescriptor;");
|
||||
CHECK_NULL(psi_fdID);
|
||||
psi_addressID = (*env)->GetFieldID(env, cls, "address",
|
||||
"Ljava/net/InetAddress;");
|
||||
CHECK_NULL(psi_addressID);
|
||||
psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
|
||||
CHECK_NULL(psi_portID);
|
||||
psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
|
||||
CHECK_NULL(psi_localportID);
|
||||
psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
|
||||
CHECK_NULL(psi_timeoutID);
|
||||
psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
|
||||
CHECK_NULL(psi_trafficClassID);
|
||||
psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
|
||||
"Ljava/lang/Object;");
|
||||
CHECK_NULL(psi_fdLockID);
|
||||
psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
|
||||
CHECK_NULL(psi_closePendingID);
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
CHECK_NULL(IO_fd_fdID);
|
||||
|
||||
initInetAddressIDs(env);
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
|
||||
/* Create the marker fd used for dup2 */
|
||||
marker_fd = getMarkerFD();
|
||||
}
|
||||
|
||||
/* a global reference to the java.net.SocketException class. In
|
||||
* socketCreate, we ensure that this is initialized. This is to
|
||||
* prevent the problem where socketCreate runs out of file
|
||||
* descriptors, and is then unable to load the exception class.
|
||||
*/
|
||||
static jclass socketExceptionCls;
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketCreate
|
||||
* Signature: (ZZ)V */
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
|
||||
jboolean stream, jboolean isServer) {
|
||||
jobject fdObj, ssObj;
|
||||
int fd;
|
||||
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||
|
||||
if (socketExceptionCls == NULL) {
|
||||
jclass c = (*env)->FindClass(env, "java/net/SocketException");
|
||||
CHECK_NULL(c);
|
||||
socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
|
||||
CHECK_NULL(socketExceptionCls);
|
||||
}
|
||||
fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
|
||||
if (fdObj == NULL) {
|
||||
(*env)->ThrowNew(env, socketExceptionCls, "null fd object");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((fd = socket(domain, type, 0)) == -1) {
|
||||
/* note: if you run out of fds, you may not be able to load
|
||||
* the exception class, and get a NoClassDefFoundError
|
||||
* instead.
|
||||
*/
|
||||
NET_ThrowNew(env, errno, "can't create socket");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
|
||||
*/
|
||||
if (domain == AF_INET6 && ipv4_available()) {
|
||||
int arg = 0;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
|
||||
sizeof(int)) < 0) {
|
||||
NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a server socket then enable SO_REUSEADDR
|
||||
* automatically and set to non blocking.
|
||||
*/
|
||||
if (isServer) {
|
||||
int arg = 1;
|
||||
SET_NONBLOCKING(fd);
|
||||
if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
|
||||
sizeof(arg)) < 0) {
|
||||
NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* inetAddress is the address object passed to the socket connect
|
||||
* call.
|
||||
*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketConnect
|
||||
* Signature: (Ljava/net/InetAddress;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
|
||||
jobject iaObj, jint port,
|
||||
jint timeout)
|
||||
{
|
||||
jint localport = (*env)->GetIntField(env, this, psi_localportID);
|
||||
int len = 0;
|
||||
/* fdObj is the FileDescriptor field on this */
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
|
||||
jclass clazz = (*env)->GetObjectClass(env, this);
|
||||
|
||||
jobject fdLock;
|
||||
|
||||
jint trafficClass = (*env)->GetIntField(env, this, psi_trafficClassID);
|
||||
|
||||
/* fd is an int field on iaObj */
|
||||
jint fd;
|
||||
|
||||
SOCKETADDRESS sa;
|
||||
/* The result of the connection */
|
||||
int connect_rv = -1;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (IS_NULL(iaObj)) {
|
||||
JNU_ThrowNullPointerException(env, "inet address argument null.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect */
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa, &len,
|
||||
JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (trafficClass != 0 && ipv6_available()) {
|
||||
NET_SetTrafficClass(&sa, trafficClass);
|
||||
}
|
||||
|
||||
if (timeout <= 0) {
|
||||
connect_rv = NET_Connect(fd, &sa.sa, len);
|
||||
} else {
|
||||
/*
|
||||
* A timeout was specified. We put the socket into non-blocking
|
||||
* mode, connect, and then wait for the connection to be
|
||||
* established, fail, or timeout.
|
||||
*/
|
||||
SET_NONBLOCKING(fd);
|
||||
|
||||
/* no need to use NET_Connect as non-blocking */
|
||||
connect_rv = connect(fd, &sa.sa, len);
|
||||
|
||||
/* connection not established immediately */
|
||||
if (connect_rv != 0) {
|
||||
socklen_t optlen;
|
||||
jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
|
||||
jlong prevNanoTime = JVM_NanoTime(env, 0);
|
||||
|
||||
if (errno != EINPROGRESS) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
|
||||
"connect failed");
|
||||
SET_BLOCKING(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the connection to be established or a
|
||||
* timeout occurs. poll needs to handle EINTR in
|
||||
* case lwp sig handler redirects any process signals to
|
||||
* this thread.
|
||||
*/
|
||||
while (1) {
|
||||
jlong newNanoTime;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLOUT;
|
||||
|
||||
errno = 0;
|
||||
connect_rv = NET_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
|
||||
|
||||
if (connect_rv >= 0) {
|
||||
break;
|
||||
}
|
||||
if (errno != EINTR) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The poll was interrupted so adjust timeout and
|
||||
* restart
|
||||
*/
|
||||
newNanoTime = JVM_NanoTime(env, 0);
|
||||
nanoTimeout -= (newNanoTime - prevNanoTime);
|
||||
if (nanoTimeout < NET_NSEC_PER_MSEC) {
|
||||
connect_rv = 0;
|
||||
break;
|
||||
}
|
||||
prevNanoTime = newNanoTime;
|
||||
|
||||
} /* while */
|
||||
|
||||
if (connect_rv == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"connect timed out");
|
||||
|
||||
/*
|
||||
* Timeout out but connection may still be established.
|
||||
* At the high level it should be closed immediately but
|
||||
* just in case we make the socket blocking again and
|
||||
* shutdown input & output.
|
||||
*/
|
||||
SET_BLOCKING(fd);
|
||||
shutdown(fd, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
/* has connection been established */
|
||||
optlen = sizeof(connect_rv);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
|
||||
&optlen) <0) {
|
||||
connect_rv = errno;
|
||||
}
|
||||
}
|
||||
|
||||
/* make socket blocking again */
|
||||
SET_BLOCKING(fd);
|
||||
|
||||
/* restore errno */
|
||||
if (connect_rv != 0) {
|
||||
errno = connect_rv;
|
||||
connect_rv = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* report the appropriate exception */
|
||||
if (connect_rv < 0) {
|
||||
|
||||
#ifdef __linux__
|
||||
/*
|
||||
* Linux/GNU distribution setup /etc/hosts so that
|
||||
* InetAddress.getLocalHost gets back the loopback address
|
||||
* rather than the host address. Thus a socket can be
|
||||
* bound to the loopback address and the connect will
|
||||
* fail with EADDRNOTAVAIL. In addition the Linux kernel
|
||||
* returns the wrong error in this case - it returns EINVAL
|
||||
* instead of EADDRNOTAVAIL. We handle this here so that
|
||||
* a more descriptive exception text is used.
|
||||
*/
|
||||
if (connect_rv == -1 && errno == EINVAL) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Invalid argument or cannot assign requested address");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if defined(EPROTO)
|
||||
if (errno == EPROTO) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
|
||||
"Protocol error");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (errno == ECONNREFUSED) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
|
||||
"Connection refused");
|
||||
} else if (errno == ETIMEDOUT) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
|
||||
"Connection timed out");
|
||||
} else if (errno == EHOSTUNREACH) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
|
||||
"Host unreachable");
|
||||
} else if (errno == EADDRNOTAVAIL) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
|
||||
"Address not available");
|
||||
} else if ((errno == EISCONN) || (errno == EBADF)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "connect failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
|
||||
|
||||
/* set the remote peer address and port */
|
||||
(*env)->SetObjectField(env, this, psi_addressID, iaObj);
|
||||
(*env)->SetIntField(env, this, psi_portID, port);
|
||||
|
||||
/*
|
||||
* we need to initialize the local port field if bind was called
|
||||
* previously to the connect (by the client) then localport field
|
||||
* will already be initialized
|
||||
*/
|
||||
if (localport == 0) {
|
||||
/* Now that we're a connected socket, let's extract the port number
|
||||
* that the system chose for us and store it in the Socket object.
|
||||
*/
|
||||
socklen_t slen = sizeof(SOCKETADDRESS);
|
||||
if (getsockname(fd, &sa.sa, &slen) == -1) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
|
||||
} else {
|
||||
localport = NET_GetPortFromSockaddr(&sa);
|
||||
(*env)->SetIntField(env, this, psi_localportID, localport);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketBind
|
||||
* Signature: (Ljava/net/InetAddress;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
|
||||
jobject iaObj, jint localport) {
|
||||
|
||||
/* fdObj is the FileDescriptor field on this */
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
/* fd is an int field on fdObj */
|
||||
int fd;
|
||||
int len = 0;
|
||||
SOCKETADDRESS sa;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (IS_NULL(iaObj)) {
|
||||
JNU_ThrowNullPointerException(env, "iaObj is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* bind */
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, localport, &sa,
|
||||
&len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NET_Bind(fd, &sa, len) < 0) {
|
||||
if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
|
||||
errno == EPERM || errno == EACCES) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
|
||||
"Bind failed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Bind failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the address */
|
||||
(*env)->SetObjectField(env, this, psi_addressID, iaObj);
|
||||
|
||||
/* initialize the local port */
|
||||
if (localport == 0) {
|
||||
socklen_t slen = sizeof(SOCKETADDRESS);
|
||||
/* Now that we're a connected socket, let's extract the port number
|
||||
* that the system chose for us and store it in the Socket object.
|
||||
*/
|
||||
if (getsockname(fd, &sa.sa, &slen) == -1) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
|
||||
return;
|
||||
}
|
||||
localport = NET_GetPortFromSockaddr(&sa);
|
||||
(*env)->SetIntField(env, this, psi_localportID, localport);
|
||||
} else {
|
||||
(*env)->SetIntField(env, this, psi_localportID, localport);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketListen
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketListen(JNIEnv *env, jobject this,
|
||||
jint count)
|
||||
{
|
||||
/* this FileDescriptor fd field */
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
/* fdObj's int fd field */
|
||||
int fd;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
|
||||
* If listen backlog is Integer.MAX_VALUE then subtract 1.
|
||||
*/
|
||||
if (count == 0x7fffffff)
|
||||
count -= 1;
|
||||
|
||||
if (listen(fd, count) == -1) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Listen failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketAccept
|
||||
* Signature: (Ljava/net/SocketImpl;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
|
||||
jobject socket)
|
||||
{
|
||||
/* fields on this */
|
||||
int port;
|
||||
jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
|
||||
jlong prevNanoTime = 0;
|
||||
jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
|
||||
/* the FileDescriptor field on socket */
|
||||
jobject socketFdObj;
|
||||
/* the InetAddress field on socket */
|
||||
jobject socketAddressObj;
|
||||
|
||||
/* the ServerSocket fd int field on fdObj */
|
||||
jint fd;
|
||||
|
||||
/* accepted fd */
|
||||
jint newfd;
|
||||
|
||||
SOCKETADDRESS sa;
|
||||
socklen_t slen = sizeof(SOCKETADDRESS);
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (IS_NULL(socket)) {
|
||||
JNU_ThrowNullPointerException(env, "socket is null");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* accept connection but ignore ECONNABORTED indicating that
|
||||
* connection was eagerly accepted by the OS but was reset
|
||||
* before accept() was called.
|
||||
*
|
||||
* If accept timeout in place and timeout is adjusted with
|
||||
* each ECONNABORTED or EWOULDBLOCK or EAGAIN to ensure that
|
||||
* semantics of timeout are preserved.
|
||||
*/
|
||||
for (;;) {
|
||||
int ret;
|
||||
jlong currNanoTime;
|
||||
|
||||
/* first usage pick up current time */
|
||||
if (prevNanoTime == 0 && nanoTimeout > 0) {
|
||||
prevNanoTime = JVM_NanoTime(env, 0);
|
||||
}
|
||||
|
||||
/* passing a timeout of 0 to poll will return immediately,
|
||||
but in the case of ServerSocket 0 means infinite. */
|
||||
if (timeout <= 0) {
|
||||
ret = NET_Timeout(env, fd, -1, 0);
|
||||
} else {
|
||||
ret = NET_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC, prevNanoTime);
|
||||
}
|
||||
if (ret == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Accept timed out");
|
||||
return;
|
||||
} else if (ret == -1) {
|
||||
if (errno == EBADF) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
} else if (errno == ENOMEM) {
|
||||
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Accept failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
newfd = NET_Accept(fd, &sa.sa, &slen);
|
||||
|
||||
/* connection accepted */
|
||||
if (newfd >= 0) {
|
||||
SET_BLOCKING(newfd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* non (ECONNABORTED or EWOULDBLOCK or EAGAIN) error */
|
||||
if (!(errno == ECONNABORTED || errno == EWOULDBLOCK || errno == EAGAIN)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* ECONNABORTED or EWOULDBLOCK or EAGAIN error so adjust timeout if there is one. */
|
||||
if (nanoTimeout >= NET_NSEC_PER_MSEC) {
|
||||
currNanoTime = JVM_NanoTime(env, 0);
|
||||
nanoTimeout -= (currNanoTime - prevNanoTime);
|
||||
if (nanoTimeout < NET_NSEC_PER_MSEC) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Accept timed out");
|
||||
return;
|
||||
}
|
||||
prevNanoTime = currNanoTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (newfd < 0) {
|
||||
if (newfd == -2) {
|
||||
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
|
||||
"operation interrupted");
|
||||
} else {
|
||||
if (errno == EINVAL) {
|
||||
errno = EBADF;
|
||||
}
|
||||
if (errno == EBADF) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Accept failed");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill up the remote peer port and address in the new socket structure.
|
||||
*/
|
||||
socketAddressObj = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
if (socketAddressObj == NULL) {
|
||||
/* should be pending exception */
|
||||
close(newfd);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Populate SocketImpl.fd.fd
|
||||
*/
|
||||
socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
|
||||
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
|
||||
|
||||
(*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
|
||||
(*env)->SetIntField(env, socket, psi_portID, port);
|
||||
/* also fill up the local port information */
|
||||
port = (*env)->GetIntField(env, this, psi_localportID);
|
||||
(*env)->SetIntField(env, socket, psi_localportID, port);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketAvailable
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
|
||||
int count = 0;
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
jint fd;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return -1;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (NET_SocketAvailable(fd, &count) != 0) {
|
||||
if (errno == ECONNRESET) {
|
||||
JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "ioctl FIONREAD failed");
|
||||
}
|
||||
}
|
||||
return (jint) count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketClose0
|
||||
* Signature: (Z)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
|
||||
jboolean useDeferredClose) {
|
||||
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
jint fd;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"socket already closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (fd != -1) {
|
||||
if (useDeferredClose && marker_fd >= 0) {
|
||||
NET_Dup2(marker_fd, fd);
|
||||
} else {
|
||||
(*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
|
||||
NET_SocketClose(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketShutdown
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
|
||||
jint howto)
|
||||
{
|
||||
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
jint fd;
|
||||
|
||||
/*
|
||||
* WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
|
||||
* -1 already?
|
||||
*/
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"socket already closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
shutdown(fd, howto);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketSetOption0
|
||||
* Signature: (IZLjava/lang/Object;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketSetOption0
|
||||
(JNIEnv *env, jobject this, jint cmd, jboolean on, jobject value)
|
||||
{
|
||||
int fd;
|
||||
int level, optname, optlen;
|
||||
union {
|
||||
int i;
|
||||
struct linger ling;
|
||||
} optval;
|
||||
|
||||
/*
|
||||
* Check that socket hasn't been closed
|
||||
*/
|
||||
fd = getFD(env, this);
|
||||
if (fd < 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* SO_TIMEOUT is a NOOP on Solaris/Linux
|
||||
*/
|
||||
if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the Java level socket option to the platform specific
|
||||
* level and option name.
|
||||
*/
|
||||
if (NET_MapSocketOption(cmd, &level, &optname)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case java_net_SocketOptions_SO_SNDBUF :
|
||||
case java_net_SocketOptions_SO_RCVBUF :
|
||||
case java_net_SocketOptions_SO_LINGER :
|
||||
case java_net_SocketOptions_IP_TOS :
|
||||
{
|
||||
jclass cls;
|
||||
jfieldID fid;
|
||||
|
||||
cls = (*env)->FindClass(env, "java/lang/Integer");
|
||||
CHECK_NULL(cls);
|
||||
fid = (*env)->GetFieldID(env, cls, "value", "I");
|
||||
CHECK_NULL(fid);
|
||||
|
||||
if (cmd == java_net_SocketOptions_SO_LINGER) {
|
||||
if (on) {
|
||||
optval.ling.l_onoff = 1;
|
||||
optval.ling.l_linger = (*env)->GetIntField(env, value, fid);
|
||||
} else {
|
||||
optval.ling.l_onoff = 0;
|
||||
optval.ling.l_linger = 0;
|
||||
}
|
||||
optlen = sizeof(optval.ling);
|
||||
} else {
|
||||
optval.i = (*env)->GetIntField(env, value, fid);
|
||||
optlen = sizeof(optval.i);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Boolean -> int */
|
||||
default :
|
||||
optval.i = (on ? 1 : 0);
|
||||
optlen = sizeof(optval.i);
|
||||
|
||||
}
|
||||
|
||||
if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
|
||||
#if defined(_AIX)
|
||||
if (errno == EINVAL) {
|
||||
// On AIX setsockopt will set errno to EINVAL if the socket
|
||||
// is closed. The default error message is then confusing
|
||||
char fullMsg[128];
|
||||
jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
|
||||
return;
|
||||
}
|
||||
#endif /* _AIX */
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketGetOption
|
||||
* Signature: (ILjava/lang/Object;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketGetOption
|
||||
(JNIEnv *env, jobject this, jint cmd, jobject iaContainerObj)
|
||||
{
|
||||
int fd;
|
||||
int level, optname, optlen;
|
||||
union {
|
||||
int i;
|
||||
struct linger ling;
|
||||
} optval;
|
||||
|
||||
/*
|
||||
* Check that socket hasn't been closed
|
||||
*/
|
||||
fd = getFD(env, this);
|
||||
if (fd < 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* SO_BINDADDR isn't a socket option
|
||||
*/
|
||||
if (cmd == java_net_SocketOptions_SO_BINDADDR) {
|
||||
SOCKETADDRESS sa;
|
||||
socklen_t len = sizeof(SOCKETADDRESS);
|
||||
int port;
|
||||
jobject iaObj;
|
||||
jclass iaCntrClass;
|
||||
jfieldID iaFieldID;
|
||||
|
||||
if (getsockname(fd, &sa.sa, &len) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error getting socket name");
|
||||
return -1;
|
||||
}
|
||||
iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
CHECK_NULL_RETURN(iaObj, -1);
|
||||
|
||||
iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
|
||||
iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
|
||||
CHECK_NULL_RETURN(iaFieldID, -1);
|
||||
(*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
|
||||
return 0; /* notice change from before */
|
||||
}
|
||||
|
||||
/*
|
||||
* Map the Java level socket option to the platform specific
|
||||
* level and option name.
|
||||
*/
|
||||
if (NET_MapSocketOption(cmd, &level, &optname)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Args are int except for SO_LINGER
|
||||
*/
|
||||
if (cmd == java_net_SocketOptions_SO_LINGER) {
|
||||
optlen = sizeof(optval.ling);
|
||||
} else {
|
||||
optlen = sizeof(optval.i);
|
||||
}
|
||||
|
||||
if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case java_net_SocketOptions_SO_LINGER:
|
||||
return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
|
||||
|
||||
case java_net_SocketOptions_SO_SNDBUF:
|
||||
case java_net_SocketOptions_SO_RCVBUF:
|
||||
case java_net_SocketOptions_IP_TOS:
|
||||
return optval.i;
|
||||
|
||||
default :
|
||||
return (optval.i == 0) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socketSendUrgentData
|
||||
* Signature: (B)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
|
||||
jint data) {
|
||||
/* The fd field */
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
|
||||
int n, fd;
|
||||
unsigned char d = data & 0xFF;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
/* Bug 4086704 - If the Socket associated with this file descriptor
|
||||
* was closed (sysCloseFD), the file descriptor is set to -1.
|
||||
*/
|
||||
if (fd == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
n = NET_Send(fd, (char *)&d, 1, MSG_OOB);
|
||||
if (n == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Write failed");
|
||||
}
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "net_util.h"
|
||||
#include "java_net_SocketCleanable.h"
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketCleanable
|
||||
* Method: cleanupClose0
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketCleanable_cleanupClose0(JNIEnv *env, jclass c1, jint fd)
|
||||
{
|
||||
NET_SocketClose(fd);
|
||||
}
|
||||
|
||||
@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jvm.h"
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_SocketInputStream.h"
|
||||
|
||||
/*
|
||||
* SocketInputStream
|
||||
*/
|
||||
|
||||
static jfieldID IO_fd_fdID;
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketInputStream
|
||||
* Method: init
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) {
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
}
|
||||
|
||||
static int NET_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len, long timeout) {
|
||||
int result = 0;
|
||||
jlong prevNanoTime = JVM_NanoTime(env, 0);
|
||||
jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
|
||||
while (nanoTimeout >= NET_NSEC_PER_MSEC) {
|
||||
result = NET_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC, prevNanoTime);
|
||||
if (result <= 0) {
|
||||
if (result == 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketTimeoutException", "Read timed out");
|
||||
} else if (result == -1) {
|
||||
if (errno == EBADF) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
} else if (errno == ENOMEM) {
|
||||
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, "java/net/SocketException", "select/poll failed");
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
result = NET_NonBlockingRead(fd, bufP, len);
|
||||
if (result == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
|
||||
jlong newtNanoTime = JVM_NanoTime(env, 0);
|
||||
nanoTimeout -= newtNanoTime - prevNanoTime;
|
||||
if (nanoTimeout >= NET_NSEC_PER_MSEC) {
|
||||
prevNanoTime = newtNanoTime;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketInputStream
|
||||
* Method: socketRead0
|
||||
* Signature: (Ljava/io/FileDescriptor;[BIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
|
||||
jobject fdObj, jbyteArray data,
|
||||
jint off, jint len, jint timeout)
|
||||
{
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
char *bufP;
|
||||
jint fd, nread;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException",
|
||||
"Socket closed");
|
||||
return -1;
|
||||
}
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
if (fd == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the read is greater than our stack allocated buffer then
|
||||
* we allocate from the heap (up to a limit)
|
||||
*/
|
||||
if (len > MAX_BUFFER_LEN) {
|
||||
if (len > MAX_HEAP_BUFFER_LEN) {
|
||||
len = MAX_HEAP_BUFFER_LEN;
|
||||
}
|
||||
bufP = (char *)malloc((size_t)len);
|
||||
if (bufP == NULL) {
|
||||
bufP = BUF;
|
||||
len = MAX_BUFFER_LEN;
|
||||
}
|
||||
} else {
|
||||
bufP = BUF;
|
||||
}
|
||||
if (timeout) {
|
||||
nread = NET_ReadWithTimeout(env, fd, bufP, len, timeout);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
} else {
|
||||
nread = NET_Read(fd, bufP, len);
|
||||
}
|
||||
|
||||
if (nread <= 0) {
|
||||
if (nread < 0) {
|
||||
|
||||
switch (errno) {
|
||||
case ECONNRESET:
|
||||
case EPIPE:
|
||||
JNU_ThrowByName(env, "sun/net/ConnectionResetException",
|
||||
"Connection reset");
|
||||
break;
|
||||
|
||||
case EBADF:
|
||||
JNU_ThrowByName(env, "java/net/SocketException",
|
||||
"Socket closed");
|
||||
break;
|
||||
|
||||
case EINTR:
|
||||
JNU_ThrowByName(env, "java/io/InterruptedIOException",
|
||||
"Operation interrupted");
|
||||
break;
|
||||
default:
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, "java/net/SocketException", "Read failed");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
|
||||
}
|
||||
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_SocketOutputStream.h"
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/*
|
||||
* SocketOutputStream
|
||||
*/
|
||||
|
||||
static jfieldID IO_fd_fdID;
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketOutputStream
|
||||
* Method: init
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketOutputStream_init(JNIEnv *env, jclass cls) {
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketOutputStream
|
||||
* Method: socketWrite0
|
||||
* Signature: (Ljava/io/FileDescriptor;[BII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
|
||||
jobject fdObj,
|
||||
jbyteArray data,
|
||||
jint off, jint len) {
|
||||
char *bufP;
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
int buflen;
|
||||
int fd;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
/* Bug 4086704 - If the Socket associated with this file descriptor
|
||||
* was closed (sysCloseFD), the file descriptor is set to -1.
|
||||
*/
|
||||
if (fd == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (len <= MAX_BUFFER_LEN) {
|
||||
bufP = BUF;
|
||||
buflen = MAX_BUFFER_LEN;
|
||||
} else {
|
||||
buflen = min(MAX_HEAP_BUFFER_LEN, len);
|
||||
bufP = (char *)malloc((size_t)buflen);
|
||||
|
||||
/* if heap exhausted resort to stack buffer */
|
||||
if (bufP == NULL) {
|
||||
bufP = BUF;
|
||||
buflen = MAX_BUFFER_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
while(len > 0) {
|
||||
int loff = 0;
|
||||
int chunkLen = min(buflen, len);
|
||||
int llen = chunkLen;
|
||||
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
|
||||
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
break;
|
||||
} else {
|
||||
while(llen > 0) {
|
||||
int n = NET_Send(fd, bufP + loff, llen, 0);
|
||||
if (n > 0) {
|
||||
llen -= n;
|
||||
loff += n;
|
||||
continue;
|
||||
}
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, "java/net/SocketException", "Write failed");
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
len -= chunkLen;
|
||||
off += chunkLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.util.Properties;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* This class defines a factory for creating DatagramSocketImpls. It defaults
|
||||
* to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls
|
||||
* by setting the impl.prefix system property.
|
||||
*
|
||||
* For Windows versions lower than Windows Vista a TwoStacksPlainDatagramSocketImpl
|
||||
* is always created. This impl supports IPv6 on these platform where available.
|
||||
*
|
||||
* On Windows platforms greater than Vista that support a dual layer TCP/IP stack
|
||||
* a DualStackPlainDatagramSocketImpl is created for DatagramSockets. For MulticastSockets
|
||||
* a TwoStacksPlainDatagramSocketImpl is always created. This is to overcome the lack
|
||||
* of behavior defined for multicasting over a dual layer socket by the RFC.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class DefaultDatagramSocketImplFactory
|
||||
{
|
||||
private static final Class<?> prefixImplClass;
|
||||
|
||||
/* java.net.preferIPv4Stack */
|
||||
private static final boolean preferIPv4Stack;
|
||||
|
||||
/* True if exclusive binding is on for Windows */
|
||||
private static final boolean exclusiveBind;
|
||||
|
||||
static {
|
||||
Class<?> prefixImplClassLocal = null;
|
||||
|
||||
Properties props = GetPropertyAction.privilegedGetProperties();
|
||||
preferIPv4Stack = Boolean.parseBoolean(
|
||||
props.getProperty("java.net.preferIPv4Stack"));
|
||||
|
||||
String exclBindProp = props.getProperty("sun.net.useExclusiveBind", "");
|
||||
exclusiveBind = (exclBindProp.isEmpty())
|
||||
? true
|
||||
: Boolean.parseBoolean(exclBindProp);
|
||||
|
||||
// impl.prefix
|
||||
String prefix = null;
|
||||
try {
|
||||
prefix = props.getProperty("impl.prefix");
|
||||
if (prefix != null)
|
||||
prefixImplClassLocal = Class.forName("java.net."+prefix+"DatagramSocketImpl");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Can't find class: java.net." +
|
||||
prefix +
|
||||
"DatagramSocketImpl: check impl.prefix property");
|
||||
}
|
||||
|
||||
prefixImplClass = prefixImplClassLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>DatagramSocketImpl</code> instance.
|
||||
*
|
||||
* @param isMulticast true if this impl is to be used for a MutlicastSocket
|
||||
* @return a new instance of <code>PlainDatagramSocketImpl</code>.
|
||||
*/
|
||||
static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast)
|
||||
throws SocketException {
|
||||
if (prefixImplClass != null) {
|
||||
try {
|
||||
@SuppressWarnings("deprecation")
|
||||
Object result = prefixImplClass.newInstance();
|
||||
return (DatagramSocketImpl) result;
|
||||
} catch (Exception e) {
|
||||
throw new SocketException("can't instantiate DatagramSocketImpl");
|
||||
}
|
||||
} else {
|
||||
// Always use TwoStacksPlainDatagramSocketImpl since we need
|
||||
// to support multicasting at DatagramSocket level
|
||||
return new TwoStacksPlainDatagramSocketImpl(exclusiveBind && !isMulticast, isMulticast);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,324 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
/**
|
||||
* This class defines the plain DatagramSocketImpl that is used on
|
||||
* Windows platforms greater than or equal to Windows Vista. These
|
||||
* platforms have a dual layer TCP/IP stack and can handle both IPv4
|
||||
* and IPV6 through a single file descriptor.
|
||||
* <p>
|
||||
* Note: Multicasting on a dual layer TCP/IP stack is always done with
|
||||
* TwoStacksPlainDatagramSocketImpl. This is to overcome the lack
|
||||
* of behavior defined for multicasting over a dual layer socket by the RFC.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
||||
{
|
||||
static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
// true if this socket is exclusively bound
|
||||
private final boolean exclusiveBind;
|
||||
|
||||
/*
|
||||
* Set to true if SO_REUSEADDR is set after the socket is bound to
|
||||
* indicate SO_REUSEADDR is being emulated
|
||||
*/
|
||||
private boolean reuseAddressEmulated;
|
||||
|
||||
// emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
|
||||
private boolean isReuseAddress;
|
||||
|
||||
DualStackPlainDatagramSocketImpl(boolean exclBind) {
|
||||
super(false);
|
||||
exclusiveBind = exclBind;
|
||||
}
|
||||
|
||||
protected void datagramSocketCreate() throws SocketException {
|
||||
if (fd == null)
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
int newfd = socketCreate();
|
||||
|
||||
fdAccess.set(fd, newfd);
|
||||
}
|
||||
|
||||
protected synchronized void bind0(int lport, InetAddress laddr)
|
||||
throws SocketException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (laddr == null)
|
||||
throw new NullPointerException("argument address");
|
||||
|
||||
socketBind(nativefd, laddr, lport, exclusiveBind);
|
||||
if (lport == 0) {
|
||||
localPort = socketLocalPort(nativefd);
|
||||
} else {
|
||||
localPort = lport;
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized int peek(InetAddress address) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (address == null)
|
||||
throw new NullPointerException("Null address in peek()");
|
||||
|
||||
// Use peekData()
|
||||
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
|
||||
int peekPort = peekData(peekPacket);
|
||||
address = peekPacket.getAddress();
|
||||
return peekPort;
|
||||
}
|
||||
|
||||
protected synchronized int peekData(DatagramPacket p) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (p == null)
|
||||
throw new NullPointerException("packet");
|
||||
if (p.getData() == null)
|
||||
throw new NullPointerException("packet buffer");
|
||||
|
||||
return socketReceiveOrPeekData(nativefd, p, timeout, connected, true /*peek*/);
|
||||
}
|
||||
|
||||
protected synchronized void receive0(DatagramPacket p) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (p == null)
|
||||
throw new NullPointerException("packet");
|
||||
if (p.getData() == null)
|
||||
throw new NullPointerException("packet buffer");
|
||||
|
||||
socketReceiveOrPeekData(nativefd, p, timeout, connected, false /*receive*/);
|
||||
}
|
||||
|
||||
protected void send0(DatagramPacket p) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (p == null)
|
||||
throw new NullPointerException("null packet");
|
||||
|
||||
if (p.getAddress() == null ||p.getData() ==null)
|
||||
throw new NullPointerException("null address || null buffer");
|
||||
|
||||
socketSend(nativefd, p.getData(), p.getOffset(), p.getLength(),
|
||||
p.getAddress(), p.getPort(), connected);
|
||||
}
|
||||
|
||||
protected void connect0(InetAddress address, int port) throws SocketException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (address == null)
|
||||
throw new NullPointerException("address");
|
||||
|
||||
socketConnect(nativefd, address, port);
|
||||
}
|
||||
|
||||
protected void disconnect0(int family /*unused*/) {
|
||||
if (fd == null || !fd.valid())
|
||||
return; // disconnect doesn't throw any exceptions
|
||||
|
||||
socketDisconnect(fdAccess.get(fd));
|
||||
}
|
||||
|
||||
protected void datagramSocketClose() {
|
||||
if (fd == null || !fd.valid())
|
||||
return; // close doesn't throw any exceptions
|
||||
|
||||
socketClose(fdAccess.get(fd));
|
||||
fdAccess.set(fd, -1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
protected void socketSetOption(int opt, Object val) throws SocketException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
int optionValue = 0;
|
||||
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
if (opt == SO_REUSEPORT) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
|
||||
switch(opt) {
|
||||
case IP_TOS :
|
||||
case SO_RCVBUF :
|
||||
case SO_SNDBUF :
|
||||
optionValue = ((Integer)val).intValue();
|
||||
break;
|
||||
case SO_REUSEADDR :
|
||||
if (exclusiveBind && localPort != 0) {
|
||||
// socket already bound, emulate SO_REUSEADDR
|
||||
reuseAddressEmulated = true;
|
||||
isReuseAddress = (Boolean)val;
|
||||
return;
|
||||
}
|
||||
//Intentional fallthrough
|
||||
case SO_BROADCAST :
|
||||
optionValue = ((Boolean)val).booleanValue() ? 1 : 0;
|
||||
break;
|
||||
default: /* shouldn't get here */
|
||||
throw new SocketException("Option not supported");
|
||||
}
|
||||
|
||||
socketSetIntOption(nativefd, opt, optionValue);
|
||||
}
|
||||
|
||||
protected Object socketGetOption(int opt) throws SocketException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
// SO_BINDADDR is not a socket option.
|
||||
if (opt == SO_BINDADDR) {
|
||||
return socketLocalAddress(nativefd);
|
||||
}
|
||||
if (opt == SO_REUSEADDR && reuseAddressEmulated)
|
||||
return isReuseAddress;
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
if (opt == SO_REUSEPORT)
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
|
||||
int value = socketGetIntOption(nativefd, opt);
|
||||
Object returnValue = null;
|
||||
|
||||
switch (opt) {
|
||||
case SO_REUSEADDR :
|
||||
case SO_BROADCAST :
|
||||
returnValue = (value == 0) ? Boolean.FALSE : Boolean.TRUE;
|
||||
break;
|
||||
case IP_TOS :
|
||||
case SO_RCVBUF :
|
||||
case SO_SNDBUF :
|
||||
returnValue = Integer.valueOf(value);
|
||||
break;
|
||||
default: /* shouldn't get here */
|
||||
throw new SocketException("Option not supported");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<SocketOption<?>> supportedOptions() {
|
||||
HashSet<SocketOption<?>> options = new HashSet<>();
|
||||
options.add(StandardSocketOptions.SO_SNDBUF);
|
||||
options.add(StandardSocketOptions.SO_RCVBUF);
|
||||
options.add(StandardSocketOptions.SO_REUSEADDR);
|
||||
options.add(StandardSocketOptions.SO_BROADCAST);
|
||||
options.add(StandardSocketOptions.IP_TOS);
|
||||
|
||||
options.addAll(ExtendedSocketOptions.datagramSocketOptions());
|
||||
return Collections.unmodifiableSet(options);
|
||||
}
|
||||
|
||||
/* Multicast specific methods.
|
||||
* Multicasting on a dual layer TCP/IP stack is always done with
|
||||
* TwoStacksPlainDatagramSocketImpl. This is to overcome the lack
|
||||
* of behavior defined for multicasting over a dual layer socket by the RFC.
|
||||
*/
|
||||
protected void join(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
|
||||
protected void leave(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
|
||||
protected void setTimeToLive(int ttl) throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
|
||||
protected int getTimeToLive() throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void setTTL(byte ttl) throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected byte getTTL() throws IOException {
|
||||
throw new IOException("Method not implemented!");
|
||||
}
|
||||
/* END Multicast specific methods */
|
||||
|
||||
private int checkAndReturnNativeFD() throws SocketException {
|
||||
if (fd == null || !fd.valid())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
return fdAccess.get(fd);
|
||||
}
|
||||
|
||||
/* Native methods */
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
private static native int socketCreate();
|
||||
|
||||
private static native void socketBind(int fd, InetAddress localAddress,
|
||||
int localport, boolean exclBind) throws SocketException;
|
||||
|
||||
private static native void socketConnect(int fd, InetAddress address, int port)
|
||||
throws SocketException;
|
||||
|
||||
private static native void socketDisconnect(int fd);
|
||||
|
||||
private static native void socketClose(int fd);
|
||||
|
||||
private static native int socketLocalPort(int fd) throws SocketException;
|
||||
|
||||
private static native Object socketLocalAddress(int fd) throws SocketException;
|
||||
|
||||
private static native int socketReceiveOrPeekData(int fd, DatagramPacket packet,
|
||||
int timeout, boolean connected, boolean peek) throws IOException;
|
||||
|
||||
private static native void socketSend(int fd, byte[] data, int offset, int length,
|
||||
InetAddress address, int port, boolean connected) throws IOException;
|
||||
|
||||
private static native void socketSetIntOption(int fd, int cmd,
|
||||
int optionValue) throws SocketException;
|
||||
|
||||
private static native int socketGetIntOption(int fd, int cmd) throws SocketException;
|
||||
|
||||
native int dataAvailable();
|
||||
}
|
||||
@ -1,354 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileDescriptor;
|
||||
import java.security.AccessController;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
|
||||
/**
|
||||
* On Windows system we simply delegate to native methods.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
class PlainSocketImpl extends AbstractPlainSocketImpl {
|
||||
|
||||
private static final JavaIOFileDescriptorAccess fdAccess =
|
||||
SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final boolean preferIPv4Stack =
|
||||
Boolean.parseBoolean(AccessController.doPrivileged(
|
||||
new GetPropertyAction("java.net.preferIPv4Stack", "false")));
|
||||
|
||||
/**
|
||||
* Empty value of sun.net.useExclusiveBind is treated as 'true'.
|
||||
*/
|
||||
private static final boolean useExclusiveBind;
|
||||
|
||||
static {
|
||||
@SuppressWarnings("removal")
|
||||
String exclBindProp = AccessController.doPrivileged(
|
||||
new GetPropertyAction("sun.net.useExclusiveBind", ""));
|
||||
useExclusiveBind = exclBindProp.isEmpty()
|
||||
|| Boolean.parseBoolean(exclBindProp);
|
||||
}
|
||||
|
||||
// emulates SO_REUSEADDR when useExclusiveBind is true
|
||||
private boolean isReuseAddress;
|
||||
|
||||
/**
|
||||
* Constructs an empty instance.
|
||||
*/
|
||||
PlainSocketImpl(boolean isServer) {
|
||||
super(isServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketCreate(boolean stream) throws IOException {
|
||||
if (fd == null)
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
int newfd = socket0(stream);
|
||||
|
||||
fdAccess.set(fd, newfd);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketConnect(InetAddress address, int port, int timeout)
|
||||
throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (address == null)
|
||||
throw new NullPointerException("inet address argument is null.");
|
||||
|
||||
if (preferIPv4Stack && !(address instanceof Inet4Address))
|
||||
throw new SocketException("Protocol family not supported");
|
||||
|
||||
int connectResult;
|
||||
if (timeout <= 0) {
|
||||
connectResult = connect0(nativefd, address, port);
|
||||
} else {
|
||||
configureBlocking(nativefd, false);
|
||||
try {
|
||||
connectResult = connect0(nativefd, address, port);
|
||||
if (connectResult == WOULDBLOCK) {
|
||||
waitForConnect(nativefd, timeout);
|
||||
}
|
||||
} finally {
|
||||
configureBlocking(nativefd, true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We need to set the local port field. If bind was called
|
||||
* previous to the connect (by the client) then localport field
|
||||
* will already be set.
|
||||
*/
|
||||
if (localport == 0)
|
||||
localport = localPort0(nativefd);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketBind(InetAddress address, int port) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (address == null)
|
||||
throw new NullPointerException("inet address argument is null.");
|
||||
|
||||
if (preferIPv4Stack && !(address instanceof Inet4Address))
|
||||
throw new SocketException("Protocol family not supported");
|
||||
|
||||
bind0(nativefd, address, port, useExclusiveBind);
|
||||
if (port == 0) {
|
||||
localport = localPort0(nativefd);
|
||||
} else {
|
||||
localport = port;
|
||||
}
|
||||
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketListen(int backlog) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
listen0(nativefd, backlog);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketAccept(SocketImpl s) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (s == null)
|
||||
throw new NullPointerException("socket is null");
|
||||
|
||||
int newfd = -1;
|
||||
InetSocketAddress[] isaa = new InetSocketAddress[1];
|
||||
if (timeout <= 0) {
|
||||
newfd = accept0(nativefd, isaa);
|
||||
} else {
|
||||
configureBlocking(nativefd, false);
|
||||
try {
|
||||
waitForNewConnection(nativefd, timeout);
|
||||
newfd = accept0(nativefd, isaa);
|
||||
if (newfd != -1) {
|
||||
configureBlocking(newfd, true);
|
||||
}
|
||||
} finally {
|
||||
configureBlocking(nativefd, true);
|
||||
}
|
||||
}
|
||||
/* Update (SocketImpl)s' fd */
|
||||
fdAccess.set(s.fd, newfd);
|
||||
/* Update socketImpls remote port, address and localport */
|
||||
InetSocketAddress isa = isaa[0];
|
||||
s.port = isa.getPort();
|
||||
s.address = isa.getAddress();
|
||||
s.localport = localport;
|
||||
if (preferIPv4Stack && !(s.address instanceof Inet4Address))
|
||||
throw new SocketException("Protocol family not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
int socketAvailable() throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
return available0(nativefd);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
|
||||
if (fd == null)
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
if (!fd.valid())
|
||||
return;
|
||||
|
||||
final int nativefd = fdAccess.get(fd);
|
||||
fdAccess.set(fd, -1);
|
||||
close0(nativefd);
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketShutdown(int howto) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
shutdown0(nativefd, howto);
|
||||
}
|
||||
|
||||
// Intentional fallthrough after SO_REUSEADDR
|
||||
@SuppressWarnings("fallthrough")
|
||||
@Override
|
||||
void socketSetOption(int opt, boolean on, Object value)
|
||||
throws SocketException {
|
||||
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
if (opt == SO_REUSEPORT) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
if (opt == SO_TIMEOUT) {
|
||||
if (preferIPv4Stack) {
|
||||
// Don't enable the socket option on ServerSocket as it's
|
||||
// meaningless (we don't receive on a ServerSocket).
|
||||
if (!isServer) {
|
||||
setSoTimeout0(nativefd, ((Integer)value).intValue());
|
||||
}
|
||||
} // else timeout is implemented through select.
|
||||
return;
|
||||
}
|
||||
|
||||
int optionValue = 0;
|
||||
|
||||
switch(opt) {
|
||||
case SO_REUSEADDR:
|
||||
if (useExclusiveBind) {
|
||||
// SO_REUSEADDR emulated when using exclusive bind
|
||||
isReuseAddress = on;
|
||||
return;
|
||||
}
|
||||
// intentional fallthrough
|
||||
case TCP_NODELAY:
|
||||
case SO_OOBINLINE:
|
||||
case SO_KEEPALIVE:
|
||||
optionValue = on ? 1 : 0;
|
||||
break;
|
||||
case SO_SNDBUF:
|
||||
case SO_RCVBUF:
|
||||
case IP_TOS:
|
||||
optionValue = ((Integer)value).intValue();
|
||||
break;
|
||||
case SO_LINGER:
|
||||
if (on) {
|
||||
optionValue = ((Integer)value).intValue();
|
||||
} else {
|
||||
optionValue = -1;
|
||||
}
|
||||
break;
|
||||
default :/* shouldn't get here */
|
||||
throw new SocketException("Option not supported");
|
||||
}
|
||||
|
||||
setIntOption(nativefd, opt, optionValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
int socketGetOption(int opt, Object iaContainerObj)
|
||||
throws SocketException {
|
||||
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
if (opt == SO_REUSEPORT) {
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
}
|
||||
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
|
||||
// SO_BINDADDR is not a socket option.
|
||||
if (opt == SO_BINDADDR) {
|
||||
localAddress(nativefd, (InetAddressContainer)iaContainerObj);
|
||||
return 0; // return value doesn't matter.
|
||||
}
|
||||
|
||||
// SO_REUSEADDR emulated when using exclusive bind
|
||||
if (opt == SO_REUSEADDR && useExclusiveBind)
|
||||
return isReuseAddress ? 1 : -1;
|
||||
|
||||
int value = getIntOption(nativefd, opt);
|
||||
|
||||
switch (opt) {
|
||||
case TCP_NODELAY:
|
||||
case SO_OOBINLINE:
|
||||
case SO_KEEPALIVE:
|
||||
case SO_REUSEADDR:
|
||||
return (value == 0) ? -1 : 1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
void socketSendUrgentData(int data) throws IOException {
|
||||
int nativefd = checkAndReturnNativeFD();
|
||||
sendOOB(nativefd, data);
|
||||
}
|
||||
|
||||
private int checkAndReturnNativeFD() throws SocketException {
|
||||
if (fd == null || !fd.valid())
|
||||
throw new SocketException("Socket closed");
|
||||
|
||||
return fdAccess.get(fd);
|
||||
}
|
||||
|
||||
static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
}
|
||||
|
||||
/* Native methods */
|
||||
|
||||
static native void initIDs();
|
||||
|
||||
static native int socket0(boolean stream) throws IOException;
|
||||
|
||||
static native void bind0(int fd, InetAddress localAddress, int localport,
|
||||
boolean exclBind)
|
||||
throws IOException;
|
||||
|
||||
static native int connect0(int fd, InetAddress remote, int remotePort)
|
||||
throws IOException;
|
||||
|
||||
static native void waitForConnect(int fd, int timeout) throws IOException;
|
||||
|
||||
static native int localPort0(int fd) throws IOException;
|
||||
|
||||
static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
|
||||
|
||||
static native void listen0(int fd, int backlog) throws IOException;
|
||||
|
||||
static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
|
||||
|
||||
static native void waitForNewConnection(int fd, int timeout) throws IOException;
|
||||
|
||||
static native int available0(int fd) throws IOException;
|
||||
|
||||
static native void close0(int fd) throws IOException;
|
||||
|
||||
static native void shutdown0(int fd, int howto) throws IOException;
|
||||
|
||||
static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
|
||||
|
||||
static native void setSoTimeout0(int fd, int timeout) throws SocketException;
|
||||
|
||||
static native int getIntOption(int fd, int cmd) throws SocketException;
|
||||
|
||||
static native void sendOOB(int fd, int data) throws IOException;
|
||||
|
||||
static native void configureBlocking(int fd, boolean blocking) throws IOException;
|
||||
}
|
||||
@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package java.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileDescriptor;
|
||||
import sun.net.ResourceManager;
|
||||
|
||||
/**
|
||||
* This class defines the plain DatagramSocketImpl that is used for all
|
||||
* Windows versions lower than Vista. It adds support for IPv6 on
|
||||
* these platforms where available.
|
||||
*
|
||||
* For backward compatibility windows platforms that do not have IPv6
|
||||
* support also use this implementation, and fd1 gets set to null
|
||||
* during socket creation.
|
||||
*
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
final class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
|
||||
{
|
||||
/* Used for IPv6 on Windows only */
|
||||
private FileDescriptor fd1;
|
||||
|
||||
/*
|
||||
* Needed for ipv6 on windows because we need to know
|
||||
* if the socket was bound to ::0 or 0.0.0.0, when a caller
|
||||
* asks for it. In this case, both sockets are used, but we
|
||||
* don't know whether the caller requested ::0 or 0.0.0.0
|
||||
* and need to remember it here.
|
||||
*/
|
||||
private InetAddress anyLocalBoundAddr=null;
|
||||
|
||||
private int fduse=-1; /* saved between peek() and receive() calls */
|
||||
|
||||
/* saved between successive calls to receive, if data is detected
|
||||
* on both sockets at same time. To ensure that one socket is not
|
||||
* starved, they rotate using this field
|
||||
*/
|
||||
private int lastfd=-1;
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
// true if this socket is exclusively bound
|
||||
private final boolean exclusiveBind;
|
||||
|
||||
/*
|
||||
* Set to true if SO_REUSEADDR is set after the socket is bound to
|
||||
* indicate SO_REUSEADDR is being emulated
|
||||
*/
|
||||
private boolean reuseAddressEmulated;
|
||||
|
||||
// emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
|
||||
private boolean isReuseAddress;
|
||||
|
||||
TwoStacksPlainDatagramSocketImpl(boolean exclBind, boolean isMulticast) {
|
||||
super(isMulticast);
|
||||
exclusiveBind = exclBind;
|
||||
}
|
||||
|
||||
protected synchronized void create() throws SocketException {
|
||||
fd1 = new FileDescriptor();
|
||||
try {
|
||||
super.create();
|
||||
// make SocketCleanable treat fd1 as a stream socket
|
||||
// to avoid touching the counter in ResourceManager
|
||||
SocketCleanable.register(fd1, true);
|
||||
} catch (SocketException e) {
|
||||
fd1 = null;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void bind(int lport, InetAddress laddr)
|
||||
throws SocketException {
|
||||
super.bind(lport, laddr);
|
||||
if (laddr.isAnyLocalAddress()) {
|
||||
anyLocalBoundAddr = laddr;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void bind0(int lport, InetAddress laddr)
|
||||
throws SocketException
|
||||
{
|
||||
// The native bind0 may close one or both of the underlying file
|
||||
// descriptors, and even create new sockets, so the safest course of
|
||||
// action is to unregister the socket cleaners, and register afterwards.
|
||||
SocketCleanable.unregister(fd);
|
||||
SocketCleanable.unregister(fd1);
|
||||
|
||||
bind0(lport, laddr, exclusiveBind);
|
||||
|
||||
SocketCleanable.register(fd, false);
|
||||
// make SocketCleanable treat fd1 as a stream socket
|
||||
// to avoid touching the counter in ResourceManager
|
||||
SocketCleanable.register(fd1, true);
|
||||
}
|
||||
|
||||
protected synchronized void receive(DatagramPacket p)
|
||||
throws IOException {
|
||||
try {
|
||||
receive0(p);
|
||||
} finally {
|
||||
fduse = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
if (isClosed()) {
|
||||
throw new SocketException("Socket Closed");
|
||||
}
|
||||
|
||||
if (optID == SO_BINDADDR) {
|
||||
if ((fd != null && fd1 != null) && !connected) {
|
||||
return anyLocalBoundAddr;
|
||||
}
|
||||
int family = connectedAddress == null ? -1 : connectedAddress.holder().getFamily();
|
||||
return socketLocalAddress(family);
|
||||
} else if (optID == SO_REUSEADDR && reuseAddressEmulated) {
|
||||
return isReuseAddress;
|
||||
} else if (optID == SO_REUSEPORT) {
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
} else {
|
||||
return super.getOption(optID);
|
||||
}
|
||||
}
|
||||
|
||||
protected void socketSetOption(int opt, Object val)
|
||||
throws SocketException
|
||||
{
|
||||
if (opt == SO_REUSEADDR && exclusiveBind && localPort != 0) {
|
||||
// socket already bound, emulate
|
||||
reuseAddressEmulated = true;
|
||||
isReuseAddress = (Boolean)val;
|
||||
} else if (opt == SO_REUSEPORT) {
|
||||
// SO_REUSEPORT is not supported on Windows.
|
||||
throw new UnsupportedOperationException("unsupported option");
|
||||
} else {
|
||||
socketNativeSetOption(opt, val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean isClosed() {
|
||||
return (fd == null && fd1 == null) ? true : false;
|
||||
}
|
||||
|
||||
protected void close() {
|
||||
if (fd != null || fd1 != null) {
|
||||
SocketCleanable.unregister(fd);
|
||||
SocketCleanable.unregister(fd1);
|
||||
datagramSocketClose();
|
||||
ResourceManager.afterUdpClose();
|
||||
fd = null;
|
||||
fd1 = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* Native methods */
|
||||
|
||||
protected synchronized native void bind0(int lport, InetAddress laddr,
|
||||
boolean exclBind)
|
||||
throws SocketException;
|
||||
|
||||
protected native void send0(DatagramPacket p) throws IOException;
|
||||
|
||||
protected synchronized native int peek(InetAddress i) throws IOException;
|
||||
|
||||
protected synchronized native int peekData(DatagramPacket p) throws IOException;
|
||||
|
||||
protected synchronized native void receive0(DatagramPacket p)
|
||||
throws IOException;
|
||||
|
||||
protected native void setTimeToLive(int ttl) throws IOException;
|
||||
|
||||
protected native int getTimeToLive() throws IOException;
|
||||
|
||||
@Deprecated
|
||||
protected native void setTTL(byte ttl) throws IOException;
|
||||
|
||||
@Deprecated
|
||||
protected native byte getTTL() throws IOException;
|
||||
|
||||
protected native void join(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
protected native void leave(InetAddress inetaddr, NetworkInterface netIf)
|
||||
throws IOException;
|
||||
|
||||
protected native void datagramSocketCreate() throws SocketException;
|
||||
|
||||
protected native void datagramSocketClose();
|
||||
|
||||
protected native void socketNativeSetOption(int opt, Object val)
|
||||
throws SocketException;
|
||||
|
||||
protected native Object socketGetOption(int opt) throws SocketException;
|
||||
|
||||
protected native void connect0(InetAddress address, int port) throws SocketException;
|
||||
|
||||
protected native Object socketLocalAddress(int family) throws SocketException;
|
||||
|
||||
protected native void disconnect0(int family);
|
||||
|
||||
native int dataAvailable();
|
||||
|
||||
/**
|
||||
* Perform class load-time initializations.
|
||||
*/
|
||||
private static native void init();
|
||||
}
|
||||
@ -1,539 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_DualStackPlainDatagramSocketImpl.h"
|
||||
|
||||
/*
|
||||
* This function "purges" all outstanding ICMP port unreachable packets
|
||||
* outstanding on a socket and returns JNI_TRUE if any ICMP messages
|
||||
* have been purged. The rational for purging is to emulate normal BSD
|
||||
* behaviour whereby receiving a "connection reset" status resets the
|
||||
* socket.
|
||||
*/
|
||||
static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd)
|
||||
{
|
||||
jboolean got_icmp = JNI_FALSE;
|
||||
char buf[1];
|
||||
fd_set tbl;
|
||||
struct timeval t = { 0, 0 };
|
||||
SOCKETADDRESS rmtaddr;
|
||||
int addrlen = sizeof(rmtaddr);
|
||||
|
||||
/*
|
||||
* Peek at the queue to see if there is an ICMP port unreachable. If there
|
||||
* is then receive it.
|
||||
*/
|
||||
FD_ZERO(&tbl);
|
||||
FD_SET(fd, &tbl);
|
||||
while(1) {
|
||||
if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) {
|
||||
break;
|
||||
}
|
||||
if (recvfrom(fd, buf, 1, MSG_PEEK,
|
||||
&rmtaddr.sa, &addrlen) != SOCKET_ERROR) {
|
||||
break;
|
||||
}
|
||||
if (WSAGetLastError() != WSAECONNRESET) {
|
||||
/* some other error - we don't care here */
|
||||
break;
|
||||
}
|
||||
|
||||
recvfrom(fd, buf, 1, 0, &rmtaddr.sa, &addrlen);
|
||||
got_icmp = JNI_TRUE;
|
||||
}
|
||||
|
||||
return got_icmp;
|
||||
}
|
||||
|
||||
static jfieldID IO_fd_fdID = NULL;
|
||||
static jfieldID pdsi_fdID = NULL;
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: initIDs
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_initIDs
|
||||
(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
pdsi_fdID = (*env)->GetFieldID(env, clazz, "fd",
|
||||
"Ljava/io/FileDescriptor;");
|
||||
CHECK_NULL(pdsi_fdID);
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
CHECK_NULL(IO_fd_fdID);
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
|
||||
initInetAddressIDs(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketCreate
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate
|
||||
(JNIEnv *env, jclass clazz) {
|
||||
int fd, rv, opt=0, t=TRUE;
|
||||
DWORD x1, x2; /* ignored result codes */
|
||||
|
||||
fd = (int) socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (fd == INVALID_SOCKET) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
|
||||
if (rv == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
|
||||
NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL));
|
||||
|
||||
/* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which
|
||||
* returns connection reset errors on unconnected UDP sockets (as well
|
||||
* as connected sockets). The solution is to only enable this feature
|
||||
* when the socket is connected.
|
||||
*/
|
||||
t = FALSE;
|
||||
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketBind
|
||||
* Signature: (ILjava/net/InetAddress;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) {
|
||||
SOCKETADDRESS sa;
|
||||
int rv, sa_len = 0;
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
|
||||
&sa_len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
rv = NET_WinBind(fd, &sa, sa_len, exclBind);
|
||||
|
||||
if (rv == SOCKET_ERROR) {
|
||||
if (WSAGetLastError() == WSAEACCES) {
|
||||
WSASetLastError(WSAEADDRINUSE);
|
||||
}
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Cannot bind");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketConnect
|
||||
* Signature: (ILjava/net/InetAddress;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
|
||||
SOCKETADDRESS sa;
|
||||
int rv, sa_len = 0, t;
|
||||
DWORD x1, x2; /* ignored result codes */
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
|
||||
&sa_len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = connect(fd, &sa.sa, sa_len);
|
||||
if (rv == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "connect");
|
||||
return;
|
||||
}
|
||||
|
||||
/* see comment in socketCreate */
|
||||
t = TRUE;
|
||||
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketDisconnect
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisconnect
|
||||
(JNIEnv *env, jclass clazz, jint fd ) {
|
||||
SOCKETADDRESS sa;
|
||||
int sa_len = sizeof(sa);
|
||||
DWORD x1, x2; /* ignored result codes */
|
||||
int t = FALSE;
|
||||
|
||||
memset(&sa, 0, sa_len);
|
||||
connect(fd, &sa.sa, sa_len);
|
||||
|
||||
/* see comment in socketCreate */
|
||||
WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketClose
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose
|
||||
(JNIEnv *env, jclass clazz , jint fd) {
|
||||
NET_SocketClose(fd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketLocalPort
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort
|
||||
(JNIEnv *env, jclass clazz, jint fd) {
|
||||
SOCKETADDRESS sa;
|
||||
int len = sizeof(sa);
|
||||
|
||||
if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockname");
|
||||
return -1;
|
||||
}
|
||||
return (int) ntohs((u_short)GET_PORT(&sa));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketLocalAddress
|
||||
* Signature: (I)Ljava/lang/Object;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress
|
||||
(JNIEnv *env , jclass clazz, jint fd) {
|
||||
SOCKETADDRESS sa;
|
||||
int len = sizeof(sa);
|
||||
jobject iaObj;
|
||||
int port;
|
||||
|
||||
if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
return iaObj;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketReceiveOrPeekData
|
||||
* Signature: (ILjava/net/DatagramPacket;IZZ)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketReceiveOrPeekData
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject dpObj,
|
||||
jint timeout, jboolean connected, jboolean peek) {
|
||||
SOCKETADDRESS sa;
|
||||
int sa_len = sizeof(sa);
|
||||
int port, rv, flags=0;
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
char *fullPacket;
|
||||
BOOL retry;
|
||||
jlong prevTime = 0;
|
||||
|
||||
jint packetBufferOffset, packetBufferLen;
|
||||
jbyteArray packetBuffer;
|
||||
|
||||
/* if we are only peeking. Called from peekData */
|
||||
if (peek) {
|
||||
flags = MSG_PEEK;
|
||||
}
|
||||
|
||||
packetBuffer = (*env)->GetObjectField(env, dpObj, dp_bufID);
|
||||
packetBufferOffset = (*env)->GetIntField(env, dpObj, dp_offsetID);
|
||||
packetBufferLen = (*env)->GetIntField(env, dpObj, dp_bufLengthID);
|
||||
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
|
||||
* the max size of an IP packet. Anything bigger is truncated anyway.
|
||||
*/
|
||||
if (packetBufferLen > MAX_PACKET_LEN) {
|
||||
packetBufferLen = MAX_PACKET_LEN;
|
||||
}
|
||||
|
||||
if (packetBufferLen > MAX_BUFFER_LEN) {
|
||||
fullPacket = (char *)malloc(packetBufferLen);
|
||||
if (!fullPacket) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fullPacket = &(BUF[0]);
|
||||
}
|
||||
|
||||
do {
|
||||
retry = FALSE;
|
||||
|
||||
if (timeout) {
|
||||
if (prevTime == 0) {
|
||||
prevTime = JVM_CurrentTimeMillis(env, 0);
|
||||
}
|
||||
rv = NET_Timeout(fd, timeout);
|
||||
if (rv <= 0) {
|
||||
if (rv == 0) {
|
||||
JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Receive timed out");
|
||||
} else if (rv == -1) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
}
|
||||
if (packetBufferLen > MAX_BUFFER_LEN) {
|
||||
free(fullPacket);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* receive the packet */
|
||||
rv = recvfrom(fd, fullPacket, packetBufferLen, flags,
|
||||
&sa.sa, &sa_len);
|
||||
|
||||
if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
|
||||
/* An icmp port unreachable - we must receive this as Windows
|
||||
* does not reset the state of the socket until this has been
|
||||
* received.
|
||||
*/
|
||||
purgeOutstandingICMP(env, fd);
|
||||
|
||||
if (connected) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
|
||||
"ICMP Port Unreachable");
|
||||
if (packetBufferLen > MAX_BUFFER_LEN)
|
||||
free(fullPacket);
|
||||
return -1;
|
||||
} else if (timeout) {
|
||||
/* Adjust timeout */
|
||||
jlong newTime = JVM_CurrentTimeMillis(env, 0);
|
||||
timeout -= (jint)(newTime - prevTime);
|
||||
if (timeout <= 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Receive timed out");
|
||||
if (packetBufferLen > MAX_BUFFER_LEN)
|
||||
free(fullPacket);
|
||||
return -1;
|
||||
}
|
||||
prevTime = newTime;
|
||||
}
|
||||
retry = TRUE;
|
||||
}
|
||||
} while (retry);
|
||||
|
||||
port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&sa));
|
||||
|
||||
/* truncate the data if the packet's length is too small */
|
||||
if (rv > packetBufferLen) {
|
||||
rv = packetBufferLen;
|
||||
}
|
||||
if (rv < 0) {
|
||||
if (WSAGetLastError() == WSAEMSGSIZE) {
|
||||
/* it is because the buffer is too small. It's UDP, it's
|
||||
* unreliable, it's all good. discard the rest of the
|
||||
* data..
|
||||
*/
|
||||
rv = packetBufferLen;
|
||||
} else {
|
||||
/* failure */
|
||||
(*env)->SetIntField(env, dpObj, dp_lengthID, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (rv == -1) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
|
||||
} else if (rv == -2) {
|
||||
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
|
||||
"operation interrupted");
|
||||
} else if (rv < 0) {
|
||||
NET_ThrowCurrent(env, "Datagram receive failed");
|
||||
} else {
|
||||
jobject packetAddress;
|
||||
/*
|
||||
* Check if there is an InetAddress already associated with this
|
||||
* packet. If so, we check if it is the same source address. We
|
||||
* can't update any existing InetAddress because it is immutable
|
||||
*/
|
||||
packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID);
|
||||
if (packetAddress != NULL) {
|
||||
if (!NET_SockaddrEqualsInetAddress(env, &sa, packetAddress)) {
|
||||
/* force a new InetAddress to be created */
|
||||
packetAddress = NULL;
|
||||
}
|
||||
}
|
||||
if (!(*env)->ExceptionCheck(env)){
|
||||
if (packetAddress == NULL ) {
|
||||
packetAddress = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
if (packetAddress != NULL) {
|
||||
/* stuff the new InetAddress into the packet */
|
||||
(*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress);
|
||||
}
|
||||
}
|
||||
/* populate the packet */
|
||||
(*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, rv,
|
||||
(jbyte *)fullPacket);
|
||||
(*env)->SetIntField(env, dpObj, dp_portID, port);
|
||||
(*env)->SetIntField(env, dpObj, dp_lengthID, rv);
|
||||
}
|
||||
}
|
||||
|
||||
if (packetBufferLen > MAX_BUFFER_LEN) {
|
||||
free(fullPacket);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketSend
|
||||
* Signature: (I[BIILjava/net/InetAddress;IZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend
|
||||
(JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length,
|
||||
jobject iaObj, jint port, jboolean connected) {
|
||||
SOCKETADDRESS sa;
|
||||
int rv, sa_len = 0;
|
||||
struct sockaddr *sap = 0;
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
char *fullPacket;
|
||||
|
||||
// if already connected, sap arg to sendto() is null
|
||||
if (!connected) {
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
|
||||
&sa_len, JNI_TRUE) != 0) {
|
||||
return;
|
||||
}
|
||||
sap = &sa.sa;
|
||||
}
|
||||
|
||||
if (length > MAX_BUFFER_LEN) {
|
||||
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
|
||||
* the max size of an IP packet. Anything bigger is truncated anyway.
|
||||
*/
|
||||
if (length > MAX_PACKET_LEN) {
|
||||
length = MAX_PACKET_LEN;
|
||||
}
|
||||
fullPacket = (char *)malloc(length);
|
||||
if (!fullPacket) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
fullPacket = &(BUF[0]);
|
||||
}
|
||||
|
||||
(*env)->GetByteArrayRegion(env, data, offset, length,
|
||||
(jbyte *)fullPacket);
|
||||
rv = sendto(fd, fullPacket, length, 0, sap, sa_len);
|
||||
if (rv == SOCKET_ERROR) {
|
||||
if (rv == -1) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (length > MAX_BUFFER_LEN) {
|
||||
free(fullPacket);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketSetIntOption
|
||||
* Signature: (III)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
|
||||
{
|
||||
int level = 0, opt = 0;
|
||||
|
||||
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NET_SetSockOpt(fd, level, opt, (char *)&value, sizeof(value)) < 0) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: socketGetIntOption
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint cmd)
|
||||
{
|
||||
int level = 0, opt = 0, result = 0;
|
||||
int result_len = sizeof(result);
|
||||
|
||||
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (NET_GetSockOpt(fd, level, opt, (void *)&result, &result_len) < 0) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_DualStackPlainDatagramSocketImpl
|
||||
* Method: dataAvailable
|
||||
* Signature: ()I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_DualStackPlainDatagramSocketImpl_dataAvailable
|
||||
(JNIEnv *env, jobject this)
|
||||
{
|
||||
SOCKET fd;
|
||||
int rv = -1;
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
|
||||
|
||||
if (!IS_NULL(fdObj)) {
|
||||
int retval = 0;
|
||||
fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
rv = ioctlsocket(fd, FIONREAD, &retval);
|
||||
if (retval > 0) {
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,535 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_PlainSocketImpl.h"
|
||||
#include "java_net_SocketOptions.h"
|
||||
|
||||
#define SET_BLOCKING 0
|
||||
#define SET_NONBLOCKING 1
|
||||
|
||||
static jclass isa_class; /* java.net.InetSocketAddress */
|
||||
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: initIDs
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_initIDs
|
||||
(JNIEnv *env, jclass clazz) {
|
||||
|
||||
jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
|
||||
CHECK_NULL(cls);
|
||||
isa_class = (*env)->NewGlobalRef(env, cls);
|
||||
CHECK_NULL(isa_class);
|
||||
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
CHECK_NULL(isa_ctorID);
|
||||
initInetAddressIDs(env);
|
||||
|
||||
// implement read timeout with select.
|
||||
isRcvTimeoutSupported = JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: socket0
|
||||
* Signature: (ZZ)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_socket0
|
||||
(JNIEnv *env, jclass clazz, jboolean stream) {
|
||||
int fd, rv, opt = 0;
|
||||
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||
|
||||
fd = NET_Socket(domain, type, 0);
|
||||
|
||||
if (fd == INVALID_SOCKET) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "create");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (domain == AF_INET6) {
|
||||
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
|
||||
sizeof(opt));
|
||||
if (rv == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "create");
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: bind0
|
||||
* Signature: (ILjava/net/InetAddress;I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_bind0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
|
||||
jboolean exclBind)
|
||||
{
|
||||
SOCKETADDRESS sa;
|
||||
int rv, sa_len = 0;
|
||||
jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
|
||||
&sa_len, v4MappedAddress) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = NET_WinBind(fd, &sa, sa_len, exclBind);
|
||||
|
||||
if (rv == SOCKET_ERROR)
|
||||
NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: connect0
|
||||
* Signature: (ILjava/net/InetAddress;I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_connect0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
|
||||
SOCKETADDRESS sa;
|
||||
int rv, sa_len = 0;
|
||||
jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
|
||||
|
||||
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
|
||||
&sa_len, v4MappedAddress) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = connect(fd, &sa.sa, sa_len);
|
||||
if (rv == SOCKET_ERROR) {
|
||||
int err = WSAGetLastError();
|
||||
if (err == WSAEWOULDBLOCK) {
|
||||
return java_net_PlainSocketImpl_WOULDBLOCK;
|
||||
} else if (err == WSAEADDRNOTAVAIL) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
|
||||
"connect: Address is invalid on local machine,"
|
||||
" or port is not valid on remote machine");
|
||||
} else {
|
||||
NET_ThrowNew(env, err, "connect");
|
||||
}
|
||||
// return value not important.
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: waitForConnect
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForConnect
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
|
||||
int rv, retry;
|
||||
int optlen = sizeof(rv);
|
||||
fd_set wr, ex;
|
||||
struct timeval t;
|
||||
|
||||
FD_ZERO(&wr);
|
||||
FD_ZERO(&ex);
|
||||
FD_SET(fd, &wr);
|
||||
FD_SET(fd, &ex);
|
||||
t.tv_sec = timeout / 1000;
|
||||
t.tv_usec = (timeout % 1000) * 1000;
|
||||
|
||||
/*
|
||||
* Wait for timeout, connection established or
|
||||
* connection failed.
|
||||
*/
|
||||
rv = select(fd+1, 0, &wr, &ex, &t);
|
||||
|
||||
/*
|
||||
* Timeout before connection is established/failed so
|
||||
* we throw exception and shutdown input/output to prevent
|
||||
* socket from being used.
|
||||
* The socket should be closed immediately by the caller.
|
||||
*/
|
||||
if (rv == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"connect timed out");
|
||||
shutdown(fd, SD_BOTH);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Socket is writable or error occurred. On some Windows editions
|
||||
* the socket will appear writable when the connect fails so we
|
||||
* check for error rather than writable.
|
||||
*/
|
||||
if (!FD_ISSET(fd, &ex)) {
|
||||
return; /* connection established */
|
||||
}
|
||||
|
||||
/*
|
||||
* Connection failed. The logic here is designed to work around
|
||||
* bug on Windows NT whereby using getsockopt to obtain the
|
||||
* last error (SO_ERROR) indicates there is no error. The workaround
|
||||
* on NT is to allow winsock to be scheduled and this is done by
|
||||
* yielding and retrying. As yielding is problematic in heavy
|
||||
* load conditions we attempt up to 3 times to get the error reason.
|
||||
*/
|
||||
for (retry = 0; retry < 3; retry++) {
|
||||
NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
|
||||
(char*)&rv, &optlen);
|
||||
if (rv) {
|
||||
break;
|
||||
}
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Unable to establish connection");
|
||||
} else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
|
||||
"connect: Address is invalid on local machine,"
|
||||
" or port is not valid on remote machine");
|
||||
} else {
|
||||
NET_ThrowNew(env, rv, "connect");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: localPort0
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_localPort0
|
||||
(JNIEnv *env, jclass clazz, jint fd) {
|
||||
SOCKETADDRESS sa;
|
||||
int len = sizeof(sa);
|
||||
|
||||
if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
|
||||
if (WSAGetLastError() == WSAENOTSOCK) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
} else {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return (int) ntohs((u_short)GET_PORT(&sa));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: localAddress
|
||||
* Signature: (ILjava/net/InetAddressContainer;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_localAddress
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
|
||||
int port;
|
||||
SOCKETADDRESS sa;
|
||||
int len = sizeof(sa);
|
||||
jobject iaObj;
|
||||
jclass iaContainerClass;
|
||||
jfieldID iaFieldID;
|
||||
|
||||
if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
|
||||
return;
|
||||
}
|
||||
iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
CHECK_NULL(iaObj);
|
||||
|
||||
iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
|
||||
iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
|
||||
CHECK_NULL(iaFieldID);
|
||||
(*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: listen0
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_listen0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint backlog) {
|
||||
if (listen(fd, backlog) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "listen failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: accept0
|
||||
* Signature: (I[Ljava/net/InetSocketAddress;)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_accept0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
|
||||
int newfd, port = 0;
|
||||
jobject isa;
|
||||
jobject ia;
|
||||
SOCKETADDRESS sa;
|
||||
int len = sizeof(sa);
|
||||
|
||||
memset((char *)&sa, 0, len);
|
||||
newfd = accept(fd, &sa.sa, &len);
|
||||
|
||||
if (newfd == INVALID_SOCKET) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "accept failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
|
||||
|
||||
ia = NET_SockaddrToInetAddress(env, &sa, &port);
|
||||
if (ia == NULL){
|
||||
closesocket(newfd);
|
||||
return -1;
|
||||
}
|
||||
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
|
||||
if (isa == NULL) {
|
||||
closesocket(newfd);
|
||||
return -1;
|
||||
}
|
||||
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
|
||||
|
||||
return newfd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: waitForNewConnection
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForNewConnection
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint timeout) {
|
||||
int rv;
|
||||
|
||||
rv = NET_Timeout(fd, timeout);
|
||||
if (rv == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Accept timed out");
|
||||
} else if (rv == -1) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
|
||||
} else if (rv == -2) {
|
||||
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
|
||||
"operation interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: available0
|
||||
* Signature: (I)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_available0
|
||||
(JNIEnv *env, jclass clazz, jint fd) {
|
||||
jint available = -1;
|
||||
|
||||
if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "socket available");
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: close0
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_close0
|
||||
(JNIEnv *env, jclass clazz, jint fd) {
|
||||
NET_SocketClose(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: shutdown0
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_shutdown0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint howto) {
|
||||
shutdown(fd, howto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: setIntOption
|
||||
* Signature: (III)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_setIntOption
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
|
||||
{
|
||||
int level = 0, opt = 0;
|
||||
struct linger linger = {0, 0};
|
||||
char *parg;
|
||||
int arglen;
|
||||
|
||||
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt == java_net_SocketOptions_SO_LINGER) {
|
||||
parg = (char *)&linger;
|
||||
arglen = sizeof(linger);
|
||||
if (value >= 0) {
|
||||
linger.l_onoff = 1;
|
||||
linger.l_linger = (unsigned short)value;
|
||||
} else {
|
||||
linger.l_onoff = 0;
|
||||
linger.l_linger = 0;
|
||||
}
|
||||
} else {
|
||||
parg = (char *)&value;
|
||||
arglen = sizeof(value);
|
||||
}
|
||||
|
||||
if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: setSoTimeout0
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainSocketImpl_setSoTimeout0
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint timeout)
|
||||
{
|
||||
/*
|
||||
* SO_TIMEOUT is the socket option used to specify the timeout
|
||||
* for ServerSocket.accept and Socket.getInputStream().read.
|
||||
* It does not typically map to a native level socket option.
|
||||
* For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
|
||||
* socket option to specify a receive timeout on the socket. This
|
||||
* receive timeout is applicable to Socket only and the socket
|
||||
* option should not be set on ServerSocket.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SO_RCVTIMEO is only supported on Microsoft's implementation
|
||||
* of Windows Sockets so if WSAENOPROTOOPT returned then
|
||||
* reset flag and timeout will be implemented using
|
||||
* select() -- see SocketInputStream.socketRead.
|
||||
*/
|
||||
if (isRcvTimeoutSupported) {
|
||||
/*
|
||||
* Disable SO_RCVTIMEO if timeout is <= 5 second.
|
||||
*/
|
||||
if (timeout <= 5000) {
|
||||
timeout = 0;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
|
||||
sizeof(timeout)) < 0) {
|
||||
int err = WSAGetLastError();
|
||||
if (err == WSAENOPROTOOPT) {
|
||||
isRcvTimeoutSupported = JNI_FALSE;
|
||||
} else {
|
||||
NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: getIntOption
|
||||
* Signature: (II)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_getIntOption
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint cmd)
|
||||
{
|
||||
int level = 0, opt = 0;
|
||||
int result = 0;
|
||||
struct linger linger = {0, 0};
|
||||
char *arg;
|
||||
int arglen;
|
||||
|
||||
if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opt == java_net_SocketOptions_SO_LINGER) {
|
||||
arg = (char *)&linger;
|
||||
arglen = sizeof(linger);
|
||||
} else {
|
||||
arg = (char *)&result;
|
||||
arglen = sizeof(result);
|
||||
}
|
||||
|
||||
if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (opt == java_net_SocketOptions_SO_LINGER)
|
||||
return linger.l_onoff ? linger.l_linger : -1;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: sendOOB
|
||||
* Signature: (II)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_sendOOB
|
||||
(JNIEnv *env, jclass clazz, jint fd, jint data) {
|
||||
jint n;
|
||||
unsigned char d = (unsigned char) data & 0xff;
|
||||
|
||||
n = send(fd, (char *)&data, 1, MSG_OOB);
|
||||
if (n == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "send");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_PlainSocketImpl
|
||||
* Method: configureBlocking
|
||||
* Signature: (IZ)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_configureBlocking
|
||||
(JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
|
||||
u_long arg;
|
||||
int result;
|
||||
|
||||
if (blocking == JNI_TRUE) {
|
||||
arg = SET_BLOCKING; // 0
|
||||
} else {
|
||||
arg = SET_NONBLOCKING; // 1
|
||||
}
|
||||
|
||||
result = ioctlsocket(fd, FIONBIO, &arg);
|
||||
if (result == SOCKET_ERROR) {
|
||||
NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
#include "net_util.h"
|
||||
#include "java_net_SocketCleanable.h"
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
// SO_REUSEPORT is not supported on Windows
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
// SO_REUSEPORT is not supported on Windows
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1)
|
||||
{
|
||||
// SO_REUSEPORT is not supported on Windows
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketCleanable
|
||||
* Method: cleanupClose0
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketCleanable_cleanupClose0(JNIEnv *env, jclass c1, jint fd)
|
||||
{
|
||||
NET_SocketClose(fd);
|
||||
}
|
||||
|
||||
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <malloc.h>
|
||||
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_SocketInputStream.h"
|
||||
|
||||
/*************************************************************************
|
||||
* SocketInputStream
|
||||
*/
|
||||
static jfieldID IO_fd_fdID;
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketInputStream
|
||||
* Method: init
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) {
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketInputStream
|
||||
* Method: socketRead
|
||||
* Signature: (Ljava/io/FileDescriptor;[BIII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
|
||||
jobject fdObj, jbyteArray data,
|
||||
jint off, jint len, jint timeout)
|
||||
{
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
char *bufP;
|
||||
jint fd, newfd, nread;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException",
|
||||
"Socket closed");
|
||||
return -1;
|
||||
}
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
if (fd == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the caller buffer is large than our stack buffer then we allocate
|
||||
* from the heap (up to a limit). If memory is exhausted we always use
|
||||
* the stack buffer.
|
||||
*/
|
||||
if (len <= MAX_BUFFER_LEN) {
|
||||
bufP = BUF;
|
||||
} else {
|
||||
if (len > MAX_HEAP_BUFFER_LEN) {
|
||||
len = MAX_HEAP_BUFFER_LEN;
|
||||
}
|
||||
bufP = (char *)malloc((size_t)len);
|
||||
if (bufP == NULL) {
|
||||
/* allocation failed so use stack buffer */
|
||||
bufP = BUF;
|
||||
len = MAX_BUFFER_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (timeout) {
|
||||
if (timeout <= 5000 || !isRcvTimeoutSupported) {
|
||||
int ret = NET_Timeout (fd, timeout);
|
||||
|
||||
if (ret <= 0) {
|
||||
if (ret == 0) {
|
||||
JNU_ThrowByName(env, "java/net/SocketTimeoutException",
|
||||
"Read timed out");
|
||||
} else if (ret == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "socket closed");
|
||||
}
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*check if the socket has been closed while we were in timeout*/
|
||||
newfd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
if (newfd == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nread = recv(fd, bufP, len, 0);
|
||||
if (nread > 0) {
|
||||
(*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
|
||||
} else {
|
||||
if (nread < 0) {
|
||||
int err = WSAGetLastError();
|
||||
// Check if the socket has been closed since we last checked.
|
||||
// This could be a reason for recv failing.
|
||||
if ((*env)->GetIntField(env, fdObj, IO_fd_fdID) == -1) {
|
||||
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
|
||||
} else {
|
||||
switch (err) {
|
||||
case WSAEINTR:
|
||||
JNU_ThrowByName(env, "java/net/SocketException",
|
||||
"socket closed");
|
||||
break;
|
||||
|
||||
case WSAECONNRESET:
|
||||
case WSAESHUTDOWN:
|
||||
/*
|
||||
* Connection has been reset - Windows sometimes reports
|
||||
* the reset as a shutdown error.
|
||||
*/
|
||||
JNU_ThrowByName(env, "sun/net/ConnectionResetException",
|
||||
"");
|
||||
break;
|
||||
|
||||
case WSAETIMEDOUT :
|
||||
JNU_ThrowByName(env, "java/net/SocketTimeoutException",
|
||||
"Read timed out");
|
||||
break;
|
||||
|
||||
default:
|
||||
NET_ThrowCurrent(env, "recv failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return nread;
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <malloc.h>
|
||||
|
||||
#include "net_util.h"
|
||||
|
||||
#include "java_net_SocketOutputStream.h"
|
||||
|
||||
/************************************************************************
|
||||
* SocketOutputStream
|
||||
*/
|
||||
static jfieldID IO_fd_fdID;
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketOutputStream
|
||||
* Method: init
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketOutputStream_init(JNIEnv *env, jclass cls) {
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketOutputStream
|
||||
* Method: socketWrite
|
||||
* Signature: (Ljava/io/FileDescriptor;[BII)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
|
||||
jobject fdObj, jbyteArray data,
|
||||
jint off, jint len) {
|
||||
char *bufP;
|
||||
char BUF[MAX_BUFFER_LEN];
|
||||
int buflen;
|
||||
int fd;
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
return;
|
||||
} else {
|
||||
fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
|
||||
}
|
||||
if (IS_NULL(data)) {
|
||||
JNU_ThrowNullPointerException(env, "data argument");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use stack allocate buffer if possible. For large sizes we allocate
|
||||
* an intermediate buffer from the heap (up to a maximum). If heap is
|
||||
* unavailable just use our stack buffer.
|
||||
*/
|
||||
if (len <= MAX_BUFFER_LEN) {
|
||||
bufP = BUF;
|
||||
buflen = MAX_BUFFER_LEN;
|
||||
} else {
|
||||
buflen = min(MAX_HEAP_BUFFER_LEN, len);
|
||||
bufP = (char *)malloc((size_t)buflen);
|
||||
if (bufP == NULL) {
|
||||
bufP = BUF;
|
||||
buflen = MAX_BUFFER_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
while(len > 0) {
|
||||
int loff = 0;
|
||||
int chunkLen = min(buflen, len);
|
||||
int llen = chunkLen;
|
||||
int retry = 0;
|
||||
|
||||
(*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
break;
|
||||
} else {
|
||||
while(llen > 0) {
|
||||
int n = send(fd, bufP + loff, llen, 0);
|
||||
if (n > 0) {
|
||||
llen -= n;
|
||||
loff += n;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Due to a bug in Windows Sockets (observed on NT and Windows
|
||||
* 2000) it may be necessary to retry the send. The issue is that
|
||||
* on blocking sockets send/WSASend is supposed to block if there
|
||||
* is insufficient buffer space available. If there are a large
|
||||
* number of threads blocked on write due to congestion then it's
|
||||
* possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
|
||||
* The workaround we use is to retry the send. If we have a
|
||||
* large buffer to send (>2k) then we retry with a maximum of
|
||||
* 2k buffer. If we hit the issue with <=2k buffer then we backoff
|
||||
* for 1 second and retry again. We repeat this up to a reasonable
|
||||
* limit before bailing out and throwing an exception. In load
|
||||
* conditions we've observed that the send will succeed after 2-3
|
||||
* attempts but this depends on network buffers associated with
|
||||
* other sockets draining.
|
||||
*/
|
||||
if (WSAGetLastError() == WSAENOBUFS) {
|
||||
if (llen > MAX_BUFFER_LEN) {
|
||||
buflen = MAX_BUFFER_LEN;
|
||||
chunkLen = MAX_BUFFER_LEN;
|
||||
llen = MAX_BUFFER_LEN;
|
||||
continue;
|
||||
}
|
||||
if (retry >= 30) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"No buffer space available - exhausted attempts to queue buffer");
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Sleep(1000);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send failed - can be caused by close or write error.
|
||||
*/
|
||||
if (WSAGetLastError() == WSAENOTSOCK) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
} else {
|
||||
NET_ThrowCurrent(env, "socket write error");
|
||||
}
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
len -= chunkLen;
|
||||
off += chunkLen;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -265,13 +265,6 @@ dbgsysNetworkToHostLong(uint32_t netlong) {
|
||||
return (uint32_t)ntohl((u_long)netlong);
|
||||
}
|
||||
|
||||
/*
|
||||
* Below Adapted from PlainSocketImpl.c, win32 version 1.18. Changed exception
|
||||
* throws to returns of SYS_ERR; we should improve the error codes
|
||||
* eventually. Changed java objects to values the debugger back end can
|
||||
* more easily deal with.
|
||||
*/
|
||||
|
||||
int
|
||||
dbgsysSetSocketOption(int fd, jint cmd, jboolean on, jvalue value)
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@
|
||||
* @build jdk.test.lib.net.SimpleSSLContext
|
||||
* @run main/othervm Test1
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true Test1
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl Test1
|
||||
* @run main/othervm -Dsun.net.httpserver.maxReqTime=10 Test1
|
||||
* @run main/othervm -Dsun.net.httpserver.nodelay=true Test1
|
||||
* @summary Light weight HTTP server
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@
|
||||
* @summary DatagramSocket.send should throw IllegalArgumentException
|
||||
* when the packet address is not correctly set.
|
||||
* @run main AddressNotSet
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl AddressNotSet
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
@ -33,8 +33,6 @@
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* @run main/othervm DatagramSocketExample
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true DatagramSocketExample
|
||||
* @run main/othervm -Djdk.usePlainDatagramSocketImpl=true DatagramSocketExample
|
||||
* @run main/othervm -Djdk.usePlainDatagramSocketImpl=true -Djava.net.preferIPv4Stack=true DatagramSocketExample
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* @run main/othervm DatagramSocketMulticasting
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true DatagramSocketMulticasting
|
||||
* @run main/othervm -Djdk.usePlainDatagramSocketImpl=true DatagramSocketMulticasting
|
||||
* @run main/othervm -Djdk.usePlainDatagramSocketImpl=true -Djava.net.preferIPv4Stack=true DatagramSocketMulticasting
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@
|
||||
* @summary Test to see if timeout hangs. Also checks that
|
||||
* negative timeout value fails as expected.
|
||||
* @run testng DatagramTimeout
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl DatagramTimeout
|
||||
*/
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,7 +37,6 @@ import static java.lang.Thread.sleep;
|
||||
* @summary Check interrupt mechanism for DatagramSocket,
|
||||
* MulticastSocket, and DatagramSocketAdaptor
|
||||
* @run main InterruptibleDatagramSocket
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl InterruptibleDatagramSocket
|
||||
*/
|
||||
|
||||
public class InterruptibleDatagramSocket {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
/* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,7 +36,6 @@ import java.net.SocketException;
|
||||
* @summary Expected SocketException not thrown when calling bind() with
|
||||
* setReuseAddress(false)
|
||||
* @run main/othervm ReuseAddressTest
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl ReuseAddressTest
|
||||
*/
|
||||
|
||||
public class ReuseAddressTest {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,7 +48,6 @@ import static org.testng.Assert.expectThrows;
|
||||
* throw expected Execption when passed a DatagramPacket
|
||||
* with invalid details
|
||||
* @run testng SendCheck
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl SendCheck
|
||||
*/
|
||||
|
||||
public class SendCheck {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,7 @@
|
||||
*
|
||||
* @summary DatagramSocket.send should throw exception when connected
|
||||
* to an invalid destination (on platforms that support it).
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl=false SendDatagramToBadAddress
|
||||
* @run main/othervm SendDatagramToBadAddress
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,7 +49,6 @@ import static org.testng.Assert.assertThrows;
|
||||
* @summary Check that DatagramSocket throws expected
|
||||
* Exception when sending a DatagramPacket with port 0
|
||||
* @run testng/othervm -Djava.security.manager=allow SendPortZero
|
||||
* @run testng/othervm -Djava.security.manager=allow -Djdk.net.usePlainDatagramSocketImpl SendPortZero
|
||||
*/
|
||||
|
||||
public class SendPortZero {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,9 +36,6 @@
|
||||
* @run testng/othervm SendReceiveMaxSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SendReceiveMaxSize
|
||||
* @run testng/othervm -Djava.net.preferIPv6Addresses=true SendReceiveMaxSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl SendReceiveMaxSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl -Djava.net.preferIPv4Stack=true SendReceiveMaxSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl -Djava.net.preferIPv6Addresses=true SendReceiveMaxSize
|
||||
*/
|
||||
|
||||
import jdk.test.lib.RandomFactory;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,14 +23,149 @@
|
||||
|
||||
package java.net;
|
||||
|
||||
public class MyDatagramSocketImplFactory implements DatagramSocketImplFactory {
|
||||
public DatagramSocketImpl createDatagramSocketImpl() {
|
||||
try {
|
||||
return DefaultDatagramSocketImplFactory.createDatagramSocketImpl(false);
|
||||
} catch (SocketException se) {
|
||||
assert false;
|
||||
}
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
|
||||
return null;
|
||||
public class MyDatagramSocketImplFactory implements DatagramSocketImplFactory {
|
||||
static class MyDatagramSocketImpl extends DatagramSocketImpl {
|
||||
DatagramSocket ds;
|
||||
|
||||
@Override
|
||||
protected void create() throws SocketException {
|
||||
try {
|
||||
ds = DatagramChannel.open().socket();
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage());}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bind(int lport, InetAddress laddr) throws SocketException {
|
||||
ds.bind(new InetSocketAddress(laddr, lport));
|
||||
localPort = ds.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void send(DatagramPacket p) throws IOException {
|
||||
ds.send(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int peek(InetAddress i) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int peekData(DatagramPacket p) throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void receive(DatagramPacket p) throws IOException {
|
||||
ds.receive(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setTTL(byte ttl) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte getTTL() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setTimeToLive(int ttl) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTimeToLive() throws IOException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void join(InetAddress inetaddr) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void leave(InetAddress inetaddr) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close() {
|
||||
ds.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOption(int optID, Object value) throws SocketException {
|
||||
try {
|
||||
if (optID == SocketOptions.SO_SNDBUF) {
|
||||
if (((Integer) value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid send buffer size:" + value);
|
||||
ds.setOption(StandardSocketOptions.SO_SNDBUF, (Integer) value);
|
||||
} else if (optID == SocketOptions.SO_RCVBUF) {
|
||||
if (((Integer) value).intValue() < 0)
|
||||
throw new IllegalArgumentException("Invalid recv buffer size:" + value);
|
||||
ds.setOption(StandardSocketOptions.SO_RCVBUF, (Integer) value);
|
||||
} else if (optID == SocketOptions.SO_REUSEADDR) {
|
||||
ds.setOption(StandardSocketOptions.SO_REUSEADDR, (Boolean) value);
|
||||
} else if (optID == SocketOptions.SO_REUSEPORT) {
|
||||
ds.setOption(StandardSocketOptions.SO_REUSEPORT, (Boolean) value);
|
||||
} else if (optID == SocketOptions.SO_BROADCAST) {
|
||||
ds.setOption(StandardSocketOptions.SO_BROADCAST, (Boolean) value);
|
||||
} else if (optID == SocketOptions.IP_TOS) {
|
||||
int i = ((Integer) value).intValue();
|
||||
if (i < 0 || i > 255)
|
||||
throw new IllegalArgumentException("Invalid IP_TOS value: " + value);
|
||||
ds.setOption(StandardSocketOptions.IP_TOS, (Integer) value);
|
||||
} else if (optID == SocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean enable = (boolean) value;
|
||||
// Legacy ds.setOption expects true to mean 'disabled'
|
||||
ds.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, !enable);
|
||||
} else {
|
||||
throw new AssertionError("unknown option :" + optID);
|
||||
}
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage()); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOption(int optID) throws SocketException {
|
||||
try {
|
||||
if (optID == SocketOptions.SO_SNDBUF) {
|
||||
return ds.getOption(StandardSocketOptions.SO_SNDBUF);
|
||||
} else if (optID == SocketOptions.SO_RCVBUF) {
|
||||
return ds.getOption(StandardSocketOptions.SO_RCVBUF);
|
||||
} else if (optID == SocketOptions.SO_REUSEADDR) {
|
||||
return ds.getOption(StandardSocketOptions.SO_REUSEADDR);
|
||||
} else if (optID == SocketOptions.SO_REUSEPORT) {
|
||||
return ds.getOption(StandardSocketOptions.SO_REUSEPORT);
|
||||
} else if (optID == SocketOptions.SO_BROADCAST) {
|
||||
return ds.getOption(StandardSocketOptions.SO_BROADCAST);
|
||||
} else if (optID == SocketOptions.IP_TOS) {
|
||||
return ds.getOption(StandardSocketOptions.IP_TOS);
|
||||
} else if (optID == SocketOptions.IP_MULTICAST_LOOP) {
|
||||
boolean disabled = (boolean) ds.getOption(StandardSocketOptions.IP_MULTICAST_LOOP);
|
||||
// Legacy getOption returns true when disabled
|
||||
return Boolean.valueOf(!disabled);
|
||||
} else {
|
||||
throw new AssertionError("unknown option: " + optID);
|
||||
}
|
||||
} catch (IOException ex) { throw new SocketException(ex.getMessage()); }
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public MyDatagramSocketImpl createDatagramSocketImpl() {
|
||||
return new MyDatagramSocketImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@
|
||||
* @summary Check that setReceiveBufferSize and getReceiveBufferSize work as expected
|
||||
* @run testng SetGetReceiveBufferSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SetGetReceiveBufferSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl SetGetReceiveBufferSize
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,8 +29,6 @@
|
||||
* @summary Check that setSendBufferSize and getSendBufferSize work as expected
|
||||
* @run testng SetGetSendBufferSize
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SetGetSendBufferSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl SetGetSendBufferSize
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl -Djava.net.preferIPv4Stack=true SetGetSendBufferSize
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
* @bug 6505016
|
||||
* @summary Socket spec should clarify what getInetAddress/getPort/etc return after the Socket is closed
|
||||
* @run main TestAfterClose
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl TestAfterClose
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@
|
||||
* java.base/sun.net java.base/sun.nio.ch:+open
|
||||
* @run main/othervm UnreferencedDatagramSockets
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true UnreferencedDatagramSockets
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl UnreferencedDatagramSockets
|
||||
* @summary Check that unreferenced datagram sockets are closed
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
* @bug 6427403
|
||||
* @summary java.net.MulticastSocket.joinGroup() reports 'socket closed'
|
||||
* @run main B6427403
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl B6427403
|
||||
*/
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@
|
||||
* @summary Test that MutlicastSocket.joinGroup is working for
|
||||
* various multicast and non-multicast addresses.
|
||||
* @run main MulticastAddresses
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl MulticastAddresses
|
||||
*/
|
||||
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,6 @@
|
||||
* @run main/othervm NoSetNetworkInterface
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true NoSetNetworkInterface
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true NoSetNetworkInterface
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl NoSetNetworkInterface
|
||||
* @summary Check that methods that are used to set and get the NetworkInterface
|
||||
* for a MulticastSocket work as expected. This test also checks that getOption
|
||||
* returns null correctly when a NetworkInterface has not been set
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
* @library /test/lib
|
||||
* @summary Test for interference when two sockets are bound to the same
|
||||
* port but joined to different multicast groups
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl Promiscuous
|
||||
* @run main Promiscuous
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true Promiscuous
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,7 +49,6 @@ import static org.testng.Assert.assertThrows;
|
||||
* @summary Check that MulticastSocket throws expected
|
||||
* Exception when sending a DatagramPacket with port 0
|
||||
* @run testng/othervm -Djava.security.manager=allow SendPortZero
|
||||
* @run testng/othervm -Djava.security.manager=allow -Djdk.net.usePlainDatagramSocketImpl SendPortZero
|
||||
*/
|
||||
|
||||
public class SendPortZero {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,6 @@
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main/othervm SetLoopbackMode
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl SetLoopbackMode
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,8 +32,6 @@
|
||||
* SetLoopbackMode
|
||||
* SetLoopbackModeIPv4
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true SetLoopbackModeIPv4
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true
|
||||
* -Djdk.net.usePlainDatagramSocketImpl SetLoopbackModeIPv4
|
||||
*/
|
||||
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,7 +31,6 @@
|
||||
* @run testng/othervm SetLoopbackOption
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true SetLoopbackOption
|
||||
* @run testng/othervm -Djava.net.preferIPv6Addresses=true SetLoopbackOption
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl SetLoopbackOption
|
||||
*/
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
* @bug 4742177 8241786
|
||||
* @library /test/lib
|
||||
* @run main/othervm SetOutgoingIf
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl SetOutgoingIf
|
||||
* @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
|
||||
*/
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
* @bug 4189640
|
||||
* @summary Make setTTL/getTTL works
|
||||
* @run main SetTTLAndGetTTL
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl SetTTLAndGetTTL
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
* @bug 4148757
|
||||
* @summary Make sure TTL can be set to 0
|
||||
* @run main SetTTLTo0
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl SetTTLTo0
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@
|
||||
* @modules java.management java.base/java.io:+open java.base/java.net:+open
|
||||
* java.base/sun.net java.base/sun.nio.ch:+open
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true UnreferencedMulticastSockets
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl UnreferencedMulticastSockets
|
||||
* @run main/othervm UnreferencedMulticastSockets
|
||||
* @summary Check that unreferenced multicast sockets are closed
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,7 @@
|
||||
* @test
|
||||
* @author Gary Ellison
|
||||
* @bug 4106600
|
||||
* @summary java.net.PlainSocketImpl backlog value bug avoidance
|
||||
* @summary java.net.SocketImpl backlog value bug avoidance
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8024952
|
||||
* @summary ClassCastException in PlainSocketImpl.accept() when using custom socketImpl
|
||||
* @summary ClassCastException in SocketImpl.accept() when using custom socketImpl
|
||||
* @run main/othervm CustomSocketImplFactory
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,7 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 4165948
|
||||
* @summary java.net.PlainSocketImpl {set,get}Option throws SocketException
|
||||
* @summary java.net.SocketImpl {set,get}Option throws SocketException
|
||||
* when socket is closed.
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,7 +41,6 @@
|
||||
* jdk.test.lib.process.*
|
||||
* AcceptCauseFileDescriptorLeak
|
||||
* @run main/othervm AcceptCauseFileDescriptorLeak root
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl AcceptCauseFileDescriptorLeak root
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@
|
||||
* @modules java.management java.base/java.io:+open java.base/java.net:+open
|
||||
* @run main/othervm UnreferencedSockets
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true UnreferencedSockets
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl UnreferencedSockets
|
||||
* @summary Check that unreferenced sockets are closed
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,6 @@
|
||||
* SocketAddress
|
||||
* @run main AddressTest
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true AddressTest
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl AddressTest
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,7 +24,6 @@
|
||||
/**
|
||||
* @test
|
||||
* @run testng ConnectionReset
|
||||
* @run testng/othervm -Djdk.net.usePlainSocketImpl ConnectionReset
|
||||
* @summary Test behavior of read and available when a connection is reset
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,11 +24,9 @@
|
||||
/**
|
||||
* @test
|
||||
* @bug 8237858
|
||||
* @summary PlainSocketImpl.socketAccept() handles EINTR incorrectly
|
||||
* @summary SocketImpl.socketAccept() handles EINTR incorrectly
|
||||
* @requires (os.family != "windows")
|
||||
* @compile NativeThread.java
|
||||
* @run main/othervm/native -Djdk.net.usePlainSocketImpl=true SocketAcceptInterruptTest 0
|
||||
* @run main/othervm/native -Djdk.net.usePlainSocketImpl=true SocketAcceptInterruptTest 5000
|
||||
* @run main/othervm/native SocketAcceptInterruptTest 0
|
||||
* @run main/othervm/native SocketAcceptInterruptTest 5000
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,12 +24,10 @@
|
||||
/**
|
||||
* @test
|
||||
* @bug 8237858
|
||||
* @summary PlainSocketImpl.socketAccept() handles EINTR incorrectly
|
||||
* @summary SocketImpl.socketAccept() handles EINTR incorrectly
|
||||
* @requires (os.family != "windows")
|
||||
* @compile NativeThread.java
|
||||
* @run main/othervm/native -Djdk.net.usePlainSocketImpl=true SocketReadInterruptTest 2000 3000
|
||||
* @run main/othervm/native SocketReadInterruptTest 2000 3000
|
||||
* @run main/othervm/native -Djdk.net.usePlainSocketImpl=true SocketReadInterruptTest 2000 0
|
||||
* @run main/othervm/native SocketReadInterruptTest 2000 0
|
||||
*/
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,7 +35,6 @@ import static java.util.concurrent.CompletableFuture.*;
|
||||
* cause any thread blocked on the socket to throw a SocketException.
|
||||
* @run main AsyncClose
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true AsyncClose
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl AsyncClose
|
||||
*/
|
||||
|
||||
public class AsyncClose {
|
||||
|
||||
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8221481
|
||||
* @modules java.base/java.net:+open java.base/sun.nio.ch:+open
|
||||
* @run testng CompareSocketOptions
|
||||
* @summary Compare the set of socket options supported by the old and new SocketImpls
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketImpl;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class CompareSocketOptions {
|
||||
|
||||
/**
|
||||
* Test that the old and new platform SocketImpl support the same set of
|
||||
* client socket options.
|
||||
*/
|
||||
public void testClientSocketSupportedOptions() throws IOException {
|
||||
Socket s1 = new Socket(createOldSocketImpl(false)) { };
|
||||
Socket s2 = new Socket(createNewSocketImpl(false)) { };
|
||||
assertEquals(s1.supportedOptions(), s2.supportedOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the old and new platform SocketImpl support the same set of
|
||||
* server socket options.
|
||||
*/
|
||||
public void testServerSocketSupportedOptions() throws IOException {
|
||||
ServerSocket ss1 = new ServerSocket(createOldSocketImpl(true)) { };
|
||||
ServerSocket ss2 = new ServerSocket(createNewSocketImpl(true)) { };
|
||||
assertEquals(ss1.supportedOptions(), ss2.supportedOptions());
|
||||
}
|
||||
|
||||
private static SocketImpl createOldSocketImpl(boolean server) {
|
||||
return newPlatformSocketImpl("java.net.PlainSocketImpl", server);
|
||||
}
|
||||
|
||||
private static SocketImpl createNewSocketImpl(boolean server) {
|
||||
return newPlatformSocketImpl("sun.nio.ch.NioSocketImpl", server);
|
||||
}
|
||||
|
||||
private static SocketImpl newPlatformSocketImpl(String name, boolean server) {
|
||||
try {
|
||||
var ctor = Class.forName(name).getDeclaredConstructor(boolean.class);
|
||||
ctor.setAccessible(true);
|
||||
return (SocketImpl) ctor.newInstance(server);
|
||||
} catch (Exception e) {
|
||||
fail("Should not get here", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,8 +26,6 @@
|
||||
* @bug 8224477
|
||||
* @summary Ensures that IOException is thrown after the socket is closed
|
||||
* @run testng AfterClose
|
||||
* @run testng/othervm -Djdk.net.usePlainSocketImpl AfterClose
|
||||
* @run testng/othervm -Djdk.net.usePlainDatagramSocketImpl AfterClose
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,6 @@
|
||||
* @bug 8224477
|
||||
* @summary Basic test for NPE, UOE, and IAE for get/setOption
|
||||
* @run testng NullsAndBadValues
|
||||
* @run testng/othervm -Djdk.net.usePlainSocketImpl NullsAndBadValues
|
||||
* @run testng/othervm -Dsun.net.useExclusiveBind=false NullsAndBadValues
|
||||
*/
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,8 +27,6 @@
|
||||
* @library /test/lib
|
||||
* @requires !vm.graal.enabled
|
||||
* @run main/othervm -Xcheck:jni OptionsTest
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl OptionsTest
|
||||
* @run main/othervm -Djdk.net.usePlainDatagramSocketImpl OptionsTest
|
||||
* @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
|
||||
* @run main/othervm --limit-modules=java.base OptionsTest
|
||||
* @run main/othervm/policy=options.policy OptionsTest
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,7 +43,6 @@ import static java.net.StandardSocketOptions.*;
|
||||
* @bug 8235141
|
||||
* @summary verifies that our implementation supports the set
|
||||
* of SocketOptions that are required by the API documentation.
|
||||
* @run testng/othervm -Djdk.net.usePlainSocketImpl RequiredOptions
|
||||
* @run testng/othervm RequiredOptions
|
||||
*/
|
||||
public class RequiredOptions {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,7 +32,6 @@
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main TcpTest -d
|
||||
* @run main/othervm -Djdk.net.usePlainSocketImpl TcpTest -d
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user