Home | History | Annotate | Download | only in http
      1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <brillo/http/curl_api.h>
      6 
      7 #include <base/logging.h>
      8 
      9 namespace brillo {
     10 namespace http {
     11 
     12 namespace {
     13 
     14 static_assert(CURLOPTTYPE_LONG == 0 &&
     15               CURLOPTTYPE_OBJECTPOINT == 10000 &&
     16               CURLOPTTYPE_FUNCTIONPOINT == 20000 &&
     17               CURLOPTTYPE_OFF_T == 30000,
     18               "CURL option types are expected to be multiples of 10000");
     19 
     20 inline bool VerifyOptionType(CURLoption option, int expected_type) {
     21   int option_type = (static_cast<int>(option) / 10000) * 10000;
     22   return (option_type == expected_type);
     23 }
     24 
     25 }  // anonymous namespace
     26 
     27 CurlApi::CurlApi() {
     28   curl_global_init(CURL_GLOBAL_ALL);
     29 }
     30 
     31 CurlApi::~CurlApi() {
     32   curl_global_cleanup();
     33 }
     34 
     35 CURL* CurlApi::EasyInit() {
     36   return curl_easy_init();
     37 }
     38 
     39 void CurlApi::EasyCleanup(CURL* curl) {
     40   curl_easy_cleanup(curl);
     41 }
     42 
     43 CURLcode CurlApi::EasySetOptInt(CURL* curl, CURLoption option, int value) {
     44   CHECK(VerifyOptionType(option, CURLOPTTYPE_LONG))
     45       << "Only options that expect a LONG data type must be specified here";
     46   // CURL actually uses "long" type, so have to make sure we feed it what it
     47   // expects.
     48   // NOLINTNEXTLINE(runtime/int)
     49   return curl_easy_setopt(curl, option, static_cast<long>(value));
     50 }
     51 
     52 CURLcode CurlApi::EasySetOptStr(CURL* curl,
     53                                 CURLoption option,
     54                                 const std::string& value) {
     55   CHECK(VerifyOptionType(option, CURLOPTTYPE_OBJECTPOINT))
     56       << "Only options that expect a STRING data type must be specified here";
     57   return curl_easy_setopt(curl, option, value.c_str());
     58 }
     59 
     60 CURLcode CurlApi::EasySetOptPtr(CURL* curl, CURLoption option, void* value) {
     61   CHECK(VerifyOptionType(option, CURLOPTTYPE_OBJECTPOINT))
     62       << "Only options that expect a pointer data type must be specified here";
     63   return curl_easy_setopt(curl, option, value);
     64 }
     65 
     66 CURLcode CurlApi::EasySetOptCallback(CURL* curl,
     67                                      CURLoption option,
     68                                      intptr_t address) {
     69   CHECK(VerifyOptionType(option, CURLOPTTYPE_FUNCTIONPOINT))
     70       << "Only options that expect a function pointers must be specified here";
     71   return curl_easy_setopt(curl, option, address);
     72 }
     73 
     74 CURLcode CurlApi::EasySetOptOffT(CURL* curl,
     75                                  CURLoption option,
     76                                  curl_off_t value) {
     77   CHECK(VerifyOptionType(option, CURLOPTTYPE_OFF_T))
     78       << "Only options that expect a large data size must be specified here";
     79   return curl_easy_setopt(curl, option, value);
     80 }
     81 
     82 CURLcode CurlApi::EasyPerform(CURL* curl) {
     83   return curl_easy_perform(curl);
     84 }
     85 
     86 CURLcode CurlApi::EasyGetInfoInt(CURL* curl, CURLINFO info, int* value) const {
     87   CHECK_EQ(CURLINFO_LONG, info & CURLINFO_TYPEMASK) << "Wrong option type";
     88   long data = 0;  // NOLINT(runtime/int) - curl expects a long here.
     89   CURLcode code = curl_easy_getinfo(curl, info, &data);
     90   if (code == CURLE_OK)
     91     *value = static_cast<int>(data);
     92   return code;
     93 }
     94 
     95 CURLcode CurlApi::EasyGetInfoDbl(CURL* curl,
     96                                  CURLINFO info,
     97                                  double* value) const {
     98   CHECK_EQ(CURLINFO_DOUBLE, info & CURLINFO_TYPEMASK) << "Wrong option type";
     99   return curl_easy_getinfo(curl, info, value);
    100 }
    101 
    102 CURLcode CurlApi::EasyGetInfoStr(CURL* curl,
    103                                  CURLINFO info,
    104                                  std::string* value) const {
    105   CHECK_EQ(CURLINFO_STRING, info & CURLINFO_TYPEMASK) << "Wrong option type";
    106   char* data = nullptr;
    107   CURLcode code = curl_easy_getinfo(curl, info, &data);
    108   if (code == CURLE_OK)
    109     *value = data;
    110   return code;
    111 }
    112 
    113 CURLcode CurlApi::EasyGetInfoPtr(CURL* curl,
    114                                  CURLINFO info,
    115                                  void** value) const {
    116   // CURL uses "string" type for generic pointer info. Go figure.
    117   CHECK_EQ(CURLINFO_STRING, info & CURLINFO_TYPEMASK) << "Wrong option type";
    118   return curl_easy_getinfo(curl, info, value);
    119 }
    120 
    121 std::string CurlApi::EasyStrError(CURLcode code) const {
    122   return curl_easy_strerror(code);
    123 }
    124 
    125 CURLM* CurlApi::MultiInit() {
    126   return curl_multi_init();
    127 }
    128 
    129 CURLMcode CurlApi::MultiCleanup(CURLM* multi_handle) {
    130   return curl_multi_cleanup(multi_handle);
    131 }
    132 
    133 CURLMsg* CurlApi::MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) {
    134   return curl_multi_info_read(multi_handle, msgs_in_queue);
    135 }
    136 
    137 CURLMcode CurlApi::MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) {
    138   return curl_multi_add_handle(multi_handle, curl_handle);
    139 }
    140 
    141 CURLMcode CurlApi::MultiRemoveHandle(CURLM* multi_handle, CURL* curl_handle) {
    142   return curl_multi_remove_handle(multi_handle, curl_handle);
    143 }
    144 
    145 CURLMcode CurlApi::MultiSetSocketCallback(CURLM* multi_handle,
    146                                           curl_socket_callback socket_callback,
    147                                           void* userp) {
    148   CURLMcode code =
    149       curl_multi_setopt(multi_handle, CURLMOPT_SOCKETFUNCTION, socket_callback);
    150   if (code != CURLM_OK)
    151     return code;
    152   return curl_multi_setopt(multi_handle, CURLMOPT_SOCKETDATA, userp);
    153 }
    154 
    155 CURLMcode CurlApi::MultiSetTimerCallback(
    156     CURLM* multi_handle,
    157     curl_multi_timer_callback timer_callback,
    158     void* userp) {
    159   CURLMcode code =
    160       curl_multi_setopt(multi_handle, CURLMOPT_TIMERFUNCTION, timer_callback);
    161   if (code != CURLM_OK)
    162     return code;
    163   return curl_multi_setopt(multi_handle, CURLMOPT_TIMERDATA, userp);
    164 }
    165 
    166 CURLMcode CurlApi::MultiAssign(CURLM* multi_handle,
    167                                curl_socket_t sockfd,
    168                                void* sockp) {
    169   return curl_multi_assign(multi_handle, sockfd, sockp);
    170 }
    171 
    172 CURLMcode CurlApi::MultiSocketAction(CURLM* multi_handle,
    173                                      curl_socket_t s,
    174                                      int ev_bitmask,
    175                                      int* running_handles) {
    176   return curl_multi_socket_action(multi_handle, s, ev_bitmask, running_handles);
    177 }
    178 
    179 std::string CurlApi::MultiStrError(CURLMcode code) const {
    180   return curl_multi_strerror(code);
    181 }
    182 
    183 CURLMcode CurlApi::MultiPerform(CURLM* multi_handle, int* running_handles) {
    184   return curl_multi_perform(multi_handle, running_handles);
    185 }
    186 
    187 CURLMcode CurlApi::MultiWait(CURLM* multi_handle,
    188                              curl_waitfd extra_fds[],
    189                              unsigned int extra_nfds,
    190                              int timeout_ms,
    191                              int* numfds) {
    192   return curl_multi_wait(multi_handle, extra_fds, extra_nfds, timeout_ms,
    193                          numfds);
    194 }
    195 
    196 }  // namespace http
    197 }  // namespace brillo
    198