1 //
2 //  Copyright (C) 2015 Google, Inc.
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 #include "service/common/bluetooth/uuid.h"
18 
19 #include <algorithm>
20 #include <array>
21 #include <stack>
22 #include <string>
23 
24 #include <base/rand_util.h>
25 #include <base/strings/string_split.h>
26 #include <base/strings/string_util.h>
27 #include <base/strings/stringprintf.h>
28 
29 namespace bluetooth {
30 
31 namespace {
32 
33 const UUID::UUID128Bit kSigBaseUUID = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34                                         0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
35                                         0x5f, 0x9b, 0x34, 0xfb}};
36 
37 }  // namespace
38 
39 // static
GetRandom()40 UUID UUID::GetRandom() {
41   UUID128Bit bytes;
42   base::RandBytes(bytes.data(), bytes.size());
43   return UUID(bytes);
44 }
45 
46 // static
GetNil()47 UUID UUID::GetNil() {
48   UUID128Bit bytes;
49   bytes.fill(0);
50   return UUID(bytes);
51 }
52 
53 // static
GetMax()54 UUID UUID::GetMax() {
55   UUID128Bit bytes;
56   bytes.fill(1);
57   return UUID(bytes);
58 }
59 
InitializeDefault()60 void UUID::InitializeDefault() {
61   // Initialize to Bluetooth SIG base UUID.
62   id_ = kSigBaseUUID;
63   is_valid_ = true;
64 }
65 
UUID()66 UUID::UUID() { InitializeDefault(); }
67 
UUID(std::string uuid)68 UUID::UUID(std::string uuid) {
69   InitializeDefault();
70   is_valid_ = false;
71 
72   if (uuid.empty()) return;
73 
74   if (uuid.size() < 11 && uuid.find("0x") == 0) uuid = uuid.substr(2);
75 
76   if (uuid.size() != 4 && uuid.size() != 8 && uuid.size() != 36) return;
77 
78   if (uuid.size() == 36) {
79     if (uuid[8] != '-') return;
80     if (uuid[13] != '-') return;
81     if (uuid[18] != '-') return;
82     if (uuid[23] != '-') return;
83 
84     std::vector<std::string> tokens = base::SplitString(
85         uuid, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
86 
87     if (tokens.size() != 5) return;
88 
89     uuid = base::JoinString(tokens, "");
90   }
91 
92   const int start_index = uuid.size() == 4 ? 2 : 0;
93   const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
94   for (size_t i = 0; i < copy_size; ++i) {
95     std::string octet_text(uuid, i * 2, 2);
96     char* temp = nullptr;
97     id_[start_index + i] = strtol(octet_text.c_str(), &temp, 16);
98     if (*temp != '\0') return;
99   }
100 
101   is_valid_ = true;
102 }
103 
UUID(const bt_uuid_t & uuid)104 UUID::UUID(const bt_uuid_t& uuid) {
105   std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
106   is_valid_ = true;
107 }
108 
UUID(const UUID16Bit & uuid)109 UUID::UUID(const UUID16Bit& uuid) {
110   InitializeDefault();
111   std::copy(uuid.begin(), uuid.end(), id_.begin() + kNumBytes16);
112 }
113 
UUID(const UUID32Bit & uuid)114 UUID::UUID(const UUID32Bit& uuid) {
115   InitializeDefault();
116   std::copy(uuid.begin(), uuid.end(), id_.begin());
117 }
118 
UUID(const UUID128Bit & uuid)119 UUID::UUID(const UUID128Bit& uuid) : id_(uuid), is_valid_(true) {}
120 
GetFullBigEndian() const121 UUID::UUID128Bit UUID::GetFullBigEndian() const { return id_; }
122 
GetFullLittleEndian() const123 UUID::UUID128Bit UUID::GetFullLittleEndian() const {
124   UUID::UUID128Bit ret;
125   std::reverse_copy(id_.begin(), id_.end(), ret.begin());
126   return ret;
127 }
128 
GetBlueDroid() const129 bt_uuid_t UUID::GetBlueDroid() const {
130   bt_uuid_t ret;
131   std::reverse_copy(id_.begin(), id_.end(), ret.uu);
132   return ret;
133 }
134 
ToString() const135 std::string UUID::ToString() const {
136   return base::StringPrintf(
137       "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
138       id_[0], id_[1], id_[2], id_[3], id_[4], id_[5], id_[6], id_[7], id_[8],
139       id_[9], id_[10], id_[11], id_[12], id_[13], id_[14], id_[15]);
140 }
141 
GetShortestRepresentationSize() const142 size_t UUID::GetShortestRepresentationSize() const {
143   if (memcmp(id_.data() + 4, kSigBaseUUID.data() + 4, id_.size() - 4) != 0)
144     return kNumBytes128;
145 
146   if (id_[0] == 0 && id_[1] == 0) return kNumBytes16;
147 
148   return kNumBytes32;
149 }
150 
operator <(const UUID & rhs) const151 bool UUID::operator<(const UUID& rhs) const {
152   return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
153                                       rhs.id_.end());
154 }
155 
operator ==(const UUID & rhs) const156 bool UUID::operator==(const UUID& rhs) const {
157   return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
158 }
159 
160 }  // namespace bluetooth
161