| 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 import "package:expect/expect.dart"; | 5 import "package:expect/expect.dart"; |
| 6 import "dart:utf"; | 6 import "dart:utf"; |
| 7 import "dart:math"; | 7 import "dart:math"; |
| 8 import "dart:async"; | 8 import "dart:async"; |
| 9 import "dart:collection"; | 9 import "dart:collection"; |
| 10 import "dart:typed_data"; | 10 import "dart:typed_data"; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 WebSocketFrame(int opcode, List<int> data); | 21 WebSocketFrame(int opcode, List<int> data); |
| 22 } | 22 } |
| 23 | 23 |
| 24 // Class that when hooked up to the web socket protocol transformer will | 24 // Class that when hooked up to the web socket protocol transformer will |
| 25 // collect the message and expect it to be equal to the | 25 // collect the message and expect it to be equal to the |
| 26 // expectedMessage field when fully received. | 26 // expectedMessage field when fully received. |
| 27 class WebSocketMessageCollector { | 27 class WebSocketMessageCollector { |
| 28 List<int> expectedMessage; | 28 List<int> expectedMessage; |
| 29 | 29 |
| 30 int messageCount = 0; | 30 int messageCount = 0; |
| 31 int closeCount = 0; | |
| 32 | 31 |
| 33 var data; | 32 var data; |
| 34 | 33 |
| 34 Function onClosed; |
| 35 |
| 35 WebSocketMessageCollector(Stream stream, | 36 WebSocketMessageCollector(Stream stream, |
| 36 [List<int> this.expectedMessage = null]) { | 37 [List<int> this.expectedMessage = null]) { |
| 37 stream.listen(onMessageData, onDone: onClosed, onError: onError); | 38 stream.listen(onMessageData, onDone: onClosed, onError: onError); |
| 38 } | 39 } |
| 39 | 40 |
| 40 void onMessageData(buffer) { | 41 void onMessageData(buffer) { |
| 41 if (buffer is String) { | 42 if (buffer is String) { |
| 42 buffer = _encodeString(buffer); | 43 buffer = _encodeString(buffer); |
| 43 } | 44 } |
| 44 Expect.listEquals(expectedMessage, buffer); | 45 Expect.listEquals(expectedMessage, buffer); |
| 45 messageCount++; | 46 messageCount++; |
| 46 data = buffer; | 47 data = buffer; |
| 47 } | 48 } |
| 48 | 49 |
| 49 void onClosed() { | |
| 50 closeCount++; | |
| 51 } | |
| 52 | |
| 53 void onError(e) { | 50 void onError(e) { |
| 54 String msg = "Unexpected error $e"; | 51 String msg = "Unexpected error $e"; |
| 55 var trace = getAttachedStackTrace(e); | 52 var trace = getAttachedStackTrace(e); |
| 56 if (trace != null) msg += "\nStackTrace: $trace"; | 53 if (trace != null) msg += "\nStackTrace: $trace"; |
| 57 Expect.fail(msg); | 54 Expect.fail(msg); |
| 58 } | 55 } |
| 59 | 56 |
| 60 } | 57 } |
| 61 | 58 |
| 62 | 59 |
| 63 // Web socket constants. | 60 // Web socket constants. |
| 64 const int FRAME_OPCODE_TEXT = 1; | 61 const int FRAME_OPCODE_TEXT = 1; |
| 65 const int FRAME_OPCODE_BINARY = 2; | 62 const int FRAME_OPCODE_BINARY = 2; |
| 66 | 63 |
| 67 | 64 |
| 68 // Function for building a web socket frame. | 65 // Function for building a web socket frame. |
| 69 List<int> createFrame(bool fin, | 66 List<int> createFrame(bool fin, |
| 70 int opcode, | 67 int opcode, |
| 71 int maskingKey, | 68 int maskingKey, |
| 72 List<int> data, | 69 List<int> data, |
| 73 int offset, | 70 int offset, |
| 74 int count) { | 71 int count) { |
| 75 int frameSize = 2; | 72 int frameSize = 2; |
| 76 if (count > 125) frameSize += 2; | 73 if (count > 125) frameSize += 2; |
| 77 if (count > 65535) frameSize += 6; | 74 if (count > 65535) frameSize += 6; |
| 78 frameSize += count; | 75 frameSize += count; |
| 79 // No masking. | 76 // No masking. |
| 80 assert(maskingKey == null); | 77 assert(maskingKey == null); |
| 81 List<int> frame = new List<int>(frameSize); | 78 List<int> frame = new Uint8List(frameSize); |
| 82 int frameIndex = 0; | 79 int frameIndex = 0; |
| 83 frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode; | 80 frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode; |
| 84 if (count < 126) { | 81 if (count < 126) { |
| 85 frame[frameIndex++] = count; | 82 frame[frameIndex++] = count; |
| 86 } else if (count < 65536) { | 83 } else if (count < 65536) { |
| 87 frame[frameIndex++] = 126; | 84 frame[frameIndex++] = 126; |
| 88 frame[frameIndex++] = count >> 8; | 85 frame[frameIndex++] = count >> 8; |
| 89 frame[frameIndex++] = count & 0xFF; | 86 frame[frameIndex++] = count & 0xFF; |
| 90 } else { | 87 } else { |
| 91 frame[frameIndex++] = 127; | 88 frame[frameIndex++] = 127; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 108 WebSocketMessageCollector mc = new WebSocketMessageCollector( | 105 WebSocketMessageCollector mc = new WebSocketMessageCollector( |
| 109 controller.stream.transform(transformer), | 106 controller.stream.transform(transformer), |
| 110 message); | 107 message); |
| 111 | 108 |
| 112 List<int> frame = createFrame( | 109 List<int> frame = createFrame( |
| 113 true, opcode, null, message, 0, message.length); | 110 true, opcode, null, message, 0, message.length); |
| 114 | 111 |
| 115 // Update the transformer with one big chunk. | 112 // Update the transformer with one big chunk. |
| 116 messageCount++; | 113 messageCount++; |
| 117 controller.add(frame); | 114 controller.add(frame); |
| 118 Expect.isNotNull(mc.data); | 115 mc.onClosed = () { |
| 119 Expect.equals(0, transformer._state); | 116 Expect.isNotNull(mc.data); |
| 117 Expect.equals(0, transformer._state); |
| 120 | 118 |
| 121 mc.data = null; | |
| 122 | |
| 123 // Only run this part on small messages. | |
| 124 if (message.length < 1000) { | |
| 125 // Update the transformer one byte at the time. | |
| 126 messageCount++; | |
| 127 for (int i = 0; i < frame.length; i++) { | |
| 128 controller.add(<int>[frame[i]]); | |
| 129 } | |
| 130 Expect.equals(0, transformer._state); | |
| 131 Expect.isNotNull(mc.data); | |
| 132 mc.data = null; | 119 mc.data = null; |
| 133 | 120 |
| 134 // Update the transformer two bytes at the time. | 121 // Only run this part on small messages. |
| 135 messageCount++; | 122 if (message.length < 1000) { |
| 136 for (int i = 0; i < frame.length; i += 2) { | 123 // Update the transformer one byte at the time. |
| 137 controller.add(frame.sublist(i, min(i + 2, frame.length))); | 124 messageCount++; |
| 125 for (int i = 0; i < frame.length; i++) { |
| 126 controller.add(<int>[frame[i]]); |
| 127 } |
| 128 Expect.equals(0, transformer._state); |
| 129 Expect.isNotNull(mc.data); |
| 130 mc.data = null; |
| 131 |
| 132 // Update the transformer two bytes at the time. |
| 133 messageCount++; |
| 134 for (int i = 0; i < frame.length; i += 2) { |
| 135 controller.add(frame.sublist(i, min(i + 2, frame.length))); |
| 136 } |
| 137 Expect.equals(0, transformer._state); |
| 138 Expect.isNotNull(mc.data); |
| 138 } | 139 } |
| 139 Expect.equals(0, transformer._state); | 140 Expect.equals(messageCount, mc.messageCount); |
| 140 Expect.isNotNull(mc.data); | 141 print("Messages test, messages $messageCount"); |
| 141 } | 142 }; |
| 142 Expect.equals(messageCount, mc.messageCount); | 143 controller.close(); |
| 143 Expect.equals(0, mc.closeCount); | |
| 144 print("Messages test, messages $messageCount"); | |
| 145 } | 144 } |
| 146 | 145 |
| 147 void runTest(int from, int to, int step) { | 146 void runTest(int from, int to, int step) { |
| 148 for (int messageLength = from; messageLength < to; messageLength += step) { | 147 for (int messageLength = from; messageLength < to; messageLength += step) { |
| 149 List<int> message = new List<int>(messageLength); | 148 List<int> message = new List<int>(messageLength); |
| 150 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F; | 149 for (int i = 0; i < messageLength; i++) message[i] = i & 0x7F; |
| 151 testMessage(FRAME_OPCODE_TEXT, message); | 150 testMessage(FRAME_OPCODE_TEXT, message); |
| 152 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; | 151 for (int i = 0; i < messageLength; i++) message[i] = i & 0xFF; |
| 153 testMessage(FRAME_OPCODE_BINARY, message); | 152 testMessage(FRAME_OPCODE_BINARY, message); |
| 154 } | 153 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 } | 219 } |
| 221 } | 220 } |
| 222 | 221 |
| 223 // Test different message sizes. | 222 // Test different message sizes. |
| 224 runTest(0, 10, 1); | 223 runTest(0, 10, 1); |
| 225 runTest(120, 130, 1); | 224 runTest(120, 130, 1); |
| 226 runTest(0, 1000, 100); | 225 runTest(0, 1000, 100); |
| 227 runTest(65534, 65537, 1); | 226 runTest(65534, 65537, 1); |
| 228 print("Fragment messages test, messages $messageCount, frames $frameCount"); | 227 print("Fragment messages test, messages $messageCount, frames $frameCount"); |
| 229 Expect.equals(messageCount, mc.messageCount); | 228 Expect.equals(messageCount, mc.messageCount); |
| 230 Expect.equals(0, mc.closeCount); | |
| 231 } | 229 } |
| 232 | 230 |
| 233 void testUnmaskedMessage() { | 231 void testUnmaskedMessage() { |
| 234 var transformer = new _WebSocketProtocolTransformer(true); | 232 var transformer = new _WebSocketProtocolTransformer(true); |
| 235 var controller = new StreamController(); | 233 var controller = new StreamController(); |
| 236 var port = new ReceivePort(); | 234 var port = new ReceivePort(); |
| 237 controller.stream.transform(transformer).listen((_) {}, onError: (e) { | 235 controller.stream.transform(transformer).listen((_) {}, onError: (e) { |
| 238 port.close(); | 236 port.close(); |
| 239 }); | 237 }); |
| 240 var message = new Uint8List(10); | 238 var message = new Uint8List(10); |
| 241 List<int> frame = createFrame( | 239 List<int> frame = createFrame( |
| 242 true, FRAME_OPCODE_BINARY, null, message, 0, message.length); | 240 true, FRAME_OPCODE_BINARY, null, message, 0, message.length); |
| 243 controller.add(frame); | 241 controller.add(frame); |
| 244 } | 242 } |
| 245 | 243 |
| 246 | 244 |
| 247 void main() { | 245 void main() { |
| 248 testFullMessages(); | 246 testFullMessages(); |
| 249 testFragmentedMessages(); | 247 testFragmentedMessages(); |
| 250 testUnmaskedMessage(); | 248 testUnmaskedMessage(); |
| 251 } | 249 } |
| OLD | NEW |