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