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 library dart.io; | 5 library dart.io; |
6 | 6 |
7 import "package:async_helper/async_helper.dart"; | 7 import "package:async_helper/async_helper.dart"; |
8 import "package:expect/expect.dart"; | 8 import "package:expect/expect.dart"; |
9 import "dart:async"; | 9 import "dart:async"; |
10 import "dart:collection"; | 10 import "dart:collection"; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 class WebSocketMessageCollector { | 53 class WebSocketMessageCollector { |
54 List<int> expectedMessage; | 54 List<int> expectedMessage; |
55 | 55 |
56 int messageCount = 0; | 56 int messageCount = 0; |
57 | 57 |
58 var data; | 58 var data; |
59 | 59 |
60 Function onClosed; | 60 Function onClosed; |
61 | 61 |
62 WebSocketMessageCollector(Stream stream, | 62 WebSocketMessageCollector(Stream stream, |
63 [List<int> this.expectedMessage = null]) { | 63 [List<int> this.expectedMessage = null]) { |
64 stream.listen(onMessageData, onDone: onClosed, onError: onError); | 64 stream.listen(onMessageData, onDone: onClosed, onError: onError); |
65 } | 65 } |
66 | 66 |
67 void onMessageData(buffer) { | 67 void onMessageData(buffer) { |
68 if (buffer is String) { | 68 if (buffer is String) { |
69 buffer = UTF8.encode(buffer); | 69 buffer = UTF8.encode(buffer); |
70 } | 70 } |
71 Expect.listEquals(expectedMessage, buffer); | 71 Expect.listEquals(expectedMessage, buffer); |
72 messageCount++; | 72 messageCount++; |
73 data = buffer; | 73 data = buffer; |
74 } | 74 } |
75 | 75 |
76 void onError(e, trace) { | 76 void onError(e, trace) { |
77 String msg = "Unexpected error $e"; | 77 String msg = "Unexpected error $e"; |
78 if (trace != null) msg += "\nStackTrace: $trace"; | 78 if (trace != null) msg += "\nStackTrace: $trace"; |
79 Expect.fail(msg); | 79 Expect.fail(msg); |
80 } | 80 } |
81 | |
82 } | 81 } |
83 | 82 |
84 | |
85 // Web socket constants. | 83 // Web socket constants. |
86 const int FRAME_OPCODE_TEXT = 1; | 84 const int FRAME_OPCODE_TEXT = 1; |
87 const int FRAME_OPCODE_BINARY = 2; | 85 const int FRAME_OPCODE_BINARY = 2; |
88 | 86 |
89 | |
90 // Function for building a web socket frame. | 87 // Function for building a web socket frame. |
91 List<int> createFrame(bool fin, | 88 List<int> createFrame(bool fin, int opcode, int maskingKey, List<int> data, |
92 int opcode, | 89 int offset, int count) { |
93 int maskingKey, | |
94 List<int> data, | |
95 int offset, | |
96 int count) { | |
97 int frameSize = 2; | 90 int frameSize = 2; |
98 if (count > 125) frameSize += 2; | 91 if (count > 125) frameSize += 2; |
99 if (count > 65535) frameSize += 6; | 92 if (count > 65535) frameSize += 6; |
100 frameSize += count; | 93 frameSize += count; |
101 // No masking. | 94 // No masking. |
102 assert(maskingKey == null); | 95 assert(maskingKey == null); |
103 List<int> frame = new Uint8List(frameSize); | 96 List<int> frame = new Uint8List(frameSize); |
104 int frameIndex = 0; | 97 int frameIndex = 0; |
105 frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode; | 98 frame[frameIndex++] = (fin ? 0x80 : 0x00) | opcode; |
106 if (count < 126) { | 99 if (count < 126) { |
107 frame[frameIndex++] = count; | 100 frame[frameIndex++] = count; |
108 } else if (count < 65536) { | 101 } else if (count < 65536) { |
109 frame[frameIndex++] = 126; | 102 frame[frameIndex++] = 126; |
110 frame[frameIndex++] = count >> 8; | 103 frame[frameIndex++] = count >> 8; |
111 frame[frameIndex++] = count & 0xFF; | 104 frame[frameIndex++] = count & 0xFF; |
112 } else { | 105 } else { |
113 frame[frameIndex++] = 127; | 106 frame[frameIndex++] = 127; |
114 for (int i = 0; i < 8; i++) { | 107 for (int i = 0; i < 8; i++) { |
115 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF; | 108 frame[frameIndex++] = count >> ((7 - i) * 8) & 0xFF; |
116 } | 109 } |
117 } | 110 } |
118 frame.setRange(frameIndex, frameIndex + count, data, offset); | 111 frame.setRange(frameIndex, frameIndex + count, data, offset); |
119 return frame; | 112 return frame; |
120 } | 113 } |
121 | 114 |
122 | |
123 // Test processing messages which are sent in a single frame. | 115 // Test processing messages which are sent in a single frame. |
124 void testFullMessages() { | 116 void testFullMessages() { |
125 void testMessage(int opcode, List<int> message) { | 117 void testMessage(int opcode, List<int> message) { |
126 int messageCount = 0; | 118 int messageCount = 0; |
127 // Use the same web socket protocol transformer for all frames. | 119 // Use the same web socket protocol transformer for all frames. |
128 var transformer = new _WebSocketProtocolTransformer(); | 120 var transformer = new _WebSocketProtocolTransformer(); |
129 var controller = new StreamController(sync: true); | 121 var controller = new StreamController(sync: true); |
130 WebSocketMessageCollector mc = new WebSocketMessageCollector( | 122 WebSocketMessageCollector mc = new WebSocketMessageCollector( |
131 controller.stream.transform(transformer), | 123 controller.stream.transform(transformer), message); |
132 message); | |
133 | 124 |
134 List<int> frame = createFrame( | 125 List<int> frame = |
135 true, opcode, null, message, 0, message.length); | 126 createFrame(true, opcode, null, message, 0, message.length); |
136 | 127 |
137 // Update the transformer with one big chunk. | 128 // Update the transformer with one big chunk. |
138 messageCount++; | 129 messageCount++; |
139 controller.add(frame); | 130 controller.add(frame); |
140 mc.onClosed = () { | 131 mc.onClosed = () { |
141 Expect.isNotNull(mc.data); | 132 Expect.isNotNull(mc.data); |
142 Expect.equals(0, transformer._state); | 133 Expect.equals(0, transformer._state); |
143 | 134 |
144 mc.data = null; | 135 mc.data = null; |
145 | 136 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 169 } |
179 } | 170 } |
180 | 171 |
181 // Test different message sizes. | 172 // Test different message sizes. |
182 runTest(0, 10, 1); | 173 runTest(0, 10, 1); |
183 runTest(120, 130, 1); | 174 runTest(120, 130, 1); |
184 runTest(0, 1000, 100); | 175 runTest(0, 1000, 100); |
185 runTest(65534, 65537, 1); | 176 runTest(65534, 65537, 1); |
186 } | 177 } |
187 | 178 |
188 | |
189 // Test processing of frames which are split into fragments. | 179 // Test processing of frames which are split into fragments. |
190 void testFragmentedMessages() { | 180 void testFragmentedMessages() { |
191 // Use the same web socket protocol transformer for all frames. | 181 // Use the same web socket protocol transformer for all frames. |
192 var transformer = new _WebSocketProtocolTransformer(); | 182 var transformer = new _WebSocketProtocolTransformer(); |
193 var controller = new StreamController(sync: true); | 183 var controller = new StreamController(sync: true); |
194 WebSocketMessageCollector mc = new WebSocketMessageCollector( | 184 WebSocketMessageCollector mc = |
195 controller.stream.transform(transformer)); | 185 new WebSocketMessageCollector(controller.stream.transform(transformer)); |
196 | 186 |
197 int messageCount = 0; | 187 int messageCount = 0; |
198 int frameCount = 0; | 188 int frameCount = 0; |
199 | 189 |
200 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) { | 190 void testFragmentMessage(int opcode, List<int> message, int fragmentSize) { |
201 messageCount++; | 191 messageCount++; |
202 int messageIndex = 0; | 192 int messageIndex = 0; |
203 int remaining = message.length; | 193 int remaining = message.length; |
204 bool firstFrame = true; | 194 bool firstFrame = true; |
205 bool lastFrame = false; | 195 bool lastFrame = false; |
206 while (!lastFrame) { | 196 while (!lastFrame) { |
207 int payloadSize = min(fragmentSize, remaining); | 197 int payloadSize = min(fragmentSize, remaining); |
208 lastFrame = payloadSize == remaining; | 198 lastFrame = payloadSize == remaining; |
209 List<int> frame = createFrame(lastFrame, | 199 List<int> frame = createFrame(lastFrame, firstFrame ? opcode : 0x00, null, |
210 firstFrame ? opcode : 0x00, | 200 message, messageIndex, payloadSize); |
211 null, | |
212 message, | |
213 messageIndex, | |
214 payloadSize); | |
215 frameCount++; | 201 frameCount++; |
216 messageIndex += payloadSize; | 202 messageIndex += payloadSize; |
217 controller.add(frame); | 203 controller.add(frame); |
218 remaining -= payloadSize; | 204 remaining -= payloadSize; |
219 firstFrame = false; | 205 firstFrame = false; |
220 } | 206 } |
221 } | 207 } |
222 | 208 |
223 void testMessageFragmentation(int opcode, List<int> message) { | 209 void testMessageFragmentation(int opcode, List<int> message) { |
224 mc.expectedMessage = message; | 210 mc.expectedMessage = message; |
(...skipping 29 matching lines...) Expand all Loading... |
254 } | 240 } |
255 | 241 |
256 void testUnmaskedMessage() { | 242 void testUnmaskedMessage() { |
257 var transformer = new _WebSocketProtocolTransformer(true); | 243 var transformer = new _WebSocketProtocolTransformer(true); |
258 var controller = new StreamController(sync: true); | 244 var controller = new StreamController(sync: true); |
259 asyncStart(); | 245 asyncStart(); |
260 controller.stream.transform(transformer).listen((_) {}, onError: (e) { | 246 controller.stream.transform(transformer).listen((_) {}, onError: (e) { |
261 asyncEnd(); | 247 asyncEnd(); |
262 }); | 248 }); |
263 var message = new Uint8List(10); | 249 var message = new Uint8List(10); |
264 List<int> frame = createFrame( | 250 List<int> frame = |
265 true, FRAME_OPCODE_BINARY, null, message, 0, message.length); | 251 createFrame(true, FRAME_OPCODE_BINARY, null, message, 0, message.length); |
266 controller.add(frame); | 252 controller.add(frame); |
267 } | 253 } |
268 | 254 |
269 | |
270 void main() { | 255 void main() { |
271 testFullMessages(); | 256 testFullMessages(); |
272 testFragmentedMessages(); | 257 testFragmentedMessages(); |
273 testUnmaskedMessage(); | 258 testUnmaskedMessage(); |
274 } | 259 } |
OLD | NEW |