XRootD
Loading...
Searching...
No Matches
TPC::State Class Reference

#include <XrdHttpTpcState.hh>

+ Collaboration diagram for TPC::State:

Public Types

enum  ErrorCode {
  errNone = 0 ,
  errWrite = 1 ,
  errFlush = 2 ,
  errClose = 3 ,
  errTimeout = 10
}
 

Public Member Functions

 State ()
 
 State (CURL *curl, bool tpcForwardCreds)
 
 State (off_t start_offset, Stream &stream, CURL *curl, bool push, bool tpcForwardCreds)
 
 ~State ()
 
int AvailableBuffers () const
 
bool BodyTransferInProgress () const
 
off_t BytesTransferred () const
 
void DumpBuffers () const
 
StateDuplicate ()
 
bool Finalize ()
 
int Flush ()
 
std::string GetConnectionDescription ()
 
off_t GetContentLength () const
 
int GetErrorCode () const
 
std::string GetErrorMessage () const
 
int GetFinalizeErrorCode () const
 
std::string GetFinalizeErrorMessage () const
 
CURLGetHandle () const
 
int GetStatusCode () const
 
void Move (State &other)
 
void ResetAfterRequest ()
 
void SetContentLength (const off_t content_length)
 
void SetErrorCode (int error_code)
 
void SetErrorMessage (const std::string &error_msg)
 
void SetTransferParameters (off_t offset, size_t size)
 
void SetupHeaders (XrdHttpExtReq &req)
 

Detailed Description

Definition at line 21 of file XrdHttpTpcState.hh.

Member Enumeration Documentation

◆ ErrorCode

Enumerator
errNone 
errWrite 
errFlush 
errClose 
errTimeout 

Definition at line 27 of file XrdHttpTpcState.hh.

27 {
28 errNone = 0,
29 errWrite = 1, // Failure while writing the received data to the local file.
30 errFlush = 2, // Failure while flushing the local file.
31 errClose = 3, // Failure while closing the local file.
32 errTimeout = 10 // The transfer did not make any progress within the timeout.
33 };

Constructor & Destructor Documentation

◆ State() [1/3]

TPC::State::State ( )
inline

Definition at line 35 of file XrdHttpTpcState.hh.

35 :
36 m_push(true),
37 m_recv_status_line(false),
38 m_recv_all_headers(false),
39 m_offset(0),
40 m_start_offset(0),
41 m_status_code(-1),
42 m_error_code(0),
43 m_content_length(-1),
44 m_stream(NULL),
45 m_curl(NULL),
46 m_headers(NULL),
47 m_is_transfer_state(true)
48 {}

Referenced by Duplicate(), and Move().

+ Here is the caller graph for this function:

◆ State() [2/3]

TPC::State::State ( CURL * curl,
bool tpcForwardCreds )
inline

Don't use that constructor if you want to do some transfers.

Parameters
curlthe curl handle

Definition at line 54 of file XrdHttpTpcState.hh.

54 :
55 m_push(true),
56 m_recv_status_line(false),
57 m_recv_all_headers(false),
58 m_offset(0),
59 m_start_offset(0),
60 m_status_code(-1),
61 m_error_code(0),
62 m_content_length(-1),
63 m_push_length(-1),
64 m_stream(NULL),
65 m_curl(curl),
66 m_headers(NULL),
67 m_is_transfer_state(false),
68 tpcForwardCreds(tpcForwardCreds)
69 {
70 InstallHandlers(curl);
71 }

◆ State() [3/3]

TPC::State::State ( off_t start_offset,
Stream & stream,
CURL * curl,
bool push,
bool tpcForwardCreds )
inline

Definition at line 76 of file XrdHttpTpcState.hh.

76 :
77 m_push(push),
78 m_recv_status_line(false),
79 m_recv_all_headers(false),
80 m_offset(0),
81 m_start_offset(start_offset),
82 m_status_code(-1),
83 m_error_code(0),
84 m_content_length(-1),
85 m_push_length(-1),
86 m_stream(&stream),
87 m_curl(curl),
88 m_headers(NULL),
89 m_is_transfer_state(true),
90 tpcForwardCreds(tpcForwardCreds)
91 {
92 InstallHandlers(curl);
93 }

◆ ~State()

State::~State ( )

Definition at line 18 of file XrdHttpTpcState.cc.

18 {
19 if (m_headers) {
20 curl_slist_free_all(m_headers);
21 m_headers = NULL;
22 if (m_curl) {curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headers);}
23 }
24}

Member Function Documentation

◆ AvailableBuffers()

int State::AvailableBuffers ( ) const

Definition at line 291 of file XrdHttpTpcState.cc.

292{
293 return m_stream->AvailableBuffers();
294}

◆ BodyTransferInProgress()

bool TPC::State::BodyTransferInProgress ( ) const
inline

Definition at line 136 of file XrdHttpTpcState.hh.

