Make the header list size limit configurable on both client and server side.

This commit is contained in:
Xudong Ma 2015-10-28 15:03:34 -07:00
parent a4f319f0c3
commit 750b1977ca
7 changed files with 121 additions and 24 deletions

View File

@ -145,6 +145,11 @@ public final class GrpcUtil {
*/ */
public static final int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; public static final int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024;
/**
* The default maximum size (in bytes) for inbound header/trailer.
*/
public static final int DEFAULT_MAX_HEADER_LIST_SIZE = 8192;
/** /**
* The set of valid status codes for client cancellation. * The set of valid status codes for client cancellation.
*/ */

View File

@ -71,6 +71,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
private SslContext sslContext; private SslContext sslContext;
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW; private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
/** /**
* Creates a new builder with the given server address. This factory method is primarily intended * Creates a new builder with the given server address. This factory method is primarily intended
@ -160,14 +161,14 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
* is {@link #DEFAULT_FLOW_CONTROL_WINDOW}). * is {@link #DEFAULT_FLOW_CONTROL_WINDOW}).
*/ */
public final NettyChannelBuilder flowControlWindow(int flowControlWindow) { public final NettyChannelBuilder flowControlWindow(int flowControlWindow) {
Preconditions.checkArgument(flowControlWindow > 0, "flowControlWindow must be positive"); checkArgument(flowControlWindow > 0, "flowControlWindow must be positive");
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
return this; return this;
} }
/** /**
* Sets the maximum message size allowed to be received on the channel. If not called, * Sets the maximum message size allowed to be received on the channel. If not called,
* defaults to {@link io.grpc.internal.GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE}. * defaults to {@link GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE}.
*/ */
public final NettyChannelBuilder maxMessageSize(int maxMessageSize) { public final NettyChannelBuilder maxMessageSize(int maxMessageSize) {
checkArgument(maxMessageSize >= 0, "maxMessageSize must be >= 0"); checkArgument(maxMessageSize >= 0, "maxMessageSize must be >= 0");
@ -175,6 +176,16 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
return this; return this;
} }
/**
* Sets the maximum size of header list allowed to be received on the channel. If not called,
* defaults to {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE}.
*/
public final NettyChannelBuilder maxHeaderListSize(int maxHeaderListSize) {
checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be > 0");
this.maxHeaderListSize = maxHeaderListSize;
return this;
}
/** /**
* Equivalent to using {@link #negotiationType(NegotiationType)} with {@code PLAINTEXT} or * Equivalent to using {@link #negotiationType(NegotiationType)} with {@code PLAINTEXT} or
* {@code PLAINTEXT_UPGRADE}. * {@code PLAINTEXT_UPGRADE}.
@ -192,7 +203,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
@Override @Override
protected ClientTransportFactory buildTransportFactory() { protected ClientTransportFactory buildTransportFactory() {
return new NettyTransportFactory(channelType, negotiationType, sslContext, return new NettyTransportFactory(channelType, negotiationType, sslContext,
eventLoopGroup, flowControlWindow, maxMessageSize); eventLoopGroup, flowControlWindow, maxMessageSize, maxHeaderListSize);
} }
@Override @Override
@ -246,18 +257,21 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
private final boolean usingSharedGroup; private final boolean usingSharedGroup;
private final int flowControlWindow; private final int flowControlWindow;
private final int maxMessageSize; private final int maxMessageSize;
private final int maxHeaderListSize;
private NettyTransportFactory(Class<? extends Channel> channelType, private NettyTransportFactory(Class<? extends Channel> channelType,
NegotiationType negotiationType, NegotiationType negotiationType,
SslContext sslContext, SslContext sslContext,
EventLoopGroup group, EventLoopGroup group,
int flowControlWindow, int flowControlWindow,
int maxMessageSize) { int maxMessageSize,
int maxHeaderListSize) {
this.channelType = channelType; this.channelType = channelType;
this.negotiationType = negotiationType; this.negotiationType = negotiationType;
this.sslContext = sslContext; this.sslContext = sslContext;
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
this.maxMessageSize = maxMessageSize; this.maxMessageSize = maxMessageSize;
this.maxHeaderListSize = maxHeaderListSize;
usingSharedGroup = group == null; usingSharedGroup = group == null;
if (usingSharedGroup) { if (usingSharedGroup) {
// The group was unspecified, using the shared group. // The group was unspecified, using the shared group.
@ -272,7 +286,7 @@ public class NettyChannelBuilder extends AbstractManagedChannelImplBuilder<Netty
ProtocolNegotiator negotiator = ProtocolNegotiator negotiator =
createProtocolNegotiator(authority, negotiationType, sslContext); createProtocolNegotiator(authority, negotiationType, sslContext);
return new NettyClientTransport(serverAddress, channelType, group, negotiator, return new NettyClientTransport(serverAddress, channelType, group, negotiator,
flowControlWindow, maxMessageSize, authority); flowControlWindow, maxMessageSize, maxHeaderListSize, authority);
} }
@Override @Override

View File

@ -54,11 +54,14 @@ import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder; import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder;
import io.netty.handler.codec.http2.DefaultHttp2FrameReader; import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
import io.netty.handler.codec.http2.DefaultHttp2FrameWriter; import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
import io.netty.handler.codec.http2.DefaultHttp2HeadersDecoder;
import io.netty.handler.codec.http2.Http2CodecUtil;
import io.netty.handler.codec.http2.Http2Connection; import io.netty.handler.codec.http2.Http2Connection;
import io.netty.handler.codec.http2.Http2FrameLogger; import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2FrameReader; import io.netty.handler.codec.http2.Http2FrameReader;
import io.netty.handler.codec.http2.Http2FrameWriter; import io.netty.handler.codec.http2.Http2FrameWriter;
import io.netty.handler.codec.http2.Http2Headers; import io.netty.handler.codec.http2.Http2Headers;
import io.netty.handler.codec.http2.Http2HeadersDecoder;
import io.netty.handler.codec.http2.Http2InboundFrameLogger; import io.netty.handler.codec.http2.Http2InboundFrameLogger;
import io.netty.handler.codec.http2.Http2OutboundFrameLogger; import io.netty.handler.codec.http2.Http2OutboundFrameLogger;
import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LogLevel;
@ -81,6 +84,7 @@ class NettyClientTransport implements ClientTransport {
private final AsciiString authority; private final AsciiString authority;
private final int flowControlWindow; private final int flowControlWindow;
private final int maxMessageSize; private final int maxMessageSize;
private final int maxHeaderListSize;
// We should not send on the channel until negotiation completes. This is a hard requirement // We should not send on the channel until negotiation completes. This is a hard requirement
// by SslHandler but is appropriate for HTTP/1.1 Upgrade as well. // by SslHandler but is appropriate for HTTP/1.1 Upgrade as well.
private Channel channel; private Channel channel;
@ -94,13 +98,15 @@ class NettyClientTransport implements ClientTransport {
NettyClientTransport(SocketAddress address, Class<? extends Channel> channelType, NettyClientTransport(SocketAddress address, Class<? extends Channel> channelType,
EventLoopGroup group, ProtocolNegotiator negotiator, EventLoopGroup group, ProtocolNegotiator negotiator,
int flowControlWindow, int maxMessageSize, String authority) { int flowControlWindow, int maxMessageSize, int maxHeaderListSize,
String authority) {
Preconditions.checkNotNull(negotiator, "negotiator"); Preconditions.checkNotNull(negotiator, "negotiator");
this.address = Preconditions.checkNotNull(address, "address"); this.address = Preconditions.checkNotNull(address, "address");
this.group = Preconditions.checkNotNull(group, "group"); this.group = Preconditions.checkNotNull(group, "group");
this.channelType = Preconditions.checkNotNull(channelType, "channelType"); this.channelType = Preconditions.checkNotNull(channelType, "channelType");
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
this.maxMessageSize = maxMessageSize; this.maxMessageSize = maxMessageSize;
this.maxHeaderListSize = maxHeaderListSize;
this.authority = new AsciiString(authority); this.authority = new AsciiString(authority);
handler = newHandler(); handler = newHandler();
@ -244,7 +250,9 @@ class NettyClientTransport implements ClientTransport {
private NettyClientHandler newHandler() { private NettyClientHandler newHandler() {
Http2Connection connection = new DefaultHttp2Connection(false); Http2Connection connection = new DefaultHttp2Connection(false);
Http2FrameReader frameReader = new DefaultHttp2FrameReader(); Http2HeadersDecoder headersDecoder =
new DefaultHttp2HeadersDecoder(maxHeaderListSize, Http2CodecUtil.DEFAULT_HEADER_TABLE_SIZE);
Http2FrameReader frameReader = new DefaultHttp2FrameReader(headersDecoder);
Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter(); Http2FrameWriter frameWriter = new DefaultHttp2FrameWriter();
Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, getClass()); Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, getClass());

View File

@ -76,12 +76,13 @@ public class NettyServer implements Server {
private Channel channel; private Channel channel;
private final int flowControlWindow; private final int flowControlWindow;
private final int maxMessageSize; private final int maxMessageSize;
private final int maxHeaderListSize;
private final ReferenceCounted eventLoopReferenceCounter = new EventLoopReferenceCounter(); private final ReferenceCounted eventLoopReferenceCounter = new EventLoopReferenceCounter();
NettyServer(SocketAddress address, Class<? extends ServerChannel> channelType, NettyServer(SocketAddress address, Class<? extends ServerChannel> channelType,
@Nullable EventLoopGroup bossGroup, @Nullable EventLoopGroup workerGroup, @Nullable EventLoopGroup bossGroup, @Nullable EventLoopGroup workerGroup,
@Nullable SslContext sslContext, int maxStreamsPerConnection, int flowControlWindow, @Nullable SslContext sslContext, int maxStreamsPerConnection, int flowControlWindow,
int maxMessageSize) { int maxMessageSize, int maxHeaderListSize) {
this.address = address; this.address = address;
this.channelType = checkNotNull(channelType, "channelType"); this.channelType = checkNotNull(channelType, "channelType");
this.bossGroup = bossGroup; this.bossGroup = bossGroup;
@ -92,6 +93,7 @@ public class NettyServer implements Server {
this.maxStreamsPerConnection = maxStreamsPerConnection; this.maxStreamsPerConnection = maxStreamsPerConnection;
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
this.maxMessageSize = maxMessageSize; this.maxMessageSize = maxMessageSize;
this.maxHeaderListSize = maxHeaderListSize;
} }
@Override @Override
@ -119,7 +121,7 @@ public class NettyServer implements Server {
}); });
NettyServerTransport transport NettyServerTransport transport
= new NettyServerTransport(ch, sslContext, maxStreamsPerConnection, flowControlWindow, = new NettyServerTransport(ch, sslContext, maxStreamsPerConnection, flowControlWindow,
maxMessageSize); maxMessageSize, maxHeaderListSize);
transport.start(listener.transportCreated(transport)); transport.start(listener.transportCreated(transport));
} }
}); });

View File

@ -39,6 +39,7 @@ import com.google.common.base.Preconditions;
import io.grpc.ExperimentalApi; import io.grpc.ExperimentalApi;
import io.grpc.HandlerRegistry; import io.grpc.HandlerRegistry;
import io.grpc.internal.AbstractServerImplBuilder; import io.grpc.internal.AbstractServerImplBuilder;
import io.grpc.internal.GrpcUtil;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel; import io.netty.channel.ServerChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
@ -68,6 +69,7 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE; private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE;
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW; private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
/** /**
* Creates a server builder that will bind to the given port. * Creates a server builder that will bind to the given port.
@ -182,7 +184,7 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
* limit. * limit.
*/ */
public NettyServerBuilder maxConcurrentCallsPerConnection(int maxCalls) { public NettyServerBuilder maxConcurrentCallsPerConnection(int maxCalls) {
Preconditions.checkArgument(maxCalls > 0, "max must be positive: %s", maxCalls); checkArgument(maxCalls > 0, "max must be positive: %s", maxCalls);
this.maxConcurrentCallsPerConnection = maxCalls; this.maxConcurrentCallsPerConnection = maxCalls;
return this; return this;
} }
@ -192,7 +194,7 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
* is {@link #DEFAULT_FLOW_CONTROL_WINDOW}). * is {@link #DEFAULT_FLOW_CONTROL_WINDOW}).
*/ */
public NettyServerBuilder flowControlWindow(int flowControlWindow) { public NettyServerBuilder flowControlWindow(int flowControlWindow) {
Preconditions.checkArgument(flowControlWindow > 0, "flowControlWindow must be positive"); checkArgument(flowControlWindow > 0, "flowControlWindow must be positive");
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
return this; return this;
} }
@ -207,11 +209,21 @@ public final class NettyServerBuilder extends AbstractServerImplBuilder<NettySer
return this; return this;
} }
/**
* Sets the maximum size of header list allowed to be received on the server. If not called,
* defaults to {@link GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE}.
*/
public NettyServerBuilder maxHeaderListSize(int maxHeaderListSize) {
checkArgument(maxHeaderListSize > 0, "maxHeaderListSize must be > 0");
this.maxHeaderListSize = maxHeaderListSize;
return this;
}
@Override @Override
protected NettyServer buildTransportServer() { protected NettyServer buildTransportServer() {
return new NettyServer(address, channelType, bossEventLoopGroup, return new NettyServer(address, channelType, bossEventLoopGroup,
workerEventLoopGroup, sslContext, maxConcurrentCallsPerConnection, flowControlWindow, workerEventLoopGroup, sslContext, maxConcurrentCallsPerConnection, flowControlWindow,
maxMessageSize); maxMessageSize, maxHeaderListSize);
} }
@Override @Override

