// Copyright 2014 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#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