Skip to content

Commit

Permalink
Correctly handle unresolvable InetSocketAddress when using DatagramCh…
Browse files Browse the repository at this point in the history
…annel (#13017)


Motivation:

We should consistent handle the case when a DatagramPacket was send to an unresolvable InetSocketAddress.

Modifications:

Consistently fail in the case of unresolvable InetSocketAddress

Result:

Fixes #13015
  • Loading branch information
normanmaurer committed Nov 28, 2022
1 parent b64a6e2 commit 91527ff
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import io.netty.util.NetUtil;
import io.netty.util.internal.EmptyArrays;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.opentest4j.TestAbortedException;

import java.io.IOException;
import java.net.BindException;
import java.net.DatagramSocket;
import java.net.Inet6Address;
Expand All @@ -42,6 +43,7 @@
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.UnresolvedAddressException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
Expand All @@ -51,6 +53,7 @@

import static org.assertj.core.api.Assumptions.assumeThat;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -241,6 +244,61 @@ protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throw
}
}

@Test
public void testSendToUnresolvableAddress(TestInfo testInfo) throws Throwable {
run(testInfo, new Runner<Bootstrap, Bootstrap>() {
@Override
public void run(Bootstrap bootstrap, Bootstrap bootstrap2) throws Throwable {
testSendToUnresolvableAddress(bootstrap, bootstrap2);
}
});
}

public void testSendToUnresolvableAddress(Bootstrap sb, Bootstrap cb) throws Throwable {
SocketAddress serverAddress = newSocketAddress();
if (!(serverAddress instanceof InetSocketAddress)) {
return;
}
Channel sc = sb.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
// Just drop
}
});
}
}).bind(serverAddress).sync().channel();

Channel cc = cb.option(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION, true).
handler(new ChannelInboundHandlerAdapter()).register().sync().channel();
try {
InetSocketAddress goodHost = sendToAddress((InetSocketAddress) sc.localAddress());
InetSocketAddress unresolvedHost = new InetSocketAddress("NOT_A_REAL_ADDRESS", goodHost.getPort());

assertFalse(goodHost.isUnresolved());
assertTrue(unresolvedHost.isUnresolved());

String message = "hello world!";
cc.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(message, CharsetUtil.US_ASCII), goodHost)).sync();
assertInstanceOf(UnresolvedAddressException.class, cc.writeAndFlush(new DatagramPacket(
Unpooled.copiedBuffer(message, CharsetUtil.US_ASCII), unresolvedHost)).await().cause());

// DatagramChannel should still be open after sending to unresolved address
assertTrue(cc.isOpen());

// DatagramChannel should still be able to send messages outbound
cc.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(message, CharsetUtil.US_ASCII), goodHost)).sync();
assertInstanceOf(UnresolvedAddressException.class, cc.writeAndFlush(new DatagramPacket(
Unpooled.copiedBuffer(message, CharsetUtil.US_ASCII), unresolvedHost)).await().cause());
assertTrue(cc.isOpen());
} finally {
closeChannel(cc);
closeChannel(sc);
}
}

