Haio 0.2.X
Homebrew Asset IO/CDN
Loading...
Searching...
No Matches
key.cpp
Go to the documentation of this file.
1#include <haio_cache.hpp>
2#include <haio_util.hpp>
3
4#include <wolfssl/options.h>
5#include <wolfssl/wolfcrypt/md5.h>
6
7#include <stdexcept>
8#include <string>
9#include <vector>
10
11namespace {
12
13std::string hexMd5(std::string_view text) {
14 wc_Md5 state;
15 if (wc_InitMd5(&state) != 0) throw std::runtime_error("cannot start md5");
16
17 wc_Md5Update(&state, reinterpret_cast<const uint8_t*>(text.data()), static_cast<word32>(text.size()));
18 uint8_t digest[WC_MD5_DIGEST_SIZE];
19 wc_Md5Final(&state, digest);
20
21 static constexpr char hex[] = "0123456789abcdef";
22 std::string out(WC_MD5_DIGEST_SIZE * 2, '0');
23 for (size_t at = 0; at < WC_MD5_DIGEST_SIZE; at++) {
24 out[at * 2] = hex[digest[at] >> 4];
25 out[at * 2 + 1] = hex[digest[at] & 0x0F];
26 }
27 return out;
28}
29
30}
31
32namespace Haio::Cdn {
33
34std::string cacheKey(std::string_view bucket, std::string_view path, std::string_view query) {
35 std::string normalised;
36 normalised.reserve(bucket.size() + path.size() + query.size() + 2);
37 normalised += bucket;
38 normalised += '\n';
39 normalised += path;
40 normalised += '\n';
41 normalised += query;
42 return hexMd5(normalised);
43}
44
45std::vector<uint8_t> encodeEntry(const CacheEntry& entry) {
46 std::vector<uint8_t> out;
47 out.reserve(entry.data.size() + entry.contentType.size() + entry.filename.size() + 8);
48
49 Util::appendU32LE(out, static_cast<uint32_t>(entry.contentType.size()));
50 out.insert(out.end(), entry.contentType.begin(), entry.contentType.end());
51 Util::appendU32LE(out, static_cast<uint32_t>(entry.filename.size()));
52 out.insert(out.end(), entry.filename.begin(), entry.filename.end());
53 out.insert(out.end(), entry.data.begin(), entry.data.end());
54 return out;
55}
56
57/** a truncated or corrupt entry reads as a miss rather than as a bad response */
58std::optional<CacheEntry> decodeEntry(std::span<const uint8_t> raw) {
59 if (raw.size() < 4) return std::nullopt;
60
61 const auto typeSize = Util::readU32LE(raw, 0);
62 if (raw.size() < 4 + typeSize + 4) return std::nullopt;
63
64 const auto nameAt = 4 + typeSize;
65 const auto nameSize = Util::readU32LE(raw, nameAt);
66 if (raw.size() < nameAt + 4 + nameSize) return std::nullopt;
67
68 const auto dataAt = nameAt + 4 + nameSize;
69 CacheEntry entry;
70 entry.contentType.assign(raw.begin() + 4, raw.begin() + 4 + typeSize);
71 entry.filename.assign(raw.begin() + nameAt + 4, raw.begin() + nameAt + 4 + nameSize);
72 entry.data.assign(raw.begin() + dataAt, raw.end());
73 return entry;
74}
75
76}
std::optional< CacheEntry > decodeEntry(std::span< const uint8_t > raw)
Definition key.cpp:58
std::vector< uint8_t > data
std::string contentType
std::vector< uint8_t > encodeEntry(const CacheEntry &entry)
Definition key.cpp:45
std::string cacheKey(std::string_view bucket, std::string_view path, std::string_view query)
Definition key.cpp:34
uint32_t readU32LE(Bytes data, size_t off)
Definition bytes.cpp:21
void appendU32LE(std::vector< uint8_t > &out, uint32_t value)
Definition bytes.cpp:9