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  kADLER32,
35  kCRC32,
36  kCRC32C,
37  kMD5,
38  kSHA1,
39  kSHA256,
40  kAll, // Select any supported checksum.
41  kUnknown, // Indicates an unset value; `kUnknown - 1` is used in for-loops to iterate through all checksums.
42 };
43 
44 inline const std::string GetTypeString(ChecksumType ctype) {
45  switch (ctype) {
46  case ChecksumType::kADLER32:
47  return "adler32";
48  case ChecksumType::kCRC32:
49  return "crc32";
50  case ChecksumType::kCRC32C:
51  return "crc32c";
52  case ChecksumType::kMD5:
53  return "md5";
54  case ChecksumType::kSHA1:
55  return "sha1";
56  case ChecksumType::kSHA256:
57  return "sha256";
58  case ChecksumType::kAll: // fallthrough
59  case ChecksumType::kUnknown:
60  return "unknown";
61  }
62  return "unknown";
63 }
64 
65 inline size_t GetChecksumLength(ChecksumType ctype) {
66  switch (ctype) {
67  case ChecksumType::kADLER32:
68  case ChecksumType::kCRC32:
69  case ChecksumType::kCRC32C:
70  return 4;
71  case ChecksumType::kMD5:
72  return 16;
73  case ChecksumType::kSHA1:
74  return 20;
75  case ChecksumType::kSHA256:
76  return 32;
77  case ChecksumType::kAll: // fallthrough
78  case ChecksumType::kUnknown:
79  return 0;
80  }
81  return 0;
82 }
83 
84 inline ChecksumType GetTypeFromString(const std::string &str) {
85  if (str == "adler" || str == "adler32") {
86  return ChecksumType::kADLER32;
87  } else if (str == "crc32") {
88  return ChecksumType::kCRC32;
89  } else if (str == "crc32c") {
90  return ChecksumType::kCRC32C;
91  } else if (str == "md5") {
92  return ChecksumType::kMD5;
93  } else if (str == "sha1") {
94  return ChecksumType::kSHA1;
95  } else if (str == "sha256") {
96  return ChecksumType::kSHA256;
97  }
98  return ChecksumType::kUnknown;
99 }
100 
101 // A single checksum type / value pair
102 // Value is stored as raw bytes in memory.
104  ChecksumType type{ChecksumType::kUnknown};
105  std::array<unsigned char, g_max_checksum_length> value;
106 };
107 
108 // All known checksums for a given object
109 //
110 // If the checksum is not available, then checksums[ctype].type == kUnknown.
111 // Otherwise, checksums[type].value contains the checksum and checksums[ctype].type
112 // is set to ctype for a given ctype in the ChecksumType enum.
114 public:
115 
116  // Check to see if a checksum's value is set
117  //
118  // Always returns false if kAll or kUnknown are requested.
119  bool IsSet(ChecksumType ctype) const {
120  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll)) return false;
121  return checksums[static_cast<size_t>(ctype)].type != ChecksumType::kUnknown;
122  }
123 
124  // Get the checksum value for a given checksum type
125  //
126  // If an invalid value is requested (kAll, kUnknown), then the return value is
127  // undefined (as opposed to throwing an exception).
128  //
129  // If the checksum value is not set (IsSet returns false), then the return value
130  // is undefined.
131  const std::array<unsigned char, g_max_checksum_length> &Get(ChecksumType ctype) const {
132  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll))
133  ctype = ChecksumType::kCRC32C;
134  return checksums[static_cast<size_t>(ctype)].value;
135  }
136 
137  // Set the value of the checksum for a known type.
138  //
139  // Returns true if the checksum type is valid, false otherwise (kAll, kUnknown).
140  bool Set(ChecksumType ctype, const std::array<unsigned char, g_max_checksum_length> &value) {
141  if ((ctype == ChecksumType::kUnknown) || (ctype == ChecksumType::kAll)) return false;
142  checksums[static_cast<size_t>(ctype)] = ChecksumEntry{ctype, value};
143  return true;
144  }
145 
146  // Returns a tuple of the type and value of the first set checksum in the object.
147  //
148  // If no value is set, then the returned type will be kUnknown.
149  std::tuple<ChecksumType, std::array<unsigned char, g_max_checksum_length>, bool> GetFirst() const {
150  for (int idx=0; idx < static_cast<int>(ChecksumType::kAll); ++idx) {
151  if (checksums[idx].type != ChecksumType::kUnknown) {
152  return std::make_tuple(static_cast<ChecksumType>(idx), checksums[idx].value, true);
153  }
154  }
155  return std::make_tuple(ChecksumType::kUnknown, std::array<unsigned char, g_max_checksum_length>(), false);
156  }
157 
158 private:
159  std::array<ChecksumEntry, static_cast<int>(ChecksumType::kAll)> checksums;
160 };
161 
162 }
163 
164 #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