136{return m_offset && (m_offset != m_content_length);}

◆ BytesTransferred()

off_t TPC::State::BytesTransferred ( ) const
inline

Definition at line 101 of file XrdHttpTpcState.hh.

101{return m_offset;}

◆ DumpBuffers()

void State::DumpBuffers ( ) const

Definition at line 296 of file XrdHttpTpcState.cc.

297{
298 m_stream->DumpBuffers();
299}

◆ Duplicate()

State * State::Duplicate ( )

Definition at line 259 of file XrdHttpTpcState.cc.

259 {
260 CURL *curl = curl_easy_duphandle(m_curl);
261 if (!curl) {
262 throw std::runtime_error("Failed to duplicate existing curl handle.");
263 }
264
265 State *state = new State(0, *m_stream, curl, m_push, tpcForwardCreds);
266
267 if (m_headers) {
268 state->m_headers_copy.reserve(m_headers_copy.size());
269 for (std::vector<std::string>::const_iterator header_iter = m_headers_copy.begin();
270 header_iter != m_headers_copy.end();
271 header_iter++) {
272 state->m_headers = curl_slist_append(state->m_headers, header_iter->c_str());
273 state->m_headers_copy.push_back(*header_iter);
274 }
275 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
276 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->m_headers);
277 }
278
279 return state;
280}
void CURL

References State().

+ Here is the call graph for this function:

◆ Finalize()

bool State::Finalize ( )

Definition at line 301 of file XrdHttpTpcState.cc.

302{
303 if (!m_stream->Finalize()) {
304 RecordFinalizeError(errClose, m_stream->GetErrorMessage());
305 return false;
306 }
307 return true;
308}

References errClose.

◆ Flush()

int State::Flush ( )

Definition at line 228 of file XrdHttpTpcState.cc.

228 {
229 if (m_push) {
230 return 0;
231 }
232
233 ssize_t retval = m_stream->Write(m_start_offset + m_offset, 0, 0, true);
234 if (retval == SFS_ERROR) {
235 RecordFinalizeError(errFlush, m_stream->GetErrorMessage());
236 return -1;
237 }
238 m_offset += retval;
239 return retval;
240}
#define SFS_ERROR

References errFlush, and SFS_ERROR.

◆ GetConnectionDescription()

std::string State::GetConnectionDescription ( )

Definition at line 310 of file XrdHttpTpcState.cc.

311{
312 // CURLINFO_PRIMARY_PORT is only defined for 7.21.0 or later; on older
313 // library versions, simply omit this information.
314#if LIBCURL_VERSION_NUM >= 0x071500
315 char *curl_ip = NULL;
316 CURLcode rc = curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_IP, &curl_ip);
317 if ((rc != CURLE_OK) || !curl_ip) {
318 return "";
319 }
320 long curl_port = 0;
321 rc = curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_PORT, &curl_port);
322 if ((rc != CURLE_OK) || !curl_port) {
323 return "";
324 }
325 std::stringstream ss;
326 // libcurl returns IPv6 addresses of the form:
327 // 2600:900:6:1301:5054:ff:fe0b:9cba:8000
328 // However the HTTP-TPC spec says to use the form
329 // [2600:900:6:1301:5054:ff:fe0b:9cba]:8000
330 // Hence, we add '[' and ']' whenever a ':' is seen.
331 if (NULL == strchr(curl_ip, ':'))
332 ss << "tcp:" << curl_ip << ":" << curl_port;
333 else
334 ss << "tcp:[" << curl_ip << "]:" << curl_port;
335 return ss.str();
336#else
337 return "";
338#endif
339}

◆ GetContentLength()

off_t TPC::State::GetContentLength ( ) const
inline

Definition at line 105 of file XrdHttpTpcState.hh.

105{return m_content_length;}

◆ GetErrorCode()

int TPC::State::GetErrorCode ( ) const
inline

Definition at line 107 of file XrdHttpTpcState.hh.

107{return m_error_code;}

◆ GetErrorMessage()

std::string TPC::State::GetErrorMessage ( ) const
inline

Definition at line 113 of file XrdHttpTpcState.hh.

113{return m_error_buf;}

◆ GetFinalizeErrorCode()

int TPC::State::GetFinalizeErrorCode ( ) const
inline

Definition at line 122 of file XrdHttpTpcState.hh.

122{return m_finalize_error_code;}

◆ GetFinalizeErrorMessage()

std::string TPC::State::GetFinalizeErrorMessage ( ) const
inline

Definition at line 124 of file XrdHttpTpcState.hh.

124{return m_finalize_error_buf;}

◆ GetHandle()

CURL * TPC::State::GetHandle ( ) const
inline

Definition at line 128 of file XrdHttpTpcState.hh.

128{return m_curl;}

◆ GetStatusCode()

int TPC::State::GetStatusCode ( ) const
inline