@SuppressWarnings("deprecation")
private void testSimpleSend0(Bootstrap sb, Bootstrap cb, ByteBuf buf, boolean bindClient,
final byte[] bytes, int count, WrapType wrapType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.net.PortUnreachableException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.UnresolvedAddressException;

import static io.netty.channel.epoll.LinuxSocket.newSocketDgram;

Expand Down Expand Up @@ -417,6 +418,13 @@ private boolean doWriteMessage(Object msg) throws Exception {
return doWriteOrSendBytes(data, remoteAddress, false) > 0;
}

private static void checkUnresolved(AddressedEnvelope<?, ?> envelope) {
if (envelope.recipient() instanceof InetSocketAddress
&& (((InetSocketAddress) envelope.recipient()).isUnresolved())) {
throw new UnresolvedAddressException();
}
}

@Override
protected Object filterOutboundMessage(Object msg) {
if (msg instanceof io.netty.channel.unix.SegmentedDatagramPacket) {
Expand All @@ -425,12 +433,16 @@ protected Object filterOutboundMessage(Object msg) {
"unsupported message type: " + StringUtil.simpleClassName(msg) + EXPECTED_TYPES);
}
io.netty.channel.unix.SegmentedDatagramPacket packet = (io.netty.channel.unix.SegmentedDatagramPacket) msg;
checkUnresolved(packet);

ByteBuf content = packet.content();
return UnixChannelUtil.isBufferCopyNeededForWrite(content) ?
packet.replace(newDirectBuffer(packet, content)) : msg;
}
if (msg instanceof DatagramPacket) {
DatagramPacket packet = (DatagramPacket) msg;
checkUnresolved(packet);

ByteBuf content = packet.content();
return UnixChannelUtil.isBufferCopyNeededForWrite(content) ?
new DatagramPacket(newDirectBuffer(packet, content), packet.recipient()) : msg;
Expand All @@ -444,6 +456,8 @@ protected Object filterOutboundMessage(Object msg) {
if (msg instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
checkUnresolved(e);

if (e.content() instanceof ByteBuf &&
(e.recipient() == null || e.recipient() instanceof InetSocketAddress)) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.UnresolvedAddressException;

import static io.netty.channel.kqueue.BsdSocket.newSocketDgram;

Expand Down Expand Up @@ -296,10 +297,18 @@ protected boolean doWriteMessage(Object msg) throws Exception {
return writtenBytes > 0;
}

private static void checkUnresolved(AddressedEnvelope<?, ?> envelope) {
if (envelope.recipient() instanceof InetSocketAddress
&& (((InetSocketAddress) envelope.recipient()).isUnresolved())) {
throw new UnresolvedAddressException();
}
}

@Override
protected Object filterOutboundMessage(Object msg) {
if (msg instanceof DatagramPacket) {
DatagramPacket packet = (DatagramPacket) msg;
checkUnresolved(packet);
ByteBuf content = packet.content();
return UnixChannelUtil.isBufferCopyNeededForWrite(content) ?
new DatagramPacket(newDirectBuffer(packet, content), packet.recipient()) : msg;
Expand All @@ -313,6 +322,8 @@ protected Object filterOutboundMessage(Object msg) {
if (msg instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
checkUnresolved(e);

if (e.content() instanceof ByteBuf &&
(e.recipient() == null || e.recipient() instanceof InetSocketAddress)) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.nio.channels.SelectionKey;
import java.nio.channels.UnresolvedAddressException;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -300,10 +301,18 @@ protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Ex
return writtenBytes > 0;
}

private static void checkUnresolved(AddressedEnvelope<?, ?> envelope) {
if (envelope.recipient() instanceof InetSocketAddress
&& (((InetSocketAddress) envelope.recipient()).isUnresolved())) {
throw new UnresolvedAddressException();
}
}

@Override
protected Object filterOutboundMessage(Object msg) {
if (msg instanceof DatagramPacket) {
DatagramPacket p = (DatagramPacket) msg;
checkUnresolved(p);
ByteBuf content = p.content();
if (isSingleDirectBuffer(content)) {
return p;
Expand All @@ -322,6 +331,7 @@ protected Object filterOutboundMessage(Object msg) {
if (msg instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
checkUnresolved(e);
if (e.content() instanceof ByteBuf) {
ByteBuf content = (ByteBuf) e.content();
if (isSingleDirectBuffer(content)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.UnresolvedAddressException;
import java.util.List;
import java.util.Locale;

Expand Down Expand Up @@ -292,15 +293,28 @@ protected void doWrite(ChannelOutboundBuffer in) throws Exception {
}
}

private static void checkUnresolved(AddressedEnvelope<?, ?> envelope) {
if (envelope.recipient() instanceof InetSocketAddress
&& (((InetSocketAddress) envelope.recipient()).isUnresolved())) {
throw new UnresolvedAddressException();
}
}

@Override
protected Object filterOutboundMessage(Object msg) {
if (msg instanceof DatagramPacket || msg instanceof ByteBuf) {
if (msg instanceof DatagramPacket) {
checkUnresolved((DatagramPacket) msg);
return msg;
}

if (msg instanceof ByteBuf) {
return msg;
}

if (msg instanceof AddressedEnvelope) {
@SuppressWarnings("unchecked")
AddressedEnvelope<Object, SocketAddress> e = (AddressedEnvelope<Object, SocketAddress>) msg;
checkUnresolved(e);
if (e.content() instanceof ByteBuf) {
return msg;
}
Expand Down

0 comments on commit 91527ff

Please sign in to comment.