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