io.netty.channel.socket.ChannelInputShutdownReadComplete#io.netty.handler.ssl.SslHandshakeCompletionEvent源码实例Demo

下面列出了io.netty.channel.socket.ChannelInputShutdownReadComplete#io.netty.handler.ssl.SslHandshakeCompletionEvent 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

@Test
public void tlsHandler_userEventTriggeredSslEvent_unsupportedProtocol() throws Exception {
  SslHandler badSslHandler = new SslHandler(engine, false) {
    @Override
    public String applicationProtocol() {
      return "badprotocol";
    }
  };

  ChannelHandler handler = new ServerTlsHandler(sslContext, grpcHandler);
  pipeline.addLast(handler);

  pipeline.replace(SslHandler.class, null, badSslHandler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);

  // No h2 protocol was specified, so this should be closed.
  assertFalse(channel.isOpen());
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNull(grpcHandlerCtx);
}
 
@Test
public void tlsHandler_userEventTriggeredSslEvent_supportedProtocolH2() throws Exception {
  SslHandler goodSslHandler = new SslHandler(engine, false) {
    @Override
    public String applicationProtocol() {
      return "h2";
    }
  };

  ChannelHandler handler = new ServerTlsHandler(sslContext, grpcHandler);
  pipeline.addLast(handler);

  pipeline.replace(SslHandler.class, null, goodSslHandler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);

  assertTrue(channel.isOpen());
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNotNull(grpcHandlerCtx);
}
 
@Test
public void tlsHandler_userEventTriggeredSslEvent_supportedProtocolGrpcExp() throws Exception {
  SslHandler goodSslHandler = new SslHandler(engine, false) {
    @Override
    public String applicationProtocol() {
      return "grpc-exp";
    }
  };

  ChannelHandler handler = new ServerTlsHandler(sslContext, grpcHandler);
  pipeline.addLast(handler);

  pipeline.replace(SslHandler.class, null, goodSslHandler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);

  assertTrue(channel.isOpen());
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNotNull(grpcHandlerCtx);
}
 
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) throws Exception {

    if (!(evt instanceof SslHandshakeCompletionEvent)) {
        super.userEventTriggered(ctx, evt);
        return;
    }

    final Channel channel = ctx.channel();
    final SslHandler sslHandler = (SslHandler) channel.pipeline().get(ChannelHandlerNames.SSL_HANDLER);
    final SSLSession session = sslHandler.engine().getSession();
    channel.attr(ChannelAttributes.AUTH_CIPHER_SUITE).set(session.getCipherSuite());
    channel.attr(ChannelAttributes.AUTH_PROTOCOL).set(session.getProtocol());

    channel.pipeline().remove(this);

    super.userEventTriggered(ctx, evt);
}
 
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof SslHandshakeCompletionEvent) {
        SslHandshakeCompletionEvent handshakeEvt = (SslHandshakeCompletionEvent) evt;
        if (handshakeCounter == 0) {
            handshakeCounter++;
            if (handshakeEvt.cause() != null) {
                logger.warn("Handshake failed:", handshakeEvt.cause());
            }
            assertSame(SslHandshakeCompletionEvent.SUCCESS, evt);
        } else {
            if (ctx.channel().parent() == null) {
                assertTrue(handshakeEvt.cause() instanceof ClosedChannelException);
            }
        }
    }
}
 
