A faster implementation of TProtocol::readMessageBegin without depending on thrift stuff.
| 70 | // A faster implementation of TProtocol::readMessageBegin without depending |
| 71 | // on thrift stuff. |
| 72 | static butil::Status |
| 73 | ReadThriftMessageBegin(butil::IOBuf* body, |
| 74 | std::string* method_name, |
| 75 | ::apache::thrift::protocol::TMessageType* mtype, |
| 76 | uint32_t* seq_id) { |
| 77 | // Thrift protocol format: |
| 78 | // Version + Message type + Length + Method + Sequence Id |
| 79 | // | | | | | |
| 80 | // 3 + 1 + 4 + >0 + 4 |
| 81 | uint32_t version_and_len_buf[2]; |
| 82 | size_t k = body->copy_to(version_and_len_buf, sizeof(version_and_len_buf)); |
| 83 | if (k != sizeof(version_and_len_buf) ) { |
| 84 | return butil::Status(-1, "Fail to copy %zu bytes from body", |
| 85 | sizeof(version_and_len_buf)); |
| 86 | } |
| 87 | *mtype = (apache::thrift::protocol::TMessageType) |
| 88 | (ntohl(version_and_len_buf[0]) & 0x000000FF); |
| 89 | const uint32_t method_name_length = ntohl(version_and_len_buf[1]); |
| 90 | if (method_name_length > MAX_THRIFT_METHOD_NAME_LENGTH) { |
| 91 | return butil::Status(-1, "method_name_length=%u is too long", |
| 92 | method_name_length); |
| 93 | } |
| 94 | |
| 95 | char buf[sizeof(version_and_len_buf) + method_name_length + 4]; |
| 96 | k = body->cutn(buf, sizeof(buf)); |
| 97 | if (k != sizeof(buf)) { |
| 98 | return butil::Status(-1, "Fail to cut %zu bytes", sizeof(buf)); |
| 99 | } |
| 100 | method_name->assign(buf + sizeof(version_and_len_buf), method_name_length); |
| 101 | // suppress strict-aliasing warning |
| 102 | uint32_t* p_seq_id = (uint32_t*)(buf + sizeof(version_and_len_buf) + method_name_length); |
| 103 | *seq_id = ntohl(*p_seq_id); |
| 104 | return butil::Status::OK(); |
| 105 | } |
| 106 | |
| 107 | inline size_t ThriftMessageBeginSize(const std::string& method_name) { |
| 108 | return 12 + method_name.size(); |
no test coverage detected