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