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 { return address.data(); }
data()54   inline const uint8_t* data() const override { return address.data(); }
55 
56   // storage::Serializable methods
57   std::string ToString() const override;
58   std::string ToColonSepHexString() const;
59   std::string ToStringForLogging() const override;
60   std::string ToRedactedStringForLogging() const override;
61 
62   static std::optional<Address> FromString(const std::string& from);
63   std::string ToLegacyConfigString() const override;
64   static std::optional<Address> FromLegacyConfigString(const std::string& str);
65 
66   bool operator<(const Address& rhs) const { return address < rhs.address; }
67   bool operator==(const Address& rhs) const { return address == rhs.address; }
68   bool operator>(const Address& rhs) const { return rhs < *this; }
69   bool operator<=(const Address& rhs) const { return !(*this > rhs); }
70   bool operator>=(const Address& rhs) const { return !(*this < rhs); }
71   bool operator!=(const Address& rhs) const { return !(*this == rhs); }
72 
IsEmpty()73   bool IsEmpty() const { return *this == kEmpty; }
74 
75   // Converts |string| to Address and places it in |to|. If |from| does
76   // not represent a Bluetooth address, |to| is not modified and this function
77   // returns false. Otherwise, it returns true.
78   static bool FromString(const std::string& from, Address& to);
79 
80   // Copies |from| raw Bluetooth address octets to the local object.
81   // Returns the number of copied octets - should be always Address::kLength
82   size_t FromOctets(const uint8_t* from);
83 
84   static bool IsValidAddress(const std::string& address);
85 
86   static const Address kEmpty;  // 00:00:00:00:00:00
87   static const Address kAny;    // FF:FF:FF:FF:FF:FF
88 private:
89   std::string _ToMaskedColonSepHexString(int bytes_to_mask) const;
90 };
91 
92 // TODO: to fine-tune this.
93 // we need an interface between the logger and ILoggable
94 inline std::ostream& operator<<(std::ostream& os, const Address& a) {
95   os << a.ToString();
96   return os;
97 }
98 
99 }  // namespace hci
100 }  // namespace bluetooth
101 
102 namespace std {
103 template <>
104 struct hash<bluetooth::hci::Address> {
105   std::size_t operator()(const bluetooth::hci::Address& val) const {
106     static_assert(sizeof(uint64_t) >= bluetooth::hci::Address::kLength);
107     uint64_t int_addr = 0;
108     memcpy(reinterpret_cast<uint8_t*>(&int_addr), val.data(), bluetooth::hci::Address::kLength);
109     return std::hash<uint64_t>{}(int_addr);
110   }
111 };
112 }  // namespace std
113 
114 #if __has_include(<bluetooth/log.h>)
115 #include <bluetooth/log.h>
116 
117 namespace std {
118 template <>
119 struct formatter<bluetooth::hci::Address> : formatter<std::string> {
120   template <class Context>
121   typename Context::iterator format(const bluetooth::hci::Address& address, Context& ctx) const {
122     std::string repr = address.ToRedactedStringForLogging();
123     return std::formatter<std::string>::format(repr, ctx);
124   }
125 };
126 }  // namespace std
127 
128 #endif  // __has_include(<bluetooth/log.h>
129