]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_http_client.h
update sources to v12.1.0
[ceph.git] / ceph / src / rgw / rgw_http_client.h
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#ifndef CEPH_RGW_HTTP_CLIENT_H
5#define CEPH_RGW_HTTP_CLIENT_H
6
7#include "common/RWLock.h"
8#include "common/Cond.h"
9#include "rgw_common.h"
10#include "rgw_string.h"
11
12#include <atomic>
13
14using param_pair_t = pair<string, string>;
15using param_vec_t = vector<param_pair_t>;
16
17struct rgw_http_req_data;
18
19class RGWHTTPClient
20{
21 friend class RGWHTTPManager;
22
23 bufferlist send_bl;
24 bufferlist::iterator send_iter;
25 size_t send_len;
26 bool has_send_len;
27 long http_status;
28
29 rgw_http_req_data *req_data;
30
31 void *user_info;
32
33 string last_method;
34 string last_url;
35 bool verify_ssl; // Do not validate self signed certificates, default to false
36
37 std::atomic<unsigned> stopped { 0 };
38
39protected:
40 CephContext *cct;
41 param_vec_t headers;
42
43 int init_request(const char *method,
44 const char *url,
31f18b77
FG
45 rgw_http_req_data *req_data,
46 bool send_data_hint = false);
7c673cae
FG
47
48 virtual int receive_header(void *ptr, size_t len) {
49 return 0;
50 }
51 virtual int receive_data(void *ptr, size_t len) {
52 return 0;
53 }
54 virtual int send_data(void *ptr, size_t len) {
55 return 0;
56 }
57
58 /* Callbacks for libcurl. */
59 static size_t simple_receive_http_header(void *ptr,
60 size_t size,
61 size_t nmemb,
62 void *_info);
63 static size_t receive_http_header(void *ptr,
64 size_t size,
65 size_t nmemb,
66 void *_info);
67
68 static size_t simple_receive_http_data(void *ptr,
69 size_t size,
70 size_t nmemb,
71 void *_info);
72 static size_t receive_http_data(void *ptr,
73 size_t size,
74 size_t nmemb,
75 void *_info);
76
77 static size_t simple_send_http_data(void *ptr,
78 size_t size,
79 size_t nmemb,
80 void *_info);
81 static size_t send_http_data(void *ptr,
82 size_t size,
83 size_t nmemb,
84 void *_info);
85public:
86 static const long HTTP_STATUS_NOSTATUS = 0;
87 static const long HTTP_STATUS_UNAUTHORIZED = 401;
88 static const long HTTP_STATUS_NOTFOUND = 404;
89
90 virtual ~RGWHTTPClient();
91 explicit RGWHTTPClient(CephContext *cct)
92 : send_len(0),
93 has_send_len(false),
94 http_status(HTTP_STATUS_NOSTATUS),
95 req_data(nullptr),
96 user_info(nullptr),
31f18b77 97 verify_ssl(cct->_conf->rgw_verify_ssl),
7c673cae
FG
98 cct(cct) {
99 }
100
101 void set_user_info(void *info) {
102 user_info = info;
103 }
104
105 void *get_user_info() {
106 return user_info;
107 }
108
109 void append_header(const string& name, const string& val) {
110 headers.push_back(pair<string, string>(name, val));
111 }
112
113 void set_send_length(size_t len) {
114 send_len = len;
115 has_send_len = true;
116 }
117
118
119 long get_http_status() const {
120 return http_status;
121 }
122
123 void set_verify_ssl(bool flag) {
124 verify_ssl = flag;
125 }
126
127 int process(const char *method, const char *url);
128 int process(const char *url) { return process("GET", url); }
129
130 int wait();
131 rgw_http_req_data *get_req_data() { return req_data; }
132
133 string to_str();
134
135 int get_req_retcode();
136};
137
138
139class RGWHTTPHeadersCollector : public RGWHTTPClient {
140public:
141 typedef std::string header_name_t;
142 typedef std::string header_value_t;
143 typedef std::set<header_name_t, ltstr_nocase> header_spec_t;
144
145 RGWHTTPHeadersCollector(CephContext * const cct,
146 const header_spec_t relevant_headers)
147 : RGWHTTPClient(cct),
148 relevant_headers(relevant_headers) {
149 }
150
151 std::map<header_name_t, header_value_t, ltstr_nocase> get_headers() const {
152 return found_headers;
153 }
154
155 /* Throws std::out_of_range */
156 const header_value_t& get_header_value(const header_name_t& name) const {
157 return found_headers.at(name);
158 }
159
160protected:
161 int receive_header(void *ptr, size_t len) override;
162
163 int receive_data(void *ptr, size_t len) override {
164 return 0;
165 }
166
167 int send_data(void *ptr, size_t len) override {
168 return 0;
169 }
170
171private:
172 const std::set<header_name_t, ltstr_nocase> relevant_headers;
173 std::map<header_name_t, header_value_t, ltstr_nocase> found_headers;
174};
175
176
177class RGWHTTPTransceiver : public RGWHTTPHeadersCollector {
178 bufferlist * const read_bl;
179 std::string post_data;
180 size_t post_data_index;
181
182public:
183 RGWHTTPTransceiver(CephContext * const cct,
184 bufferlist * const read_bl,
185 const header_spec_t intercept_headers = {})
186 : RGWHTTPHeadersCollector(cct, intercept_headers),
187 read_bl(read_bl),
188 post_data_index(0) {
189 }
190
191 RGWHTTPTransceiver(CephContext * const cct,
192 bufferlist * const read_bl,
193 const bool verify_ssl,
194 const header_spec_t intercept_headers = {})
195 : RGWHTTPHeadersCollector(cct, intercept_headers),
196 read_bl(read_bl),
197 post_data_index(0) {
198 set_verify_ssl(verify_ssl);
199 }
200
201 void set_post_data(const std::string& _post_data) {
202 this->post_data = _post_data;
203 }
204
205protected:
206 int send_data(void* ptr, size_t len) override;
207
208 int receive_data(void *ptr, size_t len) override {
209 read_bl->append((char *)ptr, len);
210 return 0;
211 }
212};
213
214typedef RGWHTTPTransceiver RGWPostHTTPData;
215
216
217class RGWCompletionManager;
218
219class RGWHTTPManager {
220 CephContext *cct;
221 RGWCompletionManager *completion_mgr;
222 void *multi_handle;
223 bool is_threaded;
224 std::atomic<unsigned> going_down { 0 };
225 std::atomic<unsigned> is_stopped { 0 };
226
227 RWLock reqs_lock;
228 map<uint64_t, rgw_http_req_data *> reqs;
229 list<rgw_http_req_data *> unregistered_reqs;
230 map<uint64_t, rgw_http_req_data *> complete_reqs;
231 int64_t num_reqs;
232 int64_t max_threaded_req;
233 int thread_pipe[2];
234
235 void register_request(rgw_http_req_data *req_data);
236 void complete_request(rgw_http_req_data *req_data);
237 void _complete_request(rgw_http_req_data *req_data);
238 void unregister_request(rgw_http_req_data *req_data);
239 void _unlink_request(rgw_http_req_data *req_data);
240 void unlink_request(rgw_http_req_data *req_data);
241 void finish_request(rgw_http_req_data *req_data, int r);
242 void _finish_request(rgw_http_req_data *req_data, int r);
243 int link_request(rgw_http_req_data *req_data);
244
245 void manage_pending_requests();
246
247 class ReqsThread : public Thread {
248 RGWHTTPManager *manager;
249
250 public:
251 ReqsThread(RGWHTTPManager *_m) : manager(_m) {}
252 void *entry() override;
253 };
254
255 ReqsThread *reqs_thread;
256
257 void *reqs_thread_entry();
258
259 int signal_thread();
260
261public:
262 RGWHTTPManager(CephContext *_cct, RGWCompletionManager *completion_mgr = NULL);
263 ~RGWHTTPManager();
264
265 int set_threaded();
266 void stop();
267
31f18b77
FG
268 int add_request(RGWHTTPClient *client, const char *method, const char *url,
269 bool send_data_hint = false);
7c673cae
FG
270 int remove_request(RGWHTTPClient *client);
271
272 /* only for non threaded case */
273 int process_requests(bool wait_for_data, bool *done);
274
275 int complete_requests();
276};
277
278#endif