Skip to content

Commit

Permalink
XrdTpc: Avoid using invalid object in multi-stream.
Browse files Browse the repository at this point in the history
Fixes #1378
  • Loading branch information
bbockelm committed Jan 24, 2021
1 parent e4a77f2 commit 50f3963
Showing 1 changed file with 55 additions and 10 deletions.
65 changes: 55 additions & 10 deletions src/XrdTpc/XrdTpcMultistream.cc
Expand Up @@ -34,7 +34,10 @@ class MultiCurlHandler {
MultiCurlHandler(std::vector<State*> &states, XrdSysError &log) :
m_handle(curl_multi_init()),
m_states(states),
m_log(log)
m_log(log),
m_bytes_transferred(0),
m_error_code(0),
m_status_code(0)
{
if (m_handle == NULL) {
throw CurlHandlerSetupError("Failed to initialize a libcurl multi-handle");
Expand Down Expand Up @@ -81,6 +84,17 @@ class MultiCurlHandler {
state_iter != m_states.end();
state_iter++) {
if (curl == (*state_iter)->GetHandle()) {
m_bytes_transferred += (*state_iter)->BytesTransferred();
int error_code = (*state_iter)->GetErrorCode();
if (error_code && !m_error_code) {
m_error_code = error_code;
m_error_message = (*state_iter)->GetErrorMessage();
}
int status_code = (*state_iter)->GetStatusCode();
if (status_code >= 400 && !m_status_code) {
m_status_code = status_code;
m_error_message = (*state_iter)->GetErrorMessage();
}
(*state_iter)->ResetAfterRequest();
break;
}
Expand Down Expand Up @@ -119,6 +133,34 @@ class MultiCurlHandler {
return current_offset;
}

int Flush() {
int last_error = 0;
for (std::vector<State*>::iterator state_it = m_states.begin();
state_it != m_states.end();
state_it++)
{
int error = (*state_it)->Flush();
if (error) {last_error = error;}
}
return last_error;
}

off_t BytesTransferred() const {
return m_bytes_transferred;
}

int GetStatusCode() const {
return m_status_code;
}

int GetErrorCode() const {
return m_error_code;
}

std::string GetErrorMessage() const {
return m_error_message;
}

private:

bool StartTransfer(off_t offset, size_t size) {
Expand Down Expand Up @@ -204,6 +246,10 @@ class MultiCurlHandler {
std::vector<CURL *> m_active_handles;
std::vector<State*> &m_states;
XrdSysError &m_log;
off_t m_bytes_transferred;
int m_error_code;
int m_status_code;
std::string m_error_message;
};
}

Expand Down Expand Up @@ -366,27 +412,26 @@ int TPCHandler::RunCurlWithStreamsImpl(XrdHttpExtReq &req, State &state,
throw std::runtime_error("Internal state error in libcurl");
}

state.Flush();
state.Finalize();
mch.Flush();

rec.bytes_transferred = state.BytesTransferred();
rec.tpc_status = state.GetStatusCode();
rec.bytes_transferred = mch.BytesTransferred();
rec.tpc_status = mch.GetStatusCode();

// Generate the final response back to the client.
std::stringstream ss;
success = false;
if (state.GetStatusCode() >= 400) {
std::string err = state.GetErrorMessage();
if (mch.GetStatusCode() >= 400) {
std::string err = mch.GetErrorMessage();
std::stringstream ss2;
ss2 << "Remote side failed with status code " << state.GetStatusCode();
ss2 << "Remote side failed with status code " << mch.GetStatusCode();
if (!err.empty()) {
std::replace(err.begin(), err.end(), '\n', ' ');
ss2 << "; error message: \"" << err << "\"";
}
logTransferEvent(LogMask::Error, rec, "MULTISTREAM_FAIL", ss.str());
ss << "failure: " << ss2.str();
} else if (state.GetErrorCode()) {
std::string err = state.GetErrorMessage();
} else if (mch.GetErrorCode()) {
std::string err = mch.GetErrorMessage();
if (err.empty()) {err = "(no error message provided)";}
else {std::replace(err.begin(), err.end(), '\n', ' ');}
std::stringstream ss2;
Expand Down

0 comments on commit 50f3963

Please sign in to comment.