• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20268

06 May 2026 08:58PM UTC coverage: 88.822% (-0.01%) from 88.836%
#20268

push

github

web-flow
compiler: Avoid compile error on weird proto file names

This only matters when `@generated=javax` is used, so it shouldn't
matter much.

It isn't guaranteed that javac will interpret the file as UTF-8, but it
is exceedingly common, and it doesn't seem too much to ask if you are
using weird file names.

36154 of 40704 relevant lines covered (88.82%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.61
/../netty/src/main/java/io/grpc/netty/NettyServerBuilder.java
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.DEFAULT_SERVER_PERMIT_KEEPALIVE_TIME_NANOS;
26
import static io.grpc.internal.GrpcUtil.SERVER_KEEPALIVE_TIME_NANOS_DISABLED;
27

28
import com.google.common.annotations.VisibleForTesting;
29
import com.google.errorprone.annotations.CanIgnoreReturnValue;
30
import com.google.errorprone.annotations.CheckReturnValue;
31
import com.google.errorprone.annotations.InlineMe;
32
import io.grpc.Attributes;
33
import io.grpc.ExperimentalApi;
34
import io.grpc.ForwardingServerBuilder;
35
import io.grpc.Internal;
36
import io.grpc.MetricRecorder;
37
import io.grpc.ServerBuilder;
38
import io.grpc.ServerCredentials;
39
import io.grpc.ServerStreamTracer;
40
import io.grpc.internal.FixedObjectPool;
41
import io.grpc.internal.GrpcUtil;
42
import io.grpc.internal.InternalServer;
43
import io.grpc.internal.KeepAliveManager;
44
import io.grpc.internal.ObjectPool;
45
import io.grpc.internal.ServerImplBuilder;
46
import io.grpc.internal.ServerImplBuilder.ClientTransportServersBuilder;
47
import io.grpc.internal.SharedResourcePool;
48
import io.grpc.internal.TransportTracer;
49
import io.netty.channel.ChannelFactory;
50
import io.netty.channel.ChannelOption;
51
import io.netty.channel.EventLoopGroup;
52
import io.netty.channel.ReflectiveChannelFactory;
53
import io.netty.channel.ServerChannel;
54
import io.netty.channel.socket.nio.NioServerSocketChannel;
55
import io.netty.handler.ssl.SslContext;
56
import java.io.File;
57
import java.io.InputStream;
58
import java.net.InetSocketAddress;
59
import java.net.SocketAddress;
60
import java.util.ArrayList;
61
import java.util.HashMap;
62
import java.util.List;
63
import java.util.Map;
64
import java.util.concurrent.TimeUnit;
65
import javax.net.ssl.SSLException;
66

67
/**
68
 * A builder to help simplify the construction of a Netty-based GRPC server.
69
 */
70
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784")
71
@CheckReturnValue
72
public final class NettyServerBuilder extends ForwardingServerBuilder<NettyServerBuilder> {
73

74
  // 1MiB
75
  public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1024 * 1024;
76

77
  static final long MAX_CONNECTION_IDLE_NANOS_DISABLED = Long.MAX_VALUE;
78
  static final long MAX_CONNECTION_AGE_NANOS_DISABLED = Long.MAX_VALUE;
79
  static final long MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE = Long.MAX_VALUE;
80
  static final int MAX_RST_COUNT_DISABLED = 0;
81

82
  private static final long MIN_MAX_CONNECTION_IDLE_NANO = TimeUnit.SECONDS.toNanos(1L);
1✔
83
  private static final long MIN_MAX_CONNECTION_AGE_NANO = TimeUnit.SECONDS.toNanos(1L);
1✔
84
  private static final long AS_LARGE_AS_INFINITE = TimeUnit.DAYS.toNanos(1000L);
1✔
85
  private static final ObjectPool<? extends EventLoopGroup> DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL =
1✔
86
      SharedResourcePool.forResource(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP);
1✔
87
  private static final ObjectPool<? extends EventLoopGroup> DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL =
1✔
88
      SharedResourcePool.forResource(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP);
1✔
89

90
  private final ServerImplBuilder serverImplBuilder;
91
  private final List<SocketAddress> listenAddresses = new ArrayList<>();
1✔
92

93
  private TransportTracer.Factory transportTracerFactory = TransportTracer.getDefaultFactory();
1✔
94
  private ChannelFactory<? extends ServerChannel> channelFactory =
1✔
95
      Utils.DEFAULT_SERVER_CHANNEL_FACTORY;
96
  private final Map<ChannelOption<?>, Object> channelOptions = new HashMap<>();
1✔
97
  private final Map<ChannelOption<?>, Object> childChannelOptions = new HashMap<>();
1✔
98
  private ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool =
1✔
99
      DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL;
100
  private ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool =
1✔
101
      DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
102
  private boolean forceHeapBuffer;
103
  private ProtocolNegotiator.ServerFactory protocolNegotiatorFactory;
104
  private final boolean freezeProtocolNegotiatorFactory;
105
  private int maxConcurrentCallsPerConnection = Integer.MAX_VALUE;
1✔
106
  private boolean autoFlowControl = true;
1✔
107
  private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
1✔
108
  private int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE;
1✔
109
  private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
1✔
110
  private int softLimitHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
1✔
111
  private long keepAliveTimeInNanos = DEFAULT_SERVER_KEEPALIVE_TIME_NANOS;
1✔
112
  private long keepAliveTimeoutInNanos = DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS;
1✔
113
  private long maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED;
1✔
114
  private long maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED;
1✔
115
  private long maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE;
1✔
116
  private boolean permitKeepAliveWithoutCalls;
117
  private long permitKeepAliveTimeInNanos = DEFAULT_SERVER_PERMIT_KEEPALIVE_TIME_NANOS;
1✔
118
  private int maxRstCount;
119
  private long maxRstPeriodNanos;
120
  private Attributes eagAttributes = Attributes.EMPTY;
1✔
121

122
  /**
123
   * Creates a server builder that will bind to the given port.
124
   *
125
   * @param port the port on which the server is to be bound.
126
   * @return the server builder.
127
   */
128
  public static NettyServerBuilder forPort(int port) {
129
    return forAddress(new InetSocketAddress(port));
1✔
130
  }
131

132
  /**
133
   * Creates a server builder that will bind to the given port.
134
   *
135
   * @param port the port on which the server is to be bound.
136
   * @return the server builder.
137
   */
138
  public static NettyServerBuilder forPort(int port, ServerCredentials creds) {
139
    return forAddress(new InetSocketAddress(port), creds);
1✔
140
  }
141

142
  /**
143
   * Creates a server builder configured with the given {@link SocketAddress}.
144
   *
145
   * @param address the socket address on which the server is to be bound.
146
   * @return the server builder
147
   */
148
  public static NettyServerBuilder forAddress(SocketAddress address) {
149
    return new NettyServerBuilder(address);
1✔
150
  }
151

152
  /**
153
   * Creates a server builder configured with the given {@link SocketAddress}.
154
   *
155
   * @param address the socket address on which the server is to be bound.
156
   * @return the server builder
157
   */
158
  public static NettyServerBuilder forAddress(SocketAddress address, ServerCredentials creds) {
159
    ProtocolNegotiators.FromServerCredentialsResult result = ProtocolNegotiators.from(creds);
1✔
160
    if (result.error != null) {
1✔
161
      throw new IllegalArgumentException(result.error);
×
162
    }
163
    return new NettyServerBuilder(address, result.negotiator);
1✔
164
  }
165

166
  private final class NettyClientTransportServersBuilder implements ClientTransportServersBuilder {
1✔
167
    @Override
168
    public InternalServer buildClientTransportServers(
169
        List<? extends ServerStreamTracer.Factory> streamTracerFactories,
170
        MetricRecorder metricRecorder) {
171
      return buildTransportServers(streamTracerFactories, metricRecorder);
1✔
172
    }
173
  }
174

175
  private NettyServerBuilder(SocketAddress address) {
1✔
176
    serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
1✔
177
    this.listenAddresses.add(address);
1✔
178
    this.protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
1✔
179
    this.freezeProtocolNegotiatorFactory = false;
1✔
180
  }
1✔
181

182
  NettyServerBuilder(SocketAddress address, ProtocolNegotiator.ServerFactory negotiatorFactory) {
1✔
183
    serverImplBuilder = new ServerImplBuilder(new NettyClientTransportServersBuilder());
1✔
184
    this.listenAddresses.add(address);
1✔
185
    this.protocolNegotiatorFactory = checkNotNull(negotiatorFactory, "negotiatorFactory");
1✔
186
    this.freezeProtocolNegotiatorFactory = true;
1✔
187
  }
1✔
188

189
  @Internal
190
  @Override
191
  protected ServerBuilder<?> delegate() {
192
    return serverImplBuilder;
1✔
193
  }
194

195
  /**
196
   * Adds an additional address for this server to listen on.  Callers must ensure that all socket
197
   * addresses are compatible with the Netty channel type, and that they don't conflict with each
198
   * other.
199
   */
200
  @CanIgnoreReturnValue
201
  public NettyServerBuilder addListenAddress(SocketAddress listenAddress) {
202
    this.listenAddresses.add(checkNotNull(listenAddress, "listenAddress"));
1✔
203
    return this;
1✔
204
  }
205

206
  /**
207
   * Specifies the channel type to use, by default we use {@code EpollServerSocketChannel} if
208
   * available, otherwise using {@link NioServerSocketChannel}.
209
   *
210
   * <p>You either use this or {@link #channelFactory(io.netty.channel.ChannelFactory)} if your
211
   * {@link ServerChannel} implementation has no no-args constructor.
212
   *
213
   * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory
214
   * when the channel is built, the builder will use the default one which is static.
215
   *
216
   * <p>You must also provide corresponding {@link EventLoopGroup} using {@link
217
   * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For
218
   * example, {@link NioServerSocketChannel} must use {@link
219
   * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start.
220
   */
221
  @CanIgnoreReturnValue
222
  public NettyServerBuilder channelType(Class<? extends ServerChannel> channelType) {
223
    checkNotNull(channelType, "channelType");
1✔
224
    return channelFactory(new ReflectiveChannelFactory<>(channelType));
1✔
225
  }
226

227
  /**
228
   * Specifies the {@link ChannelFactory} to create {@link ServerChannel} instances. This method is
229
   * usually only used if the specific {@code ServerChannel} requires complex logic which requires
230
   * additional information to create the {@code ServerChannel}. Otherwise, recommend to use {@link
231
   * #channelType(Class)}.
232
   *
233
   * <p>It's an optional parameter. If the user has not provided an Channel type or ChannelFactory
234
   * when the channel is built, the builder will use the default one which is static.
235
   *
236
   * <p>You must also provide corresponding {@link EventLoopGroup} using {@link
237
   * #workerEventLoopGroup(EventLoopGroup)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For
238
   * example, if the factory creates {@link NioServerSocketChannel} you must use {@link
239
   * io.netty.channel.nio.NioEventLoopGroup}, otherwise your server won't start.
240
   */
241
  @CanIgnoreReturnValue
242
  public NettyServerBuilder channelFactory(ChannelFactory<? extends ServerChannel> channelFactory) {
243
    this.channelFactory = checkNotNull(channelFactory, "channelFactory");
1✔
244
    return this;
1✔
245
  }
246

247
  /**
248
   * Specifies a channel option. As the underlying channel as well as network implementation may
249
   * ignore this value applications should consider it a hint.
250
   *
251
   * @since 1.30.0
252
   */
253
  @CanIgnoreReturnValue
254
  public <T> NettyServerBuilder withOption(ChannelOption<T> option, T value) {
255
    this.channelOptions.put(option, value);
×
256
    return this;
×
257
  }
258

259
  /**
260
   * Specifies a child channel option. As the underlying channel as well as network implementation
261
   * may ignore this value applications should consider it a hint.
262
   *
263
   * @since 1.9.0
264
   */
265
  @CanIgnoreReturnValue
266
  public <T> NettyServerBuilder withChildOption(ChannelOption<T> option, T value) {
267
    this.childChannelOptions.put(option, value);
×
268
    return this;
×
269
  }
270

271
  /**
272
   * Provides the boss EventGroupLoop to the server.
273
   *
274
   * <p>It's an optional parameter. If the user has not provided one when the server is built, the
275
   * builder will use the default one which is static.
276
   *
277
   * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link
278
   * #channelType(Class)} and {@link #workerEventLoopGroup(EventLoopGroup)}. For example, {@link
279
   * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss
280
   * and worker {@link EventLoopGroup}, otherwise your server won't start.
281
   *
282
   * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
283
   * to shut it down when it's desired.
284
   *
285
   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
286
   * continue to run even after the main thread has terminated. However, users have to be cautious
287
   * when providing their own {@link EventLoopGroup}s.
288
   * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
289
   * and thus an application with only daemon threads running besides the main thread will exit as
290
   * soon as the main thread completes.
291
   * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
292
   * keep the main thread alive until the server has terminated.
293
   */
294
  @CanIgnoreReturnValue
295
  public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) {
296
    if (group != null) {
1✔
297
      return bossEventLoopGroupPool(new FixedObjectPool<>(group));
1✔
298
    }
299
    return bossEventLoopGroupPool(DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL);
×
300
  }
301

302
  @CanIgnoreReturnValue
303
  NettyServerBuilder bossEventLoopGroupPool(
304
      ObjectPool<? extends EventLoopGroup> bossEventLoopGroupPool) {
305
    this.bossEventLoopGroupPool = checkNotNull(bossEventLoopGroupPool, "bossEventLoopGroupPool");
1✔
306
    return this;
1✔
307
  }
308

309
  /**
310
   * Provides the worker EventGroupLoop to the server.
311
   *
312
   * <p>It's an optional parameter. If the user has not provided one when the server is built, the
313
   * builder will create one.
314
   *
315
   * <p>You must also provide corresponding {@link io.netty.channel.Channel} type using {@link
316
   * #channelType(Class)} and {@link #bossEventLoopGroup(EventLoopGroup)}. For example, {@link
317
   * NioServerSocketChannel} must use {@link io.netty.channel.nio.NioEventLoopGroup} for both boss
318
   * and worker {@link EventLoopGroup}, otherwise your server won't start.
319
   *
320
   * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
321
   * to shut it down when it's desired.
322
   *
323
   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
324
   * continue to run even after the main thread has terminated. However, users have to be cautious
325
   * when providing their own {@link EventLoopGroup}s.
326
   * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
327
   * and thus an application with only daemon threads running besides the main thread will exit as
328
   * soon as the main thread completes.
329
   * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
330
   * keep the main thread alive until the server has terminated.
331
   */
332
  @CanIgnoreReturnValue
333
  public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) {
334
    if (group != null) {
1✔
335
      return workerEventLoopGroupPool(new FixedObjectPool<>(group));
1✔
336
    }
337
    return workerEventLoopGroupPool(DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL);
×
338
  }
