• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc.netty;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Preconditions.checkState;
22 import static io.grpc.internal.GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
23 import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS;
24 import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIME_NANOS;
25 import static io.grpc.internal.GrpcUtil.SERVER_KEEPALIVE_TIME_NANOS_DISABLED;
26 
27 import com.google.common.annotations.VisibleForTesting;
28 import com.google.errorprone.annotations.CanIgnoreReturnValue;
29 import com.google.errorprone.annotations.CheckReturnValue;
30 import com.google.errorprone.annotations.InlineMe;
31 import io.grpc.Attributes;
32 import io.grpc.ExperimentalApi;
33 import io.grpc.Internal;
34 import io.grpc.ServerBuilder;
35 import io.grpc.ServerCredentials;
36 import io.grpc.ServerStreamTracer;
37 import io.grpc.internal.AbstractServerImplBuilder;
38 import io.grpc.internal.FixedObjectPool;
39 import io.grpc.internal.GrpcUtil;
40 import io.grpc.internal.InternalServer;
41 import io.grpc.internal.KeepAliveManager;
42 import io.grpc.internal.ObjectPool;
43 import io.grpc.internal.ServerImplBuilder;
44 import io.grpc.internal.ServerImplBuilder.ClientTransportServersBuilder;
45 import io.grpc.internal.SharedResourcePool;
46 import io.grpc.internal.TransportTracer;
47 import io.netty.channel.ChannelFactory;
48 import io.netty.channel.ChannelOption;
49 import io.netty.channel.EventLoopGroup;
50 import io.netty.channel.ReflectiveChannelFactory;
51 import io.netty.channel.ServerChannel;
52 import io.netty.channel.socket.nio.NioServerSocketChannel;
53 import io.netty.handler.ssl.SslContext;
54 import java.io.File;
55 import java.io.InputStream;
56 import java.net.InetSocketAddress;
57 import java.net.SocketAddress;
58 import java.util.ArrayList;
59 import java.util.HashMap;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.concurrent.TimeUnit;
63 import javax.net.ssl.SSLException;
64 
65 /**
66  * A builder to help simplify the construction of a Netty-based GRPC server.
67  */
68 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784")
69 @CheckReturnValue
70 public final class NettyServerBuilder extends AbstractServerImplBuilder<NettyServerBuilder> {
71 
72   // 1MiB
73   public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1024 * 1024;
74 
75   static final long MAX_CONNECTION_IDLE_NANOS_DISABLED = Long.MAX_VALUE;
76   static final long MAX_CONNECTION_AGE_NANOS_DISABLED = Long.MAX_VALUE;
77   static final long MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE = Long.MAX_VALUE;
78 
79   private static final long MIN_KEEPALIVE_TIME_NANO = TimeUnit.MILLISECONDS.toNanos(1L);
80   private static final long MIN_KEEPALIVE_TIMEOUT_NANO = TimeUnit.MICROSECONDS.toNanos(499L);
81   private static final long MIN_MAX_CONNECTION_IDLE_NANO = TimeUnit.SECONDS.toNanos(1L);
82   private static final long MIN_MAX_CONNECTION_AGE_NANO = TimeUnit.SECONDS.toNanos(1L);
83   private static final long AS_LARGE_AS_INFINITE = TimeUnit.DAYS.toNanos(1000L);
84   private static final ObjectPool<? extends EventLoopGroup> DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL =
85       SharedResourcePool.forResource(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP);
86   private static final ObjectPool<? extends EventLoopGroup> DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL =
87       SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP);
88 
89   private final ServerImplBuilder serverImplBuilder;
90   private final List<SocketAddress> listenAddresses = new ArrayList<>();
91 
92   private TransportTracer.Factory transportTracerFactory = TransportTracer.getDefaultFactory();
93   private ChannelFactory<? extends ServerChannel> channelFactory =
94       Utils.DEFAULT_SERVER_CHANNEL_FACTORY;
95   private final Map<ChannelOption<?>, Object> channelOptions = new HashMap<>();
96   private final Map<ChannelOption<?>, Object> childChannelOptions = new HashMap<>();
97   private ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool =
98       DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL;
99   private ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool =
100       DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
101   private boolean forceHeapBuffer;
102   private ProtocolNegotiator.ServerFactory protocolNegotiatorFactory;
103   private final boolean freezeProtocolNegotiatorFactory;
104   private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE;
105   private boolean autoFlowControl = true;
106   private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
107   private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
108   private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
109   private long keepAliveTimeInNanos = DEFAULT_SERVER_KEEPALIVE_TIME_NANOS;
110   private long keepAliveTimeoutInNanos = DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS;
111   private long maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED;
112   private long maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED;
113   private long maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE;
114   private boolean permitKeepAliveWithoutCalls;
115   private long permitKeepAliveTimeInNanos = TimeUnit.MINUTES.toNanos(5);
116   private Attributes eagAttributes = Attributes.EMPTY;
117 
118   /**
119    * Creates a server builder that will bind to the given port.
120    *
121    * @param port the port on which the server is to be bound.
122    * @return the server builder.
123    */
forPort(int port)124   public static NettyServerBuilder forPort(int port) {
125     return forAddress(new InetSocketAddress(port));
126   }
127 
128   /**
129    * Creates a server builder that will bind to the given port.
130    *
131    * @param port the port on which the server is to be bound.
132    * @return the server builder.
133    */
forPort(int port, ServerCredentials creds)134   public static NettyServerBuilder forPort(int port, ServerCredentials creds) {
135     return forAddress(new InetSocketAddress(port), creds);
136   }
137 
138   /**
139    * Creates a server builder configured with the given {@link SocketAddress}.
140    *
141    * @param address the socket address on which the server is to be bound.
142    * @return the server builder
143    */
forAddress(SocketAddress address)144   public static NettyServerBuilder forAddress(SocketAddress address) {
145     return new NettyServerBuilder(address);
146   }
147 
148   /**
149    * Creates a server builder configured with the given {@link SocketAddress}.
150    *
151    * @param address the socket address on which the server is to be bound.
152    * @return the server builder
153    */
forAddress(SocketAddress address, ServerCredentials creds)154   public static NettyServerBuilder forAddress(SocketAddress address, ServerCredentials creds) {
155     ProtocolNegotiators.FromServerCredentialsResult result = ProtocolNegotiators.from(creds);
156     if (result.error != null) {
157       throw new IllegalArgumentException(result.error);
158     }
159     return new NettyServerBuilder(address, result.negotiator);
160   }
161 
162   private final class NettyClientTransportServersBuilder implements ClientTransportServersBuilder {
163     @Override
buildClientTransportServers( List<? extends ServerStreamTracer.Factory> streamTracerFactories)164     public InternalServer buildClientTransportServers(
165         List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
166       return buildTransportServers(streamTracerFactories);
167     }
168   }
169 
NettyServerBuilder(SocketAddress address)170   private NettyServerBuilder(SocketAddress address) {
171     serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
172     this.listenAddresses.add(address);
173     this.protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
174     this.freezeProtocolNegotiatorFactory = false;
175   }
176 
NettyServerBuilder(SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory)177   NettyServerBuilder(SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory) {
178     serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
179     this.listenAddresses.add(address);
180     this.protocolNegotiatorFactory = checkNotNull(negotiatorFactory, "negotiatorFactory");
181     this.freezeProtocolNegotiatorFactory = true;
182   }
183 
184   @Internal
185   @Override
delegate()186   protected ServerBuilder<?> delegate() {
187     return serverImplBuilder;
188   }
189 
190   /**
191    * Adds an additional address for this server to listen on.  Callers must ensure that all socket
192    * addresses are compatible with the Netty channel type, and that they don't conflict with each
193    * other.
194    */
195   @CanIgnoreReturnValue
addListenAddress(SocketAddress listenAddress)196   public NettyServerBuilder addListenAddress(SocketAddress listenAddress) {
197     this.listenAddresses.add(checkNotNull(listenAddress, "listenAddress"));
198     return this;
199   }
200 
201   /**
202    * Specifies the channel type to use, by default we use {@code EpollServerSocketChannel} if
203    * available, otherwise using {@link NioServerSocketChannel}.
204    *
205    * <p>You either use this or {@link #channelFactory(io.netty.channel.ChannelFactory)} if your
206    * {@link ServerChannel} implementation has no no-args constructor.
207    *
208    * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory
209    * when the channel is built, the builder will use the default one which is static.
210    *
211    * <p>You must also provide corresponding {@link EventLoopGroup} using {@link
212    * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For
213    * example, {@link NioServerSocketChannel} must use {@link
214    * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start.
215    */
216   @CanIgnoreReturnValue
channelType(Class<? extends ServerChannel> channelType)217   public NettyServerBuilder channelType(Class<? extends ServerChannel> channelType) {
218     checkNotNull(channelType, "channelType");
219     return channelFactory(new ReflectiveChannelFactory<>(channelType));
220   }
221 
222   /**
223    * Specifies the {@link ChannelFactory} to create {@link ServerChannel} instances. This method is
224    * usually only used if the specific {@code ServerChannel} requires complex logic which requires
225    * additional information to create the {@code ServerChannel}. Otherwise, recommend to use {@link
226    * #channelType(Class)}.
227    *
228    * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory
229    * when the channel is built, the builder will use the default one which is static.
230    *
231    * <p>You must also provide corresponding {@link EventLoopGroup} using {@link
232    * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For
233    * example, if the factory creates {@link NioServerSocketChannel} you must use {@link
234    * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start.
235    */
236   @CanIgnoreReturnValue
channelFactory(ChannelFactory<? extends ServerChannel> channelFactory)237   public NettyServerBuilder channelFactory(ChannelFactory<? extends ServerChannel> channelFactory) {
238     this.channelFactory = checkNotNull(channelFactory, "channelFactory");
239     return this;
240   }
241 
242   /**
243    * Specifies a channel option. As the underlying channel as well as network implementation may
244    * ignore this value applications should consider it a hint.
245    *
246    * @since 1.30.0
247    */
248   @CanIgnoreReturnValue
withOption(ChannelOption<T> option, T value)249   public <T> NettyServerBuilder withOption(ChannelOption<T> option, T value) {
250     this.channelOptions.put(option, value);
251     return this;
252   }
253 
254   /**
255    * Specifies a child channel option. As the underlying channel as well as network implementation
256    * may ignore this value applications should consider it a hint.
257    *
258    * @since 1.9.0
259    */
260   @CanIgnoreReturnValue
withChildOption(ChannelOption<T> option, T value)261   public <T> NettyServerBuilder withChildOption(ChannelOption<T> option, T value) {
262     this.childChannelOptions.put(option, value);
263     return this;
264   }
265 
266   /**
267    * Provides the boss EventGroupLoop to the server.
268    *
269    * <p>It's an optional parameter. If the user has not provided one when the server is built, the
270    * builder will use the default one which is static.
271    *
272    * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link
273    * #channelType(Class)} and {@link #workerEventLoopGroup(EventLoopGroup)}. For example, {@link
274    * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss
275    * and worker {@link EventLoopGroup}, otherwise your server won't start.
276    *
277    * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
278    * to shut it down when it's desired.
279    *
280    * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
281    * continue to run even after the main thread has terminated. However, users have to be cautious
282    * when providing their own {@link EventLoopGroup}s.
283    * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
284    * and thus an application with only daemon threads running besides the main thread will exit as
285    * soon as the main thread completes.
286    * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
287    * keep the main thread alive until the server has terminated.
288    */
289   @CanIgnoreReturnValue
bossEventLoopGroup(EventLoopGroup group)290   public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) {
291     if (group != null) {
292       return bossEventLoopGroupPool(new FixedObjectPool<>(group));
293     }
294     return bossEventLoopGroupPool(DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL);
295   }
296 
297   @CanIgnoreReturnValue
bossEventLoopGroupPool( ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool)298   NettyServerBuilder bossEventLoopGroupPool(
299       ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool) {
300     this.bossEventLoopGroupPool = checkNotNull(bossEventLoopGroupPool, "bossEventLoopGroupPool");
301     return this;
302   }
303 
304   /**
305    * Provides the worker EventGroupLoop to the server.
306    *
307    * <p>It's an optional parameter. If the user has not provided one when the server is built, the
308    * builder will create one.
309    *
310    * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link
311    * #channelType(Class)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For example, {@link
312    * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss
313    * and worker {@link EventLoopGroup}, otherwise your server won't start.
314    *
315    * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
316    * to shut it down when it's desired.
317    *
318    * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
319    * continue to run even after the main thread has terminated. However, users have to be cautious
320    * when providing their own {@link EventLoopGroup}s.
321    * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
322    * and thus an application with only daemon threads running besides the main thread will exit as
323    * soon as the main thread completes.
324    * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
325    * keep the main thread alive until the server has terminated.
326    */
327   @CanIgnoreReturnValue
workerEventLoopGroup(EventLoopGroup group)328   public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) {
329     if (group != null) {
330       return workerEventLoopGroupPool(new FixedObjectPool<>(group));
331     }
332     return workerEventLoopGroupPool(DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL);
333   }
334 
335   @CanIgnoreReturnValue
workerEventLoopGroupPool( ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool)336   NettyServerBuilder workerEventLoopGroupPool(
337       ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool) {
338     this.workerEventLoopGroupPool =
339         checkNotNull(workerEventLoopGroupPool, "workerEventLoopGroupPool");
340     return this;
341   }
342 
343   /**
344    * Force using heap buffer when custom allocator is enabled.
345    */
setForceHeapBuffer(boolean value)346   void setForceHeapBuffer(boolean value) {
347     forceHeapBuffer = value;
348   }
349 
350   /**
351    * Sets the TLS context to use for encryption. Providing a context enables encryption. It must
352    * have been configured with {@link GrpcSslContexts}, but options could have been overridden.
353    */
354   @CanIgnoreReturnValue
sslContext(SslContext sslContext)355   public NettyServerBuilder sslContext(SslContext sslContext) {
356     checkState(!freezeProtocolNegotiatorFactory,
357                "Cannot change security when using ServerCredentials");
358     if (sslContext != null) {
359       checkArgument(sslContext.isServer(),
360           "Client SSL context can not be used for server");
361       GrpcSslContexts.ensureAlpnAndH2Enabled(sslContext.applicationProtocolNegotiator());
362       protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
363     } else {
364       protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
365     }
366     return this;
367   }
368 
369   /**
370    * Sets the {@link ProtocolNegotiator} to be used. Overrides the value specified in {@link
371    * #sslContext(SslContext)}.
372    */
373   @CanIgnoreReturnValue
374   @Internal
protocolNegotiator(ProtocolNegotiator protocolNegotiator)375   public final NettyServerBuilder protocolNegotiator(ProtocolNegotiator protocolNegotiator) {
376     checkState(!freezeProtocolNegotiatorFactory,
377                "Cannot change security when using ServerCredentials");
378     this.protocolNegotiatorFactory = ProtocolNegotiators.fixedServerFactory(protocolNegotiator);
379     return this;
380   }
381 
setTracingEnabled(boolean value)382   void setTracingEnabled(boolean value) {
383     this.serverImplBuilder.setTracingEnabled(value);
384   }
385 
setStatsEnabled(boolean value)386   void setStatsEnabled(boolean value) {
387     this.serverImplBuilder.setStatsEnabled(value);
388   }
389 
setStatsRecordStartedRpcs(boolean value)390   void setStatsRecordStartedRpcs(boolean value) {
391     this.serverImplBuilder.setStatsRecordStartedRpcs(value);
392   }
393 
setStatsRecordRealTimeMetrics(boolean value)394   void setStatsRecordRealTimeMetrics(boolean value) {
395     this.serverImplBuilder.setStatsRecordRealTimeMetrics(value);
396   }
397 
398   /**
399    * The maximum number of concurrent calls permitted for each incoming connection. Defaults to no
400    * limit.
401    */
402   @CanIgnoreReturnValue
maxConcurrentCallsPerConnection(int maxCalls)403   public NettyServerBuilder maxConcurrentCallsPerConnection(int maxCalls) {
404     checkArgument(maxCalls > 0, "max must be positive: %s", maxCalls);
405     this.maxConcurrentCallsPerConnection = maxCalls;
406     return this;
407   }
408 
409   /**
410    * Sets the initial flow control window in bytes. Setting initial flow control window enables auto
411    * flow control tuning using bandwidth-delay product algorithm. To disable auto flow control
412    * tuning, use {@link #flowControlWindow(int)}. By default, auto flow control is enabled with
413    * initial flow control window size of {@link #DEFAULT_FLOW_CONTROL_WINDOW}.
414    */
415   @CanIgnoreReturnValue
initialFlowControlWindow(int initialFlowControlWindow)416   public NettyServerBuilder initialFlowControlWindow(int initialFlowControlWindow) {
417     checkArgument(initialFlowControlWindow > 0, "initialFlowControlWindow must be positive");
418     this.flowControlWindow = initialFlowControlWindow;
419     this.autoFlowControl = true;
420     return this;
421   }
422 
423   /**
424    * Sets the flow control window in bytes. Setting flowControlWindow disables auto flow control
425    * tuning; use {@link #initialFlowControlWindow(int)} to enable auto flow control tuning. If not
426    * called, the default value is {@link #DEFAULT_FLOW_CONTROL_WINDOW}) with auto flow control
427    * tuning.
428    */
429   @CanIgnoreReturnValue
flowControlWindow(int flowControlWindow)430   public NettyServerBuilder flowControlWindow(int flowControlWindow) {
431     checkArgument(flowControlWindow > 0, "flowControlWindow must be positive: %s",
432         flowControlWindow);
433     this.flowControlWindow = flowControlWindow;
434     this.autoFlowControl = false;
435     return this;
436   }
437 
438   /**
439    * Sets the maximum message size allowed to be received on the server. If not called,
440    * defaults to 4 MiB. The default provides protection to services who haven't considered the
441    * possibility of receiving large messages while trying to be large enough to not be hit in normal
442    * usage.
443    *
444    * @deprecated Call {@link #maxInboundMessageSize} instead. This method will be removed in a
445    *     future release.
446    */
447   @CanIgnoreReturnValue
448   @Deprecated
449   @InlineMe(replacement = "this.maxInboundMessageSize(maxMessageSize)")
maxMessageSize(int maxMessageSize)450   public NettyServerBuilder maxMessageSize(int maxMessageSize) {
451     return maxInboundMessageSize(maxMessageSize);
452   }
453 
454   /** {@inheritDoc} */
455   @CanIgnoreReturnValue
456   @Override
maxInboundMessageSize(int bytes)457   public NettyServerBuilder maxInboundMessageSize(int bytes) {
458     checkArgument(bytes >= 0, "bytes must be non-negative: %s", bytes);
459     this.maxMessageSize = bytes;
460     return this;
461   }
462 
463   /**
464    * Sets the maximum size of header list allowed to be received. This is cumulative size of the
465    * headers with some overhead, as defined for
466    * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2">
467    * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB.
468    *
469    * @deprecated Use {@link #maxInboundMetadataSize} instead
470    */
471   @CanIgnoreReturnValue
472   @Deprecated
473   @InlineMe(replacement = "this.maxInboundMetadataSize(maxHeaderListSize)")
maxHeaderListSize(int maxHeaderListSize)474   public NettyServerBuilder maxHeaderListSize(int maxHeaderListSize) {
475     return maxInboundMetadataSize(maxHeaderListSize);
476   }
477 
478   /**
479    * Sets the maximum size of metadata allowed to be received. This is cumulative size of the
480    * entries with some overhead, as defined for
481    * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2">
482    * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB.
483    *
484    * @param bytes the maximum size of received metadata
485    * @return this
486    * @throws IllegalArgumentException if bytes is non-positive
487    * @since 1.17.0
488    */
489   @CanIgnoreReturnValue
490   @Override
maxInboundMetadataSize(int bytes)491   public NettyServerBuilder maxInboundMetadataSize(int bytes) {
492     checkArgument(bytes > 0, "maxInboundMetadataSize must be positive: %s", bytes);
493     this.maxHeaderListSize = bytes;
494     return this;
495   }
496 
497   /**
498    * Sets a custom keepalive time, the delay time for sending next keepalive ping. An unreasonably
499    * small value might be increased, and {@code Long.MAX_VALUE} nano seconds or an unreasonably
500    * large value will disable keepalive.
501    *
502    * @since 1.3.0
503    */
504   @CanIgnoreReturnValue
505   @Override
keepAliveTime(long keepAliveTime, TimeUnit timeUnit)506   public NettyServerBuilder keepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
507     checkArgument(keepAliveTime > 0L, "keepalive time must be positive:%s", keepAliveTime);
508     keepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime);
509     keepAliveTimeInNanos = KeepAliveManager.clampKeepAliveTimeInNanos(keepAliveTimeInNanos);
510     if (keepAliveTimeInNanos >= AS_LARGE_AS_INFINITE) {
511       // Bump keepalive time to infinite. This disables keep alive.
512       keepAliveTimeInNanos = SERVER_KEEPALIVE_TIME_NANOS_DISABLED;
513     }
514     if (keepAliveTimeInNanos < MIN_KEEPALIVE_TIME_NANO) {
515       // Bump keepalive time.
516       keepAliveTimeInNanos = MIN_KEEPALIVE_TIME_NANO;
517     }
518     return this;
519   }
520 
521   /**
522    * Sets a custom keepalive timeout, the timeout for keepalive ping requests. An unreasonably small
523    * value might be increased.
524    *
525    * @since 1.3.0
526    */
527   @CanIgnoreReturnValue
528   @Override
keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit)529   public NettyServerBuilder keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit) {
530     checkArgument(keepAliveTimeout > 0L, "keepalive timeout must be positive: %s",
531         keepAliveTimeout);
532     keepAliveTimeoutInNanos = timeUnit.toNanos(keepAliveTimeout);
533     keepAliveTimeoutInNanos =
534         KeepAliveManager.clampKeepAliveTimeoutInNanos(keepAliveTimeoutInNanos);
535     if (keepAliveTimeoutInNanos < MIN_KEEPALIVE_TIMEOUT_NANO) {
536       // Bump keepalive timeout.
537       keepAliveTimeoutInNanos = MIN_KEEPALIVE_TIMEOUT_NANO;
538     }
539     return this;
540   }
541 
542   /**
543    * Sets a custom max connection idle time, connection being idle for longer than which will be
544    * gracefully terminated. Idleness duration is defined since the most recent time the number of
545    * outstanding RPCs became zero or the connection establishment. An unreasonably small value might
546    * be increased. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable
547    * max connection idle.
548    *
549    * @since 1.4.0
550    */
551   @CanIgnoreReturnValue
552   @Override
maxConnectionIdle(long maxConnectionIdle, TimeUnit timeUnit)553   public NettyServerBuilder maxConnectionIdle(long maxConnectionIdle, TimeUnit timeUnit) {
554     checkArgument(maxConnectionIdle > 0L, "max connection idle must be positive: %s",
555         maxConnectionIdle);
556     maxConnectionIdleInNanos = timeUnit.toNanos(maxConnectionIdle);
557     if (maxConnectionIdleInNanos >= AS_LARGE_AS_INFINITE) {
558       maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED;
559     }
560     if (maxConnectionIdleInNanos < MIN_MAX_CONNECTION_IDLE_NANO) {
561       maxConnectionIdleInNanos = MIN_MAX_CONNECTION_IDLE_NANO;
562     }
563     return this;
564   }
565 
566   /**
567    * Sets a custom max connection age, connection lasting longer than which will be gracefully
568    * terminated. An unreasonably small value might be increased.  A random jitter of +/-10% will be
569    * added to it. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable
570    * max connection age.
571    *
572    * @since 1.3.0
573    */
574   @CanIgnoreReturnValue
575   @Override
maxConnectionAge(long maxConnectionAge, TimeUnit timeUnit)576   public NettyServerBuilder maxConnectionAge(long maxConnectionAge, TimeUnit timeUnit) {
577     checkArgument(maxConnectionAge > 0L, "max connection age must be positive: %s",
578         maxConnectionAge);
579     maxConnectionAgeInNanos = timeUnit.toNanos(maxConnectionAge);
580     if (maxConnectionAgeInNanos >= AS_LARGE_AS_INFINITE) {
581       maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED;
582     }
583     if (maxConnectionAgeInNanos < MIN_MAX_CONNECTION_AGE_NANO) {
584       maxConnectionAgeInNanos = MIN_MAX_CONNECTION_AGE_NANO;
585     }
586     return this;
587   }
588 
589   /**
590    * Sets a custom grace time for the graceful connection termination. Once the max connection age
591    * is reached, RPCs have the grace time to complete. RPCs that do not complete in time will be
592    * cancelled, allowing the connection to terminate. {@code Long.MAX_VALUE} nano seconds or an
593    * unreasonably large value are considered infinite.
594    *
595    * @see #maxConnectionAge(long, TimeUnit)
596    * @since 1.3.0
597    */
598   @CanIgnoreReturnValue
599   @Override
maxConnectionAgeGrace(long maxConnectionAgeGrace, TimeUnit timeUnit)600   public NettyServerBuilder maxConnectionAgeGrace(long maxConnectionAgeGrace, TimeUnit timeUnit) {
601     checkArgument(maxConnectionAgeGrace >= 0L, "max connection age grace must be non-negative: %s",
602         maxConnectionAgeGrace);
603     maxConnectionAgeGraceInNanos = timeUnit.toNanos(maxConnectionAgeGrace);
604     if (maxConnectionAgeGraceInNanos >= AS_LARGE_AS_INFINITE) {
605       maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE;
606     }
607     return this;
608   }
609 
610   /**
611    * Specify the most aggressive keep-alive time clients are permitted to configure. The server will
612    * try to detect clients exceeding this rate and when detected will forcefully close the
613    * connection. The default is 5 minutes.
614    *
615    * <p>Even though a default is defined that allows some keep-alives, clients must not use
616    * keep-alive without approval from the service owner. Otherwise, they may experience failures in
617    * the future if the service becomes more restrictive. When unthrottled, keep-alives can cause a
618    * significant amount of traffic and CPU usage, so clients and servers should be conservative in
619    * what they use and accept.
620    *
621    * @see #permitKeepAliveWithoutCalls(boolean)
622    * @since 1.3.0
623    */
624   @CanIgnoreReturnValue
625   @Override
permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit)626   public NettyServerBuilder permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
627     checkArgument(keepAliveTime >= 0, "permit keepalive time must be non-negative: %s",
628         keepAliveTime);
629     permitKeepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime);
630     return this;
631   }
632 
633   /**
634    * Sets whether to allow clients to send keep-alive HTTP/2 PINGs even if there are no outstanding
635    * RPCs on the connection. Defaults to {@code false}.
636    *
637    * @see #permitKeepAliveTime(long, TimeUnit)
638    * @since 1.3.0
639    */
640   @CanIgnoreReturnValue
641   @Override
permitKeepAliveWithoutCalls(boolean permit)642   public NettyServerBuilder permitKeepAliveWithoutCalls(boolean permit) {
643     permitKeepAliveWithoutCalls = permit;
644     return this;
645   }
646 
647   /** Sets the EAG attributes available to protocol negotiators. Not for general use. */
eagAttributes(Attributes eagAttributes)648   void eagAttributes(Attributes eagAttributes) {
649     this.eagAttributes = checkNotNull(eagAttributes, "eagAttributes");
650   }
651 
buildTransportServers( List<? extends ServerStreamTracer.Factory> streamTracerFactories)652   NettyServer buildTransportServers(
653       List<? extends ServerStreamTracer.Factory> streamTracerFactories) {
654     assertEventLoopsAndChannelType();
655 
656     ProtocolNegotiator negotiator = protocolNegotiatorFactory.newNegotiator(
657         this.serverImplBuilder.getExecutorPool());
658 
659     return new NettyServer(
660         listenAddresses, channelFactory, channelOptions, childChannelOptions,
661         bossEventLoopGroupPool, workerEventLoopGroupPool, forceHeapBuffer, negotiator,
662         streamTracerFactories, transportTracerFactory, maxConcurrentCallsPerConnection,
663         autoFlowControl, flowControlWindow, maxMessageSize, maxHeaderListSize,
664         keepAliveTimeInNanos, keepAliveTimeoutInNanos,
665         maxConnectionIdleInNanos, maxConnectionAgeInNanos,
666         maxConnectionAgeGraceInNanos, permitKeepAliveWithoutCalls, permitKeepAliveTimeInNanos,
667         eagAttributes, this.serverImplBuilder.getChannelz());
668   }
669 
670   @VisibleForTesting
assertEventLoopsAndChannelType()671   void assertEventLoopsAndChannelType() {
672     boolean allProvided = channelFactory != Utils.DEFAULT_SERVER_CHANNEL_FACTORY
673         && bossEventLoopGroupPool != DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
674         && workerEventLoopGroupPool != DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
675     boolean nonProvided = channelFactory == Utils.DEFAULT_SERVER_CHANNEL_FACTORY
676         && bossEventLoopGroupPool == DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
677         && workerEventLoopGroupPool == DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
678     checkState(
679         allProvided || nonProvided,
680         "All of BossEventLoopGroup, WorkerEventLoopGroup and ChannelType should be provided or "
681             + "neither should be");
682   }
683 
684   @CanIgnoreReturnValue
setTransportTracerFactory(TransportTracer.Factory transportTracerFactory)685   NettyServerBuilder setTransportTracerFactory(TransportTracer.Factory transportTracerFactory) {
686     this.transportTracerFactory = transportTracerFactory;
687     return this;
688   }
689 
690   @CanIgnoreReturnValue
691   @Override
useTransportSecurity(File certChain, File privateKey)692   public NettyServerBuilder useTransportSecurity(File certChain, File privateKey) {
693     checkState(!freezeProtocolNegotiatorFactory,
694                "Cannot change security when using ServerCredentials");
695     SslContext sslContext;
696     try {
697       sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
698     } catch (SSLException e) {
699       // This should likely be some other, easier to catch exception.
700       throw new RuntimeException(e);
701     }
702     protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
703     return this;
704   }
705 
706   @CanIgnoreReturnValue
707   @Override
useTransportSecurity(InputStream certChain, InputStream privateKey)708   public NettyServerBuilder useTransportSecurity(InputStream certChain, InputStream privateKey) {
709     checkState(!freezeProtocolNegotiatorFactory,
710                "Cannot change security when using ServerCredentials");
711     SslContext sslContext;
712     try {
713       sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
714     } catch (SSLException e) {
715       // This should likely be some other, easier to catch exception.
716       throw new RuntimeException(e);
717     }
718     protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
719     return this;
720   }
721 }
722