/**
* This file is part of SecureNIO. Copyright (C) 2014 K. Dermitzakis
* <dermitza@gmail.com>
*
* SecureNIO is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* SecureNIO is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with SecureNIO. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.dermitza.securenio.socket;
import ch.dermitza.securenio.socket.timeout.worker.Timeout;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
/**
* An interface that defines the underlying {@link SocketChannel}
* implementations. <p> These can be either of a {@link PlainSocket}
* implementation or a {@link ch.dermitza.securenio.socket.secure.SecureSocket}
* implementation. The interface is needed to envelop the underlying
* {@link SocketChannel} implementations such that the secure channel can
* perform handshaking, encryption and decryption of the data, as only the
* Oracle {@link SocketChannel} implementation is allowed to be associated with
* a {@link Selector}.
*
* @author K. Dermitzakis
* @version 0.19
* @since 0.18
*
*/
public interface SocketIF {
/**
* Returns the underlying {@link SocketChannel}. This is done in order to
* register the current socket with a {@link Selector}, as only the
* {@link SocketChannel} implementation is allowed to be associated with a
* {@link Selector}.
*
* @return the underlying SocketChannel
*/
SocketChannel getSocket();
//------------------ PASS-THROUGH IMPLEMENTATIONS ------------------------//
/**
* Pass-through implementation of
* {@link SocketChannel#connect(SocketAddress remote)}
*
* @param remote The remote address to which this channel is to be connected
* @return true if a connection was established, false if this channel is in
* non-blocking mode and the connection operation is in progress
* @throws IOException Propagated exceptions from the underlying
* {@link SocketChannel#connect(SocketAddress remote)} implementation.
*/
boolean connect(SocketAddress remote) throws IOException;
/**
* Pass-through implementation of {@link SocketChannel#finishConnect()}
*
* @return true if, and only if, this channel's socket is now connected
* @throws IOException Propagated exceptions from the underlying
* {@link SocketChannel#finishConnect()} implementation.
*/
boolean finishConnect() throws IOException;
/**
* Pass-through implementation of
* {@link SocketChannel#register(Selector sel, int ops)}
*
* @param sel The selector with which this channel is to be registered
* @param ops The interest set for the resulting key
* @return A key representing the registration of this channel with the
* given selector
* @throws ClosedChannelException Propagated exceptions from the underlying
* {@link SocketChannel#register(Selector sel, int ops)} implementation.
*/
SelectionKey register(Selector sel, int ops) throws ClosedChannelException;
/**
* Pass-through implementation of
* {@link SocketChannel#configureBlocking(boolean block)}
*
* @param block If true then this channel will be placed in blocking mode;
* if false then it will be placed in non-blocking mode
* @return This selectable channel
* @throws IOException Propagated exceptions from the underlying
* {@link SocketChannel#configureBlocking(boolean block)} implementation.
*/
SelectableChannel configureBlocking(boolean block) throws IOException;
/**
* Pass-through implementation of
* {@link SocketChannel#read(ByteBuffer buffer)}
*
* @param buffer The buffer into which bytes are to be transferred
* @return The number of bytes read, possibly zero, or -1 if the channel has
* reached end-of-stream
* @throws IOException Propagated exceptions from the underlying
* {@link SocketChannel#read(ByteBuffer buffer)} implementation.
*/
int read(ByteBuffer buffer) throws IOException;
/**
* Pass-through implementation of
* {@link SocketChannel#write(ByteBuffer buffer)}
*
* @param buffer
* @return The number of bytes written, possibly zero
* @throws IOException Propagated exceptions from the underlying
* {@link SocketChannel#write(ByteBuffer buffer)} implementation.
*/
int write(ByteBuffer buffer) throws IOException;
/**
* Pass-through implementation of {@link SocketChannel#close()}
*
* @throws IOException Propagated exceptions from the underlying
* SocketChannel.close() implementation.
*/
void close() throws IOException;
//-------------------- SSL/TLS-SPECIFIC IMPLEMENTATIONS ------------------//
/**
* Invalidate the current {@link javax.net.ssl.SSLSession}. This method
* could be periodically used via a {@link Timeout} to perform SSL/TLS
* session rotation if needed. <p> This method has NO EFFECT for a
* {@link PlainSocket} implementation.
*/
void invalidateSession();
/**
* Initialize SSL/TLS handshaking. <p> This method has NO EFFECT for a
* {@link PlainSocket} implementation.
*
* @throws IOException propagated exceptions from
* {@link #processHandshake()}
* @throws javax.net.ssl.SSLException if there is an SSL/TLS problem with
* the call to the underlying
* {@link javax.net.ssl.SSLEngine#beginHandshake()}.
* @see ch.dermitza.securenio.socket.secure.SecureSocket#initHandshake()
*/
void initHandshake() throws IOException;
/**
* Update the {@link javax.net.ssl.SSLEngineResult} and
* {@link #setTaskPending(boolean)} to false. <p> This method has NO EFFECT
* for a {@link PlainSocket} implementation.
*
* @see ch.dermitza.securenio.socket.secure.SecureSocket#updateResult()
*/
void updateResult();
/**
* Used to identify whether the handshaking performed from the underlying
* {@link javax.net.ssl.SSLEngine} is still pending. <p> This method has NO
* EFFECT for a {@link PlainSocket} implementation.
*
* @return whether the SSL/TLS handshaking is still pending. Always false
* for a {@link PlainSocket} implementation
* @see ch.dermitza.securenio.socket.secure.SecureSocket#handshakePending()
*/
boolean handshakePending();
/**
* Sets whether or not there is an {@link javax.net.ssl.SSLEngine} task
* pending, during an SSL/TLS handshake. <p> This method has NO EFFECT for a
* {@link PlainSocket} implementation.
*
* @param taskPending Set whether or not there is a
* {@link javax.net.ssl.SSLEngine} task pending for the
* {@link javax.net.ssl.SSLEngine} associated with the underlying
* {@link SocketChannel}. Has no effect in a single threaded implementation.
* @see
* ch.dermitza.securenio.socket.secure.SecureSocket#setTaskPending(boolean)
*/
void setTaskPending(boolean taskPending);
/**
* Performs SSL/TLS handshaking. <p> This method has NO EFFECT for a
* {@link PlainSocket} implementation.
*
* @throws IOException If there is an underlying IOException while
* performing the handshake
* @throws javax.net.ssl.SSLException If there is an exception thrown by the
* underlying {@link javax.net.ssl.SSLEngine} while performing the handshake
* @see ch.dermitza.securenio.socket.secure.SecureSocket#processHandshake()
*/
void processHandshake() throws IOException;
}