From 47b67342d6205b2491a49d0da2183b921c73ee46 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Sat, 2 Nov 2019 10:10:02 +0100 Subject: NETWORKING: Improve libcurl error handling Error messages for failed requests are now printed as warnings. --- backends/networking/curl/connectionmanager.cpp | 19 +++++++++---------- backends/networking/curl/networkreadstream.cpp | 18 +++++++++++++++++- backends/networking/curl/networkreadstream.h | 3 ++- 3 files changed, 28 insertions(+), 12 deletions(-) (limited to 'backends') diff --git a/backends/networking/curl/connectionmanager.cpp b/backends/networking/curl/connectionmanager.cpp index 34a9701f75..557fcf06eb 100644 --- a/backends/networking/curl/connectionmanager.cpp +++ b/backends/networking/curl/connectionmanager.cpp @@ -184,20 +184,19 @@ void ConnectionManager::processTransfers() { int messagesInQueue; CURLMsg *curlMsg; while ((curlMsg = curl_multi_info_read(_multi, &messagesInQueue))) { - CURL *easyHandle = curlMsg->easy_handle; + if (curlMsg->msg == CURLMSG_DONE) { + CURL *easyHandle = curlMsg->easy_handle; - NetworkReadStream *stream; - curl_easy_getinfo(easyHandle, CURLINFO_PRIVATE, &stream); - if (stream) - stream->finished(); + NetworkReadStream *stream = nullptr; + curl_easy_getinfo(easyHandle, CURLINFO_PRIVATE, &stream); - if (curlMsg->msg == CURLMSG_DONE) { - debug(9, "ConnectionManager: SUCCESS (%d - %s)", curlMsg->data.result, curl_easy_strerror(curlMsg->data.result)); + if (stream) + stream->finished(curlMsg->data.result); + + curl_multi_remove_handle(_multi, easyHandle); } else { - warning("ConnectionManager: FAILURE (CURLMsg (%d))", curlMsg->msg); + warning("Unknown libcurl message type %d", curlMsg->msg); } - - curl_multi_remove_handle(_multi, easyHandle); } } diff --git a/backends/networking/curl/networkreadstream.cpp b/backends/networking/curl/networkreadstream.cpp index 59d2a5475c..b41a3c37b7 100644 --- a/backends/networking/curl/networkreadstream.cpp +++ b/backends/networking/curl/networkreadstream.cpp @@ -26,6 +26,7 @@ #include "backends/networking/curl/networkreadstream.h" #include "backends/networking/curl/connectionmanager.h" #include "base/version.h" +#include "common/debug.h" namespace Networking { @@ -64,6 +65,7 @@ int NetworkReadStream::curlProgressCallbackOlder(void *p, double dltotal, double void NetworkReadStream::init(const char *url, curl_slist *headersList, const byte *buffer, uint32 bufferSize, bool uploading, bool usingPatch, bool post) { _eos = _requestComplete = false; + _errorBuffer = (char *)calloc(CURL_ERROR_SIZE, 1); _sendingContentsBuffer = nullptr; _sendingContentsSize = _sendingContentsPos = 0; _progressDownloaded = _progressTotal = 0; @@ -77,6 +79,7 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt curl_easy_setopt(_easy, CURLOPT_HEADERDATA, this); curl_easy_setopt(_easy, CURLOPT_HEADERFUNCTION, curlHeadersCallback); curl_easy_setopt(_easy, CURLOPT_URL, url); + curl_easy_setopt(_easy, CURLOPT_ERRORBUFFER, _errorBuffer); curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); @@ -120,6 +123,7 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, const byt void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::HashMap formFields, Common::HashMap formFiles) { _eos = _requestComplete = false; + _errorBuffer = (char *)calloc(CURL_ERROR_SIZE, 1); _sendingContentsBuffer = nullptr; _sendingContentsSize = _sendingContentsPos = 0; _progressDownloaded = _progressTotal = 0; @@ -133,6 +137,7 @@ void NetworkReadStream::init(const char *url, curl_slist *headersList, Common::H curl_easy_setopt(_easy, CURLOPT_HEADERDATA, this); curl_easy_setopt(_easy, CURLOPT_HEADERFUNCTION, curlHeadersCallback); curl_easy_setopt(_easy, CURLOPT_URL, url); + curl_easy_setopt(_easy, CURLOPT_ERRORBUFFER, _errorBuffer); curl_easy_setopt(_easy, CURLOPT_VERBOSE, 0L); curl_easy_setopt(_easy, CURLOPT_FOLLOWLOCATION, 1L); //probably it's OK to have it always on curl_easy_setopt(_easy, CURLOPT_HTTPHEADER, headersList); @@ -205,6 +210,7 @@ NetworkReadStream::~NetworkReadStream() { if (_easy) curl_easy_cleanup(_easy); free(_bufferCopy); + free(_errorBuffer); } bool NetworkReadStream::eos() const { @@ -223,8 +229,18 @@ uint32 NetworkReadStream::read(void *dataPtr, uint32 dataSize) { return actuallyRead; } -void NetworkReadStream::finished() { +void NetworkReadStream::finished(uint32 errorCode) { _requestComplete = true; + + char *url = nullptr; + curl_easy_getinfo(_easy, CURLINFO_EFFECTIVE_URL, &url); + + if (errorCode == CURLE_OK) { + debug(9, "NetworkReadStream: %s - Request succeeded", url); + } else { + warning("NetworkReadStream: %s - Request failed (%d - %s)", url, errorCode, + strlen(_errorBuffer) ? _errorBuffer : curl_easy_strerror((CURLcode)errorCode)); + } } long NetworkReadStream::httpResponseCode() const { diff --git a/backends/networking/curl/networkreadstream.h b/backends/networking/curl/networkreadstream.h index 7d19286f85..468fce70a4 100644 --- a/backends/networking/curl/networkreadstream.h +++ b/backends/networking/curl/networkreadstream.h @@ -38,6 +38,7 @@ class NetworkReadStream: public Common::ReadStream { CURL *_easy; Common::MemoryReadWriteStream _backingStream; bool _eos, _requestComplete; + char *_errorBuffer; const byte *_sendingContentsBuffer; uint32 _sendingContentsSize; uint32 _sendingContentsPos; @@ -111,7 +112,7 @@ public: * * @note It's called on failure too. */ - void finished(); + void finished(uint32 errorCode); /** * Returns HTTP response code from inner CURL handle. -- cgit v1.2.3