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

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

Issue 11361190: a === b -> identical(a, b) (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 1 month 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 | « sdk/lib/io/timer_impl.dart ('k') | sdk/lib/mirrors/mirrors.dart » ('j') | 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) 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 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 5 const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
6 6
7 class _WebSocketMessageType { 7 class _WebSocketMessageType {
8 static const int NONE = 0; 8 static const int NONE = 0;
9 static const int BINARY = 1; 9 static const int BINARY = 1;
10 static const int TEXT = 2; 10 static const int TEXT = 2;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 if (_currentMessageType == _WebSocketMessageType.NONE) { 81 if (_currentMessageType == _WebSocketMessageType.NONE) {
82 throw new WebSocketException("Protocol error"); 82 throw new WebSocketException("Protocol error");
83 } 83 }
84 break; 84 break;
85 85
86 case _WebSocketOpcode.TEXT: 86 case _WebSocketOpcode.TEXT:
87 if (_currentMessageType != _WebSocketMessageType.NONE) { 87 if (_currentMessageType != _WebSocketMessageType.NONE) {
88 throw new WebSocketException("Protocol error"); 88 throw new WebSocketException("Protocol error");
89 } 89 }
90 _currentMessageType = _WebSocketMessageType.TEXT; 90 _currentMessageType = _WebSocketMessageType.TEXT;
91 if (onMessageStart !== null) { 91 if (onMessageStart != null) {
92 onMessageStart(_WebSocketMessageType.TEXT); 92 onMessageStart(_WebSocketMessageType.TEXT);
93 } 93 }
94 break; 94 break;
95 95
96 case _WebSocketOpcode.BINARY: 96 case _WebSocketOpcode.BINARY:
97 if (_currentMessageType != _WebSocketMessageType.NONE) { 97 if (_currentMessageType != _WebSocketMessageType.NONE) {
98 throw new WebSocketException("Protocol error"); 98 throw new WebSocketException("Protocol error");
99 } 99 }
100 _currentMessageType = _WebSocketMessageType.BINARY; 100 _currentMessageType = _WebSocketMessageType.BINARY;
101 if (onMessageStart !== null) { 101 if (onMessageStart != null) {
102 onMessageStart(_WebSocketMessageType.BINARY); 102 onMessageStart(_WebSocketMessageType.BINARY);
103 } 103 }
104 break; 104 break;
105 105
106 case _WebSocketOpcode.CLOSE: 106 case _WebSocketOpcode.CLOSE:
107 case _WebSocketOpcode.PING: 107 case _WebSocketOpcode.PING:
108 case _WebSocketOpcode.PONG: 108 case _WebSocketOpcode.PONG:
109 // Control frames cannot be fragmented. 109 // Control frames cannot be fragmented.
110 if (!_fin) throw new WebSocketException("Protocol error"); 110 if (!_fin) throw new WebSocketException("Protocol error");
111 break; 111 break;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 if (_remainingPayloadBytes == 0) { 185 if (_remainingPayloadBytes == 0) {
186 _controlFrameEnd(); 186 _controlFrameEnd();
187 } 187 }
188 } else { 188 } else {
189 switch (_currentMessageType) { 189 switch (_currentMessageType) {
190 case _WebSocketMessageType.NONE: 190 case _WebSocketMessageType.NONE:
191 throw new WebSocketException("Protocol error"); 191 throw new WebSocketException("Protocol error");
192 192
193 case _WebSocketMessageType.TEXT: 193 case _WebSocketMessageType.TEXT:
194 case _WebSocketMessageType.BINARY: 194 case _WebSocketMessageType.BINARY:
195 if (onMessageData !== null) { 195 if (onMessageData != null) {
196 onMessageData(buffer, index, payload); 196 onMessageData(buffer, index, payload);
197 } 197 }
198 index += payload; 198 index += payload;
199 if (_remainingPayloadBytes == 0) { 199 if (_remainingPayloadBytes == 0) {
200 _messageFrameEnd(); 200 _messageFrameEnd();
201 } 201 }
202 break; 202 break;
203 203
204 default: 204 default:
205 throw new WebSocketException("Protocol error"); 205 throw new WebSocketException("Protocol error");
206 } 206 }
207 } 207 }
208 208
209 // Hack - as we always do index++ below. 209 // Hack - as we always do index++ below.
210 index--; 210 index--;
211 break; 211 break;
212 } 212 }
213 213
214 // Move to the next byte. 214 // Move to the next byte.
215 index++; 215 index++;
216 } 216 }
217 } catch (e) { 217 } catch (e) {
218 if (onClosed !== null) onClosed(WebSocketStatus.PROTOCOL_ERROR, 218 if (onClosed != null) onClosed(WebSocketStatus.PROTOCOL_ERROR,
219 "Protocol error"); 219 "Protocol error");
220 _state = FAILURE; 220 _state = FAILURE;
221 } 221 }
222 } 222 }
223 223
224 /** 224 /**
225 * Indicate that the underlying communication channel has been closed. 225 * Indicate that the underlying communication channel has been closed.
226 */ 226 */
227 void closed() { 227 void closed() {
228 if (_state == START || _state == CLOSED || _state == FAILURE) return; 228 if (_state == START || _state == CLOSED || _state == FAILURE) return;
229 if (onClosed !== null) onClosed(WebSocketStatus.ABNORMAL_CLOSURE, 229 if (onClosed != null) onClosed(WebSocketStatus.ABNORMAL_CLOSURE,
230 "Connection closed unexpectedly"); 230 "Connection closed unexpectedly");
231 _state = CLOSED; 231 _state = CLOSED;
232 } 232 }
233 233
234 void _lengthDone() { 234 void _lengthDone() {
235 if (_masked) { 235 if (_masked) {
236 _state = MASK; 236 _state = MASK;
237 _remainingMaskingKeyBytes = 4; 237 _remainingMaskingKeyBytes = 4;
238 } else { 238 } else {
239 _remainingPayloadBytes = _len; 239 _remainingPayloadBytes = _len;
240 _startPayload(); 240 _startPayload();
241 } 241 }
242 } 242 }
243 243
244 void _maskDone() { 244 void _maskDone() {
245 _remainingPayloadBytes = _len; 245 _remainingPayloadBytes = _len;
246 _startPayload(); 246 _startPayload();
247 } 247 }
248 248
249 void _startPayload() { 249 void _startPayload() {
250 // If there is no actual payload perform perform callbacks without 250 // If there is no actual payload perform perform callbacks without
251 // going through the PAYLOAD state. 251 // going through the PAYLOAD state.
252 if (_remainingPayloadBytes == 0) { 252 if (_remainingPayloadBytes == 0) {
253 if (_isControlFrame()) { 253 if (_isControlFrame()) {
254 switch (_opcode) { 254 switch (_opcode) {
255 case _WebSocketOpcode.CLOSE: 255 case _WebSocketOpcode.CLOSE:
256 if (onClosed !== null) onClosed(1005, ""); 256 if (onClosed != null) onClosed(1005, "");
257 _state = CLOSED; 257 _state = CLOSED;
258 break; 258 break;
259 case _WebSocketOpcode.PING: 259 case _WebSocketOpcode.PING:
260 if (onPing !== null) onPing(null); 260 if (onPing != null) onPing(null);
261 break; 261 break;
262 case _WebSocketOpcode.PONG: 262 case _WebSocketOpcode.PONG:
263 if (onPong !== null) onPong(null); 263 if (onPong != null) onPong(null);
264 break; 264 break;
265 } 265 }
266 _prepareForNextFrame(); 266 _prepareForNextFrame();
267 } else { 267 } else {
268 _messageFrameEnd(); 268 _messageFrameEnd();
269 } 269 }
270 } else { 270 } else {
271 _state = PAYLOAD; 271 _state = PAYLOAD;
272 } 272 }
273 } 273 }
274 274
275 void _messageFrameEnd() { 275 void _messageFrameEnd() {
276 if (_fin) { 276 if (_fin) {
277 if (onMessageEnd !== null) onMessageEnd(); 277 if (onMessageEnd != null) onMessageEnd();
278 _currentMessageType = _WebSocketMessageType.NONE; 278 _currentMessageType = _WebSocketMessageType.NONE;
279 } 279 }
280 _prepareForNextFrame(); 280 _prepareForNextFrame();
281 } 281 }
282 282
283 void _controlFrameEnd() { 283 void _controlFrameEnd() {
284 switch (_opcode) { 284 switch (_opcode) {
285 case _WebSocketOpcode.CLOSE: 285 case _WebSocketOpcode.CLOSE:
286 int status = WebSocketStatus.NO_STATUS_RECEIVED; 286 int status = WebSocketStatus.NO_STATUS_RECEIVED;
287 String reason = ""; 287 String reason = "";
288 if (_controlPayload.length > 0) { 288 if (_controlPayload.length > 0) {
289 if (_controlPayload.length == 1) { 289 if (_controlPayload.length == 1) {
290 throw new WebSocketException("Protocol error"); 290 throw new WebSocketException("Protocol error");
291 } 291 }
292 status = _controlPayload[0] << 8 | _controlPayload[1]; 292 status = _controlPayload[0] << 8 | _controlPayload[1];
293 if (status == WebSocketStatus.NO_STATUS_RECEIVED) { 293 if (status == WebSocketStatus.NO_STATUS_RECEIVED) {
294 throw new WebSocketException("Protocol error"); 294 throw new WebSocketException("Protocol error");
295 } 295 }
296 if (_controlPayload.length > 2) { 296 if (_controlPayload.length > 2) {
297 var decoder = _StringDecoders.decoder(Encoding.UTF_8); 297 var decoder = _StringDecoders.decoder(Encoding.UTF_8);
298 decoder.write( 298 decoder.write(
299 _controlPayload.getRange(2, _controlPayload.length - 2)); 299 _controlPayload.getRange(2, _controlPayload.length - 2));
300 reason = decoder.decoded(); 300 reason = decoder.decoded();
301 } 301 }
302 } 302 }
303 if (onClosed !== null) onClosed(status, reason); 303 if (onClosed != null) onClosed(status, reason);
304 _state = CLOSED; 304 _state = CLOSED;
305 break; 305 break;
306 306
307 case _WebSocketOpcode.PING: 307 case _WebSocketOpcode.PING:
308 if (onPing !== null) onPing(_controlPayload); 308 if (onPing != null) onPing(_controlPayload);
309 break; 309 break;
310 310
311 case _WebSocketOpcode.PONG: 311 case _WebSocketOpcode.PONG:
312 if (onPong !== null) onPong(_controlPayload); 312 if (onPong != null) onPong(_controlPayload);
313 break; 313 break;
314 } 314 }
315 _prepareForNextFrame(); 315 _prepareForNextFrame();
316 } 316 }
317 317
318 bool _isControlFrame() { 318 bool _isControlFrame() {
319 return _opcode == _WebSocketOpcode.CLOSE || 319 return _opcode == _WebSocketOpcode.CLOSE ||
320 _opcode == _WebSocketOpcode.PING || 320 _opcode == _WebSocketOpcode.PING ||
321 _opcode == _WebSocketOpcode.PONG; 321 _opcode == _WebSocketOpcode.PONG;
322 } 322 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 365 }
366 366
367 void _startProcessing(List<int> unparsedData) { 367 void _startProcessing(List<int> unparsedData) {
368 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor(); 368 _WebSocketProtocolProcessor processor = new _WebSocketProtocolProcessor();
369 processor.onMessageStart = _onWebSocketMessageStart; 369 processor.onMessageStart = _onWebSocketMessageStart;
370 processor.onMessageData = _onWebSocketMessageData; 370 processor.onMessageData = _onWebSocketMessageData;
371 processor.onMessageEnd = _onWebSocketMessageEnd; 371 processor.onMessageEnd = _onWebSocketMessageEnd;
372 processor.onPing = _onWebSocketPing; 372 processor.onPing = _onWebSocketPing;
373 processor.onPong = _onWebSocketPong; 373 processor.onPong = _onWebSocketPong;
374 processor.onClosed = _onWebSocketClosed; 374 processor.onClosed = _onWebSocketClosed;
375 if (unparsedData !== null) { 375 if (unparsedData != null) {
376 processor.update(unparsedData, 0, unparsedData.length); 376 processor.update(unparsedData, 0, unparsedData.length);
377 } 377 }
378 _socket.onData = () { 378 _socket.onData = () {
379 int available = _socket.available(); 379 int available = _socket.available();
380 List<int> data = new List<int>(available); 380 List<int> data = new List<int>(available);
381 int read = _socket.readList(data, 0, available); 381 int read = _socket.readList(data, 0, available);
382 processor.update(data, 0, read); 382 processor.update(data, 0, read);
383 }; 383 };
384 _socket.onClosed = () { 384 _socket.onClosed = () {
385 processor.closed(); 385 processor.closed();
386 if (_closeSent) { 386 if (_closeSent) {
387 // Got socket close in response to close frame. Don't treat 387 // Got socket close in response to close frame. Don't treat
388 // that as an error. 388 // that as an error.
389 if (_closeTimer !== null) _closeTimer.cancel(); 389 if (_closeTimer != null) _closeTimer.cancel();
390 } else { 390 } else {
391 if (_onClosed !== null) _onClosed(WebSocketStatus.ABNORMAL_CLOSURE, 391 if (_onClosed != null) _onClosed(WebSocketStatus.ABNORMAL_CLOSURE,
392 "Unexpected close"); 392 "Unexpected close");
393 } 393 }
394 _socket.close(); 394 _socket.close();
395 }; 395 };
396 } 396 }
397 397
398 void set onMessage(void callback(Object message)) { 398 void set onMessage(void callback(Object message)) {
399 _onMessage = callback; 399 _onMessage = callback;
400 } 400 }
401 401
402 void set onClosed(void callback(int status, String reason)) { 402 void set onClosed(void callback(int status, String reason)) {
403 _onClosed = callback; 403 _onClosed = callback;
404 } 404 }
405 405
406 send(message) { 406 send(message) {
407 if (_closeSent) { 407 if (_closeSent) {
408 throw new WebSocketException("Connection closed"); 408 throw new WebSocketException("Connection closed");
409 } 409 }
410 List<int> data; 410 List<int> data;
411 int opcode; 411 int opcode;
412 if (message !== null) { 412 if (message != null) {
413 if (message is String) { 413 if (message is String) {
414 opcode = _WebSocketOpcode.TEXT; 414 opcode = _WebSocketOpcode.TEXT;
415 data = _StringEncoders.encoder(Encoding.UTF_8).encodeString(message); 415 data = _StringEncoders.encoder(Encoding.UTF_8).encodeString(message);
416 } else { 416 } else {
417 if (message is !List<int>) { 417 if (message is !List<int>) {
418 throw new ArgumentError(message); 418 throw new ArgumentError(message);
419 } 419 }
420 opcode = _WebSocketOpcode.BINARY; 420 opcode = _WebSocketOpcode.BINARY;
421 data = message; 421 data = message;
422 } 422 }
423 } else { 423 } else {
424 opcode = _WebSocketOpcode.TEXT; 424 opcode = _WebSocketOpcode.TEXT;
425 } 425 }
426 _sendFrame(opcode, data); 426 _sendFrame(opcode, data);
427 } 427 }
428 428
429 close([int status, String reason]) { 429 close([int status, String reason]) {
430 if (status == WebSocketStatus.RESERVED_1004 || 430 if (status == WebSocketStatus.RESERVED_1004 ||
431 status == WebSocketStatus.NO_STATUS_RECEIVED || 431 status == WebSocketStatus.NO_STATUS_RECEIVED ||
432 status == WebSocketStatus.RESERVED_1015) { 432 status == WebSocketStatus.RESERVED_1015) {
433 throw new WebSocketException("Reserved status code $status"); 433 throw new WebSocketException("Reserved status code $status");
434 } 434 }
435 435
436 if (_closeSent) return; 436 if (_closeSent) return;
437 List<int> data; 437 List<int> data;
438 if (status !== null) { 438 if (status != null) {
439 data = new List<int>(); 439 data = new List<int>();
440 data.add((status >> 8) & 0xFF); 440 data.add((status >> 8) & 0xFF);
441 data.add(status & 0xFF); 441 data.add(status & 0xFF);
442 if (reason !== null) { 442 if (reason != null) {
443 data.addAll( 443 data.addAll(
444 _StringEncoders.encoder(Encoding.UTF_8).encodeString(reason)); 444 _StringEncoders.encoder(Encoding.UTF_8).encodeString(reason));
445 } 445 }
446 } 446 }
447 _sendFrame(_WebSocketOpcode.CLOSE, data); 447 _sendFrame(_WebSocketOpcode.CLOSE, data);
448 448
449 if (_closeReceived) { 449 if (_closeReceived) {
450 // Close the socket when the close frame has been sent - if it 450 // Close the socket when the close frame has been sent - if it
451 // does not take too long. 451 // does not take too long.
452 _socket.outputStream.close(); 452 _socket.outputStream.close();
453 _socket.outputStream.onClosed = () { 453 _socket.outputStream.onClosed = () {
454 if (_closeTimer !== null) _closeTimer.cancel(); 454 if (_closeTimer != null) _closeTimer.cancel();
455 _socket.close(); 455 _socket.close();
456 }; 456 };
457 _closeTimer = new Timer(5000, (t) { 457 _closeTimer = new Timer(5000, (t) {
458 _socket.close(); 458 _socket.close();
459 }); 459 });
460 } else { 460 } else {
461 // Half close the socket and expect a close frame in response 461 // Half close the socket and expect a close frame in response
462 // before closing the socket. If a close frame does not arrive 462 // before closing the socket. If a close frame does not arrive
463 // within a reasonable amount of time just close the socket. 463 // within a reasonable amount of time just close the socket.
464 _socket.outputStream.close(); 464 _socket.outputStream.close();
(...skipping 17 matching lines...) Expand all
482 482
483 _onWebSocketMessageData(List<int> buffer, int offset, int count) { 483 _onWebSocketMessageData(List<int> buffer, int offset, int count) {
484 if (_currentMessageType == _WebSocketMessageType.TEXT) { 484 if (_currentMessageType == _WebSocketMessageType.TEXT) {
485 _decoder.write(buffer.getRange(offset, count)); 485 _decoder.write(buffer.getRange(offset, count));
486 } else { 486 } else {
487 _outputStream.write(buffer.getRange(offset, count)); 487 _outputStream.write(buffer.getRange(offset, count));
488 } 488 }
489 } 489 }
490 490
491 _onWebSocketMessageEnd() { 491 _onWebSocketMessageEnd() {
492 if (_onMessage !== null) { 492 if (_onMessage != null) {
493 if (_currentMessageType == _WebSocketMessageType.TEXT) { 493 if (_currentMessageType == _WebSocketMessageType.TEXT) {
494 _onMessage(_decoder.decoded()); 494 _onMessage(_decoder.decoded());
495 } else { 495 } else {
496 _onMessage(_outputStream.read()); 496 _onMessage(_outputStream.read());
497 } 497 }
498 } 498 }
499 _decoder = null; 499 _decoder = null;
500 _outputStream = null; 500 _outputStream = null;
501 } 501 }
502 502
503 _onWebSocketPing(List<int> payload) { 503 _onWebSocketPing(List<int> payload) {
504 _sendFrame(_WebSocketOpcode.PONG, payload); 504 _sendFrame(_WebSocketOpcode.PONG, payload);
505 } 505 }
506 506
507 _onWebSocketPong(List<int> payload) { 507 _onWebSocketPong(List<int> payload) {
508 // Currently pong messages are ignored. 508 // Currently pong messages are ignored.
509 } 509 }
510 510
511 _onWebSocketClosed(int status, String reason) { 511 _onWebSocketClosed(int status, String reason) {
512 _closeReceived = true; 512 _closeReceived = true;
513 if (_onClosed !== null) _onClosed(status, reason); 513 if (_onClosed != null) _onClosed(status, reason);
514 if (_closeSent) { 514 if (_closeSent) {
515 // Got close frame in response to close frame. Now close the socket. 515 // Got close frame in response to close frame. Now close the socket.
516 if (_closeTimer !== null) _closeTimer.cancel(); 516 if (_closeTimer != null) _closeTimer.cancel();
517 _socket.close(); 517 _socket.close();
518 } else { 518 } else {
519 if (status != WebSocketStatus.NO_STATUS_RECEIVED) { 519 if (status != WebSocketStatus.NO_STATUS_RECEIVED) {
520 close(status); 520 close(status);
521 } else { 521 } else {
522 close(); 522 close();
523 } 523 }
524 } 524 }
525 } 525 }
526 526
(...skipping 20 matching lines...) Expand all
547 } else if (dataLength > 125) { 547 } else if (dataLength > 125) {
548 header[index++] = 126; 548 header[index++] = 126;
549 lengthBytes = 2; 549 lengthBytes = 2;
550 } 550 }
551 // Write the length in network byte order into the header. 551 // Write the length in network byte order into the header.
552 for (int i = 0; i < lengthBytes; i++) { 552 for (int i = 0; i < lengthBytes; i++) {
553 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF; 553 header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF;
554 } 554 }
555 assert(index == headerSize); 555 assert(index == headerSize);
556 _socket.outputStream.write(header); 556 _socket.outputStream.write(header);
557 if (data !== null) { 557 if (data != null) {
558 _socket.outputStream.write(data); 558 _socket.outputStream.write(data);
559 } 559 }
560 } 560 }
561 561
562 Socket _socket; 562 Socket _socket;
563 Timer _closeTimer; 563 Timer _closeTimer;
564 int _hash; 564 int _hash;
565 565
566 Function _onMessage; 566 Function _onMessage;
567 Function _onClosed; 567 Function _onClosed;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 String key = request.headers.value("Sec-WebSocket-Key"); 600 String key = request.headers.value("Sec-WebSocket-Key");
601 SHA1 sha1 = new SHA1(); 601 SHA1 sha1 = new SHA1();
602 sha1.update("$key$_webSocketGUID".charCodes); 602 sha1.update("$key$_webSocketGUID".charCodes);
603 String accept = _Base64._encode(sha1.digest()); 603 String accept = _Base64._encode(sha1.digest());
604 response.headers.add("Sec-WebSocket-Accept", accept); 604 response.headers.add("Sec-WebSocket-Accept", accept);
605 response.contentLength = 0; 605 response.contentLength = 0;
606 606
607 // Upgrade the connection and get the underlying socket. 607 // Upgrade the connection and get the underlying socket.
608 WebSocketConnection conn = 608 WebSocketConnection conn =
609 new _WebSocketConnection(response.detachSocket()); 609 new _WebSocketConnection(response.detachSocket());
610 if (_onOpen !== null) _onOpen(conn); 610 if (_onOpen != null) _onOpen(conn);
611 } 611 }
612 612
613 void set onOpen(callback(WebSocketConnection connection)) { 613 void set onOpen(callback(WebSocketConnection connection)) {
614 _onOpen = callback; 614 _onOpen = callback;
615 } 615 }
616 616
617 bool _isWebSocketUpgrade(HttpRequest request) { 617 bool _isWebSocketUpgrade(HttpRequest request) {
618 if (request.method != "GET") { 618 if (request.method != "GET") {
619 return false; 619 return false;
620 } 620 }
(...skipping 24 matching lines...) Expand all
645 } 645 }
646 646
647 647
648 class _WebSocketClientConnection 648 class _WebSocketClientConnection
649 extends _WebSocketConnectionBase implements WebSocketClientConnection { 649 extends _WebSocketConnectionBase implements WebSocketClientConnection {
650 _WebSocketClientConnection(HttpClientConnection this._conn, 650 _WebSocketClientConnection(HttpClientConnection this._conn,
651 [List<String> protocols]) { 651 [List<String> protocols]) {
652 _conn.onRequest = _onHttpClientRequest; 652 _conn.onRequest = _onHttpClientRequest;
653 _conn.onResponse = _onHttpClientResponse; 653 _conn.onResponse = _onHttpClientResponse;
654 _conn.onError = (e) { 654 _conn.onError = (e) {
655 if (_onClosed !== null) { 655 if (_onClosed != null) {
656 _onClosed(WebSocketStatus.ABNORMAL_CLOSURE, "$e"); 656 _onClosed(WebSocketStatus.ABNORMAL_CLOSURE, "$e");
657 } 657 }
658 }; 658 };
659 659
660 // Generate the nonce now as it is also used to set the hash code. 660 // Generate the nonce now as it is also used to set the hash code.
661 _generateNonceAndHash(); 661 _generateNonceAndHash();
662 } 662 }
663 663
664 void set onRequest(void callback(HttpClientRequest request)) { 664 void set onRequest(void callback(HttpClientRequest request)) {
665 _onRequest = callback; 665 _onRequest = callback;
666 } 666 }
667 667
668 void set onOpen(void callback()) { 668 void set onOpen(void callback()) {
669 _onOpen = callback; 669 _onOpen = callback;
670 } 670 }
671 671
672 void set onNoUpgrade(void callback(HttpClientResponse request)) { 672 void set onNoUpgrade(void callback(HttpClientResponse request)) {
673 _onNoUpgrade = callback; 673 _onNoUpgrade = callback;
674 } 674 }
675 675
676 void _onHttpClientRequest(HttpClientRequest request) { 676 void _onHttpClientRequest(HttpClientRequest request) {
677 if (_onRequest !== null) { 677 if (_onRequest != null) {
678 _onRequest(request); 678 _onRequest(request);
679 } 679 }
680 // Setup the initial handshake. 680 // Setup the initial handshake.
681 request.headers.add(HttpHeaders.CONNECTION, "upgrade"); 681 request.headers.add(HttpHeaders.CONNECTION, "upgrade");
682 request.headers.set(HttpHeaders.UPGRADE, "websocket"); 682 request.headers.set(HttpHeaders.UPGRADE, "websocket");
683 request.headers.set("Sec-WebSocket-Key", _nonce); 683 request.headers.set("Sec-WebSocket-Key", _nonce);
684 request.headers.set("Sec-WebSocket-Version", "13"); 684 request.headers.set("Sec-WebSocket-Version", "13");
685 request.contentLength = 0; 685 request.contentLength = 0;
686 request.outputStream.close(); 686 request.outputStream.close();
687 } 687 }
688 688
689 void _onHttpClientResponse(HttpClientResponse response) { 689 void _onHttpClientResponse(HttpClientResponse response) {
690 if (response.statusCode != HttpStatus.SWITCHING_PROTOCOLS) { 690 if (response.statusCode != HttpStatus.SWITCHING_PROTOCOLS) {
691 if (_onNoUpgrade !== null) { 691 if (_onNoUpgrade != null) {
692 _onNoUpgrade(response); 692 _onNoUpgrade(response);
693 } else { 693 } else {
694 _conn.detachSocket().socket.close(); 694 _conn.detachSocket().socket.close();
695 throw new WebSocketException("Protocol upgrade refused"); 695 throw new WebSocketException("Protocol upgrade refused");
696 } 696 }
697 return; 697 return;
698 } 698 }
699 699
700 if (!_isWebSocketUpgrade(response)) { 700 if (!_isWebSocketUpgrade(response)) {
701 _conn.detachSocket().socket.close(); 701 _conn.detachSocket().socket.close();
702 throw new WebSocketException("Protocol upgrade failed"); 702 throw new WebSocketException("Protocol upgrade failed");
703 return; 703 return;
704 } 704 }
705 705
706 // Connection upgrade successful. 706 // Connection upgrade successful.
707 DetachedSocket detached = _conn.detachSocket(); 707 DetachedSocket detached = _conn.detachSocket();
708 _socketConnected(detached.socket); 708 _socketConnected(detached.socket);
709 if (_onOpen !== null) _onOpen(); 709 if (_onOpen != null) _onOpen();
710 _startProcessing(detached.unparsedData); 710 _startProcessing(detached.unparsedData);
711 } 711 }
712 712
713 void _generateNonceAndHash() { 713 void _generateNonceAndHash() {
714 Random random = new Random(); 714 Random random = new Random();
715 assert(_nonce == null); 715 assert(_nonce == null);
716 void intToBigEndianBytes(int value, List<int> bytes, int offset) { 716 void intToBigEndianBytes(int value, List<int> bytes, int offset) {
717 bytes[offset] = (value >> 24) & 0xFF; 717 bytes[offset] = (value >> 24) & 0xFF;
718 bytes[offset + 1] = (value >> 16) & 0xFF; 718 bytes[offset + 1] = (value >> 16) & 0xFF;
719 bytes[offset + 2] = (value >> 8) & 0xFF; 719 bytes[offset + 2] = (value >> 8) & 0xFF;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 788
789 HttpClient client = new HttpClient(); 789 HttpClient client = new HttpClient();
790 HttpClientConnection conn = client.open("GET", uri.domain, port, path); 790 HttpClientConnection conn = client.open("GET", uri.domain, port, path);
791 if (protocols is String) protocols = [protocols]; 791 if (protocols is String) protocols = [protocols];
792 _wsconn = new WebSocketClientConnection(conn, protocols); 792 _wsconn = new WebSocketClientConnection(conn, protocols);
793 _wsconn.onOpen = () { 793 _wsconn.onOpen = () {
794 // HTTP client not needed after socket have been detached. 794 // HTTP client not needed after socket have been detached.
795 client.shutdown(); 795 client.shutdown();
796 client = null; 796 client = null;
797 _readyState = WebSocket.OPEN; 797 _readyState = WebSocket.OPEN;
798 if (_onopen !== null) _onopen(); 798 if (_onopen != null) _onopen();
799 }; 799 };
800 _wsconn.onMessage = (message) { 800 _wsconn.onMessage = (message) {
801 if (_onmessage !== null) { 801 if (_onmessage != null) {
802 _onmessage(new _WebSocketMessageEvent(message)); 802 _onmessage(new _WebSocketMessageEvent(message));
803 } 803 }
804 }; 804 };
805 _wsconn.onClosed = (status, reason) { 805 _wsconn.onClosed = (status, reason) {
806 _readyState = WebSocket.CLOSED; 806 _readyState = WebSocket.CLOSED;
807 if (_onclose !== null) { 807 if (_onclose != null) {
808 _onclose(new _WebSocketCloseEvent(true, status, reason)); 808 _onclose(new _WebSocketCloseEvent(true, status, reason));
809 } 809 }
810 }; 810 };
811 _wsconn.onNoUpgrade = (response) { 811 _wsconn.onNoUpgrade = (response) {
812 if (_onclose !== null) { 812 if (_onclose != null) {
813 _onclose( 813 _onclose(
814 new _WebSocketCloseEvent(true, 814 new _WebSocketCloseEvent(true,
815 WebSocketStatus.ABNORMAL_CLOSURE, 815 WebSocketStatus.ABNORMAL_CLOSURE,
816 "Connection not upgraded")); 816 "Connection not upgraded"));
817 } 817 }
818 }; 818 };
819 } 819 }
820 820
821 int get readyState => _readyState; 821 int get readyState => _readyState;
822 int get bufferedAmount => 0; 822 int get bufferedAmount => 0;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 864
865 class _WebSocketCloseEvent implements CloseEvent { 865 class _WebSocketCloseEvent implements CloseEvent {
866 _WebSocketCloseEvent(this._wasClean, this._code, this._reason); 866 _WebSocketCloseEvent(this._wasClean, this._code, this._reason);
867 bool get wasClean => _wasClean; 867 bool get wasClean => _wasClean;
868 int get code => _code; 868 int get code => _code;
869 String get reason => _reason; 869 String get reason => _reason;
870 bool _wasClean; 870 bool _wasClean;
871 int _code; 871 int _code;
872 String _reason; 872 String _reason;
873 } 873 }
OLDNEW
« no previous file with comments | « sdk/lib/io/timer_impl.dart ('k') | sdk/lib/mirrors/mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698