private void doTasks() { Runnable runnable = null; while ((runnable = tlsEngine.getDelegatedTask()) != null) { runnable.run(); } // end of while ((runnable = engine.getDelegatedTask()) != 0) }
protected boolean handleSSLHandshake2() throws IOException { // We need to make sure the handshake process finished as a whole // boolean proceed = false; SSLEngineResult engineResult = null; isHanshakeDone = false; while (true) { switch (engine.getHandshakeStatus()) { case NOT_HANDSHAKING: case FINISHED: isHanshakeDone = true; return true; case NEED_TASK: Executor exec = Executors.newSingleThreadExecutor(); Runnable task; while ((task = engine.getDelegatedTask()) != null) { exec.execute(task); } continue; case NEED_WRAP: // We need to call a wrap on the engine appSendBuffer.flip(); engineResult = engine.wrap(appSendBuffer, netSendBuffer); appSendBuffer.compact(); if (engineResult.getStatus() == Status.BUFFER_OVERFLOW || engineResult.getStatus() == Status .OK) { // The enigne sys we need to flush the current buffer into the network // So just set the selector to the write mode channel.register(selector, SelectionKey.OP_WRITE); selector.wakeup(); // System.out.println("Handshake wants to do a write "); return false; } else if (engineResult.getStatus() == Status.CLOSED) { throw new IOException("Connection closed"); } else { continue; } case NEED_UNWRAP: // We need to call unwarap method of the engine netRecvBuffer.flip(); engineResult = engine.unwrap(netRecvBuffer, appRecvBuffer); netRecvBuffer.compact(); // System.out.println(engine.isInboundDone()); if (engineResult.getStatus() == Status.BUFFER_UNDERFLOW) { if (!engine.isInboundDone()) { channel.register(selector, SelectionKey.OP_READ); selector.wakeup(); // System.out.println("Handshake wants to do a read "); return false; } else continue; } else if (engineResult.getStatus() == Status.CLOSED) { throw new IOException("Connection closed"); } else { continue; } } } }
/** * Perform tasks, if any, during the handshake phase * * @return The handshake status ( {@link javax.net.ssl.SSLEngineResult.HandshakeStatus}) */ private SSLEngineResult.HandshakeStatus tasks() { Runnable task = null; while ((task = sslEngine.getDelegatedTask()) != null) { // Run the task in blocking mode task.run(); } return sslEngine.getHandshakeStatus(); }
/** * Fetches all delegated tasks from the {@link SSLEngine} and runs them by invoking them directly. */ private void runDelegatedTasks() { for (; ; ) { Runnable task = engine.getDelegatedTask(); if (task == null) { break; } task.run(); } }
private void runDelegatedTasks() { for (; ; ) { Runnable task = engine.getDelegatedTask(); if (task == null) { break; } delegatedTaskExecutor.execute(task); } }
private static void runDelegatedTasks(SSLEngine engine) { Runnable runnable; System.out.println("Running delegated tasks..."); while ((runnable = engine.getDelegatedTask()) != null) { runnable.run(); } HandshakeStatus hs = engine.getHandshakeStatus(); if (hs == HandshakeStatus.NEED_TASK) { throw new Error("Handshake shouldn't need additional tasks."); } }
/* * Do all the outstanding handshake tasks in the current Thread. */ private SSLEngineResult.HandshakeStatus doTasks() { Runnable runnable; /* * We could run this in a separate thread, but * do in the current for now. */ while ((runnable = sslEngine.getDelegatedTask()) != null) { runnable.run(); } return sslEngine.getHandshakeStatus(); }
/* * If the result indicates that we have outstanding tasks to do, * go ahead and run them in this thread. */ private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) throws Exception { if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { log("\trunning delegated task..."); runnable.run(); } HandshakeStatus hsStatus = engine.getHandshakeStatus(); if (hsStatus == HandshakeStatus.NEED_TASK) { throw new Exception("handshake shouldn't need additional tasks"); } log("\tnew HandshakeStatus: " + hsStatus); } }
private void checkResult( SSLEngine engine, SSLEngineResult result, HandshakeStatus rqdHsStatus, boolean consumed, boolean produced) throws Exception { HandshakeStatus hsStatus = result.getHandshakeStatus(); if (hsStatus == HandshakeStatus.NEED_TASK) { Runnable runnable; while ((runnable = engine.getDelegatedTask()) != null) { runnable.run(); } hsStatus = engine.getHandshakeStatus(); } if (hsStatus != rqdHsStatus) { throw new Exception("Required " + rqdHsStatus + ", got " + hsStatus); } int bc = result.bytesConsumed(); int bp = result.bytesProduced(); if (consumed) { if (bc <= 0) { throw new Exception("Should have consumed bytes"); } } else { if (bc > 0) { throw new Exception("Should not have consumed bytes"); } } if (produced) { if (bp <= 0) { throw new Exception("Should have produced bytes"); } } else { if (bp > 0) { throw new Exception("Should not have produced bytes"); } } }
private void runDelegatedTasks() { for (; ; ) { final Runnable task; synchronized (handshakeLock) { task = engine.getDelegatedTask(); } if (task == null) { break; } delegatedTaskExecutor.execute( new Runnable() { public void run() { synchronized (handshakeLock) { task.run(); } } }); } }
private ByteBuffer unwrap(ByteBuffer b) throws SSLException { in.clear(); while (b.hasRemaining()) { sslEngineResult = sslEngine.unwrap(b, in); if (sslEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { if (DEBUG) { log("Handshake NEED TASK"); } Runnable task; while ((task = sslEngine.getDelegatedTask()) != null) { if (DEBUG) { log("Running task: " + task); } task.run(); } } else if (sslEngineResult.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED || sslEngineResult.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW) { return in; } } return in; }
boolean step() { switch (engine.getHandshakeStatus()) { case NOT_HANDSHAKING: boolean anything = false; { if (wrapSrc.position() > 0) anything |= this.wrap(); if (unwrapSrc.position() > 0) anything |= this.unwrap(); } return anything; case NEED_WRAP: if (!this.wrap()) return false; break; case NEED_UNWRAP: if (!this.unwrap()) return false; break; case NEED_TASK: final Runnable sslTask = engine.getDelegatedTask(); Runnable wrappedTask = new Runnable() { @Override public void run() { sslTask.run(); // continue handling I/O ioWorker.execute(NonBlockingSSL.this.stepTask); } }; taskWorkers.execute(wrappedTask); return false; case FINISHED: throw new IllegalStateException("FINISHED"); } return true; }
private void handshake() throws IOException { while (!isEstablished()) { switch (engine.getHandshakeStatus()) { case NOT_HANDSHAKING: case FINISHED: throw new IllegalStateException("Not handshaking"); case NEED_TASK: Runnable task = engine.getDelegatedTask(); if (task != null) { task.run(); } break; case NEED_WRAP: wrap(EMPTY); break; case NEED_UNWRAP: if (!unwrap()) { return; } break; } } }
Runnable getDelegatedTask() { return _engine.getDelegatedTask(); }
@Test public void testTcpClose() throws Exception { // This test replaces SSLSocket() with a very manual SSL client // so we can close TCP underneath SSL. SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress()); client.socket().setSoTimeout(500); SocketChannel server = _connector.accept(); server.configureBlocking(false); _manager.accept(server); SSLEngine engine = __sslCtxFactory.newSSLEngine(); engine.setUseClientMode(true); engine.beginHandshake(); ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize() * 2); ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize() * 2); boolean debug = false; if (debug) System.err.println(engine.getHandshakeStatus()); int loop = 20; while (engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) { if (--loop == 0) throw new IllegalStateException(); if (engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP) { if (debug) System.err.printf( "sslOut %d-%d-%d%n", sslOut.position(), sslOut.limit(), sslOut.capacity()); if (debug) System.err.printf( "appOut %d-%d-%d%n", appOut.position(), appOut.limit(), appOut.capacity()); SSLEngineResult result = engine.wrap(appOut, sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed = client.write(sslOut); if (debug) System.err.println("out=" + flushed); sslOut.clear(); } if (engine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); if (sslIn.position() == 0) { int filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); } sslIn.flip(); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); SSLEngineResult result = engine.unwrap(sslIn, appIn); if (debug) System.err.println(result); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); if (debug) System.err.printf("sslIn %d-%d-%d%n", sslIn.position(), sslIn.limit(), sslIn.capacity()); } if (engine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable task; while ((task = engine.getDelegatedTask()) != null) task.run(); if (debug) System.err.println(engine.getHandshakeStatus()); } } if (debug) System.err.println("\nSay Hello"); // write a message appOut.put("HelloWorld".getBytes(StandardCharsets.UTF_8)); appOut.flip(); SSLEngineResult result = engine.wrap(appOut, sslOut); if (debug) System.err.println(result); sslOut.flip(); int flushed = client.write(sslOut); if (debug) System.err.println("out=" + flushed); sslOut.clear(); appOut.clear(); // read the response int filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); sslIn.flip(); result = engine.unwrap(sslIn, appIn); if (debug) System.err.println(result); if (sslIn.hasRemaining()) sslIn.compact(); else sslIn.clear(); appIn.flip(); String reply = new String(appIn.array(), appIn.arrayOffset(), appIn.remaining()); appIn.clear(); Assert.assertEquals("HelloWorld", reply); if (debug) System.err.println("Shutting down output"); client.socket().shutdownOutput(); filled = client.read(sslIn); if (debug) System.err.println("in=" + filled); if (filled >= 0) { // this is the old behaviour. sslIn.flip(); try { // Since the client closed abruptly, the server is sending a close alert with a failure engine.unwrap(sslIn, appIn); Assert.fail(); } catch (SSLException x) { // Expected } } sslIn.clear(); filled = client.read(sslIn); Assert.assertEquals(-1, filled); Assert.assertFalse(server.isOpen()); }
@Test public void checkSslEngineBehaviour() throws Exception { SSLEngine server = __sslCtxFactory.newSSLEngine(); SSLEngine client = __sslCtxFactory.newSSLEngine(); ByteBuffer netC2S = ByteBuffer.allocate(server.getSession().getPacketBufferSize()); ByteBuffer netS2C = ByteBuffer.allocate(server.getSession().getPacketBufferSize()); ByteBuffer serverIn = ByteBuffer.allocate(server.getSession().getApplicationBufferSize()); ByteBuffer serverOut = ByteBuffer.allocate(server.getSession().getApplicationBufferSize()); ByteBuffer clientIn = ByteBuffer.allocate(client.getSession().getApplicationBufferSize()); SSLEngineResult result; // start the client client.setUseClientMode(true); client.beginHandshake(); Assert.assertEquals(HandshakeStatus.NEED_WRAP, client.getHandshakeStatus()); // what if we try an unwrap? netS2C.flip(); result = client.unwrap(netS2C, clientIn); // unwrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_WRAP, result.getHandshakeStatus()); netS2C.clear(); // do the needed WRAP of empty buffer result = client.wrap(BufferUtil.EMPTY_BUFFER, netC2S); // unwrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertThat(result.bytesProduced(), greaterThan(0)); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); netC2S.flip(); assertEquals(netC2S.remaining(), result.bytesProduced()); // start the server server.setUseClientMode(false); server.beginHandshake(); Assert.assertEquals(HandshakeStatus.NEED_UNWRAP, server.getHandshakeStatus()); // what if we try a needless wrap? serverOut.put(BufferUtil.toBuffer("Hello World")); serverOut.flip(); result = server.wrap(serverOut, netS2C); // wrap is a noop assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to an empty buffer result = server.unwrap(netC2S, BufferUtil.EMPTY_BUFFER); assertEquals(SSLEngineResult.Status.BUFFER_OVERFLOW, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to a full buffer serverIn.position(serverIn.limit()); result = server.unwrap(netC2S, serverIn); assertEquals(SSLEngineResult.Status.BUFFER_OVERFLOW, result.getStatus()); assertEquals(0, result.bytesConsumed()); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_UNWRAP, result.getHandshakeStatus()); // Do the needed unwrap, to an empty buffer serverIn.clear(); result = server.unwrap(netC2S, serverIn); assertEquals(SSLEngineResult.Status.OK, result.getStatus()); assertThat(result.bytesConsumed(), greaterThan(0)); assertEquals(0, result.bytesProduced()); assertEquals(HandshakeStatus.NEED_TASK, result.getHandshakeStatus()); server.getDelegatedTask().run(); assertEquals(HandshakeStatus.NEED_WRAP, server.getHandshakeStatus()); }