XRootD
Loading...
Searching...
No Matches
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
27#include "XrdClHttpTape.hh"
28#include "XrdClHttpUtil.hh"
29#include "XrdClHttpVerb.hh"
30
31#include <XrdCl/XrdClBuffer.hh>
35
36#include <atomic>
37#include <memory>
38#include <string>
39#include <utility>
40#include <vector>
41
42#include <curl/curl.h>
43
44namespace XrdCl {
45
46class Log;
47class ResponseHandler;
48class URL;
49
50}
51
52class TiXmlElement;
53
54namespace XrdClHttp {
55
56class CurlWorker;
57class File;
58class ResponseInfo;
59
61public:
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 {
291 }
292
293 // Sets the slow transfer rate for transfer operations.
294 static void SetSlowRateBytesSec(int rate)
295 {
297 }
298
299protected:
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
341private:
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
409protected:
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.
429class CurlOptionsOp final : public CurlOperation {
430public:
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
457private:
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.
466class CurlStatOp : public CurlOperation {
467public:
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
490protected:
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
499private:
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
515class CurlOpenOp final : public CurlStatOp {
516public:
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
532private:
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.
548class 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:
565 XrdClHttp::File *m_file{nullptr};
566 };
567
568// Operation issuing a DELETE request to the remote server.
569//
570class CurlDeleteOp final : public CurlOperation {
571public:
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
585private:
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//
593class CurlMkcolOp final : public CurlOperation {
594public:
595CurlMkcolOp(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
609private:
610 bool m_response_info{false}; // Indicate whether to give extended information in the response.
611};
612
613// Cache control query
614//
615class CurlQueryOp final : public CurlStatOp {
616public:
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
632class CurlTapeOp : public CurlOperation {
633public:
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
644protected:
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
650private:
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
664class CurlTapePrepareOp final : public CurlTapeOp {
665public:
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
673class CurlTapeQueryOp final : public CurlTapeOp {
674public:
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
681class CurlReadOp : public CurlOperation {
682public:
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
711private:
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
736protected:
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
752public:
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
763private:
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
818class CurlPgReadOp final : public CurlReadOp {
819public:
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
836class CurlListdirOp final : public CurlOperation {
837public:
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
849private:
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.
887enum class TpcMode {
890};
891
892// A third-party-copy operation
893//
894// Invoke the COPY verb to move a file between two HTTP endpoints.
895class CurlCopyOp final : public CurlOperation {
896public:
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
919private:
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
949class CurlPutOp final : public CurlOperation {
950public:
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
986private:
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
@ kXR_noErrorYet
void CURL
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
std::vector< std::pair< std::string, std::string > > Headers
void ReleaseHandle() override
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)
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
void SetDone(bool has_failed)
static void SetStallTimeout(const std::chrono::steady_clock::duration &stall_interval)
int FailCallback(XErrorCode ecode, const std::string &emsg)
std::chrono::steady_clock::time_point GetHeaderExpiry() const
bool FinishSetup(CURL *curl)
std::atomic< std::chrono::steady_clock::time_point > m_header_expiry
std::unique_ptr< ResponseInfo > MoveResponseInfo()
const std::string m_url
const std::string & GetUrl() const
CURL * GetCurlHandle() const
std::unique_ptr< CURL, void(*)(CURL *)> m_curl
bool TransferStalled(uint64_t xfer_bytes, const std::chrono::steady_clock::time_point &now)
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)
static constexpr int m_default_minimum_rate
static void SetSlowRateBytesSec(int rate)
static void SetStallTimeout(int stall_interval)
CreateConnCalloutType GetConnCalloutFunc() const
std::vector< std::pair< std::string, std::string > > HeaderList
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)
std::unique_ptr< ResponseInfo > GetResponseInfo()
XrdClHttp::HttpVerb HttpVerb
std::chrono::steady_clock::time_point m_operation_expiry
virtual void Fail(uint16_t errCode, uint32_t errNum, const std::string &)
virtual RedirectAction Redirect(std::string &target)
XrdCl::ResponseHandler * m_handler
CurlOperation(XrdCl::ResponseHandler *handler, const std::string &url, struct timespec timeout, XrdCl::Log *log, CreateConnCalloutType, HeaderCallout *header_callout)
static int GetDefaultStallTimeout()
void SetPaused(bool paused)
virtual void SetContinueQueue(std::shared_ptr< XrdClHttp::HandlerQueue > queue)
bool StartConnectionCallout(std::string &err)
bool OperationTimeoutExpired(const std::chrono::steady_clock::time_point &now)
CurlOperation(const CurlOperation &)=delete
virtual bool Setup(CURL *curl, CurlWorker &)
std::pair< XErrorCode, std::string > GetCallbackError() 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
CURL * GetParentCurlHandle() 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
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
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.
Handle diagnostics.
Definition XrdClLog.hh:101
Handle the progress of an asynchronous operation.
Handle an async response.
URL representation.
Definition XrdClURL.hh:31
ConnectionCallout *(*)(const std::string &, const ResponseInfo &) CreateConnCalloutType
std::vector< ChunkInfo > ChunkList
List of chunks.
Code
XRootD query request codes.