下面列出了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);
}
}
}
}
@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);
}
/**
* 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();
}
@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);
}
@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);
}
@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);
}
@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);
}
@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());
}
@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);
}
}
@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);
}
}
@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);
}
@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);
}
@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);
}
@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);
}
@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);
}
@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);
}
@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"));
}