Class ServerTlsChannel
- All Implemented Interfaces:
java.io.Closeable,java.lang.AutoCloseable,java.nio.channels.ByteChannel,java.nio.channels.Channel,java.nio.channels.GatheringByteChannel,java.nio.channels.ReadableByteChannel,java.nio.channels.ScatteringByteChannel,java.nio.channels.WritableByteChannel,TlsChannel
public class ServerTlsChannel extends java.lang.Object implements TlsChannel
TlsChannel.-
Nested Class Summary
Nested Classes Modifier and Type Class Description static classServerTlsChannel.BuilderBuilder ofServerTlsChannel -
Field Summary
Fields inherited from interface tlschannel.TlsChannel
defaultEncryptedBufferAllocator, defaultPlainBufferAllocator -
Method Summary
Modifier and Type Method Description voidclose()Closes the underlying channel.TrackingAllocatorgetEncryptedBufferAllocator()Return theBufferAllocatorto use for encrypted data.TrackingAllocatorgetPlainBufferAllocator()Return theBufferAllocatorto use for unencrypted data.booleangetRunTasks()Return whether CPU-intensive tasks are run or not.java.util.function.Consumer<javax.net.ssl.SSLSession>getSessionInitCallback()Return the callback function to be executed when the TLS session is established (or re-established).javax.net.ssl.SSLContextgetSslContext()Return the usedSSLContext.javax.net.ssl.SSLEnginegetSslEngine()Return a reference to theSSLEngineused.java.nio.channels.ByteChannelgetUnderlying()Return a reference to the underlyingByteChannel.voidhandshake()Forces the initial TLS handshake.booleanisOpen()static ServerTlsChannel.BuildernewBuilder(java.nio.channels.ByteChannel underlying, javax.net.ssl.SSLContext sslContext)Create a newServerTlsChannel.Builder, configured with a underlyingChanneland a fixedSSLContext, which will be used to create theSSLEngine.static ServerTlsChannel.BuildernewBuilder(java.nio.channels.ByteChannel underlying, SniSslContextFactory sslContextFactory)Create a newServerTlsChannel.Builder, configured with a underlyingChanneland a customSSLContextfactory, which will be used to create the context (in turn used to create theSSLEngine, as a function of the SNI received at the TLS connection start.intread(java.nio.ByteBuffer dstBuffer)Reads a sequence of bytesProduced from this channel into the given buffer.longread(java.nio.ByteBuffer[] dstBuffers)Reads a sequence of bytesProduced from this channel into the given buffers.longread(java.nio.ByteBuffer[] dstBuffers, int offset, int length)Reads a sequence of bytesProduced from this channel into a subsequence of the given buffers.voidrenegotiate()Initiates a handshake (initial or renegotiation) on this channel.booleanshutdown()Shuts down the TLS connection.booleanshutdownReceived()Return whether this side of the connection has already received the close notification.booleanshutdownSent()Return whether this side of the connection has already sent the close notification.intwrite(java.nio.ByteBuffer srcBuffer)Writes a sequence of bytesProduced to this channel from the given buffer.longwrite(java.nio.ByteBuffer[] srcs)Writes a sequence of bytesProduced to this channel from the given buffers.longwrite(java.nio.ByteBuffer[] srcs, int offset, int length)Writes a sequence of bytesProduced to this channel from a subsequence of the given buffers.
-
Method Details
-
newBuilder
public static ServerTlsChannel.Builder newBuilder(java.nio.channels.ByteChannel underlying, javax.net.ssl.SSLContext sslContext)Create a newServerTlsChannel.Builder, configured with a underlyingChanneland a fixedSSLContext, which will be used to create theSSLEngine.- Parameters:
underlying- a reference to the underlyingByteChannelsslContext- a fixedSSLContextto be used- Returns:
- the new builder
-
newBuilder
public static ServerTlsChannel.Builder newBuilder(java.nio.channels.ByteChannel underlying, SniSslContextFactory sslContextFactory)Create a newServerTlsChannel.Builder, configured with a underlyingChanneland a customSSLContextfactory, which will be used to create the context (in turn used to create theSSLEngine, as a function of the SNI received at the TLS connection start.Implementation note:
Due to limitations ofSSLEngine, configuring aServerTlsChannelto select theSSLContextbased on the SNI value implies parsing the first TLS frame (ClientHello) independently of the SSLEngine.- Parameters:
underlying- a reference to the underlyingByteChannelsslContextFactory- a function from an optional SNI to theSSLContextto be used- Returns:
- the new builder
- See Also:
- Server Name Indication
-
getUnderlying
public java.nio.channels.ByteChannel getUnderlying()Description copied from interface:TlsChannelReturn a reference to the underlyingByteChannel.- Specified by:
getUnderlyingin interfaceTlsChannel- Returns:
- the underlying channel
-
getSslContext
public javax.net.ssl.SSLContext getSslContext()Return the usedSSLContext.- Returns:
- if context if present, of null if the TLS connection as not been initializer, or the SNI not received yet.
-
getSslEngine
public javax.net.ssl.SSLEngine getSslEngine()Description copied from interface:TlsChannelReturn a reference to theSSLEngineused.- Specified by:
getSslEnginein interfaceTlsChannel- Returns:
- the engine reference if present, or
nullif unknown (that can happen in server-side channels before the SNI is parsed).
-
getSessionInitCallback
public java.util.function.Consumer<javax.net.ssl.SSLSession> getSessionInitCallback()Description copied from interface:TlsChannelReturn the callback function to be executed when the TLS session is established (or re-established).- Specified by:
getSessionInitCallbackin interfaceTlsChannel- Returns:
- the callback function
- See Also:
TlsChannelBuilder.withSessionInitCallback(Consumer)
-
getRunTasks
public boolean getRunTasks()Description copied from interface:TlsChannelReturn whether CPU-intensive tasks are run or not.- Specified by:
getRunTasksin interfaceTlsChannel- Returns:
- whether tasks are run
- See Also:
TlsChannelBuilder.withRunTasks(boolean)
-
getPlainBufferAllocator
Description copied from interface:TlsChannelReturn theBufferAllocatorto use for unencrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel.- Specified by:
getPlainBufferAllocatorin interfaceTlsChannel- Returns:
- the buffer allocator
- See Also:
TlsChannelBuilder.withPlainBufferAllocator(BufferAllocator),TrackingAllocator
-
getEncryptedBufferAllocator
Description copied from interface:TlsChannelReturn theBufferAllocatorto use for encrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel.- Specified by:
getEncryptedBufferAllocatorin interfaceTlsChannel- Returns:
- the buffer allocator
- See Also:
TlsChannelBuilder.withEncryptedBufferAllocator(BufferAllocator),TrackingAllocator
-
read
public long read(java.nio.ByteBuffer[] dstBuffers, int offset, int length) throws java.io.IOExceptionDescription copied from interface:TlsChannelReads a sequence of bytesProduced from this channel into a subsequence of the given buffers.See
ScatteringByteChannel.read(ByteBuffer[], int, int)for more details of the meaning of this signature.This method behaves slightly different than the interface specification, with respect to non-blocking responses, see
TlsChannel.read(ByteBuffer)for more details.- Specified by:
readin interfacejava.nio.channels.ScatteringByteChannel- Specified by:
readin interfaceTlsChannel- Parameters:
dstBuffers- The buffers into which bytesProduced are to be transferredoffset- The offset within the buffer array of the first buffer into which bytesProduced are to be transferred; must be non-negative and no larger thandsts.lengthlength- The maximum number of buffers to be accessed; must be non-negative and no larger thandsts.length-offset- Returns:
- The number of bytesProduced read, or
-1if the channel has reached end-of-stream; contrary to the behavior specified inByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
read
public long read(java.nio.ByteBuffer[] dstBuffers) throws java.io.IOExceptionDescription copied from interface:TlsChannelReads a sequence of bytesProduced from this channel into the given buffers.An invocation of this method of the form
c.read(dsts)behaves in exactly the same manner as the invocationc.read(dsts, 0, dsts.length);
This method behaves slightly different than the interface specification, with respect to non-blocking responses, see
TlsChannel.read(ByteBuffer)for more details.- Specified by:
readin interfacejava.nio.channels.ScatteringByteChannel- Specified by:
readin interfaceTlsChannel- Parameters:
dstBuffers- The buffers into which bytesProduced are to be transferred- Returns:
- The number of bytesProduced read, or
-1if the channel has reached end-of-stream; contrary to the behavior specified inByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
read
public int read(java.nio.ByteBuffer dstBuffer) throws java.io.IOExceptionDescription copied from interface:TlsChannelReads a sequence of bytesProduced from this channel into the given buffer.An attempt is made to read up to r bytesProduced from the channel, where r is the number of bytesProduced remaining in the buffer, that is,
dst.remaining(), at the moment this method is invoked.Suppose that a byte sequence of length n is read, where
0<=n<=r. This byte sequence will be transferred into the buffer so that the first byte in the sequence is at index p and the last byte is at index p+n-1, where p is the buffer's position at the moment this method is invoked. Upon return the buffer's position will be equal to p+n; its limit will not have changed.A read operation might not fill the buffer, and in fact it might not read any bytesProduced at all. Whether or not it does so depends upon the nature and state of the underlying channel. It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read. On the other hand, if the underlying channel is in non-blocking mode then a
WouldBlockExceptionmay be thrown. Note that this also includes the possibility of aNeedsWriteException, due to the fact that, during a TLS handshake, bytesProduced need to be written to the underlying channel. In any case, after aWouldBlockException, the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).If the channel is configured to not run tasks and one is due to run, a
NeedsTaskExceptionwill be thrown. In this case the operation should be retried after the task is run.This method may be invoked at any time. If another thread has already initiated a read or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.
- Specified by:
readin interfacejava.nio.channels.ReadableByteChannel- Specified by:
readin interfaceTlsChannel- Parameters:
dstBuffer- The buffer into which bytesProduced are to be transferred- Returns:
- The number of bytesProduced read, or
-1if the channel has reached end-of-stream; contrary to the behavior specified inByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
write
public long write(java.nio.ByteBuffer[] srcs, int offset, int length) throws java.io.IOExceptionDescription copied from interface:TlsChannelWrites a sequence of bytesProduced to this channel from a subsequence of the given buffers.See
GatheringByteChannel.write(ByteBuffer[], int, int)for more details of the meaning of this signature.This method behaves slightly different than the interface specification, with respect to non-blocking responses, see
TlsChannel.write(ByteBuffer)for more details.- Specified by:
writein interfacejava.nio.channels.GatheringByteChannel- Specified by:
writein interfaceTlsChannel- Parameters:
srcs- The buffers from which bytesProduced are to be retrievedoffset- The offset within the buffer array of the first buffer from which bytesProduced are to be retrieved; must be non-negative and no larger thansrcs.lengthlength- The maximum number of buffers to be accessed; must be non-negative and no larger thansrcs.length-offset- Returns:
- The number of bytesProduced written, contrary to the behavior specified in
ByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
write
public long write(java.nio.ByteBuffer[] srcs) throws java.io.IOExceptionDescription copied from interface:TlsChannelWrites a sequence of bytesProduced to this channel from the given buffers.An invocation of this method of the form
c.write(srcs)behaves in exactly the same manner as the invocation
This method behaves slightly different than the interface specification, with respect to non-blocking responses, seec.write(srcs, 0, srcs.length);
TlsChannel.write(ByteBuffer)for more details.- Specified by:
writein interfacejava.nio.channels.GatheringByteChannel- Specified by:
writein interfaceTlsChannel- Parameters:
srcs- The buffers from which bytesProduced are to be retrieved- Returns:
- The number of bytesProduced written, contrary to the behavior specified in
ByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOExceptions
-
write
public int write(java.nio.ByteBuffer srcBuffer) throws java.io.IOExceptionDescription copied from interface:TlsChannelWrites a sequence of bytesProduced to this channel from the given buffer.An attempt is made to write up to r bytesProduced to the channel, where r is the number of bytesProduced remaining in the buffer, that is,
src.remaining(), at the moment this method is invoked.Suppose that a byte sequence of length n is written, where
0<=n<=r. This byte sequence will be transferred from the buffer starting at index p, where p is the buffer's position at the moment this method is invoked; the index of the last byte written will be p+n-1. Upon return the buffer's position will be equal to p+n; its limit will not have changed.If the underlying channel is in blocking mode, a write operation will return only after writing all of the r requested bytesProduced. On the other hand, if it is in non-blocking mode, this operation may write only some of the bytesProduced or possibly none at all, in this case a
WouldBlockExceptionwill be thrown. Note that this also includes the possibility of aNeedsReadException, due to the fact that, during a TLS handshake, bytes need to be read from the underlying channel. In any case, after aWouldBlockException, the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).If the channel is configured to not run tasks and one is due to run, a
NeedsTaskExceptionwill be thrown. In this case the operation should be retried after the task is run.This method may be invoked at any time. If another thread has already initiated a write or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.
- Specified by:
writein interfaceTlsChannel- Specified by:
writein interfacejava.nio.channels.WritableByteChannel- Parameters:
srcBuffer- The buffer from which bytesProduced are to be retrieved- Returns:
- The number of bytesProduced written, contrary to the behavior specified in
ByteChannel, this method never returns 0, but throwsWouldBlockException - Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
renegotiate
public void renegotiate() throws java.io.IOExceptionDescription copied from interface:TlsChannelInitiates a handshake (initial or renegotiation) on this channel. This method is not needed for the initial handshake, as theread()andwrite()methods will implicitly do the initial handshake if needed.This method may block if the underlying channel if in blocking mode.
Note that renegotiation is a problematic feature of the TLS protocol, that should only be initiated at quiet point of the protocol.
This method may block if the underlying channel is in blocking mode, otherwise a
WouldBlockExceptioncan be thrown. In this case the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).If the channel is configured to not run tasks and one is due to run, a
NeedsTaskExceptionwill be thrown, with a reference to the task. In this case the operation should be retried after the task is run.This method may be invoked at any time. If another thread has already initiated a read, write, or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.
- Specified by:
renegotiatein interfaceTlsChannel- Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
handshake
public void handshake() throws java.io.IOExceptionDescription copied from interface:TlsChannelForces the initial TLS handshake. Calling this method is usually not needed, as a handshake will happen automatically when doing the firstread()orwrite()operation. Calling this method after the initial handshake has been done has no effect.This method may block if the underlying channel is in blocking mode, otherwise a
WouldBlockExceptioncan be thrown. In this case the operation should be retried when the underlying channel is ready (for reading or writing, depending on the subclass).If the channel is configured to not run tasks and one is due to run, a
NeedsTaskExceptionwill be thrown, with a reference to the task. In this case the operation should be retried after the task is run.This method may be invoked at any time. If another thread has already initiated a read, write, or handshaking operation upon this channel, however, then an invocation of this method will block until the first operation is complete.
- Specified by:
handshakein interfaceTlsChannel- Throws:
WouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediatelyNeedsTaskException- if the channel is not configured to run tasks automatically and a task needs to be executed to complete the operationjavax.net.ssl.SSLException- if theSSLEnginethrows a SSLExceptionjava.io.IOException- if the underlying channel throws an IOException
-
close
public void close() throws java.io.IOExceptionDescription copied from interface:TlsChannelCloses the underlying channel. This method first does some form of TLS close if not already done. The exact behavior can be configured using theTlsChannelBuilder.withWaitForCloseConfirmation(boolean).The default behavior mimics what happens in a normal (that is, non layered)
Socket.close().For finer control of the TLS close, use
TlsChannel.shutdown()- Specified by:
closein interfacejava.lang.AutoCloseable- Specified by:
closein interfacejava.nio.channels.Channel- Specified by:
closein interfacejava.io.Closeable- Specified by:
closein interfaceTlsChannel- Throws:
java.io.IOException- if the underlying channel throws an IOException during close. Exceptions thrown during any previous TLS close are not propagated.
-
isOpen
public boolean isOpen()- Specified by:
isOpenin interfacejava.nio.channels.Channel
-
shutdown
public boolean shutdown() throws java.io.IOExceptionDescription copied from interface:TlsChannelShuts down the TLS connection. This method emulates the behavior of OpenSSL's SSL_shutdown().The shutdown procedure consists of two steps: the sending of the "close notify" shutdown alert and the reception of the peer's "close notify". According to the TLS standard, it is acceptable for an application to only send its shutdown alert and then close the underlying connection without waiting for the peer's response. When the underlying connection shall be used for more communications, the complete shutdown procedure (bidirectional "close notify" alerts) must be performed, so that the peers stay synchronized.
This class supports both uni- and bidirectional shutdown by its 2 step behavior, using this method.
When this is the first party to send the "close notify" alert, this method will only send the alert, set the
TlsChannel.shutdownSent()flag and returnfalse. If a unidirectional shutdown is enough, this first call is sufficient. In order to complete the bidirectional shutdown handshake, This method must be called again. The second call will wait for the peer's "close notify" shutdown alert. On success, the second call will returntrue.If the peer already sent the "close notify" alert and it was already processed implicitly inside a read operation, the
TlsChannel.shutdownReceived()flag is already set. This method will then send the "close notify" alert, set theTlsChannel.shutdownSent()flag and immediately returntrue. It is therefore recommended to check the return value of this method and call it again, if the bidirectional shutdown is not yet complete.If the underlying channel is blocking, this method will only return once the handshake step has been finished or an error occurred.
If the underlying channel is non-blocking, this method may throw
WouldBlockExceptionif the underlying channel could not support the continuation of the handshake. The calling process then must repeat the call after taking appropriate action (like waiting in a selector in case of aSocketChannel).Note that despite not being mandated by the specification, a proper TLS close is important to prevent truncation attacks, which consists, essentially, of an adversary introducing TCP FIN segments to trick on party to ignore the final bytes of a secure stream. For more details, see the original paper.
- Specified by:
shutdownin interfaceTlsChannel- Returns:
- whether the closing is finished.
- Throws:
java.io.IOException- if the underlying channel throws an IOExceptionWouldBlockException- if the channel is in non-blocking mode and the IO operation cannot be completed immediately- See Also:
TlsChannelBuilder.withWaitForCloseConfirmation(boolean)
-
shutdownReceived
public boolean shutdownReceived()Description copied from interface:TlsChannelReturn whether this side of the connection has already received the close notification.- Specified by:
shutdownReceivedin interfaceTlsChannel- Returns:
trueif the close notification was received- See Also:
TlsChannel.shutdown()
-
shutdownSent
public boolean shutdownSent()Description copied from interface:TlsChannelReturn whether this side of the connection has already sent the close notification.- Specified by:
shutdownSentin interfaceTlsChannel- Returns:
trueif the close notification was sent- See Also:
TlsChannel.shutdown()
-