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