XRootD
XrdClHttpOpChecksum.cc
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 #include "XrdClHttpOps.hh"
22 #include "XrdClHttpResponses.hh"
23 #include "XrdClHttpUtil.hh"
24 
25 #include <XrdCl/XrdClLog.hh>
27 
28 #include <iomanip>
29 #include <sstream>
30 
31 using namespace XrdClHttp;
32 
34  struct timespec timeout, XrdCl::Log *logger, bool response_info, CreateConnCalloutType callout,
35  HeaderCallout *header_callout)
36 :
37  CurlStatOp(handler, url, timeout, logger, response_info, callout, header_callout),
38  m_preferred_cksum(preferred)
39 {}
40 
41 // Override to prevent the parent CurlStatOp from switching verb to PROPFIND
42 void
44 {}
45 
46 bool
48 {
49  auto rv = CurlStatOp::Setup(curl, worker);
50  if (!rv) return false;
51 
52  curl_easy_setopt(m_curl.get(), CURLOPT_NOBODY, 1L);
53  curl_easy_setopt(m_curl.get(), CURLOPT_CUSTOMREQUEST, nullptr);
54 
55  m_headers_list.emplace_back("Want-Digest", XrdClHttp::HeaderParser::ChecksumTypeToDigestName(m_preferred_cksum));
56 
57  return true;
58 }
59 
61 CurlChecksumOp::Redirect(std::string &target)
62 {
63  auto result = CurlOperation::Redirect(target);
64  curl_easy_setopt(m_curl.get(), CURLOPT_NOBODY, 1L);
65  curl_easy_setopt(m_curl.get(), CURLOPT_CUSTOMREQUEST, nullptr);
66  return result;
67 }
68 
69 void
71 {
72  if (m_curl == nullptr) return;
73  curl_easy_setopt(m_curl.get(), CURLOPT_HTTPHEADER, nullptr);
74 
76 }
77 
78 void
80 {
81  SetDone(false);
82  auto checksums = m_headers.GetChecksums();
83 
84  std::array<unsigned char, XrdClHttp::g_max_checksum_length> value;
85  auto type = XrdClHttp::ChecksumType::kUnknown;
86  if (checksums.IsSet(m_preferred_cksum)) {
87  value = checksums.Get(m_preferred_cksum);
88  type = m_preferred_cksum;
89  } else {
90  bool isset;
91  std::tie(type, value, isset) = checksums.GetFirst();
92  if (!isset) {
93  m_logger->Error(kLogXrdClHttp, "Checksums not found in response for %s", m_url.c_str());
94  auto handle = m_handler;
95  m_handler = nullptr;
97  return;
98  }
99  }
100  std::stringstream ss;
101  for (size_t idx = 0; idx < XrdClHttp::GetChecksumLength(type); ++idx) {
102  ss << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(value[idx]);
103  }
104 
105  std::string response = XrdClHttp::GetTypeString(type) + " " + ss.str();
106  auto buf = new XrdClHttp::QueryResponse();
107  buf->FromString(response);
108  buf->SetResponseInfo(MoveResponseInfo());
109 
110  auto obj = new XrdCl::AnyObject();
111  obj->Set(static_cast<XrdCl::Buffer*>(buf));
112 
113  auto handle = m_handler;
114  m_handler = nullptr;
115  handle->HandleResponse(new XrdCl::XRootDStatus(), obj);
116  // Does not call CurlStatOp::Success() as we don't need to invoke a stat info callback
117 }
void CURL
const std::array< unsigned char, g_max_checksum_length > & Get(ChecksumType ctype) const
virtual void OptionsDone() override
RedirectAction Redirect(std::string &target) override
CurlChecksumOp(XrdCl::ResponseHandler *handler, const std::string &url, XrdClHttp::ChecksumType preferred, struct timespec timeout, XrdCl::Log *logger, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
bool Setup(CURL *curl, CurlWorker &) override
void SetDone(bool has_failed)
const std::string m_url
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
std::vector< std::pair< std::string, std::string > > m_headers_list
virtual RedirectAction Redirect(std::string &target)
XrdCl::ResponseHandler * m_handler
std::unique_ptr< ResponseInfo > MoveResponseInfo()
void ReleaseHandle() override
bool Setup(CURL *curl, CurlWorker &) override
const XrdClHttp::ChecksumInfo & GetChecksums() const
static std::string ChecksumTypeToDigestName(XrdClHttp::ChecksumType type)
Binary blob representation.
Definition: XrdClBuffer.hh:34
Handle diagnostics.
Definition: XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
Handle an async response.
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
size_t GetChecksumLength(ChecksumType ctype)
const std::string GetTypeString(ChecksumType ctype)
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
const uint16_t errCheckSumError
Definition: XrdClStatus.hh:101
ConnectionCallout *(*)(const std::string &, const ResponseInfo &) CreateConnCalloutType
const uint64_t kLogXrdClHttp