bool McParser::readUmbrellaData() { while (!readBuffer_.empty()) { auto st = um_parse_header(readBuffer_.data(), readBuffer_.length(), &umMsgInfo_); if (st == um_not_enough_data) { return true; } if (st != um_ok) { errorHelper(McReply(mc_res_remote_error, "Error parsing Umbrella header")); return false; } /* Three cases: */ if (readBuffer_.length() >= umMsgInfo_.message_size) { /* 1) we already have the entire message */ if (!umMessageReady( readBuffer_.data(), readBuffer_.data() + umMsgInfo_.header_size, readBuffer_)) { readBuffer_.clear(); return false; } /* Re-enter the loop */ readBuffer_.trimStart(umMsgInfo_.message_size); continue; } else if (readBuffer_.length() >= umMsgInfo_.header_size && umMsgInfo_.message_size - readBuffer_.length() > minBufferSize_) { /* 2) we have the entire header, but body is incomplete. Copy the partially read body into the new buffer. TODO: this copy could be eliminated, but needs some modification of umbrella library. */ auto partial = readBuffer_.length() - umMsgInfo_.header_size; umBodyBuffer_ = folly::IOBuf::copyBuffer( readBuffer_.data() + umMsgInfo_.header_size, partial, /* headroom= */ 0, /* minTailroom= */ umMsgInfo_.body_size - partial); return true; } /* 3) else header is incomplete */ return true; } return true; }
um_status_t um_consume_no_copy(const uint8_t* header, size_t nheader, const uint8_t* body, size_t nbody, uint64_t* reqid_out, mc_msg_t* msg_out) { FBI_ASSERT(header && body && reqid_out && msg_out); um_message_info_t info; um_status_t header_rv = um_parse_header(header, nheader, &info); if (header_rv != um_ok) { return header_rv; } if (!(nheader == info.header_size && nbody == info.body_size && nheader + nbody == info.message_size)) { return um_invalid_range; } entry_list_t elist; entry_list_init(&elist); /* We know that header/body won't be modified here, but the interface is messed up */ ssize_t rv = entry_list_read_from_buf(&elist, (char*)header, nheader, (char*)body, nbody, /*free_buf_when_done=*/0); if (rv < 0 || rv != info.message_size) { return um_message_parse_error; } _parse_info_t parse_info; if (_fill_base_msg(&elist, msg_out, &parse_info) != 0) { return um_message_parse_error; } /* TODO: support stats with no_copy API */ if (parse_info.stats_count > 0) { return um_message_parse_error; } if (_fill_msg_strs(msg_out, &elist, body, &parse_info) != 0) { return um_message_parse_error; } *reqid_out = parse_info.reqid; return um_ok; }