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 }