/**
* 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 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;
/**
* A plain socket implementation of {@link SocketIF}. As a plain socket behaves
* no different than a {@link SocketChannel}, this class can also be seen as a
* wrapper with no additional functionality. Note that this class is declared as
* final as it should NOT be extended. <p> All required methods from
* {@link SocketIF} that deal with the secure implementation
* ({@link ch.dermitza.securenio.socket.secure.SecureSocket}) have no effect in
* this implementation.
*
* @author K. Dermitzakis
* @version 0.18
*/
public final class PlainSocket implements SocketIF {
/**
* The underlying {@link SocketChannel}
*/
private final SocketChannel channel;
/**
* Create a plain socket (i.e. no encryption) instance of the
* {@link SocketIF} interface. This instance has empty placeholder methods
* for the SSL/TLS-related methods.
*
* @param channel The associated underlying {@link SocketChannel}.
*/
public PlainSocket(SocketChannel channel) {
this.channel = channel;
}
/**
* 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.
*/
@Override
public SelectableChannel configureBlocking(boolean block) throws IOException {
return channel.configureBlocking(block);
}
/**
* 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.
*/
@Override
public int read(ByteBuffer buffer) throws IOException {
return channel.read(buffer);
}
/**
* 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.
*/
@Override
public int write(ByteBuffer buffer) throws IOException {
return channel.write(buffer);
}
/**
* 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.
*/
@Override
public boolean connect(SocketAddress remote) throws IOException {
return channel.connect(remote);
}
/**
* 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.
*/
@Override
public SelectionKey register(Selector sel, int ops) throws ClosedChannelException {
return channel.register(sel, ops);
}
/**
* 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
*/
@Override
public SocketChannel getSocket() {
return channel;
}
/**
* Pass-through implementation of {@link SocketChannel#close()}
*
* @throws IOException Propagated exceptions from the underlying
* SocketChannel.close() implementation.
*/
@Override
public void close() throws IOException {
channel.close();
}
/**
* 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.
*/
@Override
public boolean finishConnect() throws IOException {
return channel.finishConnect();
}
//---------------------- SSL/TLS METHODS (UNUSED) ------------------------//
/**
* Empty implementation satisfying {@link SocketIF#processHandshake()}. No
* handshaking is present on a {@link PlainSocket}. This method has NO
* effect.
*/
@Override
public void processHandshake() {
// we don't need to do any handshaking on a plain channel
}
/**
* Empty implementation satisfying {@link SocketIF#handshakePending()}. No
* handshaking is present on a {@link PlainSocket}. This method has NO
* effect.
*
* @return Always false, no handshake is pending on a PlainSocket
*/
@Override
public boolean handshakePending() {
// No handshaking happens in a plain socket
return false;
}
/**
* Empty implementation satisfying {@link SocketIF#updateResult()}. No
* {@link javax.net.ssl.SSLEngineResult} is present on a
* {@link PlainSocket}. This method has NO effect.
*/
@Override
public void updateResult() {
// Nothing to do in a plain channel
}
/**
* Empty implementation satisfying
* {@link SocketIF#setTaskPending(boolean taskPending)}. No task is pending
* on a {@link PlainSocket}. This method has NO effect.
*
* @param taskPending unused
*/
@Override
public void setTaskPending(boolean taskPending) {
// no pending task for a plain socket, do nothing
}
/**
* Empty implementation satisfying {@link SocketIF#invalidateSession()}. No
* {@link javax.net.ssl.SSLSession} is present on a {@link PlainSocket}.
* This method has NO effect.
*/
@Override
public void invalidateSession() {
// Nothing to do here
}
/**
* Empty implementation satisfying {@link SocketIF#initHandshake()}. No
* handshaking is present on a {@link PlainSocket}. This method has NO
* effect.
*
* @throws IOException Never thrown.
*/
@Override
public void initHandshake() throws IOException {
// Nothing to do here
}
}