]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_http_client.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_http_client.h
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae
FG
3
4#ifndef CEPH_RGW_HTTP_CLIENT_H
5#define CEPH_RGW_HTTP_CLIENT_H
6
eafe8130 7#include "common/async/yield_context.h"
7c673cae
FG
8#include "common/Cond.h"
9#include "rgw_common.h"
10#include "rgw_string.h"
9f95a23c 11#include "rgw_http_client_types.h"
7c673cae
FG
12
13#include <atomic>
14
20effc67
TL
15using param_pair_t = std::pair<std::string, std::string>;
16using param_vec_t = std::vector<param_pair_t>;
7c673cae 17
11fdf7f2
TL
18void rgw_http_client_init(CephContext *cct);
19void rgw_http_client_cleanup();
20
7c673cae 21struct rgw_http_req_data;
11fdf7f2
TL
22class RGWHTTPManager;
23
20effc67
TL
24class RGWHTTPClient : public RGWIOProvider,
25 public NoDoutPrefix
7c673cae
FG
26{
27 friend class RGWHTTPManager;
28
29 bufferlist send_bl;
30 bufferlist::iterator send_iter;
7c673cae
FG
31 bool has_send_len;
32 long http_status;
11fdf7f2
TL
33 bool send_data_hint{false};
34 size_t receive_pause_skip{0}; /* how many bytes to skip next time receive_data is called
35 due to being paused */
7c673cae 36
11fdf7f2 37 void *user_info{nullptr};
7c673cae 38
11fdf7f2 39 rgw_http_req_data *req_data;
7c673cae 40
7c673cae
FG
41 bool verify_ssl; // Do not validate self signed certificates, default to false
42
20effc67 43 std::string ca_path;
522d829b 44
20effc67 45 std::string client_cert;
522d829b 46
20effc67 47 std::string client_key;
522d829b 48
7c673cae
FG
49 std::atomic<unsigned> stopped { 0 };
50
11fdf7f2 51
7c673cae
FG
52protected:
53 CephContext *cct;
11fdf7f2 54
20effc67
TL
55 std::string method;
56 std::string url;
57
58 std::string protocol;
59 std::string host;
60 std::string resource_prefix;
11fdf7f2
TL
61
62 size_t send_len{0};
63
7c673cae
FG
64 param_vec_t headers;
65
f67539c2
TL
66 long req_timeout{0L};
67
20effc67
TL
68 void init();
69
11fdf7f2
TL
70 RGWHTTPManager *get_manager();
71
72 int init_request(rgw_http_req_data *req_data);
7c673cae
FG
73
74 virtual int receive_header(void *ptr, size_t len) {
75 return 0;
76 }
11fdf7f2 77 virtual int receive_data(void *ptr, size_t len, bool *pause) {
7c673cae
FG
78 return 0;
79 }
11fdf7f2
TL
80
81 virtual int send_data(void *ptr, size_t len, bool *pause=nullptr) {
7c673cae
FG
82 return 0;
83 }
84
85 /* Callbacks for libcurl. */
7c673cae
FG
86 static size_t receive_http_header(void *ptr,
87 size_t size,
88 size_t nmemb,
89 void *_info);
90
7c673cae
FG
91 static size_t receive_http_data(void *ptr,
92 size_t size,
93 size_t nmemb,
94 void *_info);
95
7c673cae
FG
96 static size_t send_http_data(void *ptr,
97 size_t size,
98 size_t nmemb,
99 void *_info);
11fdf7f2 100
9f95a23c 101 ceph::mutex& get_req_lock();
11fdf7f2
TL
102
103 /* needs to be called under req_lock() */
104 void _set_write_paused(bool pause);
105 void _set_read_paused(bool pause);
7c673cae
FG
106public:
107 static const long HTTP_STATUS_NOSTATUS = 0;
108 static const long HTTP_STATUS_UNAUTHORIZED = 401;
109 static const long HTTP_STATUS_NOTFOUND = 404;
110
11fdf7f2
TL
111 static constexpr int HTTPCLIENT_IO_READ = 0x1;
112 static constexpr int HTTPCLIENT_IO_WRITE = 0x2;
113 static constexpr int HTTPCLIENT_IO_CONTROL = 0x4;
114
7c673cae 115 virtual ~RGWHTTPClient();
11fdf7f2 116 explicit RGWHTTPClient(CephContext *cct,
20effc67
TL
117 const std::string& _method,
118 const std::string& _url);
119
120 std::ostream& gen_prefix(std::ostream& out) const override;
121
7c673cae 122
20effc67
TL
123 void append_header(const std::string& name, const std::string& val) {
124 headers.push_back(std::pair<std::string, std::string>(name, val));
7c673cae
FG
125 }
126
127 void set_send_length(size_t len) {
128 send_len = len;
129 has_send_len = true;
130 }
131
11fdf7f2
TL
132 void set_send_data_hint(bool hint) {
133 send_data_hint = hint;
134 }
7c673cae
FG
135
136 long get_http_status() const {
137 return http_status;
138 }
139
9f95a23c
TL
140 void set_http_status(long _http_status) {
141 http_status = _http_status;
142 }
143
7c673cae
FG
144 void set_verify_ssl(bool flag) {
145 verify_ssl = flag;
146 }
147
f67539c2
TL
148 // set request timeout in seconds
149 // zero (default) mean that request will never timeout
150 void set_req_timeout(long timeout) {
151 req_timeout = timeout;
152 }
153
9f95a23c 154 int process(optional_yield y);
7c673cae 155
9f95a23c 156 int wait(optional_yield y);
11fdf7f2
TL
157 void cancel();
158 bool is_done();
159
7c673cae
FG
160 rgw_http_req_data *get_req_data() { return req_data; }
161
20effc67 162 std::string to_str();
7c673cae
FG
163
164 int get_req_retcode();
11fdf7f2 165
20effc67 166 void set_url(const std::string& _url) {
11fdf7f2
TL
167 url = _url;
168 }
169
20effc67 170 void set_method(const std::string& _method) {
11fdf7f2
TL
171 method = _method;
172 }
173
174 void set_io_user_info(void *_user_info) override {
175 user_info = _user_info;
176 }
177
178 void *get_io_user_info() override {
179 return user_info;
180 }
522d829b 181
20effc67 182 void set_ca_path(const std::string& _ca_path) {
522d829b
TL
183 ca_path = _ca_path;
184 }
185
20effc67 186 void set_client_cert(const std::string& _client_cert) {
522d829b
TL
187 client_cert = _client_cert;
188 }
189
20effc67 190 void set_client_key(const std::string& _client_key) {
522d829b
TL
191 client_key = _client_key;
192 }
7c673cae
FG
193};
194
195
196class RGWHTTPHeadersCollector : public RGWHTTPClient {
197public:
198 typedef std::string header_name_t;
199 typedef std::string header_value_t;
200 typedef std::set<header_name_t, ltstr_nocase> header_spec_t;
201
202 RGWHTTPHeadersCollector(CephContext * const cct,
20effc67
TL
203 const std::string& method,
204 const std::string& url,
11fdf7f2
TL
205 const header_spec_t &relevant_headers)
206 : RGWHTTPClient(cct, method, url),
7c673cae
FG
207 relevant_headers(relevant_headers) {
208 }
209
210 std::map<header_name_t, header_value_t, ltstr_nocase> get_headers() const {
211 return found_headers;
212 }
213
214 /* Throws std::out_of_range */
215 const header_value_t& get_header_value(const header_name_t& name) const {
216 return found_headers.at(name);
217 }
218
219protected:
220 int receive_header(void *ptr, size_t len) override;
221
7c673cae
FG
222private:
223 const std::set<header_name_t, ltstr_nocase> relevant_headers;
224 std::map<header_name_t, header_value_t, ltstr_nocase> found_headers;
225};
226
227
228class RGWHTTPTransceiver : public RGWHTTPHeadersCollector {
229 bufferlist * const read_bl;
230 std::string post_data;
231 size_t post_data_index;
232
233public:
234 RGWHTTPTransceiver(CephContext * const cct,
20effc67
TL
235 const std::string& method,
236 const std::string& url,
7c673cae
FG
237 bufferlist * const read_bl,
238 const header_spec_t intercept_headers = {})
11fdf7f2 239 : RGWHTTPHeadersCollector(cct, method, url, intercept_headers),
7c673cae
FG
240 read_bl(read_bl),
241 post_data_index(0) {
242 }
243
244 RGWHTTPTransceiver(CephContext * const cct,
20effc67
TL
245 const std::string& method,
246 const std::string& url,
7c673cae
FG
247 bufferlist * const read_bl,
248 const bool verify_ssl,
249 const header_spec_t intercept_headers = {})
11fdf7f2 250 : RGWHTTPHeadersCollector(cct, method, url, intercept_headers),
7c673cae
FG
251 read_bl(read_bl),
252 post_data_index(0) {
253 set_verify_ssl(verify_ssl);
254 }
255
256 void set_post_data(const std::string& _post_data) {
257 this->post_data = _post_data;
258 }
259
260protected:
11fdf7f2 261 int send_data(void* ptr, size_t len, bool *pause=nullptr) override;
7c673cae 262
11fdf7f2 263 int receive_data(void *ptr, size_t len, bool *pause) override {
7c673cae
FG
264 read_bl->append((char *)ptr, len);
265 return 0;
266 }
267};
268
269typedef RGWHTTPTransceiver RGWPostHTTPData;
270
271
272class RGWCompletionManager;
273
11fdf7f2
TL
274enum RGWHTTPRequestSetState {
275 SET_NOP = 0,
276 SET_WRITE_PAUSED = 1,
277 SET_WRITE_RESUME = 2,
278 SET_READ_PAUSED = 3,
279 SET_READ_RESUME = 4,
280};
281
7c673cae 282class RGWHTTPManager {
11fdf7f2
TL
283 struct set_state {
284 rgw_http_req_data *req;
285 int bitmask;
286
287 set_state(rgw_http_req_data *_req, int _bitmask) : req(_req), bitmask(_bitmask) {}
288 };
7c673cae
FG
289 CephContext *cct;
290 RGWCompletionManager *completion_mgr;
291 void *multi_handle;
9f95a23c 292 bool is_started = false;
7c673cae
FG
293 std::atomic<unsigned> going_down { 0 };
294 std::atomic<unsigned> is_stopped { 0 };
295
9f95a23c 296 ceph::shared_mutex reqs_lock = ceph::make_shared_mutex("RGWHTTPManager::reqs_lock");
20effc67
TL
297 std::map<uint64_t, rgw_http_req_data *> reqs;
298 std::list<rgw_http_req_data *> unregistered_reqs;
299 std::list<set_state> reqs_change_state;
300 std::map<uint64_t, rgw_http_req_data *> complete_reqs;
9f95a23c
TL
301 int64_t num_reqs = 0;
302 int64_t max_threaded_req = 0;
7c673cae
FG
303 int thread_pipe[2];
304
305 void register_request(rgw_http_req_data *req_data);
306 void complete_request(rgw_http_req_data *req_data);
307 void _complete_request(rgw_http_req_data *req_data);
11fdf7f2 308 bool unregister_request(rgw_http_req_data *req_data);
7c673cae
FG
309 void _unlink_request(rgw_http_req_data *req_data);
310 void unlink_request(rgw_http_req_data *req_data);
9f95a23c 311 void finish_request(rgw_http_req_data *req_data, int r, long http_status = -1);
7c673cae 312 void _finish_request(rgw_http_req_data *req_data, int r);
11fdf7f2 313 void _set_req_state(set_state& ss);
7c673cae
FG
314 int link_request(rgw_http_req_data *req_data);
315
316 void manage_pending_requests();
317
318 class ReqsThread : public Thread {
319 RGWHTTPManager *manager;
320
321 public:
11fdf7f2 322 explicit ReqsThread(RGWHTTPManager *_m) : manager(_m) {}
7c673cae
FG
323 void *entry() override;
324 };
325
9f95a23c 326 ReqsThread *reqs_thread = nullptr;
7c673cae
FG
327
328 void *reqs_thread_entry();
329
330 int signal_thread();
331
332public:
333 RGWHTTPManager(CephContext *_cct, RGWCompletionManager *completion_mgr = NULL);
334 ~RGWHTTPManager();
335
11fdf7f2 336 int start();
7c673cae
FG
337 void stop();
338
11fdf7f2 339 int add_request(RGWHTTPClient *client);
7c673cae 340 int remove_request(RGWHTTPClient *client);
11fdf7f2 341 int set_request_state(RGWHTTPClient *client, RGWHTTPRequestSetState state);
7c673cae
FG
342};
343
11fdf7f2
TL
344class RGWHTTP
345{
346public:
347 static int send(RGWHTTPClient *req);
9f95a23c 348 static int process(RGWHTTPClient *req, optional_yield y);
11fdf7f2 349};
7c673cae 350#endif