1 modulehunt.http.WebSocketConnection;
2 3 importhunt.http.HttpRequest;
4 importhunt.http.HttpResponse;
5 importhunt.http.codec.websocket.stream.IOState;
6 importhunt.http.WebSocketFrame;
7 importhunt.http.WebSocketPolicy;
8 importhunt.http.HttpConnection;
9 10 importhunt.io.ByteBuffer;
11 importhunt.concurrency.FuturePromise;
12 importhunt.Exceptions;
13 importhunt.Functions;
14 importhunt.logging;
15 importhunt.net.Connection;
16 importhunt.util.Common;
17 18 19 deprecated("Using WebSocketConnectionState instead.")
20 aliasConnectionState = WebSocketConnectionState;
21 22 /**
23 * Connection states as outlined in <a href="https://tools.ietf.org/html/rfc6455">RFC6455</a>.
24 */25 enumWebSocketConnectionState {
26 Unknown,
27 28 /**
29 * [RFC] Initial state of a connection, the upgrade request / response is in progress
30 */31 CONNECTING,
32 /**
33 * [Impl] Intermediate state between CONNECTING and OPEN, used to indicate that a upgrade request/response is successful, but the end-user provided socket's
34 * onOpen code has yet to run.
35 * <p>
36 * This state is to allow the local socket to initiate messages and frames, but to NOT start reading yet.
37 */38 CONNECTED,
39 /**
40 * [RFC] The websocket connection is established and open.
41 * <p>
42 * This indicates that the Upgrade has succeed, and the end-user provided socket's onOpen code has completed.
43 * <p>
44 * It is now time to start reading from the remote endpoint.
45 */46 OPEN,
47 /**
48 * [RFC] The websocket closing handshake is started.
49 * <p>
50 * This can be considered a half-closed state.
51 * <p>
52 * When receiving this as an event on {@link ConnectionStateListener#onConnectionStateChange(ConnectionState)} a close frame should be sent using
53 * the {@link CloseInfo} available from {@link IOState#getCloseInfo()}
54 */55 CLOSING,
56 /**
57 * [RFC] The websocket connection is closed.
58 * <p>
59 * Connection should be disconnected and no further reads or writes should occur.
60 */61 CLOSED62 }
63 64 65 /**
66 * Interface for dealing with Incoming Frames.
67 */68 interfaceIncomingFrames {
69 70 voidincomingError(Exceptiont);
71 72 /**
73 * Process the incoming frame.
74 * <p>
75 * Note: if you need to hang onto any information from the frame, be sure
76 * to copy it, as the information contained in the Frame will be released
77 * and/or reused by the implementation.
78 *
79 * @param frame the frame to process
80 */81 voidincomingFrame(WebSocketFrameframe);
82 }
83 84 85 /**
86 * Interface for dealing with frames outgoing to (eventually) the network layer.
87 */88 interfaceOutgoingFrames {
89 /**
90 * A frame, and optional callback, intended for the network layer.
91 * <p>
92 * Note: the frame can undergo many transformations in the various
93 * layers and extensions present in the implementation.
94 * <p>
95 * If you are implementing a mutation, you are obliged to handle
96 * the incoming WriteCallback appropriately.
97 *
98 * @param frame the frame to eventually write to the network layer.
99 * @param callback the callback to notify when the frame is written.
100 */101 voidoutgoingFrame(WebSocketFrameframe, Callbackcallback);
102 103 }
104 105 106 /**
107 *
108 */109 interfaceWebSocketConnection : OutgoingFrames, HttpConnection {
110 111 /**
112 * Register the connection close callback.
113 *
114 * @param closedListener The connection close callback.
115 * @return The WebSocket connection.
116 */117 // WebSocketConnection onClose(Action1!(WebSocketConnection) closedListener);118 119 /**
120 * Register the exception callback.
121 *
122 * @param exceptionListener The exception callback.
123 * @return The WebSocket connection.
124 */125 // WebSocketConnection onException(Action2!(WebSocketConnection, Exception) exceptionListener);126 127 /**
128 * Get the read/write idle timeout.
129 *
130 * @return the idle timeout in milliseconds
131 */132 // long getIdleTimeout();133 134 boolisConnected();
135 136 /**
137 * Get the IOState of the connection.
138 *
139 * @return the IOState of the connection.
140 */141 IOStategetIOState();
142 143 /**
144 * The policy that the connection is running under.
145 *
146 * @return the policy for the connection
147 */148 WebSocketPolicygetPolicy();
149 150 /**
151 * Generate random 4bytes mask key
152 *
153 * @return the mask key
154 */155 byte[] generateMask();
156 157 /**
158 * Send text message.
159 *
160 * @param text The text message.
161 * @return The future result.
162 */163 FuturePromise!(bool) sendText(stringtext);
164 165 /**
166 * Send binary message.
167 *
168 * @param data The binary message.
169 * @return The future result.
170 */171 FuturePromise!(bool) sendData(byte[] data);
172 173 /**
174 * Send binary message.
175 *
176 * @param data The binary message.
177 * @return The future result.
178 */179 FuturePromise!(bool) sendData(ByteBufferdata);
180 181 /**
182 * Get the websocket upgrade request.
183 *
184 * @return The upgrade request.
185 */186 HttpRequestgetUpgradeRequest();
187 188 /**
189 * Get the websocket upgrade response.
190 *
191 * @return The upgrade response.
192 */193 HttpResponsegetUpgradeResponse();
194 195 finalstringgetPath() {
196 returngetUpgradeRequest().getURI().getPath();
197 }
198 199 }
200 201 202 /**
203 *
204 */205 interfaceWebSocketMessageHandler {
206 207 voidonOpen(WebSocketConnectionconnection);
208 209 voidonClosed(WebSocketConnectionconnection); // CloseStatus closeStatus210 211 voidonPing(WebSocketConnectionconnection);
212 213 voidonPong(WebSocketConnectionconnection);
214 215 voidonText(WebSocketConnectionconnection, stringtext);
216 217 voidonBinary(WebSocketConnectionconnection, ByteBufferbuffer);
218 219 voidonContinuation(WebSocketConnectionconnection, ByteBufferbuffer);
220 221 voidonError(WebSocketConnectionconnection, Exceptionexception);
222 223 aliasonFailure = onError;
224 }
225 226 /**
227 * See_Also:
228 * WebSocketListener from OKHTTP3
229 */230 abstractclassAbstractWebSocketMessageHandler : WebSocketMessageHandler {
231 232 voidonOpen(WebSocketConnectionconnection) { implementationMissing(false); }
233 234 voidonClosed(WebSocketConnectionconnection) {
235 version(HUNT_HTTP_DEBUG) infof("closed with %s", connection.getRemoteAddress());
236 }
237 238 voidonPing(WebSocketConnectionconnection) {
239 version(HUNT_HTTP_DEBUG) tracef("ping from %s", connection.getRemoteAddress());
240 }
241 242 voidonPong(WebSocketConnectionconnection) {
243 version(HUNT_HTTP_DEBUG) tracef("ping from %s", connection.getRemoteAddress());
244 }
245 246 voidonText(WebSocketConnectionconnection, stringtext) {
247 version(HUNT_HTTP_DEBUG) tracef("received (from %s): %s", connection.getRemoteAddress(), text);
248 }
249 250 voidonBinary(WebSocketConnectionconnection, ByteBufferbuffer) { implementationMissing(false); }
251 252 voidonContinuation(WebSocketConnectionconnection, ByteBufferbuffer) { implementationMissing(false); }
253 254 voidonError(WebSocketConnectionconnection, Exceptionex) {
255 debugwarningf("error (from %s): %s", connection.getRemoteAddress(), ex.msg);
256 version(HUNT_DEBUG) warning(ex);
257 }
258 }