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

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

Issue 130913010: Use a list of Uint8List-views instead of a BytesBuilder, to build up websocket messages. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 8
9 // Matches _WebSocketOpcode. 9 // Matches _WebSocketOpcode.
10 class _WebSocketMessageType { 10 class _WebSocketMessageType {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 int _remainingPayloadBytes = -1; 62 int _remainingPayloadBytes = -1;
63 int _unmaskingIndex = 0; 63 int _unmaskingIndex = 0;
64 int _currentMessageType = _WebSocketMessageType.NONE; 64 int _currentMessageType = _WebSocketMessageType.NONE;
65 int closeCode = WebSocketStatus.NO_STATUS_RECEIVED; 65 int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
66 String closeReason = ""; 66 String closeReason = "";
67 67
68 EventSink _eventSink; 68 EventSink _eventSink;
69 69
70 final bool _serverSide; 70 final bool _serverSide;
71 final List _maskingBytes = new List(4); 71 final List _maskingBytes = new List(4);
72 final BytesBuilder _payload = new BytesBuilder(); 72 final List<Uint8List> _payloads = new List<Uint8List>();
73 73
74 _WebSocketProtocolTransformer([this._serverSide = false]); 74 _WebSocketProtocolTransformer([this._serverSide = false]);
75 75
76 Stream bind(Stream stream) { 76 Stream bind(Stream stream) {
77 return new Stream.eventTransformed( 77 return new Stream.eventTransformed(
78 stream, 78 stream,
79 (EventSink eventSink) { 79 (EventSink eventSink) {
80 if (_eventSink != null) { 80 if (_eventSink != null) {
81 throw new StateError("WebSocket transformer already used."); 81 throw new StateError("WebSocket transformer already used.");
82 } 82 }
83 _eventSink = eventSink; 83 _eventSink = eventSink;
84 return this; 84 return this;
85 }); 85 });
86 } 86 }
87 87
88 void addError(Object error, [StackTrace stackTrace]) => 88 void addError(Object error, [StackTrace stackTrace]) =>
89 _eventSink.addError(error, stackTrace); 89 _eventSink.addError(error, stackTrace);
90 90
91 void close() => _eventSink.close(); 91 void close() => _eventSink.close();
92 92
93 Uint8List _takePayload() {
94 if (_payloads.length == 0) return new Uint8List(0);
kasperl 2014/01/29 11:10:44 Do you have to create a new one here? Cache an emp
Anders Johnsen 2014/01/29 14:23:40 The empty-list case is very rare, and not somethin
95 if (_payloads.length == 1) {
96 Uint8List result = _payloads.single;
97 _payloads.clear();
98 return result;
99 }
100 int length = 0;
101 for (Uint8List payload in _payloads) {
102 length += payload.length;
103 }
104 Uint8List result = new Uint8List(length);
105 int offset = 0;
106 for (Uint8List payload in _payloads) {
107 result.setRange(offset, offset + payload.length, payload);
108 offset += payload.length;
109 }
110 _payloads.clear();
111 return result;
112 }
113
93 /** 114 /**
94 * Process data received from the underlying communication channel. 115 * Process data received from the underlying communication channel.
95 */ 116 */
96 void add(Uint8List buffer) { 117 void add(Uint8List buffer) {
97 int count = buffer.length; 118 int count = buffer.length;
98 int index = 0; 119 int index = 0;
99 int lastIndex = count; 120 int lastIndex = count;
100 if (_state == CLOSED) { 121 if (_state == CLOSED) {
101 throw new WebSocketException("Data on closed connection"); 122 throw new WebSocketException("Data on closed connection");
102 } 123 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 189 }
169 } else { 190 } else {
170 assert(_state == PAYLOAD); 191 assert(_state == PAYLOAD);
171 // The payload is not handled one byte at a time but in blocks. 192 // The payload is not handled one byte at a time but in blocks.
172 int payloadLength = min(lastIndex - index, _remainingPayloadBytes); 193 int payloadLength = min(lastIndex - index, _remainingPayloadBytes);
173 _remainingPayloadBytes -= payloadLength; 194 _remainingPayloadBytes -= payloadLength;
174 // Unmask payload if masked. 195 // Unmask payload if masked.
175 if (_masked) { 196 if (_masked) {
176 _unmask(index, payloadLength, buffer); 197 _unmask(index, payloadLength, buffer);
177 } 198 }
178 // Control frame and data frame share _payload builder. 199 // Control frame and data frame share _payloads.
179 _payload.add(new Uint8List.view(buffer.buffer, index, payloadLength)); 200 _payloads.add(
201 new Uint8List.view(buffer.buffer, index, payloadLength));
180 index += payloadLength; 202 index += payloadLength;
181 if (_isControlFrame()) { 203 if (_isControlFrame()) {
182 if (_remainingPayloadBytes == 0) _controlFrameEnd(); 204 if (_remainingPayloadBytes == 0) _controlFrameEnd();
183 } else { 205 } else {
184 if (_currentMessageType != _WebSocketMessageType.TEXT && 206 if (_currentMessageType != _WebSocketMessageType.TEXT &&
185 _currentMessageType != _WebSocketMessageType.BINARY) { 207 _currentMessageType != _WebSocketMessageType.BINARY) {
186 throw new WebSocketException("Protocol error"); 208 throw new WebSocketException("Protocol error");
187 } 209 }
188 if (_remainingPayloadBytes == 0) _messageFrameEnd(); 210 if (_remainingPayloadBytes == 0) _messageFrameEnd();
189 } 211 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 } 300 }
279 } else { 301 } else {
280 _state = PAYLOAD; 302 _state = PAYLOAD;
281 } 303 }
282 } 304 }
283 305
284 void _messageFrameEnd() { 306 void _messageFrameEnd() {
285 if (_fin) { 307 if (_fin) {
286 switch (_currentMessageType) { 308 switch (_currentMessageType) {
287 case _WebSocketMessageType.TEXT: 309 case _WebSocketMessageType.TEXT:
288 _eventSink.add(UTF8.decode(_payload.takeBytes())); 310 _eventSink.add(UTF8.decode(_takePayload()));
289 break; 311 break;
290 case _WebSocketMessageType.BINARY: 312 case _WebSocketMessageType.BINARY:
291 _eventSink.add(_payload.takeBytes()); 313 _eventSink.add(_takePayload());
292 break; 314 break;
293 } 315 }
294 _currentMessageType = _WebSocketMessageType.NONE; 316 _currentMessageType = _WebSocketMessageType.NONE;
295 } 317 }
296 _prepareForNextFrame(); 318 _prepareForNextFrame();
297 } 319 }
298 320
299 void _controlFrameEnd() { 321 void _controlFrameEnd() {
300 switch (_opcode) { 322 switch (_opcode) {
301 case _WebSocketOpcode.CLOSE: 323 case _WebSocketOpcode.CLOSE:
302 closeCode = WebSocketStatus.NO_STATUS_RECEIVED; 324 closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
303 if (_payload.length > 0) { 325 var payload = _takePayload();
304 var bytes = _payload.takeBytes(); 326 if (payload.length > 0) {
305 if (bytes.length == 1) { 327 if (payload.length == 1) {
306 throw new WebSocketException("Protocol error"); 328 throw new WebSocketException("Protocol error");
307 } 329 }
308 closeCode = bytes[0] << 8 | bytes[1]; 330 closeCode = payload[0] << 8 | payload[1];
309 if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) { 331 if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) {
310 throw new WebSocketException("Protocol error"); 332 throw new WebSocketException("Protocol error");
311 } 333 }
312 if (bytes.length > 2) { 334 if (payload.length > 2) {
313 closeReason = UTF8.decode(bytes.sublist(2)); 335 closeReason = UTF8.decode(payload.sublist(2));
314 } 336 }
315 } 337 }
316 _state = CLOSED; 338 _state = CLOSED;
317 _eventSink.close(); 339 _eventSink.close();
318 break; 340 break;
319 341
320 case _WebSocketOpcode.PING: 342 case _WebSocketOpcode.PING:
321 _eventSink.add(new _WebSocketPing(_payload.takeBytes())); 343 _eventSink.add(new _WebSocketPing(_takePayload()));
322 break; 344 break;
323 345
324 case _WebSocketOpcode.PONG: 346 case _WebSocketOpcode.PONG:
325 _eventSink.add(new _WebSocketPong(_payload.takeBytes())); 347 _eventSink.add(new _WebSocketPong(_takePayload()));
326 break; 348 break;
327 } 349 }
328 _prepareForNextFrame(); 350 _prepareForNextFrame();
329 } 351 }
330 352
331 bool _isControlFrame() { 353 bool _isControlFrame() {
332 return _opcode == _WebSocketOpcode.CLOSE || 354 return _opcode == _WebSocketOpcode.CLOSE ||
333 _opcode == _WebSocketOpcode.PING || 355 _opcode == _WebSocketOpcode.PING ||
334 _opcode == _WebSocketOpcode.PONG; 356 _opcode == _WebSocketOpcode.PONG;
335 } 357 }
(...skipping 616 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 (code < WebSocketStatus.NORMAL_CLOSURE || 974 (code < WebSocketStatus.NORMAL_CLOSURE ||
953 code == WebSocketStatus.RESERVED_1004 || 975 code == WebSocketStatus.RESERVED_1004 ||
954 code == WebSocketStatus.NO_STATUS_RECEIVED || 976 code == WebSocketStatus.NO_STATUS_RECEIVED ||
955 code == WebSocketStatus.ABNORMAL_CLOSURE || 977 code == WebSocketStatus.ABNORMAL_CLOSURE ||
956 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && 978 (code > WebSocketStatus.INTERNAL_SERVER_ERROR &&
957 code < WebSocketStatus.RESERVED_1015) || 979 code < WebSocketStatus.RESERVED_1015) ||
958 (code >= WebSocketStatus.RESERVED_1015 && 980 (code >= WebSocketStatus.RESERVED_1015 &&
959 code < 3000)); 981 code < 3000));
960 } 982 }
961 } 983 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698