1 module hunt.http.server.WebSocketHandler;
2 
3 import hunt.http.HttpOutputStream;
4 
5 import hunt.http.WebSocketFrame;
6 import hunt.http.codec.websocket.stream.IOState;
7 import hunt.http.WebSocketConnection;
8 
9 import hunt.http.HttpRequest;
10 import hunt.http.HttpResponse;
11 import hunt.http.WebSocketPolicy;
12 
13 import hunt.http.HttpConnection;
14 
15 import hunt.logging;
16 import hunt.Functions;
17 
18 import std.conv;
19 
20 /**
21  * 
22  */
23 interface WebSocketHandler {
24      bool acceptUpgrade(HttpRequest request, HttpResponse response,
25             HttpOutputStream output, HttpConnection connection);
26     
27     // deprecated("Using onOpen instead.")
28     // alias onConnect = onOpen;
29 
30     void onOpen(WebSocketConnection connection);
31 
32     void onClosed(WebSocketConnection connection);
33 
34     WebSocketPolicy getWebSocketPolicy();
35 
36     void setWebSocketPolicy(WebSocketPolicy w);
37 
38     void onFrame(WebSocketFrame frame, WebSocketConnection connection);
39 
40     void onError(Exception t, WebSocketConnection connection);
41 }
42 
43 alias HttpEventHandler = Func4!(HttpRequest, HttpResponse, HttpOutputStream, HttpConnection, bool);
44 
45 /** 
46  * 
47  */
48 abstract class AbstractWebSocketHandler : WebSocketHandler {
49 
50     protected WebSocketPolicy defaultWebSocketPolicy;
51     protected WebSocketPolicy _webSocketPolicy;
52 
53     private HttpEventHandler _acceptUpgradeHandler;
54     private Action1!(WebSocketConnection) _openHandler;
55     private Action1!(WebSocketConnection) _closeHandler;
56     private Action2!(WebSocketFrame, WebSocketConnection) _frameHandler;
57     private Action2!(Exception, WebSocketConnection) _errorHandler;
58 
59     this() {
60         defaultWebSocketPolicy = WebSocketPolicy.newServerPolicy();
61     }
62 
63     WebSocketPolicy getWebSocketPolicy() {
64         if (_webSocketPolicy is null) {
65             return defaultWebSocketPolicy;
66         } else {
67             return _webSocketPolicy;
68         }
69     }
70 
71     void setWebSocketPolicy(WebSocketPolicy w) {
72         this._webSocketPolicy = w;
73     }
74 
75     bool acceptUpgrade(HttpRequest request, HttpResponse response,
76             HttpOutputStream output, HttpConnection connection) {
77                 
78         version (HUNT_HTTP_DEBUG) {
79             string path = request.getURI().getPath();
80             infof("The connection %s will upgrade to WebSocket on path %s",
81                 connection.getId(), path);
82         }
83 
84         if(_acceptUpgradeHandler !is null)
85             return _acceptUpgradeHandler(request, response, output, connection);
86         
87         // no handler
88         return false;
89     }
90 
91     void onOpen(WebSocketConnection connection) {
92         version (HUNT_HTTP_DEBUG) trace("Opened a connection with ", connection.getRemoteAddress());
93         if(_openHandler !is null) 
94             _openHandler(connection);
95     }
96 
97     void onClosed(WebSocketConnection connection) {
98         version (HUNT_HTTP_DEBUG) tracef("Connection %d closed: ", connection.getId(), connection.getRemoteAddress());
99         if(_closeHandler !is null) 
100             _closeHandler(connection);
101     }
102 
103     void onFrame(WebSocketFrame frame, WebSocketConnection connection) {
104         version (HUNT_HTTP_DEBUG) {
105             tracef("The WebSocket connection %s received a frame: %s",
106                     connection.getId(), frame.to!string());
107         }
108 
109         if(_frameHandler !is null)
110             _frameHandler(frame, connection);
111     }
112 
113     void onError(Exception ex, WebSocketConnection connection) {
114         version(HUNT_DEBUG) warningf("WebSocket error: ", ex.msg);
115         version(HUNT_HTTP_DEBUG) error(ex);
116         if(_errorHandler !is null)
117             _errorHandler(ex, connection);
118     }
119 
120     AbstractWebSocketHandler onAcceptUpgrade(HttpEventHandler handler) {
121         _acceptUpgradeHandler = handler;
122         return this;
123     }
124 
125     AbstractWebSocketHandler onOpen(Action1!(WebSocketConnection) handler) {
126         _openHandler = handler;
127         return this;
128     }
129 
130     AbstractWebSocketHandler onClosed(Action1!(WebSocketConnection) handler) {
131         _closeHandler = handler;
132         return this;
133     }
134 
135     AbstractWebSocketHandler onFrame(Action2!(WebSocketFrame, WebSocketConnection) handler) {
136         _frameHandler = handler;
137         return this;
138     }
139 
140     AbstractWebSocketHandler onError(Action2!(Exception, WebSocketConnection) handler) {
141         _errorHandler = handler;
142         return this;
143     }
144 }
145 
146 
147 class WebSocketHandlerAdapter : AbstractWebSocketHandler {
148     
149 }