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 }