• 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.testing.integration;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertNotNull;
21 import static org.junit.Assert.assertTrue;
22 
23 import com.google.common.base.Throwables;
24 import com.squareup.okhttp.ConnectionSpec;
25 import io.grpc.ManagedChannel;
26 import io.grpc.internal.AbstractServerImplBuilder;
27 import io.grpc.internal.GrpcUtil;
28 import io.grpc.internal.testing.StreamRecorder;
29 import io.grpc.internal.testing.TestUtils;
30 import io.grpc.netty.GrpcSslContexts;
31 import io.grpc.netty.NettyServerBuilder;
32 import io.grpc.okhttp.OkHttpChannelBuilder;
33 import io.grpc.okhttp.internal.Platform;
34 import io.grpc.stub.StreamObserver;
35 import io.grpc.testing.integration.EmptyProtos.Empty;
36 import io.netty.handler.ssl.OpenSsl;
37 import io.netty.handler.ssl.SslContext;
38 import io.netty.handler.ssl.SslContextBuilder;
39 import io.netty.handler.ssl.SslProvider;
40 import io.netty.handler.ssl.SupportedCipherSuiteFilter;
41 import java.io.IOException;
42 import javax.net.ssl.HostnameVerifier;
43 import javax.net.ssl.SSLPeerUnverifiedException;
44 import javax.net.ssl.SSLSession;
45 import org.junit.BeforeClass;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.junit.runners.JUnit4;
49 
50 /**
51  * Integration tests for GRPC over Http2 using the OkHttp framework.
52  */
53 @RunWith(JUnit4.class)
54 public class Http2OkHttpTest extends AbstractInteropTest {
55 
56   private static final String BAD_HOSTNAME = "I.am.a.bad.hostname";
57 
58   @BeforeClass
loadConscrypt()59   public static void loadConscrypt() throws Exception {
60     // Load conscrypt if it is available. Either Conscrypt or Jetty ALPN needs to be available for
61     // OkHttp to negotiate.
62     TestUtils.installConscryptIfAvailable();
63   }
64 
65   @Override
getServerBuilder()66   protected AbstractServerImplBuilder<?> getServerBuilder() {
67     // Starts the server with HTTPS.
68     try {
69       SslProvider sslProvider = SslContext.defaultServerProvider();
70       if (sslProvider == SslProvider.OPENSSL && !OpenSsl.isAlpnSupported()) {
71         // OkHttp only supports Jetty ALPN on OpenJDK. So if OpenSSL doesn't support ALPN, then we
72         // are forced to use Jetty ALPN for Netty instead of OpenSSL.
73         sslProvider = SslProvider.JDK;
74       }
75       SslContextBuilder contextBuilder = SslContextBuilder
76           .forServer(TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key"));
77       GrpcSslContexts.configure(contextBuilder, sslProvider);
78       contextBuilder.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE);
79       return NettyServerBuilder.forPort(0)
80           .flowControlWindow(65 * 1024)
81           .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE)
82           .sslContext(contextBuilder.build());
83     } catch (IOException ex) {
84       throw new RuntimeException(ex);
85     }
86   }
87 
88   @Override
createChannel()89   protected ManagedChannel createChannel() {
90     return createChannelBuilder().build();
91   }
92 
createChannelBuilder()93   private OkHttpChannelBuilder createChannelBuilder() {
94     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("localhost", getPort())
95         .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE)
96         .connectionSpec(new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
97             .cipherSuites(TestUtils.preferredTestCiphers().toArray(new String[0]))
98             .build())
99         .overrideAuthority(GrpcUtil.authorityFromHostAndPort(
100             TestUtils.TEST_SERVER_HOST, getPort()));
101     io.grpc.internal.TestingAccessor.setStatsImplementation(
102         builder, createClientCensusStatsModule());
103     try {
104       builder.sslSocketFactory(TestUtils.newSslSocketFactoryForCa(Platform.get().getProvider(),
105           TestUtils.loadCert("ca.pem")));
106     } catch (Exception e) {
107       throw new RuntimeException(e);
108     }
109     return builder;
110   }
111 
112   @Test
receivedDataForFinishedStream()113   public void receivedDataForFinishedStream() throws Exception {
114     Messages.ResponseParameters.Builder responseParameters =
115         Messages.ResponseParameters.newBuilder()
116         .setSize(1);
117     Messages.StreamingOutputCallRequest.Builder requestBuilder =
118         Messages.StreamingOutputCallRequest.newBuilder()
119             .setResponseType(Messages.PayloadType.COMPRESSABLE);
120     for (int i = 0; i < 1000; i++) {
121       requestBuilder.addResponseParameters(responseParameters);
122     }
123 
124     StreamRecorder<Messages.StreamingOutputCallResponse> recorder = StreamRecorder.create();
125     StreamObserver<Messages.StreamingOutputCallRequest> requestStream =
126         asyncStub.fullDuplexCall(recorder);
127     Messages.StreamingOutputCallRequest request = requestBuilder.build();
128     requestStream.onNext(request);
129     recorder.firstValue().get();
130     requestStream.onError(new Exception("failed"));
131 
132     recorder.awaitCompletion();
133 
134     assertEquals(EMPTY, blockingStub.emptyCall(EMPTY));
135   }
136 
137   @Test
wrongHostNameFailHostnameVerification()138   public void wrongHostNameFailHostnameVerification() throws Exception {
139     ManagedChannel channel = createChannelBuilder()
140         .overrideAuthority(GrpcUtil.authorityFromHostAndPort(
141             BAD_HOSTNAME, getPort()))
142         .build();
143     TestServiceGrpc.TestServiceBlockingStub blockingStub =
144         TestServiceGrpc.newBlockingStub(channel);
145 
146     Throwable actualThrown = null;
147     try {
148       blockingStub.emptyCall(Empty.getDefaultInstance());
149     } catch (Throwable t) {
150       actualThrown = t;
151     }
152     assertNotNull("The rpc should have been failed due to hostname verification", actualThrown);
153     Throwable cause = Throwables.getRootCause(actualThrown);
154     assertTrue(
155         "Failed by unexpected exception: " + cause, cause instanceof SSLPeerUnverifiedException);
156     channel.shutdown();
157   }
158 
159   @Test
hostnameVerifierWithBadHostname()160   public void hostnameVerifierWithBadHostname() throws Exception {
161     ManagedChannel channel = createChannelBuilder()
162         .overrideAuthority(GrpcUtil.authorityFromHostAndPort(
163             BAD_HOSTNAME, getPort()))
164         .hostnameVerifier(new HostnameVerifier() {
165           @Override
166           public boolean verify(String hostname, SSLSession session) {
167             return true;
168           }
169         })
170         .build();
171     TestServiceGrpc.TestServiceBlockingStub blockingStub =
172         TestServiceGrpc.newBlockingStub(channel);
173 
174     blockingStub.emptyCall(Empty.getDefaultInstance());
175 
176     channel.shutdown();
177   }
178 
179   @Test
hostnameVerifierWithCorrectHostname()180   public void hostnameVerifierWithCorrectHostname() throws Exception {
181     ManagedChannel channel = createChannelBuilder()
182         .overrideAuthority(GrpcUtil.authorityFromHostAndPort(
183             TestUtils.TEST_SERVER_HOST, getPort()))
184         .hostnameVerifier(new HostnameVerifier() {
185           @Override
186           public boolean verify(String hostname, SSLSession session) {
187             return false;
188           }
189         })
190         .build();
191     TestServiceGrpc.TestServiceBlockingStub blockingStub =
192         TestServiceGrpc.newBlockingStub(channel);
193 
194     Throwable actualThrown = null;
195     try {
196       blockingStub.emptyCall(Empty.getDefaultInstance());
197     } catch (Throwable t) {
198       actualThrown = t;
199     }
200     assertNotNull("The rpc should have been failed due to hostname verification", actualThrown);
201     Throwable cause = Throwables.getRootCause(actualThrown);
202     assertTrue(
203         "Failed by unexpected exception: " + cause, cause instanceof SSLPeerUnverifiedException);
204     channel.shutdown();
205   }
206 }
207