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