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.
This commit is contained in:
Norman Maurer 2015-11-26 16:02:58 +01:00
parent f4386fb8e9
commit 1f6b957377
2 changed files with 45 additions and 16 deletions

View File

@ -755,7 +755,7 @@ public abstract class AbstractEpollStreamChannel extends AbstractEpollChannel {
/** /**
* Finish the connect * Finish the connect
*/ */
private boolean doFinishConnect() throws Exception { boolean doFinishConnect() throws Exception {
if (fd().finishConnect()) { if (fd().finishConnect()) {
clearFlag(Native.EPOLLOUT); clearFlag(Native.EPOLLOUT);
return true; return true;

View File

@ -25,10 +25,12 @@ import io.netty.channel.unix.FileDescriptor;
import io.netty.channel.unix.Socket; import io.netty.channel.unix.Socket;
import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.GlobalEventExecutor;
import io.netty.util.internal.OneTimeTask; import io.netty.util.internal.OneTimeTask;
import io.netty.util.internal.PlatformDependent;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
@ -46,6 +48,8 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
private volatile InetSocketAddress local; private volatile InetSocketAddress local;
private volatile InetSocketAddress remote; private volatile InetSocketAddress remote;
private InetSocketAddress requestedRemote;
private volatile Collection<InetAddress> tcpMd5SigAddresses = Collections.emptyList(); private volatile Collection<InetAddress> tcpMd5SigAddresses = Collections.emptyList();
EpollSocketChannel(Channel parent, Socket fd, InetSocketAddress remote) { EpollSocketChannel(Channel parent, Socket fd, InetSocketAddress remote) {
@ -124,14 +128,6 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
@Override @Override
protected SocketAddress remoteAddress0() { 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; return remote;
} }
@ -198,22 +194,45 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
return new EpollSocketChannelUnsafe(); 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 @Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception { protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
if (localAddress != null) { if (localAddress != null) {
checkResolvable((InetSocketAddress) localAddress); 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 // We always need to set the localAddress even if not connected yet
// //
// See https://github.com/netty/netty/issues/3463 // See https://github.com/netty/netty/issues/3463
local = fd().localAddress(); 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 { private final class EpollSocketChannelUnsafe extends EpollStreamUnsafe {
@ -232,6 +251,16 @@ public final class EpollSocketChannel extends AbstractEpollStreamChannel impleme
} }
return null; return null;
} }
@Override
boolean doFinishConnect() throws Exception {
if (super.doFinishConnect()) {
remote = computeRemoteAddr(requestedRemote, fd().remoteAddress());
requestedRemote = null;
return true;
}
return false;
}
} }
void setTcpMd5Sig(Map<InetAddress, byte[]> keys) { void setTcpMd5Sig(Map<InetAddress, byte[]> keys) {