339

340
  @CanIgnoreReturnValue
341
  NettyServerBuilder workerEventLoopGroupPool(
342
      ObjectPool<? extends EventLoopGroup> workerEventLoopGroupPool) {
343
    this.workerEventLoopGroupPool =
1✔
344
        checkNotNull(workerEventLoopGroupPool, "workerEventLoopGroupPool");
1✔
345
    return this;
1✔
346
  }
347

348
  /**
349
   * Force using heap buffer when custom allocator is enabled.
350
   */
351
  void setForceHeapBuffer(boolean value) {
352
    forceHeapBuffer = value;
×
353
  }
×
354

355
  /**
356
   * Sets the TLS context to use for encryption. Providing a context enables encryption. It must
357
   * have been configured with {@link GrpcSslContexts}, but options could have been overridden.
358
   */
359
  @CanIgnoreReturnValue
360
  public NettyServerBuilder sslContext(SslContext sslContext) {
361
    checkState(!freezeProtocolNegotiatorFactory,
1✔
362
               "Cannot change security when using ServerCredentials");
363
    if (sslContext != null) {
1✔
364
      checkArgument(sslContext.isServer(),
1✔
365
          "Client SSL context can not be used for server");
366
      GrpcSslContexts.ensureAlpnAndH2Enabled(sslContext.applicationProtocolNegotiator());
1✔
367
      protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
1✔
368
    } else {
369
      protocolNegotiatorFactory = ProtocolNegotiators.serverPlaintextFactory();
1✔
370
    }
371
    return this;
1✔
372
  }
