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 <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 * (i.e. {@link #close()}). 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 #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 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 * Returns the set of keys of all user-defined attributes. 323 */ 324 Set<Object> getAttributeKeys(); 325 326 /** 327 * Returns <code>true</code> if this session is connected with remote peer. 328 */ 329 boolean isConnected(); 330 331 /** 332 * Returns <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 * Returns the {@link CloseFuture} of this session. This method returns 339 * the same instance whenever user calls it. 340 */ 341 CloseFuture getCloseFuture(); 342 343 /** 344 * Returns the socket address of remote peer. 345 */ 346 SocketAddress getRemoteAddress(); 347 348 /** 349 * Returns the socket address of local machine which is associated with this 350 * session. 351 */ 352 SocketAddress getLocalAddress(); 353 354 /** 355 * Returns the socket address of the {@link IoService} listens to to manage 356 * this session. If this session is managed by {@link IoAcceptor}, it 357 * returns the {@link SocketAddress} which is specified as a parameter of 358 * {@link IoAcceptor#bind()}. If this session is managed by 359 * {@link IoConnector}, this method returns the same address with 360 * that of {@link #getRemoteAddress()}. 361 */ 362 SocketAddress getServiceAddress(); 363 364 /** 365 * 366 * TODO setWriteRequestQueue. 367 * 368 * @param writeRequestQueue 369 */ 370 void setCurrentWriteRequest(WriteRequest currentWriteRequest); 371 372 /** 373 * Suspends read operations for this session. 374 */ 375 void suspendRead(); 376 377 /** 378 * Suspends write operations for this session. 379 */ 380 void suspendWrite(); 381 382 /** 383 * Resumes read operations for this session. 384 */ 385 void resumeRead(); 386 387 /** 388 * Resumes write operations for this session. 389 */ 390 void resumeWrite(); 391 392 /** 393 * Is read operation is suspended for this session. 394 * @return <code>true</code> if suspended 395 */ 396 boolean isReadSuspended(); 397 398 /** 399 * Is write operation is suspended for this session. 400 * @return <code>true</code> if suspended 401 */ 402 boolean isWriteSuspended(); 403 404 /** 405 * Update all statistical properties related with throughput assuming 406 * the specified time is the current time. By default this method returns 407 * silently without updating the throughput properties if they were 408 * calculated already within last 409 * {@link IoSessionConfig#getThroughputCalculationInterval() calculation interval}. 410 * If, however, <tt>force</tt> is specified as <tt>true</tt>, this method 411 * updates the throughput properties immediately. 412 413 * @param currentTime the current time in milliseconds 414 */ 415 void updateThroughput(long currentTime, boolean force); 416 417 /** 418 * Returns the total number of bytes which were read from this session. 419 */ 420 long getReadBytes(); 421 422 /** 423 * Returns the total number of bytes which were written to this session. 424 */ 425 long getWrittenBytes(); 426 427 /** 428 * Returns the total number of messages which were read and decoded from this session. 429 */ 430 long getReadMessages(); 431 432 /** 433 * Returns the total number of messages which were written and encoded by this session. 434 */ 435 long getWrittenMessages(); 436 437 /** 438 * Returns the number of read bytes per second. 439 */ 440 double getReadBytesThroughput(); 441 442 /** 443 * Returns the number of written bytes per second. 444 */ 445 double getWrittenBytesThroughput(); 446 447 /** 448 * Returns the number of read messages per second. 449 */ 450 double getReadMessagesThroughput(); 451 452 /** 453 * Returns the number of written messages per second. 454 */ 455 double getWrittenMessagesThroughput(); 456 457 /** 458 * Returns the number of messages which are scheduled to be written to this session. 459 */ 460 int getScheduledWriteMessages(); 461 462 /** 463 * Returns the number of bytes which are scheduled to be written to this 464 * session. 465 */ 466 long getScheduledWriteBytes(); 467 468 /** 469 * Returns the message which is being written by {@link IoService}. 470 * @return <tt>null</tt> if and if only no message is being written 471 */ 472 Object getCurrentWriteMessage(); 473 474 /** 475 * Returns the {@link WriteRequest} which is being processed by 476 * {@link IoService}. 477 * 478 * @return <tt>null</tt> if and if only no message is being written 479 */ 480 WriteRequest getCurrentWriteRequest(); 481 482 /** 483 * @return the session's creation time in milliseconds 484 */ 485 long getCreationTime(); 486 487 /** 488 * Returns the time in millis when I/O occurred lastly. 489 */ 490 long getLastIoTime(); 491 492 /** 493 * Returns the time in millis when read operation occurred lastly. 494 */ 495 long getLastReadTime(); 496 497 /** 498 * Returns the time in millis when write operation occurred lastly. 499 */ 500 long getLastWriteTime(); 501 502 /** 503 * Returns <code>true</code> if this session is idle for the specified 504 * {@link IdleStatus}. 505 */ 506 boolean isIdle(IdleStatus status); 507 508 /** 509 * Returns <code>true</code> if this session is {@link IdleStatus#READER_IDLE}. 510 * @see #isIdle(IdleStatus) 511 */ 512 boolean isReaderIdle(); 513 514 /** 515 * Returns <code>true</code> if this session is {@link IdleStatus#WRITER_IDLE}. 516 * @see #isIdle(IdleStatus) 517 */ 518 boolean isWriterIdle(); 519 520 /** 521 * Returns <code>true</code> if this session is {@link IdleStatus#BOTH_IDLE}. 522 * @see #isIdle(IdleStatus) 523 */ 524 boolean isBothIdle(); 525 526 /** 527 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 528 * for the specified {@link IdleStatus}. 529 * <p/> 530 * If <tt>sessionIdle</tt> event is fired first after some time after I/O, 531 * <tt>idleCount</tt> becomes <tt>1</tt>. <tt>idleCount</tt> resets to 532 * <tt>0</tt> if any I/O occurs again, otherwise it increases to 533 * <tt>2</tt> and so on if <tt>sessionIdle</tt> event is fired again without 534 * any I/O between two (or more) <tt>sessionIdle</tt> events. 535 */ 536 int getIdleCount(IdleStatus status); 537 538 /** 539 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 540 * for {@link IdleStatus#READER_IDLE}. 541 * @see #getIdleCount(IdleStatus) 542 */ 543 int getReaderIdleCount(); 544 545 /** 546 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 547 * for {@link IdleStatus#WRITER_IDLE}. 548 * @see #getIdleCount(IdleStatus) 549 */ 550 int getWriterIdleCount(); 551 552 /** 553 * Returns the number of the fired continuous <tt>sessionIdle</tt> events 554 * for {@link IdleStatus#BOTH_IDLE}. 555 * @see #getIdleCount(IdleStatus) 556 */ 557 int getBothIdleCount(); 558 559 /** 560 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 561 * is fired for the specified {@link IdleStatus}. 562 */ 563 long getLastIdleTime(IdleStatus status); 564 565 /** 566 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 567 * is fired for {@link IdleStatus#READER_IDLE}. 568 * @see #getLastIdleTime(IdleStatus) 569 */ 570 long getLastReaderIdleTime(); 571 572 /** 573 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 574 * is fired for {@link IdleStatus#WRITER_IDLE}. 575 * @see #getLastIdleTime(IdleStatus) 576 */ 577 long getLastWriterIdleTime(); 578 579 /** 580 * Returns the time in milliseconds when the last <tt>sessionIdle</tt> event 581 * is fired for {@link IdleStatus#BOTH_IDLE}. 582 * @see #getLastIdleTime(IdleStatus) 583 */ 584 long getLastBothIdleTime(); 585 }