001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.core.session; 021 022import java.net.SocketAddress; 023import java.util.Set; 024 025import org.apache.mina.core.filterchain.IoFilter; 026import org.apache.mina.core.filterchain.IoFilterChain; 027import org.apache.mina.core.future.CloseFuture; 028import org.apache.mina.core.future.ReadFuture; 029import org.apache.mina.core.future.WriteFuture; 030import org.apache.mina.core.service.IoAcceptor; 031import org.apache.mina.core.service.IoConnector; 032import org.apache.mina.core.service.IoHandler; 033import org.apache.mina.core.service.IoService; 034import org.apache.mina.core.service.TransportMetadata; 035import org.apache.mina.core.write.WriteRequest; 036import org.apache.mina.core.write.WriteRequestQueue; 037 038/** 039 * <p> 040 * A handle which represents connection between two end-points regardless of 041 * transport types. 042 * </p> 043 * <p> 044 * {@link IoSession} provides user-defined attributes. User-defined attributes 045 * are application-specific data which are associated with a session. 046 * It often contains objects that represents the state of a higher-level protocol 047 * and becomes a way to exchange data between filters and handlers. 048 * </p> 049 * <h3>Adjusting Transport Type Specific Properties</h3> 050 * <p> 051 * You can simply downcast the session to an appropriate subclass. 052 * </p> 053 * <h3>Thread Safety</h3> 054 * <p> 055 * {@link IoSession} is thread-safe. But please note that performing 056 * more than one {@link #write(Object)} calls at the same time will 057 * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,IoSession,WriteRequest)} 058 * to be executed simultaneously, and therefore you have to make sure the 059 * {@link IoFilter} implementations you're using are thread-safe, too. 060 * </p> 061 * <h3>Equality of Sessions</h3> 062 * TODO : The getId() method is totally wrong. We can't base 063 * a method which is designed to create a unique ID on the hashCode method. 064 * {@link Object#equals(Object)} and {@link Object#hashCode()} shall not be overriden 065 * to the default behavior that is defined in {@link Object}. 066 * 067 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 068 */ 069public interface IoSession { 070 /** 071 * @return a unique identifier for this session. Every session has its own 072 * ID which is different from each other. 073 * 074 * TODO : The way it's implemented does not guarantee that the contract is 075 * respected. It uses the HashCode() method which don't guarantee the key 076 * unicity. 077 */ 078 long getId(); 079 080 /** 081 * @return the {@link IoService} which provides I/O service to this session. 082 */ 083 IoService getService(); 084 085 /** 086 * @return the {@link IoHandler} which handles this session. 087 */ 088 IoHandler getHandler(); 089 090 /** 091 * @return the configuration of this session. 092 */ 093 IoSessionConfig getConfig(); 094 095 /** 096 * @return the filter chain that only affects this session. 097 */ 098 IoFilterChain getFilterChain(); 099 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 * @return The {@link CloseFuture} that can be use to wait for the completion of this operation 190 */ 191 CloseFuture closeNow(); 192 193 /** 194 * Closes this session after all queued write requests are flushed. This operation 195 * is asynchronous. Wait for the returned {@link CloseFuture} if you want to wait 196 * for the session actually closed. 197 * 198 * @return The associated CloseFuture 199 */ 200 CloseFuture closeOnFlush(); 201 202 /** 203 * Closes this session after all queued write requests 204 * are flushed. This operation is asynchronous. Wait for the returned 205 * {@link CloseFuture} if you want to wait for the session actually closed. 206 * @deprecated use {@link #close(boolean)} 207 * 208 * @return The associated CloseFuture 209 */ 210 @Deprecated 211 CloseFuture close(); 212 213 /** 214 * Returns an attachment of this session. 215 * This method is identical with <tt>getAttribute( "" )</tt>. 216 * 217 * @return The attachment 218 * @deprecated Use {@link #getAttribute(Object)} instead. 219 */ 220 @Deprecated 221 Object getAttachment(); 222 223 /** 224 * Sets an attachment of this session. 225 * This method is identical with <tt>setAttribute( "", attachment )</tt>. 226 * 227 * @param attachment The attachment 228 * @return Old attachment. <tt>null</tt> if it is new. 229 * @deprecated Use {@link #setAttribute(Object, Object)} instead. 230 */ 231 @Deprecated 232 Object setAttachment(Object attachment); 233 234 /** 235 * Returns the value of the user-defined attribute of this session. 236 * 237 * @param key the key of the attribute 238 * @return <tt>null</tt> if there is no attribute with the specified key 239 */ 240 Object getAttribute(Object key); 241 242 /** 243 * Returns the value of user defined attribute associated with the 244 * specified key. If there's no such attribute, the specified default 245 * value is associated with the specified key, and the default value is 246 * returned. This method is same with the following code except that the 247 * operation is performed atomically. 248 * <pre> 249 * if (containsAttribute(key)) { 250 * return getAttribute(key); 251 * } else { 252 * setAttribute(key, defaultValue); 253 * return defaultValue; 254 * } 255 * </pre> 256 * 257 * @param key the key of the attribute we want to retreive 258 * @param defaultValue the default value of the attribute 259 * @return The retrieved attribute or <tt>null</tt> if not found 260 */ 261 Object getAttribute(Object key, Object defaultValue); 262 263 /** 264 * Sets a user-defined attribute. 265 * 266 * @param key the key of the attribute 267 * @param value the value of the attribute 268 * @return The old value of the attribute. <tt>null</tt> if it is new. 269 */ 270 Object setAttribute(Object key, Object value); 271 272 /** 273 * Sets a user defined attribute without a value. This is useful when 274 * you just want to put a 'mark' attribute. Its value is set to 275 * {@link Boolean#TRUE}. 276 * 277 * @param key the key of the attribute 278 * @return The old value of the attribute. <tt>null</tt> if it is new. 279 */ 280 Object setAttribute(Object key); 281 282 /** 283 * Sets a user defined attribute if the attribute with the specified key 284 * is not set yet. This method is same with the following code except 285 * that the operation is performed atomically. 286 * <pre> 287 * if (containsAttribute(key)) { 288 * return getAttribute(key); 289 * } else { 290 * return setAttribute(key, value); 291 * } 292 * </pre> 293 * 294 * @param key The key of the attribute we want to set 295 * @param value The value we want to set 296 * @return The old value of the attribute. <tt>null</tt> if not found. 297 */ 298 Object setAttributeIfAbsent(Object key, Object value); 299 300 /** 301 * Sets a user defined attribute without a value if the attribute with 302 * the specified key is not set yet. This is useful when you just want to 303 * put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}. 304 * This method is same with the following code except that the operation 305 * is performed atomically. 306 * <pre> 307 * if (containsAttribute(key)) { 308 * return getAttribute(key); // might not always be Boolean.TRUE. 309 * } else { 310 * return setAttribute(key); 311 * } 312 * </pre> 313 * 314 * @param key The key of the attribute we want to set 315 * @return The old value of the attribute. <tt>null</tt> if not found. 316 */ 317 Object setAttributeIfAbsent(Object key); 318 319 /** 320 * Removes a user-defined attribute with the specified key. 321 * 322 * @param key The key of the attribute we want to remove 323 * @return The old value of the attribute. <tt>null</tt> if not found. 324 */ 325 Object removeAttribute(Object key); 326 327 /** 328 * Removes a user defined attribute with the specified key if the current 329 * attribute value is equal to the specified value. This method is same 330 * with the following code except that the operation is performed 331 * atomically. 332 * <pre> 333 * if (containsAttribute(key) && getAttribute(key).equals(value)) { 334 * removeAttribute(key); 335 * return true; 336 * } else { 337 * return false; 338 * } 339 * </pre> 340 * 341 * @param key The key we want to remove 342 * @param value The value we want to remove 343 * @return <tt>true</tt> if the removal was successful 344 */ 345 boolean removeAttribute(Object key, Object value); 346 347 /** 348 * Replaces a user defined attribute with the specified key if the 349 * value of the attribute is equals to the specified old value. 350 * This method is same with the following code except that the operation 351 * is performed atomically. 352 * <pre> 353 * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) { 354 * setAttribute(key, newValue); 355 * return true; 356 * } else { 357 * return false; 358 * } 359 * </pre> 360 * 361 * @param key The key we want to replace 362 * @param oldValue The previous value 363 * @param newValue The new value 364 * @return <tt>true</tt> if the replacement was successful 365 */ 366 boolean replaceAttribute(Object key, Object oldValue, Object newValue); 367 368 /** 369 * @param key The key of the attribute we are looking for in the session 370 * @return <tt>true</tt> if this session contains the attribute with 371 * the specified <tt>key</tt>. 372 */ 373 boolean containsAttribute(Object key); 374 375 /** 376 * @return the set of keys of all user-defined attributes. 377 */ 378 Set<Object> getAttributeKeys(); 379 380 /** 381 * @return <tt>true</tt> if this session is connected with remote peer. 382 */ 383 boolean isConnected(); 384 385 /** 386 * @return <tt>true</tt> if this session is active. 387 */ 388 boolean isActive(); 389 390 /** 391 * @return <tt>true</tt> if and only if this session is being closed 392 * (but not disconnected yet) or is closed. 393 */ 394 boolean isClosing(); 395 396 /** 397 * @return <tt>true</tt> if the session has started and initialized a SslEngine, 398 * <tt>false</tt> if the session is not yet secured (the handshake is not completed) 399 * or if SSL is not set for this session, or if SSL is not even an option. 400 */ 401 boolean isSecured(); 402 403 /** 404 * @return the {@link CloseFuture} of this session. This method returns 405 * the same instance whenever user calls it. 406 */ 407 CloseFuture getCloseFuture(); 408 409 /** 410 * @return the socket address of remote peer. 411 */ 412 SocketAddress getRemoteAddress(); 413 414 /** 415 * @return the socket address of local machine which is associated with this 416 * session. 417 */ 418 SocketAddress getLocalAddress(); 419 420 /** 421 * @return the socket address of the {@link IoService} listens to to manage 422 * this session. If this session is managed by {@link IoAcceptor}, it 423 * returns the {@link SocketAddress} which is specified as a parameter of 424 * {@link IoAcceptor#bind()}. If this session is managed by 425 * {@link IoConnector}, this method returns the same address with 426 * that of {@link #getRemoteAddress()}. 427 */ 428 SocketAddress getServiceAddress(); 429 430 /** 431 * 432 * Associate the current write request with the session 433 * 434 * @param currentWriteRequest the current write request to associate 435 */ 436 void setCurrentWriteRequest(WriteRequest currentWriteRequest); 437 438 /** 439 * Suspends read operations for this session. 440 */ 441 void suspendRead(); 442 443 /** 444 * Suspends write operations for this session. 445 */ 446 void suspendWrite(); 447 448 /** 449 * Resumes read operations for this session. 450 */ 451 void resumeRead(); 452 453 /** 454 * Resumes write operations for this session. 455 */ 456 void resumeWrite(); 457 458 /** 459 * Is read operation is suspended for this session. 460 * 461 * @return <tt>true</tt> if suspended 462 */ 463 boolean isReadSuspended(); 464 465 /** 466 * Is write operation is suspended for this session. 467 * 468 * @return <tt>true</tt> if suspended 469 */ 470 boolean isWriteSuspended(); 471 472 /** 473 * Update all statistical properties related with throughput assuming 474 * the specified time is the current time. By default this method returns 475 * silently without updating the throughput properties if they were 476 * calculated already within last 477 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. 478 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method 479 * updates the throughput properties immediately. 480 481 * @param currentTime the current time in milliseconds 482 * @param force Force the update if <tt>true</tt> 483 */ 484 void updateThroughput(long currentTime, boolean force); 485 486 /** 487 * @return the total number of bytes which were read from this session. 488 */ 489 long getReadBytes(); 490 491 /** 492 * @return the total number of bytes which were written to this session. 493 */ 494 long getWrittenBytes(); 495 496 /** 497 * @return the total number of messages which were read and decoded from this session. 498 */ 499 long getReadMessages(); 500 501 /** 502 * @return the total number of messages which were written and encoded by this session. 503 */ 504 long getWrittenMessages(); 505 506 /** 507 * @return the number of read bytes per second. 508 */ 509 double getReadBytesThroughput(); 510 511 /** 512 * @return the number of written bytes per second. 513 */ 514 double getWrittenBytesThroughput(); 515 516 /** 517 * @return the number of read messages per second. 518 */ 519 double getReadMessagesThroughput(); 520 521 /** 522 * @return the number of written messages per second. 523 */ 524 double getWrittenMessagesThroughput(); 525 526 /** 527 * @return the number of messages which are scheduled to be written to this session. 528 */ 529 int getScheduledWriteMessages(); 530 531 /** 532 * @return the number of bytes which are scheduled to be written to this 533 * session. 534 */ 535 long getScheduledWriteBytes(); 536 537 /** 538 * Returns the message which is being written by {@link IoService}. 539 * @return <tt>null</tt> if and if only no message is being written 540 */ 541 Object getCurrentWriteMessage(); 542 543 /** 544 * Returns the {@link WriteRequest} which is being processed by 545 * {@link IoService}. 546 * 547 * @return <tt>null</tt> if and if only no message is being written 548 */ 549 WriteRequest getCurrentWriteRequest(); 550 551 /** 552 * @return the session's creation time in milliseconds 553 */ 554 long getCreationTime(); 555 556 /** 557 * @return the time in millis when I/O occurred lastly. 558 */ 559 long getLastIoTime(); 560 561 /** 562 * @return the time in millis when read operation occurred lastly. 563 */ 564 long getLastReadTime(); 565 566 /** 567 * @return the time in millis when write operation occurred lastly. 568 */ 569 long getLastWriteTime(); 570 571 /** 572 * @param status The researched idle status 573 * @return <tt>true</tt> if this session is idle for the specified 574 * {@link IdleStatus}. 575 */ 576 boolean isIdle(IdleStatus status); 577 578 /** 579 * @return <tt>true</tt> if this session is {@link IdleStatus#READER_IDLE}. 580 * @see #isIdle(IdleStatus) 581 */ 582 boolean isReaderIdle(); 583 584 /** 585 * @return <tt>true</tt> if this session is {@link IdleStatus#WRITER_IDLE}. 586 * @see #isIdle(IdleStatus) 587 */ 588 boolean isWriterIdle(); 589 590 /** 591 * @return <tt>true</tt> if this session is {@link IdleStatus#BOTH_IDLE}. 592 * @see #isIdle(IdleStatus) 593 */ 594 boolean isBothIdle(); 595 596 /** 597 * @param status The researched idle status 598 * @return the number of the fired continuous <tt>sessionIdle</tt> events 599 * for the specified {@link IdleStatus}. 600 * <p> 601 * If <tt>sessionIdle</tt> event is fired first after some time after I/O, 602 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to 603 * <tt>0</tt> if any I/O occurs again, otherwise it increases to 604 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without 605 * any I/O between two (or more) <tt>sessionIdle</tt> events. 606 */ 607 int getIdleCount(IdleStatus status); 608 609 /** 610 * @return the number of the fired continuous <tt>sessionIdle</tt> events 611 * for {@link IdleStatus#READER_IDLE}. 612 * @see #getIdleCount(IdleStatus) 613 */ 614 int getReaderIdleCount(); 615 616 /** 617 * @return the number of the fired continuous <tt>sessionIdle</tt> events 618 * for {@link IdleStatus#WRITER_IDLE}. 619 * @see #getIdleCount(IdleStatus) 620 */ 621 int getWriterIdleCount(); 622 623 /** 624 * @return the number of the fired continuous <tt>sessionIdle</tt> events 625 * for {@link IdleStatus#BOTH_IDLE}. 626 * @see #getIdleCount(IdleStatus) 627 */ 628 int getBothIdleCount(); 629 630 /** 631 * @param status The researched idle status 632 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event 633 * is fired for the specified {@link IdleStatus}. 634 */ 635 long getLastIdleTime(IdleStatus status); 636 637 /** 638 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event 639 * is fired for {@link IdleStatus#READER_IDLE}. 640 * @see #getLastIdleTime(IdleStatus) 641 */ 642 long getLastReaderIdleTime(); 643 644 /** 645 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event 646 * is fired for {@link IdleStatus#WRITER_IDLE}. 647 * @see #getLastIdleTime(IdleStatus) 648 */ 649 long getLastWriterIdleTime(); 650 651 /** 652 * @return the time in milliseconds when the last <tt>sessionIdle</tt> event 653 * is fired for {@link IdleStatus#BOTH_IDLE}. 654 * @see #getLastIdleTime(IdleStatus) 655 */ 656 long getLastBothIdleTime(); 657}