OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/tools/balsa/balsa_frame.h" | 5 #include "net/tools/balsa/balsa_frame.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #if __SSE2__ | 8 #if __SSE2__ |
9 #include <emmintrin.h> | 9 #include <emmintrin.h> |
10 #endif // __SSE2__ | 10 #endif // __SSE2__ |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 BalsaHeadersEnums::ContentLengthStatus* status, | 623 BalsaHeadersEnums::ContentLengthStatus* status, |
624 size_t* length) { | 624 size_t* length) { |
625 const HeaderLineDescription& header_line = headers_->header_lines_[line_idx]; | 625 const HeaderLineDescription& header_line = headers_->header_lines_[line_idx]; |
626 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); | 626 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); |
627 const char* line_end = stream_begin + header_line.last_char_idx; | 627 const char* line_end = stream_begin + header_line.last_char_idx; |
628 const char* value_begin = (stream_begin + header_line.value_begin_idx); | 628 const char* value_begin = (stream_begin + header_line.value_begin_idx); |
629 | 629 |
630 if (value_begin >= line_end) { | 630 if (value_begin >= line_end) { |
631 // There is no non-whitespace value data. | 631 // There is no non-whitespace value data. |
632 #if DEBUGFRAMER | 632 #if DEBUGFRAMER |
633 LOG(INFO) << "invalid content-length -- no non-whitespace value data"; | 633 VLOG(0) << "invalid content-length -- no non-whitespace value data"; |
634 #endif | 634 #endif |
635 *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH; | 635 *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH; |
636 return; | 636 return; |
637 } | 637 } |
638 | 638 |
639 *length = 0; | 639 *length = 0; |
640 while (value_begin < line_end) { | 640 while (value_begin < line_end) { |
641 if (*value_begin < '0' || *value_begin > '9') { | 641 if (*value_begin < '0' || *value_begin > '9') { |
642 // bad! content-length found, and couldn't parse all of it! | 642 // bad! content-length found, and couldn't parse all of it! |
643 *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH; | 643 *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH; |
644 #if DEBUGFRAMER | 644 #if DEBUGFRAMER |
645 LOG(INFO) << "invalid content-length - non numeric character detected"; | 645 VLOG(0) << "invalid content-length - non numeric character detected"; |
646 #endif // DEBUGFRAMER | 646 #endif // DEBUGFRAMER |
647 return; | 647 return; |
648 } | 648 } |
649 const size_t kMaxDiv10 = std::numeric_limits<size_t>::max() / 10; | 649 const size_t kMaxDiv10 = std::numeric_limits<size_t>::max() / 10; |
650 size_t length_x_10 = *length * 10; | 650 size_t length_x_10 = *length * 10; |
651 const unsigned char c = *value_begin - '0'; | 651 const unsigned char c = *value_begin - '0'; |
652 if (*length > kMaxDiv10 || | 652 if (*length > kMaxDiv10 || |
653 (std::numeric_limits<size_t>::max() - length_x_10) < c) { | 653 (std::numeric_limits<size_t>::max() - length_x_10) < c) { |
654 *status = BalsaHeadersEnums::CONTENT_LENGTH_OVERFLOW; | 654 *status = BalsaHeadersEnums::CONTENT_LENGTH_OVERFLOW; |
655 #if DEBUGFRAMER | 655 #if DEBUGFRAMER |
656 LOG(INFO) << "content-length overflow"; | 656 VLOG(0) << "content-length overflow"; |
657 #endif // DEBUGFRAMER | 657 #endif // DEBUGFRAMER |
658 return; | 658 return; |
659 } | 659 } |
660 *length = length_x_10 + c; | 660 *length = length_x_10 + c; |
661 ++value_begin; | 661 ++value_begin; |
662 } | 662 } |
663 #if DEBUGFRAMER | 663 #if DEBUGFRAMER |
664 LOG(INFO) << "content_length parsed: " << *length; | 664 VLOG(0) << "content_length parsed: " << *length; |
665 #endif // DEBUGFRAMER | 665 #endif // DEBUGFRAMER |
666 *status = BalsaHeadersEnums::VALID_CONTENT_LENGTH; | 666 *status = BalsaHeadersEnums::VALID_CONTENT_LENGTH; |
667 } | 667 } |
668 | 668 |
669 void BalsaFrame::ProcessTransferEncodingLine(HeaderLines::size_type line_idx) { | 669 void BalsaFrame::ProcessTransferEncodingLine(HeaderLines::size_type line_idx) { |
670 const HeaderLineDescription& header_line = headers_->header_lines_[line_idx]; | 670 const HeaderLineDescription& header_line = headers_->header_lines_[line_idx]; |
671 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); | 671 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); |
672 const char* line_end = stream_begin + header_line.last_char_idx; | 672 const char* line_end = stream_begin + header_line.last_char_idx; |
673 const char* value_begin = stream_begin + header_line.value_begin_idx; | 673 const char* value_begin = stream_begin + header_line.value_begin_idx; |
674 size_t value_length = line_end - value_begin; | 674 size_t value_length = line_end - value_begin; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 BalsaHeaders* extensions) { | 751 BalsaHeaders* extensions) { |
752 ProcessChunkExtensionsManual(base::StringPiece(input, size), extensions); | 752 ProcessChunkExtensionsManual(base::StringPiece(input, size), extensions); |
753 } | 753 } |
754 | 754 |
755 void BalsaFrame::ProcessHeaderLines() { | 755 void BalsaFrame::ProcessHeaderLines() { |
756 HeaderLines::size_type content_length_idx = 0; | 756 HeaderLines::size_type content_length_idx = 0; |
757 HeaderLines::size_type transfer_encoding_idx = 0; | 757 HeaderLines::size_type transfer_encoding_idx = 0; |
758 | 758 |
759 DCHECK(!lines_.empty()); | 759 DCHECK(!lines_.empty()); |
760 #if DEBUGFRAMER | 760 #if DEBUGFRAMER |
761 LOG(INFO) << "******@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**********\n"; | 761 VLOG(0) << "******@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**********\n"; |
762 #endif // DEBUGFRAMER | 762 #endif // DEBUGFRAMER |
763 | 763 |
764 // There is no need to attempt to process headers if no header lines exist. | 764 // There is no need to attempt to process headers if no header lines exist. |
765 // There are at least two lines in the message which are not header lines. | 765 // There are at least two lines in the message which are not header lines. |
766 // These two non-header lines are the first line of the message, and the | 766 // These two non-header lines are the first line of the message, and the |
767 // last line of the message (which is an empty line). | 767 // last line of the message (which is an empty line). |
768 // Thus, we test to see if we have more than two lines total before attempting | 768 // Thus, we test to see if we have more than two lines total before attempting |
769 // to parse any header lines. | 769 // to parse any header lines. |
770 if (lines_.size() > 2) { | 770 if (lines_.size() > 2) { |
771 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); | 771 const char* stream_begin = headers_->OriginalHeaderStreamBegin(); |
772 | 772 |
773 // Then, for the rest of the header data, we parse these into key-value | 773 // Then, for the rest of the header data, we parse these into key-value |
774 // pairs. | 774 // pairs. |
775 FindColonsAndParseIntoKeyValue(); | 775 FindColonsAndParseIntoKeyValue(); |
776 // At this point, we've parsed all of the headers. Time to look for those | 776 // At this point, we've parsed all of the headers. Time to look for those |
777 // headers which we require for framing. | 777 // headers which we require for framing. |
778 const HeaderLines::size_type | 778 const HeaderLines::size_type |
779 header_lines_size = headers_->header_lines_.size(); | 779 header_lines_size = headers_->header_lines_.size(); |
780 for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) { | 780 for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) { |
781 const HeaderLineDescription& current_header_line = | 781 const HeaderLineDescription& current_header_line = |
782 headers_->header_lines_[i]; | 782 headers_->header_lines_[i]; |
783 const char* key_begin = | 783 const char* key_begin = |
784 (stream_begin + current_header_line.first_char_idx); | 784 (stream_begin + current_header_line.first_char_idx); |
785 const char* key_end = (stream_begin + current_header_line.key_end_idx); | 785 const char* key_end = (stream_begin + current_header_line.key_end_idx); |
786 const size_t key_len = key_end - key_begin; | 786 const size_t key_len = key_end - key_begin; |
787 const char c = *key_begin; | 787 const char c = *key_begin; |
788 #if DEBUGFRAMER | 788 #if DEBUGFRAMER |
789 LOG(INFO) << "[" << i << "]: " << std::string(key_begin, key_len) | 789 VLOG(0) << "[" << i << "]: " << std::string(key_begin, key_len) |
790 << " c: '" << c << "' key_len: " << key_len; | 790 << " c: '" << c << "' key_len: " << key_len; |
791 #endif // DEBUGFRAMER | 791 #endif // DEBUGFRAMER |
792 // If a header begins with either lowercase or uppercase 'c' or 't', then | 792 // If a header begins with either lowercase or uppercase 'c' or 't', then |
793 // the header may be one of content-length, connection, content-encoding | 793 // the header may be one of content-length, connection, content-encoding |
794 // or transfer-encoding. These headers are special, as they change the way | 794 // or transfer-encoding. These headers are special, as they change the way |
795 // that the message is framed, and so the framer is required to search | 795 // that the message is framed, and so the framer is required to search |
796 // for them. | 796 // for them. |
797 | 797 |
798 | 798 |
799 if (c == 'c' || c == 'C') { | 799 if (c == 'c' || c == 'C') { |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 const size_t relative_idx = message_current - message_start; | 1004 const size_t relative_idx = message_current - message_start; |
1005 const size_t message_current_idx = 1 + base_idx + relative_idx; | 1005 const size_t message_current_idx = 1 + base_idx + relative_idx; |
1006 lines_.push_back(std::make_pair(last_slash_n_idx_, | 1006 lines_.push_back(std::make_pair(last_slash_n_idx_, |
1007 message_current_idx)); | 1007 message_current_idx)); |
1008 if (lines_.size() == 1) { | 1008 if (lines_.size() == 1) { |
1009 headers_->WriteFromFramer(checkpoint, | 1009 headers_->WriteFromFramer(checkpoint, |
1010 1 + message_current - checkpoint); | 1010 1 + message_current - checkpoint); |
1011 checkpoint = message_current + 1; | 1011 checkpoint = message_current + 1; |
1012 const char* begin = headers_->OriginalHeaderStreamBegin(); | 1012 const char* begin = headers_->OriginalHeaderStreamBegin(); |
1013 #if DEBUGFRAMER | 1013 #if DEBUGFRAMER |
1014 LOG(INFO) << "First line " << std::string(begin, lines_[0].second); | 1014 VLOG(0) << "First line " << std::string(begin, lines_[0].second); |
1015 LOG(INFO) << "is_request_: " << is_request_; | 1015 VLOG(0) << "is_request_: " << is_request_; |
1016 #endif | 1016 #endif |
1017 ProcessFirstLine(begin, begin + lines_[0].second); | 1017 ProcessFirstLine(begin, begin + lines_[0].second); |
1018 if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ) | 1018 if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ) |
1019 goto process_lines; | 1019 goto process_lines; |
1020 else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) | 1020 else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) |
1021 goto bottom; | 1021 goto bottom; |
1022 } | 1022 } |
1023 const size_t chars_since_last_slash_n = (message_current_idx - | 1023 const size_t chars_since_last_slash_n = (message_current_idx - |
1024 last_slash_n_idx_); | 1024 last_slash_n_idx_); |
1025 last_slash_n_idx_ = message_current_idx; | 1025 last_slash_n_idx_ = message_current_idx; |
(...skipping 22 matching lines...) Expand all Loading... |
1048 const size_t relative_idx = message_current - message_start; | 1048 const size_t relative_idx = message_current - message_start; |
1049 const size_t message_current_idx = 1 + base_idx + relative_idx; | 1049 const size_t message_current_idx = 1 + base_idx + relative_idx; |
1050 lines_.push_back(std::make_pair(last_slash_n_idx_, | 1050 lines_.push_back(std::make_pair(last_slash_n_idx_, |
1051 message_current_idx)); | 1051 message_current_idx)); |
1052 if (lines_.size() == 1) { | 1052 if (lines_.size() == 1) { |
1053 headers_->WriteFromFramer(checkpoint, | 1053 headers_->WriteFromFramer(checkpoint, |
1054 1 + message_current - checkpoint); | 1054 1 + message_current - checkpoint); |
1055 checkpoint = message_current + 1; | 1055 checkpoint = message_current + 1; |
1056 const char* begin = headers_->OriginalHeaderStreamBegin(); | 1056 const char* begin = headers_->OriginalHeaderStreamBegin(); |
1057 #if DEBUGFRAMER | 1057 #if DEBUGFRAMER |
1058 LOG(INFO) << "First line " << std::string(begin, lines_[0].second); | 1058 VLOG(0) << "First line " << std::string(begin, lines_[0].second); |
1059 LOG(INFO) << "is_request_: " << is_request_; | 1059 VLOG(0) << "is_request_: " << is_request_; |
1060 #endif | 1060 #endif |
1061 ProcessFirstLine(begin, begin + lines_[0].second); | 1061 ProcessFirstLine(begin, begin + lines_[0].second); |
1062 if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ) | 1062 if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ) |
1063 goto process_lines; | 1063 goto process_lines; |
1064 else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) | 1064 else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) |
1065 goto bottom; | 1065 goto bottom; |
1066 } | 1066 } |
1067 const size_t chars_since_last_slash_n = (message_current_idx - | 1067 const size_t chars_since_last_slash_n = (message_current_idx - |
1068 last_slash_n_idx_); | 1068 last_slash_n_idx_); |
1069 last_slash_n_idx_ = message_current_idx; | 1069 last_slash_n_idx_ = message_current_idx; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 // also one label at the bottom of the function. When it is appropriate to | 1212 // also one label at the bottom of the function. When it is appropriate to |
1213 // return from the function, that part of the state machine instead issues a | 1213 // return from the function, that part of the state machine instead issues a |
1214 // goto bottom; This results in less code duplication, and makes debugging | 1214 // goto bottom; This results in less code duplication, and makes debugging |
1215 // easier (as you can add a statement to a section of code which is guaranteed | 1215 // easier (as you can add a statement to a section of code which is guaranteed |
1216 // to be invoked when the function is exiting. | 1216 // to be invoked when the function is exiting. |
1217 size_t BalsaFrame::ProcessInput(const char* input, size_t size) { | 1217 size_t BalsaFrame::ProcessInput(const char* input, size_t size) { |
1218 const char* current = input; | 1218 const char* current = input; |
1219 const char* on_entry = current; | 1219 const char* on_entry = current; |
1220 const char* end = current + size; | 1220 const char* end = current + size; |
1221 #if DEBUGFRAMER | 1221 #if DEBUGFRAMER |
1222 LOG(INFO) << "\n==============" | 1222 VLOG(0) << "\n==============" |
1223 << BalsaFrameEnums::ParseStateToString(parse_state_) | 1223 << BalsaFrameEnums::ParseStateToString(parse_state_) |
1224 << "===============\n"; | 1224 << "===============\n"; |
1225 #endif // DEBUGFRAMER | 1225 #endif // DEBUGFRAMER |
1226 | 1226 |
1227 DCHECK(headers_ != NULL); | 1227 DCHECK(headers_ != NULL); |
1228 if (headers_ == NULL) return 0; | 1228 if (headers_ == NULL) return 0; |
1229 | 1229 |
1230 if (parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE) { | 1230 if (parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE) { |
1231 const size_t header_length = headers_->GetReadableBytesFromHeaderStream(); | 1231 const size_t header_length = headers_->GetReadableBytesFromHeaderStream(); |
1232 // Yes, we still have to check this here as the user can change the | 1232 // Yes, we still have to check this here as the user can change the |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 visitor_->ProcessBodyInput(current, bytes_remaining); | 1507 visitor_->ProcessBodyInput(current, bytes_remaining); |
1508 visitor_->ProcessBodyData(current, bytes_remaining); | 1508 visitor_->ProcessBodyData(current, bytes_remaining); |
1509 current += bytes_remaining; | 1509 current += bytes_remaining; |
1510 } | 1510 } |
1511 } | 1511 } |
1512 goto bottom; // case BalsaFrameEnums::READING_UNTIL_CLOSE | 1512 goto bottom; // case BalsaFrameEnums::READING_UNTIL_CLOSE |
1513 | 1513 |
1514 // label_reading_content: | 1514 // label_reading_content: |
1515 case BalsaFrameEnums::READING_CONTENT: | 1515 case BalsaFrameEnums::READING_CONTENT: |
1516 #if DEBUGFRAMER | 1516 #if DEBUGFRAMER |
1517 LOG(INFO) << "ReadingContent: " << content_length_remaining_; | 1517 VLOG(0) << "ReadingContent: " << content_length_remaining_; |
1518 #endif // DEBUGFRAMER | 1518 #endif // DEBUGFRAMER |
1519 while (content_length_remaining_ && current < end) { | 1519 while (content_length_remaining_ && current < end) { |
1520 // read in the content | 1520 // read in the content |
1521 const size_t bytes_remaining = end - current; | 1521 const size_t bytes_remaining = end - current; |
1522 const size_t consumed_bytes = | 1522 const size_t consumed_bytes = |
1523 (content_length_remaining_ < bytes_remaining) ? | 1523 (content_length_remaining_ < bytes_remaining) ? |
1524 content_length_remaining_ : bytes_remaining; | 1524 content_length_remaining_ : bytes_remaining; |
1525 visitor_->ProcessBodyInput(current, consumed_bytes); | 1525 visitor_->ProcessBodyInput(current, consumed_bytes); |
1526 visitor_->ProcessBodyData(current, consumed_bytes); | 1526 visitor_->ProcessBodyData(current, consumed_bytes); |
1527 current += consumed_bytes; | 1527 current += consumed_bytes; |
1528 content_length_remaining_ -= consumed_bytes; | 1528 content_length_remaining_ -= consumed_bytes; |
1529 } | 1529 } |
1530 if (content_length_remaining_ == 0) { | 1530 if (content_length_remaining_ == 0) { |
1531 parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ; | 1531 parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ; |
1532 visitor_->MessageDone(); | 1532 visitor_->MessageDone(); |
1533 } | 1533 } |
1534 goto bottom; // case BalsaFrameEnums::READING_CONTENT | 1534 goto bottom; // case BalsaFrameEnums::READING_CONTENT |
1535 | 1535 |
1536 default: | 1536 default: |
1537 // The state-machine should never be in a state that isn't handled | 1537 // The state-machine should never be in a state that isn't handled |
1538 // above. This is a glaring logic error, and we should do something | 1538 // above. This is a glaring logic error, and we should do something |
1539 // drastic to ensure that this gets looked-at and fixed. | 1539 // drastic to ensure that this gets looked-at and fixed. |
1540 LOG(FATAL) << "Unknown state: " << parse_state_ // COV_NF_LINE | 1540 LOG(FATAL) << "Unknown state: " << parse_state_ // COV_NF_LINE |
1541 << " memory corruption?!"; // COV_NF_LINE | 1541 << " memory corruption?!"; // COV_NF_LINE |
1542 } | 1542 } |
1543 } | 1543 } |
1544 bottom: | 1544 bottom: |
1545 #if DEBUGFRAMER | 1545 #if DEBUGFRAMER |
1546 LOG(INFO) << "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n" | 1546 VLOG(0) << "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n" |
1547 << std::string(input, current) | 1547 << std::string(input, current) |
1548 << "\n$$$$$$$$$$$$$$" | 1548 << "\n$$$$$$$$$$$$$$" |
1549 << BalsaFrameEnums::ParseStateToString(parse_state_) | 1549 << BalsaFrameEnums::ParseStateToString(parse_state_) |
1550 << "$$$$$$$$$$$$$$$" | 1550 << "$$$$$$$$$$$$$$$" |
1551 << " consumed: " << (current - input); | 1551 << " consumed: " << (current - input); |
1552 if (Error()) { | 1552 if (Error()) { |
1553 LOG(INFO) << BalsaFrameEnums::ErrorCodeToString(ErrorCode()); | 1553 VLOG(0) << BalsaFrameEnums::ErrorCodeToString(ErrorCode()); |
1554 } | 1554 } |
1555 #endif // DEBUGFRAMER | 1555 #endif // DEBUGFRAMER |
1556 return current - input; | 1556 return current - input; |
1557 } | 1557 } |
1558 | 1558 |
1559 const uint32 BalsaFrame::kValidTerm1; | 1559 const uint32 BalsaFrame::kValidTerm1; |
1560 const uint32 BalsaFrame::kValidTerm1Mask; | 1560 const uint32 BalsaFrame::kValidTerm1Mask; |
1561 const uint32 BalsaFrame::kValidTerm2; | 1561 const uint32 BalsaFrame::kValidTerm2; |
1562 const uint32 BalsaFrame::kValidTerm2Mask; | 1562 const uint32 BalsaFrame::kValidTerm2Mask; |
1563 | 1563 |
1564 } // namespace net | 1564 } // namespace net |
OLD | NEW |