// 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.
#ifndef LIBBRILLO_BRILLO_HTTP_CURL_API_H_
#define LIBBRILLO_BRILLO_HTTP_CURL_API_H_
#include <curl/curl.h>
#include <string>
#include <base/macros.h>
#include <brillo/brillo_export.h>
namespace brillo {
namespace http {
// Abstract wrapper around libcurl C API that allows us to mock it out in tests.
class CurlInterface {
public:
CurlInterface() = default;
virtual ~CurlInterface() = default;
// Wrapper around curl_easy_init().
virtual CURL* EasyInit() = 0;
// Wrapper around curl_easy_cleanup().
virtual void EasyCleanup(CURL* curl) = 0;
// Wrappers around curl_easy_setopt().
virtual CURLcode EasySetOptInt(CURL* curl, CURLoption option, int value) = 0;
virtual CURLcode EasySetOptStr(CURL* curl,
CURLoption option,
const std::string& value) = 0;
virtual CURLcode EasySetOptPtr(CURL* curl,
CURLoption option,
void* value) = 0;
virtual CURLcode EasySetOptCallback(CURL* curl,
CURLoption option,
intptr_t address) = 0;
virtual CURLcode EasySetOptOffT(CURL* curl,
CURLoption option,
curl_off_t value) = 0;
// A type-safe wrapper around function callback options.
template<typename R, typename... Args>
inline CURLcode EasySetOptCallback(CURL* curl,
CURLoption option,
R(*callback)(Args...)) {
return EasySetOptCallback(
curl, option, reinterpret_cast<intptr_t>(callback));
}
// Wrapper around curl_easy_perform().
virtual CURLcode EasyPerform(CURL* curl) = 0;
// Wrappers around curl_easy_getinfo().
virtual CURLcode EasyGetInfoInt(CURL* curl,
CURLINFO info,
int* value) const = 0;
virtual CURLcode EasyGetInfoDbl(CURL* curl,
CURLINFO info,
double* value) const = 0;
virtual CURLcode EasyGetInfoStr(CURL* curl,
CURLINFO info,
std::string* value) const = 0;
virtual CURLcode EasyGetInfoPtr(CURL* curl,
CURLINFO info,
void** value) const = 0;
// Wrapper around curl_easy_strerror().
virtual std::string EasyStrError(CURLcode code) const = 0;
// Wrapper around curl_multi_init().
virtual CURLM* MultiInit() = 0;
// Wrapper around curl_multi_cleanup().
virtual CURLMcode MultiCleanup(CURLM* multi_handle) = 0;
// Wrapper around curl_multi_info_read().
virtual CURLMsg* MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) = 0;
// Wrapper around curl_multi_add_handle().
virtual CURLMcode MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) = 0;
// Wrapper around curl_multi_remove_handle().
virtual CURLMcode MultiRemoveHandle(CURLM* multi_handle,
CURL* curl_handle) = 0;
// Wrapper around curl_multi_setopt(CURLMOPT_SOCKETFUNCTION/SOCKETDATA).
virtual CURLMcode MultiSetSocketCallback(
CURLM* multi_handle,
curl_socket_callback socket_callback,
void* userp) = 0;
// Wrapper around curl_multi_setopt(CURLMOPT_TIMERFUNCTION/TIMERDATA).
virtual CURLMcode MultiSetTimerCallback(
CURLM* multi_handle,
curl_multi_timer_callback timer_callback,
void* userp) = 0;
// Wrapper around curl_multi_assign().
virtual CURLMcode MultiAssign(CURLM* multi_handle,
curl_socket_t sockfd,
void* sockp) = 0;
// Wrapper around curl_multi_socket_action().
virtual CURLMcode MultiSocketAction(CURLM* multi_handle,
curl_socket_t s,
int ev_bitmask,
int* running_handles) = 0;
// Wrapper around curl_multi_strerror().
virtual std::string MultiStrError(CURLMcode code) const = 0;
// Wrapper around curl_multi_perform().
virtual CURLMcode MultiPerform(CURLM* multi_handle,
int* running_handles) = 0;
// Wrapper around curl_multi_wait().
virtual CURLMcode MultiWait(CURLM* multi_handle,
curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int* numfds) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(CurlInterface);
};
class BRILLO_EXPORT CurlApi : public CurlInterface {
public:
CurlApi();
~CurlApi() override;
// Wrapper around curl_easy_init().
CURL* EasyInit() override;
// Wrapper around curl_easy_cleanup().
void EasyCleanup(CURL* curl) override;
// Wrappers around curl_easy_setopt().
CURLcode EasySetOptInt(CURL* curl, CURLoption option, int value) override;
CURLcode EasySetOptStr(CURL* curl,
CURLoption option,
const std::string& value) override;
CURLcode EasySetOptPtr(CURL* curl, CURLoption option, void* value) override;
CURLcode EasySetOptCallback(CURL* curl,
CURLoption option,
intptr_t address) override;
CURLcode EasySetOptOffT(CURL* curl,
CURLoption option,
curl_off_t value) override;
// Wrapper around curl_easy_perform().
CURLcode EasyPerform(CURL* curl) override;
// Wrappers around curl_easy_getinfo().
CURLcode EasyGetInfoInt(CURL* curl, CURLINFO info, int* value) const override;
CURLcode EasyGetInfoDbl(CURL* curl,
CURLINFO info,
double* value) const override;
CURLcode EasyGetInfoStr(CURL* curl,
CURLINFO info,
std::string* value) const override;
CURLcode EasyGetInfoPtr(CURL* curl,
CURLINFO info,
void** value) const override;
// Wrapper around curl_easy_strerror().
std::string EasyStrError(CURLcode code) const override;
// Wrapper around curl_multi_init().
CURLM* MultiInit() override;
// Wrapper around curl_multi_cleanup().
CURLMcode MultiCleanup(CURLM* multi_handle) override;
// Wrapper around curl_multi_info_read().
CURLMsg* MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) override;
// Wrapper around curl_multi_add_handle().
CURLMcode MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) override;
// Wrapper around curl_multi_remove_handle().
CURLMcode MultiRemoveHandle(CURLM* multi_handle, CURL* curl_handle) override;
// Wrapper around curl_multi_setopt(CURLMOPT_SOCKETFUNCTION/SOCKETDATA).
CURLMcode MultiSetSocketCallback(
CURLM* multi_handle,
curl_socket_callback socket_callback,
void* userp) override;
// Wrapper around curl_multi_setopt(CURLMOPT_TIMERFUNCTION/TIMERDATA).
CURLMcode MultiSetTimerCallback(
CURLM* multi_handle,
curl_multi_timer_callback timer_callback,
void* userp) override;
// Wrapper around curl_multi_assign().
CURLMcode MultiAssign(CURLM* multi_handle,
curl_socket_t sockfd,
void* sockp) override;
// Wrapper around curl_multi_socket_action().
CURLMcode MultiSocketAction(CURLM* multi_handle,
curl_socket_t s,
int ev_bitmask,
int* running_handles) override;
// Wrapper around curl_multi_strerror().
std::string MultiStrError(CURLMcode code) const override;
// Wrapper around curl_multi_perform().
CURLMcode MultiPerform(CURLM* multi_handle,
int* running_handles) override;
// Wrapper around curl_multi_wait().
CURLMcode MultiWait(CURLM* multi_handle,
curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int* numfds) override;
private:
DISALLOW_COPY_AND_ASSIGN(CurlApi);
};
} // namespace http
} // namespace brillo
#endif // LIBBRILLO_BRILLO_HTTP_CURL_API_H_