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  import org.apache.mina.core.write.WriteRequestQueue;
37  
38  /**
39   * A handle which represents connection between two end-points regardless of
40   * transport types.
41   * <p/>
42   * {@link IoSession} provides user-defined attributes.  User-defined attributes
43   * are application-specific data which are associated with a session.
44   * It often contains objects that represents the state of a higher-level protocol
45   * and becomes a way to exchange data between filters and handlers.
46   * <p/>
47   * <h3>Adjusting Transport Type Specific Properties</h3>
48   * <p/>
49   * You can simply downcast the session to an appropriate subclass.
50   * </p>
51   * <p/>
52   * <h3>Thread Safety</h3>
53   * <p/>
54   * {@link IoSession} is thread-safe.  But please note that performing
55   * more than one {@link #write(Object)} calls at the same time will
56   * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)}
57   * to be executed simultaneously, and therefore you have to make sure the
58   * {@link IoFilter} implementations you're using are thread-safe, too.
59   * </p>
60   * <p/>
61   * <h3>Equality of Sessions</h3>
62   * TODO : The getId() method is totally wrong. We can't base
63   * a method which is designed to create a unique ID on the hashCode method.
64   * {@link #equals(Object)} and {@link #hashCode()} shall not be overriden
65   * to the default behavior that is defined in {@link Object}.
66   *
67   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
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     /**
102      * TODO Add method documentation
103      */
104     WriteRequestQueue getWriteRequestQueue();
105 
106     /**
107      * @return the {@link TransportMetadata} that this session runs on.
108      */
109     TransportMetadata getTransportMetadata();
110 
111     /**
112      * TODO This javadoc is wrong. The return tag should be short.
113      * 
114      * @return a {@link ReadFuture} which is notified when a new message is
115      * received, the connection is closed or an exception is caught.  This
116      * operation is especially useful when you implement a client application.
117      * TODO : Describe here how we enable this feature.
118      * However, please note that this operation is disabled by default and
119      * throw {@link IllegalStateException} because all received events must be
120      * queued somewhere to support this operation, possibly leading to memory
121      * leak.  This means you have to keep calling {@link #read()} once you
122      * enabled this operation.  To enable this operation, please call
123      * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>.
124      *
125      * @throws IllegalStateException if
126      * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation}
127      * option has not been enabled.
128      */
129     ReadFuture read();
130 
131     /**
132      * Writes the specified <code>message</code> to remote peer.  This
133      * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)}
134      * will be invoked when the message is actually sent to remote peer.
135      * You can also wait for the returned {@link WriteFuture} if you want
136      * to wait for the message actually written.
137      */
138     WriteFuture write(Object message);
139 
140     /**
141      * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>.
142      * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)}
143      * will be invoked when the message is actually sent to remote peer. You can
144      * also wait for the returned {@link WriteFuture} if you want to wait for
145      * the message actually written.
146      * <p>
147      * When you implement a client that receives a broadcast message from a server
148      * such as DHCP server, the client might need to send a response message for the
149      * broadcast message the server sent.  Because the remote address of the session
150      * is not the address of the server in case of broadcasting, there should be a
151      * way to specify the destination when you write the response message.
152      * This interface provides {@link #write(Object, SocketAddress)} method so you
153      * can specify the destination.
154      *
155      * @param destination <tt>null</tt> if you want the message sent to the
156      *                    default remote address
157      *
158      * @throws UnsupportedOperationException if this operation is not supported
159      */
160     WriteFuture write(Object message, SocketAddress destination);
161 
162     /**
163      * Closes this session immediately or after all queued write requests
164      * are flushed.  This operation is asynchronous.  Wait for the returned
165      * {@link CloseFuture} if you want to wait for the session actually closed.
166      *
167      * @param immediately {@code true} to close this session immediately
168      *                    (i.e. {@link #close()}). The pending write requests
169      *                    will simply be discarded.
170      *                    {@code false} to close this session after all queued
171      *                    write requests are flushed (i.e. {@link #closeOnFlush()}).
172      */
173     CloseFuture close(boolean immediately);
174     
175     /**
176      * Closes this session after all queued write requests
177      * are flushed. This operation is asynchronous.  Wait for the returned
178      * {@link CloseFuture} if you want to wait for the session actually closed.
179      * @deprecated use {@link IoSession#close(boolean)}
180      */
181     @Deprecated CloseFuture close();
182 
183     /**
184      * Returns an attachment of this session.
185      * This method is identical with <tt>getAttribute( "" )</tt>.
186      *
187      * @deprecated Use {@link #getAttribute(Object)} instead.
188      */
189     @Deprecated Object getAttachment();
190 
191     /**
192      * Sets an attachment of this session.
193      * This method is identical with <tt>setAttribute( "", attachment )</tt>.
194      *
195      * @return Old attachment.  <tt>null</tt> if it is new.
196      * @deprecated Use {@link #setAttribute(Object, Object)} instead.
197      */
198     @Deprecated Object setAttachment(Object attachment);
199 
200     /**
201      * Returns the value of the user-defined attribute of this session.
202      *
203      * @param key the key of the attribute
204      * @return <tt>null</tt> if there is no attribute with the specified key
205      */
206     Object getAttribute(Object key);
207 
208     /**
209      * Returns the value of user defined attribute associated with the
210      * specified key.  If there's no such attribute, the specified default
211      * value is associated with the specified key, and the default value is
212      * returned.  This method is same with the following code except that the
213      * operation is performed atomically.
214      * <pre>
215      * if (containsAttribute(key)) {
216      *     return getAttribute(key);
217      * } else {
218      *     setAttribute(key, defaultValue);
219      *     return defaultValue;
220      * }
221      * </pre>
222      */
223     Object getAttribute(Object key, Object defaultValue);
224 
225     /**
226      * Sets a user-defined attribute.
227      *
228      * @param key   the key of the attribute
229      * @param value the value of the attribute
230      * @return The old value of the attribute.  <tt>null</tt> if it is new.
231      */
232     Object setAttribute(Object key, Object value);
233 
234     /**
235      * Sets a user defined attribute without a value.  This is useful when
236      * you just want to put a 'mark' attribute.  Its value is set to
237      * {@link Boolean#TRUE}.
238      *
239      * @param key the key of the attribute
240      * @return The old value of the attribute.  <tt>null</tt> if it is new.
241      */
242     Object setAttribute(Object key);
243 
244     /**
245      * Sets a user defined attribute if the attribute with the specified key
246      * is not set yet.  This method is same with the following code except
247      * that the operation is performed atomically.
248      * <pre>
249      * if (containsAttribute(key)) {
250      *     return getAttribute(key);
251      * } else {
252      *     return setAttribute(key, value);
253      * }
254      * </pre>
255      */
256     Object setAttributeIfAbsent(Object key, Object value);
257 
258     /**
259      * Sets a user defined attribute without a value if the attribute with
260      * the specified key is not set yet.  This is useful when you just want to
261      * put a 'mark' attribute.  Its value is set to {@link Boolean#TRUE}.
262      * This method is same with the following code except that the operation
263      * is performed atomically.
264      * <pre>
265      * if (containsAttribute(key)) {
266      *     return getAttribute(key);  // might not always be Boolean.TRUE.
267      * } else {
268      *     return setAttribute(key);
269      * }
270      * </pre>
271      */
272     Object setAttributeIfAbsent(Object key);
273 
274     /**
275      * Removes a user-defined attribute with the specified key.
276      *
277      * @return The old value of the attribute.  <tt>null</tt> if not found.
278      */
279     Object removeAttribute(Object key);
280 
281     /**
282      * Removes a user defined attribute with the specified key if the current
283      * attribute value is equal to the specified value.  This method is same
284      * with the following code except that the operation is performed
285      * atomically.
286      * <pre>
287      * if (containsAttribute(key) && getAttribute(key).equals(value)) {
288      *     removeAttribute(key);
289      *     return true;
290      * } else {
291      *     return false;
292      * }
293      * </pre>
294      */
295     boolean removeAttribute(Object key, Object value);
296 
297     /**
298      * Replaces a user defined attribute with the specified key if the
299      * value of the attribute is equals to the specified old value.
300      * This method is same with the following code except that the operation
301      * is performed atomically.
302      * <pre>
303      * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
304      *     setAttribute(key, newValue);
305      *     return true;
306      * } else {
307      *     return false;
308      * }
309      * </pre>
310      */
311     boolean replaceAttribute(Object key, Object oldValue, Object newValue);
312 
313     /**
314      * Returns <tt>true</tt> if this session contains the attribute with
315      * the specified <tt>key</tt>.
316      */
317     boolean containsAttribute(Object key);
318 
319     /**
320      * Returns the set of keys of all user-defined attributes.
321      */
322     Set<Object> getAttributeKeys();
323 
324     /**
325      * Returns <code>true</code> if this session is connected with remote peer.
326      */
327     boolean isConnected();
328 
329     /**
330      * Returns <code>true</tt> if and only if this session is being closed
331      * (but not disconnected yet) or is closed.
332      */
333     boolean isClosing();
334 
335     /**
336      * Returns the {@link CloseFuture} of this session.  This method returns
337      * the same instance whenever user calls it.
338      */
339     CloseFuture getCloseFuture();
340 
341     /**
342      * Returns the socket address of remote peer.
343      */
344     SocketAddress getRemoteAddress();
345 
346     /**
347      * Returns the socket address of local machine which is associated with this
348      * session.
349      */
350     SocketAddress getLocalAddress();
351 
352     /**
353      * Returns the socket address of the {@link IoService} listens to to manage
354      * this session.  If this session is managed by {@link IoAcceptor}, it
355      * returns the {@link SocketAddress} which is specified as a parameter of
356      * {@link IoAcceptor#bind()}.  If this session is managed by
357      * {@link IoConnector}, this method returns the same address with
358      * that of {@link #getRemoteAddress()}.
359      */
360     SocketAddress getServiceAddress();
361 
362     /**
363      * 
364      * TODO setWriteRequestQueue.
365      *
366      * @param writeRequestQueue
367      */
368     void setCurrentWriteRequest(WriteRequest currentWriteRequest);
369     
370     /**
371      * Suspends read operations for this session.
372      */
373     void suspendRead();
374 
375     /**
376      * Suspends write operations for this session.
377      */
378     void suspendWrite();
379 
380     /**
381      * Resumes read operations for this session.
382      */
383     void resumeRead();
384 
385     /**
386      * Resumes write operations for this session.
387      */
388     void resumeWrite();
389     
390     /**
391      * Is read operation is suspended for this session. 
392      * @return <code>true</code> if suspended
393      */
394     boolean isReadSuspended();
395     
396     /**
397      * Is write operation is suspended for this session.
398      * @return <code>true</code> if suspended
399      */
400     boolean isWriteSuspended();
401     
402     /**
403      * Update all statistical properties related with throughput assuming
404      * the specified time is the current time.  By default this method returns
405      * silently without updating the throughput properties if they were
406      * calculated already within last
407      * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
408      * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
409      * updates the throughput properties immediately.
410 
411      * @param currentTime the current time in milliseconds
412      */
413     void updateThroughput(long currentTime, boolean force);
414     
415     /**
416      * Returns the total number of bytes which were read from this session.
417      */
418     long getReadBytes();
419 
420     /**
421      * Returns the total number of bytes which were written to this session.
422      */
423     long getWrittenBytes();
424 
425     /**
426      * Returns the total number of messages which were read and decoded from this session.
427      */
428     long getReadMessages();
429 
430     /**
431      * Returns the total number of messages which were written and encoded by this session.
432      */
433     long getWrittenMessages();
434 
435     /**
436      * Returns the number of read bytes per second.
437      */
438     double getReadBytesThroughput();
439 
440     /**
441      * Returns the number of written bytes per second.
442      */
443     double getWrittenBytesThroughput();
444 
445     /**
446      * Returns the number of read messages per second.
447      */
448     double getReadMessagesThroughput();
449 
450     /**
451      * Returns the number of written messages per second.
452      */
453     double getWrittenMessagesThroughput();
454 
455     /**
456      * Returns the number of messages which are scheduled to be written to this session.
457      */
458     int getScheduledWriteMessages();
459 
460     /**
461      * Returns the number of bytes which are scheduled to be written to this
462      * session.
463      */
464     long getScheduledWriteBytes();
465 
466     /**
467      * Returns the message which is being written by {@link IoService}.
468      * @return <tt>null</tt> if and if only no message is being written
469      */
470     Object getCurrentWriteMessage();
471 
472     /**
473      * Returns the {@link WriteRequest} which is being processed by
474      * {@link IoService}.
475      *
476      * @return <tt>null</tt> if and if only no message is being written
477      */
478     WriteRequest getCurrentWriteRequest();
479 
480     /**
481      * @return the session's creation time in milliseconds
482      */
483     long getCreationTime();
484 
485     /**
486      * Returns the time in millis when I/O occurred lastly.
487      */
488     long getLastIoTime();
489 
490     /**
491      * Returns the time in millis when read operation occurred lastly.
492      */
493     long getLastReadTime();
494 
495     /**
496      * Returns the time in millis when write operation occurred lastly.
497      */
498     long getLastWriteTime();
499 
500     /**
501      * Returns <code>true</code> if this session is idle for the specified
502      * {@link IdleStatus}.
503      */
504     boolean isIdle(IdleStatus status);
505 
506     /**
507      * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}.
508      * @see #isIdle(IdleStatus)
509      */
510     boolean isReaderIdle();
511 
512     /**
513      * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}.
514      * @see #isIdle(IdleStatus)
515      */
516     boolean isWriterIdle();
517 
518     /**
519      * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}.
520      * @see #isIdle(IdleStatus)
521      */
522     boolean isBothIdle();
523 
524     /**
525      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
526      * for the specified {@link IdleStatus}.
527      * <p/>
528      * If <tt>sessionIdle</tt> event is fired first after some time after I/O,
529      * <tt>idleCount</tt> becomes <tt>1</tt>.  <tt>idleCount</tt> resets to
530      * <tt>0</tt> if any I/O occurs again, otherwise it increases to
531      * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
532      * any I/O between two (or more) <tt>sessionIdle</tt> events.
533      */
534     int getIdleCount(IdleStatus status);
535 
536     /**
537      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
538      * for {@link IdleStatus#READER_IDLE}.
539      * @see #getIdleCount(IdleStatus)
540      */
541     int getReaderIdleCount();
542 
543     /**
544      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
545      * for {@link IdleStatus#WRITER_IDLE}.
546      * @see #getIdleCount(IdleStatus)
547      */
548     int getWriterIdleCount();
549 
550     /**
551      * Returns the number of the fired continuous <tt>sessionIdle</tt> events
552      * for {@link IdleStatus#BOTH_IDLE}.
553      * @see #getIdleCount(IdleStatus)
554      */
555     int getBothIdleCount();
556 
557     /**
558      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
559      * is fired for the specified {@link IdleStatus}.
560      */
561     long getLastIdleTime(IdleStatus status);
562 
563 
564     /**
565      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
566      * is fired for {@link IdleStatus#READER_IDLE}.
567      * @see #getLastIdleTime(IdleStatus)
568      */
569     long getLastReaderIdleTime();
570 
571     /**
572      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
573      * is fired for {@link IdleStatus#WRITER_IDLE}.
574      * @see #getLastIdleTime(IdleStatus)
575      */
576     long getLastWriterIdleTime();
577 
578     /**
579      * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
580      * is fired for {@link IdleStatus#BOTH_IDLE}.
581      * @see #getLastIdleTime(IdleStatus)
582      */
583     long getLastBothIdleTime();
584 }