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