From 1f6b95737797de22228d79d24fb4e15027617626 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 26 Nov 2015 16:02:58 +0100 Subject: [PATCH] Ensure we retain the original hostname when connect to a remote peer when using epoll transport. Motivation: We should retain the original hostname when connect to a remote peer so the user can still query the origin hostname if getHostString() is used. Modifications: Compute a InetSocketAddress from the original remote address and the one returned by the Os. Result: Same behavior when using epoll transport and nio transport. --- .../epoll/AbstractEpollStreamChannel.java | 2 +- .../channel/epoll/EpollSocketChannel.java | 59 ++++++++++++++----- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java index 2530ad0aa1..612afce5ef 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java @@ -755,7 +755,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel { /** * Finish the connect */ - private boolean doFinishConnect() throws Exception { + boolean doFinishConnect() throws Exception { if (fd().finishConnect()) { clearFlag(Native.EPOLLOUT); return true; diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java index ec14d4aec7..aaee497e3f 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollSocketChannel.java @@ -25,10 +25,12 @@ import io.netty.channel.unix.FileDescriptor; import io.netty.channel.unix.Socket; import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.internal.OneTimeTask; +import io.netty.util.internal.PlatformDependent; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.net.UnknownHostException; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -46,6 +48,8 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme private volatile InetSocketAddress local; private volatile InetSocketAddress remote; + private InetSocketAddress requestedRemote; + private volatile Collection tcpMd5SigAddresses = Collections.emptyList(); EpollSocketChannel(Channel parent, Socket fd, InetSocketAddress remote) { @@ -124,14 +128,6 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme @Override protected SocketAddress remoteAddress0() { - if (remote == null) { - // Remote address not know, try to get it now. - InetSocketAddress address = fd().remoteAddress(); - if (address != null) { - remote = address; - } - return address; - } return remote; } @@ -198,22 +194,45 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme return new EpollSocketChannelUnsafe(); } + private static InetSocketAddress computeRemoteAddr(InetSocketAddress remoteAddr, InetSocketAddress osRemoteAddr) { + if (osRemoteAddr != null) { + if (PlatformDependent.javaVersion() >= 7) { + try { + // Only try to construct a new InetSocketAddress if we using java >= 7 as getHostString() does not + // exists in earlier releases and so the retrieval of the hostname could block the EventLoop if a + // reverse lookup would be needed. + return new InetSocketAddress(InetAddress.getByAddress(remoteAddr.getHostString(), + osRemoteAddr.getAddress().getAddress()), + osRemoteAddr.getPort()); + } catch (UnknownHostException ignore) { + // Should never happen but fallback to osRemoteAddr anyway. + } + } + return osRemoteAddr; + } + return remoteAddr; + } + @Override protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { if (localAddress != null) { checkResolvable((InetSocketAddress) localAddress); } - checkResolvable((InetSocketAddress) remoteAddress); - boolean connected = super.doConnect(remoteAddress, localAddress); - if (connected) { - remote = (InetSocketAddress) remoteAddress; - return true; - } // We always need to set the localAddress even if not connected yet // // See https://github.com/netty/netty/issues/3463 local = fd().localAddress(); - return connected; + + InetSocketAddress remoteAddr = (InetSocketAddress) remoteAddress; + checkResolvable(remoteAddr); + if (super.doConnect(remoteAddress, localAddress)) { + remote = computeRemoteAddr(remoteAddr, fd().remoteAddress()); + return true; + } + + // Store for later usage in doFinishConnect() + requestedRemote = remoteAddr; + return false; } private final class EpollSocketChannelUnsafe extends EpollStreamUnsafe { @@ -232,6 +251,16 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme } return null; } + + @Override + boolean doFinishConnect() throws Exception { + if (super.doFinishConnect()) { + remote = computeRemoteAddr(requestedRemote, fd().remoteAddress()); + requestedRemote = null; + return true; + } + return false; + } } void setTcpMd5Sig(Map keys) {