@@ -152,6 +152,19 @@ private void runGrpcTest(int port, boolean shouldSucceed) throws Exception {
152152 .setEndpoint ("localhost:" + port )
153153 .setHeaderProvider (() -> java .util .Collections .emptyMap ());
154154
155+ channelProviderBuilder .setChannelConfigurator (
156+ new com .google .api .core .ApiFunction <io .grpc .ManagedChannelBuilder , io .grpc .ManagedChannelBuilder >() {
157+ @ Override
158+ public io .grpc .ManagedChannelBuilder apply (io .grpc .ManagedChannelBuilder builder ) {
159+ builder .overrideAuthority ("localhost" );
160+ if (port == grpcPqcPort ) {
161+ configureGrpcChannelForPqc (builder );
162+ } else {
163+ configureGrpcChannelForClassical (builder );
164+ }
165+ return builder ;
166+ }
167+ });
155168
156169 com .google .api .gax .grpc .InstantiatingGrpcChannelProvider channelProvider = channelProviderBuilder .build ();
157170 com .google .api .gax .rpc .TransportChannel transportChannel = channelProvider .getTransportChannel ();
@@ -210,4 +223,66 @@ public byte[] parse(InputStream stream) {
210223 }
211224 }
212225 }
226+ private static void configureGrpcChannelForPqc (io .grpc .ManagedChannelBuilder <?> builder ) {
227+ if (!(builder instanceof NettyChannelBuilder )) {
228+ throw new IllegalArgumentException (
229+ "Unsupported channel builder type: " + builder .getClass ().getName ());
230+ }
231+ NettyChannelBuilder nettyBuilder = (NettyChannelBuilder ) builder ;
232+
233+ // Ensures HTTP/2 is used as it's required by gRPC
234+ ApplicationProtocolConfig apn =
235+ new ApplicationProtocolConfig (
236+ ApplicationProtocolConfig .Protocol .ALPN ,
237+ ApplicationProtocolConfig .SelectorFailureBehavior .NO_ADVERTISE ,
238+ ApplicationProtocolConfig .SelectedListenerFailureBehavior .ACCEPT ,
239+ "h2" );
240+
241+ try {
242+ java .security .Provider bcProvider = new org .bouncycastle .jce .provider .BouncyCastleProvider ();
243+ java .security .Provider bcJsseProvider =
244+ new org .bouncycastle .jsse .provider .BouncyCastleJsseProvider (bcProvider );
245+
246+ SslContext shadedSslContext =
247+ SslContextBuilder .forClient ()
248+ .sslProvider (io .grpc .netty .shaded .io .netty .handler .ssl .SslProvider .JDK )
249+ .sslContextProvider (bcJsseProvider )
250+ .protocols ("TLSv1.3" )
251+ .applicationProtocolConfig (apn )
252+ .trustManager (InsecureTrustManagerFactory .INSTANCE )
253+ .build ();
254+
255+ nettyBuilder .sslContext (shadedSslContext );
256+ } catch (Exception e ) {
257+ throw new RuntimeException ("Failed to configure shaded gRPC Netty channel for PQC" , e );
258+ }
259+ }
260+
261+ private static void configureGrpcChannelForClassical (io .grpc .ManagedChannelBuilder <?> builder ) {
262+ if (!(builder instanceof NettyChannelBuilder )) {
263+ throw new IllegalArgumentException (
264+ "Unsupported channel builder type: " + builder .getClass ().getName ());
265+ }
266+ NettyChannelBuilder nettyBuilder = (NettyChannelBuilder ) builder ;
267+
268+ ApplicationProtocolConfig apn =
269+ new ApplicationProtocolConfig (
270+ ApplicationProtocolConfig .Protocol .ALPN ,
271+ ApplicationProtocolConfig .SelectorFailureBehavior .NO_ADVERTISE ,
272+ ApplicationProtocolConfig .SelectedListenerFailureBehavior .ACCEPT ,
273+ "h2" );
274+
275+ try {
276+ SslContext shadedSslContext =
277+ SslContextBuilder .forClient ()
278+ .applicationProtocolConfig (apn )
279+ .trustManager (InsecureTrustManagerFactory .INSTANCE )
280+ .build ();
281+
282+ nettyBuilder .sslContext (shadedSslContext );
283+ } catch (Exception e ) {
284+ throw new RuntimeException ("Failed to configure shaded gRPC Netty channel for Classical" , e );
285+ }
286+ }
213287}
288+
0 commit comments