373

374
  /**
375
   * Sets the {@link ProtocolNegotiator} to be used. Overrides the value specified in {@link
376
   * #sslContext(SslContext)}.
377
   */
378
  @CanIgnoreReturnValue
379
  @Internal
380
  public final NettyServerBuilder protocolNegotiator(ProtocolNegotiator protocolNegotiator) {
381
    checkState(!freezeProtocolNegotiatorFactory,
×
382
               "Cannot change security when using ServerCredentials");
383
    this.protocolNegotiatorFactory = ProtocolNegotiators.fixedServerFactory(protocolNegotiator);
×
384
    return this;
×
385
  }
386

387
  void setTracingEnabled(boolean value) {
388
    this.serverImplBuilder.setTracingEnabled(value);
×
389
  }
×
390

391
  void setStatsEnabled(boolean value) {
392
    this.serverImplBuilder.setStatsEnabled(value);
1✔
393
  }
1✔
394

395
  void setStatsRecordStartedRpcs(boolean value) {
396
    this.serverImplBuilder.setStatsRecordStartedRpcs(value);
×
397
  }
×
398

399
  void setStatsRecordRealTimeMetrics(boolean value) {
400
    this.serverImplBuilder.setStatsRecordRealTimeMetrics(value);
×
401
  }
×
402

