Class SslHandler
- java.lang.Object
-
- io.netty.channel.ChannelHandlerAdapter
-
- io.netty.channel.ChannelInboundHandlerAdapter
-
- io.netty.handler.codec.ByteToMessageDecoder
-
- io.netty.handler.ssl.SslHandler
-
- All Implemented Interfaces:
ChannelHandler
,ChannelInboundHandler
,ChannelOutboundHandler
public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundHandler
Adds SSL · TLS and StartTLS support to aChannel
. Please refer to the "SecureChat" example in the distribution or the web site for the detailed usage.Beginning the handshake
Beside using the handshake
ChannelFuture
to get notified about the completion of the handshake it's also possible to detect it by implement theChannelInboundHandler.userEventTriggered(ChannelHandlerContext, Object)
method and check for aSslHandshakeCompletionEvent
.Handshake
The handshake will be automatically issued for you once the
Channel
is active andSSLEngine.getUseClientMode()
returnstrue
. So no need to bother with it by your self.Closing the session
To close the SSL session, the
closeOutbound()
method should be called to send theclose_notify
message to the remote peer. One exception is when you close theChannel
-SslHandler
intercepts the close request and send theclose_notify
message before the channel closure automatically. Once the SSL session is closed, it is not reusable, and consequently you should create a newSslHandler
with a newSSLEngine
as explained in the following section.Restarting the session
To restart the SSL session, you must remove the existing closed
SslHandler
from theChannelPipeline
, insert a newSslHandler
with a newSSLEngine
into the pipeline, and start the handshake process as described in the first section.Implementing StartTLS
StartTLS is the communication pattern that secures the wire in the middle of the plaintext connection. Please note that it is different from SSL · TLS, that secures the wire from the beginning of the connection. Typically, StartTLS is composed of three steps:
- Client sends a StartTLS request to server.
- Server sends a StartTLS response to client.
- Client begins SSL handshake.
- create a new
SslHandler
instance withstartTls
flag set totrue
, - insert the
SslHandler
to theChannelPipeline
, and - write a StartTLS response.
SslHandler
before sending the StartTLS response. Otherwise the client can send begin SSL handshake beforeSslHandler
is inserted to theChannelPipeline
, causing data corruption.The client-side implementation is much simpler.
- Write a StartTLS request,
- wait for the StartTLS response,
- create a new
SslHandler
instance withstartTls
flag set tofalse
, - insert the
SslHandler
to theChannelPipeline
, and - Initiate SSL handshake.
Known issues
Because of a known issue with the current implementation of the SslEngine that comes with Java it may be possible that you see blocked IO-Threads while a full GC is done.
So if you are affected you can workaround this problem by adjust the cache settings like shown below:
SslContext context = ...; context.getServerSessionContext().setSessionCacheSize(someSaneSize); context.getServerSessionContext().setSessionTime(someSameTimeout);
What values to use here depends on the nature of your application and should be set based on monitoring and debugging of it. For more details see #832 in our issue tracker.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private class
SslHandler.AsyncTaskCompletionHandler
private class
SslHandler.LazyChannelPromise
private static class
SslHandler.SslEngineType
private class
SslHandler.SslTasksRunner
Runnable
that will be scheduled on thedelegatedTaskExecutor
and will take care of resume work on theEventExecutor
once the task was executed.-
Nested classes/interfaces inherited from class io.netty.handler.codec.ByteToMessageDecoder
ByteToMessageDecoder.Cumulator
-
Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler
ChannelHandler.Sharable
-
-
Field Summary
Fields Modifier and Type Field Description private long
closeNotifyFlushTimeoutMillis
private long
closeNotifyReadTimeoutMillis
private ChannelHandlerContext
ctx
private java.util.concurrent.Executor
delegatedTaskExecutor
private javax.net.ssl.SSLEngine
engine
private SslHandler.SslEngineType
engineType
private Promise<Channel>
handshakePromise
private long
handshakeTimeoutMillis
private static java.util.regex.Pattern
IGNORABLE_CLASS_IN_STACK
private static java.util.regex.Pattern
IGNORABLE_ERROR_MESSAGE
private boolean
jdkCompatibilityMode
private static InternalLogger
logger
private static int
MAX_PLAINTEXT_LENGTH
2^14 which is the maximum sized plaintext chunk allowed by the TLS RFC.private int
packetLength
private SslHandlerCoalescingBufferQueue
pendingUnencryptedWrites
private ResumptionController
resumptionController
private java.nio.ByteBuffer[]
singleBuffer
Used ifSSLEngine.wrap(ByteBuffer[], ByteBuffer)
andSSLEngine.unwrap(ByteBuffer, ByteBuffer[])
should be called with aByteBuf
that is only backed by oneByteBuffer
to reduce the object creation.private SslHandler.LazyChannelPromise
sslClosePromise
private SslHandler.SslTasksRunner
sslTaskRunner
private SslHandler.SslTasksRunner
sslTaskRunnerForUnwrap
private boolean
startTls
private short
state
private static int
STATE_CLOSE_NOTIFY
private static int
STATE_FIRE_CHANNEL_READ
This flag is used to determine if we need to callChannelHandlerContext.read()
to consume more data whenChannelConfig.isAutoRead()
isfalse
.private static int
STATE_FLUSHED_BEFORE_HANDSHAKE
private static int
STATE_HANDSHAKE_STARTED
private static int
STATE_NEEDS_FLUSH
Set by wrap*() methods when something is produced.private static int
STATE_OUTBOUND_CLOSED
private static int
STATE_PROCESS_TASK
private static int
STATE_READ_DURING_HANDSHAKE
private static int
STATE_SENT_FIRST_MESSAGE
private static int
STATE_UNWRAP_REENTRY
(package private) int
wrapDataSize
-
Fields inherited from class io.netty.handler.codec.ByteToMessageDecoder
COMPOSITE_CUMULATOR, MERGE_CUMULATOR
-
-
Constructor Summary
Constructors Constructor Description SslHandler(javax.net.ssl.SSLEngine engine)
Creates a new instance which runs all delegated tasks directly on theEventExecutor
.SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls)
Creates a new instance which runs all delegated tasks directly on theEventExecutor
.SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls, java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls, java.util.concurrent.Executor delegatedTaskExecutor, ResumptionController resumptionController)
SslHandler(javax.net.ssl.SSLEngine engine, java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description private static void
addCloseListener(ChannelFuture future, ChannelPromise promise)
private ByteBuf
allocate(ChannelHandlerContext ctx, int capacity)
Always prefer a direct buffer when it's pooled, so that we reduce the number of memory copies inOpenSslEngine
.private ByteBuf
allocateOutNetBuf(ChannelHandlerContext ctx, int pendingBytes, int numComponents)
Allocates an outbound network buffer forSSLEngine.wrap(ByteBuffer, ByteBuffer)
which can encrypt the specified amount of pending bytes.java.lang.String
applicationProtocol()
Returns the name of the current application-level protocol.private void
applyHandshakeTimeout()
void
bind(ChannelHandlerContext ctx, java.net.SocketAddress localAddress, ChannelPromise promise)
Called once a bind operation is made.void
channelActive(ChannelHandlerContext ctx)
Issues an initial TLS handshake once connected when used in client-modevoid
channelInactive(ChannelHandlerContext ctx)
CallsChannelHandlerContext.fireChannelInactive()
to forward to the nextChannelInboundHandler
in theChannelPipeline
.void
channelReadComplete(ChannelHandlerContext ctx)
CallsChannelHandlerContext.fireChannelReadComplete()
to forward to the nextChannelInboundHandler
in theChannelPipeline
.private void
channelReadComplete0(ChannelHandlerContext ctx)
private void
clearState(int bit)
ChannelFuture
close()
Deprecated.void
close(ChannelHandlerContext ctx, ChannelPromise promise)
Called once a close operation is made.ChannelFuture
close(ChannelPromise promise)
Deprecated.ChannelFuture
closeOutbound()
Sends an SSLclose_notify
message to the specified channel and destroys the underlyingSSLEngine
.ChannelFuture
closeOutbound(ChannelPromise promise)
Sends an SSLclose_notify
message to the specified channel and destroys the underlyingSSLEngine
.private void
closeOutbound0(ChannelPromise promise)
private void
closeOutboundAndChannel(ChannelHandlerContext ctx, ChannelPromise promise, boolean disconnect)
void
connect(ChannelHandlerContext ctx, java.net.SocketAddress remoteAddress, java.net.SocketAddress localAddress, ChannelPromise promise)
Called once a connect operation is made.protected void
decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out)
Decode the from oneByteBuf
to an other.private void
decodeJdkCompatible(ChannelHandlerContext ctx, ByteBuf in)
private void
decodeNonJdkCompatible(ChannelHandlerContext ctx, ByteBuf in)
void
deregister(ChannelHandlerContext ctx, ChannelPromise promise)
Called once a deregister operation is made from the current registeredEventLoop
.void
disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
Called once a disconnect operation is made.javax.net.ssl.SSLEngine
engine()
Returns theSSLEngine
which is used by this handler.void
exceptionCaught(ChannelHandlerContext ctx, java.lang.Throwable cause)
CallsChannelHandlerContext.fireExceptionCaught(Throwable)
to forward to the nextChannelHandler
in theChannelPipeline
.private void
executeChannelRead(ChannelHandlerContext ctx, ByteBuf decodedOut)
private void
executeDelegatedTask(boolean inUnwrap)
private void
executeDelegatedTask(SslHandler.SslTasksRunner task)
private void
executeNotifyClosePromise(ChannelHandlerContext ctx)
void
flush(ChannelHandlerContext ctx)
Called once a flush operation is made.private void
flush(ChannelHandlerContext ctx, ChannelPromise promise)
private void
flushIfNeeded(ChannelHandlerContext ctx)
private void
forceFlush(ChannelHandlerContext ctx)
long
getCloseNotifyFlushTimeoutMillis()
Gets the timeout for flushing the close_notify that was triggered by closing theChannel
.long
getCloseNotifyReadTimeoutMillis()
Gets the timeout (in ms) for receiving the response for the close_notify that was triggered by closing theChannel
.long
getCloseNotifyTimeoutMillis()
Deprecated.long
getHandshakeTimeoutMillis()
private SslHandler.SslTasksRunner
getTaskRunner(boolean inUnwrap)
void
handlerAdded(ChannelHandlerContext ctx)
Do nothing by default, sub-classes may override this method.void
handlerRemoved0(ChannelHandlerContext ctx)
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.private void
handleUnwrapThrowable(ChannelHandlerContext ctx, java.lang.Throwable cause)
private void
handshake(boolean flushAtEnd)
Performs TLS (re)negotiation.Future<Channel>
handshakeFuture()
Returns aFuture
that will get notified once the current TLS handshake completes.private boolean
ignoreException(java.lang.Throwable t)
Checks if the givenThrowable
can be ignore and just "swallowed" When an ssl connection is closed a close_notify message is sent.private static boolean
inEventLoop(java.util.concurrent.Executor executor)
static boolean
isEncrypted(ByteBuf buffer)
Deprecated.static boolean
isEncrypted(ByteBuf buffer, boolean probeSSLv2)
Returnstrue
if the givenByteBuf
is encrypted.private boolean
isStateSet(int bit)
private static java.lang.IllegalStateException
newPendingWritesNullException()
private void
notifyClosePromise(java.lang.Throwable cause)
void
read(ChannelHandlerContext ctx)
InterceptsChannelHandlerContext.read()
.private void
readIfNeeded(ChannelHandlerContext ctx)
private void
releaseAndFailAll(ChannelHandlerContext ctx, java.lang.Throwable cause)
Future<Channel>
renegotiate()
Performs TLS renegotiation.Future<Channel>
renegotiate(Promise<Channel> promise)
Performs TLS renegotiation.private void
renegotiateOnEventLoop(Promise<Channel> newHandshakePromise)
private boolean
runDelegatedTasks(boolean inUnwrap)
Will either run the delegated task directly callingRunnable.run()
and returntrue
or will offload the delegated task usingExecutor.execute(Runnable)
and returnfalse
.private void
safeClose(ChannelHandlerContext ctx, ChannelFuture flushFuture, ChannelPromise promise)
void
setCloseNotifyFlushTimeout(long closeNotifyFlushTimeout, java.util.concurrent.TimeUnit unit)
Sets the timeout for flushing the close_notify that was triggered by closing theChannel
.void
setCloseNotifyFlushTimeoutMillis(long closeNotifyFlushTimeoutMillis)
void
setCloseNotifyReadTimeout(long closeNotifyReadTimeout, java.util.concurrent.TimeUnit unit)
Sets the timeout for receiving the response for the close_notify that was triggered by closing theChannel
.void
setCloseNotifyReadTimeoutMillis(long closeNotifyReadTimeoutMillis)
void
setCloseNotifyTimeout(long closeNotifyTimeout, java.util.concurrent.TimeUnit unit)
Deprecated.void
setCloseNotifyTimeoutMillis(long closeNotifyFlushTimeoutMillis)
Deprecated.private void
setHandshakeFailure(ChannelHandlerContext ctx, java.lang.Throwable cause)
Notify all the handshake futures about the failure during the handshake.private void
setHandshakeFailure(ChannelHandlerContext ctx, java.lang.Throwable cause, boolean closeInbound, boolean notify, boolean alwaysFlushAndClose)
Notify all the handshake futures about the failure during the handshake.private void
setHandshakeFailureTransportFailure(ChannelHandlerContext ctx, java.lang.Throwable cause)
private boolean
setHandshakeSuccess()
Notify all the handshake futures about the successfully handshakeprivate boolean
setHandshakeSuccessUnwrapMarkReentry()
void
setHandshakeTimeout(long handshakeTimeout, java.util.concurrent.TimeUnit unit)
void
setHandshakeTimeoutMillis(long handshakeTimeoutMillis)
private void
setOpensslEngineSocketFd(Channel c)
private void
setState(int bit)
void
setWrapDataSize(int wrapDataSize)
Sets the number of bytes to pass to eachSSLEngine.wrap(ByteBuffer[], int, int, ByteBuffer)
call.Future<Channel>
sslCloseFuture()
Return theFuture
that will get notified if the inbound of theSSLEngine
is closed.private void
startHandshakeProcessing(boolean flushAtEnd)
private static java.nio.ByteBuffer
toByteBuffer(ByteBuf out, int index, int len)
private int
unwrap(ChannelHandlerContext ctx, ByteBuf packet, int length)
Unwraps inbound SSL records.private int
unwrapNonAppData(ChannelHandlerContext ctx)
CallsSSLEngine.unwrap(ByteBuffer, ByteBuffer)
with an empty buffer to handle handshakes, etc.private javax.net.ssl.SSLEngineResult
wrap(ByteBufAllocator alloc, javax.net.ssl.SSLEngine engine, ByteBuf in, ByteBuf out)
private void
wrap(ChannelHandlerContext ctx, boolean inUnwrap)
private void
wrapAndFlush(ChannelHandlerContext ctx)
private javax.net.ssl.SSLEngineResult
wrapMultiple(ByteBufAllocator alloc, javax.net.ssl.SSLEngine engine, ByteBuf in, ByteBuf out)
private boolean
wrapNonAppData(ChannelHandlerContext ctx, boolean inUnwrap)
void
write(ChannelHandlerContext ctx, java.lang.Object msg, ChannelPromise promise)
Called once a write operation is made.-
Methods inherited from class io.netty.handler.codec.ByteToMessageDecoder
actualReadableBytes, callDecode, channelRead, decodeLast, discardSomeReadBytes, handlerRemoved, internalBuffer, isSingleDecode, setCumulator, setDiscardAfterReads, setSingleDecode, userEventTriggered
-
Methods inherited from class io.netty.channel.ChannelInboundHandlerAdapter
channelRegistered, channelUnregistered, channelWritabilityChanged
-
Methods inherited from class io.netty.channel.ChannelHandlerAdapter
ensureNotSharable, isSharable
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface io.netty.channel.ChannelHandler
handlerRemoved
-
-
-
-
Field Detail
-
logger
private static final InternalLogger logger
-
IGNORABLE_CLASS_IN_STACK
private static final java.util.regex.Pattern IGNORABLE_CLASS_IN_STACK
-
IGNORABLE_ERROR_MESSAGE
private static final java.util.regex.Pattern IGNORABLE_ERROR_MESSAGE
-
STATE_SENT_FIRST_MESSAGE
private static final int STATE_SENT_FIRST_MESSAGE
- See Also:
- Constant Field Values
-
STATE_FLUSHED_BEFORE_HANDSHAKE
private static final int STATE_FLUSHED_BEFORE_HANDSHAKE
- See Also:
- Constant Field Values
-
STATE_READ_DURING_HANDSHAKE
private static final int STATE_READ_DURING_HANDSHAKE
- See Also:
- Constant Field Values
-
STATE_HANDSHAKE_STARTED
private static final int STATE_HANDSHAKE_STARTED
- See Also:
- Constant Field Values
-
STATE_NEEDS_FLUSH
private static final int STATE_NEEDS_FLUSH
Set by wrap*() methods when something is produced.channelReadComplete(ChannelHandlerContext)
will check this flag, clear it, and call ctx.flush().- See Also:
- Constant Field Values
-
STATE_OUTBOUND_CLOSED
private static final int STATE_OUTBOUND_CLOSED
- See Also:
- Constant Field Values
-
STATE_CLOSE_NOTIFY
private static final int STATE_CLOSE_NOTIFY
- See Also:
- Constant Field Values
-
STATE_PROCESS_TASK
private static final int STATE_PROCESS_TASK
- See Also:
- Constant Field Values
-
STATE_FIRE_CHANNEL_READ
private static final int STATE_FIRE_CHANNEL_READ
This flag is used to determine if we need to callChannelHandlerContext.read()
to consume more data whenChannelConfig.isAutoRead()
isfalse
.- See Also:
- Constant Field Values
-
STATE_UNWRAP_REENTRY
private static final int STATE_UNWRAP_REENTRY
- See Also:
- Constant Field Values
-
MAX_PLAINTEXT_LENGTH
private static final int MAX_PLAINTEXT_LENGTH
2^14 which is the maximum sized plaintext chunk allowed by the TLS RFC.- See Also:
- Constant Field Values
-
ctx
private volatile ChannelHandlerContext ctx
-
engine
private final javax.net.ssl.SSLEngine engine
-
engineType
private final SslHandler.SslEngineType engineType
-
delegatedTaskExecutor
private final java.util.concurrent.Executor delegatedTaskExecutor
-
jdkCompatibilityMode
private final boolean jdkCompatibilityMode
-
singleBuffer
private final java.nio.ByteBuffer[] singleBuffer
Used ifSSLEngine.wrap(ByteBuffer[], ByteBuffer)
andSSLEngine.unwrap(ByteBuffer, ByteBuffer[])
should be called with aByteBuf
that is only backed by oneByteBuffer
to reduce the object creation.
-
startTls
private final boolean startTls
-
resumptionController
private final ResumptionController resumptionController
-
sslTaskRunnerForUnwrap
private final SslHandler.SslTasksRunner sslTaskRunnerForUnwrap
-
sslTaskRunner
private final SslHandler.SslTasksRunner sslTaskRunner
-
pendingUnencryptedWrites
private SslHandlerCoalescingBufferQueue pendingUnencryptedWrites
-
sslClosePromise
private final SslHandler.LazyChannelPromise sslClosePromise
-
packetLength
private int packetLength
-
state
private short state
-
handshakeTimeoutMillis
private volatile long handshakeTimeoutMillis
-
closeNotifyFlushTimeoutMillis
private volatile long closeNotifyFlushTimeoutMillis
-
closeNotifyReadTimeoutMillis
private volatile long closeNotifyReadTimeoutMillis
-
wrapDataSize
volatile int wrapDataSize
-
-
Constructor Detail
-
SslHandler
public SslHandler(javax.net.ssl.SSLEngine engine)
Creates a new instance which runs all delegated tasks directly on theEventExecutor
.- Parameters:
engine
- theSSLEngine
this handler will use
-
SslHandler
public SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls)
Creates a new instance which runs all delegated tasks directly on theEventExecutor
.- Parameters:
engine
- theSSLEngine
this handler will usestartTls
-true
if the first write request shouldn't be encrypted by theSSLEngine
-
SslHandler
public SslHandler(javax.net.ssl.SSLEngine engine, java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.- Parameters:
engine
- theSSLEngine
this handler will usedelegatedTaskExecutor
- theExecutor
that will be used to execute tasks that are returned bySSLEngine.getDelegatedTask()
.
-
SslHandler
public SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls, java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.- Parameters:
engine
- theSSLEngine
this handler will usestartTls
-true
if the first write request shouldn't be encrypted by theSSLEngine
delegatedTaskExecutor
- theExecutor
that will be used to execute tasks that are returned bySSLEngine.getDelegatedTask()
.
-
SslHandler
SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls, java.util.concurrent.Executor delegatedTaskExecutor, ResumptionController resumptionController)
-
-
Method Detail
-
getHandshakeTimeoutMillis
public long getHandshakeTimeoutMillis()
-
setHandshakeTimeout
public void setHandshakeTimeout(long handshakeTimeout, java.util.concurrent.TimeUnit unit)
-
setHandshakeTimeoutMillis
public void setHandshakeTimeoutMillis(long handshakeTimeoutMillis)
-
setWrapDataSize
@UnstableApi public final void setWrapDataSize(int wrapDataSize)
Sets the number of bytes to pass to eachSSLEngine.wrap(ByteBuffer[], int, int, ByteBuffer)
call.This value will partition data which is passed to write
write(ChannelHandlerContext, Object, ChannelPromise)
. The partitioning will work as follows:- If
wrapDataSize <= 0
then we will write each data chunk as is. - If
wrapDataSize > data size
then we will attempt to aggregate multiple data chunks together. - If
wrapDataSize > data size
Else ifwrapDataSize <= data size
then we will divide the data into chunks ofwrapDataSize
when writing.
If the
SSLEngine
doesn't support a gather wrap operation (e.g.SslProvider.OPENSSL
) then aggregating data before wrapping can help reduce the ratio between TLS overhead vs data payload which will lead to better goodput. Writing fixed chunks of data can also help target the underlying transport's (e.g. TCP) frame size. Under lossy/congested network conditions this may help the peer get full TLS packets earlier and be able to do work sooner, as opposed to waiting for the all the pieces of the TLS packet to arrive.- Parameters:
wrapDataSize
- the number of bytes which will be passed to eachSSLEngine.wrap(ByteBuffer[], int, int, ByteBuffer)
call.
- If
-
getCloseNotifyTimeoutMillis
@Deprecated public long getCloseNotifyTimeoutMillis()
Deprecated.
-
setCloseNotifyTimeout
@Deprecated public void setCloseNotifyTimeout(long closeNotifyTimeout, java.util.concurrent.TimeUnit unit)
Deprecated.
-
setCloseNotifyTimeoutMillis
@Deprecated public void setCloseNotifyTimeoutMillis(long closeNotifyFlushTimeoutMillis)
Deprecated.
-
getCloseNotifyFlushTimeoutMillis
public final long getCloseNotifyFlushTimeoutMillis()
-
setCloseNotifyFlushTimeout
public final void setCloseNotifyFlushTimeout(long closeNotifyFlushTimeout, java.util.concurrent.TimeUnit unit)
-
setCloseNotifyFlushTimeoutMillis
public final void setCloseNotifyFlushTimeoutMillis(long closeNotifyFlushTimeoutMillis)
-
getCloseNotifyReadTimeoutMillis
public final long getCloseNotifyReadTimeoutMillis()
-
setCloseNotifyReadTimeout
public final void setCloseNotifyReadTimeout(long closeNotifyReadTimeout, java.util.concurrent.TimeUnit unit)
-
setCloseNotifyReadTimeoutMillis
public final void setCloseNotifyReadTimeoutMillis(long closeNotifyReadTimeoutMillis)
-
engine
public javax.net.ssl.SSLEngine engine()
Returns theSSLEngine
which is used by this handler.
-
applicationProtocol
public java.lang.String applicationProtocol()
Returns the name of the current application-level protocol.- Returns:
- the protocol name or
null
if application-level protocol has not been negotiated
-
handshakeFuture
public Future<Channel> handshakeFuture()
Returns aFuture
that will get notified once the current TLS handshake completes.- Returns:
- the
Future
for the initial TLS handshake ifrenegotiate()
was not invoked. TheFuture
for the most recent TLS renegotiation otherwise.
-
close
@Deprecated public ChannelFuture close()
Deprecated.UsecloseOutbound()
-
close
@Deprecated public ChannelFuture close(ChannelPromise promise)
Deprecated.
-
closeOutbound
public ChannelFuture closeOutbound()
Sends an SSLclose_notify
message to the specified channel and destroys the underlyingSSLEngine
. This will not close the underlyingChannel
. If you want to also close theChannel
useChannelOutboundInvoker.close()
orChannelOutboundInvoker.close()
-
closeOutbound
public ChannelFuture closeOutbound(ChannelPromise promise)
Sends an SSLclose_notify
message to the specified channel and destroys the underlyingSSLEngine
. This will not close the underlyingChannel
. If you want to also close theChannel
useChannelOutboundInvoker.close()
orChannelOutboundInvoker.close()
-
closeOutbound0
private void closeOutbound0(ChannelPromise promise)
-
sslCloseFuture
public Future<Channel> sslCloseFuture()
Return theFuture
that will get notified if the inbound of theSSLEngine
is closed. This method will return the sameFuture
all the time.- See Also:
SSLEngine
-
handlerRemoved0
public void handlerRemoved0(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ByteToMessageDecoder
Gets called after theByteToMessageDecoder
was removed from the actual context and it doesn't handle events anymore.- Overrides:
handlerRemoved0
in classByteToMessageDecoder
- Throws:
java.lang.Exception
-
bind
public void bind(ChannelHandlerContext ctx, java.net.SocketAddress localAddress, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a bind operation is made.- Specified by:
bind
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the bind operation is madelocalAddress
- theSocketAddress
to which it should boundpromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
connect
public void connect(ChannelHandlerContext ctx, java.net.SocketAddress remoteAddress, java.net.SocketAddress localAddress, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a connect operation is made.- Specified by:
connect
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the connect operation is maderemoteAddress
- theSocketAddress
to which it should connectlocalAddress
- theSocketAddress
which is used as source on connectpromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
deregister
public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a deregister operation is made from the current registeredEventLoop
.- Specified by:
deregister
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the close operation is madepromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
disconnect
public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a disconnect operation is made.- Specified by:
disconnect
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the disconnect operation is madepromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
close
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a close operation is made.- Specified by:
close
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the close operation is madepromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
read
public void read(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
InterceptsChannelHandlerContext.read()
.- Specified by:
read
in interfaceChannelOutboundHandler
- Throws:
java.lang.Exception
-
newPendingWritesNullException
private static java.lang.IllegalStateException newPendingWritesNullException()
-
write
public void write(ChannelHandlerContext ctx, java.lang.Object msg, ChannelPromise promise) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a write operation is made. The write operation will write the messages through theChannelPipeline
. Those are then ready to be flushed to the actualChannel
onceChannel.flush()
is called- Specified by:
write
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the write operation is mademsg
- the message to writepromise
- theChannelPromise
to notify once the operation completes- Throws:
java.lang.Exception
- thrown if an error occurs
-
flush
public void flush(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from interface:ChannelOutboundHandler
Called once a flush operation is made. The flush operation will try to flush out all previous written messages that are pending.- Specified by:
flush
in interfaceChannelOutboundHandler
- Parameters:
ctx
- theChannelHandlerContext
for which the flush operation is made- Throws:
java.lang.Exception
- thrown if an error occurs
-
wrapAndFlush
private void wrapAndFlush(ChannelHandlerContext ctx) throws javax.net.ssl.SSLException
- Throws:
javax.net.ssl.SSLException
-
wrap
private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws javax.net.ssl.SSLException
- Throws:
javax.net.ssl.SSLException
-
wrapNonAppData
private boolean wrapNonAppData(ChannelHandlerContext ctx, boolean inUnwrap) throws javax.net.ssl.SSLException
This method will not callsetHandshakeFailure(ChannelHandlerContext, Throwable, boolean, boolean, boolean)
orsetHandshakeFailure(ChannelHandlerContext, Throwable)
.- Returns:
true
if this method ends onSSLEngineResult.HandshakeStatus.NOT_HANDSHAKING
.- Throws:
javax.net.ssl.SSLException
-
wrapMultiple
private javax.net.ssl.SSLEngineResult wrapMultiple(ByteBufAllocator alloc, javax.net.ssl.SSLEngine engine, ByteBuf in, ByteBuf out) throws javax.net.ssl.SSLException
- Throws:
javax.net.ssl.SSLException
-
wrap
private javax.net.ssl.SSLEngineResult wrap(ByteBufAllocator alloc, javax.net.ssl.SSLEngine engine, ByteBuf in, ByteBuf out) throws javax.net.ssl.SSLException
- Throws:
javax.net.ssl.SSLException
-
channelInactive
public void channelInactive(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireChannelInactive()
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
channelInactive
in interfaceChannelInboundHandler
- Overrides:
channelInactive
in classByteToMessageDecoder
- Throws:
java.lang.Exception
-
exceptionCaught
public void exceptionCaught(ChannelHandlerContext ctx, java.lang.Throwable cause) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireExceptionCaught(Throwable)
to forward to the nextChannelHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
exceptionCaught
in interfaceChannelHandler
- Specified by:
exceptionCaught
in interfaceChannelInboundHandler
- Overrides:
exceptionCaught
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
ignoreException
private boolean ignoreException(java.lang.Throwable t)
Checks if the givenThrowable
can be ignore and just "swallowed" When an ssl connection is closed a close_notify message is sent. After that the peer also sends close_notify however, it's not mandatory to receive the close_notify. The party who sent the initial close_notify can close the connection immediately then the peer will get connection reset error.
-
isEncrypted
@Deprecated public static boolean isEncrypted(ByteBuf buffer)
Deprecated.Returnstrue
if the givenByteBuf
is encrypted. Be aware that this method will not increase the readerIndex of the givenByteBuf
.- Parameters:
buffer
- TheByteBuf
to read from. Be aware that it must have at least 5 bytes to read, otherwise it will throw anIllegalArgumentException
.- Returns:
- encrypted
true
if theByteBuf
is encrypted,false
otherwise. - Throws:
java.lang.IllegalArgumentException
- Is thrown if the givenByteBuf
has not at least 5 bytes to read.
-
isEncrypted
public static boolean isEncrypted(ByteBuf buffer, boolean probeSSLv2)
Returnstrue
if the givenByteBuf
is encrypted. Be aware that this method will not increase the readerIndex of the givenByteBuf
.- Parameters:
buffer
- TheByteBuf
to read from. Be aware that it must have at least 5 bytes to read, otherwise it will throw anIllegalArgumentException
.probeSSLv2
-true
if the inputbuffer
might be SSLv2. Iftrue
is used this methods might produce false-positives in some cases so it's strongly suggested to usefalse
.- Returns:
- encrypted
true
if theByteBuf
is encrypted,false
otherwise. - Throws:
java.lang.IllegalArgumentException
- Is thrown if the givenByteBuf
has not at least 5 bytes to read.
-
decodeJdkCompatible
private void decodeJdkCompatible(ChannelHandlerContext ctx, ByteBuf in) throws NotSslRecordException
- Throws:
NotSslRecordException
-
decodeNonJdkCompatible
private void decodeNonJdkCompatible(ChannelHandlerContext ctx, ByteBuf in)
-
handleUnwrapThrowable
private void handleUnwrapThrowable(ChannelHandlerContext ctx, java.lang.Throwable cause)
-
decode
protected void decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws javax.net.ssl.SSLException
Description copied from class:ByteToMessageDecoder
Decode the from oneByteBuf
to an other. This method will be called till either the inputByteBuf
has nothing to read when return from this method or till nothing was read from the inputByteBuf
.- Specified by:
decode
in classByteToMessageDecoder
- Parameters:
ctx
- theChannelHandlerContext
which thisByteToMessageDecoder
belongs toin
- theByteBuf
from which to read dataout
- theList
to which decoded messages should be added- Throws:
javax.net.ssl.SSLException
-
channelReadComplete
public void channelReadComplete(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelInboundHandlerAdapter
CallsChannelHandlerContext.fireChannelReadComplete()
to forward to the nextChannelInboundHandler
in theChannelPipeline
. Sub-classes may override this method to change behavior.- Specified by:
channelReadComplete
in interfaceChannelInboundHandler
- Overrides:
channelReadComplete
in classByteToMessageDecoder
- Throws:
java.lang.Exception
-
channelReadComplete0
private void channelReadComplete0(ChannelHandlerContext ctx)
-
readIfNeeded
private void readIfNeeded(ChannelHandlerContext ctx)
-
flushIfNeeded
private void flushIfNeeded(ChannelHandlerContext ctx)
-
unwrapNonAppData
private int unwrapNonAppData(ChannelHandlerContext ctx) throws javax.net.ssl.SSLException
CallsSSLEngine.unwrap(ByteBuffer, ByteBuffer)
with an empty buffer to handle handshakes, etc.- Throws:
javax.net.ssl.SSLException
-
unwrap
private int unwrap(ChannelHandlerContext ctx, ByteBuf packet, int length) throws javax.net.ssl.SSLException
Unwraps inbound SSL records.- Throws:
javax.net.ssl.SSLException
-
setHandshakeSuccessUnwrapMarkReentry
private boolean setHandshakeSuccessUnwrapMarkReentry() throws javax.net.ssl.SSLException
- Throws:
javax.net.ssl.SSLException
-
executeNotifyClosePromise
private void executeNotifyClosePromise(ChannelHandlerContext ctx)
-
executeChannelRead
private void executeChannelRead(ChannelHandlerContext ctx, ByteBuf decodedOut)
-
toByteBuffer
private static java.nio.ByteBuffer toByteBuffer(ByteBuf out, int index, int len)
-
inEventLoop
private static boolean inEventLoop(java.util.concurrent.Executor executor)
-
runDelegatedTasks
private boolean runDelegatedTasks(boolean inUnwrap)
Will either run the delegated task directly callingRunnable.run()
and returntrue
or will offload the delegated task usingExecutor.execute(Runnable)
and returnfalse
. If the task is offloaded it will take care to resume its work on theEventExecutor
once there are no more tasks to process.
-
getTaskRunner
private SslHandler.SslTasksRunner getTaskRunner(boolean inUnwrap)
-
executeDelegatedTask
private void executeDelegatedTask(boolean inUnwrap)
-
executeDelegatedTask
private void executeDelegatedTask(SslHandler.SslTasksRunner task)
-
setHandshakeSuccess
private boolean setHandshakeSuccess() throws javax.net.ssl.SSLException
Notify all the handshake futures about the successfully handshake- Returns:
true
ifhandshakePromise
was set successfully and aSslHandshakeCompletionEvent
was fired.false
otherwise.- Throws:
javax.net.ssl.SSLException
-
setHandshakeFailure
private void setHandshakeFailure(ChannelHandlerContext ctx, java.lang.Throwable cause)
Notify all the handshake futures about the failure during the handshake.
-
setHandshakeFailure
private void setHandshakeFailure(ChannelHandlerContext ctx, java.lang.Throwable cause, boolean closeInbound, boolean notify, boolean alwaysFlushAndClose)
Notify all the handshake futures about the failure during the handshake.
-
setHandshakeFailureTransportFailure
private void setHandshakeFailureTransportFailure(ChannelHandlerContext ctx, java.lang.Throwable cause)
-
releaseAndFailAll
private void releaseAndFailAll(ChannelHandlerContext ctx, java.lang.Throwable cause)
-
notifyClosePromise
private void notifyClosePromise(java.lang.Throwable cause)
-
closeOutboundAndChannel
private void closeOutboundAndChannel(ChannelHandlerContext ctx, ChannelPromise promise, boolean disconnect) throws java.lang.Exception
- Throws:
java.lang.Exception
-
flush
private void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
- Throws:
java.lang.Exception
-
handlerAdded
public void handlerAdded(ChannelHandlerContext ctx) throws java.lang.Exception
Description copied from class:ChannelHandlerAdapter
Do nothing by default, sub-classes may override this method.- Specified by:
handlerAdded
in interfaceChannelHandler
- Overrides:
handlerAdded
in classChannelHandlerAdapter
- Throws:
java.lang.Exception
-
startHandshakeProcessing
private void startHandshakeProcessing(boolean flushAtEnd)
-
renegotiate
public Future<Channel> renegotiate(Promise<Channel> promise)
Performs TLS renegotiation.
-
handshake
private void handshake(boolean flushAtEnd)
Performs TLS (re)negotiation.- Parameters:
flushAtEnd
- Set totrue
if the outbound buffer should be flushed (written to the network) at the end. Set tofalse
if the handshake will be flushed later, e.g. as part of TCP Fast Open connect.
-
applyHandshakeTimeout
private void applyHandshakeTimeout()
-
forceFlush
private void forceFlush(ChannelHandlerContext ctx)
-
setOpensslEngineSocketFd
private void setOpensslEngineSocketFd(Channel c)
-
channelActive
public void channelActive(ChannelHandlerContext ctx) throws java.lang.Exception
Issues an initial TLS handshake once connected when used in client-mode- Specified by:
channelActive
in interfaceChannelInboundHandler
- Overrides:
channelActive
in classChannelInboundHandlerAdapter
- Throws:
java.lang.Exception
-
safeClose
private void safeClose(ChannelHandlerContext ctx, ChannelFuture flushFuture, ChannelPromise promise)
-
addCloseListener
private static void addCloseListener(ChannelFuture future, ChannelPromise promise)
-
allocate
private ByteBuf allocate(ChannelHandlerContext ctx, int capacity)
Always prefer a direct buffer when it's pooled, so that we reduce the number of memory copies inOpenSslEngine
.
-
allocateOutNetBuf
private ByteBuf allocateOutNetBuf(ChannelHandlerContext ctx, int pendingBytes, int numComponents)
Allocates an outbound network buffer forSSLEngine.wrap(ByteBuffer, ByteBuffer)
which can encrypt the specified amount of pending bytes.
-
isStateSet
private boolean isStateSet(int bit)
-
setState
private void setState(int bit)
-
clearState
private void clearState(int bit)
-
-