diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java index 1ac7f7c3f9c..1c69b9536a6 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java @@ -69,7 +69,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements * on the Operation Systems default which will be chosen. */ public EpollDatagramChannel(EventLoop eventLoop) { - this(eventLoop, (InternetProtocolFamily) null); + this(eventLoop, null); } /** @@ -78,7 +78,9 @@ public EpollDatagramChannel(EventLoop eventLoop) { */ public EpollDatagramChannel(EventLoop eventLoop, InternetProtocolFamily family) { this(eventLoop, family == null ? - newSocketDgram(Socket.isIPv6Preferred()) : newSocketDgram(family == InternetProtocolFamily.IPv6)); + newSocketDgram(Socket.isIPv6Preferred()) : + newSocketDgram(family == InternetProtocolFamily.IPv6), + false); } /** @@ -86,11 +88,11 @@ public EpollDatagramChannel(EventLoop eventLoop, InternetProtocolFamily family) * on the Operation Systems default which will be chosen. */ public EpollDatagramChannel(EventLoop eventLoop, int fd) { - this(eventLoop, new LinuxSocket(fd)); + this(eventLoop, new LinuxSocket(fd), true); } - private EpollDatagramChannel(EventLoop eventLoop, LinuxSocket fd) { - super(null, eventLoop, fd, true); + private EpollDatagramChannel(EventLoop eventLoop, LinuxSocket fd, boolean active) { + super(null, eventLoop, fd, active); config = new EpollDatagramChannelConfig(this); } diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramChannelTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramChannelTest.java new file mode 100644 index 00000000000..5bf80482fb3 --- /dev/null +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramChannelTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2019 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.epoll; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.MultithreadEventLoopGroup; +import io.netty.channel.socket.InternetProtocolFamily; +import io.netty.channel.unix.Socket; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +import static io.netty.util.NetUtil.LOCALHOST; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class EpollDatagramChannelTest { + + @Before + public void setUp() { + Epoll.ensureAvailability(); + } + + @Test + public void testNotActiveNoLocalRemoteAddress() throws IOException { + EventLoopGroup group = new MultithreadEventLoopGroup(1, EpollHandler.newFactory()); + try { + checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel(group.next())); + checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel(group.next(), InternetProtocolFamily.IPv4)); + checkNotActiveNoLocalRemoteAddress(new EpollDatagramChannel(group.next(), InternetProtocolFamily.IPv6)); + } finally { + group.shutdownGracefully(); + } + } + + @Test + public void testActiveHasLocalAddress() throws IOException { + EventLoopGroup group = new MultithreadEventLoopGroup(1, EpollHandler.newFactory()); + try { + Socket socket = Socket.newSocketDgram(); + EpollDatagramChannel channel = new EpollDatagramChannel(group.next(), socket.intValue()); + InetSocketAddress localAddress = channel.localAddress(); + assertTrue(channel.active); + assertNotNull(localAddress); + assertEquals(socket.localAddress(), localAddress); + channel.fd().close(); + } finally { + group.shutdownGracefully(); + } + } + + @Test + public void testLocalAddressBeforeAndAfterBind() { + EventLoopGroup group = new MultithreadEventLoopGroup(1, EpollHandler.newFactory()); + try { + TestHandler handler = new TestHandler(); + InetSocketAddress localAddressBeforeBind = new InetSocketAddress(LOCALHOST, 0); + + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(group) + .channel(EpollDatagramChannel.class) + .localAddress(localAddressBeforeBind) + .handler(handler); + + ChannelFuture future = bootstrap.bind().syncUninterruptibly(); + + assertNull(handler.localAddress); + + SocketAddress localAddressAfterBind = future.channel().localAddress(); + assertNotNull(localAddressAfterBind); + assertTrue(localAddressAfterBind instanceof InetSocketAddress); + assertTrue(((InetSocketAddress) localAddressAfterBind).getPort() != 0); + + future.channel().close().syncUninterruptibly(); + } finally { + group.shutdownGracefully(); + } + } + + private static void checkNotActiveNoLocalRemoteAddress(EpollDatagramChannel channel) throws IOException { + assertFalse(channel.active); + assertNull(channel.localAddress()); + assertNull(channel.remoteAddress()); + channel.fd().close(); + } + + private static final class TestHandler implements ChannelHandler { + private volatile SocketAddress localAddress; + + @Override + public void channelRegistered(ChannelHandlerContext ctx) throws Exception { + this.localAddress = ctx.channel().localAddress(); + ctx.fireChannelRegistered(); + } + } +} diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollReuseAddrTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollReuseAddrTest.java index 2fe049b4843..03db137ce68 100644 --- a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollReuseAddrTest.java +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollReuseAddrTest.java @@ -23,6 +23,8 @@ import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandler; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; import io.netty.util.NetUtil; import io.netty.util.ReferenceCountUtil; import io.netty.util.ResourceLeakDetector; @@ -78,7 +80,7 @@ public void testMultipleBindDatagramChannelWithoutReusePortFails() { } private static void testMultipleBindDatagramChannelWithoutReusePortFails0(AbstractBootstrap bootstrap) { - bootstrap.handler(new DummyHandler()); + bootstrap.handler(new LoggingHandler(LogLevel.ERROR)); ChannelFuture future = bootstrap.bind().syncUninterruptibly(); try { bootstrap.bind(future.channel().localAddress()).syncUninterruptibly();