403
  /**
404
   * The maximum number of concurrent calls permitted for each incoming connection. Defaults to no
405
   * limit.
406
   */
407
  @CanIgnoreReturnValue
408
  public NettyServerBuilder maxConcurrentCallsPerConnection(int maxCalls) {
409
    checkArgument(maxCalls > 0, "max must be positive: %s", maxCalls);
1✔
410
    this.maxConcurrentCallsPerConnection = maxCalls;
×
411
    return this;
×
412
  }
413

414
  /**
415
   * Sets the initial flow control window in bytes. Setting initial flow control window enables auto
416
   * flow control tuning using bandwidth-delay product algorithm. To disable auto flow control
417
   * tuning, use {@link #flowControlWindow(int)}. By default, auto flow control is enabled with
418
   * initial flow control window size of {@link #DEFAULT_FLOW_CONTROL_WINDOW}.
419
   */
420
  @CanIgnoreReturnValue
421
  public NettyServerBuilder initialFlowControlWindow(int initialFlowControlWindow) {
422
    checkArgument(initialFlowControlWindow > 0, "initialFlowControlWindow must be positive");
1✔
423
    this.flowControlWindow = initialFlowControlWindow;
1✔
424
    this.autoFlowControl = true;
1✔
425
    return this;
1✔
426
  }
