4848import java .util .Collections ;
4949import java .util .List ;
5050import java .util .concurrent .ScheduledExecutorService ;
51- import java .util .concurrent . ThreadLocalRandom ;
51+ import java .util .function . Function ;
5252import java .util .logging .Level ;
5353import java .util .logging .Logger ;
5454import javax .annotation .Nullable ;
5757import javax .net .ssl .SSLSession ;
5858import javax .net .ssl .StandardConstants ;
5959
60- public final class CompositeFilter implements Filter {
60+ final class CompositeFilter implements Filter {
6161
6262 static final String TYPE_URL_EXTENSION_WITH_MATCHER =
6363 "type.googleapis.com/envoy.extensions.common.matching.v3.ExtensionWithMatcher" ;
@@ -83,7 +83,9 @@ private CompositeFilter() {
8383 }
8484
8585 static final class Provider implements Filter .Provider {
86- private static final ThreadLocal <Integer > recursionDepth = ThreadLocal .withInitial (() -> 0 );
86+
87+ static Function <String , Filter .Provider > registryLookup =
88+ typeUrl -> FilterRegistry .getDefaultRegistry ().get (typeUrl );
8789
8890 @ Override
8991 public String [] typeUrls () {
@@ -110,7 +112,8 @@ public Filter newInstance(String name) {
110112 }
111113
112114 @ Override
113- public ConfigOrError <CompositeFilterConfig > parseFilterConfig (Message rawProtoMessage ) {
115+ public ConfigOrError <CompositeFilterConfig > parseFilterConfig (
116+ Message rawProtoMessage , int depth ) {
114117 if (!isSupported ()) {
115118 return ConfigOrError .fromError ("Composite Filter is experimental "
116119 + "and disabled by default." );
@@ -119,29 +122,23 @@ public ConfigOrError<CompositeFilterConfig> parseFilterConfig(Message rawProtoMe
119122 return ConfigOrError .fromError ("Invalid message type: "
120123 + rawProtoMessage .getClass ().getName ());
121124 }
122- int currentDepth = recursionDepth .get ();
123- if (currentDepth > 8 ) {
124- return ConfigOrError .fromError ("Maximum recursion depth of 8 exceeded" );
125- }
126- recursionDepth .set (currentDepth + 1 );
127125 try {
128126 Any any = (Any ) rawProtoMessage ;
129127 if (any .is (ExtensionWithMatcher .class )) {
130128 ExtensionWithMatcher proto = any .unpack (ExtensionWithMatcher .class );
131- return parseMatcherConfig (proto .getXdsMatcher ());
129+ return parseMatcherConfig (proto .getXdsMatcher (), depth );
132130 } else if (any .is (Composite .class )) {
133131 return ConfigOrError .fromConfig (new CompositeFilterConfig (null ));
134132 }
135133 } catch (InvalidProtocolBufferException e ) {
136134 return ConfigOrError .fromError ("Invalid proto: " + e );
137- } finally {
138- recursionDepth .set (currentDepth );
139135 }
140136 return ConfigOrError .fromError ("Unsupported message type in parseFilterConfig" );
141137 }
142138
143139 @ Override
144- public ConfigOrError <CompositeFilterConfig > parseFilterConfigOverride (Message rawProtoMessage ) {
140+ public ConfigOrError <CompositeFilterConfig > parseFilterConfigOverride (
141+ Message rawProtoMessage , int depth ) {
145142 if (!isSupported ()) {
146143 return ConfigOrError .fromError ("Composite Filter is experimental and disabled"
147144 + " by default." );
@@ -150,35 +147,28 @@ public ConfigOrError<CompositeFilterConfig> parseFilterConfigOverride(Message ra
150147 return ConfigOrError .fromError ("Invalid message type: "
151148 + rawProtoMessage .getClass ().getName ());
152149 }
153- int currentDepth = recursionDepth .get ();
154- if (currentDepth > 8 ) {
155- return ConfigOrError .fromError ("Maximum recursion depth of 8 exceeded" );
156- }
157- recursionDepth .set (currentDepth + 1 );
158150 try {
159151 Any any = (Any ) rawProtoMessage ;
160152 if (any .is (ExtensionWithMatcherPerRoute .class )) {
161153 ExtensionWithMatcherPerRoute proto = any .unpack (ExtensionWithMatcherPerRoute .class );
162- return parseMatcherConfig (proto .getXdsMatcher ());
154+ return parseMatcherConfig (proto .getXdsMatcher (), depth );
163155 }
164156 } catch (InvalidProtocolBufferException e ) {
165157 return ConfigOrError .fromError ("Invalid proto: " + e );
166- } finally {
167- recursionDepth .set (currentDepth );
168158 }
169159 return ConfigOrError .fromError ("Unsupported message type in "
170160 + "parseFilterConfigOverride" );
171161 }
172162
173163 private ConfigOrError <CompositeFilterConfig > parseMatcherConfig (
174- @ Nullable Matcher matcherProto ) {
164+ @ Nullable Matcher matcherProto , int depth ) {
175165 if (matcherProto == null ) {
176166 return ConfigOrError .fromConfig (new CompositeFilterConfig (null ));
177167 }
178168
179169 try {
180170 UnifiedMatcher <FilterDelegate > matcher = UnifiedMatcher .create (matcherProto ,
181- Provider :: createFilterDelegate );
171+ config -> createFilterDelegate ( config , depth ) );
182172 return ConfigOrError .fromConfig (new CompositeFilterConfig (matcher ));
183173 } catch (Exception e ) {
184174 return ConfigOrError .fromError ("Failed to create matcher: " + e .getMessage ());
@@ -190,7 +180,7 @@ private boolean isSupported() {
190180 }
191181
192182 private static FilterDelegate createFilterDelegate (
193- com .github .xds .core .v3 .TypedExtensionConfig config ) {
183+ com .github .xds .core .v3 .TypedExtensionConfig config , int depth ) {
194184 try {
195185 Any actionAny = config .getTypedConfig ();
196186 if (actionAny .is (ExecuteFilterAction .class )) {
@@ -233,12 +223,12 @@ private static FilterDelegate createFilterDelegate(
233223 throw new IllegalArgumentException ("Failed to unpack TypedStruct" , e );
234224 }
235225
236- Filter .Provider provider = FilterRegistry . getDefaultRegistry (). get (typeUrl );
226+ Filter .Provider provider = registryLookup . apply (typeUrl );
237227 if (provider == null ) {
238228 throw new IllegalArgumentException ("Action filter not found: " + typeUrl );
239229 }
240- ConfigOrError <? extends FilterConfig > parsed = provider
241- .parseFilterConfig (rawConfig );
230+ ConfigOrError <? extends FilterConfig > parsed = Filter . Parser
231+ .parseFilterConfig (provider , rawConfig , depth + 1 );
242232 if (parsed .errorDetail != null ) {
243233 throw new IllegalArgumentException (
244234 "Failed to parse child filter: " + parsed .errorDetail );
@@ -274,10 +264,17 @@ public String typeUrl() {
274264 static final class FilterDelegate {
275265 final List <DelegateEntry > delegates ;
276266 private final double threshold ;
267+ private final ThreadSafeRandom random ;
277268
278269 FilterDelegate (List <DelegateEntry > delegates , @ Nullable FractionalPercent samplePercent ) {
270+ this (delegates , samplePercent , ThreadSafeRandom .ThreadSafeRandomImpl .instance );
271+ }
272+
273+ FilterDelegate (List <DelegateEntry > delegates , @ Nullable FractionalPercent samplePercent ,
274+ ThreadSafeRandom random ) {
279275 this .delegates = Collections .unmodifiableList (delegates );
280276 this .threshold = calculateThreshold (samplePercent );
277+ this .random = random ;
281278 }
282279
283280 private static double calculateThreshold (@ Nullable FractionalPercent samplePercent ) {
@@ -309,7 +306,7 @@ boolean shouldExecute() {
309306 if (threshold <= 0.0 ) {
310307 return false ;
311308 }
312- return ThreadLocalRandom . current () .nextDouble () < threshold ;
309+ return random .nextDouble () < threshold ;
313310 }
314311 }
315312
@@ -380,9 +377,7 @@ public <ReqT, RespT> io.grpc.ServerCall.Listener<ReqT> interceptCall(
380377 }
381378 }
382379 } catch (Throwable t ) {
383- for (Filter f : filters ) {
384- f .close ();
385- }
380+ closeAll (filters );
386381 throw t ;
387382 }
388383
@@ -449,7 +444,7 @@ private UnifiedMatcher<FilterDelegate> getMatcher(
449444 return effective .matcher ;
450445 }
451446
452- private static class MatchingDataImpl implements UnifiedMatcher .MatchingData {
447+ static class MatchingDataImpl implements UnifiedMatcher .MatchingData {
453448 private final Metadata headers ;
454449 private final io .grpc .CallOptions callOptions ;
455450 private final io .grpc .Attributes attributes ;
@@ -519,6 +514,12 @@ public String getRelayedInput(com.github.xds.core.v3.TypedExtensionConfig inputC
519514 }
520515 }
521516
517+ private static void closeAll (Iterable <Filter > filters ) {
518+ for (Filter f : filters ) {
519+ f .close ();
520+ }
521+ }
522+
522523 private static class CompositeClientCall <ReqT , RespT > extends io .grpc .ClientCall <ReqT , RespT > {
523524 private final MethodDescriptor <ReqT , RespT > method ;
524525 private final io .grpc .CallOptions callOptions ;
@@ -568,9 +569,7 @@ public void start(Listener<RespT> responseListener, Metadata headers) {
568569 }
569570 }
570571 } catch (Throwable t ) {
571- for (Filter f : filters ) {
572- f .close ();
573- }
572+ closeAll (filters );
574573 throw t ;
575574 }
576575
0 commit comments