mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8260428: Drop support for pre JDK 1.4 DatagramSocketImpl implementations
Reviewed-by: alanb, dfuchs, vtewari
This commit is contained in:
parent
e265f83858
commit
977154400b
3 changed files with 212 additions and 93 deletions
|
@ -27,6 +27,7 @@ package java.net;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -99,19 +100,30 @@ public abstract class DatagramSocketImpl implements SocketOptions {
|
||||||
* packet has been received for that address, then a subsequent call to
|
* packet has been received for that address, then a subsequent call to
|
||||||
* send or receive may throw a PortUnreachableException.
|
* send or receive may throw a PortUnreachableException.
|
||||||
* Note, there is no guarantee that the exception will be thrown.
|
* Note, there is no guarantee that the exception will be thrown.
|
||||||
|
*
|
||||||
|
* @implSpec The default implementation of this method throws {@code SocketException}.
|
||||||
|
*
|
||||||
* @param address the remote InetAddress to connect to
|
* @param address the remote InetAddress to connect to
|
||||||
* @param port the remote port number
|
* @param port the remote port number
|
||||||
* @throws SocketException may be thrown if the socket cannot be
|
* @throws SocketException may be thrown if the socket cannot be
|
||||||
* connected to the remote destination
|
* connected to the remote destination
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
protected void connect(InetAddress address, int port) throws SocketException {}
|
protected void connect(InetAddress address, int port) throws SocketException {
|
||||||
|
throw new SocketException("connect not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects a datagram socket from its remote destination.
|
* Disconnects a datagram socket from its remote destination.
|
||||||
|
*
|
||||||
|
* @implSpec The default implementation of this method throws {@code UncheckedIOException}.
|
||||||
|
*
|
||||||
|
* @throws UncheckedIOException if disconnect fails or no implementation is provided
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
protected void disconnect() {}
|
protected void disconnect() {
|
||||||
|
throw new UncheckedIOException(new SocketException("disconnect not implemented"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peek at the packet to see who it is from. Updates the specified {@code InetAddress}
|
* Peek at the packet to see who it is from. Updates the specified {@code InetAddress}
|
||||||
|
|
|
@ -56,11 +56,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
*/
|
*/
|
||||||
private final DatagramSocketImpl impl;
|
private final DatagramSocketImpl impl;
|
||||||
|
|
||||||
/**
|
|
||||||
* Are we using an older DatagramSocketImpl?
|
|
||||||
*/
|
|
||||||
private final boolean oldImpl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set when a socket is ST_CONNECTED until we are certain
|
* Set when a socket is ST_CONNECTED until we are certain
|
||||||
* that any packets which might have been received prior
|
* that any packets which might have been received prior
|
||||||
|
@ -76,11 +71,9 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
* Connection state:
|
* Connection state:
|
||||||
* ST_NOT_CONNECTED = socket not connected
|
* ST_NOT_CONNECTED = socket not connected
|
||||||
* ST_CONNECTED = socket connected
|
* ST_CONNECTED = socket connected
|
||||||
* ST_CONNECTED_NO_IMPL = socket connected but not at impl level
|
|
||||||
*/
|
*/
|
||||||
static final int ST_NOT_CONNECTED = 0;
|
static final int ST_NOT_CONNECTED = 0;
|
||||||
static final int ST_CONNECTED = 1;
|
static final int ST_CONNECTED = 1;
|
||||||
static final int ST_CONNECTED_NO_IMPL = 2;
|
|
||||||
|
|
||||||
int connectState = ST_NOT_CONNECTED;
|
int connectState = ST_NOT_CONNECTED;
|
||||||
|
|
||||||
|
@ -97,7 +90,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
NetMulticastSocket(DatagramSocketImpl impl) {
|
NetMulticastSocket(DatagramSocketImpl impl) {
|
||||||
super((MulticastSocket) null);
|
super((MulticastSocket) null);
|
||||||
this.impl = Objects.requireNonNull(impl);
|
this.impl = Objects.requireNonNull(impl);
|
||||||
this.oldImpl = checkOldImpl(impl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -135,11 +127,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
if (!isBound())
|
if (!isBound())
|
||||||
bind(new InetSocketAddress(0));
|
bind(new InetSocketAddress(0));
|
||||||
|
|
||||||
// old impls do not support connect/disconnect
|
|
||||||
if (oldImpl) {
|
|
||||||
connectState = ST_CONNECTED_NO_IMPL;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
getImpl().connect(address, port);
|
getImpl().connect(address, port);
|
||||||
|
|
||||||
// socket is now connected by the impl
|
// socket is now connected by the impl
|
||||||
|
@ -153,41 +140,11 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
if (explicitFilter) {
|
if (explicitFilter) {
|
||||||
bytesLeftToFilter = getReceiveBufferSize();
|
bytesLeftToFilter = getReceiveBufferSize();
|
||||||
}
|
}
|
||||||
} catch (SocketException se) {
|
|
||||||
|
|
||||||
// connection will be emulated by DatagramSocket
|
|
||||||
connectState = ST_CONNECTED_NO_IMPL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedAddress = address;
|
connectedAddress = address;
|
||||||
connectedPort = port;
|
connectedPort = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return true if the given DatagramSocketImpl is an "old" impl. An old impl
|
|
||||||
* is one that doesn't implement the abstract methods added in Java SE 1.4.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static boolean checkOldImpl(DatagramSocketImpl impl) {
|
|
||||||
// DatagramSocketImpl.peekData() is a protected method, therefore we need to use
|
|
||||||
// getDeclaredMethod, therefore we need permission to access the member
|
|
||||||
try {
|
|
||||||
AccessController.doPrivileged(
|
|
||||||
new PrivilegedExceptionAction<>() {
|
|
||||||
public Void run() throws NoSuchMethodException {
|
|
||||||
Class<?>[] cl = new Class<?>[1];
|
|
||||||
cl[0] = DatagramPacket.class;
|
|
||||||
impl.getClass().getDeclaredMethod("peekData", cl);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
} catch (java.security.PrivilegedActionException e) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@code DatagramSocketImpl} attached to this socket,
|
* Return the {@code DatagramSocketImpl} attached to this socket,
|
||||||
* creating the socket if not already created.
|
* creating the socket if not already created.
|
||||||
|
@ -382,19 +339,11 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
if (security != null) {
|
if (security != null) {
|
||||||
while (true) {
|
while (true) {
|
||||||
String peekAd = null;
|
|
||||||
int peekPort = 0;
|
int peekPort = 0;
|
||||||
// peek at the packet to see who it is from.
|
// peek at the packet to see who it is from.
|
||||||
if (!oldImpl) {
|
|
||||||
// We can use the new peekData() API
|
|
||||||
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
|
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
|
||||||
peekPort = getImpl().peekData(peekPacket);
|
peekPort = getImpl().peekData(peekPacket);
|
||||||
peekAd = peekPacket.getAddress().getHostAddress();
|
String peekAd = peekPacket.getAddress().getHostAddress();
|
||||||
} else {
|
|
||||||
InetAddress adr = new InetAddress();
|
|
||||||
peekPort = getImpl().peek(adr);
|
|
||||||
peekAd = adr.getHostAddress();
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
security.checkAccept(peekAd, peekPort);
|
security.checkAccept(peekAd, peekPort);
|
||||||
// security check succeeded - so now break
|
// security check succeeded - so now break
|
||||||
|
@ -418,7 +367,7 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DatagramPacket tmp = null;
|
DatagramPacket tmp = null;
|
||||||
if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
|
if (explicitFilter) {
|
||||||
// We have to do the filtering the old fashioned way since
|
// We have to do the filtering the old fashioned way since
|
||||||
// the native impl doesn't support connect or the connect
|
// the native impl doesn't support connect or the connect
|
||||||
// via the impl failed, or .. "explicitFilter" may be set when
|
// via the impl failed, or .. "explicitFilter" may be set when
|
||||||
|
@ -426,21 +375,11 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
// when packets from other sources might be queued on socket.
|
// when packets from other sources might be queued on socket.
|
||||||
boolean stop = false;
|
boolean stop = false;
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
InetAddress peekAddress = null;
|
|
||||||
int peekPort = -1;
|
|
||||||
// peek at the packet to see who it is from.
|
// peek at the packet to see who it is from.
|
||||||
if (!oldImpl) {
|
|
||||||
// We can use the new peekData() API
|
|
||||||
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
|
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
|
||||||
peekPort = getImpl().peekData(peekPacket);
|
int peekPort = getImpl().peekData(peekPacket);
|
||||||
peekAddress = peekPacket.getAddress();
|
InetAddress peekAddress = peekPacket.getAddress();
|
||||||
} else {
|
if ((!connectedAddress.equals(peekAddress)) || (connectedPort != peekPort)) {
|
||||||
// this api only works for IPv4
|
|
||||||
peekAddress = new InetAddress();
|
|
||||||
peekPort = getImpl().peek(peekAddress);
|
|
||||||
}
|
|
||||||
if ((!connectedAddress.equals(peekAddress)) ||
|
|
||||||
(connectedPort != peekPort)) {
|
|
||||||
// throw the packet away and silently continue
|
// throw the packet away and silently continue
|
||||||
tmp = new DatagramPacket(
|
tmp = new DatagramPacket(
|
||||||
new byte[1024], 1024);
|
new byte[1024], 1024);
|
||||||
|
@ -578,10 +517,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
public synchronized void setReuseAddress(boolean on) throws SocketException {
|
public synchronized void setReuseAddress(boolean on) throws SocketException {
|
||||||
if (isClosed())
|
if (isClosed())
|
||||||
throw new SocketException("Socket is closed");
|
throw new SocketException("Socket is closed");
|
||||||
// Integer instead of Boolean for compatibility with older DatagramSocketImpl
|
|
||||||
if (oldImpl)
|
|
||||||
getImpl().setOption(SocketOptions.SO_REUSEADDR, on ? -1 : 0);
|
|
||||||
else
|
|
||||||
getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
|
getImpl().setOption(SocketOptions.SO_REUSEADDR, Boolean.valueOf(on));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,9 +744,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
if (!(mcastaddr instanceof InetSocketAddress addr))
|
if (!(mcastaddr instanceof InetSocketAddress addr))
|
||||||
throw new IllegalArgumentException("Unsupported address type");
|
throw new IllegalArgumentException("Unsupported address type");
|
||||||
|
|
||||||
if (oldImpl)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
|
|
||||||
checkAddress(addr.getAddress(), "joinGroup");
|
checkAddress(addr.getAddress(), "joinGroup");
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
|
@ -835,9 +767,6 @@ final class NetMulticastSocket extends MulticastSocket {
|
||||||
if (!(mcastaddr instanceof InetSocketAddress addr))
|
if (!(mcastaddr instanceof InetSocketAddress addr))
|
||||||
throw new IllegalArgumentException("Unsupported address type");
|
throw new IllegalArgumentException("Unsupported address type");
|
||||||
|
|
||||||
if (oldImpl)
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
|
|
||||||
checkAddress(addr.getAddress(), "leaveGroup");
|
checkAddress(addr.getAddress(), "leaveGroup");
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
SecurityManager security = System.getSecurityManager();
|
SecurityManager security = System.getSecurityManager();
|
||||||
|
|
178
test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java
Normal file
178
test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 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.
|
||||||
|
*
|
||||||
|
* 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 8260428
|
||||||
|
* @summary Drop support for pre JDK 1.4 DatagramSocketImpl implementations
|
||||||
|
* @run testng/othervm OldDatagramSocketImplTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class OldDatagramSocketImplTest {
|
||||||
|
InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOldImplConnect() {
|
||||||
|
try (var ds = new DatagramSocket(new OldDatagramSocketImpl()) {}) {
|
||||||
|
ds.connect(new InetSocketAddress(LOOPBACK, 6667));
|
||||||
|
throw new RuntimeException("ERROR: test failed");
|
||||||
|
} catch (SocketException ex) {
|
||||||
|
assertEquals(ex.getMessage(), "connect not implemented");
|
||||||
|
System.out.println("PASSED: default implementation of connect has thrown as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOldImplConnectTwoArgs() {
|
||||||
|
try (var ds = new DatagramSocket(new OldDatagramSocketImpl()) {}) {
|
||||||
|
ds.connect(LOOPBACK, 6667);
|
||||||
|
throw new RuntimeException("ERROR: test failed");
|
||||||
|
} catch (UncheckedIOException ex) {
|
||||||
|
assertEquals(ex.getMessage(), "connect failed");
|
||||||
|
System.out.println("PASSED: default implementation of connect has thrown as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOldImplDisconnect() {
|
||||||
|
try (var ds = new DatagramSocket(new OldDatagramSocketImplWithValidConnect()) { }){
|
||||||
|
ds.connect(LOOPBACK, 6667);
|
||||||
|
ds.disconnect();
|
||||||
|
throw new RuntimeException("ERROR: test failed");
|
||||||
|
} catch (UncheckedIOException ex) {
|
||||||
|
var innerException = ex.getCause();
|
||||||
|
assertEquals(innerException.getClass(), SocketException.class);
|
||||||
|
assertEquals(innerException.getMessage(), "disconnect not implemented");
|
||||||
|
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOldImplPublic() {
|
||||||
|
try (var ds = new PublicOldDatagramSocketImpl()) {
|
||||||
|
ds.connect(LOOPBACK, 0);
|
||||||
|
throw new RuntimeException("ERROR: test failed");
|
||||||
|
} catch (SocketException ex) {
|
||||||
|
assertEquals(ex.getMessage(), "connect not implemented");
|
||||||
|
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testOldImplPublicDisconnect() {
|
||||||
|
try (var ds = new PublicOldDatagramSocketImplWithValidConnect()) {
|
||||||
|
ds.disconnect();
|
||||||
|
throw new RuntimeException("ERROR: test failed");
|
||||||
|
} catch (UncheckedIOException ex) {
|
||||||
|
var innerException = ex.getCause();
|
||||||
|
assertEquals(innerException.getClass(), SocketException.class);
|
||||||
|
assertEquals(innerException.getMessage(), "disconnect not implemented");
|
||||||
|
System.out.println("PASSED: default implementation of disconnect has thrown as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OldDatagramSocketImpl extends DatagramSocketImpl implements AutoCloseable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void create() throws SocketException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void bind(int lport, InetAddress laddr) throws SocketException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void send(DatagramPacket p) throws IOException { }
|
||||||
|
|
||||||
|
@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 { }
|
||||||
|
|
||||||
|
@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
|
||||||
|
public void close() { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOption(int optID, Object value) throws SocketException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getOption(int optID) throws SocketException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OldDatagramSocketImplWithValidConnect extends OldDatagramSocketImpl implements AutoCloseable {
|
||||||
|
@Override
|
||||||
|
protected void connect(InetAddress address, int port) throws SocketException { }
|
||||||
|
}
|
||||||
|
// Overriding connect() to make it public so that it can be called
|
||||||
|
// directly from the test code
|
||||||
|
private class PublicOldDatagramSocketImpl extends OldDatagramSocketImpl {
|
||||||
|
public void connect(InetAddress addr, int port) throws SocketException { super.connect(addr, port); }
|
||||||
|
}
|
||||||
|
// Overriding disconnect() to make it public so that it can be called
|
||||||
|
// directly from the test code
|
||||||
|
private class PublicOldDatagramSocketImplWithValidConnect extends OldDatagramSocketImplWithValidConnect {
|
||||||
|
public void disconnect() { super.disconnect(); }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue