1 /* 2 * Copyright 2018 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 #pragma once 18 19 #include <cstdint> 20 #include <memory> 21 #include <type_traits> 22 #include <utility> 23 #include <vector> 24 25 namespace bluetooth { 26 27 // Abstract base class that is subclassed to provide type-specifc accessors on 28 // data. Manages said data's memory and guarantees the data's persistence. Once 29 // created the underlying data is immutable. 30 class Packet : public std::enable_shared_from_this<Packet> { 31 friend class Iterator; 32 friend class PacketBuilder; 33 34 public: 35 virtual ~Packet() = default; 36 37 protected: Packet()38 Packet() 39 : packet_start_index_(0), 40 packet_end_index_(0), 41 data_(std::make_shared<std::vector<uint8_t>>(0)){}; Packet(std::shared_ptr<const Packet> pkt,size_t start,size_t end)42 Packet(std::shared_ptr<const Packet> pkt, size_t start, size_t end) 43 : packet_start_index_(start), packet_end_index_(end), data_(pkt->data_){}; Packet(std::shared_ptr<const Packet> pkt)44 Packet(std::shared_ptr<const Packet> pkt) : data_(pkt->data_) { 45 auto indices = pkt->GetPayloadIndecies(); 46 packet_start_index_ = indices.first; 47 packet_end_index_ = indices.second; 48 }; 49 50 public: 51 size_t size() const; 52 class Iterator begin() const; 53 class Iterator end() const; 54 55 uint8_t operator[](size_t i); 56 57 // Check to see if the packet is structured correctly and have the correct 58 // lengths. Data access on an invalid packet may cause a crash. 59 virtual bool IsValid() const = 0; 60 61 // Debug string representation of the packet 62 virtual std::string ToString() const = 0; 63 64 // Convert a packet horizontally in a layer, you may only specialize 65 // into a more specific type and doing otherwise will cause a compiler error 66 // 67 // Example: 68 // std::shared_ptr<AvrcpPacket> base; 69 // std::shared_ptr<AvrcpVendorPacket> p = 70 // Packet::Specialize<AvrcpVendorPacket>(base); 71 template <class T, class U> Specialize(const std::shared_ptr<U> & pkt)72 static std::shared_ptr<T> Specialize(const std::shared_ptr<U>& pkt) { 73 static_assert(std::is_convertible<U*, Packet*>::value, 74 "Unable to specialize a non-packet object."); 75 static_assert(std::is_convertible<T*, Packet*>::value, 76 "Unable to specialize to something that isn't a packet"); 77 static_assert(std::is_convertible<T*, U*>::value, 78 "Can not convert between the two packet types."); 79 return std::shared_ptr<T>( 80 new T(pkt, pkt->packet_start_index_, pkt->packet_end_index_)); 81 }; 82 83 protected: 84 // Packet should be immutable other than when building 85 size_t packet_start_index_; 86 size_t packet_end_index_; 87 std::shared_ptr<std::vector<uint8_t>> data_; 88 89 private: 90 // Only Available to the iterators 91 virtual size_t get_length() const; 92 virtual uint8_t get_at_index(size_t index) const; 93 94 // Returns the begining and end indicies of the payload of the packet. 95 // Used when constructing a packet from another packet when moving 96 // between layers. 97 virtual std::pair<size_t, size_t> GetPayloadIndecies() const = 0; 98 }; 99 100 } // namespace bluetooth 101