427

428
  /**
429
   * Sets the flow control window in bytes. Setting flowControlWindow disables auto flow control
430
   * tuning; use {@link #initialFlowControlWindow(int)} to enable auto flow control tuning. If not
431
   * called, the default value is {@link #DEFAULT_FLOW_CONTROL_WINDOW}) with auto flow control
432
   * tuning.
433
   */
434
  @CanIgnoreReturnValue
435
  public NettyServerBuilder flowControlWindow(int flowControlWindow) {
436
    checkArgument(flowControlWindow > 0, "flowControlWindow must be positive: %s",
1✔
437
        flowControlWindow);
438
    this.flowControlWindow = flowControlWindow;
1✔
439
    this.autoFlowControl = false;
1✔
440
    return this;
1✔
441
  }
442

443
  /**
444
   * Sets the maximum message size allowed to be received on the server. If not called,
445
   * defaults to 4 MiB. The default provides protection to services who haven't considered the
446
   * possibility of receiving large messages while trying to be large enough to not be hit in normal
447
   * usage.
448
   *
449
   * @deprecated Call {@link #maxInboundMessageSize} instead. This method will be removed in a
450
   *     future release.
451
   */
452
  @CanIgnoreReturnValue
453
  @Deprecated
454
  @InlineMe(replacement = "this.maxInboundMessageSize(maxMessageSize)")
455
  public NettyServerBuilder maxMessageSize(int maxMessageSize) {
456
    return maxInboundMessageSize(maxMessageSize);
×
457
  }
458

459
  /** {@inheritDoc} */
460
  @CanIgnoreReturnValue
461
  @Override
462
  public NettyServerBuilder maxInboundMessageSize(int bytes) {
463
    checkArgument(bytes >= 0, "bytes must be non-negative: %s", bytes);
1✔
464
    this.maxMessageSize = bytes;
1✔
465
    return this;
1✔
466
  }
467

468
  /**
469
   * Sets the maximum size of header list allowed to be received. This is cumulative size of the
470
   * headers with some overhead, as defined for
471
   * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2">
472
   * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB.
473
   *
474
   * @deprecated Use {@link #maxInboundMetadataSize} instead
475
   */
476
  @CanIgnoreReturnValue
477
  @Deprecated
478
  @InlineMe(replacement = "this.maxInboundMetadataSize(maxHeaderListSize)")
479
  public NettyServerBuilder maxHeaderListSize(int maxHeaderListSize) {
480
    return maxInboundMetadataSize(maxHeaderListSize);
×
481
  }
482

483
  /**
484
   * Sets the maximum size of metadata allowed to be received. This is cumulative size of the
485
   * entries with some overhead, as defined for
486
   * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2">
487
   * HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE</a>. The default is 8 KiB.
488
   *
489
   * @param bytes the maximum size of received metadata
490
   * @return this
491
   * @throws IllegalArgumentException if bytes is non-positive
492
   * @since 1.17.0
493
   */
494
  @CanIgnoreReturnValue
495
  @Override
496
  public NettyServerBuilder maxInboundMetadataSize(int bytes) {
497
    checkArgument(bytes > 0, "maxInboundMetadataSize must be positive: %s", bytes);
1✔
498
    this.maxHeaderListSize = bytes;
×
499
    // Clear the soft limit setting, by setting soft limit to maxInboundMetadataSize. The
500
    // maxInboundMetadataSize will take precedence over soft limit check.
501
    this.softLimitHeaderListSize = bytes;
×
502
    return this;
×
503
  }
504

505
  /**
506
   * Sets the size of metadata that clients are advised to not exceed. When a metadata with size
507
   * larger than the soft limit is encountered there will be a probability the RPC will fail. The
508
   * chance of failing increases as the metadata size approaches the hard limit.
509
   * {@code Integer.MAX_VALUE} disables the enforcement. The default is implementation-dependent,
510
   * but is not generally less than 8 KiB and may be unlimited.
511
   *
512
   * <p>This is cumulative size of the metadata. The precise calculation is
513
   * implementation-dependent, but implementations are encouraged to follow the calculation used
514
   * for
515
   * <a href="http://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2">HTTP/2's
516
   * SETTINGS_MAX_HEADER_LIST_SIZE</a>. It sums the bytes from each entry's key and value, plus 32
517
   * bytes of overhead per entry.
518
   *
519
   * @param soft the soft size limit of received metadata
520
   * @param max the hard size limit of received metadata
521
   * @return this
522
   * @throws IllegalArgumentException if soft and/or max is non-positive, or max smaller than soft
523
   * @since 1.68.0
524
   */
