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

`#include <XrdHttpTpcState.hh>`

Collaboration diagram for TPC::State:

## 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
State * | Duplicate ()
bool | Finalize ()
int | Flush ()
std::string | GetConnectionDescription ()
off_t | GetContentLength () const
int | GetErrorCode () const
std::string | GetErrorMessage () const
CURL * | GetHandle () 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.

## Constructor & Destructor Documentation

## State() [1/3]

TPC::State::State | ( |  | ) |

inline

Definition at line 24 of file XrdHttpTpcState.hh.

:
m_push(true),
m_recv_status_line(false),
m_recv_all_headers(false),
m_offset(0),
m_start_offset(0),
m_status_code(-1),
m_error_code(0),
m_content_length(-1),
m_stream(NULL),
m_curl(NULL),
m_headers(NULL),
m_is_transfer_state(true)
{}

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

  curl | the curl handle

Definition at line 43 of file XrdHttpTpcState.hh.

:
m_push(true),
m_recv_status_line(false),
m_recv_all_headers(false),
m_offset(0),
m_start_offset(0),
m_status_code(-1),
m_error_code(0),
m_content_length(-1),
m_push_length(-1),
m_stream(NULL),
m_curl(curl),
m_headers(NULL),
m_is_transfer_state(false),
tpcForwardCreds(tpcForwardCreds)
{
InstallHandlers(curl);
}

## State() [3/3]

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

inline

Definition at line 65 of file XrdHttpTpcState.hh.

:
m_push(push),
m_recv_status_line(false),
m_recv_all_headers(false),
m_offset(0),
m_start_offset(start_offset),
m_status_code(-1),
m_error_code(0),
m_content_length(-1),
m_push_length(-1),
m_stream(&stream),
m_curl(curl),
m_headers(NULL),
m_is_transfer_state(true),
tpcForwardCreds(tpcForwardCreds)
{
InstallHandlers(curl);
}

## ~State()

State::~State | ( |  | ) |

Definition at line 18 of file XrdHttpTpcState.cc.

{
if (m_headers) {
curl_slist_free_all(m_headers);
m_headers = NULL;
if (m_curl) {curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headers);}
}
}

## Member Function Documentation

## AvailableBuffers()

int State::AvailableBuffers | ( |  | ) | const

Definition at line 292 of file XrdHttpTpcState.cc.

{
return m_stream->AvailableBuffers();
}

## BodyTransferInProgress()

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

inline

Definition at line 116 of file XrdHttpTpcState.hh.

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

## BytesTransferred()

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

inline

Definition at line 90 of file XrdHttpTpcState.hh.

{return m_offset;}

## DumpBuffers()

void State::DumpBuffers | ( |  | ) | const

Definition at line 297 of file XrdHttpTpcState.cc.

{
m_stream->DumpBuffers();
}

## Duplicate()

State * State::Duplicate | ( |  | ) |

Definition at line 260 of file XrdHttpTpcState.cc.

{
CURL *curl = curl_easy_duphandle(m_curl);
if (!curl) {
throw std::runtime_error("Failed to duplicate existing curl handle.");
}
State *state = new State(0, *m_stream, curl, m_push, tpcForwardCreds);
if (m_headers) {
state->m_headers_copy.reserve(m_headers_copy.size());
for (std::vector<std::string>::const_iterator header_iter = m_headers_copy.begin();
header_iter != m_headers_copy.end();
header_iter++) {
state->m_headers = curl_slist_append(state->m_headers, header_iter->c_str());
state->m_headers_copy.push_back(*header_iter);
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, state->m_headers);
}
return state;
}
CURL
void CURL
Definition XrdHttpTpcState.hh:15
TPC::State::State
State()
Definition XrdHttpTpcState.hh:24

References State().

Here is the call graph for this function:

## Finalize()

bool State::Finalize | ( |  | ) |

Definition at line 302 of file XrdHttpTpcState.cc.

{
if (!m_stream->Finalize()) {
m_error_buf = m_stream->GetErrorMessage();
m_error_code = 3;
return false;
}
return true;
}

## Flush()

int State::Flush | ( |  | ) |

Definition at line 228 of file XrdHttpTpcState.cc.

{
if (m_push) {
return 0;
}
ssize_t retval = m_stream->Write(m_start_offset + m_offset, 0, 0, true);
if (retval == SFS_ERROR) {
m_error_buf = m_stream->GetErrorMessage();
m_error_code = 2;
return -1;
}
m_offset += retval;
return retval;
}
SFS_ERROR
#define SFS_ERROR
Definition XrdSfsInterface.hh:109

References SFS_ERROR.

## GetConnectionDescription()

std::string State::GetConnectionDescription | ( |  | ) |

Definition at line 312 of file XrdHttpTpcState.cc.

