XRootD
XrdClHttpChecksum.hh
Go to the documentation of this file.
1 /******************************************************************************/
2 /* Copyright (C) 2025, Pelican Project, Morgridge Institute for Research */
3 /* */
4 /* This file is part of the XrdClHttp client plugin for XRootD. */
5 /* */
6 /* XRootD is free software: you can redistribute it and/or modify it under */
7 /* the terms of the GNU Lesser General Public License as published by the */
8 /* Free Software Foundation, either version 3 of the License, or (at your */
9 /* option) any later version. */
10 /* */
11 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
12 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
13 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
14 /* License for more details. */
15 /* */
16 /* The copyright holder's institutional names and contributor's names may not */
17 /* be used to endorse or promote products derived from this software without */
18 /* specific prior written permission of the institution or contributor. */
19 /******************************************************************************/
20 
21 #ifndef XRDCLHTTPCHECKSUM_HH_
22 #define XRDCLHTTPCHECKSUM_HH_
23 
24 #include <array>
25 #include <string>
26 #include <tuple>
27 
28 namespace XrdClHttp {
29 
30 constexpr size_t g_max_checksum_length = 32;
31 
32 // Checksum types known to this cache
33 enum class ChecksumType {
34  kCRC32C,
35  kMD5,
36  kSHA1,
37  kSHA256,
38  kAll, // Short-hand for setting all checksums at once.
39  kUnknown, // Indicates an unset value; `kUnknown - 1` is used in for-loops to iterate through all checksums.
40 };
41 
42 inline const std::string GetTypeString(ChecksumType ctype) {
43  switch (ctype) {
44  case ChecksumType::kCRC32C:
45  return "crc32c";
46  case ChecksumType::kMD5:
47  return "md5";
48  case ChecksumType::kSHA1:
49  return "sha1";
50  case ChecksumType::kSHA256:
51  return "sha256";
52  case ChecksumType::kAll: // fallthrough
53  case ChecksumType::kUnknown:
54  return "unknown";
55  }
56  return "unknown";
57 }
58 
59 inline size_t GetChecksumLength(ChecksumType ctype) {
60  switch (ctype) {
61  case ChecksumType::kCRC32C:
62  return 4;
63  case ChecksumType::kMD5:
64  return 16;
65  case ChecksumType::kSHA1:
66  return 20;
67  case ChecksumType::kSHA256:
68  return 32;
69  case ChecksumType::kAll: // fallthrough
70  case ChecksumType::kUnknown:
71  return 0;
72  }
73  return 0;
74 }
75 
76 inline ChecksumType GetTypeFromString(const std::string &str) {
77  if (str == "crc32c") {
78  return ChecksumType::kCRC32C;
79  } else if (str == "md5") {
80  return ChecksumType::kMD5;
81  } else if (str == "sha1") {
82  return ChecksumType::kSHA1;
83  } else if (str == "sha256") {
84  return ChecksumType::kSHA256;
85  }
86  return ChecksumType::kUnknown;
87 }
88 
89 // A single checksum type / value pair
90 // Value is stored as raw bytes in memory.
91 struct ChecksumEntry {
92  ChecksumType type{ChecksumType::kUnknown};
93  std::array<unsigned char, g_max_checksum_length> value;
94 };
95 
96 // All known checksums for a given object
97 //
98 // If the checksum is not available, then checksums[ctype].type == kUnknown.
99 // Otherwise, checksums[type].value contains the checksum and checksums[ctype].type
100 // is set to ctype for a given ctype in the ChecksumType enum.
102 public:
103 
104  // Check to see if a checksum's value is set
105  //
106  // Always returns false if kAll or kUnknown are requested.
107  bool IsSet(ChecksumType ctype) const {
108  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll)) return false;
109  return checksums[static_cast<size_t>(ctype)].type != ChecksumType::kUnknown;
110  }
111 
112  // Get the checksum value for a given checksum type
113  //
114  // If an invalid value is requested (kAll, kUnknown), then the return value is
115  // undefined (as opposed to throwing an exception).
116  //
117  // If the checksum value is not set (IsSet returns false), then the return value
118  // is undefined.
119  const std::array<unsigned char, g_max_checksum_length> &Get(ChecksumType ctype) const {
120  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll))
121  ctype = ChecksumType::kCRC32C;
122  return checksums[static_cast<size_t>(ctype)].value;
123  }
124 
125  // Set the value of the checksum for a known type.
126  //
127  // Returns true if the checksum type is valid, false otherwise (kAll, kUnknown).
128  bool Set(ChecksumType ctype, const std::array<unsigned char, g_max_checksum_length> &value) {
129  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll)) return false;
130  checksums[static_cast<size_t>(ctype)] = ChecksumEntry{ctype, value};
131  return true;
132  }
133 
134  // Returns a tuple of the type and value of the first set checksum in the object.
135  //
136  // If no value is set, then the returned type will be kUnknown.
137  std::tuple<ChecksumType, std::array<unsigned char, g_max_checksum_length>, bool> GetFirst() const {
138  for (int idx=0; idx < static_cast<int>(ChecksumType::kAll); ++idx) {
139  if (checksums[idx].type != ChecksumType::kUnknown) {
140  return std::make_tuple(static_cast<ChecksumType>(idx), checksums[idx].value, true);
141  }
142  }
143  return std::make_tuple(ChecksumType::kUnknown, std::array<unsigned char, g_max_checksum_length>(), false);
144  }
145 
146 private:
147  std::array<ChecksumEntry, static_cast<int>(ChecksumType::kAll)> checksums;
148 };
149 
150 }
151 
152 #endif // XRDCLHTTPCHECKSUM_HH_
std::tuple< ChecksumType, std::array< unsigned char, g_max_checksum_length >, bool > GetFirst() const
const std::array< unsigned char, g_max_checksum_length > & Get(ChecksumType ctype) const
bool IsSet(ChecksumType ctype) const
bool Set(ChecksumType ctype, const std::array< unsigned char, g_max_checksum_length > &value)
size_t GetChecksumLength(ChecksumType ctype)
ChecksumType GetTypeFromString(const std::string &str)
std::array< unsigned char, g_max_checksum_length > value
const std::string GetTypeString(ChecksumType ctype)
constexpr size_t g_max_checksum_length