Definition at line 111 of file XrdHttpTpcState.hh.

111{return m_status_code;}

◆ Move()

void State::Move ( State & other)

Definition at line 27 of file XrdHttpTpcState.cc.

28{
29 m_push = other.m_push;
30 m_recv_status_line = other.m_recv_status_line;
31 m_recv_all_headers = other.m_recv_all_headers;
32 m_offset = other.m_offset;
33 m_start_offset = other.m_start_offset;
34 m_status_code = other.m_status_code;
35 m_content_length = other.m_content_length;
36 m_push_length = other.m_push_length;
37 m_stream = other.m_stream;
38 m_curl = other.m_curl;
39 m_headers = other.m_headers;
40 m_headers_copy = other.m_headers_copy;
41 m_resp_protocol = other.m_resp_protocol;
42 m_is_transfer_state = other.m_is_transfer_state;
43 curl_easy_setopt(m_curl, CURLOPT_HEADERDATA, this);
44 if (m_is_transfer_state) {
45 if (m_push) {
46 curl_easy_setopt(m_curl, CURLOPT_READDATA, this);
47 } else {
48 curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);
49 }
50 }
51 tpcForwardCreds = other.tpcForwardCreds;
52 other.m_headers_copy.clear();
53 other.m_curl = NULL;
54 other.m_headers = NULL;
55 other.m_stream = NULL;
56}

References State().

+ Here is the call graph for this function:

◆ ResetAfterRequest()

void State::ResetAfterRequest ( )

Definition at line 127 of file XrdHttpTpcState.cc.

127 {
128 m_offset = 0;
129 m_status_code = -1;
130 m_content_length = -1;
131 m_push_length = -1;
132 m_recv_all_headers = false;
133 m_recv_status_line = false;
134}

◆ SetContentLength()

void TPC::State::SetContentLength ( const off_t content_length)
inline

Definition at line 103 of file XrdHttpTpcState.hh.

103{ m_content_length = content_length; }

◆ SetErrorCode()

void TPC::State::SetErrorCode ( int error_code)
inline

Definition at line 109 of file XrdHttpTpcState.hh.

109{m_error_code = error_code;}

◆ SetErrorMessage()

void TPC::State::SetErrorMessage ( const std::string & error_msg)
inline

Definition at line 115 of file XrdHttpTpcState.hh.

115{m_error_buf = error_msg;}

◆ SetTransferParameters()

void State::SetTransferParameters ( off_t offset,
size_t size )

Definition at line 282 of file XrdHttpTpcState.cc.

282 {
283 m_start_offset = offset;
284 m_offset = 0;
285 m_content_length = size;
286 std::stringstream ss;
287 ss << offset << "-" << (offset+size-1);
288 curl_easy_setopt(m_curl, CURLOPT_RANGE, ss.str().c_str());
289}

◆ SetupHeaders()

void State::SetupHeaders ( XrdHttpExtReq & req)

Setup any headers necessary for the GET/PUT operation

Currently includes:

  • Handle the 'Copy-Headers' feature
  • Adding Expect: 100-continue to get around a libcurl bug on uploads.

Definition at line 93 of file XrdHttpTpcState.cc.

93 {
94 struct curl_slist *list = NULL;
95 for (std::map<std::string, std::string>::const_iterator hdr_iter = req.headers.begin();
96 hdr_iter != req.headers.end();
97 hdr_iter++) {
98 if (!strcasecmp(hdr_iter->first.c_str(),"copy-header")) {
99 list = curl_slist_append(list, hdr_iter->second.c_str());
100 m_headers_copy.emplace_back(hdr_iter->second);
101 }
102 // Note: len("TransferHeader") == 14
103 if (!strncasecmp(hdr_iter->first.c_str(),"transferheader",14)) {
104 std::stringstream ss;
105 ss << hdr_iter->first.substr(14) << ": " << hdr_iter->second;
106 list = curl_slist_append(list, ss.str().c_str());
107 m_headers_copy.emplace_back(ss.str());
108 }
109 }
110
111 if (m_is_transfer_state && m_push && m_push_length > 0) {
112 // On libcurl 8.5.0 - 8.9.1, we've observed bugs causing failures whenever
113 // `Expect: 100-continue` is not used. Older versions of libcurl unconditionally
114 // set `Expect` whenever PUT is used (likely an older bug). To workaround the issue,
115 // we force `Expect` to be set, triggering the older libcurl behavior.
116 // See: https://github.com/xrootd/xrootd/issues/2470
117 // See: https://github.com/curl/curl/issues/17004
118 list = curl_slist_append(list, "Expect: 100-continue");
119 }
120
121 if (list != NULL) {
122 curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, list);
123 m_headers = list;
124 }
125}
std::map< std::string, std::string > & headers

References XrdHttpExtReq::headers.


The documentation for this class was generated from the following files: