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 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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 processor.onMessageData = _onWebSocketMessageData; | 372 processor.onMessageData = _onWebSocketMessageData; |
373 processor.onMessageEnd = _onWebSocketMessageEnd; | 373 processor.onMessageEnd = _onWebSocketMessageEnd; |
374 processor.onPing = _onWebSocketPing; | 374 processor.onPing = _onWebSocketPing; |
375 processor.onPong = _onWebSocketPong; | 375 processor.onPong = _onWebSocketPong; |
376 processor.onClosed = _onWebSocketClosed; | 376 processor.onClosed = _onWebSocketClosed; |
377 if (unparsedData != null) { | 377 if (unparsedData != null) { |
378 processor.update(unparsedData, 0, unparsedData.length); | 378 processor.update(unparsedData, 0, unparsedData.length); |
379 } | 379 } |
380 _socket.onData = () { | 380 _socket.onData = () { |
381 int available = _socket.available(); | 381 int available = _socket.available(); |
382 List<int> data = new List<int>(available); | 382 List<int> data = new List<int>.fixedLength(available); |
383 int read = _socket.readList(data, 0, available); | 383 int read = _socket.readList(data, 0, available); |
384 processor.update(data, 0, read); | 384 processor.update(data, 0, read); |
385 }; | 385 }; |
386 _socket.onClosed = () { | 386 _socket.onClosed = () { |
387 processor.closed(); | 387 processor.closed(); |
388 if (_closeSent) { | 388 if (_closeSent) { |
389 // Got socket close in response to close frame. Don't treat | 389 // Got socket close in response to close frame. Don't treat |
390 // that as an error. | 390 // that as an error. |
391 if (_closeTimer != null) _closeTimer.cancel(); | 391 if (_closeTimer != null) _closeTimer.cancel(); |
392 } else { | 392 } else { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 _sendFrame(int opcode, [List<int> data]) { | 529 _sendFrame(int opcode, [List<int> data]) { |
530 bool mask = false; // Masking not implemented for server. | 530 bool mask = false; // Masking not implemented for server. |
531 int dataLength = data == null ? 0 : data.length; | 531 int dataLength = data == null ? 0 : data.length; |
532 // Determine the header size. | 532 // Determine the header size. |
533 int headerSize = (mask) ? 6 : 2; | 533 int headerSize = (mask) ? 6 : 2; |
534 if (dataLength > 65535) { | 534 if (dataLength > 65535) { |
535 headerSize += 8; | 535 headerSize += 8; |
536 } else if (dataLength > 125) { | 536 } else if (dataLength > 125) { |
537 headerSize += 2; | 537 headerSize += 2; |
538 } | 538 } |
539 List<int> header = new List<int>(headerSize); | 539 List<int> header = new List<int>.fixedLength(headerSize); |
540 int index = 0; | 540 int index = 0; |
541 // Set FIN and opcode. | 541 // Set FIN and opcode. |
542 header[index++] = 0x80 | opcode; | 542 header[index++] = 0x80 | opcode; |
543 // Determine size and position of length field. | 543 // Determine size and position of length field. |
544 int lengthBytes = 1; | 544 int lengthBytes = 1; |
545 int firstLengthByte = 1; | 545 int firstLengthByte = 1; |
546 if (dataLength > 65535) { | 546 if (dataLength > 65535) { |
547 header[index++] = 127; | 547 header[index++] = 127; |
548 lengthBytes = 8; | 548 lengthBytes = 8; |
549 } else if (dataLength > 125) { | 549 } else if (dataLength > 125) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 response.outputStream.close(); | 594 response.outputStream.close(); |
595 return; | 595 return; |
596 } | 596 } |
597 | 597 |
598 // Send the upgrade response. | 598 // Send the upgrade response. |
599 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; | 599 response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; |
600 response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); | 600 response.headers.add(HttpHeaders.CONNECTION, "Upgrade"); |
601 response.headers.add(HttpHeaders.UPGRADE, "websocket"); | 601 response.headers.add(HttpHeaders.UPGRADE, "websocket"); |
602 String key = request.headers.value("Sec-WebSocket-Key"); | 602 String key = request.headers.value("Sec-WebSocket-Key"); |
603 SHA1 sha1 = new SHA1(); | 603 SHA1 sha1 = new SHA1(); |
604 sha1.update("$key$_webSocketGUID".charCodes); | 604 sha1.add("$key$_webSocketGUID".charCodes); |
605 String accept = _Base64._encode(sha1.digest()); | 605 String accept = _Base64._encode(sha1.close()); |
606 response.headers.add("Sec-WebSocket-Accept", accept); | 606 response.headers.add("Sec-WebSocket-Accept", accept); |
607 response.contentLength = 0; | 607 response.contentLength = 0; |
608 | 608 |
609 // Upgrade the connection and get the underlying socket. | 609 // Upgrade the connection and get the underlying socket. |
610 WebSocketConnection conn = | 610 WebSocketConnection conn = |
611 new _WebSocketConnection(response.detachSocket()); | 611 new _WebSocketConnection(response.detachSocket()); |
612 if (_onOpen != null) _onOpen(conn); | 612 if (_onOpen != null) _onOpen(conn); |
613 } | 613 } |
614 | 614 |
615 void set onOpen(callback(WebSocketConnection connection)) { | 615 void set onOpen(callback(WebSocketConnection connection)) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 Random random = new Random(); | 715 Random random = new Random(); |
716 assert(_nonce == null); | 716 assert(_nonce == null); |
717 void intToBigEndianBytes(int value, List<int> bytes, int offset) { | 717 void intToBigEndianBytes(int value, List<int> bytes, int offset) { |
718 bytes[offset] = (value >> 24) & 0xFF; | 718 bytes[offset] = (value >> 24) & 0xFF; |
719 bytes[offset + 1] = (value >> 16) & 0xFF; | 719 bytes[offset + 1] = (value >> 16) & 0xFF; |
720 bytes[offset + 2] = (value >> 8) & 0xFF; | 720 bytes[offset + 2] = (value >> 8) & 0xFF; |
721 bytes[offset + 3] = value & 0xFF; | 721 bytes[offset + 3] = value & 0xFF; |
722 } | 722 } |
723 | 723 |
724 // Generate 16 random bytes. Use the last four bytes for the hash code. | 724 // Generate 16 random bytes. Use the last four bytes for the hash code. |
725 List<int> nonce = new List<int>(16); | 725 List<int> nonce = new List<int>.fixedLength(16); |
726 for (int i = 0; i < 4; i++) { | 726 for (int i = 0; i < 4; i++) { |
727 int r = random.nextInt(0x100000000); | 727 int r = random.nextInt(0x100000000); |
728 intToBigEndianBytes(r, nonce, i * 4); | 728 intToBigEndianBytes(r, nonce, i * 4); |
729 } | 729 } |
730 _nonce = _Base64._encode(nonce); | 730 _nonce = _Base64._encode(nonce); |
731 _hash = random.nextInt(0x100000000); | 731 _hash = random.nextInt(0x100000000); |
732 } | 732 } |
733 | 733 |
734 bool _isWebSocketUpgrade(HttpClientResponse response) { | 734 bool _isWebSocketUpgrade(HttpClientResponse response) { |
735 if (response.headers[HttpHeaders.CONNECTION] == null) { | 735 if (response.headers[HttpHeaders.CONNECTION] == null) { |
736 return false; | 736 return false; |
737 } | 737 } |
738 bool isUpgrade = false; | 738 bool isUpgrade = false; |
739 response.headers[HttpHeaders.CONNECTION].forEach((String value) { | 739 response.headers[HttpHeaders.CONNECTION].forEach((String value) { |
740 if (value.toLowerCase() == "upgrade") isUpgrade = true; | 740 if (value.toLowerCase() == "upgrade") isUpgrade = true; |
741 }); | 741 }); |
742 if (!isUpgrade) return false; | 742 if (!isUpgrade) return false; |
743 String upgrade = response.headers.value(HttpHeaders.UPGRADE); | 743 String upgrade = response.headers.value(HttpHeaders.UPGRADE); |
744 if (upgrade == null || upgrade.toLowerCase() != "websocket") { | 744 if (upgrade == null || upgrade.toLowerCase() != "websocket") { |
745 return false; | 745 return false; |
746 } | 746 } |
747 String accept = response.headers.value("Sec-WebSocket-Accept"); | 747 String accept = response.headers.value("Sec-WebSocket-Accept"); |
748 if (accept == null) { | 748 if (accept == null) { |
749 return false; | 749 return false; |
750 } | 750 } |
751 SHA1 sha1 = new SHA1(); | 751 SHA1 sha1 = new SHA1(); |
752 sha1.update("$_nonce$_webSocketGUID".charCodes); | 752 sha1.add("$_nonce$_webSocketGUID".charCodes); |
753 List<int> expectedAccept = sha1.digest(); | 753 List<int> expectedAccept = sha1.close(); |
754 List<int> receivedAccept = _Base64._decode(accept); | 754 List<int> receivedAccept = _Base64._decode(accept); |
755 if (expectedAccept.length != receivedAccept.length) return false; | 755 if (expectedAccept.length != receivedAccept.length) return false; |
756 for (int i = 0; i < expectedAccept.length; i++) { | 756 for (int i = 0; i < expectedAccept.length; i++) { |
757 if (expectedAccept[i] != receivedAccept[i]) return false; | 757 if (expectedAccept[i] != receivedAccept[i]) return false; |
758 } | 758 } |
759 return true; | 759 return true; |
760 } | 760 } |
761 | 761 |
762 Function _onRequest; | 762 Function _onRequest; |
763 Function _onOpen; | 763 Function _onOpen; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 | 865 |
866 class _WebSocketCloseEvent implements CloseEvent { | 866 class _WebSocketCloseEvent implements CloseEvent { |
867 _WebSocketCloseEvent(this._wasClean, this._code, this._reason); | 867 _WebSocketCloseEvent(this._wasClean, this._code, this._reason); |
868 bool get wasClean => _wasClean; | 868 bool get wasClean => _wasClean; |
869 int get code => _code; | 869 int get code => _code; |
870 String get reason => _reason; | 870 String get reason => _reason; |
871 bool _wasClean; | 871 bool _wasClean; |
872 int _code; | 872 int _code; |
873 String _reason; | 873 String _reason; |
874 } | 874 } |
OLD | NEW |