源代码6 项目: servicetalk   文件: DefaultNettyConnection.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
    if (evt == CloseHandler.ProtocolPayloadEndEvent.OUTBOUND) {
        connection.channelOutboundListener.channelOutboundClosed();
    } else if (evt == ChannelOutputShutdownEvent.INSTANCE) {
        connection.closeHandler.channelClosedOutbound(ctx);
        connection.channelOutboundListener.channelClosed(StacklessClosedChannelException.newInstance(
                DefaultNettyConnection.class, "userEventTriggered(...)"));
    } else if (evt == ChannelInputShutdownReadComplete.INSTANCE) {
        // Notify close handler first to enhance error reporting
        connection.closeHandler.channelClosedInbound(ctx);
        // ChannelInputShutdownEvent is not always triggered and can get triggered before we tried to read
        // all the available data. ChannelInputShutdownReadComplete is the one that seems to (at least in
        // the current netty version) gets triggered reliably at the appropriate time.
        connection.nettyChannelPublisher.channelInboundClosed();
    } else if (evt instanceof SslHandshakeCompletionEvent) {
        connection.sslSession = extractSslSession(ctx.pipeline(), (SslHandshakeCompletionEvent) evt,
                this::tryFailSubscriber);
        if (subscriber != null) {
            assert waitForSslHandshake;
            completeSubscriber();
        }
    }
    ctx.fireUserEventTriggered(evt);
}
 
源代码7 项目: servicetalk   文件: NettyPipelineSslUtils.java
/**
 * Extract the {@link SSLSession} from the {@link ChannelPipeline} if the {@link SslHandshakeCompletionEvent}
 * is successful.
 *
 * @param pipeline the {@link ChannelPipeline} which contains handler containing the {@link SSLSession}.
 * @param sslEvent the event indicating a SSL/TLS handshake completed.
 * @param failureConsumer invoked if a failure is encountered.
 * @return The {@link SSLSession} or {@code null} if none can be found.
 */
@Nullable
public static SSLSession extractSslSession(ChannelPipeline pipeline,
                                           SslHandshakeCompletionEvent sslEvent,
                                           Consumer<Throwable> failureConsumer) {
    if (sslEvent.isSuccess()) {
        final SslHandler sslHandler = pipeline.get(SslHandler.class);
        if (sslHandler != null) {
            return sslHandler.engine().getSession();
        } else {
            failureConsumer.accept(new IllegalStateException("Unable to find " + SslHandler.class.getName() +
                    " in the pipeline."));
        }
    } else {
        failureConsumer.accept(sslEvent.cause());
    }
    return null;
}
 
@Test
public void noDeferSslHandler() {
    ChannelPipeline pipeline = configurePipeline(SslHandshakeCompletionEvent.SUCCESS);
    // Do not configureDeferSslHandler(pipeline);
    configureConnectionContext(pipeline);
    configureRequestSend();
    configureConnectRequest();
    subscribeToProxyConnectionFactory();

    assertThat(subscriber.isErrored(), is(true));
    Throwable error = subscriber.error();
    assertThat(error, is(notNullValue()));
    assertThat(error, instanceOf(IllegalStateException.class));
    assertThat(error.getMessage(), containsString(DeferSslHandler.class.getSimpleName()));
    assertConnectPayloadConsumed(false);
    assertConnectionClosed();
}
 
源代码9 项目: armeria   文件: HttpServerHandler.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof SslHandshakeCompletionEvent) {
        final SslHandler sslHandler = ctx.channel().pipeline().get(SslHandler.class);
        sslSession = sslHandler != null ? sslHandler.engine().getSession() : null;
        return;
    }

    if (evt instanceof SslCloseCompletionEvent ||
        evt instanceof ChannelInputShutdownReadComplete) {
        // Expected events
        return;
    }

    logger.warn("{} Unexpected user event: {}", ctx.channel(), evt);
}
 
源代码10 项目: LittleProxy-mitm   文件: RetryClient.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
        throws Exception {
    LOG.info(">>> userEventTriggered " + evt);
    if (evt instanceof SslHandshakeCompletionEvent) {
        SslHandshakeCompletionEvent hce = (SslHandshakeCompletionEvent) evt;
        if (!hce.isSuccess()
                && hce.cause().getMessage().contains("unrecognized_name")) {
            LOG.info(">>> unrecognized_name");
            ctx.close();
            unrecognizedName = true;
            return;
        }
    }
    super.userEventTriggered(ctx, evt);
}
 
