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 37 /** 38 * A handle which represents connection between two end-points regardless of 39 * transport types. 40 * <p/> 41 * {@link IoSession} provides user-defined attributes. User-defined attributes 42 * are application-specific data which are associated with a session. 43 * It often contains objects that represents the state of a higher-level protocol 44 * and becomes a way to exchange data between filters and handlers. 45 * <p/> 46 * <h3>Adjusting Transport Type Specific Properties</h3> 47 * <p/> 48 * You can simply downcast the session to an appropriate subclass. 49 * </p> 50 * <p/> 51 * <h3>Thread Safety</h3> 52 * <p/> 53 * {@link IoSession} is thread-safe. But please note that performing 54 * more than one {@link #write(Object)} calls at the same time will 55 * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)} 56 * to be executed simultaneously, and therefore you have to make sure the 57 * {@link IoFilter} implementations you're using are thread-safe, too. 58 * </p> 59 * <p/> 60 * <h3>Equality of Sessions</h3> 61 * TODO : The getId() method is totally wrong. We can't base 62 * a method which is designed to create a unique ID on the hashCode method. 63 * {@link #equals(Object)} and {@link #hashCode()} shall not be overriden 64 * to the default behavior that is defined in {@link Object}. 65 * 66 * @author The Apache MINA Project (dev@mina.apache.org) 67 * @version $Rev: 677564 $, $Date: 2008-07-17 13:52:14 +0200 (jeu, 17 jui 2008) $ 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 * @return the {@link TransportMetadata} that this session runs on. 102 */ 103 TransportMetadata getTransportMetadata(); 104 105 /** 106 * TODO This javadoc is wrong. The return tag should be short. 107 * 108 * @return a {@link ReadFuture} which is notified when a new message is 109 * received, the connection is closed or an exception is caught. This 110 * operation is especially useful when you implement a client application. 111 * TODO : Describe here how we enable this feature. 112 * However, please note that this operation is disabled by default and 113 * throw {@link IllegalStateException} because all received events must be 114 * queued somewhere to support this operation, possibly leading to memory 115 * leak. This means you have to keep calling {@link #read()} once you 116 * enabled this operation. To enable this operation, please call 117 * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>. 118 * 119 * @throws IllegalStateException if 120 * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation} 121 * option has not been enabled. 122 */ 123 ReadFuture read(); 124 125 /** 126 * Writes the specified <code>message</code> to remote peer. This 127 * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)} 128 * will be invoked when the message is actually sent to remote peer. 129 * You can also wait for the returned {@link WriteFuture} if you want 130 * to wait for the message actually written. 131 */ 132 WriteFuture write(Object message); 133 134 /** 135 * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>. 136 * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)} 137 * will be invoked when the message is actually sent to remote peer. You can 138 * also wait for the returned {@link WriteFuture} if you want to wait for 139 * the message actually written. 140 * <p> 141 * When you implement a client that receives a broadcast message from a server 142 * such as DHCP server, the client might need to send a response message for the 143 * broadcast message the server sent. Because the remote address of the session 144 * is not the address of the server in case of broadcasting, there should be a 145 * way to specify the destination when you write the response message. 146 * This interface provides {@link #write(Object, SocketAddress)} method so you 147 * can specify the destination. 148 * 149 * @param destination <tt>null</tt> if you want the message sent to the 150 * default remote address 151 * 152 * @throws UnsupportedOperationException if this operation is not supported 153 */ 154 WriteFuture write(Object message, SocketAddress destination); 155 156 /** 157 * Closes this session immediately. This operation is asynchronous. 158 * Wait for the returned {@link CloseFuture} if you want to wait for 159 * the session actually closed. 160 */ 161 CloseFuture close(); 162 163 /** 164 * Closes this session after all queued write requests are flushed. 165 * This operation is asynchronous. Wait for the returned {@link CloseFuture} 166 * if you want to wait for the session actually closed. 167 */ 168 CloseFuture closeOnFlush(); 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 * (i.e. {@link #close()}). 177 * {@code false} to close this session after all queued 178 * write requests are flushed (i.e. {@link #closeOnFlush()}). 179 */ 180 CloseFuture close(boolean immediately); 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 * Returns the current {@link TrafficMask} of this session. 363 */ 364 TrafficMask getTrafficMask(); 365 366 /** 367 * Sets the {@link TrafficMask} of this session which will result 368 * the parent {@link IoService} to start to control the traffic 369 * of this session immediately. 370 */ 371 void setTrafficMask(TrafficMask trafficMask); 372 373 /** 374 * A shortcut method for {@link #setTrafficMask(TrafficMask)} that 375 * suspends read operations for this session. 376 */ 377 void suspendRead(); 378 379 /** 380 * A shortcut method for {@link #setTrafficMask(TrafficMask)} that 381 * suspends write operations for this session. 382 */ 383 void suspendWrite(); 384 385 /** 386 * A shortcut method for {@link #setTrafficMask(TrafficMask)} that 387 * resumes read operations for this session. 388 */ 389 void resumeRead(); 390 391 /** 392 * A shortcut method for {@link #setTrafficMask(TrafficMask)} that 393 * resumes write operations for this session. 394 */ 395 void resumeWrite(); 396 397 /** 398 * Returns the total number of bytes which were read from this session. 399 */ 400 long getReadBytes(); 401 402 /** 403 * Returns the total number of bytes which were written to this session. 404 */ 405 long getWrittenBytes(); 406 407 /** 408 * Returns the total number of messages which were read and decoded from this session. 409 */ 410 long getReadMessages(); 411 412 /** 413 * Returns the total number of messages which were written and encoded by this session. 414 */ 415 long getWrittenMessages(); 416 417 /** 418 * Returns the number of read bytes per second. 419 */ 420 double getReadBytesThroughput(); 421 422 /** 423 * Returns the number of written bytes per second. 424 */ 425 double getWrittenBytesThroughput(); 426 427 /** 428 * Returns the number of read messages per second. 429 */ 430 double getReadMessagesThroughput(); 431 432 /** 433 * Returns the number of written messages per second. 434 */ 435 double getWrittenMessagesThroughput(); 436 437 /** 438 * Returns the number of messages which are scheduled to be written to this session. 439 */ 440 int getScheduledWriteMessages(); 441 442 /** 443 * Returns the number of bytes which are scheduled to be written to this 444 * session. 445 */ 446 long getScheduledWriteBytes(); 447 448 /** 449 * Returns the message which is being written by {@link IoService}. 450 * @return <tt>null</tt> if and if only no message is being written 451 */ 452 Object getCurrentWriteMessage(); 453 454 /** 455 * Returns the {@link WriteRequest} which is being processed by 456 * {@link IoService}. 457 * 458 * @return <tt>null</tt> if and if only no message is being written 459 */ 460 WriteRequest getCurrentWriteRequest(); 461 462 /** 463 * @return the session's creation time in nanoseconds 464 */ 465 long getCreationTime(); 466 467 /** 468 * Returns the time in millis when I/O occurred lastly. 469 */ 470 long getLastIoTime(); 471 472 /** 473 * Returns the time in millis when read operation occurred lastly. 474 */ 475 long getLastReadTime(); 476 477 /** 478 * Returns the time in millis when write operation occurred lastly. 479 */ 480 long getLastWriteTime(); 481 482 /** 483 * Returns <code>true</code> if this session is idle for the specified 484 * {@link IdleStatus}. 485 */ 486 boolean isIdle(IdleStatus status); 487 488 /** 489 * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}. 490 * @see #isIdle(IdleStatus) 491 */ 492 boolean isReaderIdle(); 493 494 /** 495 * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}. 496 * @see #isIdle(IdleStatus) 497 */ 498 boolean isWriterIdle(); 499 500 /** 501 * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}. 502 * @see #isIdle(IdleStatus) 503 */ 504 boolean isBothIdle(); 505 506 /** 507 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 508 * for the specified {@link IdleStatus}. 509 * <p/> 510 * If <tt>sessionIdle</tt> event is fired first after some time after I/O, 511 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to 512 * <tt>0</tt> if any I/O occurs again, otherwise it increases to 513 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without 514 * any I/O between two (or more) <tt>sessionIdle</tt> events. 515 */ 516 int getIdleCount(IdleStatus status); 517 518 /** 519 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 520 * for {@link IdleStatus#READER_IDLE}. 521 * @see #getIdleCount(IdleStatus) 522 */ 523 int getReaderIdleCount(); 524 525 /** 526 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 527 * for {@link IdleStatus#WRITER_IDLE}. 528 * @see #getIdleCount(IdleStatus) 529 */ 530 int getWriterIdleCount(); 531 532 /** 533 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 534 * for {@link IdleStatus#BOTH_IDLE}. 535 * @see #getIdleCount(IdleStatus) 536 */ 537 int getBothIdleCount(); 538 539 /** 540 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 541 * is fired for the specified {@link IdleStatus}. 542 */ 543 long getLastIdleTime(IdleStatus status); 544 545 546 /** 547 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 548 * is fired for {@link IdleStatus#READER_IDLE}. 549 * @see #getLastIdleTime(IdleStatus) 550 */ 551 long getLastReaderIdleTime(); 552 553 /** 554 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 555 * is fired for {@link IdleStatus#WRITER_IDLE}. 556 * @see #getLastIdleTime(IdleStatus) 557 */ 558 long getLastWriterIdleTime(); 559 560 /** 561 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 562 * is fired for {@link IdleStatus#BOTH_IDLE}. 563 * @see #getLastIdleTime(IdleStatus) 564 */ 565 long getLastBothIdleTime(); 566 }