5 #include "util/rpc/frame_format.h" 7 #include <boost/asio/read.hpp> 9 #include "absl/strings/escaping.h" 10 #include "base/bits.h" 11 #include "base/endian.h" 12 #include "base/logging.h" 13 #include "util/asio/yield.h" 14 #include "util/asio/error.h" 17 using fibers_ext::yield;
20 using namespace boost;
21 using namespace system;
25 constexpr uint8 kHeader[] =
"URPC";
27 inline uint8 SizeByteCountMinus1(uint32 size) {
28 return size <= 255 ? 0 : Bits::FindMSBSetNonZero(size) / 8;
31 inline constexpr uint32 byte_mask(uint8 n) {
32 return (1UL << (n + 1) * 8) - 1;
37 std::ostream& operator<<(std::ostream& o,
const Frame& frame) {
38 o <<
"{ rpc_id " << frame.rpc_id <<
", header_size: " << frame.header_size
39 <<
", letter_size: " << frame.letter_size <<
" }";
43 const uint32 Frame::kHeaderVal = LittleEndian::Load32(kHeader);
45 uint8_t Frame::DecodeStart(
const uint8_t* src, ::boost::system::error_code& ec) {
46 if (kHeaderVal != LittleEndian::Load32(src)) {
47 ec = make_error_code(gaia_error::bad_header);
51 if (src[4] >> 4 != 0) {
52 ec = make_error_code(gaia_error::invalid_version);
55 rpc_id = UNALIGNED_LOAD64(src + 4);
61 void Frame::DecodeEnd(
const uint8_t* src, uint8_t hsz_len, uint8_t lsz_len) {
62 header_size = LittleEndian::Load32(src) & byte_mask(hsz_len);
63 letter_size = LittleEndian::Load32(src + hsz_len + 1) & byte_mask(lsz_len);
66 unsigned Frame::Write(uint8* dest)
const {
67 LittleEndian::Store32(dest, kHeaderVal);
69 const uint8 msg_bytes_minus1 = SizeByteCountMinus1(letter_size);
70 const uint8 cntrl_bytes_minus1 = SizeByteCountMinus1(header_size);
72 DCHECK_LT(msg_bytes_minus1, 4);
73 DCHECK_LT(cntrl_bytes_minus1, 4);
75 uint64_t version = cntrl_bytes_minus1 | (msg_bytes_minus1 << 2) | (0 << 4);
77 LittleEndian::Store64(dest, (rpc_id << 8) | version);
80 LittleEndian::Store32(dest, header_size);
81 dest += (cntrl_bytes_minus1 + 1);
82 LittleEndian::Store32(dest, letter_size);
84 return 4 + 1 + 7 + cntrl_bytes_minus1 + msg_bytes_minus1 + 2;