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 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 int byte = buffer[index]; | 126 int byte = buffer[index]; |
127 if (_state <= LEN_REST) { | 127 if (_state <= LEN_REST) { |
128 if (_state == START) { | 128 if (_state == START) { |
129 _fin = (byte & FIN) != 0; | 129 _fin = (byte & FIN) != 0; |
130 | 130 |
131 if((byte & (RSV2 | RSV3)) != 0) { | 131 if((byte & (RSV2 | RSV3)) != 0) { |
132 // The RSV2, RSV3 bits must both be zero. | 132 // The RSV2, RSV3 bits must both be zero. |
133 throw new WebSocketException("Protocol error"); | 133 throw new WebSocketException("Protocol error"); |
134 } | 134 } |
135 | 135 |
136 if ((byte & RSV1) != 0) { | 136 _opcode = (byte & OPCODE); |
137 _compressed = true; | 137 |
138 } else { | 138 if (_opcode != _WebSocketOpcode.CONTINUATION) { |
139 _compressed = false; | 139 if ((byte & RSV1) != 0) { |
| 140 _compressed = true; |
| 141 } else { |
| 142 _compressed = false; |
| 143 } |
140 } | 144 } |
141 _opcode = (byte & OPCODE); | |
142 | 145 |
143 if (_opcode <= _WebSocketOpcode.BINARY) { | 146 if (_opcode <= _WebSocketOpcode.BINARY) { |
144 if (_opcode == _WebSocketOpcode.CONTINUATION) { | 147 if (_opcode == _WebSocketOpcode.CONTINUATION) { |
145 if (_currentMessageType == _WebSocketMessageType.NONE) { | 148 if (_currentMessageType == _WebSocketMessageType.NONE) { |
146 throw new WebSocketException("Protocol error"); | 149 throw new WebSocketException("Protocol error"); |
147 } | 150 } |
148 } else { | 151 } else { |
149 assert(_opcode == _WebSocketOpcode.TEXT || | 152 assert(_opcode == _WebSocketOpcode.TEXT || |
150 _opcode == _WebSocketOpcode.BINARY); | 153 _opcode == _WebSocketOpcode.BINARY); |
151 if (_currentMessageType != _WebSocketMessageType.NONE) { | 154 if (_currentMessageType != _WebSocketMessageType.NONE) { |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 } | 563 } |
561 | 564 |
562 Uint8List processIncomingMessage(List<int> msg) { | 565 Uint8List processIncomingMessage(List<int> msg) { |
563 _ensureDecoder(); | 566 _ensureDecoder(); |
564 | 567 |
565 var data = []; | 568 var data = []; |
566 data.addAll(msg); | 569 data.addAll(msg); |
567 data.addAll(const [0x00, 0x00, 0xff, 0xff]); | 570 data.addAll(const [0x00, 0x00, 0xff, 0xff]); |
568 | 571 |
569 decoder.process(data, 0, data.length); | 572 decoder.process(data, 0, data.length); |
570 var reuse = | |
571 !(serverSide ? clientNoContextTakeover : serverNoContextTakeover); | |
572 var result = []; | 573 var result = []; |
573 var out; | 574 var out; |
574 | 575 |
575 while ((out = decoder.processed(flush: reuse)) != null) { | 576 while ((out = decoder.processed()) != null) { |
576 result.addAll(out); | 577 result.addAll(out); |
577 } | 578 } |
578 | 579 |
579 decoder.processed(flush: reuse); | |
580 | |
581 if (!reuse) { | |
582 decoder.end(); | |
583 decoder = null; | |
584 } | |
585 return new Uint8List.fromList(result); | 580 return new Uint8List.fromList(result); |
586 } | 581 } |
587 | 582 |
588 List<int> processOutgoingMessage(List<int> msg) { | 583 List<int> processOutgoingMessage(List<int> msg) { |
589 _ensureEncoder(); | 584 _ensureEncoder(); |
590 var reuse = | |
591 !(serverSide ? serverNoContextTakeover : clientNoContextTakeover); | |
592 var result = []; | 585 var result = []; |
593 Uint8List buffer; | 586 Uint8List buffer; |
594 var out; | 587 var out; |
595 | 588 |
596 if (msg is! Uint8List) { | 589 if (msg is! Uint8List) { |
597 for (var i = 0; i < msg.length; i++) { | 590 for (var i = 0; i < msg.length; i++) { |
598 if (msg[i] < 0 || 255 < msg[i]) { | 591 if (msg[i] < 0 || 255 < msg[i]) { |
599 throw new ArgumentError("List element is not a byte value " | 592 throw new ArgumentError("List element is not a byte value " |
600 "(value ${msg[i]} at index $i)"); | 593 "(value ${msg[i]} at index $i)"); |
601 } | 594 } |
602 } | 595 } |
603 buffer = new Uint8List.fromList(msg); | 596 buffer = new Uint8List.fromList(msg); |
604 } else { | 597 } else { |
605 buffer = msg; | 598 buffer = msg; |
606 } | 599 } |
607 | 600 |
608 encoder.process(buffer, 0, buffer.length); | 601 encoder.process(buffer, 0, buffer.length); |
609 | 602 |
610 while ((out = encoder.processed(flush: reuse)) != null) { | 603 while ((out = encoder.processed()) != null) { |
611 result.addAll(out); | 604 result.addAll(out); |
612 } | 605 } |
613 | 606 |
614 if (serverSide ? serverNoContextTakeover : clientNoContextTakeover) { | |
615 encoder.end(); | |
616 encoder = null; | |
617 } | |
618 | |
619 if (result.length > 4) { | 607 if (result.length > 4) { |
620 result = result.sublist(0, result.length - 4); | 608 result = result.sublist(0, result.length - 4); |
621 } | 609 } |
622 | 610 |
623 return result; | 611 return result; |
624 } | 612 } |
625 } | 613 } |
626 | 614 |
627 // TODO(ajohnsen): Make this transformer reusable. | 615 // TODO(ajohnsen): Make this transformer reusable. |
628 class _WebSocketOutgoingTransformer implements StreamTransformer, EventSink { | 616 class _WebSocketOutgoingTransformer implements StreamTransformer, EventSink { |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 return code != null && | 1229 return code != null && |
1242 (code < WebSocketStatus.NORMAL_CLOSURE || | 1230 (code < WebSocketStatus.NORMAL_CLOSURE || |
1243 code == WebSocketStatus.RESERVED_1004 || | 1231 code == WebSocketStatus.RESERVED_1004 || |
1244 code == WebSocketStatus.NO_STATUS_RECEIVED || | 1232 code == WebSocketStatus.NO_STATUS_RECEIVED || |
1245 code == WebSocketStatus.ABNORMAL_CLOSURE || | 1233 code == WebSocketStatus.ABNORMAL_CLOSURE || |
1246 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && | 1234 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && |
1247 code < WebSocketStatus.RESERVED_1015) || | 1235 code < WebSocketStatus.RESERVED_1015) || |
1248 (code >= WebSocketStatus.RESERVED_1015 && code < 3000)); | 1236 (code >= WebSocketStatus.RESERVED_1015 && code < 3000)); |
1249 } | 1237 } |
1250 } | 1238 } |
OLD | NEW |