Exemplo n.º 1
0
  public void handleDownstream(final ChannelHandlerContext context, final ChannelEvent evt)
      throws Exception {
    if (evt instanceof ChannelStateEvent) {
      ChannelStateEvent e = (ChannelStateEvent) evt;
      switch (e.getState()) {
        case OPEN:
        case CONNECTED:
        case BOUND:
          if (Boolean.FALSE.equals(e.getValue()) || e.getValue() == null) {
            closeOutboundAndChannel(context, e);
            return;
          }
      }
    }
    if (!(evt instanceof MessageEvent)) {
      context.sendDownstream(evt);
      return;
    }

    MessageEvent e = (MessageEvent) evt;
    if (!(e.getMessage() instanceof ChannelBuffer)) {
      context.sendDownstream(evt);
      return;
    }

    // Do not encrypt the first write request if this handler is
    // created with startTLS flag turned on.
    if (startTls && sentFirstMessage.compareAndSet(false, true)) {
      context.sendDownstream(evt);
      return;
    }

    // Otherwise, all messages are encrypted.
    ChannelBuffer msg = (ChannelBuffer) e.getMessage();
    PendingWrite pendingWrite;

    if (msg.readable()) {
      pendingWrite =
          new PendingWrite(
              evt.getFuture(), msg.toByteBuffer(msg.readerIndex(), msg.readableBytes()));
    } else {
      pendingWrite = new PendingWrite(evt.getFuture(), null);
    }
    synchronized (pendingUnencryptedWrites) {
      boolean offered = pendingUnencryptedWrites.offer(pendingWrite);
      assert offered;
    }

    wrap(context, evt.getChannel());
  }
Exemplo n.º 2
0
  private ChannelBuffer unwrap(
      ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, int offset, int length)
      throws SSLException {
    ByteBuffer inNetBuf = buffer.toByteBuffer(offset, length);
    ByteBuffer outAppBuf = bufferPool.acquire();

    try {
      boolean needsWrap = false;
      loop:
      for (; ; ) {
        SSLEngineResult result;
        synchronized (handshakeLock) {
          if (!handshaken
              && !handshaking
              && !engine.getUseClientMode()
              && !engine.isInboundDone()
              && !engine.isOutboundDone()) {
            handshake();
          }

          try {
            result = engine.unwrap(inNetBuf, outAppBuf);
          } catch (SSLException e) {
            throw e;
          }

          final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
          handleRenegotiation(handshakeStatus);
          switch (handshakeStatus) {
            case NEED_UNWRAP:
              if (inNetBuf.hasRemaining() && !engine.isInboundDone()) {
                break;
              } else {
                break loop;
              }
            case NEED_WRAP:
              wrapNonAppData(ctx, channel);
              break;
            case NEED_TASK:
              runDelegatedTasks();
              break;
            case FINISHED:
              setHandshakeSuccess(channel);
              needsWrap = true;
              break loop;
            case NOT_HANDSHAKING:
              needsWrap = true;
              break loop;
            default:
              throw new IllegalStateException("Unknown handshake status: " + handshakeStatus);
          }
        }
      }

      if (needsWrap) {
        // wrap() acquires pendingUnencryptedWrites first and then
        // handshakeLock.  If handshakeLock is already hold by the
        // current thread, calling wrap() will lead to a dead lock
        // i.e. pendingUnencryptedWrites -> handshakeLock vs.
        //      handshakeLock -> pendingUnencryptedLock -> handshakeLock
        //
        // There is also a same issue between pendingEncryptedWrites
        // and pendingUnencryptedWrites.
        if (!Thread.holdsLock(handshakeLock)
            && !pendingEncryptedWritesLock.isHeldByCurrentThread()) {
          wrap(ctx, channel);
        }
      }

      outAppBuf.flip();

      if (outAppBuf.hasRemaining()) {
        ChannelBuffer frame = ChannelBuffers.buffer(outAppBuf.remaining());
        frame.writeBytes(outAppBuf.array(), 0, frame.capacity());
        return frame;
      } else {
        return null;
      }
    } catch (SSLException e) {
      setHandshakeFailure(channel, e);
      throw e;
    } finally {
      bufferPool.release(outAppBuf);
    }
  }