源代码11 项目: LittleProxy-mitm   文件: RestartClient.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
        throws Exception {
    LOG.info(">>> userEventTriggered " + evt);
    if (evt instanceof SslHandshakeCompletionEvent) {
        SslHandshakeCompletionEvent hce = (SslHandshakeCompletionEvent) evt;
        if (!hce.isSuccess()
                && hce.cause().getMessage()
                        .contains("unrecognized_name")) {
            LOG.info(">>> unrecognized_name");
            ctx.close();
            unrecognizedName = true;
            return;
        }
    }
    super.userEventTriggered(ctx, evt);
}
 
源代码12 项目: xio   文件: MutualAuthHandler.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
  if (evt instanceof SslHandshakeCompletionEvent) {
    ctx.pipeline().remove(this);

    SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
    String peerIdentity = TlsAuthState.UNAUTHENTICATED;
    if (handshakeEvent.isSuccess()) {
      SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
      if (sslHandler == null) {
        throw new IllegalStateException(
            "cannot find a SslHandler in the pipeline (required for MutualAuthHandler)");
      }
      peerIdentity = getPeerIdentity(sslHandler.engine());
    }
    TlsAuthState.setPeerIdentity(ctx, peerIdentity);
    peerIdentityEstablished(ctx, peerIdentity);
  }

  ctx.fireUserEventTriggered(evt);
}
 
源代码13 项目: grpc-java   文件: SdsProtocolNegotiatorsTest.java
@Test
public void clientSdsProtocolNegotiatorNewHandler_fireProtocolNegotiationEvent()
    throws IOException, InterruptedException {
  UpstreamTlsContext upstreamTlsContext =
      buildUpstreamTlsContextFromFilenames(CLIENT_KEY_FILE, CLIENT_PEM_FILE, CA_PEM_FILE);

  SdsProtocolNegotiators.ClientSdsHandler clientSdsHandler =
      new SdsProtocolNegotiators.ClientSdsHandler(grpcHandler, upstreamTlsContext);

  pipeline.addLast(clientSdsHandler);
  channelHandlerCtx = pipeline.context(clientSdsHandler);
  assertNotNull(channelHandlerCtx); // non-null since we just added it

  // kick off protocol negotiation.
  pipeline.fireUserEventTriggered(InternalProtocolNegotiationEvent.getDefault());
  channel.runPendingTasks(); // need this for tasks to execute on eventLoop
  channelHandlerCtx = pipeline.context(clientSdsHandler);
  assertThat(channelHandlerCtx).isNull();
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);
  channel.runPendingTasks(); // need this for tasks to execute on eventLoop
  assertTrue(channel.isOpen());
}
 
源代码14 项目: grpc-java   文件: ProtocolNegotiators.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  if (evt instanceof ProtocolNegotiationEvent) {
    pne = (ProtocolNegotiationEvent) evt;
  } else if (evt instanceof SslHandshakeCompletionEvent) {
    SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
    if (!handshakeEvent.isSuccess()) {
      logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed for new client.", null);
      ctx.fireExceptionCaught(handshakeEvent.cause());
      return;
    }
    SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
    if (!sslContext.applicationProtocolNegotiator().protocols().contains(
            sslHandler.applicationProtocol())) {
      logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed for new client.", null);
      ctx.fireExceptionCaught(unavailableException(
          "Failed protocol negotiation: Unable to find compatible protocol"));
      return;
    }
    ctx.pipeline().replace(ctx.name(), null, next);
    fireProtocolNegotiationEvent(ctx, sslHandler.engine().getSession());
  } else {
    super.userEventTriggered(ctx, evt);
  }
}
 