525
  @CanIgnoreReturnValue
526
  public NettyServerBuilder maxInboundMetadataSize(int soft, int max) {
527
    checkArgument(soft > 0, "softLimitHeaderListSize must be positive: %s", soft);
1✔
528
    checkArgument(max > soft,
1✔
529
        "maxInboundMetadataSize: %s must be greater than softLimitHeaderListSize: %s", max, soft);
530
    this.softLimitHeaderListSize = soft;
×
531
    this.maxHeaderListSize = max;
×
532
    return this;
×
533
  }
534

535
  /**
536
   * Sets a custom keepalive time, the delay time for sending next keepalive ping. An unreasonably
537
   * small value might be increased, and {@code Long.MAX_VALUE} nano seconds or an unreasonably
538
   * large value will disable keepalive.
539
   *
540
   * @since 1.3.0
541
   */
542
  @CanIgnoreReturnValue
543
  @Override
544
  public NettyServerBuilder keepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
545
    checkArgument(keepAliveTime > 0L, "keepalive time must be positive:%s", keepAliveTime);
1✔
546
    keepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime);
×
547
    keepAliveTimeInNanos = KeepAliveManager.clampKeepAliveTimeInNanos(keepAliveTimeInNanos);
×
548
    if (keepAliveTimeInNanos >= AS_LARGE_AS_INFINITE) {
×
549
      // Bump keepalive time to infinite. This disables keep alive.
550
      keepAliveTimeInNanos = SERVER_KEEPALIVE_TIME_NANOS_DISABLED;
×
551
    }
552
    return this;
×
553
  }
554

555
  /**
556
   * Sets a custom keepalive timeout, the timeout for keepalive ping requests. An unreasonably small
557
   * value might be increased.
558
   *
559
   * @since 1.3.0
560
   */
561
  @CanIgnoreReturnValue
562
  @Override
563
  public NettyServerBuilder keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit) {
564
    checkArgument(keepAliveTimeout > 0L, "keepalive timeout must be positive: %s",
1✔
565
        keepAliveTimeout);
566
    keepAliveTimeoutInNanos = timeUnit.toNanos(keepAliveTimeout);
×
567
    keepAliveTimeoutInNanos =
×
568
        KeepAliveManager.clampKeepAliveTimeoutInNanos(keepAliveTimeoutInNanos);
×
569
    return this;
×
570
  }
571

572
  /**
573
   * Sets a custom max connection idle time, connection being idle for longer than which will be
574
   * gracefully terminated. Idleness duration is defined since the most recent time the number of
575
   * outstanding RPCs became zero or the connection establishment. An unreasonably small value might
576
   * be increased. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable
577
   * max connection idle.
578
   *
579
   * @since 1.4.0
580
   */
581
  @CanIgnoreReturnValue
582
  @Override
583
  public NettyServerBuilder maxConnectionIdle(long maxConnectionIdle, TimeUnit timeUnit) {
584
    checkArgument(maxConnectionIdle > 0L, "max connection idle must be positive: %s",
1✔
585
        maxConnectionIdle);
586
    maxConnectionIdleInNanos = timeUnit.toNanos(maxConnectionIdle);
×
587
    if (maxConnectionIdleInNanos >= AS_LARGE_AS_INFINITE) {
×
588
      maxConnectionIdleInNanos = MAX_CONNECTION_IDLE_NANOS_DISABLED;
×
589
    }
590
    if (maxConnectionIdleInNanos < MIN_MAX_CONNECTION_IDLE_NANO) {
×
591
      maxConnectionIdleInNanos = MIN_MAX_CONNECTION_IDLE_NANO;
×
592
    }
593
    return this;
×
594
  }
595

596
  /**
597
   * Sets a custom max connection age, connection lasting longer than which will be gracefully
598
   * terminated. An unreasonably small value might be increased.  A random jitter of +/-10% will be
599
   * added to it. {@code Long.MAX_VALUE} nano seconds or an unreasonably large value will disable
600
   * max connection age.
601
   *
602
   * @since 1.3.0
603
   */
604
  @CanIgnoreReturnValue
605
  @Override
