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 #ifndef LIBBRILLO_BRILLO_HTTP_CURL_API_H_
6 #define LIBBRILLO_BRILLO_HTTP_CURL_API_H_
7 
8 #include <curl/curl.h>
9 
10 #include <string>
11 
12 #include <base/macros.h>
13 #include <brillo/brillo_export.h>
14 
15 namespace brillo {
16 namespace http {
17 
18 // Abstract wrapper around libcurl C API that allows us to mock it out in tests.
19 class CurlInterface {
20  public:
21   CurlInterface() = default;
22   virtual ~CurlInterface() = default;
23 
24   // Wrapper around curl_easy_init().
25   virtual CURL* EasyInit() = 0;
26 
27   // Wrapper around curl_easy_cleanup().
28   virtual void EasyCleanup(CURL* curl) = 0;
29 
30   // Wrappers around curl_easy_setopt().
31   virtual CURLcode EasySetOptInt(CURL* curl, CURLoption option, int value) = 0;
32   virtual CURLcode EasySetOptStr(CURL* curl,
33                                  CURLoption option,
34                                  const std::string& value) = 0;
35   virtual CURLcode EasySetOptPtr(CURL* curl,
36                                  CURLoption option,
37                                  void* value) = 0;
38   virtual CURLcode EasySetOptCallback(CURL* curl,
39                                       CURLoption option,
40                                       intptr_t address) = 0;
41   virtual CURLcode EasySetOptOffT(CURL* curl,
42                                   CURLoption option,
43                                   curl_off_t value) = 0;
44 
45   // A type-safe wrapper around function callback options.
46   template<typename R, typename... Args>
EasySetOptCallback(CURL * curl,CURLoption option,R (* callback)(Args...))47   inline CURLcode EasySetOptCallback(CURL* curl,
48                                      CURLoption option,
49                                      R(*callback)(Args...)) {
50     return EasySetOptCallback(
51         curl, option, reinterpret_cast<intptr_t>(callback));
52   }
53 
54   // Wrapper around curl_easy_perform().
55   virtual CURLcode EasyPerform(CURL* curl) = 0;
56 
57   // Wrappers around curl_easy_getinfo().
58   virtual CURLcode EasyGetInfoInt(CURL* curl,
59                                   CURLINFO info,
60                                   int* value) const = 0;
61   virtual CURLcode EasyGetInfoDbl(CURL* curl,
62                                   CURLINFO info,
63                                   double* value) const = 0;
64   virtual CURLcode EasyGetInfoStr(CURL* curl,
65                                   CURLINFO info,
66                                   std::string* value) const = 0;
67   virtual CURLcode EasyGetInfoPtr(CURL* curl,
68                                   CURLINFO info,
69                                   void** value) const = 0;
70 
71   // Wrapper around curl_easy_strerror().
72   virtual std::string EasyStrError(CURLcode code) const = 0;
73 
74   // Wrapper around curl_multi_init().
75   virtual CURLM* MultiInit() = 0;
76 
77   // Wrapper around curl_multi_cleanup().
78   virtual CURLMcode MultiCleanup(CURLM* multi_handle) = 0;
79 
80   // Wrapper around curl_multi_info_read().
81   virtual CURLMsg* MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) = 0;
82 
83   // Wrapper around curl_multi_add_handle().
84   virtual CURLMcode MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) = 0;
85 
86   // Wrapper around curl_multi_remove_handle().
87   virtual CURLMcode MultiRemoveHandle(CURLM* multi_handle,
88                                       CURL* curl_handle) = 0;
89 
90   // Wrapper around curl_multi_setopt(CURLMOPT_SOCKETFUNCTION/SOCKETDATA).
91   virtual CURLMcode MultiSetSocketCallback(
92       CURLM* multi_handle,
93       curl_socket_callback socket_callback,
94       void* userp) = 0;
95 
96   // Wrapper around curl_multi_setopt(CURLMOPT_TIMERFUNCTION/TIMERDATA).
97   virtual CURLMcode MultiSetTimerCallback(
98       CURLM* multi_handle,
99       curl_multi_timer_callback timer_callback,
100       void* userp) = 0;
101 
102   // Wrapper around curl_multi_assign().
103   virtual CURLMcode MultiAssign(CURLM* multi_handle,
104                                 curl_socket_t sockfd,
105                                 void* sockp) = 0;
106 
107   // Wrapper around curl_multi_socket_action().
108   virtual CURLMcode MultiSocketAction(CURLM* multi_handle,
109                                       curl_socket_t s,
110                                       int ev_bitmask,
111                                       int* running_handles) = 0;
112 
113   // Wrapper around curl_multi_strerror().
114   virtual std::string MultiStrError(CURLMcode code) const = 0;
115 
116  private:
117   DISALLOW_COPY_AND_ASSIGN(CurlInterface);
118 };
119 
120 class BRILLO_EXPORT CurlApi : public CurlInterface {
121  public:
122   CurlApi();
123   ~CurlApi() override;
124 
125   // Wrapper around curl_easy_init().
126   CURL* EasyInit() override;
127 
128   // Wrapper around curl_easy_cleanup().
129   void EasyCleanup(CURL* curl) override;
130 
131   // Wrappers around curl_easy_setopt().
132   CURLcode EasySetOptInt(CURL* curl, CURLoption option, int value) override;
133   CURLcode EasySetOptStr(CURL* curl,
134                          CURLoption option,
135                          const std::string& value) override;
136   CURLcode EasySetOptPtr(CURL* curl, CURLoption option, void* value) override;
137   CURLcode EasySetOptCallback(CURL* curl,
138                               CURLoption option,
139                               intptr_t address) override;
140   CURLcode EasySetOptOffT(CURL* curl,
141                           CURLoption option,
142                           curl_off_t value) override;
143 
144   // Wrapper around curl_easy_perform().
145   CURLcode EasyPerform(CURL* curl) override;
146 
147   // Wrappers around curl_easy_getinfo().
148   CURLcode EasyGetInfoInt(CURL* curl, CURLINFO info, int* value) const override;
149   CURLcode EasyGetInfoDbl(CURL* curl,
150                           CURLINFO info,
151                           double* value) const override;
152   CURLcode EasyGetInfoStr(CURL* curl,
153                           CURLINFO info,
154                           std::string* value) const override;
155   CURLcode EasyGetInfoPtr(CURL* curl,
156                           CURLINFO info,
157                           void** value) const override;
158 
159   // Wrapper around curl_easy_strerror().
160   std::string EasyStrError(CURLcode code) const override;
161 
162   // Wrapper around curl_multi_init().
163   CURLM* MultiInit() override;
164 
165   // Wrapper around curl_multi_cleanup().
166   CURLMcode MultiCleanup(CURLM* multi_handle) override;
167 
168   // Wrapper around curl_multi_info_read().
169   CURLMsg* MultiInfoRead(CURLM* multi_handle, int* msgs_in_queue) override;
170 
171   // Wrapper around curl_multi_add_handle().
172   CURLMcode MultiAddHandle(CURLM* multi_handle, CURL* curl_handle) override;
173 
174   // Wrapper around curl_multi_remove_handle().
175   CURLMcode MultiRemoveHandle(CURLM* multi_handle, CURL* curl_handle) override;
176 
177   // Wrapper around curl_multi_setopt(CURLMOPT_SOCKETFUNCTION/SOCKETDATA).
178   CURLMcode MultiSetSocketCallback(
179       CURLM* multi_handle,
180       curl_socket_callback socket_callback,
181       void* userp) override;
182 
183   // Wrapper around curl_multi_setopt(CURLMOPT_TIMERFUNCTION/TIMERDATA).
184   CURLMcode MultiSetTimerCallback(
185       CURLM* multi_handle,
186       curl_multi_timer_callback timer_callback,
187       void* userp) override;
188 
189   // Wrapper around curl_multi_assign().
190   CURLMcode MultiAssign(CURLM* multi_handle,
191                         curl_socket_t sockfd,
192                         void* sockp) override;
193 
194   // Wrapper around curl_multi_socket_action().
195   CURLMcode MultiSocketAction(CURLM* multi_handle,
196                               curl_socket_t s,
197                               int ev_bitmask,
198                               int* running_handles) override;
199 
200   // Wrapper around curl_multi_strerror().
201   std::string MultiStrError(CURLMcode code) const override;
202 
203  private:
204   DISALLOW_COPY_AND_ASSIGN(CurlApi);
205 };
206 
207 }  // namespace http
208 }  // namespace brillo
209 
210 #endif  // LIBBRILLO_BRILLO_HTTP_CURL_API_H_
211