2019-05-18 13:05:02 -07:00
|
|
|
/*
|
|
|
|
|
* JobServServer
|
|
|
|
|
*
|
|
|
|
|
* v1.0
|
|
|
|
|
*
|
|
|
|
|
* May 18, 2019
|
|
|
|
|
*/
|
|
|
|
|
|
2019-05-16 14:49:47 -07:00
|
|
|
package JobServ;
|
|
|
|
|
|
|
|
|
|
import io.grpc.Server;
|
|
|
|
|
import io.grpc.ServerBuilder;
|
2019-05-18 15:28:36 -07:00
|
|
|
import io.grpc.netty.GrpcSslContexts;
|
|
|
|
|
import io.grpc.netty.NettyServerBuilder;
|
|
|
|
|
import io.netty.handler.ssl.ClientAuth;
|
2019-05-19 13:26:15 -07:00
|
|
|
import io.netty.handler.ssl.SslContext;
|
2019-05-18 15:28:36 -07:00
|
|
|
import io.netty.handler.ssl.SslContextBuilder;
|
|
|
|
|
import io.netty.handler.ssl.SslProvider;
|
2019-05-19 13:26:15 -07:00
|
|
|
import javax.net.ssl.SSLException;
|
2019-05-19 14:16:09 -07:00
|
|
|
import java.util.InputMismatchException;
|
2019-05-18 16:40:58 -07:00
|
|
|
import java.io.File;
|
2019-05-16 14:49:47 -07:00
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
2019-05-18 13:05:02 -07:00
|
|
|
/*
|
|
|
|
|
* The JobServServer class implements the JobServ protobuf API
|
|
|
|
|
* It does this by extending the gRPC stub code.
|
|
|
|
|
* Additionally, JobServServer starts and manages a daemon
|
|
|
|
|
* Which accepts incoming connections from client.
|
|
|
|
|
*/
|
2019-05-16 14:49:47 -07:00
|
|
|
public class JobServServer {
|
|
|
|
|
private static final Logger logger = Logger.getLogger(JobServServer.class.getName());
|
|
|
|
|
|
|
|
|
|
private Server server;
|
2019-05-18 15:28:36 -07:00
|
|
|
private final int port;
|
2019-05-19 13:03:53 -07:00
|
|
|
private final SslContext ssl;
|
2019-05-18 15:28:36 -07:00
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
/*
|
|
|
|
|
* Constructor
|
|
|
|
|
* Sets port and builds sslContext
|
|
|
|
|
*/
|
2019-05-18 15:28:36 -07:00
|
|
|
public JobServServer(int port,
|
2019-05-19 13:03:53 -07:00
|
|
|
String serverCert,
|
|
|
|
|
String privateKey,
|
2019-05-19 13:26:15 -07:00
|
|
|
String trustStore) throws SSLException {
|
2019-05-18 15:28:36 -07:00
|
|
|
this.port = port;
|
2019-05-19 13:03:53 -07:00
|
|
|
SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(new File(serverCert), new File(privateKey));
|
2019-05-18 15:28:36 -07:00
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
// Mutual TLS trust store and require client auth
|
|
|
|
|
sslContextBuilder.trustManager(new File(trustStore));
|
|
|
|
|
sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
|
2019-05-18 15:28:36 -07:00
|
|
|
|
2019-05-19 13:26:15 -07:00
|
|
|
this.ssl = GrpcSslContexts.configure(sslContextBuilder).build();
|
2019-05-18 16:40:58 -07:00
|
|
|
}
|
2019-05-16 14:49:47 -07:00
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
/*
|
|
|
|
|
* start()
|
|
|
|
|
* this initializes the server
|
|
|
|
|
*/
|
2019-05-16 14:49:47 -07:00
|
|
|
private void start() throws IOException {
|
2019-05-17 01:28:26 -07:00
|
|
|
// TODO: this should be passed in from a configuration manager
|
2019-05-18 16:40:58 -07:00
|
|
|
server = NettyServerBuilder.forPort(port)
|
|
|
|
|
.addService(new ShellServerService())
|
2019-05-19 13:26:15 -07:00
|
|
|
.sslContext(this.ssl)
|
2019-05-17 01:28:26 -07:00
|
|
|
.build()
|
|
|
|
|
.start();
|
2019-05-18 15:28:36 -07:00
|
|
|
logger.info("Server initialized!");
|
|
|
|
|
|
2019-05-17 01:35:55 -07:00
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
2019-05-17 01:28:26 -07:00
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
logger.info("Shutting down server");
|
|
|
|
|
JobServServer.this.stop();
|
|
|
|
|
}
|
|
|
|
|
});
|
2019-05-16 14:49:47 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
/*
|
|
|
|
|
* stop()
|
|
|
|
|
* This is called when ctrl+c is pressed
|
|
|
|
|
*/
|
2019-05-16 14:49:47 -07:00
|
|
|
private void stop() {
|
2019-05-17 01:28:26 -07:00
|
|
|
if (server != null) {
|
|
|
|
|
server.shutdown();
|
|
|
|
|
}
|
2019-05-16 14:49:47 -07:00
|
|
|
}
|
2019-05-18 12:20:12 -07:00
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
/*
|
|
|
|
|
* blockUntilShutdown()
|
|
|
|
|
* This is more or less the main loop of the server.
|
|
|
|
|
* It spins until shutdown is called.
|
|
|
|
|
*/
|
2019-05-16 14:49:47 -07:00
|
|
|
private void blockUntilShutdown() throws InterruptedException {
|
2019-05-17 01:28:26 -07:00
|
|
|
if (server != null) {
|
|
|
|
|
server.awaitTermination();
|
|
|
|
|
}
|
2019-05-16 14:49:47 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 13:03:53 -07:00
|
|
|
/*
|
|
|
|
|
* main()
|
|
|
|
|
* Entrypoint of hte server
|
|
|
|
|
* parses args and initializes a server object.
|
|
|
|
|
* calls server main loop.
|
|
|
|
|
*/
|
2019-05-16 14:49:47 -07:00
|
|
|
public static void main(String[] args) throws IOException, InterruptedException {
|
2019-05-19 14:16:09 -07:00
|
|
|
// TODO: port and key/cert files should be handled by a config manager
|
|
|
|
|
if(args.length < 4) {
|
|
|
|
|
System.out.println("Usage: ./jobserv-server port cert privatekey truststore");
|
2019-05-18 15:28:36 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-19 13:26:15 -07:00
|
|
|
JobServServer server;
|
|
|
|
|
|
2019-05-19 14:16:09 -07:00
|
|
|
try {
|
|
|
|
|
server = new JobServServer(Integer.parseInt(args[0]), args[1], args[2], args[3]);
|
|
|
|
|
|
|
|
|
|
} catch (InputMismatchException e) {
|
|
|
|
|
System.out.println("Invalid port!");
|
|
|
|
|
return;
|
|
|
|
|
|
2019-05-19 13:26:15 -07:00
|
|
|
} catch (SSLException e) {
|
|
|
|
|
System.out.println(e.getMessage());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-17 01:28:26 -07:00
|
|
|
server.start();
|
|
|
|
|
server.blockUntilShutdown();
|
2019-05-16 14:49:47 -07:00
|
|
|
}
|
|
|
|
|
}
|