View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.core.session;
21  
22  import java.net.SocketAddress;
23  import java.util.Set;
24  
25  import org.apache.mina.core.filterchain.IoFilter;
26  import org.apache.mina.core.filterchain.IoFilterChain;
27  import org.apache.mina.core.future.CloseFuture;
28  import org.apache.mina.core.future.ReadFuture;
29  import org.apache.mina.core.future.WriteFuture;
30  import org.apache.mina.core.service.IoAcceptor;
31  import org.apache.mina.core.service.IoConnector;
32  import org.apache.mina.core.service.IoHandler;
33  import org.apache.mina.core.service.IoService;
34  import org.apache.mina.core.service.TransportMetadata;
35  import org.apache.mina.core.write.WriteRequest;
36  
37  /**
38   * A handle which represents connection between two end-points regardless of
39   * transport types.
40   * <p/>
41   * {@link IoSession} provides user-defined attributes.  User-defined attributes
42   * are application-specific data which are associated with a session.
43   * It often contains objects that represents the state of a higher-level protocol
44   * and becomes a way to exchange data between filters and handlers.
45   * <p/>
46   * <h3>Adjusting Transport Type Specific Properties</h3>
47   * <p/>
48   * You can simply downcast the session to an appropriate subclass.
49   * </p>
50   * <p/>
51   * <h3>Thread Safety</h3>
52   * <p/>
53   * {@link IoSession} is thread-safe.  But please note that performing
54   * more than one {@link #write(Object)} calls at the same time will
55   * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)}
56   * to be executed simultaneously, and therefore you have to make sure the
57   * {@link IoFilter} implementations you're using are thread-safe, too.
58   * </p>
59   * <p/>
60   * <h3>Equality of Sessions</h3>
61   * TODO : The getId() method is totally wrong. We can't base
62   * a method which is designed to create a unique ID on the hashCode method.
63   * {@link #equals(Object)} and {@link #hashCode()} shall not be overriden
64   * to the default behavior that is defined in {@link Object}.
65   *
66   * @author The Apache MINA Project (dev@mina.apache.org)
67   * @version $Rev: 677564 $, $Date: 2008-07-17 13:52:14 +0200 (jeu, 17 jui 2008) $
68   */
69  public interface IoSession {
70      /**
71       * @return a unique identifier for this session.  Every session has its own
72       * ID which is different from each other.
73       * 
74       * TODO : The way it's implemented does not guarantee that the contract is
75       * respected. It uses the HashCode() method which don't guarantee the key
76       * unicity.
77       */
78      long getId();
79  
80      /**
81       * @return the {@link IoService} which provides I/O service to this session.
82       */
83      IoService getService();
84  
85      /**
86       * @return the {@link IoHandler} which handles this session.
87       */
88      IoHandler getHandler();
89  
90      /**
91       * @return the configuration of this session.
92       */
93      IoSessionConfig getConfig();
94  
95      /**
96       * @return the filter chain that only affects this session.
97       */
98      IoFilterChain getFilterChain();
99  
100     /**
101      * @return the {@link TransportMetadata} that this session runs on.
102      */
103     TransportMetadata getTransportMetadata();
104 
105     /**
106      * TODO This javadoc is wrong. The return tag should be short.
107      * 
108      * @return a {@link ReadFuture} which is notified when a new message is
109      * received, the connection is closed or an exception is caught.  This
110      * operation is especially useful when you implement a client application.
111      * TODO : Describe here how we enable this feature.
112      * However, please note that this operation is disabled by default and
113      * throw {@link IllegalStateException} because all received events must be
114      * queued somewhere to support this operation, possibly leading to memory
115      * leak.  This means you have to keep calling {@link #read()} once you
116      * enabled this operation.  To enable this operation, please call
117      * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>.
118      *
119      * @throws IllegalStateException if
120      * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation}
121      * option has not been enabled.
122      */
123     ReadFuture read();
124 
125     /**
126      * Writes the specified <code>message</code> to remote peer.  This
127      * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)}
128      * will be invoked when the message is actually sent to remote peer.
129      * You can also wait for the returned {@link WriteFuture} if you want
130      * to wait for the message actually written.
131      */
132     WriteFuture write(Object message);
133 
134     /**
135      * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>.
136      * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)}
137      * will be invoked when the message is actually sent to remote peer. You can
138      * also wait for the returned {@link WriteFuture} if you want to wait for
139      * the message actually written.
140      * <p>
141      * When you implement a client that receives a broadcast message from a server
142      * such as DHCP server, the client might need to send a response message for the
143      * broadcast message the server sent.  Because the remote address of the session
144      * is not the address of the server in case of broadcasting, there should be a
145      * way to specify the destination when you write the response message.
146      * This interface provides {@link #write(Object, SocketAddress)} method so you
147      * can specify the destination.
148      *
149      * @param destination <tt>null</tt> if you want the message sent to the
150      *                    default remote address
151      *
152      * @throws UnsupportedOperationException if this operation is not supported
153      */
154     WriteFuture write(Object message, SocketAddress destination);
155 
156     /**
157      * Closes this session immediately.  This operation is asynchronous.
158      * Wait for the returned {@link CloseFuture} if you want to wait for
159      * the session actually closed.
160      */
161     CloseFuture close();
162 
163     /**
164      * Closes this session after all queued write requests are flushed.
165      * This operation is asynchronous.  Wait for the returned {@link CloseFuture}
166      * if you want to wait for the session actually closed.
167      */
168     CloseFuture closeOnFlush();
169 
170     /**
171      * Closes this session immediately or after all queued write requests
172      * are flushed.  This operation is asynchronous.  Wait for the returned
173      * {@link CloseFuture} if you want to wait for the session actually closed.
174      *
175      * @param immediately {@code true} to close this session immediately
176      *                    (i.e. {@link #close()}).
177      *                    {@code false} to close this session after all queued
178      *                    write requests are flushed (i.e. {@link #closeOnFlush()}).
179      */
180     CloseFuture close(boolean immediately);
181 
182     /**
183      * Returns an attachment of this session.
184      * This method is identical with <tt>getAttribute( "" )</tt>.
185      *
186      * @deprecated Use {@link #getAttribute(Object)} instead.
187      */
188     @Deprecated Object getAttachment();
189 
190     /**
191      * Sets an attachment of this session.
192      * This method is identical with <tt>setAttribute( "", attachment )</tt>.
193      *
194      * @return Old attachment.  <tt>null</tt> if it is new.
195      * @deprecated Use {@link #setAttribute(Object, Object)} instead.
196      */
197     @Deprecated Object setAttachment(Object attachment);
198 
199     /**
200      * Returns the value of the user-defined attribute of this session.
201      *
202      * @param key the key of the attribute
203      * @return <tt>null</tt> if there is no attribute with the specified key
204      */
205     Object getAttribute(Object key);
206 
207     /**
208      * Returns the value of user defined attribute associated with the
209      * specified key.  If there's no such attribute, the specified default
210      * value is associated with the specified key, and the default value is
211      * returned.  This method is same with the following code except that the
212      * operation is performed atomically.
213      * <pre>
214      * if (containsAttribute(key)) {
215      *     return getAttribute(key);
216      * } else {
217      *     setAttribute(key, defaultValue);
218      *     return defaultValue;
219      * }
220      * </pre>
221      */
222     Object getAttribute(Object key, Object defaultValue);
223 
224     /**
225      * Sets a user-defined attribute.
226      *
227      * @param key   the key of the attribute
228      * @param value the value of the attribute
229      * @return The old value of the attribute.  <tt>null</tt> if it is new.
230      */
231     Object setAttribute(Object key, Object value);
232 
233     /**
234      * Sets a user defined attribute without a value.  This is useful when
235      * you just want to put a 'mark' attribute.  Its value is set to
236      * {@link Boolean#TRUE}.
237      *
238      * @param key the key of the attribute
239      * @return The old value of the attribute.  <tt>null</tt> if it is new.
240      */
241     Object setAttribute(Object key);
242 
243     /**
244      * Sets a user defined attribute if the attribute with the specified key
245      * is not set yet.  This method is same with the following code except
246      * that the operation is performed atomically.
247      * <pre>
248      * if (containsAttribute(key)) {
249      *     return getAttribute(key);
250      * } else {
251      *     return setAttribute(key, value);
252      * }
253      * </pre>
254      */
255     Object setAttributeIfAbsent(Object key, Object value);
256 
257     /**
258      * Sets a user defined attribute without a value if the attribute with
259      * the specified key is not set yet.  This is useful when you just want to
260      * put a 'mark' attribute.  Its value is set to {@link Boolean#TRUE}.
261      * This method is same with the following code except that the operation
262      * is performed atomically.
263      * <pre>
264      * if (containsAttribute(key)) {
265      *     return getAttribute(key);  // might not always be Boolean.TRUE.
266      * } else {
267      *     return setAttribute(key);
268      * }
269      * </pre>
270      */
271     Object setAttributeIfAbsent(Object key);
272 
273     /**
274      * Removes a user-defined attribute with the specified key.
275      *
276      * @return The old value of the attribute.  <tt>null</tt> if not found.
277      */
278     Object removeAttribute(Object key);
279 
280     /**
281      * Removes a user defined attribute with the specified key if the current
282      * attribute value is equal to the specified value.  This method is same
283      * with the following code except that the operation is performed
284      * atomically.
285      * <pre>
286      * if (containsAttribute(key) && getAttribute(key).equals(value)) {
287      *     removeAttribute(key);
288      *     return true;
289      * } else {
290      *     return false;
291      * }
292      * </pre>
293      */
294     boolean removeAttribute(Object key, Object value);
295 
296     /**
297      * Replaces a user defined attribute with the specified key if the
298      * value of the attribute is equals to the specified old value.
299      * This method is same with the following code except that the operation
300      * is performed atomically.
301      * <pre>
302      * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
303      *     setAttribute(key, newValue);
304      *     return true;
305      * } else {
306      *     return false;
307      * }
308      * </pre>
309      */
310     boolean replaceAttribute(Object key, Object oldValue, Object newValue);
311 
312     /**
313      * Returns <tt>true</tt> if this session contains the attribute with
314      * the specified <tt>key</tt>.
315      */
316     boolean containsAttribute(Object key);
317 
318     /**
319      * Returns the set of keys of all user-defined attributes.
320      */
321     Set<Object> getAttributeKeys();
322 
323     /**
324      * Returns <code>true</code> if this session is connected with remote peer.
325      */
326     boolean isConnected();
327 
328     /**
329      * Returns <code>true</tt> if and only if this session is being closed
330      * (but not disconnected yet) or is closed.
331      */
332     boolean isClosing();
333 
334     /**
335      * Returns the {@link CloseFuture} of this session.  This method returns
336      * the same instance whenever user calls it.
337      */
338     CloseFuture getCloseFuture();
339 
340     /**
341      * Returns the socket address of remote peer.
342      */
343     SocketAddress getRemoteAddress();
344 
345     /**
346      * Returns the socket address of local machine which is associated with this
347      * session.
348      */
349     SocketAddress getLocalAddress();
350 
351     /**
352      * Returns the socket address of the {@link IoService} listens to to manage
353      * this session.  If this session is managed by {@link IoAcceptor}, it
354      * returns the {@link SocketAddress} which is specified as a parameter of
355      * {@link IoAcceptor#bind()}.  If this session is managed by
356      * {@link IoConnector}, this method returns the same address with
357      * that of {@link #getRemoteAddress()}.
358      */
359     SocketAddress getServiceAddress();
360 
361     /**
362      * Returns the current {@link TrafficMask} of this session.
363      */
364     TrafficMask getTrafficMask();
365 
366     /**
367      * Sets the {@link TrafficMask} of this session which will result
368      * the parent {@link IoService} to start to control the traffic
369      * of this session immediately.
370      */
371     void setTrafficMask(TrafficMask trafficMask);
372 
373     /**
374      * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
375      * suspends read operations for this session.
376      */
377     void suspendRead();
378 
379     /**
380      * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
381      * suspends write operations for this session.
382      */
383     void suspendWrite();
384 
385     /**
386      * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
387      * resumes read operations for this session.
388      */
389     void resumeRead();
390 
391     /**
392      * A shortcut method for {@link #setTrafficMask(TrafficMask)} that
393      * resumes write operations for this session.
394      */
395     void resumeWrite();
396 
397     /**
398      * Returns the total number of bytes which were read from this session.
399      */
400     long getReadBytes();
401 
402     /**
403      * Returns the total number of bytes which were written to this session.
404      */
405     long getWrittenBytes();
406 
407     /**
408      * Returns the total number of messages which were read and decoded from this session.
409      */
410     long getReadMessages();
411 
412     /**
413      * Returns the total number of messages which were written and encoded by this session.
414      */
415     long getWrittenMessages();
416 
417     /**
418      * Returns the number of read bytes per second.
419      */
420     double getReadBytesThroughput();
421 
422     /**
423      * Returns the number of written bytes per second.
424      */
425     double getWrittenBytesThroughput();
426 
427     /**
428      * Returns the number of read messages per second.
429      */
430     double getReadMessagesThroughput();
431 
432     /**
433      * Returns the number of written messages per second.
434      */
435     double getWrittenMessagesThroughput();
436 
437     /**
438      * Returns the number of messages which are scheduled to be written to this session.
439      */
440     int getScheduledWriteMessages();
441 
442     /**
443      * Returns the number of bytes which are scheduled to be written to this
444      * session.
445      */
446     long getScheduledWriteBytes();
447 
448     /**
449      * Returns the message which is being written by {@link IoService}.
450      * @return <tt>null</tt> if and if only no message is being written
451      */
452     Object getCurrentWriteMessage();
453 
454     /**
455      * Returns the {@link WriteRequest} which is being processed by
456      * {@link IoService}.
457      *
458      * @return <tt>null</tt> if and if only no message is being written
459      */
460     WriteRequest getCurrentWriteRequest();
461 
462     /**
463      * @return the session's creation time in nanoseconds
464      */
465     long getCreationTime();
466 
467     /**
468      * Returns the time in millis when I/O occurred lastly.
469      */
470     long getLastIoTime();
471 
472     /**
473      * Returns the time in millis when read operation occurred lastly.
474      */
475     long getLastReadTime();
476 
477     /**
478      * Returns the time in millis when write operation occurred lastly.
479      */
480     long getLastWriteTime();
481 
482     /**
483      * Returns <code>true</code> if this session is idle for the specified
484      * {@link IdleStatus}.
485      */
486     boolean isIdle(IdleStatus status);
487 
488     /**
489      * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}.
490      * @see #isIdle(IdleStatus)
491      */
492     boolean isReaderIdle();
493 
494     /**
495      * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}.
496      * @see #isIdle(IdleStatus)
497      */
498     boolean isWriterIdle();
499 
500     /**
501      * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}.
502      * @see #isIdle(IdleStatus)
503      */
504     boolean isBothIdle();
505 
506     /**
507      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
508      * for the specified {@link IdleStatus}.
509      * <p/>
510      * If <tt>sessionIdle</tt> event is fired first after some time after I/O,
511      * <tt>idleCount</tt> becomes <tt>1</tt>.  <tt>idleCount</tt> resets to
512      * <tt>0</tt> if any I/O occurs again, otherwise it increases to
513      * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
514      * any I/O between two (or more) <tt>sessionIdle</tt> events.
515      */
516     int getIdleCount(IdleStatus status);
517 
518     /**
519      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
520      * for {@link IdleStatus#READER_IDLE}.
521      * @see #getIdleCount(IdleStatus)
522      */
523     int getReaderIdleCount();
524 
525     /**
526      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
527      * for {@link IdleStatus#WRITER_IDLE}.
528      * @see #getIdleCount(IdleStatus)
529      */
530     int getWriterIdleCount();
531 
532     /**
533      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
534      * for {@link IdleStatus#BOTH_IDLE}.
535      * @see #getIdleCount(IdleStatus)
536      */
537     int getBothIdleCount();
538 
539     /**
540      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
541      * is fired for the specified {@link IdleStatus}.
542      */
543     long getLastIdleTime(IdleStatus status);
544 
545 
546     /**
547      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
548      * is fired for {@link IdleStatus#READER_IDLE}.
549      * @see #getLastIdleTime(IdleStatus)
550      */
551     long getLastReaderIdleTime();
552 
553     /**
554      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
555      * is fired for {@link IdleStatus#WRITER_IDLE}.
556      * @see #getLastIdleTime(IdleStatus)
557      */
558     long getLastWriterIdleTime();
559 
560     /**
561      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
562      * is fired for {@link IdleStatus#BOTH_IDLE}.
563      * @see #getLastIdleTime(IdleStatus)
564      */
565     long getLastBothIdleTime();
566 }