/*
* Copyright 2008-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Original Work: MIT License, Copyright (c) [2015-2018] all contributors
* https://github.com/marianobarrios/tls-channel
*/
package com.mongodb.internal.connection.tlschannel;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.function.Consumer;
A ByteChannel interface to a TLS (Transport Layer Security) connection.
Instances that implement this interface delegate all cryptographic operations
to the standard Java TLS implementation: SSLEngine; effectively hiding it
behind an easy-to-use streaming API, that allows to securitize JVM
applications with minimal added complexity.
In other words, an interface that allows the programmer to have TLS using the
same standard socket API used for plaintext, just like OpenSSL does for C,
only for Java.
Note that this is an API adapter, not a cryptographic implementation: with
the exception of a few bytesProduced of parsing at the beginning of the connection,
to look for the SNI, the whole protocol implementation is done by the
SSLEngine. Both the SSLContext and SSLEngine are supplied by the client;
these classes are the ones responsible for protocol configuration, including
hostname validation, client-side authentication, etc.
A TLS channel is created by using one of its subclasses. They will take an existing ByteChannel
(typically, but not necessarily, a SocketChannel
) and a SSLEngine
.
It should be noted that this interface extends ByteChannel
as a design compromise, but it does not follow its interface completely. In particular, in case of underlying non-blocking channels, when it is not possible to complete an operation, no zero is returned, but an WouldBlockException
. This divergence from the base interface is needed because both a read
and a write
operation can run out of both bytesProduced for reading and buffer space for writing, as a handshake (a bidirectional operation) can happen at any moment. The user would use a Selector
to wait for the expected condition of the underlying channel, and should know which operation to
register.
On top of that, operations can also fail to complete due to asynchronous tasks; this is communicated using a NeedsTaskException
. This behavior is controlled by the getRunTasks()
attribute. This allows the user to execute CPU-intensive tasks out of the selector loop.
/**
* A ByteChannel interface to a TLS (Transport Layer Security) connection.
*
* <p>
* Instances that implement this interface delegate all cryptographic operations
* to the standard Java TLS implementation: SSLEngine; effectively hiding it
* behind an easy-to-use streaming API, that allows to securitize JVM
* applications with minimal added complexity.
*
* <p>
* In other words, an interface that allows the programmer to have TLS using the
* same standard socket API used for plaintext, just like OpenSSL does for C,
* only for Java.
*
* <p>
* Note that this is an API adapter, not a cryptographic implementation: with
* the exception of a few bytesProduced of parsing at the beginning of the connection,
* to look for the SNI, the whole protocol implementation is done by the
* SSLEngine. Both the SSLContext and SSLEngine are supplied by the client;
* these classes are the ones responsible for protocol configuration, including
* hostname validation, client-side authentication, etc.
*
* <p>
* A TLS channel is created by using one of its subclasses. They will
* take an existing {@link ByteChannel} (typically, but not necessarily, a
* {@link SocketChannel}) and a {@link SSLEngine}.
*
* <p>
* It should be noted that this interface extends {@link ByteChannel} as a
* design compromise, but it does not follow its interface completely. In
* particular, in case of underlying non-blocking channels, when it is not
* possible to complete an operation, no zero is returned, but an
* {@link WouldBlockException}. This divergence from the base interface is
* needed because both a <code>read</code> and a <code>write</code> operation
* can run out of both bytesProduced for reading and buffer space for writing, as a
* handshake (a bidirectional operation) can happen at any moment. The user
* would use a {@link Selector} to wait for the expected condition
* <em>of the underlying channel</em>, and should know which operation to
* register.
*
* <p>
* On top of that, operations can also fail to complete due to asynchronous
* tasks; this is communicated using a {@link NeedsTaskException}. This behavior
* is controlled by the {@link #getRunTasks()} attribute. This allows the user
* to execute CPU-intensive tasks out of the selector loop.
*/
public interface TlsChannel extends ByteChannel, GatheringByteChannel, ScatteringByteChannel {
Return a reference to the underlying ByteChannel
. /**
* Return a reference to the underlying {@link ByteChannel}.
*/
ByteChannel getUnderlying();
Return a reference to the SSLEngine
used. Returns: the engine reference if present, or null
if unknown
(that can happen in server-side channels before the SNI is
parsed).
/**
* Return a reference to the {@link SSLEngine} used.
*
* @return the engine reference if present, or <code>null</code> if unknown
* (that can happen in server-side channels before the SNI is
* parsed).
*/
SSLEngine getSslEngine();
Return the callback function to be executed when the TLS session is
established (or re-established).
See Also: - withSessionInitCallback.withSessionInitCallback(Consumer)
/**
* Return the callback function to be executed when the TLS session is
* established (or re-established).
*
* @see TlsChannelBuilder#withSessionInitCallback(Consumer)
*/
Consumer<SSLSession> getSessionInitCallback();
Return the BufferAllocator
to use for unencrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel. See Also:
/**
* Return the {@link BufferAllocator} to use for unencrypted data. Actually, a decorating subclass is returned,
* which contains allocation statistics for this channel.
*
* @see TlsChannelBuilder#withPlainBufferAllocator(BufferAllocator)
* @see TrackingAllocator
*/
TrackingAllocator getPlainBufferAllocator();
Return the BufferAllocator
to use for encrypted data. Actually, a decorating subclass is returned, which contains allocation statistics for this channel. See Also:
/**
* Return the {@link BufferAllocator} to use for encrypted data. Actually, a decorating subclass is returned,
* which contains allocation statistics for this channel.
*
* @see TlsChannelBuilder#withEncryptedBufferAllocator(BufferAllocator)
* @see TrackingAllocator
*/
TrackingAllocator getEncryptedBufferAllocator();
Return whether CPU-intensive tasks are run or not.
See Also: - withRunTasks.withRunTasks(boolean)
/**
* Return whether CPU-intensive tasks are run or not.
*
* @see TlsChannelBuilder#withRunTasks(boolean)
*/
boolean getRunTasks();
Reads 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 WouldBlockException
may be thrown. Note that this also includes the possibility of a NeedsWriteException
, due to the fact that, during a TLS handshake, bytesProduced need to be written to the underlying channel. In any case, after a WouldBlockException
, 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 NeedsTaskException
will 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.
Params: - dst – The buffer into which bytesProduced are to be transferred
Throws: - WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
Returns: The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Reads a sequence of bytesProduced from this channel into the given buffer.
*
* <p>
* An attempt is made to read up to <i>r</i> bytesProduced from the channel, where
* <i>r</i> is the number of bytesProduced remaining in the buffer, that is,
* <tt>dst.remaining()</tt>, at the moment this method is invoked.
*
* <p>
* Suppose that a byte sequence of length <i>n</i> is read, where <tt>0</tt>
* <tt><=</tt> <i>n</i> <tt><=</tt> <i>r</i>.
* This byte sequence will be transferred into the buffer so that the first
* byte in the sequence is at index <i>p</i> and the last byte is at index
* <i>p</i> <tt>+</tt> <i>n</i> <tt>-</tt> <tt>1</tt>,
* where <i>p</i> is the buffer's position at the moment this method is
* invoked. Upon return the buffer's position will be equal to <i>p</i>
* <tt>+</tt> <i>n</i>; its limit will not have changed.
*
* <p>
* 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 {@link WouldBlockException} may be thrown. Note that this also includes
* the possibility of a {@link NeedsWriteException}, due to the fact that,
* during a TLS handshake, bytesProduced need to be written to the underlying
* channel. In any case, after a {@link WouldBlockException}, the operation
* should be retried when the underlying channel is ready (for reading or
* writing, depending on the subclass).
*
* <p>
* If the channel is configured to not run tasks and one is due to run, a
* {@link NeedsTaskException} will be thrown. In this case the operation
* should be retried after the task is run.
*
* <p>
* 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.
*
* @param dst The buffer into which bytesProduced are to be transferred
* @return The number of bytesProduced read, or <tt>-1</tt> if the channel has
* reached end-of-stream; contrary to the behavior specified in
* {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
int read(ByteBuffer dst) throws IOException;
Writes 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 WouldBlockException
will be thrown. Note that this also includes the possibility of a NeedsReadException
, due to the fact that, during a TLS handshake, bytes need to be read from the underlying channel. In any case, after a WouldBlockException
, 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 NeedsTaskException
will 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.
Params: - src – The buffer from which bytesProduced are to be retrieved
Throws: - WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
Returns: The number of bytesProduced written, contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Writes a sequence of bytesProduced to this channel from the given buffer.
*
* <p>
* An attempt is made to write up to <i>r</i> bytesProduced to the channel, where
* <i>r</i> is the number of bytesProduced remaining in the buffer, that is,
* <tt>src.remaining()</tt>, at the moment this method is invoked.
*
* <p>
* Suppose that a byte sequence of length <i>n</i> is written, where
* <tt>0</tt> <tt><=</tt> <i>n</i> <tt><=</tt>
* <i>r</i>. This byte sequence will be transferred from the buffer starting
* at index <i>p</i>, where <i>p</i> is the buffer's position at the moment
* this method is invoked; the index of the last byte written will be
* <i>p</i> <tt>+</tt> <i>n</i> <tt>-</tt> <tt>1</tt>.
* Upon return the buffer's position will be equal to <i>p</i>
* <tt>+</tt> <i>n</i>; its limit will not have changed.
*
* <p>
* If the underlying channel is in blocking mode, a write operation will
* return only after writing all of the <i>r</i> 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
* {@link WouldBlockException} will be thrown. Note that this also includes
* the possibility of a {@link NeedsReadException}, due to the fact that,
* during a TLS handshake, bytes need to be read from the underlying channel.
* In any case, after a {@link WouldBlockException}, the operation should be
* retried when the underlying channel is ready (for reading or writing,
* depending on the subclass).
*
* <p>
* If the channel is configured to not run tasks and one is due to run, a
* {@link NeedsTaskException} will be thrown. In this case the operation
* should be retried after the task is run.
*
* <p>
* 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.
*
* @param src The buffer from which bytesProduced are to be retrieved
* @return The number of bytesProduced written, contrary to the behavior specified
* in {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
int write(ByteBuffer src) throws IOException;
Initiates a handshake (initial or renegotiation) on this channel. This
method is not needed for the initial handshake, as the
read()
and write()
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 WouldBlockException
can 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 NeedsTaskException
will 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.
Throws: - WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
/**
* Initiates a handshake (initial or renegotiation) on this channel. This
* method is not needed for the initial handshake, as the
* <code>read()</code> and <code>write()</code> methods will implicitly do
* the initial handshake if needed.
*
* <p>
* This method may block if the underlying channel if in blocking mode.
*
* <p>
* Note that renegotiation is a problematic feature of the TLS protocol,
* that should only be initiated at quiet point of the protocol.
*
* <p>
* This method may block if the underlying channel is in blocking mode,
* otherwise a {@link WouldBlockException} can be thrown. In this case the
* operation should be retried when the underlying channel is ready (for
* reading or writing, depending on the subclass).
*
* <p>
* If the channel is configured to not run tasks and one is due to run, a
* {@link NeedsTaskException} will be thrown, with a reference to the task.
* In this case the operation should be retried after the task is run.
*
* <p>
* 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.
*
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
void renegotiate() throws IOException;
Forces the initial TLS handshake. Calling this method is usually not
needed, as a handshake will happen automatically when doing the first
read()
or write()
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 WouldBlockException
can 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 NeedsTaskException
will 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.
Throws: - WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
/**
* Forces the initial TLS handshake. Calling this method is usually not
* needed, as a handshake will happen automatically when doing the first
* <code>read()</code> or <code>write()</code> operation. Calling this
* method after the initial handshake has been done has no effect.
*
* <p>
* This method may block if the underlying channel is in blocking mode,
* otherwise a {@link WouldBlockException} can be thrown. In this case the
* operation should be retried when the underlying channel is ready (for
* reading or writing, depending on the subclass).
*
* <p>
* If the channel is configured to not run tasks and one is due to run, a
* {@link NeedsTaskException} will be thrown, with a reference to the task.
* In this case the operation should be retried after the task is run.
*
* <p>
* 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.
*
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
void handshake() throws IOException;
Writes 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 write(ByteBuffer)
for more details.
Params: - srcs – The buffers from which bytesProduced are to be retrieved
- offset – The offset within the buffer array of the first buffer from
which bytesProduced are to be retrieved; must be non-negative and no
larger than srcs.length
- length – The maximum number of buffers to be accessed; must be
non-negative and no larger than srcs.length
- offset
Throws: - IndexOutOfBoundsException – If the preconditions on the offset and
length parameters do not hold
- WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
Returns: The number of bytesProduced written, contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Writes a sequence of bytesProduced to this channel from a subsequence of the
* given buffers.
*
* <p>
* See {@link GatheringByteChannel#write(ByteBuffer[], int, int)} for more
* details of the meaning of this signature.
*
* <p>
* This method behaves slightly different than the interface specification,
* with respect to non-blocking responses, see {@link #write(ByteBuffer)}
* for more details.
*
* @param srcs The buffers from which bytesProduced are to be retrieved
* @param offset The offset within the buffer array of the first buffer from
* which bytesProduced are to be retrieved; must be non-negative and no
* larger than <tt>srcs.length</tt>
* @param length The maximum number of buffers to be accessed; must be
* non-negative and no larger than <tt>srcs.length</tt>
* - <tt>offset</tt>
* @return The number of bytesProduced written, contrary to the behavior specified
* in {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt> and
* <tt>length</tt> parameters do not hold
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
Writes 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
c.write(srcs, 0, srcs.length);
This method behaves slightly different than the interface specification, with respect to non-blocking responses, see write(ByteBuffer)
for more details.
Params: - srcs – The buffers from which bytesProduced are to be retrieved
Throws: - IndexOutOfBoundsException – If the preconditions on the offset and
length parameters do not hold
- WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOExceptions
Returns: The number of bytesProduced written, contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Writes a sequence of bytesProduced to this channel from the given buffers.
*
* <p>
* An invocation of this method of the form <tt>c.write(srcs)</tt> behaves
* in exactly the same manner as the invocation
*
* <blockquote>
*
* <pre>
* c.write(srcs, 0, srcs.length);
* </pre>
*
* </blockquote>
* <p>
* This method behaves slightly different than the interface specification,
* with respect to non-blocking responses, see {@link #write(ByteBuffer)}
* for more details.
*
* @param srcs The buffers from which bytesProduced are to be retrieved
* @return The number of bytesProduced written, contrary to the behavior specified
* in {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt> and
* <tt>length</tt> parameters do not hold
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOExceptions
*/
long write(ByteBuffer[] srcs) throws IOException;
Reads 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 read(ByteBuffer)
for more details.
Params: - dsts – The buffers into which bytesProduced are to be transferred
- offset – The offset within the buffer array of the first buffer into
which bytesProduced are to be transferred; must be non-negative and no
larger than dsts.length
- length – The maximum number of buffers to be accessed; must be
non-negative and no larger than dsts.length
- offset
Throws: - IndexOutOfBoundsException – If the preconditions on the offset and
length parameters do not hold
- WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
Returns: The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Reads a sequence of bytesProduced from this channel into a subsequence of the
* given buffers.
*
* <p>
* See {@link ScatteringByteChannel#read(ByteBuffer[], int, int)} for more
* details of the meaning of this signature.
*
* <p>
* This method behaves slightly different than the interface specification,
* with respect to non-blocking responses, see {@link #read(ByteBuffer)} for
* more details.
*
* @param dsts The buffers into which bytesProduced are to be transferred
* @param offset The offset within the buffer array of the first buffer into
* which bytesProduced are to be transferred; must be non-negative and no
* larger than <tt>dsts.length</tt>
* @param length The maximum number of buffers to be accessed; must be
* non-negative and no larger than <tt>dsts.length</tt>
* - <tt>offset</tt>
* @return The number of bytesProduced read, or <tt>-1</tt> if the channel has
* reached end-of-stream; contrary to the behavior specified in
* {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt> and
* <tt>length</tt> parameters do not hold
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
long read(ByteBuffer[] dsts, int offset, int length) throws IOException;
Reads 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 invocation
c.read(dsts, 0, dsts.length);
This method behaves slightly different than the interface specification, with respect to non-blocking responses, see read(ByteBuffer)
for more details.
Params: - dsts – The buffers into which bytesProduced are to be transferred
Throws: - IndexOutOfBoundsException – If the preconditions on the offset and
length parameters do not hold
- WouldBlockException – if the channel is in non-blocking mode and the IO operation
cannot be completed immediately
- NeedsTaskException – if the channel is not configured to run tasks automatically
and a task needs to be executed to complete the operation
- SSLException – if the
SSLEngine
throws a SSLException - IOException – if the underlying channel throws an IOException
Returns: The number of bytesProduced read, or -1 if the channel has reached end-of-stream; contrary to the behavior specified in ByteChannel
, this method never returns 0, but throws WouldBlockException
/**
* Reads a sequence of bytesProduced from this channel into the given buffers.
*
* <p>
* An invocation of this method of the form <tt>c.read(dsts)</tt> behaves in
* exactly the same manner as the invocation
*
* <blockquote>
*
* <pre>
* c.read(dsts, 0, dsts.length);
* </pre>
*
* </blockquote>
*
* <p>
* This method behaves slightly different than the interface specification,
* with respect to non-blocking responses, see {@link #read(ByteBuffer)} for
* more details.
*
* @param dsts The buffers into which bytesProduced are to be transferred
* @return The number of bytesProduced read, or <tt>-1</tt> if the channel has
* reached end-of-stream; contrary to the behavior specified in
* {@link ByteChannel}, this method never returns 0, but throws
* {@link WouldBlockException}
* @throws IndexOutOfBoundsException If the preconditions on the <tt>offset</tt> and
* <tt>length</tt> parameters do not hold
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation
* cannot be completed immediately
* @throws NeedsTaskException if the channel is not configured to run tasks automatically
* and a task needs to be executed to complete the operation
* @throws SSLException if the {@link SSLEngine} throws a SSLException
* @throws IOException if the underlying channel throws an IOException
*/
long read(ByteBuffer[] dsts) throws IOException;
Closes the underlying channel. This method first does some form of TLS close if not already done. The exact behavior can be configured using the TlsChannelBuilder.withWaitForCloseConfirmation
. The default behavior mimics what happens in a normal (that is, non layered) Socket.close()
.
For finer control of the TLS close, use shutdown()
Throws: - IOException – if the underlying channel throws an IOException during close.
Exceptions thrown during any previous TLS close are not
propagated.
/**
* Closes the underlying channel. This method first does some form of TLS
* close if not already done. The exact behavior can be configured using the
* {@link TlsChannelBuilder#withWaitForCloseConfirmation}.
*
* <p>
* The default behavior mimics what happens in a normal (that is, non
* layered) {@link javax.net.ssl.SSLSocket#close()}.
*
* <p>
* For finer control of the TLS close, use {@link #shutdown()}
*
* @throws IOException if the underlying channel throws an IOException during close.
* Exceptions thrown during any previous TLS close are not
* propagated.
*/
void close() throws IOException;
Shuts 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 shutdownSent()
flag and return false
. 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 return
true
.
If the peer already sent the "close notify" alert and it was already processed implicitly inside a read operation, the shutdownReceived()
flag is already set. This method will then send the "close notify" alert, set the shutdownSent()
flag and immediately return true
. 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 WouldBlockException
if 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 a SocketChannel
).
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.
Throws: - IOException – if the underlying channel throws an IOException
- WouldBlockException – if the channel is in non-blocking mode and the IO operation cannot be completed
immediately
See Also: Returns: whether the closing is finished.
/**
* <p> Shuts down the TLS connection. This method emulates the behavior of OpenSSL's <a
* href="https://wiki.openssl.org/index.php/Manual:SSL_shutdown(3)"> SSL_shutdown()</a>.</p>
*
* <p> 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.</p>
*
* <p> This class supports both uni- and bidirectional shutdown by its 2 step behavior, using this method.</p>
*
* <p> When this is the first party to send the "close notify" alert, this method will only send the alert, set the
* {@link #shutdownSent()} flag and return <code>false</code>. 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 return
* <code>true</code>.</p>
*
* <p> If the peer already sent the "close notify" alert and it was already processed implicitly inside a read
* operation, the {@link #shutdownReceived()} flag is already set. This method will then send the "close notify"
* alert, set the {@link #shutdownSent()} flag and immediately return <code>true</code>. It is therefore recommended
* to check the return value of this method and call it again, if the bidirectional shutdown is not yet
* complete.</p>
*
* <p> If the underlying channel is blocking, this method will only return once the handshake step has been finished
* or an error occurred.</p>
*
* <p> If the underlying channel is non-blocking, this method may throw {@link WouldBlockException} if 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 a {@link SocketChannel}).</p>
*
* <p> 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 <a href="https://hal.inria.fr/hal-01102013">the
* original paper</a>.</p>
*
* @return whether the closing is finished.
* @throws IOException if the underlying channel throws an IOException
* @throws WouldBlockException if the channel is in non-blocking mode and the IO operation cannot be completed
* immediately
* @see TlsChannelBuilder#withWaitForCloseConfirmation(boolean)
*/
boolean shutdown() throws IOException;
Return whether this side of the connection has already received the close
notification.
See Also: Returns: true
if the close notification was received
/**
* Return whether this side of the connection has already received the close
* notification.
*
* @return <code>true</code> if the close notification was received
* @see #shutdown()
*/
boolean shutdownReceived();
Return whether this side of the connection has already sent the close
notification.
See Also: Returns: true
if the close notification was sent
/**
* Return whether this side of the connection has already sent the close
* notification.
*
* @return <code>true</code> if the close notification was sent
* @see #shutdown()
*/
boolean shutdownSent();
}