From 0c2efdc25056a20e0d3eaadb14057f3087971101 Mon Sep 17 00:00:00 2001 From: mazhen Date: Sat, 15 Jul 2023 18:19:49 +0800 Subject: [PATCH] Enhance socket connection with configurable timeout --- .../sun/corba/ee/impl/misc/ORBUtility.java | 14 ++- .../ee/impl/transport/ConnectionImpl.java | 7 +- .../transport/DefaultSocketFactoryImpl.java | 23 +---- .../ee/spi/transport/ORBSocketFactory.java | 33 ++++++- .../DefaultSocketFactoryImplTest.java | 85 +++++++++++++++++++ .../corba/nortel/NortelSocketFactory.java | 11 ++- 6 files changed, 141 insertions(+), 32 deletions(-) create mode 100644 orbmain/src/test/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImplTest.java diff --git a/orbmain/src/main/java/com/sun/corba/ee/impl/misc/ORBUtility.java b/orbmain/src/main/java/com/sun/corba/ee/impl/misc/ORBUtility.java index 879d1aab2..6eb2900b7 100644 --- a/orbmain/src/main/java/com/sun/corba/ee/impl/misc/ORBUtility.java +++ b/orbmain/src/main/java/com/sun/corba/ee/impl/misc/ORBUtility.java @@ -20,6 +20,7 @@ package com.sun.corba.ee.impl.misc; +import java.net.Socket; import java.security.AccessController; import java.security.PermissionCollection; import java.security.Policy; @@ -72,24 +73,33 @@ import com.sun.corba.ee.impl.ior.iiop.JavaSerializationComponent; import com.sun.corba.ee.impl.javax.rmi.CORBA.Util; +import static com.sun.corba.ee.spi.misc.ORBConstants.TRANSPORT_TCP_CONNECT_MAX_TIME_TO_WAIT; + /** * Handy class full of static functions that don't belong in util.Utility for pure ORB reasons. */ public final class ORBUtility { + + public static SocketChannel openSocketChannel(SocketAddress sa) throws IOException { + return openSocketChannel(sa, TRANSPORT_TCP_CONNECT_MAX_TIME_TO_WAIT); + } + /** Utility method for working around leak in SocketChannel.open( SocketAddress ) * method. * @param sa address to connect to + * @param timeout – the timeout value to be used in milliseconds. * @return The opened channel * @throws java.io.IOException If an I/O error occurs * @see SocketChannel#connect(java.net.SocketAddress) */ - public static SocketChannel openSocketChannel( SocketAddress sa ) + public static SocketChannel openSocketChannel(SocketAddress sa, int timeout) throws IOException { SocketChannel sc = SocketChannel.open() ; try { - sc.connect( sa ) ; + Socket socket = sc.socket(); + socket.connect(sa, timeout); return sc ; } catch (RuntimeException | IOException exc ) { try { diff --git a/orbmain/src/main/java/com/sun/corba/ee/impl/transport/ConnectionImpl.java b/orbmain/src/main/java/com/sun/corba/ee/impl/transport/ConnectionImpl.java index 8789623b2..9108bcd90 100644 --- a/orbmain/src/main/java/com/sun/corba/ee/impl/transport/ConnectionImpl.java +++ b/orbmain/src/main/java/com/sun/corba/ee/impl/transport/ConnectionImpl.java @@ -225,8 +225,13 @@ private ConnectionImpl(ORB orb, this.contactInfo = contactInfo; try { + TcpTimeouts tcpConnectTimeouts = orb.getORBData().getTransportTcpConnectTimeouts(); defineSocket(useSelectThreadToWait, - orb.getORBData().getSocketFactory().createSocket(socketType, new InetSocketAddress(hostname, port))); + orb.getORBData().getSocketFactory().createSocket( + orb.getORBData().connectionSocketType(), + new InetSocketAddress(hostname, port), + tcpConnectTimeouts.get_max_time_to_wait()) + ); } catch (Throwable t) { throw wrapper.connectFailure(t, socketType, hostname, Integer.toString(port)); diff --git a/orbmain/src/main/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImpl.java b/orbmain/src/main/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImpl.java index a80f292d7..36304d605 100644 --- a/orbmain/src/main/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImpl.java +++ b/orbmain/src/main/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImpl.java @@ -38,7 +38,7 @@ public class DefaultSocketFactoryImpl implements ORBSocketFactory { - private ORB orb; + protected ORB orb; public void setORB(ORB orb) { @@ -62,27 +62,6 @@ public ServerSocket createServerSocket(String type, return serverSocket; } - public Socket createSocket(String type, - InetSocketAddress inetSocketAddress) - throws IOException - { - SocketChannel socketChannel = null; - Socket socket = null; - - if (orb.getORBData().connectionSocketType().equals(ORBConstants.SOCKETCHANNEL)) { - socketChannel = ORBUtility.openSocketChannel(inetSocketAddress); - socket = socketChannel.socket(); - } else { - socket = new Socket(inetSocketAddress.getHostName(), - inetSocketAddress.getPort()); - } - - // Disable Nagle's algorithm (i.e., always send immediately). - socket.setTcpNoDelay(true); - - return socket; - } - public void setAcceptedSocketOptions(Acceptor acceptor, ServerSocket serverSocket, Socket socket) diff --git a/orbmain/src/main/java/com/sun/corba/ee/spi/transport/ORBSocketFactory.java b/orbmain/src/main/java/com/sun/corba/ee/spi/transport/ORBSocketFactory.java index 3bc03e9e8..6fce3483a 100644 --- a/orbmain/src/main/java/com/sun/corba/ee/spi/transport/ORBSocketFactory.java +++ b/orbmain/src/main/java/com/sun/corba/ee/spi/transport/ORBSocketFactory.java @@ -24,9 +24,14 @@ import java.net.Socket; import java.net.SocketException; import java.net.ServerSocket; +import java.nio.channels.SocketChannel; +import com.sun.corba.ee.impl.misc.ORBUtility; +import com.sun.corba.ee.spi.misc.ORBConstants; import com.sun.corba.ee.spi.orb.ORB; +import static com.sun.corba.ee.spi.misc.ORBConstants.TRANSPORT_TCP_CONNECT_MAX_TIME_TO_WAIT; + /** * @author Harold Carr */ @@ -38,9 +43,31 @@ public ServerSocket createServerSocket(String type, InetSocketAddress inetSocketAddress) throws IOException; - public Socket createSocket(String type, - InetSocketAddress inetSocketAddress) - throws IOException; + public default Socket createSocket(String type, + InetSocketAddress inetSocketAddress) throws IOException { + return createSocket(type, inetSocketAddress, TRANSPORT_TCP_CONNECT_MAX_TIME_TO_WAIT); + } + + public default Socket createSocket(String type, + InetSocketAddress inetSocketAddress, + int timeout) + throws IOException { + SocketChannel socketChannel = null; + Socket socket = null; + + if (type.equals(ORBConstants.SOCKETCHANNEL)) { + socketChannel = ORBUtility.openSocketChannel(inetSocketAddress, timeout); + socket = socketChannel.socket(); + } else { + socket = new Socket(); + socket.connect(inetSocketAddress, timeout); + } + + // Disable Nagle's algorithm (i.e., always send immediately). + socket.setTcpNoDelay(true); + + return socket; + } public void setAcceptedSocketOptions(Acceptor acceptor, ServerSocket serverSocket, diff --git a/orbmain/src/test/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImplTest.java b/orbmain/src/test/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImplTest.java new file mode 100644 index 000000000..d2d3a94fe --- /dev/null +++ b/orbmain/src/test/java/com/sun/corba/ee/impl/transport/DefaultSocketFactoryImplTest.java @@ -0,0 +1,85 @@ +package com.sun.corba.ee.impl.transport; + +import com.sun.corba.ee.spi.misc.ORBConstants; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.util.UUID; + +import static org.junit.Assert.*; + +public class DefaultSocketFactoryImplTest { + private static final String TEST_TYPE = ORBConstants.SOCKETCHANNEL; + private static final int TEST_TIMEOUT = 1000; + + @Test + public void testCreateSocketWithSocketChannelType() throws IOException { + DefaultSocketFactoryImpl sf = new DefaultSocketFactoryImpl(); + String testMessage = UUID.randomUUID().toString(); + try (ServerSocket serverSocket = createServerSocket(testMessage)) { + final InetSocketAddress address = new InetSocketAddress("localhost", serverSocket.getLocalPort()); + Socket socket = sf.createSocket(TEST_TYPE, address, TEST_TIMEOUT); + assertNotNull(socket); + assertTrue(socket.getTcpNoDelay()); + validateSocket(socket, testMessage); + } + } + + @Test + public void testCreateSocketWithOtherType() throws IOException { + DefaultSocketFactoryImpl sf = new DefaultSocketFactoryImpl(); + String testMessage = UUID.randomUUID().toString(); + try (ServerSocket serverSocket = createServerSocket(testMessage)) { + final InetSocketAddress address = new InetSocketAddress("localhost", serverSocket.getLocalPort()); + Socket socket = sf.createSocket("otherType", address, TEST_TIMEOUT); + assertNotNull(socket); + assertTrue(socket.getTcpNoDelay()); + validateSocket(socket, testMessage); + } + } + + @Test(expected = SocketTimeoutException.class) + public void testCreateSocketWithTimeoutSocketChannelType() throws IOException { + DefaultSocketFactoryImpl sf = new DefaultSocketFactoryImpl(); + InetSocketAddress unreachableAddress = new InetSocketAddress("10.0.0.0", 8080); + sf.createSocket(TEST_TYPE, unreachableAddress, TEST_TIMEOUT); + } + + @Test(expected = SocketTimeoutException.class) + public void testCreateSocketWithTimeoutOtherType() throws IOException { + DefaultSocketFactoryImpl sf = new DefaultSocketFactoryImpl(); + InetSocketAddress unreachableAddress = new InetSocketAddress("10.0.0.0", 8080); + sf.createSocket("otherType", unreachableAddress, TEST_TIMEOUT); + } + + private ServerSocket createServerSocket(String message) throws IOException { + ServerSocket serverSocket = new ServerSocket(); + serverSocket.bind(null); + + new Thread(() -> { + try { + Socket clientSocket = serverSocket.accept(); + OutputStream out = clientSocket.getOutputStream(); + out.write(message.getBytes()); + out.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + }).start(); + + return serverSocket; + } + + private void validateSocket(Socket socket, String expectedMessage) throws IOException { + InputStream in = socket.getInputStream(); + byte[] buffer = new byte[expectedMessage.length()]; + int read = in.read(buffer); + assertEquals(expectedMessage, new String(buffer, 0, read)); + } +} diff --git a/test/src/share/classes/corba/nortel/NortelSocketFactory.java b/test/src/share/classes/corba/nortel/NortelSocketFactory.java index 88aac71eb..d8d676c28 100644 --- a/test/src/share/classes/corba/nortel/NortelSocketFactory.java +++ b/test/src/share/classes/corba/nortel/NortelSocketFactory.java @@ -20,6 +20,7 @@ package corba.nortel ; import com.sun.corba.ee.impl.transport.DefaultSocketFactoryImpl; +import com.sun.corba.ee.spi.transport.TcpTimeouts; import java.io.IOException; @@ -62,13 +63,15 @@ public Socket createSocket(String type, InetSocketAddress in) throws IOException } Socket socket = null; + TcpTimeouts tcpConnectTimeouts = orb.getORBData().getTransportTcpConnectTimeouts(); if (useNio) { - socket = super.createSocket(type, in); + socket = super.createSocket(orb.getORBData().connectionSocketType(), in, tcpConnectTimeouts.get_max_time_to_wait()); } else { - socket = new Socket(in.getHostName(), in.getPort()); - socket.setTcpNoDelay(true); + socket = new Socket(); + socket.connect(in, tcpConnectTimeouts.get_max_time_to_wait()); } - + + socket.setTcpNoDelay(true); savedSocket = socket; return socket; }