| // Copyright 2014 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include <base/check.h> | |
| #include <base/check_op.h> | |
| #include <brillo/http/curl_api.h> | |
| #include <base/logging.h> | |
| namespace brillo { | |
| namespace http { | |
| namespace { | |
| static_assert(CURLOPTTYPE_LONG == 0 && CURLOPTTYPE_OBJECTPOINT == 10000 && | |
| CURLOPTTYPE_FUNCTIONPOINT == 20000 && | |
| CURLOPTTYPE_OFF_T == 30000, | |
| "CURL option types are expected to be multiples of 10000"); | |
| inline bool VerifyOptionType(CURLoption option, int expected_type) { | |
| int option_type = (static_cast<int>(option) / 10000) * 10000; | |
| return (option_type == expected_type); | |
| } | |
| } // anonymous namespace | |
| CurlApi::CurlApi() { | |
| curl_global_init(CURL_GLOBAL_ALL); | |
| } | |
| CurlApi::~CurlApi() { | |
| curl_global_cleanup(); | |
| } | |
| CURL* CurlApi::EasyInit() { | |
| return curl_easy_init(); | |
| } | |
| void CurlApi::EasyCleanup(CURL* curl) { | |
| curl_easy_cleanup(curl); | |
| } | |
| CURLcode CurlApi::EasySetOptInt(CURL* curl, CURLoption option, int value) { | |
| CHECK(VerifyOptionType(option, CURLOPTTYPE_LONG)) | |
| << "Only options that expect a LONG data type must be specified here"; | |
| // CURL actually uses "long" type, so have to make sure we feed it what it | |
| // expects. | |
| // NOLINTNEXTLINE(runtime/int) | |
| return curl_easy_setopt(curl, option, static_cast<long>(value)); | |
| } | |
| CURLcode CurlApi::EasySetOptStr(CURL* curl, | |
| CURLoption option, | |
| const std::string& value) { | |
| CHECK(VerifyOptionType(option, CURLOPTTYPE_OBJECTPOINT)) | |
| << "Only options that expect a STRING data type must be specified here"; | |
| return curl_easy_setopt(curl, option, value.c_str()); | |
| } | |
| CURLcode CurlApi::EasySetOptPtr(CURL* curl, CURLoption option, void* value) { | |
| CHECK(VerifyOptionType(option, CURLOPTTYPE_OBJECTPOINT)) | |
| << "Only options that expect a pointer data type must be specified here"; | |
| return curl_easy_setopt(curl, option, value); | |
| } | |
| CURLcode CurlApi::EasySetOptCallback(CURL* curl, | |
| CURLoption option, | |
| intptr_t address) { | |
| CHECK(VerifyOptionType(option, CURLOPTTYPE_FUNCTIONPOINT)) | |
| << "Only options that expect a function pointers must be specified here"; | |
| return curl_easy_setopt(curl, option, address); | |
| } | |
| CURLcode CurlApi::EasySetOptOffT(CURL* curl, | |
| CURLoption option, | |
| curl_off_t value) { | |
| CHECK(VerifyOptionType(option, CURLOPTTYPE_OFF_T)) | |
| << "Only options that expect a large data size must be specified here"; | |
| return curl_easy_setopt(curl, option, value); | |
| } | |
| CURLcode CurlApi::EasyPerform(CURL* curl) { | |
| return curl_easy_perform(curl); | |
| } | |
| CURLcode CurlApi::EasyGetInfoInt(CURL* curl, CURLINFO info, int* value) const { | |
| CHECK_EQ(CURLINFO_LONG, info & CURLINFO_TYPEMASK) << "Wrong option type"; | |
| long data = 0; // NOLINT(runtime/int) - curl expects a long here. | |
| CURLcode code = curl_easy_getinfo(curl, info, &data); | |
| if (code == CURLE_OK) | |
| *value = static_cast<int>(data); | |
| return code; | |
| } | |
| CURLcode CurlApi::EasyGetInfoDbl(CURL* curl, | |
| CURLINFO info, | |
| double* value) const { | |
| CHECK_EQ(CURLINFO_DOUBLE, info & CURLINFO_TYPEMASK) << "Wrong option type"; | |
| return curl_easy_getinfo(curl, info, value); | |
| } | |
| CURLcode CurlApi::EasyGetInfoStr(CURL* curl, | |
| CURLINFO info, | |
| std::string* value) const { | |
| CHECK_EQ(CURLINFO_STRING, info & CURLINFO_TYPEMASK) << "Wrong option type"; | |
| char* data = nullptr; | |
| CURLcode code = curl_easy_getinfo(curl, info, &data); | |
| if (code == CURLE_OK) | |
| *value = data; | |
| return code; | |
| } | |
| CURLcode CurlApi::EasyGetInfoPtr(CURL* curl, | |
| CURLINFO info, | |
| void** value) const { | |
| // CURL uses "string" type for generic pointer info. Go figure. | |
| CHECK_EQ(CURLINFO_STRING, info & CURLINFO_TYPEMASK) << "Wrong option type"; | |
| return curl_easy_getinfo(curl, info, value); | |
| } | |
| std::string CurlApi::EasyStrError(CURLcode code) const { | |
| return curl_easy_strerror(code); | |
| } | |
| CURLM* CurlApi::MultiInit() { | |
| return curl_multi_init(); | |
| } | |
| CURLMcode CurlApi::MultiCleanup(CURLM* multi_handle) { | |
| return curl_multi_cleanup(multi_handle); | |
| } | |
| CURLMsg* CurlApi::MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) { | |
| return curl_multi_info_read(multi_handle, msgs_in_queue); | |
| } | |
| CURLMcode CurlApi::MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) { | |
| return curl_multi_add_handle(multi_handle, curl_handle); | |
| } | |
| CURLMcode CurlApi::MultiRemoveHandle(CURLM* multi_handle, CURL* curl_handle) { | |
| return curl_multi_remove_handle(multi_handle, curl_handle); | |
| } | |
| CURLMcode CurlApi::MultiSetSocketCallback(CURLM* multi_handle, | |
| curl_socket_callback socket_callback, | |
| void* userp) { | |
| CURLMcode code = | |
| curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback); | |
| if (code != CURLM_OK) | |
| return code; | |
| return curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, userp); | |
| } | |
| CURLMcode CurlApi::MultiSetTimerCallback( | |
| CURLM* multi_handle, | |
| curl_multi_timer_callback timer_callback, | |
| void* userp) { | |
| CURLMcode code = | |
| curl_multi_setopt(multi_handle, CURLMOPT_TIMERFUNCTION, timer_callback); | |
| if (code != CURLM_OK) | |
| return code; | |
| return curl_multi_setopt(multi_handle, CURLMOPT_TIMERDATA, userp); | |
| } | |
| CURLMcode CurlApi::MultiAssign(CURLM* multi_handle, | |
| curl_socket_t sockfd, | |
| void* sockp) { | |
| return curl_multi_assign(multi_handle, sockfd, sockp); | |
| } | |
| CURLMcode CurlApi::MultiSocketAction(CURLM* multi_handle, | |
| curl_socket_t s, | |
| int ev_bitmask, | |
| int* running_handles) { | |
| return curl_multi_socket_action(multi_handle, s, ev_bitmask, running_handles); | |
| } | |
| std::string CurlApi::MultiStrError(CURLMcode code) const { | |
| return curl_multi_strerror(code); | |
| } | |
| CURLMcode CurlApi::MultiPerform(CURLM* multi_handle, int* running_handles) { | |
| return curl_multi_perform(multi_handle, running_handles); | |
| } | |
| CURLMcode CurlApi::MultiWait(CURLM* multi_handle, | |
| curl_waitfd extra_fds[], | |
| unsigned int extra_nfds, | |
| int timeout_ms, | |
| int* numfds) { | |
| return curl_multi_wait(multi_handle, extra_fds, extra_nfds, timeout_ms, | |
| numfds); | |
| } | |
| } // namespace http | |
| } // namespace brillo |