源代码15 项目: grpc-java   文件: ProtocolNegotiators.java
@Override
protected void userEventTriggered0(ChannelHandlerContext ctx, Object evt) throws Exception {
  if (evt instanceof SslHandshakeCompletionEvent) {
    SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
    if (handshakeEvent.isSuccess()) {
      SslHandler handler = ctx.pipeline().get(SslHandler.class);
      if (sslContext.applicationProtocolNegotiator().protocols()
          .contains(handler.applicationProtocol())) {
        // Successfully negotiated the protocol.
        logSslEngineDetails(Level.FINER, ctx, "TLS negotiation succeeded.", null);
        propagateTlsComplete(ctx, handler.engine().getSession());
      } else {
        Exception ex =
            unavailableException("Failed ALPN negotiation: Unable to find compatible protocol");
        logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed.", ex);
        ctx.fireExceptionCaught(ex);
      }
    } else {
      ctx.fireExceptionCaught(handshakeEvent.cause());
    }
  } else {
    super.userEventTriggered0(ctx, evt);
  }
}
 
源代码16 项目: grpc-java   文件: ProtocolNegotiatorsTest.java
@Test
public void tlsHandler_userEventTriggeredSslEvent_handshakeFailure() throws Exception {
  ChannelHandler handler = new ServerTlsHandler(grpcHandler, sslContext, null);
  pipeline.addLast(handler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = new SslHandshakeCompletionEvent(new RuntimeException("bad"));

  final AtomicReference<Throwable> error = new AtomicReference<>();
  ChannelHandler errorCapture = new ChannelInboundHandlerAdapter() {
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
      error.set(cause);
    }
  };

  pipeline.addLast(errorCapture);

  pipeline.fireUserEventTriggered(sslEvent);

  // No h2 protocol was specified, so there should be an error, (normally handled by WBAEH)
  assertThat(error.get()).hasMessageThat().contains("bad");
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNull(grpcHandlerCtx);
}
 
源代码17 项目: grpc-java   文件: ProtocolNegotiatorsTest.java
@Test
public void tlsHandler_userEventTriggeredSslEvent_supportedProtocolH2() throws Exception {
  SslHandler goodSslHandler = new SslHandler(engine, false) {
    @Override
    public String applicationProtocol() {
      return "h2";
    }
  };

  ChannelHandler handler = new ServerTlsHandler(grpcHandler, sslContext, null);
  pipeline.addLast(handler);

  pipeline.replace(SslHandler.class, null, goodSslHandler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);

  assertTrue(channel.isOpen());
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNotNull(grpcHandlerCtx);
}
 
源代码18 项目: grpc-java   文件: ProtocolNegotiatorsTest.java
@Test
public void clientTlsHandler_userEventTriggeredSslEvent_supportedProtocolH2() throws Exception {
  SslHandler goodSslHandler = new SslHandler(engine, false) {
    @Override
    public String applicationProtocol() {
      return "h2";
    }
  };
  DefaultEventLoopGroup elg = new DefaultEventLoopGroup(1);

  ClientTlsHandler handler = new ClientTlsHandler(grpcHandler, sslContext, "authority", elg);
  pipeline.addLast(handler);
  pipeline.replace(SslHandler.class, null, goodSslHandler);
  pipeline.fireUserEventTriggered(ProtocolNegotiationEvent.DEFAULT);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = SslHandshakeCompletionEvent.SUCCESS;

  pipeline.fireUserEventTriggered(sslEvent);

  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNotNull(grpcHandlerCtx);
}
 
源代码19 项目: grpc-nebula-java   文件: ProtocolNegotiators.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  if (evt instanceof SslHandshakeCompletionEvent) {
    SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
    if (handshakeEvent.isSuccess()) {
      if (NEXT_PROTOCOL_VERSIONS.contains(sslHandler(ctx.pipeline()).applicationProtocol())) {
        SSLSession session = sslHandler(ctx.pipeline()).engine().getSession();
        // Successfully negotiated the protocol.
        // Notify about completion and pass down SSLSession in attributes.
        grpcHandler.handleProtocolNegotiationCompleted(
            Attributes.newBuilder()
                .set(Grpc.TRANSPORT_ATTR_SSL_SESSION, session)
                .set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, ctx.channel().remoteAddress())
                .set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, ctx.channel().localAddress())
                .build(),
            new InternalChannelz.Security(new InternalChannelz.Tls(session)));
        // Replace this handler with the GRPC handler.
        ctx.pipeline().replace(this, null, grpcHandler);
      } else {
        fail(ctx, new Exception(
            "Failed protocol negotiation: Unable to find compatible protocol."));
      }
    } else {
      fail(ctx, handshakeEvent.cause());
    }
  }
  super.userEventTriggered(ctx, evt);
}
 
