XRootD
XrdClHttpOps.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 XRDCLHTTP_CURLOPS_HH
22 #define XRDCLHTTP_CURLOPS_HH
23 
26 #include "XrdClHttpResponseInfo.hh"
27 #include "XrdClHttpTape.hh"
28 #include "XrdClHttpUtil.hh"
29 #include "XrdClHttpVerb.hh"
30 
31 #include <XrdCl/XrdClBuffer.hh>
32 #include <XrdCl/XrdClFileSystem.hh>
35 
36 #include <atomic>
37 #include <memory>
38 #include <string>
39 #include <utility>
40 #include <vector>
41 
42 #include <curl/curl.h>
43 
44 namespace XrdCl {
45 
46 class Log;
47 class ResponseHandler;
48 class URL;
49 
50 }
51 
52 class TiXmlElement;
53 
54 namespace XrdClHttp {
55 
56 class CurlWorker;
57 class File;
58 class ResponseInfo;
59 
61 public:
62  using HeaderList = std::vector<std::pair<std::string, std::string>>;
64 
65  // Operation constructor when the timeout is given as an offset from now.
66  CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
67  XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout);
68 
69 
70  // Operation constructor when the timeout is given as an absolute time.
71  CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, std::chrono::steady_clock::time_point expiry,
72  XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout);
73 
74  virtual ~CurlOperation();
75 
76  CurlOperation(const CurlOperation &) = delete;
77 
78  // Finish the setup of the curl handle
79  //
80  // Used for configuring any extra headers
81  bool FinishSetup(CURL *curl);
82 
83  virtual bool Setup(CURL *curl, CurlWorker &);
84 
85  virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &);
86 
87  virtual void ReleaseHandle();
88 
89  virtual void Success() = 0;
90 
91  // Returns the connection callout function for this operation
92  CreateConnCalloutType GetConnCalloutFunc() const {return m_conn_callout;}
93 
94  // Return the HTTP verb to use with this operation.
95  virtual HttpVerb GetVerb() const = 0;
96 
97  // Return a string version of the HTTP operation
98  static const std::string GetVerbString(HttpVerb);
99 
100  // Returns when the curl header timeout expires.
101  //
102  // The first byte of the header must be received before this time.
103  std::chrono::steady_clock::time_point GetHeaderExpiry() const {
104  return m_header_expiry.load(std::memory_order_relaxed);
105  }
106 
107  // Push the header deadline out to `timeout` from now, if that is later than
108  // the current deadline; never brings it forward.
109  //
110  // A chunked PUT is a single curl operation that spans many client writes,
111  // each carrying its own timeout. Without this, the whole upload would stay
112  // bound by the deadline derived from the very first write.
113  void ExtendDeadline(struct timespec timeout);
114 
115  // Returns when the curl operation expires
116  std::chrono::steady_clock::time_point GetOperationExpiry() {
117  if (m_last_xfer != std::chrono::steady_clock::time_point()) {
118  return m_last_xfer + m_stall_interval;
119  }
120  // Headers have arrived but no payload byte has been accounted for yet.
121  // The header deadline no longer applies (HeaderTimeoutExpired stops
122  // enforcing it at the same point), so anchor the stall clock on the
123  // last header activity instead of reviving a deadline that is moot.
124  if (m_received_header) {
125  return m_header_lastop + m_stall_interval;
126  }
127  return GetHeaderExpiry();
128  }
129 
130  // Clean up the thread-local DNS cache for fake lookups associated with the
131  // connection callback cache.
132  static void CleanupDnsCache();
133 
134  // Invoked when the worker thread is ready to resume a request after a pause.
135  //
136  // Pauses occur when a PUT request has started but is waiting on more data
137  // from the client; when additional data has arrived, the operation will
138  // be continued and this function called by the worker thread.
139  virtual bool ContinueHandle() {return true;}
140 
141  // Set the continue queue to use for when a paused handle is ready to
142  // be re-run.
143  virtual void SetContinueQueue(std::shared_ptr<XrdClHttp::HandlerQueue> queue) {}
144 
145  enum class RedirectAction {
146  Fail, // The redirect parsing failed and Fail() was called
147  Reinvoke, // Reinvoke the curl handle, following redirect
148  ReinvokeAfterAllow, // Reinvoke the Redirect function once the allowed verbs are known.
149  };
150  // Handle a redirect to a different URL.
151  // Returns Reinvoke if the curl handle should be invoked again immediately.
152  // Returns ReinvokeAfterAllow if the redirect should be invoked after the allowed verbs are known.
153  // In this case, the operation will set the target to the redirect target.
154  // Implementations must call Fail() if the handler should not re-invoke the curl handle.
155  virtual RedirectAction Redirect(std::string &target);
156 
157  // Indicate whether the result of the operation is a redirect.
158  //
159  // This relies on the response headers having been parsed and available; anything in
160  // the 30X range is considered a redirect.
161  bool IsRedirect() const {return m_headers.GetStatusCode() >= 300 && m_headers.GetStatusCode() < 400;}
162 
163  // If returns non-negative, the result is a FD that should be waited on after a broker connection request.
164  virtual int WaitSocket() {return m_conn_callout_listener;}
165  // Callback when the `WaitSocket` is active for read.
166  virtual int WaitSocketCallback(std::string &err);
167 
168  // Connection broker-related functionality.
169  // When the broker URL is set, the operation will use the connection broker to get a TCP socket
170  // to the remote server. Note that we will try the operation initially without in case the curl
171  // handle has an existing socket it can reuse. If reuse fails, then the operation is going to fail
172  // with CURLE_COULDNT_CONNECT and we will retry (once) to connect via the broker. This is all
173  // done outside curl's open socket callback to ensure the event loop stays non-blocking.
174 
175  bool StartConnectionCallout(std::string &err); // Start the connection callout process for a URL.
176  bool UseConnectionCallout() {return m_callout.get();} // Returns true if the callout should be tried.
177  bool GetTriedBoker() const {return m_tried_broker;} // Returns true if the connection broker has been tried.
178  void SetTriedBoker() {m_tried_broker = true;} // Note that the connection broker has been attempted.
179 
180  // Returns whethe the OPTIONS call needs to be made before the operation is started.
181  bool virtual RequiresOptions() const {return false;}
182 
183  // Invoked after the OPTIONS request is done and results are available
184  void virtual OptionsDone() {}
185 
186  // Returns the URL used by the current request.
187  const std::string &GetUrl() const {return m_request_url;}
188 
189  // Returns the response info for the operation
190  std::unique_ptr<ResponseInfo> GetResponseInfo();
191 
192  // Returns true if the header timeout has expired.
193  //
194  // The "header timeout" fires if the remote service has not returned any
195  // headers or data within the specified time.
196  // If the header timeout has expired - and no error has already been set -
197  // the m_error will be set
198  bool HeaderTimeoutExpired(const std::chrono::steady_clock::time_point &now);
199 
200  // Returns true if the operation timeout has expired.
201  //
202  // Some operations (HEAD, PROPFIND for open) return nearly no data and thus have
203  // no need for adaptive timeouts. Instead, we use a fixed timeout.
204  // If the header timeout has expired - and no error has already been set -
205  // the m_error will be set
206  bool OperationTimeoutExpired(const std::chrono::steady_clock::time_point &now);
207 
208  // Returns true if the body timeout has expired.
209  //
210  // The "body timeout" fires if the remote service has not returned any
211  // data within the specified time.
212  // If the body timeout has expired - and no error has already been set -
213  // the m_error will be set
214  bool TransferStalled(uint64_t xfer_bytes, const std::chrono::steady_clock::time_point &now);
215 
216  enum OpError {
217  ErrNone, // No error
218  ErrHeaderTimeout, // Header was not sent back in time
219  ErrCallback, // Error in the read/write callback (e.g., response too large for propfind)
220  ErrOperationTimeout, // Entire curl request operation has timed out
221  ErrTransferClientStall, // Transfer stalled while client had paused it (no data was available)
222  ErrTransferStall, // Transfer has stalled, not receiving any data within 60 seconds
223  ErrTransferSlow, // Average transfer rate is below the minimum
224  };
225 
226  // Return the libcurl handle owned by this operation.
227  CURL *GetCurlHandle() const {return m_curl.get();}
228 
229  // Return the error generated by the operation itself (separate from a curl error)
230  OpError GetError() const {return m_error;}
231 
232  // Move response info to the caller.
233  std::unique_ptr<ResponseInfo> MoveResponseInfo() {return std::move(m_response_info);}
234 
235  // Return the error generated by the callback (e.g., server has incorrect multipart framing)
236  std::pair<XErrorCode, std::string> GetCallbackError() const {return std::make_pair(m_callback_error_code, m_callback_error_str);}
237 
238  // Returns the HTTP status code (-1 if the response has not been parsed)
239  int GetStatusCode() const {return m_headers.GetStatusCode();}
240 
241  // Returns the HTTP status message (empty if the response has not been parsed)
242  std::string GetStatusMessage() const {return m_headers.GetStatusMessage();}
243 
244  // Return true if the transfer is done
245  bool IsDone() const {return m_done;}
246 
247  // Return true if the operation is paused in libcurl
248  bool IsPaused() const {return m_is_paused;}
249 
250  // Returns true if the operation has been marked as failed.
251  bool HasFailed() const {return m_has_failed.load(std::memory_order_acquire);}
252 
253  // Resets the statistics for the operation and returns a tuple of:
254  // - bytes transferred,
255  // - duration between operation start and header receipt.
256  // - duration between header receipt and now.
257  // - duration the operation has spent on pause in libcurl (waiting for client data)
258  // These numbers are reset to zero each time the `StatisticsReset` function is called.
259  std::tuple<uint64_t, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration> StatisticsReset();
260 
261 
262  std::string GetCurlErrorMessage() const {
263  if (m_curl_error_buffer[0] != '\0')
264  return m_curl_error_buffer;
265  return "";
266  }
267 
268  // Sets the stall timeout for the operation in seconds.
269  static void SetStallTimeout(int stall_interval)
270  {
271  std::chrono::seconds seconds{stall_interval};
272  m_stall_interval = std::chrono::duration_cast<std::chrono::steady_clock::duration>(seconds);
273  }
274 
275  // Sets the stall timeout for the operation
276  static void SetStallTimeout(const std::chrono::steady_clock::duration &stall_interval)
277  {
278  m_stall_interval = stall_interval;
279  }
280 
281  // Gets the code's default stall timeout in seconds
283  {
284  return std::chrono::duration_cast<std::chrono::seconds>(m_default_stall_interval).count();
285  }
286 
287  // Gets the code's default slow transfer rate
289  {
290  return m_default_minimum_rate;
291  }
292 
293  // Sets the slow transfer rate for transfer operations.
294  static void SetSlowRateBytesSec(int rate)
295  {
297  }
298 
299 protected:
300 
301  // Prepare the current easy handle for another HTTP request in a
302  // multi-step operation. The operation deadline and response handler are
303  // preserved while per-request curl, header, and callout state is reset.
304  bool SetupNextRequest(const std::string &url, CurlWorker &worker);
305 
306  // Update the count of bytes transferred
307  void UpdateBytes(uint64_t bytes) {m_bytes += bytes;}
308 
309  // Set failure from a callback function.
310  // The Fail() function may invoke libcurl functions and hence cannot be invoked from a
311  // libcurl callback. This stores the failure in the object itself and the worker
312  // thread will invoke the `Fail()` after libcurl fails the handle.
313  int FailCallback(XErrorCode ecode, const std::string &emsg);
314 
315  // Set the pause status
316  void SetPaused(bool paused);
317 
318  // The default minimum transfer rate for the operation, in bytes / sec
319  static constexpr int m_default_minimum_rate{1024 * 256}; // 256 KB/sec
320 
321  // The current global instance's minimum transfer rate for "transfer type"
322  // operations (GET, PUT). Defaults to the m_default_minimum_rate but can be
323  // overridden by configuration.
325 
326  // The minimum transfer rate for this operation, in bytes / sec
328 
329  // The expiration of the entire operation.
330  std::chrono::steady_clock::time_point m_operation_expiry;
331 
332  // The expiration time for receiving the first header.
333  //
334  // Atomic because ExtendDeadline() is invoked from the client thread that
335  // submits writes while the curl worker thread evaluates the deadline.
336  std::atomic<std::chrono::steady_clock::time_point> m_header_expiry;
337 
338  // Any additional headers to send with the request.
340 
341 private:
342  bool Header(const std::string &header);
343  static size_t HeaderCallback(char *buffer, size_t size, size_t nitems, void *data);
344 
345  // Information about the responses received for this operation.
346  std::unique_ptr<ResponseInfo> m_response_info;
347 
348  // The "stall time" for the body transfer.
349  // If the body transfer has not been updated in this time, the operation
350  // will be marked as expired.
351  //
352  // This is also used for the calculation of the interval of the EMA rate
353  static constexpr std::chrono::steady_clock::duration m_default_stall_interval{std::chrono::seconds(60)};
354  static std::chrono::steady_clock::duration m_stall_interval;
355 
356  OpError m_error{ErrNone};
357  XErrorCode m_callback_error_code{kXR_noErrorYet}; // Stored error that occurred in a callback.
358  std::string m_callback_error_str; // Stored error message that occurred in a callback.
359  bool m_tried_broker{false};
360  bool m_received_header{false};
361  bool m_done{false};
362  std::atomic<bool> m_has_failed{false};
363  bool m_is_paused{false};
364  int m_conn_callout_result{-1}; // The result of the connection callout
365  int m_conn_callout_listener{-1}; // The listener socket for the connection callout
366  uint64_t m_bytes{0}; // Count of bytes transferred by operation since last StatisticsReset()
367  std::chrono::steady_clock::time_point m_last_reset{}; // Time of last StatisticsReset()
368  std::chrono::steady_clock::time_point m_last_header_reset{}; // Time of last StatisticsReset() for header statistics
369  std::chrono::steady_clock::time_point m_start_op{}; // Time when the entire operation was started.
370  std::chrono::steady_clock::time_point m_header_start{}; // Time when the first header was received.
371  std::chrono::steady_clock::time_point m_pause_start{}; // Time of the last pause start/reset
372  std::chrono::steady_clock::duration m_pause_duration{}; // Accumulated pause time since last statistics update.
373 
374  // List of custom headers for the operation.
375  std::unique_ptr<struct curl_slist, void(*)(struct curl_slist *)> m_header_slist{nullptr, &curl_slist_free_all};
376 
377  // The callout class for connection creation.
378  CreateConnCalloutType m_conn_callout{nullptr};
379 
380  // The last time header data was received.
381  std::chrono::steady_clock::time_point m_header_lastop;
382 
383  // The last time data was transferred.
384  std::chrono::steady_clock::time_point m_last_xfer;
385 
386  // The last recorded number of bytes that had been transferred.
387  uint64_t m_last_xfer_count{0};
388 
389  // The exponential moving average of the transfer rate
390  double m_ema_rate{-1.0};
391 
392  // Detailed error message populated by libcurl via CURLOPT_ERRORBUFFER.
393  char m_curl_error_buffer[CURL_ERROR_SIZE]{};
394 
395  // Object representing the state of the callout for a connected socket.
396  std::unique_ptr<ConnectionCallout> m_callout;
397  std::unique_ptr<XrdCl::URL> m_parsed_url{nullptr};
398 
399  // A map of endpoints to IP addresses for the CURLOPT_CONNECT_TO option.
400  std::unique_ptr<struct curl_slist, void(*)(struct curl_slist *)> m_resolve_slist{nullptr, &curl_slist_free_all};
401 
402  static curl_socket_t OpenSocketCallback(void *clientp, curlsocktype purpose, struct curl_sockaddr *address);
403  static int SockOptCallback(void *clientp, curl_socket_t curlfd, curlsocktype purpose);
404  static curl_socket_t CloseSocketCallback(void *clientp, curl_socket_t item);
405 
406  // Periodic transfer info callback function invoked by curl; used for more fine-grained timeouts.
407  static int XferInfoCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
408 
409 protected:
410  void SetDone(bool has_failed) {m_done = true; m_has_failed.store(has_failed, std::memory_order_release);}
411  const std::string m_url;
412  // Multi-step operations retain their immutable input URL in m_url while
413  // advancing the URL used for each individual HTTP request here.
414  std::string m_request_url;
416  std::unique_ptr<CURL, void(*)(CURL *)> m_curl;
418  std::vector<std::pair<std::string, std::string>> m_headers_list;
420 };
421 
422 // Query the remote service using the OPTIONS verb.
423 //
424 // This is used to determine the capabilities of the remote service,
425 // such as whether it supports the PROPFIND verb.
426 // Note this does not take an XrdCl::ResponseHandler callback but is meant to be
427 // invoked directly by a libcurl worker which, based on the response, will use
428 // it to invoke the original operation.
429 class CurlOptionsOp final : public CurlOperation {
430 public:
431  CurlOptionsOp(CURL *curl, std::shared_ptr<CurlOperation> op, const std::string &url,
432  XrdCl::Log *log, CreateConnCalloutType callout) :
433  CurlOperation(nullptr, url, op->GetHeaderExpiry(), log, callout, {}),
434  m_parent(op),
435  m_parent_curl(curl)
436  {
438  }
439 
440  virtual ~CurlOptionsOp() {}
441 
442  bool Setup(CURL *curl, CurlWorker &) override;
443  void Success() override;
444  void Fail(uint16_t errCode, uint32_t errNum, const std::string &) override;
445  void ReleaseHandle() override;
446 
447  // Returns the parent operation that has been paused while waiting for the
448  // OPTIONS response.
449  std::shared_ptr<CurlOperation> GetOperation() const {return m_parent;}
450 
451  // Returns the parent operation's curl handle that has been paused while
452  // waiting for the OPTIONS response.
453  CURL *GetParentCurlHandle() const {return m_parent_curl;}
454 
455  virtual HttpVerb GetVerb() const override {return HttpVerb::OPTIONS;}
456 
457 private:
458  std::shared_ptr<CurlOperation> m_parent;
459  CURL *m_parent_curl{nullptr};
460 };
461 
462 // An operation representing a `stat` operation.
463 //
464 // Queries the remote service and parses out the response to a `stat` buffer.
465 // Depending on the remote service, this may be a HEAD or PROPFIND request.
466 class CurlStatOp : public CurlOperation {
467 public:
468  CurlStatOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
469  XrdCl::Log *log, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout) :
470  CurlOperation(handler, url, timeout, log, callout, header_callout),
471  m_response_info(response_info)
472  {
474  }
475 
476  virtual ~CurlStatOp() {}
477 
478  bool Setup(CURL *curl, CurlWorker &) override;
479  void Success() override;
480  RedirectAction Redirect(std::string &target) override;
481  void ReleaseHandle() override;
482 
483  bool virtual RequiresOptions() const override;
484  void virtual OptionsDone() override;
485 
486  std::pair<int64_t, bool> GetStatInfo();
487 
488  virtual HttpVerb GetVerb() const override {return m_is_propfind ? HttpVerb::PROPFIND : HttpVerb::HEAD;}
489 
490 protected:
491  // Mark the operation as a success and, as requested, return the stat info back
492  // to the object handler.
493  //
494  // Returning the info is optional as the CurlOpenOp derives from this clasa and
495  // if stat info is returned from an open without being requested then the
496  // object is leaked
497  void SuccessImpl(bool returnObj);
498 
499 private:
500  // Parse the properties element of a PROPFIND response.
501  std::pair<int64_t, bool> ParseProp(TiXmlElement *prop);
502  // Callback for writing the response body to the internal buffer.
503  static size_t WriteCallback(char *buffer, size_t size, size_t nitems, void *this_ptr);
504 
505  // Whether the response info variant of the info object should be sent
506  bool m_response_info{false};
507  // Whether the stat request is made using the PROPFIND verb.
508  bool m_is_propfind{false};
509  // Whether the stat response indicated that the object is a directory.
510  bool m_is_dir{false};
511  std::string m_response; // Body of the response (if using PROPFIND)
512  int64_t m_length{-1}; // Length of the object from the response
513 };
514 
515 class CurlOpenOp final : public CurlStatOp {
516 public:
517  CurlOpenOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
518  XrdCl::Log *logger, XrdClHttp::File *file, bool response_info, CreateConnCalloutType callout,
519  HeaderCallout *header_callout);
520 
521  virtual ~CurlOpenOp() {}
522 
523  void ReleaseHandle() override;
524  void Success() override;
525 
526  // Invoked to handle a failure-to-open (HEAD returns non-200)
527  //
528  // If the open operation is invoked for a file with the `New` flag set, this
529  // may be a success if the remote server returned a 404.
530  void Fail(uint16_t errCode, uint32_t errNum, const std::string &) override;
531 
532 private:
533  // Set various common properties after an open has completed.
534  //
535  // If `setSize` is set, then we'll set the file size as a file property.
536  // This is made optional because the open operation may succeed after a 404
537  // (if this was invoked by an open with O_CREAT set); in such a case, setting
538  // the size is nonsensical because the file doesn't exist.
539  void SetOpenProperties(bool setSize);
540 
541  XrdClHttp::File *m_file{nullptr};
542 };
543 
544 // Query the origin for a checksum via a HEAD request.
545 //
546 // Since the open op is a PROPFIND, we need a second operation for checksums.
547 // We expect the checksum only is done after a successful transfer.
548 class CurlChecksumOp final : public CurlStatOp {
549  public:
550  CurlChecksumOp(XrdCl::ResponseHandler *handler, const std::string &url, XrdClHttp::ChecksumType preferred,
551  struct timespec timeout, XrdCl::Log *logger,
552  bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout);
553 
554  virtual ~CurlChecksumOp() {}
555 
556  virtual HttpVerb GetVerb() const override {return HttpVerb::HEAD;}
557  virtual void OptionsDone() override;
558  bool Setup(CURL *curl, CurlWorker &) override;
559  void Success() override;
560  RedirectAction Redirect(std::string &target) override;
561  void ReleaseHandle() override;
562 
563  private:
564  XrdClHttp::ChecksumType m_preferred_cksum{XrdClHttp::ChecksumType::kAll};
565  XrdClHttp::File *m_file{nullptr};
566  };
567 
568 // Operation issuing a DELETE request to the remote server.
569 //
570 class CurlDeleteOp final : public CurlOperation {
571 public:
572  CurlDeleteOp(XrdCl::ResponseHandler *handler, const std::string &url,
573  struct timespec timeout, XrdCl::Log *logger,
574  bool response_info, CreateConnCalloutType callout,
575  HeaderCallout *header_callout);
576 
577  virtual ~CurlDeleteOp();
578 
579  bool Setup(CURL *curl, CurlWorker &) override;
580  void Success() override;
581  void ReleaseHandle() override;
582 
583  virtual HttpVerb GetVerb() const override {return HttpVerb::DELETE;}
584 
585 private:
586  bool m_response_info{false}; // Indicate whether to give extended information in the response.
587 };
588 
589 // Operation issuing a MKCOL request to the remote server.
590 //
591 // Creates a "directory" on the remote side
592 //
593 class CurlMkcolOp final : public CurlOperation {
594 public:
595 CurlMkcolOp(XrdCl::ResponseHandler *handler, const std::string &url,
596  struct timespec timeout, XrdCl::Log *logger,
597  bool response_info, CreateConnCalloutType callout,
598  HeaderCallout *header_callout);
599 
600  virtual ~CurlMkcolOp();
601 
602  void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override;
603  void ReleaseHandle() override;
604  bool Setup(CURL *curl, CurlWorker &) override;
605  void Success() override;
606 
607  virtual HttpVerb GetVerb() const override {return HttpVerb::MKCOL;}
608 
609 private:
610  bool m_response_info{false}; // Indicate whether to give extended information in the response.
611 };
612 
613 // Cache control query
614 //
615 class CurlQueryOp final : public CurlStatOp {
616 public:
617  CurlQueryOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
618  XrdCl::Log *log, bool response_info, CreateConnCalloutType callout, int queryCode, HeaderCallout *header_callout) :
619  CurlStatOp(handler, url, timeout, log, response_info, callout, header_callout),
620  m_queryCode(queryCode)
621  {
622  }
623 
624  virtual ~CurlQueryOp() {}
625 
626  void Success() override;
627 
629  std::string m_queryVal;
630 };
631 
632 class CurlTapeOp : public CurlOperation {
633 public:
634  ~CurlTapeOp() override;
635 
636  bool Setup(CURL *curl, CurlWorker &worker) override;
637  void Fail(uint16_t errCode, uint32_t errNum,
638  const std::string &message) override;
639  void ReleaseHandle() override;
640  void Success() override;
641 
642  HttpVerb GetVerb() const override;
643 
644 protected:
645  CurlTapeOp(XrdCl::ResponseHandler *handler, const std::string &url,
646  std::unique_ptr<TapeOperation> tape, struct timespec timeout,
647  XrdCl::Log *logger, CreateConnCalloutType callout,
648  HeaderCallout *header_callout);
649 
650 private:
651  bool ConfigureRequest();
652  void Complete(const std::string &response);
653  std::string RequestDescription() const;
654  static size_t WriteCallback(char *buffer, size_t size, size_t nitems,
655  void *data);
656  size_t Write(char *buffer, size_t size);
657 
658  std::unique_ptr<TapeOperation> m_tape;
659  TapeHttpRequest m_request;
660  CurlWorker *m_worker{nullptr};
661  std::string m_response;
662 };
663 
664 class CurlTapePrepareOp final : public CurlTapeOp {
665 public:
666  CurlTapePrepareOp(XrdCl::ResponseHandler *handler, const std::string &url,
667  const std::vector<std::string> &file_list,
668  XrdCl::PrepareFlags::Flags flags, struct timespec timeout,
669  XrdCl::Log *logger, CreateConnCalloutType callout,
670  HeaderCallout *header_callout);
671 };
672 
673 class CurlTapeQueryOp final : public CurlTapeOp {
674 public:
675  CurlTapeQueryOp(XrdCl::ResponseHandler *handler, const std::string &url,
676  XrdCl::QueryCode::Code query_code, const XrdCl::Buffer &arg,
677  struct timespec timeout, XrdCl::Log *logger,
678  CreateConnCalloutType callout, HeaderCallout *header_callout);
679 };
680 
681 class CurlReadOp : public CurlOperation {
682 public:
683  CurlReadOp(XrdCl::ResponseHandler *handler, std::shared_ptr<XrdCl::ResponseHandler> default_handler,
684  const std::string &url, struct timespec timeout, const std::pair<uint64_t, uint64_t> &op,
685  char *buffer, size_t sz, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout);
686 
687  virtual ~CurlReadOp() {}
688 
689  // Start continuation of a previously-started operation with additional data.
690  bool Continue(std::shared_ptr<CurlOperation> op, XrdCl::ResponseHandler *handler, char *buffer, size_t buffer_size);
691 
692  // Make state changes necessary to the curl handle for it to unpause.
693  bool ContinueHandle() override;
694 
695  // Pause the GET operation; indicates the current buffer was sent successfully
696  // but the operation is not yet complete. Will invoke the current callback.
697  virtual void Pause();
698 
699  bool Setup(CURL *curl, CurlWorker &) override;
700  void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override;
701  void Success() override;
702  void ReleaseHandle() override;
703 
704  virtual void SetContinueQueue(std::shared_ptr<XrdClHttp::HandlerQueue> queue) override {
705  m_continue_queue = queue;
706  }
707 
708  virtual HttpVerb GetVerb() const override {return HttpVerb::GET;}
709 
710 
711 private:
712  // Deliver the current buffer to the response handler and reset internal buffer state.
713  void DeliverResponse();
714 
715  static size_t WriteCallback(char *buffer, size_t size, size_t nitems, void *this_ptr);
716  size_t Write(char *buffer, size_t size);
717 
718  // Extra response data from curl that overflowed the last buffer
719  //
720  // libcurl's callback is "all or nothing": you cannot accept part of a buffer
721  // then pause the operation until the user provides a new buffer. Hence, we keep
722  // this as the "overflow" buffer; next time Continue() is called, we will process
723  // this data first.
724  std::string m_prefetch_buffer;
725 
726  // Offset into m_prefetch_buffer pointing at the first byte of unconsumed data.
727  size_t m_prefetch_buffer_offset{0};
728 
729  // Offset into the object, for the current Continue() call, relative to m_op.first
730  off_t m_prefetch_object_offset{0};
731 
732  // Default callback handler; used when the HTTP operation times out while there
733  // is no ongoing CurlFile read operation.
734  std::shared_ptr<XrdCl::ResponseHandler> m_default_handler;
735 
736 protected:
737  std::pair<uint64_t, uint64_t> m_op;
738  uint64_t m_written{0}; // Bytes written into the current client-provided buffer
739  char *m_buffer{nullptr}; // Buffer passed by XrdCl; we do not own it.
740  size_t m_buffer_size{0}; // Size of the provided buffer
741 
742  // When the read fails, the body of the response will be copied
743  // here instead of invoking the callback.
744  std::string m_err_msg;
745 
746  // Reference to the continue queue to use when the operation should be resumed.
747  std::shared_ptr<XrdClHttp::HandlerQueue> m_continue_queue;
748 };
749 
750 // Open operation that is actually an entire-object GET
752 public:
753  CurlPrefetchOpenOp(XrdClHttp::File &file, XrdCl::ResponseHandler *handler, std::shared_ptr<XrdCl::ResponseHandler> default_handler,
754  const std::string &url, struct timespec timeout, const std::pair<uint64_t, uint64_t> &op,
755  char *buffer, size_t sz, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
756  : CurlReadOp(handler, default_handler, url, timeout, op, buffer, sz, logger, callout, header_callout), m_file(file)
757  {}
758 
759  // Special handling of the first "Pause" operation after the read
760  // has started. Do the correct invocation of success or failure.
761  virtual void Pause() override;
762 
763 private:
764  bool m_first_pause{true};
765  XrdClHttp::File &m_file;
766 };
767 
769  public:
770 
771  CurlVectorReadOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout,
772  const XrdCl::ChunkList &op_list, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout);
773 
774  virtual ~CurlVectorReadOp() {}
775 
776  bool Setup(CURL *curl, CurlWorker &) override;
777  void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override;
778  void Success() override;
779  void ReleaseHandle() override;
780 
781  // Set the expected separator between parts of a response;
782  // not expected to be used externally except by unit tests.
783  void SetSeparator(const std::string &sep) {
785  }
786 
787  // Set the status code for the operation
789 
790  // Invoke the write callback for the vector read.
791  //
792  // Note: made public to help unit testing of the class; not intended for direct invocation.
793  size_t Write(char *buffer, size_t size);
794 
795  virtual HttpVerb GetVerb() const override {return HttpVerb::GET;}
796 
797  private:
798  static size_t WriteCallback(char *buffer, size_t size, size_t nitems, void *this_ptr);
799 
800  // Calculate the next request buffer the current response buffer will service.
801  // Sets the m_response_idx and m_skip_bytes
802  void CalculateNextBuffer();
803 
804  bool m_multipart_boundary {true}; //
805 
806  protected:
807  size_t m_response_idx{0}; // The offset in the m_chunk_list which the current response chunk will write into.
808  off_t m_chunk_buffer_idx{0}; // Current offset in requested chunk where we are writing bytes.
809  off_t m_bytes_consumed{0}; // Total number of bytes used for results serving the request.
810  uint64_t m_skip_bytes{0}; // Count of bytes to skip in the next response (if response chunk contains unneeded bytes).
811  std::string m_response_headers; // Buffer of an incomplete response line from a prior curl write operation.
812  std::string m_header_line; // Storage for the last complete header line returned by get_next_line.
813  std::pair<off_t, off_t> m_current_op{-1, -1}; // The (offset, length) of the current response chunk.
814  std::unique_ptr<XrdCl::VectorReadInfo> m_vr; // The response buffers for the client.
815  XrdCl::ChunkList m_chunk_list; // The requested chunks from the client.
816 };
817 
818 class CurlPgReadOp final : public CurlReadOp {
819 public:
820  CurlPgReadOp(XrdCl::ResponseHandler *handler, std::shared_ptr<XrdCl::ResponseHandler> default_handler,
821  const std::string &url, struct timespec timeout, const std::pair<uint64_t, uint64_t> &op,
822  char *buffer, size_t buffer_size, XrdCl::Log *logger, CreateConnCalloutType callout,
823  HeaderCallout *header_callout)
824  :
825  CurlReadOp(handler, default_handler, url, timeout, op, buffer, buffer_size, logger, callout, header_callout)
826  {}
827 
828  virtual ~CurlPgReadOp() {}
829 
830  void Success() override;
831 
832  virtual HttpVerb GetVerb() const override {return HttpVerb::GET;}
833 
834 };
835 
836 class CurlListdirOp final : public CurlOperation {
837 public:
838  CurlListdirOp(XrdCl::ResponseHandler *handler, const std::string &url, const std::string &host_addr, bool response_info,
839  struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout);
840 
841  virtual ~CurlListdirOp() {}
842 
843  bool Setup(CURL *curl, CurlWorker &) override;
844  void Success() override;
845  void ReleaseHandle() override;
846 
847  virtual HttpVerb GetVerb() const override {return HttpVerb::PROPFIND;}
848 
849 private:
850  struct DavEntry {
851  std::string m_name;
852  bool m_isdir{false};
853  bool m_isexec{false};
854  int64_t m_size{-1};
855  time_t m_lastmodified{-1};
856  };
857  // Parses the properties element of a PROPFIND response into a DavEntry object
858  //
859  // - prop: The properties element to parse
860  // - Returns: A pair containing the DavEntry object and a boolean indicating success or not
861  bool ParseProp(DavEntry &entry, TiXmlElement *prop);
862 
863  // Indicate whether the operation should use the extended "response info" object in response
864  const bool m_response_info{false};
865 
866  // Parses the response element of a PROPFIND
867  std::pair<DavEntry, bool> ParseResponse(TiXmlElement *response);
868 
869  // Callback for writing the response body to the internal buffer.
870  static size_t WriteCallback(char *buffer, size_t size, size_t nitems, void *this_ptr);
871 
872  // Whether the provided URL is an origin URL (and hence PROPFIND can be done directly).
873  bool m_is_origin{false};
874 
875  // Response body from the PROPFIND request.
876  std::string m_response;
877 
878  // Host address (hostname:port) of the data federation
879  std::string m_host_addr;
880 };
881 
882 // The side of a third-party-copy which the client drives.
883 //
884 // In pull mode the client sends the COPY to the destination and the
885 // destination reads from the source. In push mode the client sends the COPY to
886 // the source and the source writes to the destination.
887 enum class TpcMode {
888  Pull,
889  Push
890 };
891 
892 // A third-party-copy operation
893 //
894 // Invoke the COPY verb to move a file between two HTTP endpoints.
895 class CurlCopyOp final : public CurlOperation {
896 public:
897  using Headers = std::vector<std::pair<std::string, std::string>>;
898 
899  CurlCopyOp(XrdCl::ResponseHandler *handler, const std::string &source_url, const Headers &source_hdrs, const std::string &dest_url, const Headers &dest_hdrs, const Headers &connection_hdrs, TpcMode mode, struct timespec timeout,
900  XrdCl::Log *logger, CreateConnCalloutType callout);
901 
902  virtual ~CurlCopyOp() {}
903 
904  bool Setup(CURL *curl, CurlWorker &) override;
905  void Success() override;
906  void ReleaseHandle() override;
907 
908  // Set the handler notified when a performance marker is received.
909  //
910  // The handler is not owned by this operation and must outlive it. Give
911  // nullptr to send no notification.
912  void SetProgressHandler(XrdCl::ProgressHandler *handler) noexcept;
913 
914  virtual HttpVerb GetVerb() const override {return HttpVerb::COPY;}
915 
916  bool IsSentSuccessfully() {return m_sent_success;}
917  std::string GetSendingFailureMessage() {return m_failure;}
918 
919 private:
920  // Callback for writing the response body to the internal buffer.
921  static size_t WriteCallback(char *buffer, size_t size, size_t nitems, void *this_ptr);
922 
923  // Handle a line of information in the control channel.
924  void HandleLine(std::string_view line);
925 
926  // Returns true if the control channel has not gotten data recently enough.
927  bool ControlChannelTimeoutExpired() const;
928 
929  // Buffer of current response line
930  std::string m_line_buffer;
931 
932  // Handler notified when a performance marker is received; not owned.
933  XrdCl::ProgressHandler *m_progress_handler{nullptr};
934 
935  // The performance marker indication of bytes processed.
936  off_t m_bytemark{-1};
937 
938  // Whether the COPY operation indicated a success status in the control channel:
939  bool m_sent_success{false};
940 
941  // Failure string sent back in the control channel:
942  std::string m_failure;
943 };
944 
945 // An upload operation
946 //
947 // Invoke a PUT on the remote HTTP server; assumes that Writes are done
948 // in a single-stream
949 class CurlPutOp final : public CurlOperation {
950 public:
951  CurlPutOp(XrdCl::ResponseHandler *handler, std::shared_ptr<XrdCl::ResponseHandler> default_handler,
952  const std::string &url, const char *buffer, size_t buffer_size,
953  struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout,
954  HeaderCallout *header_callout);
955  CurlPutOp(XrdCl::ResponseHandler *handler, std::shared_ptr<XrdCl::ResponseHandler> default_handler,
956  const std::string &url, XrdCl::Buffer &&buffer,
957  struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout,
958  HeaderCallout *header_callout);
959 
960  virtual ~CurlPutOp() {}
961 
962  void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override;
963  bool Setup(CURL *curl, CurlWorker &) override;
964  void Success() override;
965  void ReleaseHandle() override;
966  bool ContinueHandle() override;
967 
968  virtual void SetContinueQueue(std::shared_ptr<XrdClHttp::HandlerQueue> queue) override {
969  m_continue_queue = queue;
970  }
971 
972  // Start continuation of a previously-started operation with additional data.
973  //
974  // Since the CurlPutOp itself is kept as a reference-counted pointer by the
975  // XrdClHttp::File handle, we need to pass a shared pointer to the continue queue.
976  // Hence the awkward interface of needing to be provided a shared pointer to oneself.
977  bool Continue(std::shared_ptr<CurlOperation> op, XrdCl::ResponseHandler *handler, const char *buffer, size_t buffer_size);
978  bool Continue(std::shared_ptr<CurlOperation> op, XrdCl::ResponseHandler *handler, XrdCl::Buffer &&buffer);
979 
980  // Pause the put operation; indicates the current buffer was sent successfully
981  // but the operation is not yet complete.
982  void Pause();
983 
984  virtual HttpVerb GetVerb() const override {return HttpVerb::PUT;}
985 
986 private:
987 
988  // Callback function for libcurl when it would like to read data from m_data
989  // (and write it to the remote socket).
990  static size_t ReadCallback(char *buffer, size_t size, size_t n, void *v);
991 
992  // Handle that represents the current operation to libcurl
993  CURL *m_curl_handle{nullptr};
994 
995  // Reference to the continue queue to use when the operation should be resumed.
996  std::shared_ptr<XrdClHttp::HandlerQueue> m_continue_queue;
997 
998  // The buffer of data to upload (if the CurlPutOp owns the buffer).
999  XrdCl::Buffer m_owned_buffer;
1000 
1001  // The non-owned view of the data to upload.
1002  // This may reference m_owned_buffer or an externally-owned `const char *`.
1003  std::string_view m_data;
1004 
1005  // The default handler to invoke if an File::Write operation is not pending.
1006  // Typically used for timeouts/errors on the PUT operation between client
1007  // writes.
1008  std::shared_ptr<XrdCl::ResponseHandler> m_default_handler;
1009 
1010  // File pointer offset
1011  off_t m_offset{0};
1012 
1013  // The final size of the object to be uploaded; -1 if not known
1014  off_t m_object_size{-1};
1015 
1016  bool m_final{false};
1017 };
1018 
1019 } // namespace XrdClHttp
1020 
1021 #endif // XRDCLHTTP_CURLOPS_HH
XErrorCode
Definition: XProtocol.hh:1031
@ kXR_noErrorYet
Definition: XProtocol.hh:1069
void CURL
XrdOucString File
int emsg(int rc, char *msg)
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)
virtual HttpVerb GetVerb() const override
bool Setup(CURL *curl, CurlWorker &) override
void Success() override
virtual HttpVerb GetVerb() const override
void ReleaseHandle() override
std::vector< std::pair< std::string, std::string > > Headers
std::string GetSendingFailureMessage()
void SetProgressHandler(XrdCl::ProgressHandler *handler) noexcept
bool Setup(CURL *curl, CurlWorker &) override
CurlCopyOp(XrdCl::ResponseHandler *handler, const std::string &source_url, const Headers &source_hdrs, const std::string &dest_url, const Headers &dest_hdrs, const Headers &connection_hdrs, TpcMode mode, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout)
bool Setup(CURL *curl, CurlWorker &) override
CurlDeleteOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *logger, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
void ReleaseHandle() override
virtual HttpVerb GetVerb() const override
bool Setup(CURL *curl, CurlWorker &) override
CurlListdirOp(XrdCl::ResponseHandler *handler, const std::string &url, const std::string &host_addr, bool response_info, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
virtual HttpVerb GetVerb() const override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override
bool Setup(CURL *curl, CurlWorker &) override
virtual HttpVerb GetVerb() const override
void ReleaseHandle() override
CurlMkcolOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *logger, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
void ReleaseHandle() override
void Success() override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &) override
CurlOpenOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *logger, XrdClHttp::File *file, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
virtual void Success()=0
virtual void OptionsDone()
void SetDone(bool has_failed)
static void SetStallTimeout(const std::chrono::steady_clock::duration &stall_interval)
int FailCallback(XErrorCode ecode, const std::string &emsg)
CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)
static int m_minimum_transfer_rate
std::chrono::steady_clock::time_point GetHeaderExpiry() const
bool FinishSetup(CURL *curl)
std::atomic< std::chrono::steady_clock::time_point > m_header_expiry
std::vector< std::pair< std::string, std::string > > HeaderList
Definition: XrdClHttpOps.hh:62
const std::string m_url
const std::string & GetUrl() const
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
std::pair< XErrorCode, std::string > GetCallbackError() const
bool TransferStalled(uint64_t xfer_bytes, const std::chrono::steady_clock::time_point &now)
virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &)
static const std::string GetVerbString(HttpVerb)
virtual HttpVerb GetVerb() const =0
std::string GetCurlErrorMessage() const
virtual void ReleaseHandle()
void UpdateBytes(uint64_t bytes)
virtual bool RequiresOptions() const
static void CleanupDnsCache()
std::chrono::steady_clock::time_point GetOperationExpiry()
std::tuple< uint64_t, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration, std::chrono::steady_clock::duration > StatisticsReset()
virtual bool ContinueHandle()
std::string GetStatusMessage() const
bool SetupNextRequest(const std::string &url, CurlWorker &worker)
CURL * GetCurlHandle() const
static constexpr int m_default_minimum_rate
static void SetSlowRateBytesSec(int rate)
static void SetStallTimeout(int stall_interval)
CreateConnCalloutType GetConnCalloutFunc() const
Definition: XrdClHttpOps.hh:92
OpError GetError() const
std::vector< std::pair< std::string, std::string > > m_headers_list
HeaderCallout * m_header_callout
static int GetDefaultSlowRateBytesSec()
bool HeaderTimeoutExpired(const std::chrono::steady_clock::time_point &now)
virtual int WaitSocketCallback(std::string &err)
void ExtendDeadline(struct timespec timeout)
XrdClHttp::HttpVerb HttpVerb
Definition: XrdClHttpOps.hh:63
std::chrono::steady_clock::time_point m_operation_expiry
CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, std::chrono::steady_clock::time_point expiry, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)
virtual RedirectAction Redirect(std::string &target)
XrdCl::ResponseHandler * m_handler
std::unique_ptr< ResponseInfo > MoveResponseInfo()
static int GetDefaultStallTimeout()
void SetPaused(bool paused)
virtual void SetContinueQueue(std::shared_ptr< XrdClHttp::HandlerQueue > queue)
bool StartConnectionCallout(std::string &err)
std::unique_ptr< ResponseInfo > GetResponseInfo()
bool OperationTimeoutExpired(const std::chrono::steady_clock::time_point &now)
CurlOperation(const CurlOperation &)=delete
virtual bool Setup(CURL *curl, CurlWorker &)
CURL * GetParentCurlHandle() const
CurlOptionsOp(CURL *curl, std::shared_ptr< CurlOperation > op, const std::string &url, XrdCl::Log *log, CreateConnCalloutType callout)
virtual HttpVerb GetVerb() const override
std::shared_ptr< CurlOperation > GetOperation() const
bool Setup(CURL *curl, CurlWorker &) override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &) override
virtual HttpVerb GetVerb() const override
CurlPgReadOp(XrdCl::ResponseHandler *handler, std::shared_ptr< XrdCl::ResponseHandler > default_handler, const std::string &url, struct timespec timeout, const std::pair< uint64_t, uint64_t > &op, char *buffer, size_t buffer_size, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
CurlPrefetchOpenOp(XrdClHttp::File &file, XrdCl::ResponseHandler *handler, std::shared_ptr< XrdCl::ResponseHandler > default_handler, const std::string &url, struct timespec timeout, const std::pair< uint64_t, uint64_t > &op, char *buffer, size_t sz, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
virtual void Pause() override
bool ContinueHandle() override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override
bool Setup(CURL *curl, CurlWorker &) override
bool Continue(std::shared_ptr< CurlOperation > op, XrdCl::ResponseHandler *handler, const char *buffer, size_t buffer_size)
virtual HttpVerb GetVerb() const override
virtual void SetContinueQueue(std::shared_ptr< XrdClHttp::HandlerQueue > queue) override
CurlPutOp(XrdCl::ResponseHandler *handler, std::shared_ptr< XrdCl::ResponseHandler > default_handler, const std::string &url, const char *buffer, size_t buffer_size, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
void Success() override
void ReleaseHandle() override
CurlQueryOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, bool response_info, CreateConnCalloutType callout, int queryCode, HeaderCallout *header_callout)
void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override
std::pair< uint64_t, uint64_t > m_op
void Success() override
bool Setup(CURL *curl, CurlWorker &) override
std::shared_ptr< XrdClHttp::HandlerQueue > m_continue_queue
bool ContinueHandle() override
CurlReadOp(XrdCl::ResponseHandler *handler, std::shared_ptr< XrdCl::ResponseHandler > default_handler, const std::string &url, struct timespec timeout, const std::pair< uint64_t, uint64_t > &op, char *buffer, size_t sz, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
virtual void SetContinueQueue(std::shared_ptr< XrdClHttp::HandlerQueue > queue) override
virtual HttpVerb GetVerb() const override
bool Continue(std::shared_ptr< CurlOperation > op, XrdCl::ResponseHandler *handler, char *buffer, size_t buffer_size)
void ReleaseHandle() override
void ReleaseHandle() override
void SuccessImpl(bool returnObj)
virtual bool RequiresOptions() const override
bool Setup(CURL *curl, CurlWorker &) override
RedirectAction Redirect(std::string &target) override
std::pair< int64_t, bool > GetStatInfo()
CurlStatOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, bool response_info, CreateConnCalloutType callout, HeaderCallout *header_callout)
virtual HttpVerb GetVerb() const override
virtual void OptionsDone() override
void Success() override
void Success() override
HttpVerb GetVerb() const override
bool Setup(CURL *curl, CurlWorker &worker) override
CurlTapeOp(XrdCl::ResponseHandler *handler, const std::string &url, std::unique_ptr< TapeOperation > tape, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
void Fail(uint16_t errCode, uint32_t errNum, const std::string &message) override
void ReleaseHandle() override
CurlTapePrepareOp(XrdCl::ResponseHandler *handler, const std::string &url, const std::vector< std::string > &file_list, XrdCl::PrepareFlags::Flags flags, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
CurlTapeQueryOp(XrdCl::ResponseHandler *handler, const std::string &url, XrdCl::QueryCode::Code query_code, const XrdCl::Buffer &arg, struct timespec timeout, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
size_t Write(char *buffer, size_t size)
CurlVectorReadOp(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, const XrdCl::ChunkList &op_list, XrdCl::Log *logger, CreateConnCalloutType callout, HeaderCallout *header_callout)
void SetSeparator(const std::string &sep)
XrdCl::ChunkList m_chunk_list
virtual HttpVerb GetVerb() const override
std::pair< off_t, off_t > m_current_op
std::unique_ptr< XrdCl::VectorReadInfo > m_vr
bool Setup(CURL *curl, CurlWorker &) override
void Fail(uint16_t errCode, uint32_t errNum, const std::string &msg) override
void SetMultipartSeparator(const std::string_view &sep)
std::string GetStatusMessage() const
Binary blob representation.
Definition: XrdClBuffer.hh:34
Handle diagnostics.
Definition: XrdClLog.hh:101
Handle the progress of an asynchronous operation.
Handle an async response.
std::vector< ChunkInfo > ChunkList
List of chunks.
XrdSysError Log
Definition: XrdConfig.cc:113
ConnectionCallout *(*)(const std::string &, const ResponseInfo &) CreateConnCalloutType
Code
XRootD query request codes.