View File

@ -42,10 +42,13 @@ import io.netty.channel.ChannelHandler;
import io.netty.handler.codec.http2.DefaultHttp2Connection; import io.netty.handler.codec.http2.DefaultHttp2Connection;
import io.netty.handler.codec.http2.DefaultHttp2FrameReader; import io.netty.handler.codec.http2.DefaultHttp2FrameReader;
import io.netty.handler.codec.http2.DefaultHttp2FrameWriter; import io.netty.handler.codec.http2.DefaultHttp2FrameWriter;
import io.netty.handler.codec.http2.DefaultHttp2HeadersDecoder;
import io.netty.handler.codec.http2.Http2CodecUtil;
import io.netty.handler.codec.http2.Http2Connection; import io.netty.handler.codec.http2.Http2Connection;
import io.netty.handler.codec.http2.Http2FrameLogger; import io.netty.handler.codec.http2.Http2FrameLogger;
import io.netty.handler.codec.http2.Http2FrameReader; import io.netty.handler.codec.http2.Http2FrameReader;
import io.netty.handler.codec.http2.Http2FrameWriter; import io.netty.handler.codec.http2.Http2FrameWriter;
import io.netty.handler.codec.http2.Http2HeadersDecoder;
import io.netty.handler.codec.http2.Http2InboundFrameLogger; import io.netty.handler.codec.http2.Http2InboundFrameLogger;
import io.netty.handler.codec.http2.Http2OutboundFrameLogger; import io.netty.handler.codec.http2.Http2OutboundFrameLogger;
import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LogLevel;
@ -70,14 +73,16 @@ class NettyServerTransport implements ServerTransport {
private boolean terminated; private boolean terminated;
private final int flowControlWindow; private final int flowControlWindow;
private final int maxMessageSize; private final int maxMessageSize;
private final int maxHeaderListSize;
NettyServerTransport(Channel channel, @Nullable SslContext sslContext, int maxStreams, NettyServerTransport(Channel channel, @Nullable SslContext sslContext, int maxStreams,
int flowControlWindow, int maxMessageSize) { int flowControlWindow, int maxMessageSize, int maxHeaderListSize) {
this.channel = Preconditions.checkNotNull(channel, "channel"); this.channel = Preconditions.checkNotNull(channel, "channel");
this.sslContext = sslContext; this.sslContext = sslContext;
this.maxStreams = maxStreams; this.maxStreams = maxStreams;
this.flowControlWindow = flowControlWindow; this.flowControlWindow = flowControlWindow;
this.maxMessageSize = maxMessageSize; this.maxMessageSize = maxMessageSize;
this.maxHeaderListSize = maxHeaderListSize;
} }
public void start(ServerTransportListener listener) { public void start(ServerTransportListener listener) {
@ -133,8 +138,10 @@ class NettyServerTransport implements ServerTransport {
private NettyServerHandler createHandler(ServerTransportListener transportListener) { private NettyServerHandler createHandler(ServerTransportListener transportListener) {
Http2Connection connection = new DefaultHttp2Connection(true); Http2Connection connection = new DefaultHttp2Connection(true);
Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, getClass()); Http2FrameLogger frameLogger = new Http2FrameLogger(LogLevel.DEBUG, getClass());
Http2FrameReader frameReader = Http2HeadersDecoder headersDecoder =
new Http2InboundFrameLogger(new DefaultHttp2FrameReader(), frameLogger); new DefaultHttp2HeadersDecoder(maxHeaderListSize, Http2CodecUtil.DEFAULT_HEADER_TABLE_SIZE);
Http2FrameReader frameReader = new Http2InboundFrameLogger(
new DefaultHttp2FrameReader(headersDecoder), frameLogger);
Http2FrameWriter frameWriter = Http2FrameWriter frameWriter =
new Http2OutboundFrameLogger(new DefaultHttp2FrameWriter(), frameLogger); new Http2OutboundFrameLogger(new DefaultHttp2FrameWriter(), frameLogger);

View File

@ -61,6 +61,7 @@ import io.grpc.testing.TestUtils;
import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http2.Http2Exception;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SupportedCipherSuiteFilter; import io.netty.handler.ssl.SupportedCipherSuiteFilter;
@ -154,14 +155,15 @@ public class NettyClientTransportTest {
assertEquals(1, serverListener.streamListeners.size()); assertEquals(1, serverListener.streamListeners.size());
Metadata receivedHeaders = serverListener.streamListeners.get(0).headers; Metadata receivedHeaders = serverListener.streamListeners.get(0).headers;
assertEquals(GrpcUtil.getGrpcUserAgent("netty", userAgent), assertEquals(GrpcUtil.getGrpcUserAgent("netty", userAgent),
receivedHeaders.get(USER_AGENT_KEY)); receivedHeaders.get(USER_AGENT_KEY));
} }
@Test @Test
public void maxMessageSizeShouldBeEnforced() throws Throwable { public void maxMessageSizeShouldBeEnforced() throws Throwable {
startServer(); startServer();
// Allow the response payloads of up to 1 byte. // Allow the response payloads of up to 1 byte.
NettyClientTransport transport = newTransport(newNegotiator(), 1); NettyClientTransport transport = newTransport(newNegotiator(),
1, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE);
transport.start(clientTransportListener); transport.start(clientTransportListener);
try { try {
@ -205,7 +207,7 @@ public class NettyClientTransportTest {
@Test @Test
public void bufferedStreamsShouldBeClosedWhenConnectionTerminates() throws Exception { public void bufferedStreamsShouldBeClosedWhenConnectionTerminates() throws Exception {
// Only allow a single stream active at a time. // Only allow a single stream active at a time.
startServer(1); startServer(1, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE);
NettyClientTransport transport = newTransport(newNegotiator()); NettyClientTransport transport = newTransport(newNegotiator());
transport.start(clientTransportListener); transport.start(clientTransportListener);
@ -234,6 +236,51 @@ public class NettyClientTransportTest {
} }
} }
@Test
public void maxHeaderListSizeShouldBeEnforcedOnClient() throws Exception {
startServer();
NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, 1);
transport.start(clientTransportListener);
try {
// Send a single RPC and wait for the response.
new Rpc(transport, new Metadata()).halfClose().waitForResponse();
fail("The stream should have been failed due to client received header exceeds header list"
+ " size limit!");
} catch (Exception e) {
Throwable rootCause = getRootCause(e);
assertTrue(rootCause instanceof Http2Exception);
assertEquals("Header size exceeded max allowed size (1)", rootCause.getMessage());
}
}
@Test
public void maxHeaderListSizeShouldBeEnforcedOnServer() throws Exception {
startServer(100, 1);
NettyClientTransport transport = newTransport(newNegotiator());
transport.start(clientTransportListener);
try {
// Send a single RPC and wait for the response.
new Rpc(transport, new Metadata()).halfClose().waitForResponse();
fail("The stream should have been failed due to server received header exceeds header list"
+ " size limit!");
} catch (Exception e) {
Throwable rootCause = getRootCause(e);
assertTrue(rootCause.getMessage(),
rootCause.getMessage().contains("Header size exceeded max allowed size (1)"));
}
}
private Throwable getRootCause(Throwable t) {
if (t.getCause() == null) {
return t;
}
return getRootCause(t.getCause());
}
private ProtocolNegotiator newNegotiator() throws IOException { private ProtocolNegotiator newNegotiator() throws IOException {
File clientCert = TestUtils.loadCert("ca.pem"); File clientCert = TestUtils.loadCert("ca.pem");
SslContext clientContext = GrpcSslContexts.forClient().trustManager(clientCert) SslContext clientContext = GrpcSslContexts.forClient().trustManager(clientCert)
@ -242,28 +289,30 @@ public class NettyClientTransportTest {
} }
private NettyClientTransport newTransport(ProtocolNegotiator negotiator) { private NettyClientTransport newTransport(ProtocolNegotiator negotiator) {
return newTransport(negotiator, DEFAULT_MAX_MESSAGE_SIZE); return newTransport(negotiator,
DEFAULT_MAX_MESSAGE_SIZE, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE);
} }
private NettyClientTransport newTransport(ProtocolNegotiator negotiator, int maxMsgSize) { private NettyClientTransport newTransport(ProtocolNegotiator negotiator,
int maxMsgSize, int maxHeaderListSize) {
NettyClientTransport transport = new NettyClientTransport(address, NioSocketChannel.class, NettyClientTransport transport = new NettyClientTransport(address, NioSocketChannel.class,
group, negotiator, DEFAULT_WINDOW_SIZE, maxMsgSize, authority); group, negotiator, DEFAULT_WINDOW_SIZE, maxMsgSize, maxHeaderListSize, authority);
transports.add(transport); transports.add(transport);
return transport; return transport;
} }
private void startServer() throws IOException { private void startServer() throws IOException {
startServer(100); startServer(100, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE);
} }
private void startServer(int maxStreamsPerConnection) throws IOException { private void startServer(int maxStreamsPerConnection, int maxHeaderListSize) throws IOException {
File serverCert = TestUtils.loadCert("server1.pem"); File serverCert = TestUtils.loadCert("server1.pem");
File key = TestUtils.loadCert("server1.key"); File key = TestUtils.loadCert("server1.key");
SslContext serverContext = GrpcSslContexts.forServer(serverCert, key) SslContext serverContext = GrpcSslContexts.forServer(serverCert, key)
.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build(); .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build();
server = new NettyServer(address, NioServerSocketChannel.class, server = new NettyServer(address, NioServerSocketChannel.class,
group, group, serverContext, maxStreamsPerConnection, group, group, serverContext, maxStreamsPerConnection,
DEFAULT_WINDOW_SIZE, DEFAULT_MAX_MESSAGE_SIZE); DEFAULT_WINDOW_SIZE, DEFAULT_MAX_MESSAGE_SIZE, maxHeaderListSize);
server.start(serverListener); server.start(serverListener);
} }