/*
* TransportChannel.java February 2007
*
* Copyright (C) 2007, Niall Gallagher <niallg@users.sf.net>
*
* 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.
*/
package org.simpleframework.transport;
import static org.simpleframework.transport.TransportEvent.ERROR;
import java.nio.channels.SocketChannel;
import java.util.Map;
import javax.net.ssl.SSLEngine;
import org.simpleframework.transport.trace.Trace;
/**
* The <code>TransportChannel</code> provides a means to deliver and receive
* content over a transport. This essentially provides two adapters which enable
* simpler communication with the underlying transport. They hide the
* complexities involved with buffering and resetting data written to and read
* from the socket.
*
* @author Niall Gallagher
*
* @see org.simpleframework.transport.Processor
*/
public class TransportChannel implements Channel {
/**
* This represents the underlying transport that is to be used.
*/
private final Transport transport;
/**
* This is the engine that is used to secure the transport.
*/
private final SSLEngine engine;
/**
* This is used to provide a cursor view on the input.
*/
private final Cursor cursor;
/**
* This is used to provide a blocking means for sending data.
*/
private final Sender sender;
/**
* This is the trace used to monitor events on the channel.
*/
private final Trace trace;
/**
* Constructor for the <code>TransportChannel</code> object. The transport
* channel basically wraps a channel and provides a means to send and
* receive data using specialized adapters. These adapters provide a simpler
* means for communicating over the network to the connected client.
*
* @param transport
* this is the underlying transport to be used
*/
public TransportChannel(Transport transport) {
this.cursor = new TransportCursor(transport);
this.sender = new TransportSender(transport);
this.engine = transport.getEngine();
this.trace = transport.getTrace();
this.transport = transport;
}
/**
* This is used to determine if the channel is secure and that data read
* from and data written to the request is encrypted. Channels transferred
* over SSL are considered secure and will have this return true, otherwise
* it will return false.
*
* @return true if this is secure for reading and writing
*/
@Override
public boolean isSecure() {
return this.engine != null;
}
/**
* This is used to acquire the SSL engine used for security. If the socket
* is connected to an SSL transport this returns an SSL engine which can be
* used to establish the secure connection and send and receive content over
* that connection. If this is null then the socket represents a normal
* transport.
*
* @return the SSL engine used to establish a secure transport
*/
@Override
public SSLEngine getEngine() {
return this.engine;
}
/**
* This gets the <code>Trace</code> object associated with the channel. The
* trace is used to log various events for the life of the transaction such
* as low level read and write events as well as milestone events and
* errors.
*
* @return this returns the trace associated with the socket
*/
@Override
public Trace getTrace() {
return this.trace;
}
/**
* This is the connected socket channel associated with this. In order to
* determine if content can be read or written to or from the channel this
* socket can be used with a selector. This provides a means to react to I/O
* events as they occur rather than polling the channel which is generally
* less performant.
*
* @return this returns the connected socket channel
*/
@Override
public SocketChannel getSocket() {
return this.transport.getChannel();
}
/**
* This returns the <code>Map</code> of attributes used to hold connection
* information for the channel. The attributes here are taken from the
* pipeline attributes and may contain details such as SSL certificates or
* other such useful information.
*
* @return returns the attributes associated with the channel
*/
@Override
public Map getAttributes() {
return this.transport.getAttributes();
}
/**
* This provides the <code>Cursor</code> for this channel. The cursor
* provides a resettable view of the input buffer and will allow the server
* kernel to peek into the input buffer without having to take the data from
* the input. This allows overflow to be pushed back on to the cursor for
* subsequent reads.
*
* @return this returns the input cursor for the channel
*/
@Override
public Cursor getCursor() {
return this.cursor;
}
/**
* This provides the <code>Sender</code> for the channel. This is used to
* provide a blocking output mechanism for the channel. Enabling blocking
* reads ensures that output buffering can be limited to an extent, which
* ensures that memory remains low at high load periods. Writes to the
* sender may result in the data being copied and queued until the socket is
* write ready.
*
* @return this returns the output sender for this channel
*/
@Override
public Sender getSender() {
return this.sender;
}
/**
* Because the channel represents a duplex means of communication there
* needs to be a means to close it down. This provides such a means. By
* closing the channel the cursor and sender will no longer send or recieve
* data to or from the network. The client will also be signaled that the
* connection has been severed.
*/
@Override
public void close() {
try {
this.transport.close();
} catch (Exception cause) {
this.trace.trace(ERROR, cause);
}
}
}