1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cinttypes> 18 #include <cstring> 19 20 #include "android-base/logging.h" 21 22 #include "wifilogd/message_buffer.h" 23 24 namespace android { 25 namespace wifilogd { 26 27 using local_utils::CopyFromBufferOrDie; 28 29 MessageBuffer::MessageBuffer(size_t size) 30 : data_(new uint8_t[size]), capacity_(size), read_pos_(0), write_pos_(0) { 31 CHECK(size > GetHeaderSize()); 32 } 33 34 bool MessageBuffer::Append(const uint8_t* message, uint16_t message_len) { 35 CHECK(message_len); 36 37 if (!CanFitNow(message_len)) { 38 return false; 39 } 40 41 AppendHeader(message_len); 42 AppendRawBytes(message, message_len); 43 return true; 44 } 45 46 bool MessageBuffer::CanFitEver(uint16_t length) const { 47 // This unusual formulation is intended to avoid overflow. 48 return capacity_ - GetHeaderSize() >= length; 49 } 50 51 bool MessageBuffer::CanFitNow(uint16_t length) const { 52 // This unusual formulation is intended to avoid overflow/underflow. 53 return GetFreeSize() >= GetHeaderSize() && 54 GetFreeSize() - GetHeaderSize() >= length; 55 } 56 57 void MessageBuffer::Clear() { 58 read_pos_ = 0; 59 write_pos_ = 0; 60 } 61 62 std::tuple<const uint8_t*, size_t> MessageBuffer::ConsumeNextMessage() { 63 if (read_pos_ == write_pos_) { 64 return {nullptr, 0}; 65 } 66 67 const auto& header = CopyFromBufferOrDie<LengthHeader>( 68 data_.get() + read_pos_, GetReadableSize()); 69 read_pos_ += sizeof(header); 70 71 const uint8_t* payload_start = data_.get() + read_pos_; 72 read_pos_ += header.payload_len; 73 CHECK(read_pos_ <= write_pos_); 74 75 return {payload_start, header.payload_len}; 76 } 77 78 void MessageBuffer::Rewind() { read_pos_ = 0; } 79 80 // Private methods below. 81 82 void MessageBuffer::AppendHeader(uint16_t message_len) { 83 LengthHeader header; 84 header.payload_len = message_len; 85 AppendRawBytes(&header, sizeof(header)); 86 } 87 88 void MessageBuffer::AppendRawBytes(const void* data_start, size_t data_len) { 89 std::memcpy(data_.get() + write_pos_, data_start, data_len); 90 write_pos_ += data_len; 91 CHECK(write_pos_ <= capacity_); 92 } 93 94 } // namespace wifilogd 95 } // namespace android 96