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 closeNow() or the flushAndClose() methods
182 */
183 CloseFuture close(boolean immediately);
184
185 /**
186 * Closes this session immediately. This operation is asynchronous, it
187 * returns a {@link CloseFuture}.
188 */
189 CloseFuture closeNow();
190
191 /**
192 * Closes this session after all queued write requests are flushed. This operation
193 * is asynchronous. Wait for the returned {@link CloseFuture} if you want to wait
194 * for the session actually closed.
195 *
196 * @return The associated CloseFuture
197 */
198 CloseFuture closeOnFlush();
199
200 /**
201 * Closes this session after all queued write requests
202 * are flushed. This operation is asynchronous. Wait for the returned
203 * {@link CloseFuture} if you want to wait for the session actually closed.
204 * @deprecated use {@link #close(boolean)}
205 *
206 * @return The associated CloseFuture
207 */
208 @Deprecated
209 CloseFuture close();
210
211 /**
212 * Returns an attachment of this session.
213 * This method is identical with <tt>getAttribute( "" )</tt>.
214 *
215 * @return The attachment
216 * @deprecated Use {@link #getAttribute(Object)} instead.
217 */
218 @Deprecated
219 Object getAttachment();
220
221 /**
222 * Sets an attachment of this session.
223 * This method is identical with <tt>setAttribute( "", attachment )</tt>.
224 *
225 * @param attachment The attachment
226 * @return Old attachment. <tt>null</tt> if it is new.
227 * @deprecated Use {@link #setAttribute(Object, Object)} instead.
228 */
229 @Deprecated
230 Object setAttachment(Object attachment);
231
232 /**
233 * Returns the value of the user-defined attribute of this session.
234 *
235 * @param key the key of the attribute
236 * @return <tt>null</tt> if there is no attribute with the specified key
237 */
238 Object getAttribute(Object key);
239
240 /**
241 * Returns the value of user defined attribute associated with the
242 * specified key. If there's no such attribute, the specified default
243 * value is associated with the specified key, and the default value is
244 * returned. This method is same with the following code except that the
245 * operation is performed atomically.
246 * <pre>
247 * if (containsAttribute(key)) {
248 * return getAttribute(key);
249 * } else {
250 * setAttribute(key, defaultValue);
251 * return defaultValue;
252 * }
253 * </pre>
254 *
255 * @param key the key of the attribute we want to retreive
256 * @param defaultValue the default value of the attribute
257 * @return The retrieved attribute or <tt>null</tt> if not found
258 */
259 Object getAttribute(Object key, Object defaultValue);
260
261 /**
262 * Sets a user-defined attribute.
263 *
264 * @param key the key of the attribute
265 * @param value the value of the attribute
266 * @return The old value of the attribute. <tt>null</tt> if it is new.
267 */
268 Object setAttribute(Object key, Object value);
269
270 /**
271 * Sets a user defined attribute without a value. This is useful when
272 * you just want to put a 'mark' attribute. Its value is set to
273 * {@link Boolean#TRUE}.
274 *
275 * @param key the key of the attribute
276 * @return The old value of the attribute. <tt>null</tt> if it is new.
277 */
278 Object setAttribute(Object key);
279
280 /**
281 * Sets a user defined attribute if the attribute with the specified key
282 * is not set yet. This method is same with the following code except
283 * that the operation is performed atomically.
284 * <pre>
285 * if (containsAttribute(key)) {
286 * return getAttribute(key);
287 * } else {
288 * return setAttribute(key, value);
289 * }
290 * </pre>
291 *
292 * @param key The key of the attribute we want to set
293 * @param value The value we want to set
294 * @return The old value of the attribute. <tt>null</tt> if not found.
295 */
296 Object setAttributeIfAbsent(Object key, Object value);
297
298 /**
299 * Sets a user defined attribute without a value if the attribute with
300 * the specified key is not set yet. This is useful when you just want to
301 * put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}.
302 * This method is same with the following code except that the operation
303 * is performed atomically.
304 * <pre>
305 * if (containsAttribute(key)) {
306 * return getAttribute(key); // might not always be Boolean.TRUE.
307 * } else {
308 * return setAttribute(key);
309 * }
310 * </pre>
311 *
312 * @param key The key of the attribute we want to set
313 * @return The old value of the attribute. <tt>null</tt> if not found.
314 */
315 Object setAttributeIfAbsent(Object key);
316
317 /**
318 * Removes a user-defined attribute with the specified key.
319 *
320 * @param key The key of the attribute we want to remove
321 * @return The old value of the attribute. <tt>null</tt> if not found.
322 */
323 Object removeAttribute(Object key);
324
325 /**
326 * Removes a user defined attribute with the specified key if the current
327 * attribute value is equal to the specified value. This method is same
328 * with the following code except that the operation is performed
329 * atomically.
330 * <pre>
331 * if (containsAttribute(key) && getAttribute(key).equals(value)) {
332 * removeAttribute(key);
333 * return true;
334 * } else {
335 * return false;
336 * }
337 * </pre>
338 *
339 * @param key The key we want to remove
340 * @param value The value we want to remove
341 * @return <tt>true</tt> if the removal was successful
342 */
343 boolean removeAttribute(Object key, Object value);
344
345 /**
346 * Replaces a user defined attribute with the specified key if the
347 * value of the attribute is equals to the specified old value.
348 * This method is same with the following code except that the operation
349 * is performed atomically.
350 * <pre>
351 * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) {
352 * setAttribute(key, newValue);
353 * return true;
354 * } else {
355 * return false;
356 * }
357 * </pre>
358 *
359 * @param key The key we want to replace
360 * @param oldValue The previous value
361 * @param newValue The new value
362 * @return <tt>true</tt> if the replacement was successful
363 */
364 boolean replaceAttribute(Object key, Object oldValue, Object newValue);
365
366 /**
367 * @param key The key of the attribute we are looking for in the session
368 * @return <tt>true</tt> if this session contains the attribute with
369 * the specified <tt>key</tt>.
370 */
371 boolean containsAttribute(Object key);
372
373 /**
374 * @return the set of keys of all user-defined attributes.
375 */
376 Set<Object> getAttributeKeys();
377
378 /**
379 * @return <tt>true</tt> if this session is connected with remote peer.
380 */
381 boolean isConnected();
382
383 /**
384 * @return <tt>true</tt> if this session is active.
385 */
386 boolean isActive();
387
388 /**
389 * @return <tt>true</tt> if and only if this session is being closed
390 * (but not disconnected yet) or is closed.
391 */
392 boolean isClosing();
393
394 /**
395 * @return <tt>true</tt> if the session has started and initialized a SslEngine,
396 * <tt>false</tt> if the session is not yet secured (the handshake is not completed)
397 * or if SSL is not set for this session, or if SSL is not even an option.
398 */
399 boolean isSecured();
400
401 /**
402 * @return the {@link CloseFuture} of this session. This method returns
403 * the same instance whenever user calls it.
404 */
405 CloseFuture getCloseFuture();
406
407 /**
408 * @return the socket address of remote peer.
409 */
410 SocketAddress getRemoteAddress();
411
412 /**
413 * @return the socket address of local machine which is associated with this
414 * session.
415 */
416 SocketAddress getLocalAddress();
417
418 /**
419 * @return the socket address of the {@link IoService} listens to to manage
420 * this session. If this session is managed by {@link IoAcceptor}, it
421 * returns the {@link SocketAddress} which is specified as a parameter of
422 * {@link IoAcceptor#bind()}. If this session is managed by
423 * {@link IoConnector}, this method returns the same address with
424 * that of {@link #getRemoteAddress()}.
425 */
426 SocketAddress getServiceAddress();
427
428 /**
429 *
430 * Associate the current write request with the session
431 *
432 * @param currentWriteRequest the current write request to associate
433 */
434 void setCurrentWriteRequest(WriteRequest currentWriteRequest);
435
436 /**
437 * Suspends read operations for this session.
438 */
439 void suspendRead();
440
441 /**
442 * Suspends write operations for this session.
443 */
444 void suspendWrite();
445
446 /**
447 * Resumes read operations for this session.
448 */
449 void resumeRead();
450
451 /**
452 * Resumes write operations for this session.
453 */
454 void resumeWrite();
455
456 /**
457 * Is read operation is suspended for this session.
458 *
459 * @return <tt>true</tt> if suspended
460 */
461 boolean isReadSuspended();
462
463 /**
464 * Is write operation is suspended for this session.
465 *
466 * @return <tt>true</tt> if suspended
467 */
468 boolean isWriteSuspended();
469
470 /**
471 * Update all statistical properties related with throughput assuming
472 * the specified time is the current time. By default this method returns
473 * silently without updating the throughput properties if they were
474 * calculated already within last
475 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}.
476 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method
477 * updates the throughput properties immediately.
478
479 * @param currentTime the current time in milliseconds
480 * @param force Force the update if <tt>true</tt>
481 */
482 void updateThroughput(long currentTime, boolean force);
483
484 /**
485 * @return the total number of bytes which were read from this session.
486 */
487 long getReadBytes();
488
489 /**
490 * @return the total number of bytes which were written to this session.
491 */
492 long getWrittenBytes();
493
494 /**
495 * @return the total number of messages which were read and decoded from this session.
496 */
497 long getReadMessages();
498
499 /**
500 * @return the total number of messages which were written and encoded by this session.
501 */
502 long getWrittenMessages();
503
504 /**
505 * @return the number of read bytes per second.
506 */
507 double getReadBytesThroughput();
508
509 /**
510 * @return the number of written bytes per second.
511 */
512 double getWrittenBytesThroughput();
513
514 /**
515 * @return the number of read messages per second.
516 */
517 double getReadMessagesThroughput();
518
519 /**
520 * @return the number of written messages per second.
521 */
522 double getWrittenMessagesThroughput();
523
524 /**
525 * @return the number of messages which are scheduled to be written to this session.
526 */
527 int getScheduledWriteMessages();
528
529 /**
530 * @return the number of bytes which are scheduled to be written to this
531 * session.
532 */
533 long getScheduledWriteBytes();
534
535 /**
536 * Returns the message which is being written by {@link IoService}.
537 * @return <tt>null</tt> if and if only no message is being written
538 */
539 Object getCurrentWriteMessage();
540
541 /**
542 * Returns the {@link WriteRequest} which is being processed by
543 * {@link IoService}.
544 *
545 * @return <tt>null</tt> if and if only no message is being written
546 */
547 WriteRequest getCurrentWriteRequest();
548
549 /**
550 * @return the session's creation time in milliseconds
551 */
552 long getCreationTime();
553
554 /**
555 * @return the time in millis when I/O occurred lastly.
556 */
557 long getLastIoTime();
558
559 /**
560 * @return the time in millis when read operation occurred lastly.
561 */
562 long getLastReadTime();
563
564 /**
565 * @return the time in millis when write operation occurred lastly.
566 */
567 long getLastWriteTime();
568
569 /**
570 * @param status The researched idle status
571 * @return <tt>true</tt> if this session is idle for the specified
572 * {@link IdleStatus}.
573 */
574 boolean isIdle(IdleStatus status);
575
576 /**
577 * @return <tt>true</tt> if this session is {@link IdleStatus#READER_IDLE}.
578 * @see #isIdle(IdleStatus)
579 */
580 boolean isReaderIdle();
581
582 /**
583 * @return <tt>true</tt> if this session is {@link IdleStatus#WRITER_IDLE}.
584 * @see #isIdle(IdleStatus)
585 */
586 boolean isWriterIdle();
587
588 /**
589 * @return <tt>true</tt> if this session is {@link IdleStatus#BOTH_IDLE}.
590 * @see #isIdle(IdleStatus)
591 */
592 boolean isBothIdle();
593
594 /**
595 * @param status The researched idle status
596 * @return the number of the fired continuous <tt>sessionIdle</tt> events
597 * for the specified {@link IdleStatus}.
598 * <p>
599 * If <tt>sessionIdle</tt> event is fired first after some time after I/O,
600 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to
601 * <tt>0</tt> if any I/O occurs again, otherwise it increases to
602 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without
603 * any I/O between two (or more) <tt>sessionIdle</tt> events.
604 */
605 int getIdleCount(IdleStatus status);
606
607 /**
608 * @return the number of the fired continuous <tt>sessionIdle</tt> events
609 * for {@link IdleStatus#READER_IDLE}.
610 * @see #getIdleCount(IdleStatus)
611 */
612 int getReaderIdleCount();
613
614 /**
615 * @return the number of the fired continuous <tt>sessionIdle</tt> events
616 * for {@link IdleStatus#WRITER_IDLE}.
617 * @see #getIdleCount(IdleStatus)
618 */
619 int getWriterIdleCount();
620
621 /**
622 * @return the number of the fired continuous <tt>sessionIdle</tt> events
623 * for {@link IdleStatus#BOTH_IDLE}.
624 * @see #getIdleCount(IdleStatus)
625 */
626 int getBothIdleCount();
627
628 /**
629 * @param status The researched idle status
630 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event
631 * is fired for the specified {@link IdleStatus}.
632 */
633 long getLastIdleTime(IdleStatus status);
634
635 /**
636 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event
637 * is fired for {@link IdleStatus#READER_IDLE}.
638 * @see #getLastIdleTime(IdleStatus)
639 */
640 long getLastReaderIdleTime();
641
642 /**
643 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event
644 * is fired for {@link IdleStatus#WRITER_IDLE}.
645 * @see #getLastIdleTime(IdleStatus)
646 */
647 long getLastWriterIdleTime();
648
649 /**
650 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event
651 * is fired for {@link IdleStatus#BOTH_IDLE}.
652 * @see #getLastIdleTime(IdleStatus)
653 */
654 long getLastBothIdleTime();
655 }