public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundHandler
Channel
. Please refer
to the "SecureChat" example in the distribution or the web
site for the detailed usage.
Beside using the handshake ChannelFuture
to get notified about the completion of the handshake it's
also possible to detect it by implement the
ChannelInboundHandler.userEventTriggered(ChannelHandlerContext, Object)
method and check for a SslHandshakeCompletionEvent
.
The handshake will be automatically issued for you once the Channel
is active and
SSLEngine.getUseClientMode()
returns true
.
So no need to bother with it by your self.
To close the SSL session, the closeOutbound()
method should be
called to send the close_notify
message to the remote peer. One
exception is when you close the Channel
- SslHandler
intercepts the close request and send the close_notify
message
before the channel closure automatically. Once the SSL session is closed,
it is not reusable, and consequently you should create a new
SslHandler
with a new SSLEngine
as explained in the
following section.
To restart the SSL session, you must remove the existing closed
SslHandler
from the ChannelPipeline
, insert a new
SslHandler
with a new SSLEngine
into the pipeline,
and start the handshake process as described in the first section.
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:
SslHandler
instance with startTls
flag set
to true
,SslHandler
to the ChannelPipeline
, andSslHandler
before sending
the StartTLS response. Otherwise the client can send begin SSL handshake
before SslHandler
is inserted to the ChannelPipeline
, causing
data corruption.
The client-side implementation is much simpler.
SslHandler
instance with startTls
flag set
to false
,SslHandler
to the ChannelPipeline
, andBecause 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.
ByteToMessageDecoder.Cumulator
ChannelHandler.Sharable
COMPOSITE_CUMULATOR, MERGE_CUMULATOR
构造器和说明 |
---|
SslHandler(javax.net.ssl.SSLEngine engine)
Creates a new instance which runs all delegated tasks directly on the
EventExecutor . |
SslHandler(javax.net.ssl.SSLEngine engine,
boolean startTls)
Creates a new instance which runs all delegated tasks directly on the
EventExecutor . |
SslHandler(javax.net.ssl.SSLEngine engine,
boolean startTls,
java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.
|
SslHandler(javax.net.ssl.SSLEngine engine,
java.util.concurrent.Executor delegatedTaskExecutor)
Creates a new instance.
|
限定符和类型 | 方法和说明 |
---|---|
java.lang.String |
applicationProtocol()
Returns the name of the current application-level protocol.
|
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-mode
|
void |
channelInactive(ChannelHandlerContext ctx)
Calls
ChannelHandlerContext.fireChannelInactive() to forward
to the next ChannelInboundHandler in the ChannelPipeline . |
void |
channelReadComplete(ChannelHandlerContext ctx)
Calls
ChannelHandlerContext.fireChannelReadComplete() to forward
to the next ChannelInboundHandler in the ChannelPipeline . |
ChannelFuture |
close()
已过时。
|
void |
close(ChannelHandlerContext ctx,
ChannelPromise promise)
Called once a close operation is made.
|
ChannelFuture |
close(ChannelPromise promise)
已过时。
|
ChannelFuture |
closeOutbound()
Sends an SSL
close_notify message to the specified channel and
destroys the underlying SSLEngine . |
ChannelFuture |
closeOutbound(ChannelPromise promise)
Sends an SSL
close_notify message to the specified channel and
destroys the underlying SSLEngine . |
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 one
ByteBuf to an other. |
void |
deregister(ChannelHandlerContext ctx,
ChannelPromise promise)
Called once a deregister operation is made from the current registered
EventLoop . |
void |
disconnect(ChannelHandlerContext ctx,
ChannelPromise promise)
Called once a disconnect operation is made.
|
javax.net.ssl.SSLEngine |
engine()
Returns the
SSLEngine which is used by this handler. |
void |
exceptionCaught(ChannelHandlerContext ctx,
java.lang.Throwable cause)
Calls
ChannelHandlerContext.fireExceptionCaught(Throwable) to forward
to the next ChannelHandler in the ChannelPipeline . |
void |
flush(ChannelHandlerContext ctx)
Called once a flush operation is made.
|
long |
getCloseNotifyFlushTimeoutMillis()
Gets the timeout for flushing the close_notify that was triggered by closing the
Channel . |
long |
getCloseNotifyReadTimeoutMillis()
Gets the timeout (in ms) for receiving the response for the close_notify that was triggered by closing the
Channel . |
long |
getCloseNotifyTimeoutMillis()
已过时。
|
long |
getHandshakeTimeoutMillis() |
void |
handlerAdded(ChannelHandlerContext ctx)
Do nothing by default, sub-classes may override this method.
|
void |
handlerRemoved0(ChannelHandlerContext ctx)
Gets called after the
ByteToMessageDecoder was removed from the actual context and it doesn't handle
events anymore. |
Future<Channel> |
handshakeFuture()
Returns a
Future that will get notified once the current TLS handshake completes. |
static boolean |
isEncrypted(ByteBuf buffer)
Returns
true if the given ByteBuf is encrypted. |
void |
read(ChannelHandlerContext ctx)
Intercepts
ChannelHandlerContext.read() . |
Future<Channel> |
renegotiate()
Performs TLS renegotiation.
|
Future<Channel> |
renegotiate(Promise<Channel> promise)
Performs TLS renegotiation.
|
void |
setCloseNotifyFlushTimeout(long closeNotifyFlushTimeout,
java.util.concurrent.TimeUnit unit)
Sets the timeout for flushing the close_notify that was triggered by closing the
Channel . |
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 the
Channel . |
void |
setCloseNotifyReadTimeoutMillis(long closeNotifyReadTimeoutMillis)
|
void |
setCloseNotifyTimeout(long closeNotifyTimeout,
java.util.concurrent.TimeUnit unit)
|
void |
setCloseNotifyTimeoutMillis(long closeNotifyFlushTimeoutMillis)
|
void |
setHandshakeTimeout(long handshakeTimeout,
java.util.concurrent.TimeUnit unit) |
void |
setHandshakeTimeoutMillis(long handshakeTimeoutMillis) |
void |
setWrapDataSize(int wrapDataSize)
Sets the number of bytes to pass to each
SSLEngine.wrap(ByteBuffer[], int, int, ByteBuffer) call. |
Future<Channel> |
sslCloseFuture()
Return the
Future that will get notified if the inbound of the SSLEngine is closed. |
void |
write(ChannelHandlerContext ctx,
java.lang.Object msg,
ChannelPromise promise)
Called once a write operation is made.
|
actualReadableBytes, callDecode, channelRead, decodeLast, discardSomeReadBytes, handlerRemoved, internalBuffer, isSingleDecode, setCumulator, setDiscardAfterReads, setSingleDecode, userEventTriggered
channelRegistered, channelUnregistered, channelWritabilityChanged
ensureNotSharable, isSharable
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
handlerRemoved
public SslHandler(javax.net.ssl.SSLEngine engine)
EventExecutor
.engine
- the SSLEngine
this handler will usepublic SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls)
EventExecutor
.engine
- the SSLEngine
this handler will usestartTls
- true
if the first write request shouldn't be
encrypted by the SSLEngine
public SslHandler(javax.net.ssl.SSLEngine engine, java.util.concurrent.Executor delegatedTaskExecutor)
engine
- the SSLEngine
this handler will usedelegatedTaskExecutor
- the Executor
that will be used to execute tasks that are returned by
SSLEngine.getDelegatedTask()
.public SslHandler(javax.net.ssl.SSLEngine engine, boolean startTls, java.util.concurrent.Executor delegatedTaskExecutor)
engine
- the SSLEngine
this handler will usestartTls
- true
if the first write request shouldn't be
encrypted by the SSLEngine
delegatedTaskExecutor
- the Executor
that will be used to execute tasks that are returned by
SSLEngine.getDelegatedTask()
.public long getHandshakeTimeoutMillis()
public void setHandshakeTimeout(long handshakeTimeout, java.util.concurrent.TimeUnit unit)
public void setHandshakeTimeoutMillis(long handshakeTimeoutMillis)
@UnstableApi public final void setWrapDataSize(int wrapDataSize)
SSLEngine.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:
wrapDataSize <= 0
then we will write each data chunk as is.wrapDataSize > data size
then we will attempt to aggregate multiple data chunks together.wrapDataSize > data size
Else if wrapDataSize <= data size
then we will divide the data
into chunks of wrapDataSize
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.
wrapDataSize
- the number of bytes which will be passed to each
SSLEngine.wrap(ByteBuffer[], int, int, ByteBuffer)
call.@Deprecated public long getCloseNotifyTimeoutMillis()
getCloseNotifyFlushTimeoutMillis()
@Deprecated public void setCloseNotifyTimeout(long closeNotifyTimeout, java.util.concurrent.TimeUnit unit)
@Deprecated public void setCloseNotifyTimeoutMillis(long closeNotifyFlushTimeoutMillis)
public final long getCloseNotifyFlushTimeoutMillis()
public final void setCloseNotifyFlushTimeout(long closeNotifyFlushTimeout, java.util.concurrent.TimeUnit unit)
public final void setCloseNotifyFlushTimeoutMillis(long closeNotifyFlushTimeoutMillis)
public final long getCloseNotifyReadTimeoutMillis()
public final void setCloseNotifyReadTimeout(long closeNotifyReadTimeout, java.util.concurrent.TimeUnit unit)
public final void setCloseNotifyReadTimeoutMillis(long closeNotifyReadTimeoutMillis)
public javax.net.ssl.SSLEngine engine()
SSLEngine
which is used by this handler.public java.lang.String applicationProtocol()
null
if application-level protocol has not been negotiatedpublic Future<Channel> handshakeFuture()
Future
that will get notified once the current TLS handshake completes.Future
for the initial TLS handshake if renegotiate()
was not invoked.
The Future
for the most recent TLS renegotiation otherwise.@Deprecated public ChannelFuture close()
closeOutbound()
@Deprecated public ChannelFuture close(ChannelPromise promise)
public ChannelFuture closeOutbound()
close_notify
message to the specified channel and
destroys the underlying SSLEngine
. This will not close the underlying
Channel
. If you want to also close the Channel
use ChannelOutboundInvoker.close()
or
ChannelOutboundInvoker.close()
public ChannelFuture closeOutbound(ChannelPromise promise)
close_notify
message to the specified channel and
destroys the underlying SSLEngine
. This will not close the underlying
Channel
. If you want to also close the Channel
use ChannelOutboundInvoker.close()
or
ChannelOutboundInvoker.close()
public Future<Channel> sslCloseFuture()
Future
that will get notified if the inbound of the SSLEngine
is closed.
This method will return the same Future
all the time.SSLEngine
public void handlerRemoved0(ChannelHandlerContext ctx) throws java.lang.Exception
ByteToMessageDecoder
ByteToMessageDecoder
was removed from the actual context and it doesn't handle
events anymore.handlerRemoved0
在类中 ByteToMessageDecoder
java.lang.Exception
public void bind(ChannelHandlerContext ctx, java.net.SocketAddress localAddress, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
bind
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the bind operation is madelocalAddress
- the SocketAddress
to which it should boundpromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void connect(ChannelHandlerContext ctx, java.net.SocketAddress remoteAddress, java.net.SocketAddress localAddress, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
connect
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the connect operation is maderemoteAddress
- the SocketAddress
to which it should connectlocalAddress
- the SocketAddress
which is used as source on connectpromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
EventLoop
.deregister
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the close operation is madepromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
disconnect
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the disconnect operation is madepromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void close(ChannelHandlerContext ctx, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
close
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the close operation is madepromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void read(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelOutboundHandler
ChannelHandlerContext.read()
.read
在接口中 ChannelOutboundHandler
java.lang.Exception
public void write(ChannelHandlerContext ctx, java.lang.Object msg, ChannelPromise promise) throws java.lang.Exception
ChannelOutboundHandler
ChannelPipeline
. Those are then ready to be flushed to the actual Channel
once
Channel.flush()
is calledwrite
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the write operation is mademsg
- the message to writepromise
- the ChannelPromise
to notify once the operation completesjava.lang.Exception
- thrown if an error occurspublic void flush(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelOutboundHandler
flush
在接口中 ChannelOutboundHandler
ctx
- the ChannelHandlerContext
for which the flush operation is madejava.lang.Exception
- thrown if an error occurspublic void channelInactive(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireChannelInactive()
to forward
to the next ChannelInboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.channelInactive
在接口中 ChannelInboundHandler
channelInactive
在类中 ByteToMessageDecoder
java.lang.Exception
public void exceptionCaught(ChannelHandlerContext ctx, java.lang.Throwable cause) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireExceptionCaught(Throwable)
to forward
to the next ChannelHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.exceptionCaught
在接口中 ChannelHandler
exceptionCaught
在接口中 ChannelInboundHandler
exceptionCaught
在类中 ChannelInboundHandlerAdapter
java.lang.Exception
public static boolean isEncrypted(ByteBuf buffer)
true
if the given ByteBuf
is encrypted. Be aware that this method
will not increase the readerIndex of the given ByteBuf
.buffer
- The ByteBuf
to read from. Be aware that it must have at least 5 bytes to read,
otherwise it will throw an IllegalArgumentException
.true
if the ByteBuf
is encrypted, false
otherwise.java.lang.IllegalArgumentException
- Is thrown if the given ByteBuf
has not at least 5 bytes to read.protected void decode(ChannelHandlerContext ctx, ByteBuf in, java.util.List<java.lang.Object> out) throws javax.net.ssl.SSLException
ByteToMessageDecoder
ByteBuf
to an other. This method will be called till either the input
ByteBuf
has nothing to read when return from this method or till nothing was read from the input
ByteBuf
.decode
在类中 ByteToMessageDecoder
ctx
- the ChannelHandlerContext
which this ByteToMessageDecoder
belongs toin
- the ByteBuf
from which to read dataout
- the List
to which decoded messages should be addedjavax.net.ssl.SSLException
public void channelReadComplete(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelInboundHandlerAdapter
ChannelHandlerContext.fireChannelReadComplete()
to forward
to the next ChannelInboundHandler
in the ChannelPipeline
.
Sub-classes may override this method to change behavior.channelReadComplete
在接口中 ChannelInboundHandler
channelReadComplete
在类中 ByteToMessageDecoder
java.lang.Exception
public void handlerAdded(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelHandlerAdapter
handlerAdded
在接口中 ChannelHandler
handlerAdded
在类中 ChannelHandlerAdapter
java.lang.Exception
public Future<Channel> renegotiate(Promise<Channel> promise)
public void channelActive(ChannelHandlerContext ctx) throws java.lang.Exception
channelActive
在接口中 ChannelInboundHandler
channelActive
在类中 ChannelInboundHandlerAdapter
java.lang.Exception