OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_stream_parser.h" | 5 #include "net/http/http_stream_parser.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
23 #include "net/socket/ssl_client_socket.h" | 23 #include "net/socket/ssl_client_socket.h" |
24 | 24 |
25 namespace net { | 25 namespace net { |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 enum HttpHeaderParserEvent { | 29 enum HttpHeaderParserEvent { |
30 HEADER_PARSER_INVOKED = 0, | 30 HEADER_PARSER_INVOKED = 0, |
31 HEADER_HTTP_09_RESPONSE = 1, | 31 HEADER_HTTP_09_RESPONSE = 1, |
32 HEADER_ALLOWED_TRUNCATED_HEADERS = 2, | 32 // Obsolete: HEADER_ALLOWED_TRUNCATED_HEADERS = 2, |
33 HEADER_SKIPPED_WS_PREFIX = 3, | 33 HEADER_SKIPPED_WS_PREFIX = 3, |
34 HEADER_SKIPPED_NON_WS_PREFIX = 4, | 34 HEADER_SKIPPED_NON_WS_PREFIX = 4, |
35 NUM_HEADER_EVENTS | 35 NUM_HEADER_EVENTS |
36 }; | 36 }; |
37 | 37 |
38 void RecordHeaderParserEvent(HttpHeaderParserEvent header_event) { | 38 void RecordHeaderParserEvent(HttpHeaderParserEvent header_event) { |
39 UMA_HISTOGRAM_ENUMERATION("Net.HttpHeaderParserEvent", header_event, | 39 UMA_HISTOGRAM_ENUMERATION("Net.HttpHeaderParserEvent", header_event, |
40 NUM_HEADER_EVENTS); | 40 NUM_HEADER_EVENTS); |
41 } | 41 } |
42 | 42 |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 | 761 |
762 return result; | 762 return result; |
763 } | 763 } |
764 | 764 |
765 int HttpStreamParser::HandleReadHeaderResult(int result) { | 765 int HttpStreamParser::HandleReadHeaderResult(int result) { |
766 DCHECK_EQ(0, read_buf_unused_offset_); | 766 DCHECK_EQ(0, read_buf_unused_offset_); |
767 | 767 |
768 if (result == 0) | 768 if (result == 0) |
769 result = ERR_CONNECTION_CLOSED; | 769 result = ERR_CONNECTION_CLOSED; |
770 | 770 |
771 if (result < 0 && result != ERR_CONNECTION_CLOSED) { | 771 if (result == ERR_CONNECTION_CLOSED) { |
772 io_state_ = STATE_DONE; | 772 if (read_buf_->offset() == 0) { |
| 773 io_state_ = STATE_DONE; |
| 774 // If the connection has not been reused, it may have been a 0-length |
| 775 // HTTP/0.9 responses, but it was most likely an error, so just return |
| 776 // ERR_EMPTY_RESPONSE instead. If the connection was reused, just pass |
| 777 // on the original connection close error, as rather than being an |
| 778 // empty HTTP/0.9 response it's much more likely the server closed the |
| 779 // socket before it received the request. |
| 780 if (!connection_->is_reused()) |
| 781 return ERR_EMPTY_RESPONSE; |
| 782 return result; |
| 783 } |
| 784 |
| 785 // The connection closed before the end of the headers. For HTTPS, |
| 786 // accepting the partial headers headers is a potential security |
| 787 // vulnerability. For HTTP, it just doesn't seem like a good idea. |
| 788 if (response_header_start_offset_ >= 0) { |
| 789 io_state_ = STATE_DONE; |
| 790 return ERR_RESPONSE_HEADERS_TRUNCATED; |
| 791 } |
| 792 |
| 793 // The response is apparently using HTTP/0.9. Treat the entire response as |
| 794 // the body. |
| 795 int rv = ParseResponseHeaders(0); |
| 796 if (rv < 0) |
| 797 return rv; |
773 return result; | 798 return result; |
774 } | 799 } |
775 // If we've used the connection before, then we know it is not a HTTP/0.9 | 800 |
776 // response and return ERR_CONNECTION_CLOSED. | 801 if (result < 0) { |
777 if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && | |
778 connection_->is_reused()) { | |
779 io_state_ = STATE_DONE; | 802 io_state_ = STATE_DONE; |
780 return result; | 803 return result; |
781 } | 804 } |
782 | 805 |
783 // Record our best estimate of the 'response time' as the time when we read | 806 // Record our best estimate of the 'response time' as the time when we read |
784 // the first bytes of the response headers. | 807 // the first bytes of the response headers. |
785 if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) | 808 if (read_buf_->offset() == 0) |
786 response_->response_time = base::Time::Now(); | 809 response_->response_time = base::Time::Now(); |
787 | 810 |
788 if (result == ERR_CONNECTION_CLOSED) { | |
789 // The connection closed before we detected the end of the headers. | |
790 if (read_buf_->offset() == 0) { | |
791 // The connection was closed before any data was sent. Likely an error | |
792 // rather than empty HTTP/0.9 response. | |
793 io_state_ = STATE_DONE; | |
794 return ERR_EMPTY_RESPONSE; | |
795 } else if (request_->url.SchemeIsCryptographic()) { | |
796 // The connection was closed in the middle of the headers. For HTTPS we | |
797 // don't parse partial headers. Return a different error code so that we | |
798 // know that we shouldn't attempt to retry the request. | |
799 io_state_ = STATE_DONE; | |
800 return ERR_RESPONSE_HEADERS_TRUNCATED; | |
801 } | |
802 // Parse things as well as we can and let the caller decide what to do. | |
803 int end_offset; | |
804 if (response_header_start_offset_ >= 0) { | |
805 // The response looks to be a truncated set of HTTP headers. | |
806 io_state_ = STATE_READ_BODY_COMPLETE; | |
807 end_offset = read_buf_->offset(); | |
808 RecordHeaderParserEvent(HEADER_ALLOWED_TRUNCATED_HEADERS); | |
809 } else { | |
810 // The response is apparently using HTTP/0.9. Treat the entire response | |
811 // the body. | |
812 end_offset = 0; | |
813 } | |
814 int rv = ParseResponseHeaders(end_offset); | |
815 if (rv < 0) | |
816 return rv; | |
817 return result; | |
818 } | |
819 | |
820 read_buf_->set_offset(read_buf_->offset() + result); | 811 read_buf_->set_offset(read_buf_->offset() + result); |
821 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); | 812 DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); |
822 DCHECK_GE(result, 0); | 813 DCHECK_GE(result, 0); |
823 | 814 |
824 int end_of_header_offset = FindAndParseResponseHeaders(); | 815 int end_of_header_offset = FindAndParseResponseHeaders(); |
825 | 816 |
826 // Note: -1 is special, it indicates we haven't found the end of headers. | 817 // Note: -1 is special, it indicates we haven't found the end of headers. |
827 // Anything less than -1 is a net::Error, so we bail out. | 818 // Anything less than -1 is a net::Error, so we bail out. |
828 if (end_of_header_offset < -1) | 819 if (end_of_header_offset < -1) |
829 return end_of_header_offset; | 820 return end_of_header_offset; |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 request_body->IsInMemory() && | 1088 request_body->IsInMemory() && |
1098 request_body->size() > 0) { | 1089 request_body->size() > 0) { |
1099 uint64 merged_size = request_headers.size() + request_body->size(); | 1090 uint64 merged_size = request_headers.size() + request_body->size(); |
1100 if (merged_size <= kMaxMergedHeaderAndBodySize) | 1091 if (merged_size <= kMaxMergedHeaderAndBodySize) |
1101 return true; | 1092 return true; |
1102 } | 1093 } |
1103 return false; | 1094 return false; |
1104 } | 1095 } |
1105 | 1096 |
1106 } // namespace net | 1097 } // namespace net |
OLD | NEW |