blob: 71e688c0a166d7c1190458393035098081351c9c [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 Schuh20ac95d2020-12-05 17:24:19 -080010#include "glog/logging.h"
11
Austin Schuh64fab802020-09-09 22:47:47 -070012namespace aos {
13namespace {
Austin Schuh5e2bfb82021-03-13 22:46:55 -080014void ToHex(const uint8_t *val, char *result, size_t count) {
15 while (count > 0) {
16 int upper = ((*val) >> 4) & 0xf;
17 if (upper < 10) {
18 result[0] = upper + '0';
19 } else {
20 result[0] = upper - 10 + 'a';
21 }
22
23 int lower = (*val) & 0xf;
24 if (lower < 10) {
25 result[1] = lower + '0';
26 } else {
27 result[1] = lower - 10 + 'a';
28 }
29
30 ++val;
31 result += 2;
32 --count;
Austin Schuh64fab802020-09-09 22:47:47 -070033 }
34}
Austin Schuh5e2bfb82021-03-13 22:46:55 -080035
36void FromHex(const char *val, uint8_t *result, size_t count) {
37 while (count > 0) {
38 CHECK((val[0] >= '0' && val[0] <= '9') || (val[0] >= 'a' && val[0] <= 'f'))
39 << ": Invalid hex '" << val[0] << "'";
40 CHECK((val[1] >= '0' && val[1] <= '9') || (val[1] >= 'a' && val[1] <= 'f'))
41 << ": Invalid hex '" << val[1] << "'";
42
43 uint8_t converted = 0;
44 if (val[0] < 'a') {
45 converted |= static_cast<uint8_t>(val[0] - '0') << 4;
46 } else {
47 converted |= (static_cast<uint8_t>(val[0] - 'a') + 0xa) << 4;
48 }
49 if (val[1] < 'a') {
50 converted |= static_cast<uint8_t>(val[1] - '0');
51 } else {
52 converted |= (static_cast<uint8_t>(val[1] - 'a') + 0xa);
53 }
54 *result = converted;
55
56 val += 2;
57 ++result;
58 --count;
59 }
60}
61
Austin Schuh64fab802020-09-09 22:47:47 -070062} // namespace
63
64UUID UUID::Random() {
65 std::random_device rd;
66 std::mt19937 gen(rd());
67
Austin Schuh5e2bfb82021-03-13 22:46:55 -080068 std::uniform_int_distribution<> dis(0, 255);
Austin Schuh64fab802020-09-09 22:47:47 -070069 std::uniform_int_distribution<> dis2(8, 11);
Austin Schuh64fab802020-09-09 22:47:47 -070070 UUID result;
Austin Schuh5e2bfb82021-03-13 22:46:55 -080071 for (size_t i = 0; i < kDataSize; ++i) {
72 result.data_[i] = dis(gen);
73 }
Austin Schuh64fab802020-09-09 22:47:47 -070074
Austin Schuh5e2bfb82021-03-13 22:46:55 -080075 // Mark the reserved bits in the data that this is a uuid4, a random UUID.
76 result.data_[6] = (result.data_[6] & 0x0f) | 0x40;
77 result.data_[8] = (result.data_[6] & 0x3f) | 0x80;
Austin Schuh64fab802020-09-09 22:47:47 -070078
79 return result;
80}
81
Austin Schuh5e2bfb82021-03-13 22:46:55 -080082std::string UUID::ToString() const {
83 std::string out;
84 out.resize(UUID::kStringSize);
85 CopyTo(out.data());
86 return out;
87}
88
89std::ostream &operator<<(std::ostream &os, const UUID &uuid) {
90 return os << uuid.ToString();
91}
92
93flatbuffers::Offset<flatbuffers::String> UUID::PackString(
94 flatbuffers::FlatBufferBuilder *fbb) const {
95 std::array<char, kStringSize> data;
96 CopyTo(data.data());
97
98 return fbb->CreateString(data.data(), data.size());
99}
100
101flatbuffers::Offset<flatbuffers::Vector<uint8_t>> UUID::PackVector(
102 flatbuffers::FlatBufferBuilder *fbb) const {
103 return fbb->CreateVector(data_.data(), data_.size());
104}
105
106void UUID::CopyTo(char *result) const {
107 ToHex(&data_[0], result, 4);
108 result[8] = '-';
109 ToHex(&data_[4], result + 9, 2);
110 result[13] = '-';
111 ToHex(&data_[6], result + 14, 2);
112 result[18] = '-';
113 ToHex(&data_[8], result + 19, 2);
114 result[23] = '-';
115 ToHex(&data_[10], result + 24, 6);
116}
117
118UUID UUID::Zero() {
119 UUID result;
120 std::memset(result.data_.data(), 0, result.data_.size());
121 return result;
122}
123
124UUID UUID::FromString(const flatbuffers::String *str) {
125 return FromString(str->string_view());
126}
127
128UUID UUID::FromVector(const flatbuffers::Vector<uint8_t> *data) {
129 CHECK(data != nullptr);
130 CHECK_EQ(data->size(), kDataSize);
131
132 UUID result;
133 std::memcpy(result.data_.data(), data->Data(), kDataSize);
134 return result;
135}
Austin Schuh20ac95d2020-12-05 17:24:19 -0800136
137UUID UUID::FromString(std::string_view str) {
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800138 CHECK_EQ(str.size(), kStringSize);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800139
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800140 UUID result;
141 FromHex(str.data(), result.data_.data(), 4);
142 CHECK(str.data()[8] == '-' && str.data()[13] == '-' &&
143 str.data()[18] == '-' && str.data()[23] == '-')
144 << ": Invalid uuid.";
145 FromHex(str.data() + 9, result.data_.data() + 4, 2);
146 FromHex(str.data() + 14, result.data_.data() + 6, 2);
147 FromHex(str.data() + 19, result.data_.data() + 8, 2);
148 FromHex(str.data() + 24, result.data_.data() + 10, 6);
Austin Schuh20ac95d2020-12-05 17:24:19 -0800149 return result;
150}
151
152UUID UUID::BootUUID() {
153 int fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY);
154 PCHECK(fd != -1);
155
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800156 std::array<char, kStringSize> data;
157 CHECK_EQ(static_cast<ssize_t>(kStringSize),
158 read(fd, data.begin(), kStringSize));
Austin Schuh20ac95d2020-12-05 17:24:19 -0800159 close(fd);
160
Austin Schuh5e2bfb82021-03-13 22:46:55 -0800161 return UUID::FromString(std::string_view(data.data(), data.size()));
Brian Silverman1f345222020-09-24 21:14:48 -0700162}
163
Austin Schuh64fab802020-09-09 22:47:47 -0700164} // namespace aos