blob: 9abdf01a975e59262acc3d83ae0c6f7e5ecc933e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.mina.core.session;
import java.net.SocketAddress;
import java.util.Set;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.filterchain.IoFilterChain;
import org.apache.mina.core.future.CloseFuture;
import org.apache.mina.core.future.ReadFuture;
import org.apache.mina.core.future.WriteFuture;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.service.TransportMetadata;
import org.apache.mina.core.write.WriteRequest;
import org.apache.mina.core.write.WriteRequestQueue;
/**
* <p>
* A handle which represents connection between two end-points regardless of
* transport types.
* </p>
* <p>
* {@link IoSession} provides user-defined attributes. User-defined attributes
* are application-specific data which are associated with a session.
* It often contains objects that represents the state of a higher-level protocol
* and becomes a way to exchange data between filters and handlers.
* </p>
* <h3>Adjusting Transport Type Specific Properties</h3>
* <p>
* You can simply downcast the session to an appropriate subclass.
* </p>
* <h3>Thread Safety</h3>
* <p>
* {@link IoSession} is thread-safe. But please note that performing
* more than one {@link #write(Object)} calls at the same time will
* cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)}
* to be executed simultaneously, and therefore you have to make sure the
* {@link IoFilter} implementations you're using are thread-safe, too.
* </p>
* <h3>Equality of Sessions</h3>
* TODO : The getId() method is totally wrong. We can't base
* a method which is designed to create a unique ID on the hashCode method.
* {@link Object#equals(Object)} and {@link Object#hashCode()} shall not be overriden
* to the default behavior that is defined in {@link Object}.
*
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public interface IoSession {
/**
* @return a unique identifier for this session. Every session has its own
* ID which is different from each other.
*
* TODO : The way it's implemented does not guarantee that the contract is
* respected. It uses the HashCode() method which don't guarantee the key
* unicity.
*/
long getId();
/**
* @return the {@link IoService} which provides I/O service to this session.
*/
IoService getService();
/**
* @return the {@link IoHandler} which handles this session.
*/
IoHandler getHandler();
/**
* @return the configuration of this session.
*/
IoSessionConfig getConfig();
/**
* @return the filter chain that only affects this session.
*/
IoFilterChain getFilterChain();
/**
* Get the queue that contains the message waiting for being written.
* As the reader might not be ready, it's frequent that the messages
* aren't written completely, or that some older messages are waiting
* to be written when a new message arrives. This queue is used to manage
* the backlog of messages.
*
* @return The queue containing the pending messages.
*/
WriteRequestQueue getWriteRequestQueue();
/**
* @return the {@link TransportMetadata} that this session runs on.
*/
TransportMetadata getTransportMetadata();
/**
* TODO This javadoc is wrong. The return tag should be short.
*
* @return a {@link ReadFuture} which is notified when a new message is
* received, the connection is closed or an exception is caught. This
* operation is especially useful when you implement a client application.
* TODO : Describe here how we enable this feature.
* However, please note that this operation is disabled by default and
* throw {@link IllegalStateException} because all received events must be
* queued somewhere to support this operation, possibly leading to memory
* leak. This means you have to keep calling {@link #read()} once you
* enabled this operation. To enable this operation, please call
* {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>.
*
* @throws IllegalStateException if
* {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation}
* option has not been enabled.
*/
ReadFuture read();
/**
* Writes the specified <code>message</code> to remote peer. This
* operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)}
* will be invoked when the message is actually sent to remote peer.
* You can also wait for the returned {@link WriteFuture} if you want
* to wait for the message actually written.
*
* @param message The message to write
* @return The associated WriteFuture
*/
WriteFuture write(Object message);
/**
* (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>.
* This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)}
* will be invoked when the message is actually sent to remote peer. You can
* also wait for the returned {@link WriteFuture} if you want to wait for
* the message actually written.
* <p>
* When you implement a client that receives a broadcast message from a server
* such as DHCP server, the client might need to send a response message for the
* broadcast message the server sent. Because the remote address of the session
* is not the address of the server in case of broadcasting, there should be a
* way to specify the destination when you write the response message.
* This interface provides {@link #write(Object, SocketAddress)} method so you
* can specify the destination.
*
* @param message The message to write
* @param destination <tt>null</tt> if you want the message sent to the
* default remote address
* @return The associated WriteFuture
*/
WriteFuture write(Object message, SocketAddress destination);
/**
* Closes this session immediately or after all queued write requests
* are flushed. This operation is asynchronous. Wait for the returned
* {@link CloseFuture} if you want to wait for the session actually closed.
*
* @param immediately {@code true} to close this session immediately
* . The pending write requests
* will simply be discarded.
* {@code false} to close this session after all queued
* write requests are flushed.
* @return The associated CloseFuture
* @deprecated Use either the {@link #closeNow()} or the {@link #closeOnFlush()} methods
*/
@Deprecated
CloseFuture close(boolean immediately);
/**
* Closes this session immediately. This operation is asynchronous, it
* returns a {@link CloseFuture}.
*
* @return The {@link CloseFuture} that can be use to wait for the completion of this operation
*/
CloseFuture closeNow();
/**
* Closes this session after all queued write requests are flushed. This operation
* is asynchronous. Wait for the returned {@link CloseFuture} if you want to wait
* for the session actually closed.
*
* @return The associated CloseFuture
*/
CloseFuture closeOnFlush();
/**
* Closes this session after all queued write requests
* are flushed. This operation is asynchronous. Wait for the returned
* {@link CloseFuture} if you want to wait for the session actually closed.
* @deprecated use {@link #closeNow()}
*
* @return The associated CloseFuture
*/
@Deprecated
CloseFuture close();
/**
* Returns an attachment of this session.
* This method is identical with <tt>getAttribute( "" )</tt>.
*
* @return The attachment
* @deprecated Use {@link #getAttribute(Object)} instead.
*/
@Deprecated
Object getAttachment();
/**
* Sets an attachment of this session.
* This method is identical with <tt>setAttribute( "", attachment )</tt>.
*
* @param attachment The attachment
* @return Old attachment. <tt>null</tt> if it is new.
* @deprecated Use {@link #setAttribute(Object, Object)} instead.
*/
@Deprecated
Object setAttachment(Object attachment);
/**
* Returns the value of the user-defined attribute of this session.
*
* @param key the key of the attribute
* @return <tt>null</tt> if there is no attribute with the specified key
*/
Object getAttribute(Object key);
/**
* Returns the value of user defined attribute associated with the
* specified key. If there's no such attribute, the specified default
* value is associated with the specified key, and the default value is
* returned. This method is same with the following code except that the
* operation is performed atomically.
* <pre>
* if (containsAttribute(key)) {
* return getAttribute(key);
* } else {
* setAttribute(key, defaultValue);
* return defaultValue;
* }
* </pre>
*
* @param key the key of the attribute we want to retreive
* @param defaultValue the default value of the attribute
* @return The retrieved attribute or <tt>null</tt> if not found
*/
Object getAttribute(Object key, Object defaultValue);
/**
* Sets a user-defined attribute.
*
* @param key the key of the attribute
* @param value the value of the attribute
* @return The old value of the attribute. <tt>null</tt> if it is new.
*/
Object setAttribute(Object key, Object value);
/**
* Sets a user defined attribute without a value. This is useful when
* you just want to put a 'mark' attribute. Its value is set to
* {@link Boolean#TRUE}.
*
* @param key the key of the attribute
* @return The old value of the attribute. <tt>null</tt> if it is new.
*/
Object setAttribute(Object key);
/**
* Sets a user defined attribute if the attribute with the specified key
* is not set yet. This method is same with the following code except
* that the operation is performed atomically.
* <pre>
* if (containsAttribute(key)) {
* return getAttribute(key);
* } else {
* return setAttribute(key, value);
* }
* </pre>
*
* @param key The key of the attribute we want to set
* @param value The value we want to set
* @return The old value of the attribute. <tt>null</tt> if not found.
*/
Object setAttributeIfAbsent(Object key, Object value);
/**
* Sets a user defined attribute without a value if the attribute with
* the specified key is not set yet. This is useful when you just want to
* put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}.
* This method is same with the following code except that the operation
* is performed atomically.
* <pre>
* if (containsAttribute(key)) {
* return getAttribute(key); // might not always be Boolean.TRUE.
* } else {
* return setAttribute(key);
* }
* </pre>
*
* @param key The key of the attribute we want to set
* @return The old value of the attribute. <tt>null</tt> if not found.
*/
Object setAttributeIfAbsent(Object key);
/**
* Removes a user-defined attribute with the specified key.
*
* @param key The key of the attribute we want to remove
* @return The old value of the attribute. <tt>null</tt> if not found.
*/
Object removeAttribute(Object key);
/**
* Removes a user defined attribute with the specified key if the current
* attribute value is equal to the specified value. This method is same
* with the following code except that the operation is performed
* atomically.
* <pre>
* if (containsAttribute(key) &amp;&amp; getAttribute(key).equals(value)) {
* removeAttribute(key);
* return true;
* } else {
* return false;
* }
* </pre>
*
* @param key The key we want to remove
* @param value The value we want to remove
* @return <tt>true</tt> if the removal was successful
*/
boolean removeAttribute(Object key, Object value);
/**
* Replaces a user defined attribute with the specified key if the
* value of the attribute is equals to the specified old value.
* This method is same with the following code except that the operation
* is performed atomically.
* <pre>
* if (containsAttribute(key) &amp;&amp; getAttribute(key).equals(oldValue)) {
* setAttribute(key, newValue);
* return true;
* } else {
* return false;
* }
* </pre>
*
* @param key The key we want to replace
* @param oldValue The previous value
* @param newValue The new value
* @return <tt>true</tt> if the replacement was successful
*/
boolean replaceAttribute(Object key, Object oldValue, Object newValue);
/**
* @param key The key of the attribute we are looking for in the session
* @return <tt>true</tt> if this session contains the attribute with
* the specified <tt>key</tt>.
*/
boolean containsAttribute(Object key);
/**
* @return the set of keys of all user-defined attributes.
*/
Set<Object> getAttributeKeys();
/**
* @return <tt>true</tt> if this session is connected with remote peer.
*/
boolean isConnected();
/**
* @return <tt>true</tt> if this session is active.
*/
boolean isActive();
/**
* @return <tt>true</tt> if and only if this session is being closed
* (but not disconnected yet) or is closed.
*/
boolean isClosing();
/**
* @return <tt>true</tt> if the session has started and initialized a SslEngine,
* <tt>false</tt> if the session is not yet secured (the handshake is not completed)
* or if SSL is not set for this session, or if SSL is not even an option.
*/
boolean isSecured();
/**
* @return the {@link CloseFuture} of this session. This method returns
* the same instance whenever user calls it.
*/
CloseFuture getCloseFuture();
/**
* @return the socket address of remote peer.
*/
SocketAddress getRemoteAddress();
/**
* @return the socket address of local machine which is associated with this
* session.
*/
SocketAddress getLocalAddress();
/**
* @return the socket address of the {@link IoService} listens to to manage
* this session. If this session is managed by {@link IoAcceptor}, it
* returns the {@link SocketAddress} which is specified as a parameter of
* {@link IoAcceptor#bind()}. If this session is managed by
* {@link IoConnector}, this method returns the same address with
* that of {@link #getRemoteAddress()}.
*/
SocketAddress getServiceAddress();
/**
*
* Associate the current write request with the session
*
* @param currentWriteRequest the current write request to associate
*/
void setCurrentWriteRequest(WriteRequest currentWriteRequest);
/**
* Suspends read operations for this session.
*/
void suspendRead();
/**
* Suspends write operations for this session.
*/
void suspendWrite();
/**
* Resumes read operations for this session.
*/
void resumeRead();
/**
* Resumes write operations for this session.
*/
void resumeWrite();
/**
* Is read operation is suspended for this session.
*
* @return <tt>true</tt> if suspended
*/
boolean isReadSuspended();
/**
* Is write operation is suspended for this session.
*
* @return <tt>true</tt> if suspended
*/
boolean isWriteSuspended();
/**
* Update all statistical properties related with throughput assuming
* the specified time is the current time. By default this method returns
* silently without updating the throughput properties if they were
* calculated already within last
* {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
* If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
* updates the throughput properties immediately.
* @param currentTime the current time in milliseconds
* @param force Force the update if <tt>true</tt>
*/
void updateThroughput(long currentTime, boolean force);
/**
* @return the total number of bytes which were read from this session.
*/
long getReadBytes();
/**
* @return the total number of bytes which were written to this session.
*/
long getWrittenBytes();
/**
* @return the total number of messages which were read and decoded from this session.
*/
long getReadMessages();
/**
* @return the total number of messages which were written and encoded by this session.
*/
long getWrittenMessages();
/**
* @return the number of read bytes per second.
*/
double getReadBytesThroughput();
/**
* @return the number of written bytes per second.
*/
double getWrittenBytesThroughput();
/**
* @return the number of read messages per second.
*/
double getReadMessagesThroughput();
/**
* @return the number of written messages per second.
*/
double getWrittenMessagesThroughput();
/**
* @return the number of messages which are scheduled to be written to this session.
*/
int getScheduledWriteMessages();
/**
* @return the number of bytes which are scheduled to be written to this
* session.
*/
long getScheduledWriteBytes();
/**
* Returns the message which is being written by {@link IoService}.
* @return <tt>null</tt> if and if only no message is being written
*/
Object getCurrentWriteMessage();
/**
* Returns the {@link WriteRequest} which is being processed by
* {@link IoService}.
*
* @return <tt>null</tt> if and if only no message is being written
*/
WriteRequest getCurrentWriteRequest();
/**
* @return the session's creation time in milliseconds
*/
long getCreationTime();
/**
* @return the time in millis when I/O occurred lastly.
*/
long getLastIoTime();
/**
* @return the time in millis when read operation occurred lastly.
*/
long getLastReadTime();
/**
* @return the time in millis when write operation occurred lastly.
*/
long getLastWriteTime();
/**
* @param status The researched idle status
* @return <tt>true</tt> if this session is idle for the specified
* {@link IdleStatus}.
*/
boolean isIdle(IdleStatus status);
/**
* @return <tt>true</tt> if this session is {@link IdleStatus#READER_IDLE}.
* @see #isIdle(IdleStatus)
*/
boolean isReaderIdle();
/**
* @return <tt>true</tt> if this session is {@link IdleStatus#WRITER_IDLE}.
* @see #isIdle(IdleStatus)
*/
boolean isWriterIdle();
/**
* @return <tt>true</tt> if this session is {@link IdleStatus#BOTH_IDLE}.
* @see #isIdle(IdleStatus)
*/
boolean isBothIdle();
/**
* @param status The researched idle status
* @return the number of the fired continuous <tt>sessionIdle</tt> events
* for the specified {@link IdleStatus}.
* <p>
* If <tt>sessionIdle</tt> event is fired first after some time after I/O,
* <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to
* <tt>0</tt> if any I/O occurs again, otherwise it increases to
* <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
* any I/O between two (or more) <tt>sessionIdle</tt> events.
*/
int getIdleCount(IdleStatus status);
/**
* @return the number of the fired continuous <tt>sessionIdle</tt> events
* for {@link IdleStatus#READER_IDLE}.
* @see #getIdleCount(IdleStatus)
*/
int getReaderIdleCount();
/**
* @return the number of the fired continuous <tt>sessionIdle</tt> events
* for {@link IdleStatus#WRITER_IDLE}.
* @see #getIdleCount(IdleStatus)
*/
int getWriterIdleCount();
/**
* @return the number of the fired continuous <tt>sessionIdle</tt> events
* for {@link IdleStatus#BOTH_IDLE}.
* @see #getIdleCount(IdleStatus)
*/
int getBothIdleCount();
/**
* @param status The researched idle status
* @return the time in milliseconds when the last <tt>sessionIdle</tt> event
* is fired for the specified {@link IdleStatus}.
*/
long getLastIdleTime(IdleStatus status);
/**
* @return the time in milliseconds when the last <tt>sessionIdle</tt> event
* is fired for {@link IdleStatus#READER_IDLE}.
* @see #getLastIdleTime(IdleStatus)
*/
long getLastReaderIdleTime();
/**
* @return the time in milliseconds when the last <tt>sessionIdle</tt> event
* is fired for {@link IdleStatus#WRITER_IDLE}.
* @see #getLastIdleTime(IdleStatus)
*/
long getLastWriterIdleTime();
/**
* @return the time in milliseconds when the last <tt>sessionIdle</tt> event
* is fired for {@link IdleStatus#BOTH_IDLE}.
* @see #getLastIdleTime(IdleStatus)
*/
long getLastBothIdleTime();
}