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
VerifyOptionType(CURLoption option,int expected_type)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
CurlApi()27 CurlApi::CurlApi() {
28 curl_global_init(CURL_GLOBAL_ALL);
29 }
30
~CurlApi()31 CurlApi::~CurlApi() {
32 curl_global_cleanup();
33 }
34
EasyInit()35 CURL* CurlApi::EasyInit() {
36 return curl_easy_init();
37 }
38
EasyCleanup(CURL * curl)39 void CurlApi::EasyCleanup(CURL* curl) {
40 curl_easy_cleanup(curl);
41 }
42
EasySetOptInt(CURL * curl,CURLoption option,int value)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
EasySetOptStr(CURL * curl,CURLoption option,const std::string & value)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
EasySetOptPtr(CURL * curl,CURLoption option,void * value)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
EasySetOptCallback(CURL * curl,CURLoption option,intptr_t address)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
EasySetOptOffT(CURL * curl,CURLoption option,curl_off_t value)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
EasyPerform(CURL * curl)82 CURLcode CurlApi::EasyPerform(CURL* curl) {
83 return curl_easy_perform(curl);
84 }
85
EasyGetInfoInt(CURL * curl,CURLINFO info,int * value) const86 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
EasyGetInfoDbl(CURL * curl,CURLINFO info,double * value) const95 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
EasyGetInfoStr(CURL * curl,CURLINFO info,std::string * value) const102 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
EasyGetInfoPtr(CURL * curl,CURLINFO info,void ** value) const113 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
EasyStrError(CURLcode code) const121 std::string CurlApi::EasyStrError(CURLcode code) const {
122 return curl_easy_strerror(code);
123 }
124
MultiInit()125 CURLM* CurlApi::MultiInit() {
126 return curl_multi_init();
127 }
128
MultiCleanup(CURLM * multi_handle)129 CURLMcode CurlApi::MultiCleanup(CURLM* multi_handle) {
130 return curl_multi_cleanup(multi_handle);
131 }
132
MultiInfoRead(CURLM * multi_handle,int * msgs_in_queue)133 CURLMsg* CurlApi::MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) {
134 return curl_multi_info_read(multi_handle, msgs_in_queue);
135 }
136
MultiAddHandle(CURLM * multi_handle,CURL * curl_handle)137 CURLMcode CurlApi::MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) {
138 return curl_multi_add_handle(multi_handle, curl_handle);
139 }
140
MultiRemoveHandle(CURLM * multi_handle,CURL * curl_handle)141 CURLMcode CurlApi::MultiRemoveHandle(CURLM* multi_handle, CURL* curl_handle) {
142 return curl_multi_remove_handle(multi_handle, curl_handle);
143 }
144
MultiSetSocketCallback(CURLM * multi_handle,curl_socket_callback socket_callback,void * userp)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
MultiSetTimerCallback(CURLM * multi_handle,curl_multi_timer_callback timer_callback,void * userp)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
MultiAssign(CURLM * multi_handle,curl_socket_t sockfd,void * sockp)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
MultiSocketAction(CURLM * multi_handle,curl_socket_t s,int ev_bitmask,int * running_handles)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
MultiStrError(CURLMcode code) const179 std::string CurlApi::MultiStrError(CURLMcode code) const {
180 return curl_multi_strerror(code);
181 }
182
183 } // namespace http
184 } // namespace brillo
185