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 #equals(Object)} and {@link #hashCode()} shall not be overriden 65 * to the default behavior that is defined in {@link Object}. 66 * 67 * @author The Apache MINA Project (dev@mina.apache.org) 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 /** 102 * TODO Add method documentation 103 */ 104 WriteRequestQueue getWriteRequestQueue(); 105 106 /** 107 * @return the {@link TransportMetadata} that this session runs on. 108 */ 109 TransportMetadata getTransportMetadata(); 110 111 /** 112 * TODO This javadoc is wrong. The return tag should be short. 113 * 114 * @return a {@link ReadFuture} which is notified when a new message is 115 * received, the connection is closed or an exception is caught. This 116 * operation is especially useful when you implement a client application. 117 * TODO : Describe here how we enable this feature. 118 * However, please note that this operation is disabled by default and 119 * throw {@link IllegalStateException} because all received events must be 120 * queued somewhere to support this operation, possibly leading to memory 121 * leak. This means you have to keep calling {@link #read()} once you 122 * enabled this operation. To enable this operation, please call 123 * {@link IoSessionConfig#setUseReadOperation(boolean)} with <tt>true</tt>. 124 * 125 * @throws IllegalStateException if 126 * {@link IoSessionConfig#setUseReadOperation(boolean) useReadOperation} 127 * option has not been enabled. 128 */ 129 ReadFuture read(); 130 131 /** 132 * Writes the specified <code>message</code> to remote peer. This 133 * operation is asynchronous; {@link IoHandler#messageSent(IoSession,Object)} 134 * will be invoked when the message is actually sent to remote peer. 135 * You can also wait for the returned {@link WriteFuture} if you want 136 * to wait for the message actually written. 137 */ 138 WriteFuture write(Object message); 139 140 /** 141 * (Optional) Writes the specified <tt>message</tt> to the specified <tt>destination</tt>. 142 * This operation is asynchronous; {@link IoHandler#messageSent(IoSession, Object)} 143 * will be invoked when the message is actually sent to remote peer. You can 144 * also wait for the returned {@link WriteFuture} if you want to wait for 145 * the message actually written. 146 * <p> 147 * When you implement a client that receives a broadcast message from a server 148 * such as DHCP server, the client might need to send a response message for the 149 * broadcast message the server sent. Because the remote address of the session 150 * is not the address of the server in case of broadcasting, there should be a 151 * way to specify the destination when you write the response message. 152 * This interface provides {@link #write(Object, SocketAddress)} method so you 153 * can specify the destination. 154 * 155 * @param destination <tt>null</tt> if you want the message sent to the 156 * default remote address 157 * 158 * @throws UnsupportedOperationException if this operation is not supported 159 */ 160 WriteFuture write(Object message, SocketAddress destination); 161 162 /** 163 * Closes this session immediately or after all queued write requests 164 * are flushed. This operation is asynchronous. Wait for the returned 165 * {@link CloseFuture} if you want to wait for the session actually closed. 166 * 167 * @param immediately {@code true} to close this session immediately 168 * (i.e. {@link #close()}). 169 * {@code false} to close this session after all queued 170 * write requests are flushed (i.e. {@link #closeOnFlush()}). 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 IoSession#close(boolean)} 179 */ 180 @Deprecated CloseFuture close(); 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 * 363 * TODO setWriteRequestQueue. 364 * 365 * @param writeRequestQueue 366 */ 367 void setCurrentWriteRequest(WriteRequest currentWriteRequest); 368 369 /** 370 * Suspends read operations for this session. 371 */ 372 void suspendRead(); 373 374 /** 375 * Suspends write operations for this session. 376 */ 377 void suspendWrite(); 378 379 /** 380 * Resumes read operations for this session. 381 */ 382 void resumeRead(); 383 384 /** 385 * Resumes write operations for this session. 386 */ 387 void resumeWrite(); 388 389 /** 390 * Is read operation is suspended for this session. 391 * @return <code>true</code> if suspended 392 */ 393 boolean isReadSuspended(); 394 395 /** 396 * Is write operation is suspended for this session. 397 * @return <code>true</code> if suspended 398 */ 399 boolean isWriteSuspended(); 400 401 /** 402 * Update all statistical properties related with throughput assuming 403 * the specified time is the current time. By default this method returns 404 * silently without updating the throughput properties if they were 405 * calculated already within last 406 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. 407 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method 408 * updates the throughput properties immediately. 409 410 * @param currentTime the current time in milliseconds 411 */ 412 void updateThroughput(long currentTime, boolean force); 413 414 /** 415 * Returns the total number of bytes which were read from this session. 416 */ 417 long getReadBytes(); 418 419 /** 420 * Returns the total number of bytes which were written to this session. 421 */ 422 long getWrittenBytes(); 423 424 /** 425 * Returns the total number of messages which were read and decoded from this session. 426 */ 427 long getReadMessages(); 428 429 /** 430 * Returns the total number of messages which were written and encoded by this session. 431 */ 432 long getWrittenMessages(); 433 434 /** 435 * Returns the number of read bytes per second. 436 */ 437 double getReadBytesThroughput(); 438 439 /** 440 * Returns the number of written bytes per second. 441 */ 442 double getWrittenBytesThroughput(); 443 444 /** 445 * Returns the number of read messages per second. 446 */ 447 double getReadMessagesThroughput(); 448 449 /** 450 * Returns the number of written messages per second. 451 */ 452 double getWrittenMessagesThroughput(); 453 454 /** 455 * Returns the number of messages which are scheduled to be written to this session. 456 */ 457 int getScheduledWriteMessages(); 458 459 /** 460 * Returns the number of bytes which are scheduled to be written to this 461 * session. 462 */ 463 long getScheduledWriteBytes(); 464 465 /** 466 * Returns the message which is being written by {@link IoService}. 467 * @return <tt>null</tt> if and if only no message is being written 468 */ 469 Object getCurrentWriteMessage(); 470 471 /** 472 * Returns the {@link WriteRequest} which is being processed by 473 * {@link IoService}. 474 * 475 * @return <tt>null</tt> if and if only no message is being written 476 */ 477 WriteRequest getCurrentWriteRequest(); 478 479 /** 480 * @return the session's creation time in nanoseconds 481 */ 482 long getCreationTime(); 483 484 /** 485 * Returns the time in millis when I/O occurred lastly. 486 */ 487 long getLastIoTime(); 488 489 /** 490 * Returns the time in millis when read operation occurred lastly. 491 */ 492 long getLastReadTime(); 493 494 /** 495 * Returns the time in millis when write operation occurred lastly. 496 */ 497 long getLastWriteTime(); 498 499 /** 500 * Returns <code>true</code> if this session is idle for the specified 501 * {@link IdleStatus}. 502 */ 503 boolean isIdle(IdleStatus status); 504 505 /** 506 * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}. 507 * @see #isIdle(IdleStatus) 508 */ 509 boolean isReaderIdle(); 510 511 /** 512 * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}. 513 * @see #isIdle(IdleStatus) 514 */ 515 boolean isWriterIdle(); 516 517 /** 518 * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}. 519 * @see #isIdle(IdleStatus) 520 */ 521 boolean isBothIdle(); 522 523 /** 524 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 525 * for the specified {@link IdleStatus}. 526 * <p/> 527 * If <tt>sessionIdle</tt> event is fired first after some time after I/O, 528 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to 529 * <tt>0</tt> if any I/O occurs again, otherwise it increases to 530 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without 531 * any I/O between two (or more) <tt>sessionIdle</tt> events. 532 */ 533 int getIdleCount(IdleStatus status); 534 535 /** 536 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 537 * for {@link IdleStatus#READER_IDLE}. 538 * @see #getIdleCount(IdleStatus) 539 */ 540 int getReaderIdleCount(); 541 542 /** 543 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 544 * for {@link IdleStatus#WRITER_IDLE}. 545 * @see #getIdleCount(IdleStatus) 546 */ 547 int getWriterIdleCount(); 548 549 /** 550 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 551 * for {@link IdleStatus#BOTH_IDLE}. 552 * @see #getIdleCount(IdleStatus) 553 */ 554 int getBothIdleCount(); 555 556 /** 557 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 558 * is fired for the specified {@link IdleStatus}. 559 */ 560 long getLastIdleTime(IdleStatus status); 561 562 563 /** 564 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 565 * is fired for {@link IdleStatus#READER_IDLE}. 566 * @see #getLastIdleTime(IdleStatus) 567 */ 568 long getLastReaderIdleTime(); 569 570 /** 571 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 572 * is fired for {@link IdleStatus#WRITER_IDLE}. 573 * @see #getLastIdleTime(IdleStatus) 574 */ 575 long getLastWriterIdleTime(); 576 577 /** 578 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 579 * is fired for {@link IdleStatus#BOTH_IDLE}. 580 * @see #getLastIdleTime(IdleStatus) 581 */ 582 long getLastBothIdleTime(); 583 }