{
// CURLINFO_PRIMARY_PORT is only defined for 7.21.0 or later; on older
// library versions, simply omit this information.
#if LIBCURL_VERSION_NUM >= 0x071500
char *curl_ip = NULL;
CURLcode rc = curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_IP, &curl_ip);
if ((rc != CURLE_OK) || !curl_ip) {
return "";
}
long curl_port = 0;
rc = curl_easy_getinfo(m_curl, CURLINFO_PRIMARY_PORT, &curl_port);
if ((rc != CURLE_OK) || !curl_port) {
return "";
}
std::stringstream ss;
// libcurl returns IPv6 addresses of the form:
// 2600:900:6:1301:5054:ff:fe0b:9cba:8000
// However the HTTP-TPC spec says to use the form
// [2600:900:6:1301:5054:ff:fe0b:9cba]:8000
// Hence, we add '[' and ']' whenever a ':' is seen.
if (NULL == strchr(curl_ip, ':'))
ss << "tcp:" << curl_ip << ":" << curl_port;
else
ss << "tcp:[" << curl_ip << "]:" << curl_port;
return ss.str();
#else
return "";
#endif
}

## GetContentLength()

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

inline

Definition at line 94 of file XrdHttpTpcState.hh.

{return m_content_length;}

## GetErrorCode()

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

inline

Definition at line 96 of file XrdHttpTpcState.hh.

{return m_error_code;}

## GetErrorMessage()

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

inline

Definition at line 102 of file XrdHttpTpcState.hh.

{return m_error_buf;}

## GetHandle()

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

inline

Definition at line 108 of file XrdHttpTpcState.hh.

{return m_curl;}

## GetStatusCode()

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

inline

Definition at line 100 of file XrdHttpTpcState.hh.

{return m_status_code;}

## Move()

void State::Move | ( | State & | other | ) |

Definition at line 27 of file XrdHttpTpcState.cc.

{
m_push = other.m_push;
m_recv_status_line = other.m_recv_status_line;
m_recv_all_headers = other.m_recv_all_headers;
m_offset = other.m_offset;
m_start_offset = other.m_start_offset;
m_status_code = other.m_status_code;
m_content_length = other.m_content_length;
m_push_length = other.m_push_length;
m_stream = other.m_stream;
m_curl = other.m_curl;
m_headers = other.m_headers;
m_headers_copy = other.m_headers_copy;
m_resp_protocol = other.m_resp_protocol;
m_is_transfer_state = other.m_is_transfer_state;
curl_easy_setopt(m_curl, CURLOPT_HEADERDATA, this);
if (m_is_transfer_state) {
if (m_push) {
curl_easy_setopt(m_curl, CURLOPT_READDATA, this);
} else {
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);
}
}
tpcForwardCreds = other.tpcForwardCreds;
other.m_headers_copy.clear();
other.m_curl = NULL;
other.m_headers = NULL;
other.m_stream = NULL;
}

References State().

Here is the call graph for this function:

## ResetAfterRequest()

void State::ResetAfterRequest | ( |  | ) |

Definition at line 135 of file XrdHttpTpcState.cc.

{
m_offset = 0;
m_status_code = -1;
m_content_length = -1;
m_push_length = -1;
m_recv_all_headers = false;
m_recv_status_line = false;
}

## SetContentLength()

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

inline

Definition at line 92 of file XrdHttpTpcState.hh.

{ m_content_length = content_length; }

## SetErrorCode()

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

inline

Definition at line 98 of file XrdHttpTpcState.hh.

{m_error_code = error_code;}

## SetErrorMessage()

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

inline

Definition at line 104 of file XrdHttpTpcState.hh.

{m_error_buf = error_msg;}

## SetTransferParameters()

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

Definition at line 283 of file XrdHttpTpcState.cc.

{
m_start_offset = offset;
m_offset = 0;
m_content_length = size;
std::stringstream ss;
ss << offset << "-" << (offset+size-1);
curl_easy_setopt(m_curl, CURLOPT_RANGE, ss.str().c_str());
}

## 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 101 of file XrdHttpTpcState.cc.

{
struct curl_slist *list = NULL;
for (std::map<std::string, std::string>::const_iterator hdr_iter = req.headers.begin();
hdr_iter != req.headers.end();
hdr_iter++) {
if (!strcasecmp(hdr_iter->first.c_str(),"copy-header")) {
list = curl_slist_append(list, hdr_iter->second.c_str());
m_headers_copy.emplace_back(hdr_iter->second);
}
// Note: len("TransferHeader") == 14
if (!strncasecmp(hdr_iter->first.c_str(),"transferheader",14)) {
std::stringstream ss;
ss << hdr_iter->first.substr(14) << ": " << hdr_iter->second;
list = curl_slist_append(list, ss.str().c_str());
m_headers_copy.emplace_back(ss.str());
}
}
if (m_is_transfer_state && m_push && m_push_length > 0) {
// On libcurl 8.5.0 - 8.9.1, we've observed bugs causing failures whenever
// `Expect: 100-continue` is not used. Older versions of libcurl unconditionally
// set `Expect` whenever PUT is used (likely an older bug). To workaround the issue,
// we force `Expect` to be set, triggering the older libcurl behavior.
// See: https://github.com/xrootd/xrootd/issues/2470
// See: https://github.com/curl/curl/issues/17004
list = curl_slist_append(list, "Expect: 100-continue");
}
if (list != NULL) {
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, list);
m_headers = list;
}
}
XrdHttpExtReq::headers
std::map< std::string, std::string > & headers
Definition XrdHttpExtHandler.hh:55

References XrdHttpExtReq::headers.

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

- XrdHttpTpcState.hh
- XrdHttpTpcState.cc