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