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