@SuppressWarnings("unchecked") protected void processCommand(String command) throws TimeoutException, IOException, RPCClient.MSFException, InterruptedException { String token = UUID.randomUUID().toString(); StringBuilder buffer = new StringBuilder(); Boolean tokenFound = false; long start; int newline; // send command mRpcClient.call("session.shell_write", mJobId, command + "\necho\necho \"$?" + token + "\"\n"); // read until token is found start = java.lang.System.currentTimeMillis(); do { String data = (((Map<String, String>) mRpcClient.call("session.shell_read", mJobId)).get("data") + ""); newline = data.indexOf('\n'); while (newline >= 0) { buffer.append(data.substring(0, newline)); if ((tokenFound = (buffer.toString().endsWith(token)))) { newline = Integer.parseInt(buffer.toString().substring(0, buffer.length() - token.length())); break; } mReceiver.onNewLine(buffer.toString()); buffer.delete(0, buffer.length()); // substring(start) => start is inclusive , we want remove the '\n' data = data.substring(newline + 1); newline = data.indexOf('\n'); } if (tokenFound) { mReceiver.onEnd(newline); return; } buffer.append(data); Thread.sleep(100); } while ((java.lang.System.currentTimeMillis() - start) < TIMEOUT); // no token found, TIMEOUT! throw new TimeoutException("token not found"); }
@Test public void test() throws UnknownHostException, ExecutionException, InterruptedException { final JavaSerializer serializer = new JavaSerializer(); RPCHandler handler1 = new RPCHandler(serializer); RPCHandler handler2 = new RPCHandler(serializer); RoutingHandler router = new RoutingHandler( ImmutableMap.<String, ChannelHandler>builder() .put("/one", handler1) .put("/two", handler2) .build()); HTTPServer server = new HTTPServer( TcpOptions.create().localAddress(new InetSocketAddress(InetAddress.getLocalHost(), 0)), 2, router); RPCClient client1 = new RPCClient(TcpOptions.create(), "/one", 2, serializer); RPCClient client2 = new RPCClient(TcpOptions.create(), "/two", 2, serializer); RPCClient client3 = new RPCClient(TcpOptions.create(), "/noexisting", 2, serializer); RPC<Void, String> signature = RPC.signature("/method", Void.class, String.class); server.startAsync().awaitRunning(); try { handler1.register( signature, new ServerMethod<Void, String>() { @Override public ListenableFuture<String> call(Envelope envelope, Void argument) { return Futures.immediateFuture("one"); } }); handler2.register( signature, new ServerMethod<Void, String>() { @Override public ListenableFuture<String> call(Envelope envelope, Void argument) { return Futures.immediateFuture("two"); } }); ClientMethod<Void, String> method1 = client1.createMethod(signature); ClientMethod<Void, String> method2 = client2.createMethod(signature); ClientMethod<Void, String> method3 = client3.createMethod(signature); Envelope envelope = new Envelope(1000, "asdfasdfas"); assertEquals(method1.call(server.getLocalAddress(), envelope, null).get(), "one"); assertEquals(method2.call(server.getLocalAddress(), envelope, null).get(), "two"); try { assertEquals(method3.call(server.getLocalAddress(), envelope, null).get(), "wtf?"); fail(); } catch (ExecutionException e) { assertTrue(e.getCause() instanceof BadResponseException); assertTrue(e.getCause().getMessage().contains("404")); } } finally { client1.stopAsync().awaitTerminated(); client2.stopAsync().awaitTerminated(); client3.stopAsync().awaitTerminated(); server.stopAsync().awaitTerminated(); } }