606
  public NettyServerBuilder maxConnectionAge(long maxConnectionAge, TimeUnit timeUnit) {
607
    checkArgument(maxConnectionAge > 0L, "max connection age must be positive: %s",
1✔
608
        maxConnectionAge);
609
    maxConnectionAgeInNanos = timeUnit.toNanos(maxConnectionAge);
×
610
    if (maxConnectionAgeInNanos >= AS_LARGE_AS_INFINITE) {
×
611
      maxConnectionAgeInNanos = MAX_CONNECTION_AGE_NANOS_DISABLED;
×
612
    }
613
    if (maxConnectionAgeInNanos < MIN_MAX_CONNECTION_AGE_NANO) {
×
614
      maxConnectionAgeInNanos = MIN_MAX_CONNECTION_AGE_NANO;
×
615
    }
616
    return this;
×
617
  }
618

619
  /**
620
   * Sets a custom grace time for the graceful connection termination. Once the max connection age
621
   * is reached, RPCs have the grace time to complete. RPCs that do not complete in time will be
622
   * cancelled, allowing the connection to terminate. {@code Long.MAX_VALUE} nano seconds or an
623
   * unreasonably large value are considered infinite.
624
   *
625
   * @see #maxConnectionAge(long, TimeUnit)
626
   * @since 1.3.0
627
   */
628
  @CanIgnoreReturnValue
629
  @Override
630
  public NettyServerBuilder maxConnectionAgeGrace(long maxConnectionAgeGrace, TimeUnit timeUnit) {
631
    checkArgument(maxConnectionAgeGrace >= 0L, "max connection age grace must be non-negative: %s",
1✔
632
        maxConnectionAgeGrace);
633
    maxConnectionAgeGraceInNanos = timeUnit.toNanos(maxConnectionAgeGrace);
×
634
    if (maxConnectionAgeGraceInNanos >= AS_LARGE_AS_INFINITE) {
×
635
      maxConnectionAgeGraceInNanos = MAX_CONNECTION_AGE_GRACE_NANOS_INFINITE;
×
636
    }
637
    return this;
×
638
  }
639

640
  /**
641
   * Specify the most aggressive keep-alive time clients are permitted to configure. The server will
642
   * try to detect clients exceeding this rate and when detected will forcefully close the
643
   * connection. The default is 5 minutes.
644
   *
645
   * <p>Even though a default is defined that allows some keep-alives, clients must not use
646
   * keep-alive without approval from the service owner. Otherwise, they may experience failures in
647
   * the future if the service becomes more restrictive. When unthrottled, keep-alives can cause a
648
   * significant amount of traffic and CPU usage, so clients and servers should be conservative in
649
   * what they use and accept.
650
   *
651
   * @see #permitKeepAliveWithoutCalls(boolean)
652
   * @since 1.3.0
653
   */
654
  @CanIgnoreReturnValue
655
  @Override
656
  public NettyServerBuilder permitKeepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
657
    checkArgument(keepAliveTime >= 0, "permit keepalive time must be non-negative: %s",
1✔
658
        keepAliveTime);
659
    permitKeepAliveTimeInNanos = timeUnit.toNanos(keepAliveTime);
×
660
    return this;
×
661
  }
662

663
  /**
664
   * Sets whether to allow clients to send keep-alive HTTP/2 PINGs even if there are no outstanding
665
   * RPCs on the connection. Defaults to {@code false}.
666
   *
667
   * @see #permitKeepAliveTime(long, TimeUnit)
668
   * @since 1.3.0
669
   */
670
  @CanIgnoreReturnValue
671
  @Override
672
  public NettyServerBuilder permitKeepAliveWithoutCalls(boolean permit) {
673
    permitKeepAliveWithoutCalls = permit;
×
674
    return this;
×
675
  }
676

677
  /**
678
   * Limits the rate of incoming RST_STREAM frames per connection to maxRstStream per
679
   * secondsPerWindow. When exceeded on a connection, the connection is closed. This can reduce the
680
   * impact of an attacker continually resetting RPCs before they complete, when combined with TLS
681
   * and {@link #maxConcurrentCallsPerConnection(int)}.
682
   *
683
   * <p>gRPC clients send RST_STREAM when they cancel RPCs, so some RST_STREAMs are normal and
684
   * setting this too low can cause errors for legimitate clients.
685
   *
686
   * <p>By default there is no limit.
687
   *
688
   * @param maxRstStream the positive limit of RST_STREAM frames per connection per period, or
689
   *     {@code Integer.MAX_VALUE} for unlimited
690
   * @param secondsPerWindow the positive number of seconds per period
691
   */
692
  @CanIgnoreReturnValue
