| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; | 7 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
| 8 | 8 |
| 9 class _WebSocketMessageType { | 9 class _WebSocketMessageType { |
| 10 static const int NONE = 0; | 10 static const int NONE = 0; |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 Function onClosed; | 356 Function onClosed; |
| 357 } | 357 } |
| 358 | 358 |
| 359 | 359 |
| 360 class _WebSocketTransformerImpl implements WebSocketTransformer { | 360 class _WebSocketTransformerImpl implements WebSocketTransformer { |
| 361 final StreamController<WebSocket> _controller = | 361 final StreamController<WebSocket> _controller = |
| 362 new StreamController<WebSocket>(); | 362 new StreamController<WebSocket>(); |
| 363 | 363 |
| 364 Stream<WebSocket> bind(Stream<HttpRequest> stream) { | 364 Stream<WebSocket> bind(Stream<HttpRequest> stream) { |
| 365 stream.listen((request) { | 365 stream.listen((request) { |
| 366 var response = request.response; | 366 _upgrade(request) |
| 367 if (!_isWebSocketUpgrade(request)) { | 367 .then((WebSocket webSocket) => _controller.add(webSocket)) |
| 368 _controller.signalError( | 368 .catchError((error) => _controller.signalError(error)); |
| 369 new AsyncError( | |
| 370 new WebSocketException("Invalid WebSocket upgrade request"))); | |
| 371 request.listen((_) {}, onDone: () { | |
| 372 response.statusCode = HttpStatus.BAD_REQUEST; | |
| 373 response.contentLength = 0; | |
| 374 response.close(); | |
| 375 }); | |
| 376 return; | |
| 377 } | |
| 378 // Send the upgrade response. | |
| 379 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; | |
| 380 response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); | |
| 381 response.headers.add(HttpHeaders.UPGRADE, "websocket"); | |
| 382 String key = request.headers.value("Sec-WebSocket-Key"); | |
| 383 SHA1 sha1 = new SHA1(); | |
| 384 sha1.add("$key$_webSocketGUID".codeUnits); | |
| 385 String accept = _Base64._encode(sha1.close()); | |
| 386 response.headers.add("Sec-WebSocket-Accept", accept); | |
| 387 response.headers.contentLength = 0; | |
| 388 response.detachSocket() | |
| 389 .then((socket) { | |
| 390 _controller.add(new _WebSocketImpl._fromSocket(socket)); | |
| 391 }, onError: (error) { | |
| 392 _controller.signalError(error); | |
| 393 }); | |
| 394 }); | 369 }); |
| 395 | 370 |
| 396 return _controller.stream; | 371 return _controller.stream; |
| 397 } | 372 } |
| 398 | 373 |
| 399 bool _isWebSocketUpgrade(HttpRequest request) { | 374 static Future<WebSocket> _upgrade(HttpRequest request) { |
| 375 var response = request.response; |
| 376 if (!_isUpgradeRequest(request)) { |
| 377 // Send error response and drain the request. |
| 378 request.listen((_) {}, onDone: () { |
| 379 response.statusCode = HttpStatus.BAD_REQUEST; |
| 380 response.contentLength = 0; |
| 381 response.close(); |
| 382 }); |
| 383 return new Future.immediateError( |
| 384 new WebSocketException("Invalid WebSocket upgrade request")); |
| 385 } |
| 386 |
| 387 // Send the upgrade response. |
| 388 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; |
| 389 response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); |
| 390 response.headers.add(HttpHeaders.UPGRADE, "websocket"); |
| 391 String key = request.headers.value("Sec-WebSocket-Key"); |
| 392 SHA1 sha1 = new SHA1(); |
| 393 sha1.add("$key$_webSocketGUID".codeUnits); |
| 394 String accept = _Base64._encode(sha1.close()); |
| 395 response.headers.add("Sec-WebSocket-Accept", accept); |
| 396 response.headers.contentLength = 0; |
| 397 return response.detachSocket() |
| 398 .then((socket) => new _WebSocketImpl._fromSocket(socket)); |
| 399 } |
| 400 |
| 401 static bool _isUpgradeRequest(HttpRequest request) { |
| 400 if (request.method != "GET") { | 402 if (request.method != "GET") { |
| 401 return false; | 403 return false; |
| 402 } | 404 } |
| 403 if (request.headers[HttpHeaders.CONNECTION] == null) { | 405 if (request.headers[HttpHeaders.CONNECTION] == null) { |
| 404 return false; | 406 return false; |
| 405 } | 407 } |
| 406 bool isUpgrade = false; | 408 bool isUpgrade = false; |
| 407 request.headers[HttpHeaders.CONNECTION].forEach((String value) { | 409 request.headers[HttpHeaders.CONNECTION].forEach((String value) { |
| 408 if (value.toLowerCase() == "upgrade") isUpgrade = true; | 410 if (value.toLowerCase() == "upgrade") isUpgrade = true; |
| 409 }); | 411 }); |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 for (int i = 0; i < lengthBytes; i++) { | 685 for (int i = 0; i < lengthBytes; i++) { |
| 684 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF; | 686 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF; |
| 685 } | 687 } |
| 686 assert(index == headerSize); | 688 assert(index == headerSize); |
| 687 _socket.add(header); | 689 _socket.add(header); |
| 688 if (data != null) { | 690 if (data != null) { |
| 689 _socket.add(data); | 691 _socket.add(data); |
| 690 } | 692 } |
| 691 } | 693 } |
| 692 } | 694 } |
| OLD | NEW |