Open weissi opened 2 weeks ago
Thanks @glbrntt , this could be a reentrancy bug
public func channelActive(context: ChannelHandlerContext) {
// We fire this a bit early, entirely on purpose. This is because
// in doHandshakeStep we may end up closing the channel again, and
// if we do we want to make sure that the channelInactive message received
// by later channel handlers makes sense.
context.fireChannelActive()
doHandshakeStep(context: context)
}
So we're calling out before calling doHandshakeStep
. This intern then triggers the implicit handshake in BoringSSL. Maybe we think that we'd never trigger the implicit handshake.
Possible that reversing those two lines will fix it because we never do the implicit handshake in BoringSSL.
NIOSSLHandler
sees the following channel events:
handlerAdded
close
(triggered from a Channel.close()
)channelInactive
(triggered from BaseSocketChannel.close0
) [BUG HERE (channelInactive
without channelActive
)]channelActive
(triggered from BaseSocketChannel.writable
-> BaseSocketChannel.finishConnect
-> BaseSocketChannel.becomeActive()
) [BUG HERE (channelActive
after channelInactive
)]Obviously those channel events are wrong. That's a bug in NIO too.
NIOSSL has the following loop
Precisely what happens is this:
NIOSSLHandler.channelActive
WebsocketClientHandshakeHander.channelActive
issues awriteAndFlush
NIOSSLHandler.flush
SSLConnection.writeDataToNetwork
SSL_write
(namespaced toCNIOBoringSSL_SSL_write
)ssl_can_write
which says false// If necessary, complete the handshake implicitly.
) handshake throughSSL_do_handshake
which returns-1
(andSSL_ERROR_WANT_READ
)writeDataToNetwork
return.incomplete
which makes_encodeSingleWrite
returnfalse