/** Notify all the handshake futures about the failure during the handshake. */ private void setHandshakeFailure(Throwable cause) { // Release all resources such as internal buffers that SSLEngine // is managing. engine.closeOutbound(); try { engine.closeInbound(); } catch (SSLException e) { if (logger.isDebugEnabled()) { logger.debug( "SSLEngine.closeInbound() raised an exception after " + "a handshake failure.", e); } } if (cause == null) { cause = new ClosedChannelException(); } for (; ; ) { ChannelFuture f = handshakeFutures.poll(); if (f == null) { break; } f.setFailure(cause); } flush0(ctx, 0, cause); }
@Override public void flush(final ChannelHandlerContext ctx, ChannelFuture future) throws Exception { final ByteBuf in = ctx.outboundByteBuffer(); final ByteBuf out = ctx.nextOutboundByteBuffer(); out.unsafe().discardSomeReadBytes(); // Do not encrypt the first write request if this handler is // created with startTLS flag turned on. if (startTls && !sentFirstMessage) { sentFirstMessage = true; out.writeBytes(in); ctx.flush(future); return; } if (ctx.executor() == ctx.channel().eventLoop()) { flushFutureNotifier.addFlushFuture(future, in.readableBytes()); } else { synchronized (flushFutureNotifier) { flushFutureNotifier.addFlushFuture(future, in.readableBytes()); } } boolean unwrapLater = false; int bytesConsumed = 0; try { for (; ; ) { SSLEngineResult result = wrap(engine, in, out); bytesConsumed += result.bytesConsumed(); if (result.getStatus() == Status.CLOSED) { // SSLEngine has been closed already. // Any further write attempts should be denied. if (in.readable()) { in.clear(); SSLException e = new SSLException("SSLEngine already closed"); future.setFailure(e); ctx.fireExceptionCaught(e); flush0(ctx, bytesConsumed, e); bytesConsumed = 0; } break; } else { switch (result.getHandshakeStatus()) { case NEED_WRAP: ctx.flush(); continue; case NEED_UNWRAP: if (ctx.inboundByteBuffer().readable()) { unwrapLater = true; } break; case NEED_TASK: runDelegatedTasks(); continue; case FINISHED: setHandshakeSuccess(); continue; case NOT_HANDSHAKING: break; default: throw new IllegalStateException( "Unknown handshake status: " + result.getHandshakeStatus()); } if (result.bytesConsumed() == 0 && result.bytesProduced() == 0) { break; } } } if (unwrapLater) { inboundBufferUpdated(ctx); } } catch (SSLException e) { setHandshakeFailure(e); throw e; } finally { in.unsafe().discardSomeReadBytes(); flush0(ctx, bytesConsumed); } }