From 622da2d238f1a9528ecd39f33676d8e6fc9a698b Mon Sep 17 00:00:00 2001 From: Aidan Hahn Date: Wed, 22 May 2019 16:23:33 -0700 Subject: [PATCH] Proces Controller Object --- src/main/java/JobServ/JobServClient.java | 61 ++++++----- src/main/java/JobServ/ProcessController.java | 101 +++++++++++++++++++ 2 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 src/main/java/JobServ/ProcessController.java diff --git a/src/main/java/JobServ/JobServClient.java b/src/main/java/JobServ/JobServClient.java index 94a69a6..f5e5606 100644 --- a/src/main/java/JobServ/JobServClient.java +++ b/src/main/java/JobServ/JobServClient.java @@ -51,7 +51,7 @@ public class JobServClient { * Spawns a new blockingStub for network operations with the server */ public JobServClient(ManagedChannel channel) { - this.channel = channel; + this.channel = channel; blockingStub = ShellServerGrpc.newBlockingStub(this.channel); } @@ -146,8 +146,8 @@ public class JobServClient { /* * sends PID to server * returns process exit code - * returns a 0-255 return code or 277 if still running - * or 278 if error in API + * returns a 0-255 return code or 256 if still running + * or 257 if error in API */ public int getProcessReturn(int pid) { logger.info("[+] Requesting return code of a job"); @@ -162,7 +162,7 @@ public class JobServClient { response = blockingStub.getReturn(request); } catch (StatusRuntimeException e) { logger.log(Level.WARNING, "(API Failure) Failed to get return code: " + e.getStatus()); - return 278; + return 257; } return response.getProcessReturnCode(); @@ -211,14 +211,13 @@ public class JobServClient { JobServClient client; try { - SslContextBuilder builder = GrpcSslContexts.forClient(); - builder.trustManager(new File(args[2])); - builder.keyManager(new File(args[1]), new File(args[0])); + SslContextBuilder builder = GrpcSslContexts.forClient(); + builder.trustManager(new File(args[2])); + builder.keyManager(new File(args[1]), new File(args[0])); - ManagedChannel channel = NettyChannelBuilder.forAddress(args[3], Integer.parseInt(args[4])) - .sslContext(builder.build()) - .build(); - + ManagedChannel channel = NettyChannelBuilder.forAddress(args[3], Integer.parseInt(args[4])) + .sslContext(builder.build()) + .build(); client = new JobServClient(channel); // Likely bad port @@ -226,7 +225,7 @@ public class JobServClient { System.out.println("Invalid Port"); return; - // bad cert or key format + // bad cert or key format } catch (SSLException e) { System.out.println(e.getMessage()); return; @@ -253,19 +252,19 @@ public class JobServClient { case "output": candidatePid = getPidArg(args, 6); - if (candidatePid < 0) { - break; - } + if (candidatePid < 0) { + break; + } String processOutput = client.getProcessOutput(candidatePid); System.out.println(processOutput); break; - + case "status": candidatePid = getPidArg(args, 6); - if (candidatePid < 0) { - break; - } + if (candidatePid < 0) { + break; + } Boolean processStatus = client.getProcessStatus(candidatePid); System.out.printf("Process is currently running? %b\n", processStatus); @@ -273,9 +272,9 @@ public class JobServClient { case "kill": candidatePid = getPidArg(args, 6); - if (candidatePid < 0) { - break; - } + if (candidatePid < 0) { + break; + } client.killProcess(candidatePid); System.out.println("End process request recieved!"); @@ -283,9 +282,9 @@ public class JobServClient { case "return": candidatePid = getPidArg(args, 6); - if (candidatePid < 0) { - break; - } + if (candidatePid < 0) { + break; + } int returnCode = client.getProcessReturn(candidatePid); @@ -314,15 +313,15 @@ public class JobServClient { * returns -1 (an invalid PID) if bad index or unparsable int */ private static int getPidArg(String[] args, int index) { - if (args.length < index) { - System.out.println("Improper formatting, try client --help"); - return -1; - } + if (args.length < index) { + System.out.println("Improper formatting, try client --help"); + return -1; + } try { return Integer.parseInt(args[6]); - - } catch (InputMismatchException e) { + + } catch (InputMismatchException e) { System.out.println(args[6] + " is not a valid int, much less a valid pid"); return -1; } diff --git a/src/main/java/JobServ/ProcessController.java b/src/main/java/JobServ/ProcessController.java new file mode 100644 index 0000000..d1d5383 --- /dev/null +++ b/src/main/java/JobServ/ProcessController.java @@ -0,0 +1,101 @@ +/* + * ProcessController + * + * v1.0 + * + * May 22, 2019 + */ + +package JobServ; + +/* + * ProcessController + * This class wraps a java Process object with metadata + * such as translated PID that exist for this specific API + * as well as general metadata like IO streams. + */ +class ProcessController { + // incremented in constructor + private static int nextPid = 0; + private int pid; + + // TODO: add an api endpoint for streaming client input into + // interactive processes (out of scope for initial API) + private OutputStream output; + private InputStream input; + private Scanner outputScanner; + + private Process process; + + /* + * Constructor + * Takes a command and spawns it in a new process + * Redirects IO streams and assigns a fake PID + */ + public ProcessController(String command) throws IOException { + this.pid = ProcessController.nextPid; + ProcessController.nextPid += 1; + + this.process = Runtime.exec(command); + this.output = this.process.getOutputStream(); + this.input = this.process.getInputStream(); + this.outputScanner = new Scanner(this.input); + this.outputScanner.useDelimieter("\\A"); + } + + /* + * getStatus() + * returns whether or not the process is running + * this isnt a very direct way of getting the information + * The alternative is to use reflection to get into the private UNIXProcess class + * for the PID and to check that against 'ps' or a similar command + * + * TODO: (for future release) return thread state + */ + public Boolean getStatus() { + try { + process.exitValue(); + return true; + } catch (IllegalThreadStateException e) { + return false; + } + } + + /* + * getReturn() + * returns the exit code of the process + * or 256 if process is still running + * (unix/posix defines an exit code as a uint8, so 256 is fair game) + */ + public int getReturn() { + try { + return process.exitValue(); + } catch (IllegalThreadStateException e) { + return 256; + } + } + + /* + * getOutput() + * gets new output from stream + * (TODO: investigate whether this would better be done by ) + */ + public String getOutput() { + String out = ""; + while(scanner.hasNext()) { + out += scanner.next(); + } + + return out; + } + + /* + * kill() + * Cleans up resources and destroys process + */ + public void kill() { + this.input.close(); + this.output.close(); + process.destroy(); + } +}