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