Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: sdk/lib/io/websocket_impl.dart

Issue 1974043002: Revert "Fix remaining strong-mode warnings and errors in dart:io." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sdk/lib/io/websocket.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 const String _clientNoContextTakeover = "client_no_context_takeover"; 8 const String _clientNoContextTakeover = "client_no_context_takeover";
9 const String _serverNoContextTakeover = "server_no_context_takeover"; 9 const String _serverNoContextTakeover = "server_no_context_takeover";
10 const String _clientMaxWindowBits = "client_max_window_bits"; 10 const String _clientMaxWindowBits = "client_max_window_bits";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 */ 43 */
44 class _CompressionMaxWindowBits { 44 class _CompressionMaxWindowBits {
45 String headerValue; 45 String headerValue;
46 int maxWindowBits; 46 int maxWindowBits;
47 _CompressionMaxWindowBits([this.headerValue, this.maxWindowBits]); 47 _CompressionMaxWindowBits([this.headerValue, this.maxWindowBits]);
48 String toString() => headerValue; 48 String toString() => headerValue;
49 } 49 }
50 50
51 /** 51 /**
52 * The web socket protocol transformer handles the protocol byte stream 52 * The web socket protocol transformer handles the protocol byte stream
53 * which is supplied through the `handleData`. As the protocol is processed, 53 * which is supplied through the [:handleData:]. As the protocol is processed,
54 * it'll output frame data as either a List<int> or String. 54 * it'll output frame data as either a List<int> or String.
55 * 55 *
56 * Important information about usage: Be sure you use cancelOnError, so the 56 * Important information about usage: Be sure you use cancelOnError, so the
57 * socket will be closed when the processor encounter an error. Not using it 57 * socket will be closed when the processor encounter an error. Not using it
58 * will lead to undefined behaviour. 58 * will lead to undefined behaviour.
59 */ 59 */
60 // TODO(ajohnsen): make this transformer reusable? 60 // TODO(ajohnsen): make this transformer reusable?
61 class _WebSocketProtocolTransformer 61 class _WebSocketProtocolTransformer
62 implements EventSink<List<int>>, StreamTransformer< 62 implements StreamTransformer<List<int>, dynamic>, EventSink<Uint8List> {
63 List<int>, dynamic/*List<int>|_WebSocketPing|_WebSocketPong>*/> {
64 static const int START = 0; 63 static const int START = 0;
65 static const int LEN_FIRST = 1; 64 static const int LEN_FIRST = 1;
66 static const int LEN_REST = 2; 65 static const int LEN_REST = 2;
67 static const int MASK = 3; 66 static const int MASK = 3;
68 static const int PAYLOAD = 4; 67 static const int PAYLOAD = 4;
69 static const int CLOSED = 5; 68 static const int CLOSED = 5;
70 static const int FAILURE = 6; 69 static const int FAILURE = 6;
71 static const int FIN = 0x80; 70 static const int FIN = 0x80;
72 static const int RSV1 = 0x40; 71 static const int RSV1 = 0x40;
73 static const int RSV2 = 0x20; 72 static const int RSV2 = 0x20;
74 static const int RSV3 = 0x10; 73 static const int RSV3 = 0x10;
75 static const int OPCODE = 0xF; 74 static const int OPCODE = 0xF;
76 75
77 int _state = START; 76 int _state = START;
78 bool _fin = false; 77 bool _fin = false;
79 bool _compressed = false; 78 bool _compressed = false;
80 int _opcode = -1; 79 int _opcode = -1;
81 int _len = -1; 80 int _len = -1;
82 bool _masked = false; 81 bool _masked = false;
83 int _remainingLenBytes = -1; 82 int _remainingLenBytes = -1;
84 int _remainingMaskingKeyBytes = 4; 83 int _remainingMaskingKeyBytes = 4;
85 int _remainingPayloadBytes = -1; 84 int _remainingPayloadBytes = -1;
86 int _unmaskingIndex = 0; 85 int _unmaskingIndex = 0;
87 int _currentMessageType = _WebSocketMessageType.NONE; 86 int _currentMessageType = _WebSocketMessageType.NONE;
88 int closeCode = WebSocketStatus.NO_STATUS_RECEIVED; 87 int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
89 String closeReason = ""; 88 String closeReason = "";
90 89
91 EventSink<dynamic/*List<int>|_WebSocketPing|_WebSocketPong>*/> _eventSink; 90 EventSink _eventSink;
92 91
93 final bool _serverSide; 92 final bool _serverSide;
94 final List _maskingBytes = new List(4); 93 final List _maskingBytes = new List(4);
95 final BytesBuilder _payload = new BytesBuilder(copy: false); 94 final BytesBuilder _payload = new BytesBuilder(copy: false);
96 95
97 _WebSocketPerMessageDeflate _deflate; 96 _WebSocketPerMessageDeflate _deflate;
98 _WebSocketProtocolTransformer([this._serverSide = false, this._deflate]); 97 _WebSocketProtocolTransformer([this._serverSide = false, this._deflate]);
99 98
100 Stream<dynamic/*List<int>|_WebSocketPing|_WebSocketPong>*/> bind( 99 Stream bind(Stream stream) {
101 Stream<List<int>> stream) {
102 return new Stream.eventTransformed(stream, (EventSink eventSink) { 100 return new Stream.eventTransformed(stream, (EventSink eventSink) {
103 if (_eventSink != null) { 101 if (_eventSink != null) {
104 throw new StateError("WebSocket transformer already used."); 102 throw new StateError("WebSocket transformer already used.");
105 } 103 }
106 _eventSink = eventSink; 104 _eventSink = eventSink;
107 return this; 105 return this;
108 }); 106 });
109 } 107 }
110 108
111 void addError(Object error, [StackTrace stackTrace]) { 109 void addError(Object error, [StackTrace stackTrace]) {
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 class _WebSocketPing { 387 class _WebSocketPing {
390 final List<int> payload; 388 final List<int> payload;
391 _WebSocketPing([this.payload = null]); 389 _WebSocketPing([this.payload = null]);
392 } 390 }
393 391
394 class _WebSocketPong { 392 class _WebSocketPong {
395 final List<int> payload; 393 final List<int> payload;
396 _WebSocketPong([this.payload = null]); 394 _WebSocketPong([this.payload = null]);
397 } 395 }
398 396
399 typedef /*String|Future<String>*/ _ProtocolSelector(List<String> protocols);
400
401 class _WebSocketTransformerImpl implements WebSocketTransformer { 397 class _WebSocketTransformerImpl implements WebSocketTransformer {
402 final StreamController<WebSocket> _controller = 398 final StreamController<WebSocket> _controller =
403 new StreamController<WebSocket>(sync: true); 399 new StreamController<WebSocket>(sync: true);
404 final _ProtocolSelector _protocolSelector; 400 final Function _protocolSelector;
405 final CompressionOptions _compression; 401 final CompressionOptions _compression;
406 402
407 _WebSocketTransformerImpl(this._protocolSelector, this._compression); 403 _WebSocketTransformerImpl(this._protocolSelector, this._compression);
408 404
409 Stream<WebSocket> bind(Stream<HttpRequest> stream) { 405 Stream<WebSocket> bind(Stream<HttpRequest> stream) {
410 stream.listen((request) { 406 stream.listen((request) {
411 _upgrade(request, _protocolSelector, _compression) 407 _upgrade(request, _protocolSelector, _compression)
412 .then((WebSocket webSocket) => _controller.add(webSocket)) 408 .then((WebSocket webSocket) => _controller.add(webSocket))
413 .catchError(_controller.addError); 409 .catchError(_controller.addError);
414 }, onDone: () { 410 }, onDone: () {
415 _controller.close(); 411 _controller.close();
416 }); 412 });
417 413
418 return _controller.stream; 414 return _controller.stream;
419 } 415 }
420 416
421 static Future<WebSocket> _upgrade(HttpRequest request, 417 static Future<WebSocket> _upgrade(
422 _ProtocolSelector _protocolSelector, CompressionOptions compression) { 418 HttpRequest request, _protocolSelector, CompressionOptions compression) {
423 var response = request.response; 419 var response = request.response;
424 if (!_isUpgradeRequest(request)) { 420 if (!_isUpgradeRequest(request)) {
425 // Send error response. 421 // Send error response.
426 response 422 response
427 ..statusCode = HttpStatus.BAD_REQUEST 423 ..statusCode = HttpStatus.BAD_REQUEST
428 ..close(); 424 ..close();
429 return new Future.error( 425 return new Future.error(
430 new WebSocketException("Invalid WebSocket upgrade request")); 426 new WebSocketException("Invalid WebSocket upgrade request"));
431 } 427 }
432 428
433 Future<WebSocket> upgrade(String protocol) { 429 Future upgrade(String protocol) {
434 // Send the upgrade response. 430 // Send the upgrade response.
435 response 431 response
436 ..statusCode = HttpStatus.SWITCHING_PROTOCOLS 432 ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
437 ..headers.add(HttpHeaders.CONNECTION, "Upgrade") 433 ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
438 ..headers.add(HttpHeaders.UPGRADE, "websocket"); 434 ..headers.add(HttpHeaders.UPGRADE, "websocket");
439 String key = request.headers.value("Sec-WebSocket-Key"); 435 String key = request.headers.value("Sec-WebSocket-Key");
440 _SHA1 sha1 = new _SHA1(); 436 _SHA1 sha1 = new _SHA1();
441 sha1.add("$key$_webSocketGUID".codeUnits); 437 sha1.add("$key$_webSocketGUID".codeUnits);
442 String accept = _CryptoUtils.bytesToBase64(sha1.close()); 438 String accept = _CryptoUtils.bytesToBase64(sha1.close());
443 response.headers.add("Sec-WebSocket-Accept", accept); 439 response.headers.add("Sec-WebSocket-Accept", accept);
444 if (protocol != null) { 440 if (protocol != null) {
445 response.headers.add("Sec-WebSocket-Protocol", protocol); 441 response.headers.add("Sec-WebSocket-Protocol", protocol);
446 } 442 }
447 443
448 var deflate = _negotiateCompression(request, response, compression); 444 var deflate = _negotiateCompression(request, response, compression);
449 445
450 response.headers.contentLength = 0; 446 response.headers.contentLength = 0;
451 return response.detachSocket().then/*<WebSocket>*/((socket) => 447 return response.detachSocket().then((socket) =>
452 new _WebSocketImpl._fromSocket( 448 new _WebSocketImpl._fromSocket(
453 socket, protocol, compression, true, deflate)); 449 socket, protocol, compression, true, deflate));
454 } 450 }
455 451
456 var protocols = request.headers['Sec-WebSocket-Protocol']; 452 var protocols = request.headers['Sec-WebSocket-Protocol'];
457 if (protocols != null && _protocolSelector != null) { 453 if (protocols != null && _protocolSelector != null) {
458 // The suggested protocols can be spread over multiple lines, each 454 // The suggested protocols can be spread over multiple lines, each
459 // consisting of multiple protocols. To unify all of them, first join 455 // consisting of multiple protocols. To unify all of them, first join
460 // the lists with ', ' and then tokenize. 456 // the lists with ', ' and then tokenize.
461 protocols = _HttpParser._tokenizeFieldValue(protocols.join(', ')); 457 protocols = _HttpParser._tokenizeFieldValue(protocols.join(', '));
462 return new Future<String>(() => _protocolSelector(protocols)) 458 return new Future(() => _protocolSelector(protocols)).then((protocol) {
463 .then/*<String>*/((protocol) {
464 if (protocols.indexOf(protocol) < 0) { 459 if (protocols.indexOf(protocol) < 0) {
465 throw new WebSocketException( 460 throw new WebSocketException(
466 "Selected protocol is not in the list of available protocols"); 461 "Selected protocol is not in the list of available protocols");
467 } 462 }
468 return protocol; 463 return protocol;
469 }).catchError((error) { 464 }).catchError((error) {
470 response 465 response
471 ..statusCode = HttpStatus.INTERNAL_SERVER_ERROR 466 ..statusCode = HttpStatus.INTERNAL_SERVER_ERROR
472 ..close(); 467 ..close();
473 throw error; 468 throw error;
474 }).then/*<WebSocket>*/(upgrade); 469 }).then(upgrade);
475 } else { 470 } else {
476 return upgrade(null); 471 return upgrade(null);
477 } 472 }
478 } 473 }
479 474
480 static _WebSocketPerMessageDeflate _negotiateCompression(HttpRequest request, 475 static _WebSocketPerMessageDeflate _negotiateCompression(HttpRequest request,
481 HttpResponse response, CompressionOptions compression) { 476 HttpResponse response, CompressionOptions compression) {
482 var extensionHeader = request.headers.value("Sec-WebSocket-Extensions"); 477 var extensionHeader = request.headers.value("Sec-WebSocket-Extensions");
483 478
484 extensionHeader ??= ""; 479 extensionHeader ??= "";
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 ZLibOption.DEFAULT_MEM_LEVEL, 563 ZLibOption.DEFAULT_MEM_LEVEL,
569 ZLibOption.STRATEGY_DEFAULT, 564 ZLibOption.STRATEGY_DEFAULT,
570 null, 565 null,
571 true); 566 true);
572 } 567 }
573 } 568 }
574 569
575 Uint8List processIncomingMessage(List<int> msg) { 570 Uint8List processIncomingMessage(List<int> msg) {
576 _ensureDecoder(); 571 _ensureDecoder();
577 572
578 var data = <int>[]; 573 var data = [];
579 data.addAll(msg); 574 data.addAll(msg);
580 data.addAll(const [0x00, 0x00, 0xff, 0xff]); 575 data.addAll(const [0x00, 0x00, 0xff, 0xff]);
581 576
582 decoder.process(data, 0, data.length); 577 decoder.process(data, 0, data.length);
583 var result = <int>[]; 578 var result = [];
584 List<int> out; 579 var out;
585 580
586 while ((out = decoder.processed()) != null) { 581 while ((out = decoder.processed()) != null) {
587 result.addAll(out); 582 result.addAll(out);
588 } 583 }
589 584
590 if ((serverSide && clientNoContextTakeover) || 585 if ((serverSide && clientNoContextTakeover) ||
591 (!serverSide && serverNoContextTakeover)) { 586 (!serverSide && serverNoContextTakeover)) {
592 decoder = null; 587 decoder = null;
593 } 588 }
594 589
595 return new Uint8List.fromList(result); 590 return new Uint8List.fromList(result);
596 } 591 }
597 592
598 List<int> processOutgoingMessage(List<int> msg) { 593 List<int> processOutgoingMessage(List<int> msg) {
599 _ensureEncoder(); 594 _ensureEncoder();
600 var result = <int>[]; 595 var result = [];
601 Uint8List buffer; 596 Uint8List buffer;
597 var out;
602 598
603 if (msg is! Uint8List) { 599 if (msg is! Uint8List) {
604 for (var i = 0; i < msg.length; i++) { 600 for (var i = 0; i < msg.length; i++) {
605 if (msg[i] < 0 || 255 < msg[i]) { 601 if (msg[i] < 0 || 255 < msg[i]) {
606 throw new ArgumentError("List element is not a byte value " 602 throw new ArgumentError("List element is not a byte value "
607 "(value ${msg[i]} at index $i)"); 603 "(value ${msg[i]} at index $i)");
608 } 604 }
609 } 605 }
610 buffer = new Uint8List.fromList(msg); 606 buffer = new Uint8List.fromList(msg);
611 } else { 607 } else {
612 buffer = msg; 608 buffer = msg;
613 } 609 }
614 610
615 encoder.process(buffer, 0, buffer.length); 611 encoder.process(buffer, 0, buffer.length);
616 612
617 List<int> out;
618 while ((out = encoder.processed()) != null) { 613 while ((out = encoder.processed()) != null) {
619 result.addAll(out); 614 result.addAll(out);
620 } 615 }
621 616
622 if ((!serverSide && clientNoContextTakeover) || 617 if ((!serverSide && clientNoContextTakeover) ||
623 (serverSide && serverNoContextTakeover)) { 618 (serverSide && serverNoContextTakeover)) {
624 encoder = null; 619 encoder = null;
625 } 620 }
626 621
627 if (result.length > 4) { 622 if (result.length > 4) {
(...skipping 10 matching lines...) Expand all
638 final _WebSocketImpl webSocket; 633 final _WebSocketImpl webSocket;
639 EventSink<List<int>> _eventSink; 634 EventSink<List<int>> _eventSink;
640 635
641 _WebSocketPerMessageDeflate _deflateHelper; 636 _WebSocketPerMessageDeflate _deflateHelper;
642 637
643 _WebSocketOutgoingTransformer(this.webSocket) { 638 _WebSocketOutgoingTransformer(this.webSocket) {
644 _deflateHelper = webSocket._deflate; 639 _deflateHelper = webSocket._deflate;
645 } 640 }
646 641
647 Stream<List<int>> bind(Stream stream) { 642 Stream<List<int>> bind(Stream stream) {
648 return new Stream<List<int>>.eventTransformed( 643 return new Stream.eventTransformed(stream, (eventSink) {
649 stream, (EventSink<List<int>> eventSink) {
650 if (_eventSink != null) { 644 if (_eventSink != null) {
651 throw new StateError("WebSocket transformer already used"); 645 throw new StateError("WebSocket transformer already used");
652 } 646 }
653 _eventSink = eventSink; 647 _eventSink = eventSink;
654 return this; 648 return this;
655 }); 649 });
656 } 650 }
657 651
658 void add(message) { 652 void add(message) {
659 if (message is _WebSocketPong) { 653 if (message is _WebSocketPong) {
660 addFrame(_WebSocketOpcode.PONG, message.payload); 654 addFrame(_WebSocketOpcode.PONG, message.payload);
661 return; 655 return;
662 } 656 }
663 if (message is _WebSocketPing) { 657 if (message is _WebSocketPing) {
664 addFrame(_WebSocketOpcode.PING, message.payload); 658 addFrame(_WebSocketOpcode.PING, message.payload);
665 return; 659 return;
666 } 660 }
667 List<int> data; 661 List<int> data;
668 int opcode; 662 int opcode;
669 if (message != null) { 663 if (message != null) {
670 if (message is String) { 664 if (message is String) {
671 opcode = _WebSocketOpcode.TEXT; 665 opcode = _WebSocketOpcode.TEXT;
672 data = UTF8.encode(message); 666 data = UTF8.encode(message);
673 } else { 667 } else {
674 if (message is List<int>) { 668 if (message is List<int>) {
669 data = message;
675 opcode = _WebSocketOpcode.BINARY; 670 opcode = _WebSocketOpcode.BINARY;
676 data = message;
677 } else { 671 } else {
678 throw new ArgumentError(message); 672 throw new ArgumentError(message);
679 } 673 }
680 } 674 }
681 675
682 if (_deflateHelper != null) { 676 if (_deflateHelper != null) {
683 data = _deflateHelper.processOutgoingMessage(data); 677 data = _deflateHelper.processOutgoingMessage(data);
684 } 678 }
685 } else { 679 } else {
686 opcode = _WebSocketOpcode.TEXT; 680 opcode = _WebSocketOpcode.TEXT;
(...skipping 14 matching lines...) Expand all
701 data.add((code >> 8) & 0xFF); 695 data.add((code >> 8) & 0xFF);
702 data.add(code & 0xFF); 696 data.add(code & 0xFF);
703 if (reason != null) { 697 if (reason != null) {
704 data.addAll(UTF8.encode(reason)); 698 data.addAll(UTF8.encode(reason));
705 } 699 }
706 } 700 }
707 addFrame(_WebSocketOpcode.CLOSE, data); 701 addFrame(_WebSocketOpcode.CLOSE, data);
708 _eventSink.close(); 702 _eventSink.close();
709 } 703 }
710 704
711 void addFrame(int opcode, List<int> data) { 705 void addFrame(int opcode, List<int> data) => createFrame(
712 createFrame( 706 opcode,
713 opcode, 707 data,
714 data, 708 webSocket._serverSide,
715 webSocket._serverSide, 709 _deflateHelper != null &&
716 _deflateHelper != null && 710 (opcode == _WebSocketOpcode.TEXT ||
717 (opcode == _WebSocketOpcode.TEXT || 711 opcode == _WebSocketOpcode.BINARY)).forEach((e) {
718 opcode == _WebSocketOpcode.BINARY)) 712 _eventSink.add(e);
719 .forEach((e) { _eventSink.add(e); }); 713 });
720 }
721 714
722 static Iterable<List<int>> createFrame( 715 static Iterable<List<int>> createFrame(
723 int opcode, List<int> data, bool serverSide, bool compressed) { 716 int opcode, List<int> data, bool serverSide, bool compressed) {
724 bool mask = !serverSide; // Masking not implemented for server. 717 bool mask = !serverSide; // Masking not implemented for server.
725 int dataLength = data == null ? 0 : data.length; 718 int dataLength = data == null ? 0 : data.length;
726 // Determine the header size. 719 // Determine the header size.
727 int headerSize = (mask) ? 6 : 2; 720 int headerSize = (mask) ? 6 : 2;
728 if (dataLength > 65535) { 721 if (dataLength > 65535) {
729 headerSize += 8; 722 headerSize += 8;
730 } else if (dataLength > 125) { 723 } else if (dataLength > 125) {
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
1256 return code != null && 1249 return code != null &&
1257 (code < WebSocketStatus.NORMAL_CLOSURE || 1250 (code < WebSocketStatus.NORMAL_CLOSURE ||
1258 code == WebSocketStatus.RESERVED_1004 || 1251 code == WebSocketStatus.RESERVED_1004 ||
1259 code == WebSocketStatus.NO_STATUS_RECEIVED || 1252 code == WebSocketStatus.NO_STATUS_RECEIVED ||
1260 code == WebSocketStatus.ABNORMAL_CLOSURE || 1253 code == WebSocketStatus.ABNORMAL_CLOSURE ||
1261 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && 1254 (code > WebSocketStatus.INTERNAL_SERVER_ERROR &&
1262 code < WebSocketStatus.RESERVED_1015) || 1255 code < WebSocketStatus.RESERVED_1015) ||
1263 (code >= WebSocketStatus.RESERVED_1015 && code < 3000)); 1256 (code >= WebSocketStatus.RESERVED_1015 && code < 3000));
1264 } 1257 }
1265 } 1258 }
OLDNEW
« no previous file with comments | « sdk/lib/io/websocket.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698