19d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal/* 29d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * Copyright (C) 2016 The Android Open Source Project 39d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * 49d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * Licensed under the Apache License, Version 2.0 (the "License"); 59d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * you may not use this file except in compliance with the License. 69d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * You may obtain a copy of the License at 79d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * 89d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * http://www.apache.org/licenses/LICENSE-2.0 99d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * 109d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * Unless required by applicable law or agreed to in writing, software 119d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * distributed under the License is distributed on an "AS IS" BASIS, 129d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * See the License for the specific language governing permissions and 149d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal * limitations under the License. 159d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal */ 169d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 179d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#ifndef MESSAGE_BUFFER_H_ 189d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#define MESSAGE_BUFFER_H_ 199d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 209d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#include <cstdint> 219d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#include <memory> 226d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal#include <tuple> 239d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 249d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#include "android-base/macros.h" 259d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 26fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal#include "wifilogd/local_utils.h" 27fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 289d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawalnamespace android { 299d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawalnamespace wifilogd { 309d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 319d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal// A fixed-size buffer, which provides FIFO access to read and write 329d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal// a sequence of messages. 339d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawalclass MessageBuffer { 349d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal public: 35fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal // A wrapper which guarantees that a MessageBuffer will be rewound, 36fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal // when the program exits the wrapper's scope. The user must ensure that 37fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal // |buffer| does not expire before the ScopedRewinder. 38fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal class ScopedRewinder { 39fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal public: 40fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal explicit ScopedRewinder(NONNULL MessageBuffer* buffer) : buffer_(buffer) {} 41fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal ~ScopedRewinder() { buffer_->Rewind(); } 42fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal 43fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal private: 44fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal MessageBuffer* const buffer_; 45fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal }; 46fd08064ec7ca120b3501c341c8dfde9fdd757316mukesh agrawal 479d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // Constructs the buffer. |size| must be greater than GetHeaderSize(). 489d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal explicit MessageBuffer(size_t size); 499d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 50fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // Appends a single message to the buffer. |data_len| must be >=1. Returns 51fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // true if the message was added to the buffer. 52fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal bool Append(NONNULL const uint8_t* data, uint16_t data_len); 53fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 540e465b480b9067a9795139a0aa1f4144d10c485emukesh agrawal // Returns true if the buffer is large enough to hold |length| bytes of user 550e465b480b9067a9795139a0aa1f4144d10c485emukesh agrawal // data, when the buffer is empty. 560e465b480b9067a9795139a0aa1f4144d10c485emukesh agrawal bool CanFitEver(uint16_t length) const; 570e465b480b9067a9795139a0aa1f4144d10c485emukesh agrawal 58fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // Returns true if the buffer currently has enough free space to hold |length| 59fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // bytes of user data. 60fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal bool CanFitNow(uint16_t length) const; 61fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 6269690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal // Clears the buffer. An immediately following read operation will return an 6369690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal // empty message. An immediately following write operation will write to the 6469690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal // head of the buffer. Clearing may be lazy (i.e., underlying storage is not 6569690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal // necessarily zeroed). 6669690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal void Clear(); 6769690078fa70e031b80f8760f3c69f0884e42d08mukesh agrawal 686d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal // Returns the first unread message in the buffer. If there is no such 696d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal // message, returns {nullptr, 0}. MessageBuffer retains ownership of the 706d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal // message's storage. 716d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal std::tuple<const uint8_t*, size_t> ConsumeNextMessage(); 726d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal 739d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // Returns the size of MessageBuffer's per-message header. 749d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal static constexpr size_t GetHeaderSize() { return sizeof(LengthHeader); } 759d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 76fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // Returns the total available free space in the buffer. This may be 77fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // larger than the usable space, due to overheads. 78fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal size_t GetFreeSize() const { return capacity_ - write_pos_; } 79fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 805f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal // Resets the read pointer to the start of the buffer. An immediately 815f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal // following read will return the first message in the buffer. An immediately 825f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal // following write, however, will be placed at the same position as if 835f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal // Rewind() had not been called. 845f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal void Rewind(); 855f88ee735e1cf0c12f96c3add65d798ec58ad4bdmukesh agrawal 869d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal private: 879d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal struct LengthHeader { 889d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal uint16_t payload_len; 899d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal }; 909d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 91fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // Prepares a header, and writes that header into the buffer. 92fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal void AppendHeader(uint16_t message_len); 93fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 94fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal // Writes arbitrary data into the buffer. 95fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal void AppendRawBytes(NONNULL const void* data_start, size_t data_len); 96fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal 97b0ef31514a28871bf7d2435e4b5aada60e813ce1mukesh agrawal // Returns the total number of bytes available for reading. This number 98b0ef31514a28871bf7d2435e4b5aada60e813ce1mukesh agrawal // includes headers. 99b0ef31514a28871bf7d2435e4b5aada60e813ce1mukesh agrawal size_t GetReadableSize() const { return write_pos_ - read_pos_; } 100b0ef31514a28871bf7d2435e4b5aada60e813ce1mukesh agrawal 101b1af0126828f129002e28659de6d52803323b671mukesh agrawal const std::unique_ptr<uint8_t[]> data_; 102b1af0126828f129002e28659de6d52803323b671mukesh agrawal const size_t capacity_; 1036d8e2206e972a5f7512d5e2c558e9c23c77169f0mukesh agrawal size_t read_pos_; 104fd65102c2bb8b5a4cfa7d9ddff7d5f6c5d08e623mukesh agrawal size_t write_pos_; 1059d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 1069d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // MessageBuffer is a value type, so it would be semantically reasonable to 1079d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // support copy and assign. Performance-wise, though, we should avoid 1089d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // copies. Remove the copy constructor and the assignment operator, to 1099d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal // ensure that we don't accidentally make copies. 1109d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal DISALLOW_COPY_AND_ASSIGN(MessageBuffer); 1119d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal}; 1129d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 1139d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal} // namespace wifilogd 1149d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal} // namespace android 1159d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal 1169d2165f7a9c41bb0081036d4ef5b9d5150fa3684mukesh agrawal#endif // MESSAGE_BUFFER_H_ 117