blob: 2e3290bc8113ad5cda1f822a4d98f08090617fe2 [file] [log] [blame]
Austin Schuh4385b142021-03-14 21:31:13 -07001#include "aos/uuid.h"
Austin Schuh64fab802020-09-09 22:47:47 -07002
Austin Schuh20ac95d2020-12-05 17:24:19 -08003#include <fcntl.h>
4#include <sys/stat.h>
5#include <sys/types.h>
Austin Schuh64fab802020-09-09 22:47:47 -07006#include <array>
7#include <random>
8#include <string_view>
9
Austin Schuh8902fa52021-03-14 22:39:24 -070010#include "gflags/gflags.h"
Austin Schuh20ac95d2020-12-05 17:24:19 -080011#include "glog/logging.h"
12
Austin Schuh8902fa52021-03-14 22:39:24 -070013DEFINE_string(boot_uuid, "",
14 "If set, override the boot UUID to have this value instead.");
15
Austin Schuh64fab802020-09-09 22:47:47 -070016namespace aos {
17namespace {
Austin Schuh5e2bfb82021-03-13 22:46:55 -080018void ToHex(const uint8_t *val, char *result, size_t count) {
19 while (count > 0) {
20 int upper = ((*val) >> 4) & 0xf;
21 if (upper < 10) {
22 result[0] = upper + '0';
23 } else {
24 result[0] = upper - 10 + 'a';
25 }
26
27 int lower = (*val) & 0xf;
28 if (lower < 10) {
29 result[1] = lower + '0';
30 } else {
31 result[1] = lower - 10 + 'a';
32 }
33
34 ++val;
35 result += 2;
36 --count;
Austin Schuh64fab802020-09-09 22:47:47 -070037 }
38}
Austin Schuh5e2bfb82021-03-13 22:46:55 -080039
40void FromHex(const char *val, uint8_t *result, size_t count) {
41 while (count > 0) {
42 CHECK((val[0] >= '0' && val[0] <= '9') || (val[0] >= 'a' && val[0] <= 'f'))
43 << ": Invalid hex '" << val[0] << "'";
44 CHECK((val[1] >= '0' && val[1] <= '9') || (val[1] >= 'a' && val[1] <= 'f'))
45 << ": Invalid hex '" << val[1] << "'";
46
47 uint8_t converted = 0;
48 if (val[0] < 'a') {
49 converted |= static_cast<uint8_t>(val[0] - '0') << 4;
50 } else {
51 converted |= (static_cast<uint8_t>(val[0] - 'a') + 0xa) << 4;
52 }
53 if (val[1] < 'a') {
54 converted |= static_cast<uint8_t>(val[1] - '0');
55 } else {
56 converted |= (static_cast<uint8_t>(val[1] - 'a') + 0xa);
57 }
58 *result = converted;
59
60 val += 2;
61 ++result;
62 --count;
63 }
64}
65
Austin Schuh64fab802020-09-09 22:47:47 -070066} // namespace
67
68UUID UUID::Random() {
69 std::random_device rd;
70 std::mt19937 gen(rd());
71
Austin Schuh5e2bfb82021-03-13 22:46:55 -080072 std::uniform_int_distribution<> dis(0, 255);
Austin Schuh64fab802020-09-09 22:47:47 -070073 std::uniform_int_distribution<> dis2(8, 11);
Austin Schuh64fab802020-09-09 22:47:47 -070074 UUID result;
Austin Schuh5e2bfb82021-03-13 22:46:55 -080075 for (size_t i = 0; i < kDataSize; ++i) {
76 result.data_[i] = dis(gen);
77 }
Austin Schuh64fab802020-09-09 22:47:47 -070078
Austin Schuh5e2bfb82021-03-13 22:46:55 -080079 // Mark the reserved bits in the data that this is a uuid4, a random UUID.
80 result.data_[6] = (result.data_[6] & 0x0f) | 0x40;
81 result.data_[8] = (result.data_[6] & 0x3f) | 0x80;
Austin Schuh64fab802020-09-09 22:47:47 -070082
83 return result;
84}
85
Austin Schuh5e2bfb82021-03-13 22:46:55 -080086std::string UUID::ToString() const {
87 std::string out;
88 out.resize(UUID::kStringSize);
89 CopyTo(out.data());
90 return out;
91}
92
93std::ostream &operator<<(std::ostream &os, const UUID &uuid) {
94 return os << uuid.ToString();
95}
96
97flatbuffers::Offset<flatbuffers::String> UUID::PackString(
98 flatbuffers::FlatBufferBuilder *fbb) const {
99 std::array<char, kStringSize> data;
100 CopyTo(data.data());
101
102 return fbb->CreateString(data.data(), data.size());
103}
104
105flatbuffers::Offset<flatbuffers::Vector<uint8_t>> UUID::PackVector(
106 flatbuffers::FlatBufferBuilder *fbb) const {
107 return fbb->CreateVector(data_.data(), data_.size());
108}
109
110void UUID::CopyTo(char *result) const {
111 ToHex(&data_[0], result, 4);
112 result[8] = '-';
113 ToHex(&data_[4], result + 9, 2);
114 result[13] = '-';
115 ToHex(&data_[6], result + 14, 2);
116 result[18] = '-';
117 ToHex(&data_[8], result + 19, 2);
118 result[23] = '-';
119 ToHex(&data_[10], result + 24, 6);
120}
121
122UUID UUID::Zero() {
123 UUID result;
124 std::memset(result.data_.data(), 0, result.data_.size());
125 return result;
126}
127
128UUID UUID::FromString(const flatbuffers::String *str) {
129 return FromString(str->string_view());
130}
131
132UUID UUID::FromVector(const flatbuffers::Vector<uint8_t> *data) {
133 CHECK(data != nullptr);
134 CHECK_EQ(data->size(), kDataSize);
135
136 UUID result;
137 std::memcpy(result.data_.data(), data->Data(), kDataSize);
138 return result;
139}
Austin Schuh20ac95d2020-12-05 17:24:19 -0800140
141UUID UUID::FromString(std::string_view str) {
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800142 CHECK_EQ(str.size(), kStringSize);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800143
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800144 UUID result;
145 FromHex(str.data(), result.data_.data(), 4);
146 CHECK(str.data()[8] == '-' && str.data()[13] == '-' &&
147 str.data()[18] == '-' && str.data()[23] == '-')
148 << ": Invalid uuid.";
149 FromHex(str.data() + 9, result.data_.data() + 4, 2);
150 FromHex(str.data() + 14, result.data_.data() + 6, 2);
151 FromHex(str.data() + 19, result.data_.data() + 8, 2);
152 FromHex(str.data() + 24, result.data_.data() + 10, 6);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800153 return result;
154}
155
156UUID UUID::BootUUID() {
Austin Schuh8902fa52021-03-14 22:39:24 -0700157 if (!FLAGS_boot_uuid.empty()) {
158 return UUID::FromString(FLAGS_boot_uuid);
159 }
160
Austin Schuh20ac95d2020-12-05 17:24:19 -0800161 int fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY);
162 PCHECK(fd != -1);
163
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800164 std::array<char, kStringSize> data;
165 CHECK_EQ(static_cast<ssize_t>(kStringSize),
166 read(fd, data.begin(), kStringSize));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800167 close(fd);
168
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800169 return UUID::FromString(std::string_view(data.data(), data.size()));
Brian Silverman1f345222020-09-24 21:14:48 -0700170}
171
Austin Schuh64fab802020-09-09 22:47:47 -0700172} // namespace aos