| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Web socket status codes used when closing a web socket connection. | 8 * Web socket status codes used when closing a web socket connection. |
| 9 */ | 9 */ |
| 10 abstract class WebSocketStatus { | 10 abstract class WebSocketStatus { |
| 11 static const int NORMAL_CLOSURE = 1000; | 11 static const int NORMAL_CLOSURE = 1000; |
| 12 static const int GOING_AWAY = 1001; | 12 static const int GOING_AWAY = 1001; |
| 13 static const int PROTOCOL_ERROR = 1002; | 13 static const int PROTOCOL_ERROR = 1002; |
| 14 static const int UNSUPPORTED_DATA = 1003; | 14 static const int UNSUPPORTED_DATA = 1003; |
| 15 static const int RESERVED_1004 = 1004; | 15 static const int RESERVED_1004 = 1004; |
| 16 static const int NO_STATUS_RECEIVED = 1005; | 16 static const int NO_STATUS_RECEIVED = 1005; |
| 17 static const int ABNORMAL_CLOSURE = 1006; | 17 static const int ABNORMAL_CLOSURE = 1006; |
| 18 static const int INVALID_FRAME_PAYLOAD_DATA = 1007; | 18 static const int INVALID_FRAME_PAYLOAD_DATA = 1007; |
| 19 static const int POLICY_VIOLATION = 1008; | 19 static const int POLICY_VIOLATION = 1008; |
| 20 static const int MESSAGE_TOO_BIG = 1009; | 20 static const int MESSAGE_TOO_BIG = 1009; |
| 21 static const int MISSING_MANDATORY_EXTENSION = 1010; | 21 static const int MISSING_MANDATORY_EXTENSION = 1010; |
| 22 static const int INTERNAL_SERVER_ERROR = 1011; | 22 static const int INTERNAL_SERVER_ERROR = 1011; |
| 23 static const int RESERVED_1015 = 1015; | 23 static const int RESERVED_1015 = 1015; |
| 24 } | 24 } |
| 25 | 25 |
| 26 /** | 26 /** |
| 27 * The web socket protocol is implemented by a HTTP or HTTPS server handler | 27 * The [WebSocketTransformer] is implemented as a stream transformer that |
| 28 * which can be instantiated like this: | 28 * transforms a stream of HttpRequest into a stream of WebSockets by upgrading |
| 29 * each HttpRequest from the HTTP or HTTPS server, to the WebSocket protocol. |
| 29 * | 30 * |
| 30 * WebSocketHandler wsHandler = new WebSocketHandler(); | 31 * Example of usage: |
| 31 * | 32 * |
| 32 * and then its onRequest method can be assigned to the HTTP server, e.g. | 33 * server.transform(new WebSocketTransformer()).listen((webSocket) => ...); |
| 33 * | |
| 34 * server.defaultHandler = wsHandler.onRequest; | |
| 35 * | 34 * |
| 36 * or | 35 * or |
| 37 * | 36 * |
| 38 * server.addRequestHandler((req) => req.path == "/ws", | 37 * server |
| 39 * wsHandler.onRequest); | 38 * .where((request) => request.uri.scheme == "ws") |
| 39 * .transform(new WebSocketTransformer()).listen((webSocket) => ...); |
| 40 * | 40 * |
| 41 * This handler strives to implement web sockets as specified by RFC6455. | 41 * This transformer strives to implement web sockets as specified by RFC6455. |
| 42 */ | 42 */ |
| 43 abstract class WebSocketHandler { | 43 abstract class WebSocketTransformer |
| 44 factory WebSocketHandler() => new _WebSocketHandler(); | 44 implements StreamTransformer<HttpRequest, WebSocket> { |
| 45 | 45 factory WebSocketTransformer() => new _WebSocketTransformerImpl(); |
| 46 /** | |
| 47 * Request handler to be registered with the HTTP server. | |
| 48 */ | |
| 49 void onRequest(HttpRequest request, HttpResponse response); | |
| 50 | |
| 51 /** | |
| 52 * Sets the callback to be called when a new web socket connection | |
| 53 * has been established. | |
| 54 */ | |
| 55 void set onOpen(callback(WebSocketConnection connection)); | |
| 56 } | 46 } |
| 57 | 47 |
| 58 | 48 |
| 59 /** | |
| 60 * Server web socket connection. | |
| 61 */ | |
| 62 abstract class WebSocketConnection { | |
| 63 /** | |
| 64 * Sets the callback to be called when a message has been | |
| 65 * received. The type on [message] is either [:String:] or | |
| 66 * [:List<int>:] depending on whether it is a text or binary | |
| 67 * message. If the message is empty [message] will be [:null:]. | |
| 68 * If [message] is a [:List<int>:] then it will contain byte values | |
| 69 * from 0 to 255. | |
| 70 */ | |
| 71 void set onMessage(void callback(message)); | |
| 72 | |
| 73 /** | |
| 74 * Sets the callback to be called when the web socket connection is | |
| 75 * closed. [status] indicate the reason for closing. For network | |
| 76 * errors the value of [status] will be | |
| 77 * WebSocketStatus.ABNORMAL_CLOSURE]. In this callback it is | |
| 78 * possible to call [close] if [close] has not already been called. | |
| 79 * If [close] has still not been called after the close callback | |
| 80 * returns the received close status will automatically be echoed | |
| 81 * back to the other end to finish the close handshake. | |
| 82 */ | |
| 83 void set onClosed(void callback(int status, String reason)); | |
| 84 | |
| 85 /** | |
| 86 * Sends a message. The [message] must be a [:String:], a | |
| 87 * [:List<int>:] containing bytes, or [:null:]. | |
| 88 */ | |
| 89 send(Object message); | |
| 90 | |
| 91 /** | |
| 92 * Close the web socket connection. The default value for [status] | |
| 93 * and [reason] are [:null:]. | |
| 94 */ | |
| 95 close([int status, String reason]); | |
| 96 } | |
| 97 | |
| 98 | |
| 99 /** | |
| 100 * Client web socket connection. | |
| 101 */ | |
| 102 abstract class WebSocketClientConnection { | |
| 103 /** | |
| 104 * Creates a new web socket client connection based on a HTTP(S) client | |
| 105 * connection. The HTTP or HTTPS client connection must be freshly opened. | |
| 106 */ | |
| 107 factory WebSocketClientConnection(HttpClientConnection conn, | |
| 108 [List<String> protocols]) { | |
| 109 return new _WebSocketClientConnection(conn, protocols); | |
| 110 } | |
| 111 | |
| 112 /** | |
| 113 * Sets the callback to be called when the request object for the | |
| 114 * opening handshake request is ready. This callback can be used if | |
| 115 * one needs to add additional headers to the opening handshake | |
| 116 * request. | |
| 117 */ | |
| 118 void set onRequest(void callback(HttpClientRequest request)); | |
| 119 | |
| 120 /** | |
| 121 * Sets the callback to be called when a web socket connection has | |
| 122 * been established. | |
| 123 */ | |
| 124 void set onOpen(void callback()); | |
| 125 | |
| 126 /** | |
| 127 * Sets the callback to be called when a message has been | |
| 128 * received. The type of [message] is either [:String:] or | |
| 129 * [:List<int>:], depending on whether it is a text or binary | |
| 130 * message. If the message is empty [message] will be [:null:]. | |
| 131 * If the message is a [:List<int>:] then it will contain byte values | |
| 132 * from 0 to 255. | |
| 133 */ | |
| 134 void set onMessage(void callback(message)); | |
| 135 | |
| 136 /** | |
| 137 * Sets the callback to be called when the web socket connection is | |
| 138 * closed. [status] indicates the reason for closing. For network | |
| 139 * errors the value of [status] will be | |
| 140 * WebSocketStatus.ABNORMAL_CLOSURE]. | |
| 141 */ | |
| 142 void set onClosed(void callback(int status, String reason)); | |
| 143 | |
| 144 /** | |
| 145 * Sets the callback to be called when the response object for the | |
| 146 * opening handshake did not cause a web socket connection | |
| 147 * upgrade. This will be called in case the response status code is | |
| 148 * not 101 (Switching Protocols). If this callback is not set and the | |
| 149 * server does not upgrade the connection, the [:onError:] callback will | |
| 150 * be called. | |
| 151 */ | |
| 152 void set onNoUpgrade(void callback(HttpClientResponse response)); | |
| 153 | |
| 154 /** | |
| 155 * Sends a message. The [message] must be a [:String:] or a | |
| 156 * [:List<int>:] containing bytes. To send an empty message send either | |
| 157 * an empty [:String:] or an empty [:List<int>:]. [:null:] cannot be sent. | |
| 158 */ | |
| 159 send(message); | |
| 160 | |
| 161 /** | |
| 162 * Close the web socket connection. The default value for [status] | |
| 163 * and [reason] are [:null:]. | |
| 164 */ | |
| 165 close([int status, String reason]); | |
| 166 } | |
| 167 | |
| 168 | |
| 169 /** | 49 /** |
| 170 * Base class for the events generated by the W3C complient browser | 50 * Base class for the events generated by the W3C complient browser |
| 171 * API for web sockets. | 51 * API for web sockets. |
| 172 */ | 52 */ |
| 173 abstract class Event { } | 53 abstract class Event { } |
| 174 | 54 |
| 175 /** | 55 /** |
| 176 * Event delivered when there is data on a web socket connection. | 56 * Event delivered when there is data on a web socket connection. |
| 177 */ | 57 */ |
| 178 abstract class MessageEvent extends Event { | 58 abstract class MessageEvent extends Event { |
| 179 /** | 59 /** |
| 180 * The type of [message] is either [:String:] or [:List<int>:] | 60 * The type of [message] is either [:String:] or [:List<int>:] |
| 181 * depending on whether it is a text or binary message. If the | 61 * depending on whether it is a text or binary message. If the |
| 182 * message is empty [message] will be [:null:] | 62 * message is empty [message] will be [:null:] |
| 183 * If the message is a [:List<int>:] then it will contain byte values | 63 * If the message is a [:List<int>:] then it will contain byte values |
| 184 * from 0 to 255. | 64 * from 0 to 255. |
| 185 | |
| 186 */ | 65 */ |
| 187 get data; | 66 get data; |
| 188 } | 67 } |
| 189 | 68 |
| 190 | 69 |
| 191 /** | 70 /** |
| 192 * Event delivered when a web socket connection is closed. | 71 * Event delivered when a web socket connection is closed. |
| 193 */ | 72 */ |
| 194 abstract class CloseEvent extends Event { | 73 abstract class CloseEvent extends Event { |
| 195 /** | 74 /** |
| (...skipping 13 matching lines...) Expand all Loading... |
| 209 */ | 88 */ |
| 210 String get reason; | 89 String get reason; |
| 211 } | 90 } |
| 212 | 91 |
| 213 | 92 |
| 214 /** | 93 /** |
| 215 * Alternative web socket client interface. This interface is compliant | 94 * Alternative web socket client interface. This interface is compliant |
| 216 * with the W3C browser API for web sockets specified in | 95 * with the W3C browser API for web sockets specified in |
| 217 * http://dev.w3.org/html5/websockets/. | 96 * http://dev.w3.org/html5/websockets/. |
| 218 */ | 97 */ |
| 219 abstract class WebSocket { | 98 abstract class WebSocket implements Stream<Event> { |
| 220 /** | 99 /** |
| 221 * Possible states of the connection. | 100 * Possible states of the connection. |
| 222 */ | 101 */ |
| 223 static const int CONNECTING = 0; | 102 static const int CONNECTING = 0; |
| 224 static const int OPEN = 1; | 103 static const int OPEN = 1; |
| 225 static const int CLOSING = 2; | 104 static const int CLOSING = 2; |
| 226 static const int CLOSED = 3; | 105 static const int CLOSED = 3; |
| 227 | 106 |
| 228 /** | 107 /** |
| 229 * Create a new web socket connection. The URL supplied in [url] | 108 * Create a new web socket connection. The URL supplied in [url] |
| 230 * must use the scheme [:ws:]. The [protocols] argument is either a | 109 * must use the scheme [:ws:] or [:wss:]. The [protocols] argument is either |
| 231 * [:String:] or [:List<String>:] specifying the subprotocols the | 110 * a [:String:] or [:List<String>:] specifying the subprotocols the |
| 232 * client is willing to speak. | 111 * client is willing to speak. |
| 233 */ | 112 */ |
| 234 factory WebSocket(String url, [protocols]) => new _WebSocket(url, protocols); | 113 static Future<WebSocket> connect(String url, [protocols]) => |
| 114 _WebSocketImpl.connect(url, protocols); |
| 235 | 115 |
| 236 /** | 116 /** |
| 237 * Returns the current state of the connection. | 117 * Returns the current state of the connection. |
| 238 */ | 118 */ |
| 239 int get readyState; | 119 int get readyState; |
| 240 | 120 |
| 241 /** | 121 /** |
| 242 * Returns the number of bytes currently buffered for transmission. | 122 * Returns the number of bytes currently buffered for transmission. |
| 243 */ | 123 */ |
| 244 int get bufferedAmount; | 124 int get bufferedAmount; |
| 245 | 125 |
| 246 /** | 126 /** |
| 247 * Sets the callback to be called when a web socket connection has | |
| 248 * been established. | |
| 249 */ | |
| 250 void set onopen(void callback()); | |
| 251 | |
| 252 /** | |
| 253 * Sets the callback to be called when the web socket connection | |
| 254 * encountered an error. | |
| 255 */ | |
| 256 void set onerror(void callback(e)); | |
| 257 | |
| 258 /** | |
| 259 * Sets the callback to be called when the web socket connection is | |
| 260 * closed. | |
| 261 */ | |
| 262 void set onclose(void callback(CloseEvent event)); | |
| 263 | |
| 264 /** | |
| 265 * The extensions property is initially the empty string. After the | 127 * The extensions property is initially the empty string. After the |
| 266 * web socket connection is established this string reflects the | 128 * web socket connection is established this string reflects the |
| 267 * extensions used by the server. | 129 * extensions used by the server. |
| 268 */ | 130 */ |
| 269 String get extensions; | 131 String get extensions; |
| 270 | 132 |
| 271 /** | 133 /** |
| 272 * The protocol property is initially the empty string. After the | 134 * The protocol property is initially the empty string. After the |
| 273 * web socket connection is established the value is the subprotocol | 135 * web socket connection is established the value is the subprotocol |
| 274 * selected by the server. If no subprotocol is negotiated the | 136 * selected by the server. If no subprotocol is negotiated the |
| 275 * value will remain [:null:]. | 137 * value will remain [:null:]. |
| 276 */ | 138 */ |
| 277 String get protocol; | 139 String get protocol; |
| 278 | 140 |
| 279 /** | 141 /** |
| 280 * Closes the web socket connection. | 142 * Closes the web socket connection. |
| 281 */ | 143 */ |
| 282 void close(int code, String reason); | 144 void close([int code, String reason]); |
| 283 | |
| 284 /** | |
| 285 * Sets the callback to be called when a message has been | |
| 286 * received. | |
| 287 */ | |
| 288 void set onmessage(void callback(MessageEvent event)); | |
| 289 | 145 |
| 290 /** | 146 /** |
| 291 * Sends data on the web socket connection. The data in [data] must | 147 * Sends data on the web socket connection. The data in [data] must |
| 292 * be either a [:String:], or a [:List<int>:] holding bytes. | 148 * be either a [:String:], or a [:List<int>:] holding bytes. |
| 293 */ | 149 */ |
| 294 void send(data); | 150 void send(data); |
| 295 } | 151 } |
| 296 | 152 |
| 297 | 153 |
| 298 class WebSocketException implements Exception { | 154 class WebSocketException implements Exception { |
| 299 const WebSocketException([String this.message = ""]); | 155 const WebSocketException([String this.message = ""]); |
| 300 String toString() => "WebSocketException: $message"; | 156 String toString() => "WebSocketException: $message"; |
| 301 final String message; | 157 final String message; |
| 302 } | 158 } |
| OLD | NEW |