MUST NOT have extras. MUST NOT have key. MUST have value.
| 766 | // MUST NOT have key. |
| 767 | // MUST have value. |
| 768 | bool MemcacheResponse::PopVersion(std::string* version) { |
| 769 | const size_t n = _buf.size(); |
| 770 | policy::MemcacheResponseHeader header; |
| 771 | if (n < sizeof(header)) { |
| 772 | butil::string_printf(&_err, "buffer is too small to contain a header"); |
| 773 | return false; |
| 774 | } |
| 775 | _buf.copy_to(&header, sizeof(header)); |
| 776 | if (header.command != policy::MC_BINARY_VERSION) { |
| 777 | butil::string_printf(&_err, "not a VERSION response"); |
| 778 | return false; |
| 779 | } |
| 780 | if (n < sizeof(header) + header.total_body_length) { |
| 781 | butil::string_printf(&_err, "response=%u < header=%u + body=%u", |
| 782 | (unsigned)n, (unsigned)sizeof(header), header.total_body_length); |
| 783 | return false; |
| 784 | } |
| 785 | LOG_IF(ERROR, header.extras_length != 0) << "VERSION response must not have flags"; |
| 786 | LOG_IF(ERROR, header.key_length != 0) << "VERSION response must not have key"; |
| 787 | const int value_size = (int)header.total_body_length - (int)header.extras_length |
| 788 | - (int)header.key_length; |
| 789 | _buf.pop_front(sizeof(header) + header.extras_length + header.key_length); |
| 790 | if (value_size < 0) { |
| 791 | butil::string_printf(&_err, "value_size=%d is negative", value_size); |
| 792 | return false; |
| 793 | } |
| 794 | if (header.status != (uint16_t)STATUS_SUCCESS) { |
| 795 | _err.clear(); |
| 796 | _buf.cutn(&_err, value_size); |
| 797 | return false; |
| 798 | } |
| 799 | if (version) { |
| 800 | version->clear(); |
| 801 | _buf.cutn(version, value_size); |
| 802 | } |
| 803 | _err.clear(); |
| 804 | return true; |
| 805 | } |
| 806 | |
| 807 | } // namespace brpc |