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()}).
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 CloseFuture close();
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 *
363 * TODO setWriteRequestQueue.
364 *
365 * @param writeRequestQueue
366 */
367 void setCurrentWriteRequest(WriteRequest currentWriteRequest);
368
369 /**
370 * Suspends read operations for this session.
371 */
372 void suspendRead();
373
374 /**
375 * Suspends write operations for this session.
376 */
377 void suspendWrite();
378
379 /**
380 * Resumes read operations for this session.
381 */
382 void resumeRead();
383
384 /**
385 * Resumes write operations for this session.
386 */
387 void resumeWrite();
388
389 /**
390 * Is read operation is suspended for this session.
391 * @return <code>true</code> if suspended
392 */
393 boolean isReadSuspended();
394
395 /**
396 * Is write operation is suspended for this session.
397 * @return <code>true</code> if suspended
398 */
399 boolean isWriteSuspended();
400
401 /**
402 * Update all statistical properties related with throughput assuming
403 * the specified time is the current time. By default this method returns
404 * silently without updating the throughput properties if they were
405 * calculated already within last
406 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
407 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
408 * updates the throughput properties immediately.
409
410 * @param currentTime the current time in milliseconds
411 */
412 void updateThroughput(long currentTime, boolean force);
413
414 /**
415 * Returns the total number of bytes which were read from this session.
416 */
417 long getReadBytes();
418
419 /**
420 * Returns the total number of bytes which were written to this session.
421 */
422 long getWrittenBytes();
423
424 /**
425 * Returns the total number of messages which were read and decoded from this session.
426 */
427 long getReadMessages();
428
429 /**
430 * Returns the total number of messages which were written and encoded by this session.
431 */
432 long getWrittenMessages();
433
434 /**
435 * Returns the number of read bytes per second.
436 */
437 double getReadBytesThroughput();
438
439 /**
440 * Returns the number of written bytes per second.
441 */
442 double getWrittenBytesThroughput();
443
444 /**
445 * Returns the number of read messages per second.
446 */
447 double getReadMessagesThroughput();
448
449 /**
450 * Returns the number of written messages per second.
451 */
452 double getWrittenMessagesThroughput();
453
454 /**
455 * Returns the number of messages which are scheduled to be written to this session.
456 */
457 int getScheduledWriteMessages();
458
459 /**
460 * Returns the number of bytes which are scheduled to be written to this
461 * session.
462 */
463 long getScheduledWriteBytes();
464
465 /**
466 * Returns the message which is being written by {@link IoService}.
467 * @return <tt>null</tt> if and if only no message is being written
468 */
469 Object getCurrentWriteMessage();
470
471 /**
472 * Returns the {@link WriteRequest} which is being processed by
473 * {@link IoService}.
474 *
475 * @return <tt>null</tt> if and if only no message is being written
476 */
477 WriteRequest getCurrentWriteRequest();
478
479 /**
480 * @return the session's creation time in milliseconds
481 */
482 long getCreationTime();
483
484 /**
485 * Returns the time in millis when I/O occurred lastly.
486 */
487 long getLastIoTime();
488
489 /**
490 * Returns the time in millis when read operation occurred lastly.
491 */
492 long getLastReadTime();
493
494 /**
495 * Returns the time in millis when write operation occurred lastly.
496 */
497 long getLastWriteTime();
498
499 /**
500 * Returns <code>true</code> if this session is idle for the specified
501 * {@link IdleStatus}.
502 */
503 boolean isIdle(IdleStatus status);
504
505 /**
506 * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}.
507 * @see #isIdle(IdleStatus)
508 */
509 boolean isReaderIdle();
510
511 /**
512 * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}.
513 * @see #isIdle(IdleStatus)
514 */
515 boolean isWriterIdle();
516
517 /**
518 * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}.
519 * @see #isIdle(IdleStatus)
520 */
521 boolean isBothIdle();
522
523 /**
524 * Returns the number of the fired continuous <tt>sessionIdle</tt> events
525 * for the specified {@link IdleStatus}.
526 * <p/>
527 * If <tt>sessionIdle</tt> event is fired first after some time after I/O,
528 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to
529 * <tt>0</tt> if any I/O occurs again, otherwise it increases to
530 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
531 * any I/O between two (or more) <tt>sessionIdle</tt> events.
532 */
533 int getIdleCount(IdleStatus status);
534
535 /**
536 * Returns the number of the fired continuous <tt>sessionIdle</tt> events
537 * for {@link IdleStatus#READER_IDLE}.
538 * @see #getIdleCount(IdleStatus)
539 */
540 int getReaderIdleCount();
541
542 /**
543 * Returns the number of the fired continuous <tt>sessionIdle</tt> events
544 * for {@link IdleStatus#WRITER_IDLE}.
545 * @see #getIdleCount(IdleStatus)
546 */
547 int getWriterIdleCount();
548
549 /**
550 * Returns the number of the fired continuous <tt>sessionIdle</tt> events
551 * for {@link IdleStatus#BOTH_IDLE}.
552 * @see #getIdleCount(IdleStatus)
553 */
554 int getBothIdleCount();
555
556 /**
557 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
558 * is fired for the specified {@link IdleStatus}.
559 */
560 long getLastIdleTime(IdleStatus status);
561
562
563 /**
564 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
565 * is fired for {@link IdleStatus#READER_IDLE}.
566 * @see #getLastIdleTime(IdleStatus)
567 */
568 long getLastReaderIdleTime();
569
570 /**
571 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
572 * is fired for {@link IdleStatus#WRITER_IDLE}.
573 * @see #getLastIdleTime(IdleStatus)
574 */
575 long getLastWriterIdleTime();
576
577 /**
578 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event
579 * is fired for {@link IdleStatus#BOTH_IDLE}.
580 * @see #getLastIdleTime(IdleStatus)
581 */
582 long getLastBothIdleTime();
583 }