源代码20 项目: grpc-nebula-java   文件: ProtocolNegotiators.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  if (evt instanceof SslHandshakeCompletionEvent) {
    SslHandshakeCompletionEvent handshakeEvent = (SslHandshakeCompletionEvent) evt;
    if (handshakeEvent.isSuccess()) {
      SslHandler handler = ctx.pipeline().get(SslHandler.class);
      if (NEXT_PROTOCOL_VERSIONS.contains(handler.applicationProtocol())) {
        // Successfully negotiated the protocol.
        logSslEngineDetails(Level.FINER, ctx, "TLS negotiation succeeded.", null);

        // Wait until negotiation is complete to add gRPC.   If added too early, HTTP/2 writes
        // will fail before we see the userEvent, and the channel is closed down prematurely.
        ctx.pipeline().addBefore(ctx.name(), null, grpcHandler);

        SSLSession session = handler.engine().getSession();
        // Successfully negotiated the protocol.
        // Notify about completion and pass down SSLSession in attributes.
        grpcHandler.handleProtocolNegotiationCompleted(
            Attributes.newBuilder()
                .set(Grpc.TRANSPORT_ATTR_SSL_SESSION, session)
                .set(Grpc.TRANSPORT_ATTR_REMOTE_ADDR, ctx.channel().remoteAddress())
                .set(Grpc.TRANSPORT_ATTR_LOCAL_ADDR, ctx.channel().localAddress())
                .set(GrpcAttributes.ATTR_SECURITY_LEVEL, SecurityLevel.PRIVACY_AND_INTEGRITY)
                .build(),
            new InternalChannelz.Security(new InternalChannelz.Tls(session)));
        writeBufferedAndRemove(ctx);
      } else {
        Exception ex = new Exception(
            "Failed ALPN negotiation: Unable to find compatible protocol.");
        logSslEngineDetails(Level.FINE, ctx, "TLS negotiation failed.", ex);
        fail(ctx, ex);
      }
    } else {
      fail(ctx, handshakeEvent.cause());
    }
  }
  super.userEventTriggered(ctx, evt);
}
 
源代码21 项目: grpc-nebula-java   文件: ProtocolNegotiatorsTest.java
@Test
public void tlsHandler_userEventTriggeredSslEvent_handshakeFailure() throws Exception {
  ChannelHandler handler = new ServerTlsHandler(sslContext, grpcHandler);
  pipeline.addLast(handler);
  channelHandlerCtx = pipeline.context(handler);
  Object sslEvent = new SslHandshakeCompletionEvent(new RuntimeException("bad"));

  pipeline.fireUserEventTriggered(sslEvent);

  // No h2 protocol was specified, so this should be closed.
  assertFalse(channel.isOpen());
  ChannelHandlerContext grpcHandlerCtx = pipeline.context(grpcHandler);
  assertNull(grpcHandlerCtx);
}
 
源代码22 项目: r2dbc-mysql   文件: SslBridgeHandler.java
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    if (evt instanceof SslState) {
        handleSslState(ctx, (SslState) evt);
        // Ignore event trigger for next handler, because it used only by this handler.
        return;
    }

    if (SslHandshakeCompletionEvent.SUCCESS == evt) {
        handleSslCompleted(ctx);
    }

    super.userEventTriggered(ctx, evt);
}
 
