| 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 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 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // 2616 section 4.3). | 443 // 2616 section 4.3). |
| 444 if (_messageType == _MessageType.REQUEST && | 444 if (_messageType == _MessageType.REQUEST && |
| 445 _contentLength < 0 && | 445 _contentLength < 0 && |
| 446 _chunked == false) { | 446 _chunked == false) { |
| 447 _contentLength = 0; | 447 _contentLength = 0; |
| 448 } | 448 } |
| 449 if (_connectionUpgrade) { | 449 if (_connectionUpgrade) { |
| 450 _state = _State.UPGRADED; | 450 _state = _State.UPGRADED; |
| 451 } | 451 } |
| 452 _createIncomingConnection(); | 452 _createIncomingConnection(); |
| 453 _incomingConnection.headers = _headers; | |
| 454 _incomingConnection.contentLength = _contentLength; | |
| 455 if (_requestParser) { | 453 if (_requestParser) { |
| 456 _incomingConnection.method = | 454 _incomingConnection.method = |
| 457 new String.fromCharCodes(_method_or_status_code); | 455 new String.fromCharCodes(_method_or_status_code); |
| 458 _incomingConnection.uri = | 456 _incomingConnection.uri = |
| 459 new Uri.fromString( | 457 new Uri.fromString( |
| 460 new String.fromCharCodes(_uri_or_reason_phrase)); | 458 new String.fromCharCodes(_uri_or_reason_phrase)); |
| 461 } else { | 459 } else { |
| 462 _incomingConnection.statusCode = _statusCode; | 460 _incomingConnection.statusCode = _statusCode; |
| 463 _incomingConnection.reasonPhrase = | 461 _incomingConnection.reasonPhrase = |
| 464 new String.fromCharCodes(_uri_or_reason_phrase); | 462 new String.fromCharCodes(_uri_or_reason_phrase); |
| 465 } | 463 } |
| 466 _method_or_status_code.clear(); | 464 _method_or_status_code.clear(); |
| 467 _uri_or_reason_phrase.clear(); | 465 _uri_or_reason_phrase.clear(); |
| 468 if (_connectionUpgrade) { | 466 if (_connectionUpgrade) { |
| 469 _incomingConnection.upgraded = true; | 467 _incomingConnection.upgraded = true; |
| 470 add(_incomingConnection); | 468 add(_incomingConnection); |
| 471 return; | 469 break; |
| 472 } | 470 } |
| 473 if (_chunked) { | 471 if (_chunked) { |
| 474 _state = _State.CHUNK_SIZE; | 472 _state = _State.CHUNK_SIZE; |
| 475 _remainingContent = 0; | 473 _remainingContent = 0; |
| 476 } else if (_contentLength == 0 || | 474 } else if (_contentLength == 0 || |
| 477 (_messageType == _MessageType.RESPONSE && | 475 (_messageType == _MessageType.RESPONSE && |
| 478 (_noMessageBody || _responseToMethod == "HEAD"))) { | 476 (_noMessageBody || _responseToMethod == "HEAD"))) { |
| 479 _state = _State.DONE; | 477 _state = _State.DONE; |
| 480 add(_incomingConnection); | 478 add(_incomingConnection); |
| 481 _incomingConnection.close(); | 479 _closeIncomingConnection(); |
| 482 _incomingConnection = null; | |
| 483 break; | 480 break; |
| 484 } else if (_contentLength > 0) { | 481 } else if (_contentLength > 0) { |
| 485 _remainingContent = _contentLength; | 482 _remainingContent = _contentLength; |
| 486 _state = _State.BODY; | 483 _state = _State.BODY; |
| 487 } else { | 484 } else { |
| 488 // Neither chunked nor content length. End of body | 485 // Neither chunked nor content length. End of body |
| 489 // indicated by close. | 486 // indicated by close. |
| 490 _state = _State.BODY; | 487 _state = _State.BODY; |
| 491 } | 488 } |
| 492 add(_incomingConnection); | 489 add(_incomingConnection); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 break; | 526 break; |
| 530 | 527 |
| 531 case _State.CHUNKED_BODY_DONE_CR: | 528 case _State.CHUNKED_BODY_DONE_CR: |
| 532 _expect(byte, _CharCode.CR); | 529 _expect(byte, _CharCode.CR); |
| 533 _state = _State.CHUNKED_BODY_DONE_LF; | 530 _state = _State.CHUNKED_BODY_DONE_LF; |
| 534 break; | 531 break; |
| 535 | 532 |
| 536 case _State.CHUNKED_BODY_DONE_LF: | 533 case _State.CHUNKED_BODY_DONE_LF: |
| 537 _expect(byte, _CharCode.LF); | 534 _expect(byte, _CharCode.LF); |
| 538 _state = _State.DONE; | 535 _state = _State.DONE; |
| 539 _incomingConnection.close(); | 536 _closeIncomingConnection(); |
| 540 _incomingConnection = null; | |
| 541 break; | 537 break; |
| 542 | 538 |
| 543 case _State.BODY: | 539 case _State.BODY: |
| 544 // The body is not handled one byte at a time but in blocks. | 540 // The body is not handled one byte at a time but in blocks. |
| 545 _index--; | 541 _index--; |
| 546 int dataAvailable = _lastIndex - _index; | 542 int dataAvailable = _lastIndex - _index; |
| 547 List<int> data; | 543 List<int> data; |
| 548 if (_remainingContent == null || | 544 if (_remainingContent == null || |
| 549 dataAvailable <= _remainingContent) { | 545 dataAvailable <= _remainingContent) { |
| 550 data = new Uint8List(dataAvailable); | 546 data = new Uint8List(dataAvailable); |
| 551 data.setRange(0, dataAvailable, _buffer, _index); | 547 data.setRange(0, dataAvailable, _buffer, _index); |
| 552 } else { | 548 } else { |
| 553 data = new Uint8List(_remainingContent); | 549 data = new Uint8List(_remainingContent); |
| 554 data.setRange(0, _remainingContent, _buffer, _index); | 550 data.setRange(0, _remainingContent, _buffer, _index); |
| 555 } | 551 } |
| 556 | 552 |
| 557 _incomingConnection.add(data); | 553 _incomingConnection.add(data); |
| 558 if (_remainingContent != null) { | 554 if (_remainingContent != null) { |
| 559 _remainingContent -= data.length; | 555 _remainingContent -= data.length; |
| 560 } | 556 } |
| 561 _index += data.length; | 557 _index += data.length; |
| 562 if (_remainingContent == 0) { | 558 if (_remainingContent == 0) { |
| 563 if (!_chunked) { | 559 if (!_chunked) { |
| 564 _state = _State.DONE; | 560 _state = _State.DONE; |
| 565 _incomingConnection.close(); | 561 _closeIncomingConnection(); |
| 566 _incomingConnection = null; | |
| 567 } else { | 562 } else { |
| 568 _state = _State.CHUNK_SIZE_STARTING_CR; | 563 _state = _State.CHUNK_SIZE_STARTING_CR; |
| 569 } | 564 } |
| 570 } | 565 } |
| 571 break; | 566 break; |
| 572 | 567 |
| 573 case _State.FAILURE: | 568 case _State.FAILURE: |
| 574 // Should be unreachable. | 569 // Should be unreachable. |
| 575 assert(false); | 570 assert(false); |
| 576 break; | 571 break; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 599 _parse(); | 594 _parse(); |
| 600 } | 595 } |
| 601 | 596 |
| 602 void _onDone() { | 597 void _onDone() { |
| 603 if (_state == _State.CLOSED || _state == _State.FAILURE) return; | 598 if (_state == _State.CLOSED || _state == _State.FAILURE) return; |
| 604 | 599 |
| 605 if (_incomingConnection != null) { | 600 if (_incomingConnection != null) { |
| 606 // Redirect to _parseObject, if present. | 601 // Redirect to _parseObject, if present. |
| 607 if (_state != _State.DONE && | 602 if (_state != _State.DONE && |
| 608 _state != _State.UPGRADED && | 603 _state != _State.UPGRADED && |
| 604 !(_state == _State.START && !_requestParser) && |
| 609 !(_state == _State.BODY && !_chunked && _contentLength == -1)) { | 605 !(_state == _State.BODY && !_chunked && _contentLength == -1)) { |
| 610 _incomingConnection.signalError( | 606 _incomingConnection.signalError( |
| 611 new AsyncError( | 607 new AsyncError( |
| 612 new HttpParserException( | 608 new HttpParserException( |
| 613 "Connection closed while receiving data"))); | 609 "Connection closed while receiving data"))); |
| 614 } | 610 } |
| 615 _incomingConnection.close(); | 611 _closeIncomingConnection(); |
| 616 _incomingConnection = null; | |
| 617 close(); | 612 close(); |
| 618 return; | 613 return; |
| 619 } | 614 } |
| 620 // If the connection is idle the HTTP stream is closed. | 615 // If the connection is idle the HTTP stream is closed. |
| 621 if (_state == _State.START) { | 616 if (_state == _State.START) { |
| 622 if (!_requestParser) { | 617 if (!_requestParser) { |
| 623 error( | 618 error( |
| 624 new AsyncError( | 619 new AsyncError( |
| 625 new HttpParserException( | 620 new HttpParserException( |
| 626 "Connection closed before full header was received"))); | 621 "Connection closed before full header was received"))); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 return byte - 0x41 + 10; // A - F | 769 return byte - 0x41 + 10; // A - F |
| 775 } else if (0x61 <= byte && byte <= 0x66) { | 770 } else if (0x61 <= byte && byte <= 0x66) { |
| 776 return byte - 0x61 + 10; // a - f | 771 return byte - 0x61 + 10; // a - f |
| 777 } else { | 772 } else { |
| 778 throw new HttpParserException("Failed to parse HTTP"); | 773 throw new HttpParserException("Failed to parse HTTP"); |
| 779 } | 774 } |
| 780 } | 775 } |
| 781 | 776 |
| 782 void _createIncomingConnection() { | 777 void _createIncomingConnection() { |
| 783 assert(_incomingConnection == null); | 778 assert(_incomingConnection == null); |
| 784 _incomingConnection = new _HttpIncomingConnection(_pauseData, _resumeData); | 779 _incomingConnection = new _HttpIncomingConnection(_headers, |
| 780 _pauseData, |
| 781 _resumeData); |
| 785 _incomingConnection.messageHandled.then(() { | 782 _incomingConnection.messageHandled.then(() { |
| 786 _paused = false; | |
| 787 _reset(); | 783 _reset(); |
| 784 // Use _resumeData to ensure we start with the current chunk, and not |
| 785 // accepting any more, unless we have an empty buffer. |
| 786 _resumeData(); |
| 788 }); | 787 }); |
| 789 } | 788 } |
| 790 | 789 |
| 790 void _closeIncomingConnection() { |
| 791 assert(_incomingConnection != null); |
| 792 var tmp = _incomingConnection; |
| 793 _incomingConnection = null; |
| 794 tmp.close(); |
| 795 } |
| 796 |
| 791 void _pauseData() { | 797 void _pauseData() { |
| 792 if (_pauseCompleter == null) { | 798 if (_pauseCompleter == null) { |
| 793 _pauseCompleter = new SignalCompleter(); | 799 _pauseCompleter = new SignalCompleter(); |
| 794 _subscription.pause(_pauseCompleter.signal); | 800 _subscription.pause(_pauseCompleter.signal); |
| 795 } | 801 } |
| 796 _paused = true; | 802 _paused = true; |
| 797 } | 803 } |
| 798 | 804 |
| 799 void _resumeData() { | 805 void _resumeData() { |
| 800 _paused = false; | 806 _paused = false; |
| 801 if (_buffer != null) { | 807 if (_buffer != null) { |
| 802 _parse(); | 808 _parse(); |
| 803 if (_paused) return; | 809 if (_paused) return; |
| 804 } | 810 } |
| 805 _pauseCompleter.complete(); | 811 if (_pauseCompleter != null) { |
| 806 _pauseCompleter = null; | 812 _pauseCompleter.complete(); |
| 813 _pauseCompleter = null; |
| 814 } |
| 807 } | 815 } |
| 808 | 816 |
| 809 void error(error) { | 817 void error(error) { |
| 810 _subscription.cancel(); | 818 _subscription.cancel(); |
| 811 _state = _State.FAILURE; | 819 _state = _State.FAILURE; |
| 812 signalError(error); | 820 signalError(error); |
| 813 close(); | 821 close(); |
| 814 } | 822 } |
| 815 | 823 |
| 816 // The data that is currently being parsed. | 824 // The data that is currently being parsed. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 846 bool _paused = false; | 854 bool _paused = false; |
| 847 SignalCompleter _pauseCompleter; | 855 SignalCompleter _pauseCompleter; |
| 848 } | 856 } |
| 849 | 857 |
| 850 | 858 |
| 851 class HttpParserException implements Exception { | 859 class HttpParserException implements Exception { |
| 852 const HttpParserException([String this.message = ""]); | 860 const HttpParserException([String this.message = ""]); |
| 853 String toString() => "HttpParserException: $message"; | 861 String toString() => "HttpParserException: $message"; |
| 854 final String message; | 862 final String message; |
| 855 } | 863 } |
| OLD | NEW |