| OLD | NEW |
| 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 // Global constants. | 7 // Global constants. |
| 8 class _Const { | 8 class _Const { |
| 9 // Bytes for "HTTP". | 9 // Bytes for "HTTP". |
| 10 static const HTTP = const [72, 84, 84, 80]; | 10 static const HTTP = const [72, 84, 84, 80]; |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 240 |
| 241 // The data that is currently being parsed. | 241 // The data that is currently being parsed. |
| 242 Uint8List _buffer; | 242 Uint8List _buffer; |
| 243 int _index; | 243 int _index; |
| 244 | 244 |
| 245 final bool _requestParser; | 245 final bool _requestParser; |
| 246 int _state; | 246 int _state; |
| 247 int _httpVersionIndex; | 247 int _httpVersionIndex; |
| 248 int _messageType; | 248 int _messageType; |
| 249 int _statusCode = 0; | 249 int _statusCode = 0; |
| 250 List _method_or_status_code; | 250 int _statusCodeLength = 0; |
| 251 List _uri_or_reason_phrase; | 251 final List<int> _method = []; |
| 252 List _headerField; | 252 final List<int> _uri_or_reason_phrase = []; |
| 253 List _headerValue; | 253 final List<int> _headerField = []; |
| 254 final List<int> _headerValue = []; |
| 254 | 255 |
| 255 int _httpVersion; | 256 int _httpVersion; |
| 256 int _transferLength = -1; | 257 int _transferLength = -1; |
| 257 bool _persistentConnection; | 258 bool _persistentConnection; |
| 258 bool _connectionUpgrade; | 259 bool _connectionUpgrade; |
| 259 bool _chunked; | 260 bool _chunked; |
| 260 | 261 |
| 261 bool _noMessageBody; | 262 bool _noMessageBody = false; |
| 262 String _responseToMethod; // Indicates the method used for the request. | |
| 263 int _remainingContent = -1; | 263 int _remainingContent = -1; |
| 264 | 264 |
| 265 _HttpHeaders _headers; | 265 _HttpHeaders _headers; |
| 266 | 266 |
| 267 // The current incoming connection. | 267 // The current incoming connection. |
| 268 _HttpIncoming _incoming; | 268 _HttpIncoming _incoming; |
| 269 StreamSubscription _socketSubscription; | 269 StreamSubscription _socketSubscription; |
| 270 bool _paused = true; | 270 bool _paused = true; |
| 271 bool _bodyPaused = false; | 271 bool _bodyPaused = false; |
| 272 StreamController<_HttpIncoming> _controller; | 272 StreamController<_HttpIncoming> _controller; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 case _State.START: | 367 case _State.START: |
| 368 if (byte == _Const.HTTP[0]) { | 368 if (byte == _Const.HTTP[0]) { |
| 369 // Start parsing method or HTTP version. | 369 // Start parsing method or HTTP version. |
| 370 _httpVersionIndex = 1; | 370 _httpVersionIndex = 1; |
| 371 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; | 371 _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION; |
| 372 } else { | 372 } else { |
| 373 // Start parsing method. | 373 // Start parsing method. |
| 374 if (!_isTokenChar(byte)) { | 374 if (!_isTokenChar(byte)) { |
| 375 throw new HttpException("Invalid request method"); | 375 throw new HttpException("Invalid request method"); |
| 376 } | 376 } |
| 377 _method_or_status_code.add(byte); | 377 _method.add(byte); |
| 378 if (!_requestParser) { | 378 if (!_requestParser) { |
| 379 throw new HttpException("Invalid response line"); | 379 throw new HttpException("Invalid response line"); |
| 380 } | 380 } |
| 381 _state = _State.REQUEST_LINE_METHOD; | 381 _state = _State.REQUEST_LINE_METHOD; |
| 382 } | 382 } |
| 383 break; | 383 break; |
| 384 | 384 |
| 385 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: | 385 case _State.METHOD_OR_RESPONSE_HTTP_VERSION: |
| 386 if (_httpVersionIndex < _Const.HTTP.length && | 386 if (_httpVersionIndex < _Const.HTTP.length && |
| 387 byte == _Const.HTTP[_httpVersionIndex]) { | 387 byte == _Const.HTTP[_httpVersionIndex]) { |
| 388 // Continue parsing HTTP version. | 388 // Continue parsing HTTP version. |
| 389 _httpVersionIndex++; | 389 _httpVersionIndex++; |
| 390 } else if (_httpVersionIndex == _Const.HTTP.length && | 390 } else if (_httpVersionIndex == _Const.HTTP.length && |
| 391 byte == _CharCode.SLASH) { | 391 byte == _CharCode.SLASH) { |
| 392 // HTTP/ parsed. As method is a token this cannot be a | 392 // HTTP/ parsed. As method is a token this cannot be a |
| 393 // method anymore. | 393 // method anymore. |
| 394 _httpVersionIndex++; | 394 _httpVersionIndex++; |
| 395 if (_requestParser) { | 395 if (_requestParser) { |
| 396 throw new HttpException("Invalid request line"); | 396 throw new HttpException("Invalid request line"); |
| 397 } | 397 } |
| 398 _state = _State.RESPONSE_HTTP_VERSION; | 398 _state = _State.RESPONSE_HTTP_VERSION; |
| 399 } else { | 399 } else { |
| 400 // Did not parse HTTP version. Expect method instead. | 400 // Did not parse HTTP version. Expect method instead. |
| 401 for (int i = 0; i < _httpVersionIndex; i++) { | 401 for (int i = 0; i < _httpVersionIndex; i++) { |
| 402 _method_or_status_code.add(_Const.HTTP[i]); | 402 _method.add(_Const.HTTP[i]); |
| 403 } | 403 } |
| 404 if (byte == _CharCode.SP) { | 404 if (byte == _CharCode.SP) { |
| 405 _state = _State.REQUEST_LINE_URI; | 405 _state = _State.REQUEST_LINE_URI; |
| 406 } else { | 406 } else { |
| 407 _method_or_status_code.add(byte); | 407 _method.add(byte); |
| 408 _httpVersion = _HttpVersion.UNDETERMINED; | 408 _httpVersion = _HttpVersion.UNDETERMINED; |
| 409 if (!_requestParser) { | 409 if (!_requestParser) { |
| 410 throw new HttpException("Invalid response line"); | 410 throw new HttpException("Invalid response line"); |
| 411 } | 411 } |
| 412 _state = _State.REQUEST_LINE_METHOD; | 412 _state = _State.REQUEST_LINE_METHOD; |
| 413 } | 413 } |
| 414 } | 414 } |
| 415 break; | 415 break; |
| 416 | 416 |
| 417 case _State.RESPONSE_HTTP_VERSION: | 417 case _State.RESPONSE_HTTP_VERSION: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 442 | 442 |
| 443 case _State.REQUEST_LINE_METHOD: | 443 case _State.REQUEST_LINE_METHOD: |
| 444 if (byte == _CharCode.SP) { | 444 if (byte == _CharCode.SP) { |
| 445 _state = _State.REQUEST_LINE_URI; | 445 _state = _State.REQUEST_LINE_URI; |
| 446 } else { | 446 } else { |
| 447 if (_Const.SEPARATOR_MAP[byte] || | 447 if (_Const.SEPARATOR_MAP[byte] || |
| 448 byte == _CharCode.CR || | 448 byte == _CharCode.CR || |
| 449 byte == _CharCode.LF) { | 449 byte == _CharCode.LF) { |
| 450 throw new HttpException("Invalid request method"); | 450 throw new HttpException("Invalid request method"); |
| 451 } | 451 } |
| 452 _method_or_status_code.add(byte); | 452 _method.add(byte); |
| 453 } | 453 } |
| 454 break; | 454 break; |
| 455 | 455 |
| 456 case _State.REQUEST_LINE_URI: | 456 case _State.REQUEST_LINE_URI: |
| 457 if (byte == _CharCode.SP) { | 457 if (byte == _CharCode.SP) { |
| 458 if (_uri_or_reason_phrase.length == 0) { | 458 if (_uri_or_reason_phrase.length == 0) { |
| 459 throw new HttpException("Invalid request URI"); | 459 throw new HttpException("Invalid request URI"); |
| 460 } | 460 } |
| 461 _state = _State.REQUEST_LINE_HTTP_VERSION; | 461 _state = _State.REQUEST_LINE_HTTP_VERSION; |
| 462 _httpVersionIndex = 0; | 462 _httpVersionIndex = 0; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 493 break; | 493 break; |
| 494 | 494 |
| 495 case _State.REQUEST_LINE_ENDING: | 495 case _State.REQUEST_LINE_ENDING: |
| 496 _expect(byte, _CharCode.LF); | 496 _expect(byte, _CharCode.LF); |
| 497 _messageType = _MessageType.REQUEST; | 497 _messageType = _MessageType.REQUEST; |
| 498 _state = _State.HEADER_START; | 498 _state = _State.HEADER_START; |
| 499 break; | 499 break; |
| 500 | 500 |
| 501 case _State.RESPONSE_LINE_STATUS_CODE: | 501 case _State.RESPONSE_LINE_STATUS_CODE: |
| 502 if (byte == _CharCode.SP) { | 502 if (byte == _CharCode.SP) { |
| 503 if (_method_or_status_code.length != 3) { | |
| 504 throw new HttpException("Invalid response status code"); | |
| 505 } | |
| 506 _state = _State.RESPONSE_LINE_REASON_PHRASE; | 503 _state = _State.RESPONSE_LINE_REASON_PHRASE; |
| 507 } else if (byte == _CharCode.CR) { | 504 } else if (byte == _CharCode.CR) { |
| 508 // Some HTTP servers does not follow the spec. and send | 505 // Some HTTP servers does not follow the spec. and send |
| 509 // \r\n right after the status code. | 506 // \r\n right after the status code. |
| 510 _state = _State.RESPONSE_LINE_ENDING; | 507 _state = _State.RESPONSE_LINE_ENDING; |
| 511 } else { | 508 } else { |
| 512 if (byte < 0x30 && 0x39 < byte) { | 509 _statusCodeLength++; |
| 510 if ((byte < 0x30 && 0x39 < byte) || _statusCodeLength > 3) { |
| 513 throw new HttpException("Invalid response status code"); | 511 throw new HttpException("Invalid response status code"); |
| 514 } else { | 512 } else { |
| 515 _method_or_status_code.add(byte); | 513 _statusCode = _statusCode * 10 + byte - 0x30; |
| 516 } | 514 } |
| 517 } | 515 } |
| 518 break; | 516 break; |
| 519 | 517 |
| 520 case _State.RESPONSE_LINE_REASON_PHRASE: | 518 case _State.RESPONSE_LINE_REASON_PHRASE: |
| 521 if (byte == _CharCode.CR) { | 519 if (byte == _CharCode.CR) { |
| 522 _state = _State.RESPONSE_LINE_ENDING; | 520 _state = _State.RESPONSE_LINE_ENDING; |
| 523 } else { | 521 } else { |
| 524 if (byte == _CharCode.CR || byte == _CharCode.LF) { | 522 if (byte == _CharCode.CR || byte == _CharCode.LF) { |
| 525 throw new HttpException("Invalid response reason phrase"); | 523 throw new HttpException("Invalid response reason phrase"); |
| 526 } | 524 } |
| 527 _uri_or_reason_phrase.add(byte); | 525 _uri_or_reason_phrase.add(byte); |
| 528 } | 526 } |
| 529 break; | 527 break; |
| 530 | 528 |
| 531 case _State.RESPONSE_LINE_ENDING: | 529 case _State.RESPONSE_LINE_ENDING: |
| 532 _expect(byte, _CharCode.LF); | 530 _expect(byte, _CharCode.LF); |
| 533 _messageType == _MessageType.RESPONSE; | 531 _messageType == _MessageType.RESPONSE; |
| 534 _statusCode = int.parse( | |
| 535 new String.fromCharCodes(_method_or_status_code)); | |
| 536 if (_statusCode < 100 || _statusCode > 599) { | 532 if (_statusCode < 100 || _statusCode > 599) { |
| 537 throw new HttpException("Invalid response status code"); | 533 throw new HttpException("Invalid response status code"); |
| 538 } else { | 534 } else { |
| 539 // Check whether this response will never have a body. | 535 // Check whether this response will never have a body. |
| 540 _noMessageBody = _statusCode <= 199 || _statusCode == 204 || | 536 if (_statusCode <= 199 || _statusCode == 204 || |
| 541 _statusCode == 304; | 537 _statusCode == 304) { |
| 538 _noMessageBody = true; |
| 539 } |
| 542 } | 540 } |
| 543 _state = _State.HEADER_START; | 541 _state = _State.HEADER_START; |
| 544 break; | 542 break; |
| 545 | 543 |
| 546 case _State.HEADER_START: | 544 case _State.HEADER_START: |
| 547 _headers = new _HttpHeaders(version); | 545 _headers = new _HttpHeaders(version); |
| 548 if (byte == _CharCode.CR) { | 546 if (byte == _CharCode.CR) { |
| 549 _state = _State.HEADER_ENDING; | 547 _state = _State.HEADER_ENDING; |
| 550 } else { | 548 } else { |
| 551 // Start of new header field. | 549 // Start of new header field. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 _state = _State.HEADER_VALUE_FOLD_OR_END; | 586 _state = _State.HEADER_VALUE_FOLD_OR_END; |
| 589 break; | 587 break; |
| 590 | 588 |
| 591 case _State.HEADER_VALUE_FOLD_OR_END: | 589 case _State.HEADER_VALUE_FOLD_OR_END: |
| 592 if (byte == _CharCode.SP || byte == _CharCode.HT) { | 590 if (byte == _CharCode.SP || byte == _CharCode.HT) { |
| 593 _state = _State.HEADER_VALUE_START; | 591 _state = _State.HEADER_VALUE_START; |
| 594 } else { | 592 } else { |
| 595 String headerField = new String.fromCharCodes(_headerField); | 593 String headerField = new String.fromCharCodes(_headerField); |
| 596 String headerValue = new String.fromCharCodes(_headerValue); | 594 String headerValue = new String.fromCharCodes(_headerValue); |
| 597 if (headerField == "transfer-encoding" && | 595 if (headerField == "transfer-encoding" && |
| 598 headerValue.toLowerCase() == "chunked") { | 596 _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) { |
| 599 _chunked = true; | 597 _chunked = true; |
| 600 } | 598 } |
| 601 if (headerField == "connection") { | 599 if (headerField == "connection") { |
| 602 List<String> tokens = _tokenizeFieldValue(headerValue); | 600 List<String> tokens = _tokenizeFieldValue(headerValue); |
| 603 for (int i = 0; i < tokens.length; i++) { | 601 for (int i = 0; i < tokens.length; i++) { |
| 604 if (tokens[i].toLowerCase() == "upgrade") { | 602 if (_caseInsensitiveCompare("upgrade".codeUnits, |
| 603 tokens[i].codeUnits)) { |
| 605 _connectionUpgrade = true; | 604 _connectionUpgrade = true; |
| 606 } | 605 } |
| 607 _headers._add(headerField, tokens[i]); | 606 _headers._add(headerField, tokens[i]); |
| 608 } | 607 } |
| 609 } else { | 608 } else { |
| 610 _headers._add(headerField, headerValue); | 609 _headers._add(headerField, headerValue); |
| 611 } | 610 } |
| 612 _headerField.clear(); | 611 _headerField.clear(); |
| 613 _headerValue.clear(); | 612 _headerValue.clear(); |
| 614 | 613 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 639 _chunked == false) { | 638 _chunked == false) { |
| 640 _transferLength = 0; | 639 _transferLength = 0; |
| 641 } | 640 } |
| 642 if (_connectionUpgrade) { | 641 if (_connectionUpgrade) { |
| 643 _state = _State.UPGRADED; | 642 _state = _State.UPGRADED; |
| 644 _transferLength = 0; | 643 _transferLength = 0; |
| 645 } | 644 } |
| 646 _createIncoming(_transferLength); | 645 _createIncoming(_transferLength); |
| 647 if (_requestParser) { | 646 if (_requestParser) { |
| 648 _incoming.method = | 647 _incoming.method = |
| 649 new String.fromCharCodes(_method_or_status_code); | 648 new String.fromCharCodes(_method); |
| 650 _incoming.uri = | 649 _incoming.uri = |
| 651 Uri.parse( | 650 Uri.parse( |
| 652 new String.fromCharCodes(_uri_or_reason_phrase)); | 651 new String.fromCharCodes(_uri_or_reason_phrase)); |
| 653 } else { | 652 } else { |
| 654 _incoming.statusCode = _statusCode; | 653 _incoming.statusCode = _statusCode; |
| 655 _incoming.reasonPhrase = | 654 _incoming.reasonPhrase = |
| 656 new String.fromCharCodes(_uri_or_reason_phrase); | 655 new String.fromCharCodes(_uri_or_reason_phrase); |
| 657 } | 656 } |
| 658 _method_or_status_code.clear(); | 657 _method.clear(); |
| 659 _uri_or_reason_phrase.clear(); | 658 _uri_or_reason_phrase.clear(); |
| 660 if (_connectionUpgrade) { | 659 if (_connectionUpgrade) { |
| 661 _incoming.upgraded = true; | 660 _incoming.upgraded = true; |
| 662 _parserCalled = false; | 661 _parserCalled = false; |
| 663 var tmp = _incoming; | 662 var tmp = _incoming; |
| 664 _closeIncoming(); | 663 _closeIncoming(); |
| 665 _controller.add(tmp); | 664 _controller.add(tmp); |
| 666 return; | 665 return; |
| 667 } | 666 } |
| 668 if (_transferLength == 0 || | 667 if (_transferLength == 0 || |
| 669 (_messageType == _MessageType.RESPONSE && | 668 (_messageType == _MessageType.RESPONSE && _noMessageBody)) { |
| 670 (_noMessageBody || _responseToMethod == "HEAD"))) { | |
| 671 _reset(); | 669 _reset(); |
| 672 var tmp = _incoming; | 670 var tmp = _incoming; |
| 673 _closeIncoming(); | 671 _closeIncoming(); |
| 674 _controller.add(tmp); | 672 _controller.add(tmp); |
| 675 break; | 673 break; |
| 676 } else if (_chunked) { | 674 } else if (_chunked) { |
| 677 _state = _State.CHUNK_SIZE; | 675 _state = _State.CHUNK_SIZE; |
| 678 _remainingContent = 0; | 676 _remainingContent = 0; |
| 679 } else if (_transferLength > 0) { | 677 } else if (_transferLength > 0) { |
| 680 _remainingContent = _transferLength; | 678 _remainingContent = _transferLength; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 return "1.1"; | 857 return "1.1"; |
| 860 } | 858 } |
| 861 return null; | 859 return null; |
| 862 } | 860 } |
| 863 | 861 |
| 864 int get messageType => _messageType; | 862 int get messageType => _messageType; |
| 865 int get transferLength => _transferLength; | 863 int get transferLength => _transferLength; |
| 866 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; | 864 bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; |
| 867 bool get persistentConnection => _persistentConnection; | 865 bool get persistentConnection => _persistentConnection; |
| 868 | 866 |
| 869 void set responseToMethod(String method) { _responseToMethod = method; } | 867 void set isHead(bool value) { |
| 868 if (value) _noMessageBody = true; |
| 869 } |
| 870 | 870 |
| 871 _HttpDetachedIncoming detachIncoming() { | 871 _HttpDetachedIncoming detachIncoming() { |
| 872 // Simulate detached by marking as upgraded. | 872 // Simulate detached by marking as upgraded. |
| 873 _state = _State.UPGRADED; | 873 _state = _State.UPGRADED; |
| 874 return new _HttpDetachedIncoming(_socketSubscription, | 874 return new _HttpDetachedIncoming(_socketSubscription, |
| 875 readUnparsedData()); | 875 readUnparsedData()); |
| 876 } | 876 } |
| 877 | 877 |
| 878 List<int> readUnparsedData() { | 878 List<int> readUnparsedData() { |
| 879 if (_buffer == null) return null; | 879 if (_buffer == null) return null; |
| 880 if (_index == _buffer.length) return null; | 880 if (_index == _buffer.length) return null; |
| 881 var result = _buffer.sublist(_index); | 881 var result = _buffer.sublist(_index); |
| 882 _releaseBuffer(); | 882 _releaseBuffer(); |
| 883 return result; | 883 return result; |
| 884 } | 884 } |
| 885 | 885 |
| 886 void _reset() { | 886 void _reset() { |
| 887 if (_state == _State.UPGRADED) return; | 887 if (_state == _State.UPGRADED) return; |
| 888 _state = _State.START; | 888 _state = _State.START; |
| 889 _messageType = _MessageType.UNDETERMINED; | 889 _messageType = _MessageType.UNDETERMINED; |
| 890 _headerField = new List(); | 890 _headerField.clear(); |
| 891 _headerValue = new List(); | 891 _headerValue.clear(); |
| 892 _method_or_status_code = new List(); | 892 _method.clear(); |
| 893 _uri_or_reason_phrase = new List(); | 893 _uri_or_reason_phrase.clear(); |
| 894 | 894 |
| 895 _statusCode = 0; | 895 _statusCode = 0; |
| 896 _statusCodeLength = 0; |
| 896 | 897 |
| 897 _httpVersion = _HttpVersion.UNDETERMINED; | 898 _httpVersion = _HttpVersion.UNDETERMINED; |
| 898 _transferLength = -1; | 899 _transferLength = -1; |
| 899 _persistentConnection = false; | 900 _persistentConnection = false; |
| 900 _connectionUpgrade = false; | 901 _connectionUpgrade = false; |
| 901 _chunked = false; | 902 _chunked = false; |
| 902 | 903 |
| 903 _noMessageBody = false; | 904 _noMessageBody = false; |
| 904 _responseToMethod = null; | |
| 905 _remainingContent = -1; | 905 _remainingContent = -1; |
| 906 | 906 |
| 907 _headers = null; | 907 _headers = null; |
| 908 } | 908 } |
| 909 | 909 |
| 910 void _releaseBuffer() { | 910 void _releaseBuffer() { |
| 911 _buffer = null; | 911 _buffer = null; |
| 912 _index = null; | 912 _index = null; |
| 913 } | 913 } |
| 914 | 914 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 933 return tokens; | 933 return tokens; |
| 934 } | 934 } |
| 935 | 935 |
| 936 int _toLowerCase(int byte) { | 936 int _toLowerCase(int byte) { |
| 937 final int aCode = "A".codeUnitAt(0); | 937 final int aCode = "A".codeUnitAt(0); |
| 938 final int zCode = "Z".codeUnitAt(0); | 938 final int zCode = "Z".codeUnitAt(0); |
| 939 final int delta = "a".codeUnitAt(0) - aCode; | 939 final int delta = "a".codeUnitAt(0) - aCode; |
| 940 return (aCode <= byte && byte <= zCode) ? byte + delta : byte; | 940 return (aCode <= byte && byte <= zCode) ? byte + delta : byte; |
| 941 } | 941 } |
| 942 | 942 |
| 943 // expected should already be lowercase. |
| 944 bool _caseInsensitiveCompare(List<int> expected, List<int> value) { |
| 945 if (expected.length != value.length) return false; |
| 946 for (int i = 0; i < expected.length; i++) { |
| 947 if (expected[i] != _toLowerCase(value[i])) return false; |
| 948 } |
| 949 return true; |
| 950 } |
| 951 |
| 943 int _expect(int val1, int val2) { | 952 int _expect(int val1, int val2) { |
| 944 if (val1 != val2) { | 953 if (val1 != val2) { |
| 945 throw new HttpException("Failed to parse HTTP"); | 954 throw new HttpException("Failed to parse HTTP"); |
| 946 } | 955 } |
| 947 } | 956 } |
| 948 | 957 |
| 949 int _expectHexDigit(int byte) { | 958 int _expectHexDigit(int byte) { |
| 950 if (0x30 <= byte && byte <= 0x39) { | 959 if (0x30 <= byte && byte <= 0x39) { |
| 951 return byte - 0x30; // 0 - 9 | 960 return byte - 0x30; // 0 - 9 |
| 952 } else if (0x41 <= byte && byte <= 0x46) { | 961 } else if (0x41 <= byte && byte <= 0x46) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1023 } | 1032 } |
| 1024 } | 1033 } |
| 1025 | 1034 |
| 1026 void _reportError(error, [stackTrace]) { | 1035 void _reportError(error, [stackTrace]) { |
| 1027 if (_socketSubscription != null) _socketSubscription.cancel(); | 1036 if (_socketSubscription != null) _socketSubscription.cancel(); |
| 1028 _state = _State.FAILURE; | 1037 _state = _State.FAILURE; |
| 1029 _controller.addError(error, stackTrace); | 1038 _controller.addError(error, stackTrace); |
| 1030 _controller.close(); | 1039 _controller.close(); |
| 1031 } | 1040 } |
| 1032 } | 1041 } |
| OLD | NEW |