blob: 86baed634bd7f971a81f66db44f10cc802815e45 [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 Schuh60e77942022-05-16 17:48:24 -07006
Austin Schuh64fab802020-09-09 22:47:47 -07007#include <array>
8#include <random>
9#include <string_view>
10
Austin Schuh8902fa52021-03-14 22:39:24 -070011#include "gflags/gflags.h"
Austin Schuh20ac95d2020-12-05 17:24:19 -080012#include "glog/logging.h"
13
Austin Schuh8902fa52021-03-14 22:39:24 -070014DEFINE_string(boot_uuid, "",
15 "If set, override the boot UUID to have this value instead.");
16
Austin Schuh64fab802020-09-09 22:47:47 -070017namespace aos {
18namespace {
Austin Schuh5e2bfb82021-03-13 22:46:55 -080019void ToHex(const uint8_t *val, char *result, size_t count) {
20 while (count > 0) {
21 int upper = ((*val) >> 4) & 0xf;
22 if (upper < 10) {
23 result[0] = upper + '0';
24 } else {
25 result[0] = upper - 10 + 'a';
26 }
27
28 int lower = (*val) & 0xf;
29 if (lower < 10) {
30 result[1] = lower + '0';
31 } else {
32 result[1] = lower - 10 + 'a';
33 }
34
35 ++val;
36 result += 2;
37 --count;
Austin Schuh64fab802020-09-09 22:47:47 -070038 }
39}
Austin Schuh5e2bfb82021-03-13 22:46:55 -080040
41void FromHex(const char *val, uint8_t *result, size_t count) {
42 while (count > 0) {
43 CHECK((val[0] >= '0' && val[0] <= '9') || (val[0] >= 'a' && val[0] <= 'f'))
44 << ": Invalid hex '" << val[0] << "'";
45 CHECK((val[1] >= '0' && val[1] <= '9') || (val[1] >= 'a' && val[1] <= 'f'))
46 << ": Invalid hex '" << val[1] << "'";
47
48 uint8_t converted = 0;
49 if (val[0] < 'a') {
50 converted |= static_cast<uint8_t>(val[0] - '0') << 4;
51 } else {
52 converted |= (static_cast<uint8_t>(val[0] - 'a') + 0xa) << 4;
53 }
54 if (val[1] < 'a') {
55 converted |= static_cast<uint8_t>(val[1] - '0');
56 } else {
57 converted |= (static_cast<uint8_t>(val[1] - 'a') + 0xa);
58 }
59 *result = converted;
60
61 val += 2;
62 ++result;
63 --count;
64 }
65}
66
Austin Schuh64fab802020-09-09 22:47:47 -070067} // namespace
68
69UUID UUID::Random() {
70 std::random_device rd;
71 std::mt19937 gen(rd());
72
Austin Schuh5e2bfb82021-03-13 22:46:55 -080073 std::uniform_int_distribution<> dis(0, 255);
Austin Schuh64fab802020-09-09 22:47:47 -070074 std::uniform_int_distribution<> dis2(8, 11);
Austin Schuh64fab802020-09-09 22:47:47 -070075 UUID result;
Austin Schuh5e2bfb82021-03-13 22:46:55 -080076 for (size_t i = 0; i < kDataSize; ++i) {
77 result.data_[i] = dis(gen);
78 }
Austin Schuh64fab802020-09-09 22:47:47 -070079
Austin Schuh5e2bfb82021-03-13 22:46:55 -080080 // Mark the reserved bits in the data that this is a uuid4, a random UUID.
81 result.data_[6] = (result.data_[6] & 0x0f) | 0x40;
82 result.data_[8] = (result.data_[6] & 0x3f) | 0x80;
Austin Schuh64fab802020-09-09 22:47:47 -070083
84 return result;
85}
86
Austin Schuh5e2bfb82021-03-13 22:46:55 -080087std::string UUID::ToString() const {
88 std::string out;
89 out.resize(UUID::kStringSize);
90 CopyTo(out.data());
91 return out;
92}
93
94std::ostream &operator<<(std::ostream &os, const UUID &uuid) {
95 return os << uuid.ToString();
96}
97
98flatbuffers::Offset<flatbuffers::String> UUID::PackString(
99 flatbuffers::FlatBufferBuilder *fbb) const {
100 std::array<char, kStringSize> data;
101 CopyTo(data.data());
102
103 return fbb->CreateString(data.data(), data.size());
104}
105
106flatbuffers::Offset<flatbuffers::Vector<uint8_t>> UUID::PackVector(
107 flatbuffers::FlatBufferBuilder *fbb) const {
108 return fbb->CreateVector(data_.data(), data_.size());
109}
110
111void UUID::CopyTo(char *result) const {
112 ToHex(&data_[0], result, 4);
113 result[8] = '-';
114 ToHex(&data_[4], result + 9, 2);
115 result[13] = '-';
116 ToHex(&data_[6], result + 14, 2);
117 result[18] = '-';
118 ToHex(&data_[8], result + 19, 2);
119 result[23] = '-';
120 ToHex(&data_[10], result + 24, 6);
121}
122
123UUID UUID::Zero() {
124 UUID result;
125 std::memset(result.data_.data(), 0, result.data_.size());
126 return result;
127}
128
129UUID UUID::FromString(const flatbuffers::String *str) {
130 return FromString(str->string_view());
131}
132
133UUID UUID::FromVector(const flatbuffers::Vector<uint8_t> *data) {
134 CHECK(data != nullptr);
135 CHECK_EQ(data->size(), kDataSize);
136
137 UUID result;
138 std::memcpy(result.data_.data(), data->Data(), kDataSize);
139 return result;
140}
Austin Schuh20ac95d2020-12-05 17:24:19 -0800141
142UUID UUID::FromString(std::string_view str) {
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800143 CHECK_EQ(str.size(), kStringSize);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800144
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800145 UUID result;
146 FromHex(str.data(), result.data_.data(), 4);
147 CHECK(str.data()[8] == '-' && str.data()[13] == '-' &&
148 str.data()[18] == '-' && str.data()[23] == '-')
149 << ": Invalid uuid.";
150 FromHex(str.data() + 9, result.data_.data() + 4, 2);
151 FromHex(str.data() + 14, result.data_.data() + 6, 2);
152 FromHex(str.data() + 19, result.data_.data() + 8, 2);
153 FromHex(str.data() + 24, result.data_.data() + 10, 6);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800154 return result;
155}
156
157UUID UUID::BootUUID() {
Austin Schuh8902fa52021-03-14 22:39:24 -0700158 if (!FLAGS_boot_uuid.empty()) {
159 return UUID::FromString(FLAGS_boot_uuid);
160 }
161
Austin Schuh20ac95d2020-12-05 17:24:19 -0800162 int fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY);
163 PCHECK(fd != -1);
164
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800165 std::array<char, kStringSize> data;
166 CHECK_EQ(static_cast<ssize_t>(kStringSize),
167 read(fd, data.begin(), kStringSize));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800168 close(fd);
169
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800170 return UUID::FromString(std::string_view(data.data(), data.size()));
Brian Silverman1f345222020-09-24 21:14:48 -0700171}
172
Austin Schuh64fab802020-09-09 22:47:47 -0700173} // namespace aos