1 module hunt.net.Connection; 2 3 import hunt.net.AsyncResult; 4 5 import hunt.io.ByteBuffer; 6 import hunt.collection.Collection; 7 import hunt.io.TcpStream; 8 import hunt.util.Common; 9 10 import core.time; 11 import std.socket; 12 13 14 deprecated("Using Connection instead.") 15 alias TcpSession = Connection; 16 deprecated("Using Connection instead.") 17 alias Session = Connection; 18 19 // alias NetEventHandler(E) = void delegate(E event); 20 // alias NetEventHandler(T, U) = void delegate(T t, U u); 21 template NetEventHandler(T...) if(T.length > 0) { 22 alias NetEventHandler = void delegate(T); 23 } 24 25 alias NetConnectHandler = NetEventHandler!Connection; 26 alias NetMessageHandler = NetEventHandler!(Connection, Object); 27 alias NetExceptionHandler = NetEventHandler!(Connection, Throwable); 28 alias NetErrorHandler = NetEventHandler!(int, Throwable); 29 // alias AsyncConnectHandler = NetEventHandler!(AsyncResult!Connection); 30 // alias AsyncVoidResultHandler = NetEventHandler!(AsyncResult!(Void)); 31 32 enum ConnectionState { 33 Ready, 34 Error, 35 Opening, 36 Opened, 37 Securing, 38 Secured, 39 // Idle, 40 // Active, 41 // Broken, 42 Closing, 43 Closed 44 } 45 46 /** 47 * <p> 48 * A handle which represents connection between two end-points regardless of 49 * transport types. 50 * </p> 51 * <p> 52 * {@link Connection} provides user-defined attributes. User-defined attributes 53 * are application-specific data which are associated with a connection. 54 * It often contains objects that represents the state of a higher-level protocol 55 * and becomes a way to exchange data between filters and handlers. 56 * </p> 57 * <h3>Adjusting Transport Type Specific Properties</h3> 58 * <p> 59 * You can simply downcast the connection to an appropriate subclass. 60 * </p> 61 * <h3>Thread Safety</h3> 62 * <p> 63 * {@link Connection} is thread-safe. But please note that performing 64 * more than one {@link #write(Object)} calls at the same time will 65 * cause the {@link IoFilter#filterWrite(IoFilter.NextFilter,Connection,WriteRequest)} 66 * to be executed simultaneously, and therefore you have to make sure the 67 * {@link IoFilter} implementations you're using are thread-safe, too. 68 * </p> 69 * <h3>Equality of Connections</h3> 70 * TODO : The getId() method is totally wrong. We can't base 71 * a method which is designed to create a unique ID on the hashCode method. 72 * {@link Object#equals(Object)} and {@link Object#hashCode()} shall not be overriden 73 * to the default behavior that is defined in {@link Object}. 74 * 75 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 76 */ 77 interface Connection : Closeable { 78 79 TcpStream getStream(); 80 81 ConnectionState getState(); 82 83 void setState(ConnectionState state); 84 85 /** 86 * @return the EventHandler which handles this connection. 87 */ 88 NetConnectionHandler getHandler(); 89 90 /** 91 * Returns the value of the user-defined attribute of this connection. 92 * 93 * @param key the key of the attribute 94 * @return <tt>null</tt> if there is no attribute with the specified key 95 */ 96 Object getAttribute(string key); 97 98 /** 99 * Returns the value of user defined attribute associated with the 100 * specified key. If there's no such attribute, the specified default 101 * value is associated with the specified key, and the default value is 102 * returned. This method is same with the following code except that the 103 * operation is performed atomically. 104 * <pre> 105 * if (containsAttribute(key)) { 106 * return getAttribute(key); 107 * } else { 108 * setAttribute(key, defaultValue); 109 * return defaultValue; 110 * } 111 * </pre> 112 * 113 * @param key the key of the attribute we want to retreive 114 * @param defaultValue the default value of the attribute 115 * @return The retrieved attribute or <tt>null</tt> if not found 116 */ 117 Object getAttribute(string key, Object defaultValue); 118 119 /** 120 * Sets a user-defined attribute. 121 * 122 * @param key the key of the attribute 123 * @param value the value of the attribute 124 * @return The old value of the attribute. <tt>null</tt> if it is new. 125 */ 126 Object setAttribute(string key, Object value); 127 128 /** 129 * Sets a user defined attribute without a value. This is useful when 130 * you just want to put a 'mark' attribute. Its value is set to 131 * {@link bool#TRUE}. 132 * 133 * @param key the key of the attribute 134 * @return The old value of the attribute. <tt>null</tt> if it is new. 135 */ 136 Object setAttribute(string key); 137 138 /** 139 * Sets a user defined attribute if the attribute with the specified key 140 * is not set yet. This method is same with the following code except 141 * that the operation is performed atomically. 142 * <pre> 143 * if (containsAttribute(key)) { 144 * return getAttribute(key); 145 * } else { 146 * return setAttribute(key, value); 147 * } 148 * </pre> 149 * 150 * @param key The key of the attribute we want to set 151 * @param value The value we want to set 152 * @return The old value of the attribute. <tt>null</tt> if not found. 153 */ 154 Object setAttributeIfAbsent(string key, Object value); 155 156 /** 157 * Sets a user defined attribute without a value if the attribute with 158 * the specified key is not set yet. This is useful when you just want to 159 * put a 'mark' attribute. Its value is set to {@link bool#TRUE}. 160 * This method is same with the following code except that the operation 161 * is performed atomically. 162 * <pre> 163 * if (containsAttribute(key)) { 164 * return getAttribute(key); // might not always be bool.TRUE. 165 * } else { 166 * return setAttribute(key); 167 * } 168 * </pre> 169 * 170 * @param key The key of the attribute we want to set 171 * @return The old value of the attribute. <tt>null</tt> if not found. 172 */ 173 Object setAttributeIfAbsent(string key); 174 175 /** 176 * Removes a user-defined attribute with the specified key. 177 * 178 * @param key The key of the attribute we want to remove 179 * @return The old value of the attribute. <tt>null</tt> if not found. 180 */ 181 Object removeAttribute(string key); 182 183 /** 184 * Removes a user defined attribute with the specified key if the current 185 * attribute value is equal to the specified value. This method is same 186 * with the following code except that the operation is performed 187 * atomically. 188 * <pre> 189 * if (containsAttribute(key) && getAttribute(key).equals(value)) { 190 * removeAttribute(key); 191 * return true; 192 * } else { 193 * return false; 194 * } 195 * </pre> 196 * 197 * @param key The key we want to remove 198 * @param value The value we want to remove 199 * @return <tt>true</tt> if the removal was successful 200 */ 201 bool removeAttribute(string key, Object value); 202 203 /** 204 * Replaces a user defined attribute with the specified key if the 205 * value of the attribute is equals to the specified old value. 206 * This method is same with the following code except that the operation 207 * is performed atomically. 208 * <pre> 209 * if (containsAttribute(key) && getAttribute(key).equals(oldValue)) { 210 * setAttribute(key, newValue); 211 * return true; 212 * } else { 213 * return false; 214 * } 215 * </pre> 216 * 217 * @param key The key we want to replace 218 * @param oldValue The previous value 219 * @param newValue The new value 220 * @return <tt>true</tt> if the replacement was successful 221 */ 222 bool replaceAttribute(string key, Object oldValue, Object newValue); 223 224 /** 225 * @param key The key of the attribute we are looking for in the connection 226 * @return <tt>true</tt> if this connection contains the attribute with 227 * the specified <tt>key</tt>. 228 */ 229 bool containsAttribute(string key); 230 231 /** 232 * @return the set of keys of all user-defined attributes. 233 */ 234 string[] getAttributeKeys(); 235 236 void encode(Object message); 237 238 // void encode(ByteBuffer[] message); 239 240 // void encode(ByteBufferOutputEntry message); 241 242 // void notifyMessageReceived(Object message); 243 244 /** 245 * Writes the specified <code>message</code> to remote peer. This 246 * operation is asynchronous; {@link IoHandler#messageSent(Connection,Object)} 247 * will be invoked when the message is actually sent to remote peer. 248 * You can also wait for the returned {@link WriteFuture} if you want 249 * to wait for the message actually written. 250 * 251 * @param message The message to write 252 * @return The associated WriteFuture 253 */ 254 void write(Object message); // It's same as void encode(Object message); 255 256 257 // void write(OutputEntry<?> entry); 258 // void write(ByteBufferOutputEntry entry); 259 260 void write(const(ubyte)[] data); 261 void write(string str); 262 void write(ByteBuffer buffer); 263 264 void write(ByteBuffer byteBuffer, Callback callback); 265 266 // void write(ByteBuffer[] buffers, Callback callback); 267 268 // void write(Collection!ByteBuffer buffers, Callback callback); 269 270 // void write(FileRegion file, Callback callback); 271 272 int getId(); 273 274 version(HUNT_METRIC) { 275 long getOpenTime(); 276 277 long getCloseTime(); 278 279 long getDuration(); 280 281 long getLastReadTime(); 282 283 long getLastWrittenTime(); 284 285 long getLastActiveTime(); 286 287 size_t getReadBytes(); 288 289 size_t getWrittenBytes(); 290 291 long getIdleTimeout(); 292 293 string toString(); 294 } 295 296 void close(); 297 298 // void closeNow(); 299 300 void shutdownOutput(); 301 302 void shutdownInput(); 303 304 // bool isOpen(); 305 306 // bool isClosed(); 307 308 /** 309 * @return <tt>true</tt> if this connection is connected with remote peer. 310 */ 311 bool isConnected(); 312 313 /** 314 * @return <tt>true</tt> if this connection is active. 315 */ 316 bool isActive(); 317 318 /** 319 * @return <tt>true</tt> if and only if this connection is being closed 320 * (but not disconnected yet) or is closed. 321 */ 322 bool isClosing(); 323 324 /** 325 * @return <tt>true</tt> if the connection has started and initialized a SslEngine, 326 * <tt>false</tt> if the connection is not yet secured (the handshake is not completed) 327 * or if SSL is not set for this connection, or if SSL is not even an option. 328 */ 329 bool isSecured(); 330 331 bool isShutdownOutput(); 332 333 bool isShutdownInput(); 334 335 bool isWaitingForClose(); 336 337 Address getLocalAddress(); 338 339 Address getRemoteAddress(); 340 341 Duration getMaxIdleTimeout(); 342 } 343 344 345 deprecated("Using NetConnectionHandler instead.") 346 alias ConnectionEventHandler = NetConnectionHandler; 347 348 alias ConnectionEventHandlerAdapter = NetConnectionHandlerAdapter; 349 350 /** 351 * Handles all I/O events on a socket connection. 352 * 353 */ 354 abstract class NetConnectionHandler { 355 356 void connectionOpened(Connection connection) ; 357 358 void connectionClosed(Connection connection) ; 359 360 void messageReceived(Connection connection, Object message) ; 361 362 void exceptionCaught(Connection connection, Throwable t) ; 363 364 void failedOpeningConnection(int connectionId, Throwable t) { } 365 366 void failedAcceptingConnection(int connectionId, Throwable t) { } 367 } 368 369 alias NetConnectionHandlerAdapter = AbstractNetConnectionHandler; 370 371 /** 372 * 373 */ 374 class AbstractNetConnectionHandler : NetConnectionHandler { 375 376 private NetConnectHandler _openedHandler; 377 private NetConnectHandler _closedHandler; 378 private NetMessageHandler _messageHandler; 379 private NetExceptionHandler _exceptionHandler; 380 private NetErrorHandler _openFailedHandler; 381 private NetErrorHandler _acceptFailedHandler; 382 383 this() { 384 385 } 386 387 /* ----------------------------- Event Handlers ----------------------------- */ 388 389 /// 390 void onOpened(NetConnectHandler handler) { 391 _openedHandler = handler; 392 } 393 394 void onClosed(NetConnectHandler handler) { 395 _closedHandler = handler; 396 } 397 398 void onMessageReceived(NetMessageHandler handler) { 399 _messageHandler = handler; 400 } 401 402 void onException(NetExceptionHandler handler) { 403 _exceptionHandler = handler; 404 } 405 406 void onOpenFailed(NetErrorHandler handler) { 407 _openFailedHandler = handler; 408 } 409 410 /* ------------------------ NetConnectionHandler APIs ----------------------- */ 411 412 /// 413 override void connectionOpened(Connection connection) { 414 if(_openedHandler !is null) 415 _openedHandler(connection); 416 } 417 418 override void connectionClosed(Connection connection) { 419 if(_closedHandler !is null) 420 _closedHandler(connection); 421 } 422 423 override void messageReceived(Connection connection, Object message) { 424 if(_messageHandler !is null) 425 _messageHandler(connection, message); 426 } 427 428 override void exceptionCaught(Connection connection, Throwable e) { 429 if(_exceptionHandler !is null) 430 _exceptionHandler(connection, e); 431 } 432 433 override void failedOpeningConnection(int connectionId, Throwable e) { 434 if(_openFailedHandler !is null) 435 _openFailedHandler(connectionId, e); 436 } 437 438 override void failedAcceptingConnection(int connectionId, Throwable e) { 439 if(_acceptFailedHandler !is null) 440 _acceptFailedHandler(connectionId, e); 441 } 442 }