@Override
public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) throws Exception {

    if (!(evt instanceof SslHandshakeCompletionEvent)) {
        super.userEventTriggered(ctx, evt);
        return;
    }

    final SslHandshakeCompletionEvent sslHandshakeCompletionEvent = (SslHandshakeCompletionEvent) evt;

    if (!sslHandshakeCompletionEvent.isSuccess()) {
        log.trace("Handshake failed", sslHandshakeCompletionEvent.cause());
        return;
    }

    final Channel channel = ctx.channel();

    try {
        final SslHandler sslHandler = (SslHandler) channel.pipeline().get(ChannelHandlerNames.SSL_HANDLER);

        final SSLSession session = sslHandler.engine().getSession();
        final Certificate[] peerCertificates = session.getPeerCertificates();
        final SslClientCertificate sslClientCertificate = new SslClientCertificateImpl(peerCertificates);
        channel.attr(ChannelAttributes.AUTH_CERTIFICATE).set(sslClientCertificate);

    } catch (final SSLPeerUnverifiedException e) {
        handleSslPeerUnverifiedException(channel, e);

    } catch (final ClassCastException e2) {
        eventLog.clientWasDisconnected(channel, "SSL handshake failed");
        channel.close();
        throw new RuntimeException("Not able to get SslHandler from pipeline", e2);
    }

    channel.pipeline().remove(this);

}
 
@Test
public void test_ssl_completion_user_event() {
    when(sslHandler.engine()).thenReturn(sslEngine);
    when(sslEngine.getSession()).thenReturn(sslSession);
    when(sslSession.getCipherSuite()).thenReturn("CipherSuite");
    when(sslSession.getProtocol()).thenReturn("Protocol");
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);
    assertEquals("Protocol", channel.attr(ChannelAttributes.AUTH_PROTOCOL).get());
    assertEquals("CipherSuite", channel.attr(ChannelAttributes.AUTH_CIPHER_SUITE).get());
    assertNull(channel.pipeline().get(SslParameterHandler.class));
}
 
@Test
public void test_peer_not_authenticated_but_required() throws SSLPeerUnverifiedException, InterruptedException {

    when(tls.getClientAuthMode()).thenReturn(Tls.ClientAuthMode.REQUIRED);
    when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("peer not authenticated"));
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog).clientWasDisconnected(eq(channel), anyString());
}
 
@Test
public void test_peer_not_authenticated_but_optional() throws SSLPeerUnverifiedException, InterruptedException {

    when(tls.getClientAuthMode()).thenReturn(Tls.ClientAuthMode.OPTIONAL);
    when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("peer not authenticated"));
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog, never()).clientWasDisconnected(eq(channel), anyString());
}
 
@Test
public void test_peer_not_verified_but_required() throws SSLPeerUnverifiedException, InterruptedException {

    when(tls.getClientAuthMode()).thenReturn(Tls.ClientAuthMode.REQUIRED);
    when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("peer not verified"));
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog).clientWasDisconnected(eq(channel), anyString());
}
 
@Test
public void test_peer_not_verified_but_optional() throws SSLPeerUnverifiedException, InterruptedException {

    when(tls.getClientAuthMode()).thenReturn(Tls.ClientAuthMode.OPTIONAL);
    when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("peer not verified"));
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog, never()).clientWasDisconnected(eq(channel), anyString());
}
 
@Test
public void test_peer_other_exception() throws SSLPeerUnverifiedException, InterruptedException {

    when(tls.getClientAuthMode()).thenReturn(Tls.ClientAuthMode.OPTIONAL);
    when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException("other exception"));
    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog).clientWasDisconnected(eq(channel), eq("SSL handshake failed"));
}
 
@Test
public void test_class_cast_exception_no_ssl_handler() throws SSLPeerUnverifiedException, InterruptedException {

    channel = new EmbeddedChannel();
    channel.pipeline().addLast(new SslClientCertificateHandler(tls, eventLog));
    channel.pipeline().addLast(ChannelHandlerNames.SSL_HANDLER, new WrongHandler());

    channel.pipeline().fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);

    verify(eventLog).clientWasDisconnected(eq(channel), eq("SSL handshake failed"));
}