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