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

grpc / grpc-java / #19716

06 Mar 2025 10:34AM UTC coverage: 88.494% (+0.02%) from 88.479%
#19716

push

github

web-flow
xds: avoid unnecessary dns lookup (#11932)

34495 of 38980 relevant lines covered (88.49%)

0.88 hits per line

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

92.86
/../xds/src/main/java/io/grpc/xds/EnvoyServerProtoData.java
1
/*
2
 * Copyright 2020 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.xds;
18

19
import static com.google.common.base.Preconditions.checkNotNull;
20

21
import com.google.auto.value.AutoValue;
22
import com.google.common.annotations.VisibleForTesting;
23
import com.google.common.collect.ImmutableList;
24
import com.google.protobuf.util.Durations;
25
import io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.CommonTlsContext;
26
import io.grpc.Internal;
27
import io.grpc.xds.client.EnvoyProtoData;
28
import io.grpc.xds.internal.security.SslContextProviderSupplier;
29
import java.net.InetAddress;
30
import java.util.Objects;
31
import javax.annotation.Nullable;
32

33
/**
34
 * Defines gRPC data types for Envoy protobuf messages used in xDS protocol on the server side,
35
 * similar to how {@link EnvoyProtoData} defines it for the client side.
36
 */
37
@Internal
38
public final class EnvoyServerProtoData {
39

40
  // Prevent instantiation.
41
  private EnvoyServerProtoData() {
42
  }
43

44
  public abstract static class BaseTlsContext {
45
    protected final CommonTlsContext commonTlsContext;
46

47
    protected BaseTlsContext(CommonTlsContext commonTlsContext) {
1✔
48
      this.commonTlsContext = checkNotNull(commonTlsContext, "commonTlsContext cannot be null.");
1✔
49
    }
1✔
50

51
    public CommonTlsContext getCommonTlsContext() {
52
      return commonTlsContext;
1✔
53
    }
54

55
    @Override
56
    public boolean equals(Object o) {
57
      if (this == o) {
1✔
58
        return true;
×
59
      }
60
      if (!(o instanceof BaseTlsContext)) {
1✔
61
        return false;
1✔
62
      }
63
      BaseTlsContext that = (BaseTlsContext) o;
1✔
64
      return Objects.equals(commonTlsContext, that.commonTlsContext);
1✔
65
    }
66

67
    @Override
68
    public int hashCode() {
69
      return Objects.hashCode(commonTlsContext);
1✔
70
    }
71
  }
72

73
  public static final class UpstreamTlsContext extends BaseTlsContext {
74

75
    @VisibleForTesting
76
    public UpstreamTlsContext(CommonTlsContext commonTlsContext) {
77
      super(commonTlsContext);
1✔
78
    }
1✔
79

80
    public static UpstreamTlsContext fromEnvoyProtoUpstreamTlsContext(
81
        io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
82
            upstreamTlsContext) {
83
      return new UpstreamTlsContext(upstreamTlsContext.getCommonTlsContext());
1✔
84
    }
85

86
    @Override
87
    public String toString() {
88
      return "UpstreamTlsContext{" + "commonTlsContext=" + commonTlsContext + '}';
1✔
89
    }
90
  }
91

92
  public static final class DownstreamTlsContext extends BaseTlsContext {
93

94
    private final boolean requireClientCertificate;
95

96
    @VisibleForTesting
97
    public DownstreamTlsContext(
98
        CommonTlsContext commonTlsContext, boolean requireClientCertificate) {
99
      super(commonTlsContext);
1✔
100
      this.requireClientCertificate = requireClientCertificate;
1✔
101
    }
1✔
102

103
    public static DownstreamTlsContext fromEnvoyProtoDownstreamTlsContext(
104
        io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
105
            downstreamTlsContext) {
106
      return new DownstreamTlsContext(downstreamTlsContext.getCommonTlsContext(),
1✔
107
        downstreamTlsContext.hasRequireClientCertificate());
1✔
108
    }
109

110
    public boolean isRequireClientCertificate() {
111
      return requireClientCertificate;
1✔
112
    }
113

114
    @Override
115
    public String toString() {
116
      return "DownstreamTlsContext{"
×
117
          + "commonTlsContext="
118
          + commonTlsContext
119
          + ", requireClientCertificate="
120
          + requireClientCertificate
121
          + '}';
122
    }
123

124
    @Override
125
    public boolean equals(Object o) {
126
      if (this == o) {
1✔
127
        return true;
×
128
      }
129
      if (o == null || getClass() != o.getClass()) {
1✔
130
        return false;
×
131
      }
132
      if (!super.equals(o)) {
1✔
133
        return false;
1✔
134
      }
135
      DownstreamTlsContext that = (DownstreamTlsContext) o;
1✔
136
      return requireClientCertificate == that.requireClientCertificate;
1✔
137
    }
138

139
    @Override
140
    public int hashCode() {
141
      return Objects.hash(super.hashCode(), requireClientCertificate);
1✔
142
    }
143
  }
144

145
  @AutoValue
146
  abstract static class CidrRange {
1✔
147

148
    abstract InetAddress addressPrefix();
149

150
    abstract int prefixLen();
151

152
    static CidrRange create(InetAddress addressPrefix, int prefixLen) {
153
      return new AutoValue_EnvoyServerProtoData_CidrRange(
1✔
154
          addressPrefix, prefixLen);
155
    }
156
  }
157

158
  enum ConnectionSourceType {
1✔
159
    // Any connection source matches.
160
    ANY,
1✔
161

162
    // Match a connection originating from the same host.
163
    SAME_IP_OR_LOOPBACK,
1✔
164

165
    // Match a connection originating from a different host.
166
    EXTERNAL
1✔
167
  }
168

169
  /**
170
   * Corresponds to Envoy proto message
171
   * {@link io.envoyproxy.envoy.config.listener.v3.FilterChainMatch}.
172
   */
173
  @AutoValue
174
  abstract static class FilterChainMatch {
1✔
175

176
    abstract int destinationPort();
177

178
    abstract ImmutableList<CidrRange> prefixRanges();
179

180
    abstract ImmutableList<String> applicationProtocols();
181

182
    abstract ImmutableList<CidrRange> sourcePrefixRanges();
183

184
    abstract ConnectionSourceType connectionSourceType();
185

186
    abstract ImmutableList<Integer> sourcePorts();
187

188
    abstract ImmutableList<String> serverNames();
189

190
    abstract String transportProtocol();
191

192
    public static FilterChainMatch create(int destinationPort,
193
        ImmutableList<CidrRange> prefixRanges,
194
        ImmutableList<String> applicationProtocols, ImmutableList<CidrRange> sourcePrefixRanges,
195
        ConnectionSourceType connectionSourceType, ImmutableList<Integer> sourcePorts,
196
        ImmutableList<String> serverNames, String transportProtocol) {
197
      return new AutoValue_EnvoyServerProtoData_FilterChainMatch(
1✔
198
          destinationPort, prefixRanges, applicationProtocols, sourcePrefixRanges,
199
          connectionSourceType, sourcePorts, serverNames, transportProtocol);
200
    }
201
  }
202

203
  /**
204
   * Corresponds to Envoy proto message {@link io.envoyproxy.envoy.config.listener.v3.FilterChain}.
205
   */
206
  @AutoValue
207
  abstract static class FilterChain {
1✔
208

209
    // possibly empty
210
    abstract String name();
211

212
    // TODO(sanjaypujare): flatten structure by moving FilterChainMatch class members here.
213
    abstract FilterChainMatch filterChainMatch();
214

215
    abstract HttpConnectionManager httpConnectionManager();
216

217
    @Nullable
218
    abstract SslContextProviderSupplier sslContextProviderSupplier();
219

220
    static FilterChain create(
221
        String name,
222
        FilterChainMatch filterChainMatch,
223
        HttpConnectionManager httpConnectionManager,
224
        @Nullable DownstreamTlsContext downstreamTlsContext,
225
        TlsContextManager tlsContextManager) {
226
      SslContextProviderSupplier sslContextProviderSupplier =
227
          downstreamTlsContext == null
1✔
228
              ? null : new SslContextProviderSupplier(downstreamTlsContext, tlsContextManager);
1✔
229
      return new AutoValue_EnvoyServerProtoData_FilterChain(
1✔
230
          name, filterChainMatch, httpConnectionManager, sslContextProviderSupplier);
231
    }
232
  }
233

234
  /**
235
   * Corresponds to Envoy proto message {@link io.envoyproxy.envoy.config.listener.v3.Listener} and
236
   * related classes.
237
   */
238
  @AutoValue
239
  abstract static class Listener {
1✔
240

241
    abstract String name();
242

243
    @Nullable
244
    abstract String address();
245

246
    abstract ImmutableList<FilterChain> filterChains();
247

248
    @Nullable
249
    abstract FilterChain defaultFilterChain();
250

251
    static Listener create(
252
        String name,
253
        @Nullable String address,
254
        ImmutableList<FilterChain> filterChains,
255
        @Nullable FilterChain defaultFilterChain) {
256
      return new AutoValue_EnvoyServerProtoData_Listener(name, address, filterChains,
1✔
257
          defaultFilterChain);
258
    }
259
  }
260

261
  /**
262
   * Corresponds to Envoy proto message {@link
263
   * io.envoyproxy.envoy.config.cluster.v3.OutlierDetection}. Only the fields supported by gRPC are
264
   * included.
265
   *
266
   * <p>Protobuf Duration fields are represented in their string format (e.g. "10s").
267
   */
268
  @AutoValue
269
  abstract static class OutlierDetection {
1✔
270

271
    @Nullable
272
    abstract Long intervalNanos();
273

274
    @Nullable
275
    abstract Long baseEjectionTimeNanos();
276

277
    @Nullable
278
    abstract Long maxEjectionTimeNanos();
279

280
    @Nullable
281
    abstract Integer maxEjectionPercent();
282

283
    @Nullable
284
    abstract SuccessRateEjection successRateEjection();
285

286
    @Nullable
287
    abstract FailurePercentageEjection failurePercentageEjection();
288

289
    static OutlierDetection create(
290
        @Nullable Long intervalNanos,
291
        @Nullable Long baseEjectionTimeNanos,
292
        @Nullable Long maxEjectionTimeNanos,
293
        @Nullable Integer maxEjectionPercentage,
294
        @Nullable SuccessRateEjection successRateEjection,
295
        @Nullable FailurePercentageEjection failurePercentageEjection) {
296
      return new AutoValue_EnvoyServerProtoData_OutlierDetection(intervalNanos,
1✔
297
          baseEjectionTimeNanos, maxEjectionTimeNanos, maxEjectionPercentage, successRateEjection,
298
          failurePercentageEjection);
299
    }
300

301
    static OutlierDetection fromEnvoyOutlierDetection(
302
        io.envoyproxy.envoy.config.cluster.v3.OutlierDetection envoyOutlierDetection) {
303

304
      Long intervalNanos = envoyOutlierDetection.hasInterval()
1✔
305
          ? Durations.toNanos(envoyOutlierDetection.getInterval()) : null;
1✔
306
      Long baseEjectionTimeNanos = envoyOutlierDetection.hasBaseEjectionTime()
1✔
307
          ? Durations.toNanos(envoyOutlierDetection.getBaseEjectionTime()) : null;
1✔
308
      Long maxEjectionTimeNanos = envoyOutlierDetection.hasMaxEjectionTime()
1✔
309
          ? Durations.toNanos(envoyOutlierDetection.getMaxEjectionTime()) : null;
1✔
310
      Integer maxEjectionPercentage = envoyOutlierDetection.hasMaxEjectionPercent()
1✔
311
          ? envoyOutlierDetection.getMaxEjectionPercent().getValue() : null;
1✔
312

313
      SuccessRateEjection successRateEjection;
314
      // If success rate enforcement has been turned completely off, don't configure this ejection.
315
      if (envoyOutlierDetection.hasEnforcingSuccessRate()
1✔
316
          && envoyOutlierDetection.getEnforcingSuccessRate().getValue() == 0) {
1✔
317
        successRateEjection = null;
×
318
      } else {
319
        Integer stdevFactor = envoyOutlierDetection.hasSuccessRateStdevFactor()
1✔
320
            ? envoyOutlierDetection.getSuccessRateStdevFactor().getValue() : null;
1✔
321
        Integer enforcementPercentage = envoyOutlierDetection.hasEnforcingSuccessRate()
1✔
322
            ? envoyOutlierDetection.getEnforcingSuccessRate().getValue() : null;
1✔
323
        Integer minimumHosts = envoyOutlierDetection.hasSuccessRateMinimumHosts()
1✔
324
            ? envoyOutlierDetection.getSuccessRateMinimumHosts().getValue() : null;
1✔
325
        Integer requestVolume = envoyOutlierDetection.hasSuccessRateRequestVolume()
1✔
326
            ? envoyOutlierDetection.getSuccessRateMinimumHosts().getValue() : null;
1✔
327

328
        successRateEjection = SuccessRateEjection.create(stdevFactor, enforcementPercentage,
1✔
329
            minimumHosts, requestVolume);
330
      }
331

332
      FailurePercentageEjection failurePercentageEjection;
333
      if (envoyOutlierDetection.hasEnforcingFailurePercentage()
1✔
334
          && envoyOutlierDetection.getEnforcingFailurePercentage().getValue() == 0) {
1✔
335
        failurePercentageEjection = null;
×
336
      } else {
337
        Integer threshold = envoyOutlierDetection.hasFailurePercentageThreshold()
1✔
338
            ? envoyOutlierDetection.getFailurePercentageThreshold().getValue() : null;
1✔
339
        Integer enforcementPercentage = envoyOutlierDetection.hasEnforcingFailurePercentage()
1✔
340
            ? envoyOutlierDetection.getEnforcingFailurePercentage().getValue() : null;
1✔
341
        Integer minimumHosts = envoyOutlierDetection.hasFailurePercentageMinimumHosts()
1✔
342
            ? envoyOutlierDetection.getFailurePercentageMinimumHosts().getValue() : null;
1✔
343
        Integer requestVolume = envoyOutlierDetection.hasFailurePercentageRequestVolume()
1✔
344
            ? envoyOutlierDetection.getFailurePercentageRequestVolume().getValue() : null;
1✔
345

346
        failurePercentageEjection = FailurePercentageEjection.create(threshold,
1✔
347
            enforcementPercentage, minimumHosts, requestVolume);
348
      }
349

350
      return create(intervalNanos, baseEjectionTimeNanos, maxEjectionTimeNanos,
1✔
351
          maxEjectionPercentage, successRateEjection, failurePercentageEjection);
352
    }
353
  }
354

355
  @AutoValue
356
  abstract static class SuccessRateEjection {
1✔
357

358
    @Nullable
359
    abstract Integer stdevFactor();
360

361
    @Nullable
362
    abstract Integer enforcementPercentage();
363

364
    @Nullable
365
    abstract Integer minimumHosts();
366

367
    @Nullable
368
    abstract Integer requestVolume();
369

370
    static SuccessRateEjection create(
371
        @Nullable Integer stdevFactor,
372
        @Nullable Integer enforcementPercentage,
373
        @Nullable Integer minimumHosts,
374
        @Nullable Integer requestVolume) {
375
      return new AutoValue_EnvoyServerProtoData_SuccessRateEjection(stdevFactor,
1✔
376
          enforcementPercentage, minimumHosts, requestVolume);
377
    }
378
  }
379

380
  @AutoValue
381
  abstract static class FailurePercentageEjection {
1✔
382

383
    @Nullable
384
    abstract Integer threshold();
385

386
    @Nullable
387
    abstract Integer enforcementPercentage();
388

389
    @Nullable
390
    abstract Integer minimumHosts();
391

392
    @Nullable
393
    abstract Integer requestVolume();
394

395
    static FailurePercentageEjection create(
396
        @Nullable Integer threshold,
397
        @Nullable Integer enforcementPercentage,
398
        @Nullable Integer minimumHosts,
399
        @Nullable Integer requestVolume) {
400
      return new AutoValue_EnvoyServerProtoData_FailurePercentageEjection(threshold,
1✔
401
          enforcementPercentage, minimumHosts, requestVolume);
402
    }
403
  }
404
}
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