Read if needed on ProxyHandler's handshake. Fixes #5933.

Motivation:

When auto-read is disabled and no reads are issued by a user, ProxyHandler will stall the connection on the proxy handshake phase waiting for the first response from a server (that was never read).

Modifications:

Read if needed when very first handshake message is send by ProxyHandler.

Result:

Proxy handshake now succeeds no matter if auto-read disabled or enabled. Without the fix, the new test is failing on master.
This commit is contained in:
Vladimir Kostyukov 2016-10-24 10:52:42 -07:00 committed by Norman Maurer
parent 9cfa467554
commit 23f033ac08
2 changed files with 21 additions and 3 deletions

View File

@ -208,6 +208,8 @@ public abstract class ProxyHandler extends ChannelDuplexHandler {
if (initialMessage != null) {
sendToProxyServer(initialMessage);
}
readIfNeeded(ctx);
}
/**
@ -384,9 +386,7 @@ public abstract class ProxyHandler extends ChannelDuplexHandler {
if (suppressChannelReadComplete) {
suppressChannelReadComplete = false;
if (!ctx.channel().config().isAutoRead()) {
ctx.read();
}
readIfNeeded(ctx);
} else {
ctx.fireChannelReadComplete();
}
@ -412,6 +412,12 @@ public abstract class ProxyHandler extends ChannelDuplexHandler {
}
}
private static void readIfNeeded(ChannelHandlerContext ctx) {
if (!ctx.channel().config().isAutoRead()) {
ctx.read();
}
}
private void writePendingWrites() {
if (pendingWrites != null) {
pendingWrites.removeAndWriteAll();

View File

@ -26,6 +26,7 @@ import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
@ -61,6 +62,7 @@ import java.util.List;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.*;
@ -363,9 +365,16 @@ public class ProxyHandlerTest {
final Queue<Throwable> exceptions = new LinkedBlockingQueue<Throwable>();
volatile int eventCount;
private static void readIfNeeded(ChannelHandlerContext ctx) {
if (!ctx.channel().config().isAutoRead()) {
ctx.read();
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("A\n", CharsetUtil.US_ASCII));
readIfNeeded(ctx);
}
@Override
@ -378,6 +387,7 @@ public class ProxyHandlerTest {
// ProxyHandlers in the pipeline. Therefore, we send the 'B' message only on the first event.
ctx.writeAndFlush(Unpooled.copiedBuffer("B\n", CharsetUtil.US_ASCII));
}
readIfNeeded(ctx);
}
}
@ -388,6 +398,7 @@ public class ProxyHandlerTest {
if ("2".equals(str)) {
ctx.writeAndFlush(Unpooled.copiedBuffer("C\n", CharsetUtil.US_ASCII));
}
readIfNeeded(ctx);
}
@Override
@ -523,6 +534,7 @@ public class ProxyHandlerTest {
Bootstrap b = new Bootstrap();
b.group(group);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.AUTO_READ, ThreadLocalRandom.current().nextBoolean());
b.resolver(NoopAddressResolverGroup.INSTANCE);
b.handler(new ChannelInitializer<SocketChannel>() {
@Override