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 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 * TODO Add method documentation 102 */ 103 WriteRequestQueue getWriteRequestQueue(); 104 105 /** 106 * @return the {@link TransportMetadata} that this session runs on. 107 */ 108 TransportMetadata getTransportMetadata(); 109 110 /** 111 * TODO This javadoc is wrong. The return tag should be short. 112 * 113 * @return a {@link ReadFuture} which is notified when a new message is 114 * received, the connection is closed or an exception is caught. This 115 * operation is especially useful when you implement a client application. 116 * TODO : Describe here how we enable this feature. 117 * However, please note that this operation is disabled by default and 118 * throw {@link IllegalStateException} because all received events must be 119 * queued somewhere to support this operation, possibly leading to memory 120 * leak. This means you have to keep calling {@link #read()} once you 121 * enabled this operation. To enable this operation, please call 122 * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>. 123 * 124 * @throws IllegalStateException if 125 * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation} 126 * option has not been enabled. 127 */ 128 ReadFuture read(); 129 130 /** 131 * Writes the specified <code>message</code> to remote peer. This 132 * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)} 133 * will be invoked when the message is actually sent to remote peer. 134 * You can also wait for the returned {@link WriteFuture} if you want 135 * to wait for the message actually written. 136 */ 137 WriteFuture write(Object message); 138 139 /** 140 * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>. 141 * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)} 142 * will be invoked when the message is actually sent to remote peer. You can 143 * also wait for the returned {@link WriteFuture} if you want to wait for 144 * the message actually written. 145 * <p> 146 * When you implement a client that receives a broadcast message from a server 147 * such as DHCP server, the client might need to send a response message for the 148 * broadcast message the server sent. Because the remote address of the session 149 * is not the address of the server in case of broadcasting, there should be a 150 * way to specify the destination when you write the response message. 151 * This interface provides {@link #write(Object, SocketAddress)} method so you 152 * can specify the destination. 153 * 154 * @param destination <tt>null</tt> if you want the message sent to the 155 * default remote address 156 * 157 * @throws UnsupportedOperationException if this operation is not supported 158 */ 159 WriteFuture write(Object message, SocketAddress destination); 160 161 /** 162 * Closes this session immediately or after all queued write requests 163 * are flushed. This operation is asynchronous. Wait for the returned 164 * {@link CloseFuture} if you want to wait for the session actually closed. 165 * 166 * @param immediately {@code true} to close this session immediately 167 * . The pending write requests 168 * will simply be discarded. 169 * {@code false} to close this session after all queued 170 * write requests are flushed (i.e. {@link #close()}). 171 */ 172 CloseFuture close(boolean immediately); 173 174 /** 175 * Closes this session after all queued write requests 176 * are flushed. This operation is asynchronous. Wait for the returned 177 * {@link CloseFuture} if you want to wait for the session actually closed. 178 * @deprecated use {@link #close(boolean)} 179 */ 180 @Deprecated 181 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 190 Object getAttachment(); 191 192 /** 193 * Sets an attachment of this session. 194 * This method is identical with <tt>setAttribute( "", attachment )</tt>. 195 * 196 * @return Old attachment. <tt>null</tt> if it is new. 197 * @deprecated Use {@link #setAttribute(Object, Object)} instead. 198 */ 199 @Deprecated 200 Object setAttachment(Object attachment); 201 202 /** 203 * Returns the value of the user-defined attribute of this session. 204 * 205 * @param key the key of the attribute 206 * @return <tt>null</tt> if there is no attribute with the specified key 207 */ 208 Object getAttribute(Object key); 209 210 /** 211 * Returns the value of user defined attribute associated with the 212 * specified key. If there's no such attribute, the specified default 213 * value is associated with the specified key, and the default value is 214 * returned. This method is same with the following code except that the 215 * operation is performed atomically. 216 * <pre> 217 * if (containsAttribute(key)) { 218 * return getAttribute(key); 219 * } else { 220 * setAttribute(key, defaultValue); 221 * return defaultValue; 222 * } 223 * </pre> 224 */ 225 Object getAttribute(Object key, Object defaultValue); 226 227 /** 228 * Sets a user-defined attribute. 229 * 230 * @param key the key of the attribute 231 * @param value the value of the attribute 232 * @return The old value of the attribute. <tt>null</tt> if it is new. 233 */ 234 Object setAttribute(Object key, Object value); 235 236 /** 237 * Sets a user defined attribute without a value. This is useful when 238 * you just want to put a 'mark' attribute. Its value is set to 239 * {@link Boolean#TRUE}. 240 * 241 * @param key the key of the attribute 242 * @return The old value of the attribute. <tt>null</tt> if it is new. 243 */ 244 Object setAttribute(Object key); 245 246 /** 247 * Sets a user defined attribute if the attribute with the specified key 248 * is not set yet. This method is same with the following code except 249 * that the operation is performed atomically. 250 * <pre> 251 * if (containsAttribute(key)) { 252 * return getAttribute(key); 253 * } else { 254 * return setAttribute(key, value); 255 * } 256 * </pre> 257 */ 258 Object setAttributeIfAbsent(Object key, Object value); 259 260 /** 261 * Sets a user defined attribute without a value if the attribute with 262 * the specified key is not set yet. This is useful when you just want to 263 * put a 'mark' attribute. Its value is set to {@link Boolean#TRUE}. 264 * This method is same with the following code except that the operation 265 * is performed atomically. 266 * <pre> 267 * if (containsAttribute(key)) { 268 * return getAttribute(key); // might not always be Boolean.TRUE. 269 * } else { 270 * return setAttribute(key); 271 * } 272 * </pre> 273 */ 274 Object setAttributeIfAbsent(Object key); 275 276 /** 277 * Removes a user-defined attribute with the specified key. 278 * 279 * @return The old value of the attribute. <tt>null</tt> if not found. 280 */ 281 Object removeAttribute(Object key); 282 283 /** 284 * Removes a user defined attribute with the specified key if the current 285 * attribute value is equal to the specified value. This method is same 286 * with the following code except that the operation is performed 287 * atomically. 288 * <pre> 289 * if (containsAttribute(key) && getAttribute(key).equals(value)) { 290 * removeAttribute(key); 291 * return true; 292 * } else { 293 * return false; 294 * } 295 * </pre> 296 */ 297 boolean removeAttribute(Object key, Object value); 298 299 /** 300 * Replaces a user defined attribute with the specified key if the 301 * value of the attribute is equals to the specified old value. 302 * This method is same with the following code except that the operation 303 * is performed atomically. 304 * <pre> 305 * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) { 306 * setAttribute(key, newValue); 307 * return true; 308 * } else { 309 * return false; 310 * } 311 * </pre> 312 */ 313 boolean replaceAttribute(Object key, Object oldValue, Object newValue); 314 315 /** 316 * Returns <tt>true</tt> if this session contains the attribute with 317 * the specified <tt>key</tt>. 318 */ 319 boolean containsAttribute(Object key); 320 321 /** 322 * @return the set of keys of all user-defined attributes. 323 */ 324 Set<Object> getAttributeKeys(); 325 326 /** 327 * @return <code>true</code> if this session is connected with remote peer. 328 */ 329 boolean isConnected(); 330 331 /** 332 * @return <code>true</tt> if and only if this session is being closed 333 * (but not disconnected yet) or is closed. 334 */ 335 boolean isClosing(); 336 337 /** 338 * @return <code>true</tt> if the session has started and initialized a SslEngine, 339 * <code>false</code> if the session is not yet secured (the handshake is not completed) 340 * or if SSL is not set for this session, or if SSL is not even an option. 341 */ 342 boolean isSecured(); 343 344 /** 345 * Returns the {@link CloseFuture} of this session. This method returns 346 * the same instance whenever user calls it. 347 */ 348 CloseFuture getCloseFuture(); 349 350 /** 351 * Returns the socket address of remote peer. 352 */ 353 SocketAddress getRemoteAddress(); 354 355 /** 356 * Returns the socket address of local machine which is associated with this 357 * session. 358 */ 359 SocketAddress getLocalAddress(); 360 361 /** 362 * Returns the socket address of the {@link IoService} listens to to manage 363 * this session. If this session is managed by {@link IoAcceptor}, it 364 * returns the {@link SocketAddress} which is specified as a parameter of 365 * {@link IoAcceptor#bind()}. If this session is managed by 366 * {@link IoConnector}, this method returns the same address with 367 * that of {@link #getRemoteAddress()}. 368 */ 369 SocketAddress getServiceAddress(); 370 371 /** 372 * 373 * Associate the current write request with the session 374 * 375 * @param currentWriteRequest the current write request to associate 376 */ 377 void setCurrentWriteRequest(WriteRequest currentWriteRequest); 378 379 /** 380 * Suspends read operations for this session. 381 */ 382 void suspendRead(); 383 384 /** 385 * Suspends write operations for this session. 386 */ 387 void suspendWrite(); 388 389 /** 390 * Resumes read operations for this session. 391 */ 392 void resumeRead(); 393 394 /** 395 * Resumes write operations for this session. 396 */ 397 void resumeWrite(); 398 399 /** 400 * Is read operation is suspended for this session. 401 * @return <code>true</code> if suspended 402 */ 403 boolean isReadSuspended(); 404 405 /** 406 * Is write operation is suspended for this session. 407 * @return <code>true</code> if suspended 408 */ 409 boolean isWriteSuspended(); 410 411 /** 412 * Update all statistical properties related with throughput assuming 413 * the specified time is the current time. By default this method returns 414 * silently without updating the throughput properties if they were 415 * calculated already within last 416 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. 417 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method 418 * updates the throughput properties immediately. 419 420 * @param currentTime the current time in milliseconds 421 */ 422 void updateThroughput(long currentTime, boolean force); 423 424 /** 425 * Returns the total number of bytes which were read from this session. 426 */ 427 long getReadBytes(); 428 429 /** 430 * Returns the total number of bytes which were written to this session. 431 */ 432 long getWrittenBytes(); 433 434 /** 435 * Returns the total number of messages which were read and decoded from this session. 436 */ 437 long getReadMessages(); 438 439 /** 440 * Returns the total number of messages which were written and encoded by this session. 441 */ 442 long getWrittenMessages(); 443 444 /** 445 * Returns the number of read bytes per second. 446 */ 447 double getReadBytesThroughput(); 448 449 /** 450 * Returns the number of written bytes per second. 451 */ 452 double getWrittenBytesThroughput(); 453 454 /** 455 * Returns the number of read messages per second. 456 */ 457 double getReadMessagesThroughput(); 458 459 /** 460 * Returns the number of written messages per second. 461 */ 462 double getWrittenMessagesThroughput(); 463 464 /** 465 * Returns the number of messages which are scheduled to be written to this session. 466 */ 467 int getScheduledWriteMessages(); 468 469 /** 470 * Returns the number of bytes which are scheduled to be written to this 471 * session. 472 */ 473 long getScheduledWriteBytes(); 474 475 /** 476 * Returns the message which is being written by {@link IoService}. 477 * @return <tt>null</tt> if and if only no message is being written 478 */ 479 Object getCurrentWriteMessage(); 480 481 /** 482 * Returns the {@link WriteRequest} which is being processed by 483 * {@link IoService}. 484 * 485 * @return <tt>null</tt> if and if only no message is being written 486 */ 487 WriteRequest getCurrentWriteRequest(); 488 489 /** 490 * @return the session's creation time in milliseconds 491 */ 492 long getCreationTime(); 493 494 /** 495 * Returns the time in millis when I/O occurred lastly. 496 */ 497 long getLastIoTime(); 498 499 /** 500 * Returns the time in millis when read operation occurred lastly. 501 */ 502 long getLastReadTime(); 503 504 /** 505 * Returns the time in millis when write operation occurred lastly. 506 */ 507 long getLastWriteTime(); 508 509 /** 510 * Returns <code>true</code> if this session is idle for the specified 511 * {@link IdleStatus}. 512 */ 513 boolean isIdle(IdleStatus status); 514 515 /** 516 * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}. 517 * @see #isIdle(IdleStatus) 518 */ 519 boolean isReaderIdle(); 520 521 /** 522 * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}. 523 * @see #isIdle(IdleStatus) 524 */ 525 boolean isWriterIdle(); 526 527 /** 528 * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}. 529 * @see #isIdle(IdleStatus) 530 */ 531 boolean isBothIdle(); 532 533 /** 534 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 535 * for the specified {@link IdleStatus}. 536 * <p/> 537 * If <tt>sessionIdle</tt> event is fired first after some time after I/O, 538 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to 539 * <tt>0</tt> if any I/O occurs again, otherwise it increases to 540 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without 541 * any I/O between two (or more) <tt>sessionIdle</tt> events. 542 */ 543 int getIdleCount(IdleStatus status); 544 545 /** 546 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 547 * for {@link IdleStatus#READER_IDLE}. 548 * @see #getIdleCount(IdleStatus) 549 */ 550 int getReaderIdleCount(); 551 552 /** 553 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 554 * for {@link IdleStatus#WRITER_IDLE}. 555 * @see #getIdleCount(IdleStatus) 556 */ 557 int getWriterIdleCount(); 558 559 /** 560 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 561 * for {@link IdleStatus#BOTH_IDLE}. 562 * @see #getIdleCount(IdleStatus) 563 */ 564 int getBothIdleCount(); 565 566 /** 567 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 568 * is fired for the specified {@link IdleStatus}. 569 */ 570 long getLastIdleTime(IdleStatus status); 571 572 /** 573 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 574 * is fired for {@link IdleStatus#READER_IDLE}. 575 * @see #getLastIdleTime(IdleStatus) 576 */ 577 long getLastReaderIdleTime(); 578 579 /** 580 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 581 * is fired for {@link IdleStatus#WRITER_IDLE}. 582 * @see #getLastIdleTime(IdleStatus) 583 */ 584 long getLastWriterIdleTime(); 585 586 /** 587 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 588 * is fired for {@link IdleStatus#BOTH_IDLE}. 589 * @see #getLastIdleTime(IdleStatus) 590 */ 591 long getLastBothIdleTime(); 592 }