693
  public NettyServerBuilder maxRstFramesPerWindow(int maxRstStream, int secondsPerWindow) {
694
    checkArgument(maxRstStream > 0, "maxRstStream must be positive");
×
695
    checkArgument(secondsPerWindow > 0, "secondsPerWindow must be positive");
×
696
    if (maxRstStream == Integer.MAX_VALUE) {
×
697
      maxRstStream = MAX_RST_COUNT_DISABLED;
×
698
    }
699
    this.maxRstCount = maxRstStream;
×
700
    this.maxRstPeriodNanos = TimeUnit.SECONDS.toNanos(secondsPerWindow);
×
701
    return this;
×
702
  }
703

704
  /** Sets the EAG attributes available to protocol negotiators. Not for general use. */
705
  void eagAttributes(Attributes eagAttributes) {
706
    this.eagAttributes = checkNotNull(eagAttributes, "eagAttributes");
1✔
707
  }
1✔
708

709
  @VisibleForTesting
710
  NettyServer buildTransportServers(
711
      List<? extends ServerStreamTracer.Factory> streamTracerFactories,
712
      MetricRecorder metricRecorder) {
713
    assertEventLoopsAndChannelType();
1✔
714

715
    ProtocolNegotiator negotiator = protocolNegotiatorFactory.newNegotiator(
1✔
716
        this.serverImplBuilder.getExecutorPool());
1✔
717

718
    return new NettyServer(
1✔
719
        listenAddresses,
720
        channelFactory,
721
        channelOptions,
722
        childChannelOptions,
723
        bossEventLoopGroupPool,
724
        workerEventLoopGroupPool,
725
        forceHeapBuffer,
726
        negotiator,
727
        streamTracerFactories,
728
        transportTracerFactory,
729
        maxConcurrentCallsPerConnection,
730
        autoFlowControl,
731
        flowControlWindow,
732
        maxMessageSize,
733
        maxHeaderListSize,
734
        softLimitHeaderListSize,
735
        keepAliveTimeInNanos,
736
        keepAliveTimeoutInNanos,
737
        maxConnectionIdleInNanos,
738
        maxConnectionAgeInNanos,
739
        maxConnectionAgeGraceInNanos,
740
        permitKeepAliveWithoutCalls,
741
        permitKeepAliveTimeInNanos,
742
        maxRstCount,
743
        maxRstPeriodNanos,
744
        eagAttributes,
745
        this.serverImplBuilder.getChannelz(),
1✔
746
        metricRecorder);
747
  }
748

749
  @VisibleForTesting
750
  void assertEventLoopsAndChannelType() {
751
    boolean allProvided = channelFactory != Utils.DEFAULT_SERVER_CHANNEL_FACTORY
1✔
752
        && bossEventLoopGroupPool != DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
753
        && workerEventLoopGroupPool != DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
754
    boolean nonProvided = channelFactory == Utils.DEFAULT_SERVER_CHANNEL_FACTORY
1✔
755
        && bossEventLoopGroupPool == DEFAULT_BOSS_EVENT_LOOP_GROUP_POOL
756
        && workerEventLoopGroupPool == DEFAULT_WORKER_EVENT_LOOP_GROUP_POOL;
757
    checkState(
1✔
758
        allProvided || nonProvided,
759
        "All of BossEventLoopGroup, WorkerEventLoopGroup and ChannelType should be provided or "
760
            + "neither should be");
761
  }
1✔
762

763
  @CanIgnoreReturnValue
764
  NettyServerBuilder setTransportTracerFactory(TransportTracer.Factory transportTracerFactory) {
765
    this.transportTracerFactory = transportTracerFactory;
1✔
766
    return this;
1✔
767
  }
768

769
  @CanIgnoreReturnValue
770
  @Override
771
  public NettyServerBuilder useTransportSecurity(File certChain, File privateKey) {
772
    checkState(!freezeProtocolNegotiatorFactory,
×
773
               "Cannot change security when using ServerCredentials");
774
    SslContext sslContext;
775
    try {
776
      sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
×
777
    } catch (SSLException e) {
×
778
      // This should likely be some other, easier to catch exception.
779
      throw new RuntimeException(e);
×
780
    }
×
781
    protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
×
782
    return this;
×
783
  }
784

785
  @CanIgnoreReturnValue
786
  @Override
787
  public NettyServerBuilder useTransportSecurity(InputStream certChain, InputStream privateKey) {
788
    checkState(!freezeProtocolNegotiatorFactory,
×
789
               "Cannot change security when using ServerCredentials");
790
    SslContext sslContext;
791
    try {
792
      sslContext = GrpcSslContexts.forServer(certChain, privateKey).build();
×
793
    } catch (SSLException e) {
×
794
      // This should likely be some other, easier to catch exception.
795
      throw new RuntimeException(e);
×
796
    }
×
797
    protocolNegotiatorFactory = ProtocolNegotiators.serverTlsFactory(sslContext);
×
798
    return this;
×
799
  }
800
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc