diff --git a/src/lib/curl/Adapter.cxx b/src/lib/curl/Adapter.cxx index 6e1fadab3..aba94acc3 100644 --- a/src/lib/curl/Adapter.cxx +++ b/src/lib/curl/Adapter.cxx @@ -31,7 +31,6 @@ #include "Easy.hxx" #include "Handler.hxx" #include "util/CharUtil.hxx" -#include "util/RuntimeError.hxx" #include "util/StringSplit.hxx" #include "util/StringStrip.hxx" @@ -98,8 +97,8 @@ CurlResponseHandlerAdapter::Done(CURLcode result) noexcept StripRight(error_buffer); const char *msg = error_buffer; if (*msg == 0) - msg = curl_easy_strerror(result); - throw FormatRuntimeError("CURL failed: %s", msg); + msg = "CURL failed"; + throw Curl::MakeError(result, msg); } FinishBody(); diff --git a/src/lib/curl/Easy.hxx b/src/lib/curl/Easy.hxx index 8a434b719..fd2cceef0 100644 --- a/src/lib/curl/Easy.hxx +++ b/src/lib/curl/Easy.hxx @@ -30,6 +30,7 @@ #ifndef CURL_EASY_HXX #define CURL_EASY_HXX +#include "Error.hxx" #include "String.hxx" #include @@ -92,7 +93,7 @@ public: void SetOption(CURLoption option, T value) { CURLcode code = curl_easy_setopt(handle, option, value); if (code != CURLE_OK) - throw std::runtime_error(curl_easy_strerror(code)); + throw Curl::MakeError(code, "Failed to set option"); } void SetPrivate(void *pointer) { @@ -209,7 +210,7 @@ public: void Perform() { CURLcode code = curl_easy_perform(handle); if (code != CURLE_OK) - throw std::runtime_error(curl_easy_strerror(code)); + throw Curl::MakeError(code, "CURL failed"); } bool Unpause() noexcept { diff --git a/src/lib/curl/Error.hxx b/src/lib/curl/Error.hxx new file mode 100644 index 000000000..f4c7131ac --- /dev/null +++ b/src/lib/curl/Error.hxx @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +#include + +namespace Curl { + +class ErrorCategory final : public std::error_category { +public: + const char *name() const noexcept override { + return "curl"; + } + + std::string message(int condition) const override { + return curl_easy_strerror(static_cast(condition)); + } +}; + +inline ErrorCategory error_category; + +inline std::system_error +MakeError(CURLcode code, const char *msg) noexcept +{ + return std::system_error(static_cast(code), error_category, msg); +} + +} // namespace Curl diff --git a/src/lib/curl/Init.cxx b/src/lib/curl/Init.cxx index aa6e09efd..38f555467 100644 --- a/src/lib/curl/Init.cxx +++ b/src/lib/curl/Init.cxx @@ -29,6 +29,7 @@ #include "Init.hxx" #include "Global.hxx" +#include "Error.hxx" #include "event/Call.hxx" #include "thread/Mutex.hxx" @@ -48,7 +49,7 @@ CurlInit::CurlInit(EventLoop &event_loop) CURLcode code = curl_global_init(CURL_GLOBAL_ALL); if (code != CURLE_OK) - throw std::runtime_error(curl_easy_strerror(code)); + throw Curl::MakeError(code, "CURL initialization failed"); assert(instance == nullptr); instance = new CurlGlobal(event_loop);