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

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

Issue 137833011: Use Int32x4List to optimize mask/unmask websockets. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Review update 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 } 162 }
163 } else { 163 } else {
164 if (_state == MASK) { 164 if (_state == MASK) {
165 _maskingBytes[4 - _remainingMaskingKeyBytes--] = byte; 165 _maskingBytes[4 - _remainingMaskingKeyBytes--] = byte;
166 if (_remainingMaskingKeyBytes == 0) { 166 if (_remainingMaskingKeyBytes == 0) {
167 _maskDone(); 167 _maskDone();
168 } 168 }
169 } else { 169 } else {
170 assert(_state == PAYLOAD); 170 assert(_state == PAYLOAD);
171 // The payload is not handled one byte at a time but in blocks. 171 // The payload is not handled one byte at a time but in blocks.
172 int payload = min(lastIndex - index, _remainingPayloadBytes); 172 int payloadLength = min(lastIndex - index, _remainingPayloadBytes);
173 _remainingPayloadBytes -= payload; 173 _remainingPayloadBytes -= payloadLength;
174 // Unmask payload if masked. 174 // Unmask payload if masked.
175 if (_masked) { 175 if (_masked) {
176 for (int i = index; i < index + payload; i++) { 176 _unmask(index, payloadLength, buffer);
177 buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
178 }
179 } 177 }
180 // Control frame and data frame share _payload builder. 178 // Control frame and data frame share _payload builder.
181 _payload.add(new Uint8List.view(buffer.buffer, index, payload)); 179 _payload.add(new Uint8List.view(buffer.buffer, index, payloadLength));
182 index += payload; 180 index += payloadLength;
183 if (_isControlFrame()) { 181 if (_isControlFrame()) {
184 if (_remainingPayloadBytes == 0) _controlFrameEnd(); 182 if (_remainingPayloadBytes == 0) _controlFrameEnd();
185 } else { 183 } else {
186 if (_currentMessageType != _WebSocketMessageType.TEXT && 184 if (_currentMessageType != _WebSocketMessageType.TEXT &&
187 _currentMessageType != _WebSocketMessageType.BINARY) { 185 _currentMessageType != _WebSocketMessageType.BINARY) {
188 throw new WebSocketException("Protocol error"); 186 throw new WebSocketException("Protocol error");
189 } 187 }
190 if (_remainingPayloadBytes == 0) _messageFrameEnd(); 188 if (_remainingPayloadBytes == 0) _messageFrameEnd();
191 } 189 }
192 190
193 // Hack - as we always do index++ below. 191 // Hack - as we always do index++ below.
194 index--; 192 index--;
195 } 193 }
196 } 194 }
197 195
198 // Move to the next byte. 196 // Move to the next byte.
199 index++; 197 index++;
200 } 198 }
201 } 199 }
202 200
201 void _unmask(int index, int length, Uint8List buffer) {
202 const int BLOCK_SIZE = 16;
203 // Skip Int32x4-version if message is small.
204 if (length >= BLOCK_SIZE) {
205 // Start by aligning to 16 bytes.
206 final int startOffset = BLOCK_SIZE - (index & 15);
207 final int end = index + startOffset;
208 for (int i = index; i < end; i++) {
209 buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
210 }
211 index += startOffset;
212 length -= startOffset;
213 final int blockCount = length ~/ BLOCK_SIZE;
214 if (blockCount > 0) {
215 // Create mask block.
216 int mask = 0;
217 for (int i = 3; i >= 0; i--) {
218 mask = (mask << 8) | _maskingBytes[(_unmaskingIndex + i) & 3];
219 }
220 Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
221 Int32x4List blockBuffer = new Int32x4List.view(
222 buffer.buffer, index, blockCount);
223 for (int i = 0; i < blockBuffer.length; i++) {
224 blockBuffer[i] ^= blockMask;
225 }
226 final int bytes = blockCount * BLOCK_SIZE;
227 index += bytes;
228 length -= bytes;
229 }
230 }
231 // Handle end.
232 final int end = index + length;
233 for (int i = index; i < end; i++) {
234 buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
235 }
236 }
237
203 void _lengthDone() { 238 void _lengthDone() {
204 if (_masked) { 239 if (_masked) {
205 if (!_serverSide) { 240 if (!_serverSide) {
206 throw new WebSocketException("Received masked frame from server"); 241 throw new WebSocketException("Received masked frame from server");
207 } 242 }
208 _state = MASK; 243 _state = MASK;
209 } else { 244 } else {
210 if (_serverSide) { 245 if (_serverSide) {
211 throw new WebSocketException("Received unmasked frame from client"); 246 throw new WebSocketException("Received unmasked frame from client");
212 } 247 }
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 // Write the length in network byte order into the header. 558 // Write the length in network byte order into the header.
524 for (int i = 0; i < lengthBytes; i++) { 559 for (int i = 0; i < lengthBytes; i++) {
525 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF; 560 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF;
526 } 561 }
527 if (mask) { 562 if (mask) {
528 header[1] |= 1 << 7; 563 header[1] |= 1 << 7;
529 var maskBytes = _IOCrypto.getRandomBytes(4); 564 var maskBytes = _IOCrypto.getRandomBytes(4);
530 header.setRange(index, index + 4, maskBytes); 565 header.setRange(index, index + 4, maskBytes);
531 index += 4; 566 index += 4;
532 if (data != null) { 567 if (data != null) {
533 var list; 568 Uint8List list;
534 // If this is a text message just do the masking inside the 569 // If this is a text message just do the masking inside the
535 // encoded data. 570 // encoded data.
536 if (opcode == _WebSocketOpcode.TEXT) { 571 if (opcode == _WebSocketOpcode.TEXT && data is Uint8List) {
537 list = data; 572 list = data;
538 } else { 573 } else {
539 list = new Uint8List(data.length); 574 if (data is Uint8List) {
575 list = new Uint8List.fromList(data);
576 } else {
577 list = new Uint8List(data.length);
578 for (int i = 0; i < data.length; i++) {
579 if (data[i] < 0 || 255 < data[i]) {
580 throw new ArgumentError(
581 "List element is not a byte value "
582 "(value ${data[i]} at index $i)");
583 }
584 list[i] = data[i];
585 }
586 }
540 } 587 }
541 if (data is Uint8List) { 588 const int BLOCK_SIZE = 16;
542 for (int i = 0; i < data.length; i++) { 589 int blockCount = list.length ~/ BLOCK_SIZE;
543 list[i] = data[i] ^ maskBytes[i & 3]; 590 if (blockCount > 0) {
591 // Create mask block.
592 int mask = 0;
593 for (int i = 3; i >= 0; i--) {
594 mask = (mask << 8) | maskBytes[i];
544 } 595 }
545 } else { 596 Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
546 for (int i = 0; i < data.length; i++) { 597 Int32x4List blockBuffer = new Int32x4List.view(
547 if (data[i] < 0 || 255 < data[i]) { 598 list.buffer, 0, blockCount);
548 throw new ArgumentError( 599 for (int i = 0; i < blockBuffer.length; i++) {
549 "List element is not a byte value " 600 blockBuffer[i] ^= blockMask;
550 "(value ${data[i]} at index $i)");
551 }
552 list[i] = data[i] ^ maskBytes[i & 3];
553 } 601 }
554 } 602 }
603 // Handle end.
604 for (int i = blockCount * BLOCK_SIZE; i < list.length; i++) {
605 list[i] ^= maskBytes[i & 3];
606 }
555 data = list; 607 data = list;
556 } 608 }
557 } 609 }
558 assert(index == headerSize); 610 assert(index == headerSize);
559 if (data == null) { 611 if (data == null) {
560 return [header]; 612 return [header];
561 } else { 613 } else {
562 return [header, data]; 614 return [header, data];
563 } 615 }
564 } 616 }
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 (code < WebSocketStatus.NORMAL_CLOSURE || 952 (code < WebSocketStatus.NORMAL_CLOSURE ||
901 code == WebSocketStatus.RESERVED_1004 || 953 code == WebSocketStatus.RESERVED_1004 ||
902 code == WebSocketStatus.NO_STATUS_RECEIVED || 954 code == WebSocketStatus.NO_STATUS_RECEIVED ||
903 code == WebSocketStatus.ABNORMAL_CLOSURE || 955 code == WebSocketStatus.ABNORMAL_CLOSURE ||
904 (code > WebSocketStatus.INTERNAL_SERVER_ERROR && 956 (code > WebSocketStatus.INTERNAL_SERVER_ERROR &&
905 code < WebSocketStatus.RESERVED_1015) || 957 code < WebSocketStatus.RESERVED_1015) ||
906 (code >= WebSocketStatus.RESERVED_1015 && 958 (code >= WebSocketStatus.RESERVED_1015 &&
907 code < 3000)); 959 code < 3000));
908 } 960 }
909 } 961 }
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