1 /******************************************************************************
2  *
3  *  Copyright 2019 The Android Open Source Project
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #pragma once
20 
21 #include <array>
22 #include <cstring>
23 #include <initializer_list>
24 #include <optional>
25 #include <ostream>
26 #include <string>
27 
28 #include "common/interfaces/ILoggable.h"
29 #include "os/logging/log_adapter.h"
30 #include "packet/custom_field_fixed_size_interface.h"
31 #include "storage/serializable.h"
32 
33 namespace bluetooth {
34 namespace hci {
35 
36 class Address final : public packet::CustomFieldFixedSizeInterface<Address>,
37                       public storage::Serializable<Address>,
38                       public bluetooth::common::IRedactableLoggable {
39  public:
40   static constexpr size_t kLength = 6;
41 
42   // Bluetooth MAC address bytes saved in little endian format.
43   // The address MSB is address[5], the address LSB is address[0].
44   // Note that the textual representation follows the big endian format,
45   // ie. Address{0, 1, 2, 3, 4, 5} is represented as 05:04:03:02:01:00.
46   std::array<uint8_t, kLength> address = {};
47 
48   Address() = default;
49   Address(const uint8_t (&addr)[kLength]);
50   Address(std::initializer_list<uint8_t> l);
51 
52   // CustomFieldFixedSizeInterface methods
data()53   inline uint8_t* data() override {
54     return address.data();
55   }
data()56   inline const uint8_t* data() const override {
57     return address.data();
58   }
59 
60   // storage::Serializable methods
61   std::string ToString() const override;
62   std::string ToColonSepHexString() const;
63   std::string ToStringForLogging() const override;
64   std::string ToRedactedStringForLogging() const override;
65 
66   static std::optional<Address> FromString(const std::string& from);
67   std::string ToLegacyConfigString() const override;
68   static std::optional<Address> FromLegacyConfigString(const std::string& str);
69 
70   bool operator<(const Address& rhs) const {
71     return address < rhs.address;
72   }
73   bool operator==(const Address& rhs) const {
74     return address == rhs.address;
75   }
76   bool operator>(const Address& rhs) const {
77     return (rhs < *this);
78   }
79   bool operator<=(const Address& rhs) const {
80     return !(*this > rhs);
81   }
82   bool operator>=(const Address& rhs) const {
83     return !(*this < rhs);
84   }
85   bool operator!=(const Address& rhs) const {
86     return !(*this == rhs);
87   }
88 
IsEmpty()89   bool IsEmpty() const {
90     return *this == kEmpty;
91   }
92 
93   // Converts |string| to Address and places it in |to|. If |from| does
94   // not represent a Bluetooth address, |to| is not modified and this function
95   // returns false. Otherwise, it returns true.
96   static bool FromString(const std::string& from, Address& to);
97 
98   // Copies |from| raw Bluetooth address octets to the local object.
99   // Returns the number of copied octets - should be always Address::kLength
100   size_t FromOctets(const uint8_t* from);
101 
102   static bool IsValidAddress(const std::string& address);
103 
104   static const Address kEmpty;  // 00:00:00:00:00:00
105   static const Address kAny;    // FF:FF:FF:FF:FF:FF
106  private:
107   std::string _ToMaskedColonSepHexString(int bytes_to_mask) const;
108 };
109 
110 // TODO: to fine-tune this.
111 // we need an interface between the logger and ILoggable
112 inline std::ostream& operator<<(std::ostream& os, const Address& a) {
113   os << a.ToString();
114   return os;
115 }
116 
117 }  // namespace hci
118 }  // namespace bluetooth
119 
120 namespace std {
121 template <>
122 struct hash<bluetooth::hci::Address> {
123   std::size_t operator()(const bluetooth::hci::Address& val) const {
124     static_assert(sizeof(uint64_t) >= bluetooth::hci::Address::kLength);
125     uint64_t int_addr = 0;
126     memcpy(reinterpret_cast<uint8_t*>(&int_addr), val.data(), bluetooth::hci::Address::kLength);
127     return std::hash<uint64_t>{}(int_addr);
128   }
129 };
130 }  // namespace std
131 
132 #if __has_include(<bluetooth/log.h>)
133 #include <bluetooth/log.h>
134 
135 namespace fmt {
136 template <>
137 struct formatter<bluetooth::hci::Address> : formatter<std::string> {
138   template <class Context>
139   typename Context::iterator format(const bluetooth::hci::Address& address, Context& ctx) const {
140     std::string repr = bluetooth::os::should_log_be_redacted()
141                            ? address.ToRedactedStringForLogging()
142                            : address.ToStringForLogging();
143     return fmt::formatter<std::string>::format(repr, ctx);
144   }
145 };
146 }  // namespace fmt
147 
148 #endif  // __has_include(<bluetooth/log.h>
149