• 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 com.google.common.annotations.VisibleForTesting;
20 import com.google.common.util.concurrent.MoreExecutors;
21 import io.grpc.BindableService;
22 import io.grpc.Grpc;
23 import io.grpc.InsecureServerCredentials;
24 import io.grpc.Server;
25 import io.grpc.ServerCredentials;
26 import io.grpc.ServerInterceptors;
27 import io.grpc.TlsServerCredentials;
28 import io.grpc.alts.AltsServerCredentials;
29 import io.grpc.services.MetricRecorder;
30 import io.grpc.testing.TlsTesting;
31 import io.grpc.xds.orca.OrcaMetricReportingServerInterceptor;
32 import io.grpc.xds.orca.OrcaServiceImpl;
33 import java.util.concurrent.Executors;
34 import java.util.concurrent.ScheduledExecutorService;
35 import java.util.concurrent.TimeUnit;
36 
37 /** Server that manages startup/shutdown of a single {@code TestService}. */
38 public class TestServiceServer {
39   /** The main application allowing this server to be launched from the command line. */
main(String[] args)40   public static void main(String[] args) throws Exception {
41     final TestServiceServer server = new TestServiceServer();
42     server.parseArgs(args);
43     if (server.useTls) {
44       System.out.println(
45           "\nUsing fake CA for TLS certificate. Test clients should expect host\n"
46               + "*.test.google.fr and our test CA. For the Java test client binary, use:\n"
47               + "--server_host_override=foo.test.google.fr --use_test_ca=true\n");
48     }
49 
50     Runtime.getRuntime()
51         .addShutdownHook(
52             new Thread() {
53               @Override
54               @SuppressWarnings("CatchAndPrintStackTrace")
55               public void run() {
56                 try {
57                   System.out.println("Shutting down");
58                   server.stop();
59                 } catch (Exception e) {
60                   e.printStackTrace();
61                 }
62               }
63             });
64     server.start();
65     System.out.println("Server started on port " + server.port);
66     server.blockUntilShutdown();
67   }
68 
69   private int port = 8080;
70   private boolean useTls = true;
71   private boolean useAlts = false;
72 
73   private ScheduledExecutorService executor;
74   private Server server;
75   private int localHandshakerPort = -1;
76 
77   @VisibleForTesting
parseArgs(String[] args)78   void parseArgs(String[] args) {
79     boolean usage = false;
80     for (String arg : args) {
81       if (!arg.startsWith("--")) {
82         System.err.println("All arguments must start with '--': " + arg);
83         usage = true;
84         break;
85       }
86       String[] parts = arg.substring(2).split("=", 2);
87       String key = parts[0];
88       if ("help".equals(key)) {
89         usage = true;
90         break;
91       }
92       if (parts.length != 2) {
93         System.err.println("All arguments must be of the form --arg=value");
94         usage = true;
95         break;
96       }
97       String value = parts[1];
98       if ("port".equals(key)) {
99         port = Integer.parseInt(value);
100       } else if ("use_tls".equals(key)) {
101         useTls = Boolean.parseBoolean(value);
102       } else if ("use_alts".equals(key)) {
103         useAlts = Boolean.parseBoolean(value);
104       } else if ("local_handshaker_port".equals(key)) {
105         localHandshakerPort = Integer.parseInt(value);
106       } else if ("grpc_version".equals(key)) {
107         if (!"2".equals(value)) {
108           System.err.println("Only grpc version 2 is supported");
109           usage = true;
110           break;
111         }
112       } else {
113         System.err.println("Unknown argument: " + key);
114         usage = true;
115         break;
116       }
117     }
118     if (useAlts) {
119       useTls = false;
120     }
121     if (usage) {
122       TestServiceServer s = new TestServiceServer();
123       System.out.println(
124           "Usage: [ARGS...]"
125               + "\n"
126               + "\n  --port=PORT           Port to connect to. Default " + s.port
127               + "\n  --use_tls=true|false  Whether to use TLS. Default " + s.useTls
128               + "\n  --use_alts=true|false Whether to use ALTS. Enable ALTS will disable TLS."
129               + "\n                        Default " + s.useAlts
130               + "\n  --local_handshaker_port=PORT"
131               + "\n                        Use local ALTS handshaker service on the specified port "
132               + "\n                        for testing. Only effective when --use_alts=true."
133       );
134       System.exit(1);
135     }
136   }
137 
138   @VisibleForTesting
start()139   void start() throws Exception {
140     executor = Executors.newSingleThreadScheduledExecutor();
141     ServerCredentials serverCreds;
142     if (useAlts) {
143       if (localHandshakerPort > -1) {
144         serverCreds = AltsServerCredentials.newBuilder()
145             .enableUntrustedAltsForTesting()
146             .setHandshakerAddressForTesting("localhost:" + localHandshakerPort).build();
147       } else {
148         serverCreds = AltsServerCredentials.create();
149       }
150     } else if (useTls) {
151       serverCreds = TlsServerCredentials.create(
152           TlsTesting.loadCert("server1.pem"), TlsTesting.loadCert("server1.key"));
153     } else {
154       serverCreds = InsecureServerCredentials.create();
155     }
156     MetricRecorder metricRecorder = MetricRecorder.newInstance();
157     BindableService orcaOobService =
158         OrcaServiceImpl.createService(executor, metricRecorder, 1, TimeUnit.SECONDS);
159     server = Grpc.newServerBuilderForPort(port, serverCreds)
160         .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE)
161         .addService(
162             ServerInterceptors.intercept(
163                 new TestServiceImpl(executor, metricRecorder), TestServiceImpl.interceptors()))
164         .addService(orcaOobService)
165         .intercept(OrcaMetricReportingServerInterceptor.create(metricRecorder))
166         .build()
167         .start();
168   }
169 
170   @VisibleForTesting
stop()171   void stop() throws Exception {
172     server.shutdownNow();
173     if (!server.awaitTermination(5, TimeUnit.SECONDS)) {
174       System.err.println("Timed out waiting for server shutdown");
175     }
176     MoreExecutors.shutdownAndAwaitTermination(executor, 5, TimeUnit.SECONDS);
177   }
178 
179   @VisibleForTesting
getPort()180   int getPort() {
181     return server.getPort();
182   }
183 
184   /** Await termination on the main thread since the grpc library uses daemon threads. */
blockUntilShutdown()185   private void blockUntilShutdown() throws InterruptedException {
186     if (server != null) {
187       server.awaitTermination();
188     }
189   }
190 }
191