Correctly detect InternetProtocolFamily when EpollDatagramChannel is created with existing FileDescriptor (#9185)

Motivation:

When EpollDatagramChannel is created with an existing FileDescriptor we should detect the correct InternetProtocolFamily.

Modifications:

Obtain the InternetProtocolFamily from the given FD

Result:

Use correct InternetProtocolFamily when EpollDatagramChannel is created via existing FileDescriptor
This commit is contained in:
Norman Maurer 2019-05-26 20:22:55 +02:00 committed by GitHub
parent 70731bfa7e
commit e17ce934da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 13 additions and 20 deletions

View File

@ -59,7 +59,6 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
StringUtil.simpleClassName(InetSocketAddress.class) + ">, " + StringUtil.simpleClassName(InetSocketAddress.class) + ">, " +
StringUtil.simpleClassName(ByteBuf.class) + ')'; StringUtil.simpleClassName(ByteBuf.class) + ')';
final InternetProtocolFamily family;
private final EpollDatagramChannelConfig config; private final EpollDatagramChannelConfig config;
private volatile boolean connected; private volatile boolean connected;
@ -68,7 +67,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
* on the Operation Systems default which will be chosen. * on the Operation Systems default which will be chosen.
*/ */
public EpollDatagramChannel() { public EpollDatagramChannel() {
this(null); this((InternetProtocolFamily) null);
} }
/** /**
@ -76,17 +75,8 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
* on the Operation Systems default which will be chosen. * on the Operation Systems default which will be chosen.
*/ */
public EpollDatagramChannel(InternetProtocolFamily family) { public EpollDatagramChannel(InternetProtocolFamily family) {
super(family == null ? this(family == null ?
newSocketDgram(Socket.isIPv6Preferred()) : newSocketDgram(family == InternetProtocolFamily.IPv6)); newSocketDgram(Socket.isIPv6Preferred()) : newSocketDgram(family == InternetProtocolFamily.IPv6));
this.family = internetProtocolFamily(family);
config = new EpollDatagramChannelConfig(this);
}
private static InternetProtocolFamily internetProtocolFamily(InternetProtocolFamily family) {
if (family == null) {
return Socket.isIPv6Preferred() ? InternetProtocolFamily.IPv6 : InternetProtocolFamily.IPv4;
}
return family;
} }
/** /**
@ -94,12 +84,11 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
* on the Operation Systems default which will be chosen. * on the Operation Systems default which will be chosen.
*/ */
public EpollDatagramChannel(int fd) { public EpollDatagramChannel(int fd) {
this(new LinuxSocket(fd), null); this(new LinuxSocket(fd));
} }
private EpollDatagramChannel(LinuxSocket fd, InternetProtocolFamily family) { private EpollDatagramChannel(LinuxSocket fd) {
super(null, fd, true); super(null, fd, true);
this.family = internetProtocolFamily(family);
config = new EpollDatagramChannelConfig(this); config = new EpollDatagramChannelConfig(this);
} }

View File

@ -367,7 +367,7 @@ public final class EpollDatagramChannelConfig extends EpollChannelConfig impleme
public EpollDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) { public EpollDatagramChannelConfig setNetworkInterface(NetworkInterface networkInterface) {
try { try {
EpollDatagramChannel datagramChannel = (EpollDatagramChannel) channel; EpollDatagramChannel datagramChannel = (EpollDatagramChannel) channel;
datagramChannel.socket.setNetworkInterface(networkInterface, datagramChannel.family); datagramChannel.socket.setNetworkInterface(networkInterface);
return this; return this;
} catch (IOException e) { } catch (IOException e) {
throw new ChannelException(e); throw new ChannelException(e);

View File

@ -44,6 +44,10 @@ final class LinuxSocket extends Socket {
super(fd); super(fd);
} }
private InternetProtocolFamily family() {
return ipv6 ? InternetProtocolFamily.IPv6 : InternetProtocolFamily.IPv4;
}
int sendmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs, int sendmmsg(NativeDatagramPacketArray.NativeDatagramPacket[] msgs,
int offset, int len) throws IOException { int offset, int len) throws IOException {
return Native.sendmmsg(intValue(), ipv6, msgs, offset, len); return Native.sendmmsg(intValue(), ipv6, msgs, offset, len);
@ -58,10 +62,10 @@ final class LinuxSocket extends Socket {
setInterface(intValue(), ipv6, a.address(), a.scopeId(), interfaceIndex(address)); setInterface(intValue(), ipv6, a.address(), a.scopeId(), interfaceIndex(address));
} }
void setNetworkInterface(NetworkInterface netInterface, InternetProtocolFamily family) throws IOException { void setNetworkInterface(NetworkInterface netInterface) throws IOException {
InetAddress address = deriveInetAddress(netInterface, family == InternetProtocolFamily.IPv6); InetAddress address = deriveInetAddress(netInterface, family() == InternetProtocolFamily.IPv6);
if (address.equals(family == InternetProtocolFamily.IPv4 ? INET_ANY : INET6_ANY)) { if (address.equals(family() == InternetProtocolFamily.IPv4 ? INET_ANY : INET6_ANY)) {
throw new IOException("NetworkInterface does not support " + family); throw new IOException("NetworkInterface does not support " + family());
} }
final NativeInetAddress nativeAddress = NativeInetAddress.newInstance(address); final NativeInetAddress nativeAddress = NativeInetAddress.newInstance(address);
setInterface(intValue(), ipv6, nativeAddress.address(), nativeAddress.scopeId(), interfaceIndex(netInterface)); setInterface(intValue(), ipv6, nativeAddress.address(), nativeAddress.scopeId(), interfaceIndex(netInterface));