72class OPENDHT_PUBLIC Connection :
public std::enable_shared_from_this<Connection>
75 Connection(asio::io_context& ctx,
const bool ssl =
true, std::shared_ptr<log::Logger> l = {});
76 Connection(asio::io_context& ctx,
77 std::shared_ptr<dht::crypto::Certificate> server_ca,
78 const dht::crypto::Identity& identity,
79 std::shared_ptr<log::Logger> l = {});
82 inline unsigned int id()
const {
return id_; };
85 void checkOcsp(
bool check =
true) { checkOcsp_ = check; }
87 void set_ssl_verification(
const std::string& hostname,
const asio::ssl::verify_mode verify_mode);
89 asio::streambuf& input();
90 std::istream& data() {
return istream_; }
92 std::string read_bytes(
size_t bytes = 0);
93 std::string read_until(
const char delim);
95 void async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb);
96 void async_handshake(HandlerCb cb);
97 void async_write(BytesHandlerCb cb);
98 void async_read_until(
const char* delim, BytesHandlerCb cb);
99 void async_read_until(
char delim, BytesHandlerCb cb);
100 void async_read(
size_t bytes, BytesHandlerCb cb);
101 void async_read_some(
size_t bytes, BytesHandlerCb cb);
103 void set_keepalive(uint32_t seconds);
105 const asio::ip::address& local_address()
const;
107 void timeout(
const std::chrono::seconds& timeout, HandlerCb cb = {});
120 T wrapCallback(T cb)
const
122 return [t = shared_from_this(), cb = std::move(cb)](
auto... params) {
127 mutable std::mutex mutex_;
130 static std::atomic_uint ids_;
132 asio::io_context& ctx_;
133 std::unique_ptr<socket_t> socket_;
134 std::shared_ptr<asio::ssl::context> ssl_ctx_;
135 std::unique_ptr<ssl_socket_t> ssl_socket_;
137 asio::ip::tcp::endpoint endpoint_;
139 asio::streambuf write_buf_;
140 asio::streambuf read_buf_;
141 std::istream istream_;
143 asio::ip::address local_address_;
145 std::unique_ptr<asio::steady_timer> timeout_timer_;
146 std::shared_ptr<log::Logger> logger_;
147 bool checkOcsp_ {
false};
153class OPENDHT_PUBLIC Resolver
157 = std::function<void(
const asio::error_code& ec,
const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
159 Resolver(asio::io_context& ctx, std::string url, std::shared_ptr<log::Logger> logger = {});
160 Resolver(asio::io_context& ctx,
161 std::string_view host,
162 std::string_view service,
163 const bool ssl =
false,
164 std::shared_ptr<log::Logger> logger = {});
167 Resolver(asio::io_context& ctx,
168 std::vector<asio::ip::tcp::endpoint> endpoints,
169 const bool ssl =
false,
170 std::shared_ptr<log::Logger> logger = {});
174 inline const Url& get_url()
const {
return url_; }
176 void add_callback(ResolverCb cb, sa_family_t family = AF_UNSPEC);
178 std::shared_ptr<log::Logger> getLogger()
const {
return logger_; }
183 void resolve(std::string_view host, std::string_view service);
185 mutable std::mutex mutex_;
188 asio::error_code ec_;
189 asio::ip::tcp::resolver resolver_;
190 std::shared_ptr<bool> destroyed_;
191 std::vector<asio::ip::tcp::endpoint> endpoints_;
193 bool completed_ {
false};
194 std::queue<ResolverCb> cbs_;
196 std::shared_ptr<log::Logger> logger_;
210class OPENDHT_PUBLIC Request :
public std::enable_shared_from_this<Request>
213 enum class State { CREATED, SENDING, HEADER_RECEIVED, RECEIVING, DONE };
214 using OnStatusCb = std::function<void(
unsigned status_code)>;
215 using OnDataCb = std::function<void(
const char* at,
size_t length)>;
216 using OnStateChangeCb = std::function<void(State state,
const Response& response)>;
217 using OnJsonCb = std::function<void(Json::Value value,
const Response& response)>;
218 using OnDoneCb = std::function<void(
const Response& response)>;
221 Request(asio::io_context& ctx,
223 const Json::Value& json,
225 std::shared_ptr<log::Logger> logger = {});
226 Request(asio::io_context& ctx, std::string url, OnJsonCb jsoncb, std::shared_ptr<log::Logger> logger = {});
228 Request(asio::io_context& ctx, std::string url, std::shared_ptr<log::Logger> logger = {});
229 Request(asio::io_context& ctx,
230 std::string_view host,
231 std::string_view service,
232 const bool ssl =
false,
233 std::shared_ptr<log::Logger> logger = {});
234 Request(asio::io_context& ctx, std::string url, OnDoneCb onDone, std::shared_ptr<log::Logger> logger = {});
237 Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
238 Request(asio::io_context& ctx,
239 std::shared_ptr<Resolver> resolver,
240 const std::string& target,
241 sa_family_t family = AF_UNSPEC);
244 Request(asio::io_context& ctx,
245 std::vector<asio::ip::tcp::endpoint>&& endpoints,
246 const bool ssl =
false,
247 std::shared_ptr<log::Logger> logger = {});
251 inline unsigned int id()
const {
return id_; };
252 void set_connection(std::shared_ptr<Connection> connection);
253 std::shared_ptr<Connection> get_connection()
const;
254 inline const Url& get_url()
const {
return resolver_->get_url(); };
256 void timeout(
const std::chrono::seconds& timeout, HandlerCb cb = {})
263 std::shared_ptr<Request>
getPrevious()
const {
return prev_.lock(); }
265 inline std::string& to_string() {
return request_; }
267 void set_certificate_authority(std::shared_ptr<dht::crypto::Certificate> certificate);
268 void set_identity(
const dht::crypto::Identity& identity);
269 void set_logger(std::shared_ptr<log::Logger> logger);
275 void set_method(restinio::http_method_id_t method);
276 void set_target(std::string target);
277 void set_header_field(restinio::http_field_t field, std::string value);
278 void set_connection_type(restinio::http_connection_header_t connection);
279 void set_body(std::string body);
280 void set_body(
const uint8_t* data,
size_t length);
281 void set_auth(
const std::string& username,
const std::string& password);
283 void add_on_status_callback(OnStatusCb cb);
284 void add_on_body_callback(OnDataCb cb);
285 void add_on_state_change_callback(OnStateChangeCb cb);
286 void add_on_done_callback(OnDoneCb cb);
297 void terminate(
const asio::error_code& ec);
300 using OnCompleteCb = std::function<void()>;
304 OnStatusCb on_status;
305 OnDataCb on_header_field;
306 OnDataCb on_header_value;
308 OnStateChangeCb on_state_change;
311 static std::string getRelativePath(
const Url& origin,
const std::string& path);
313 void notify_state_change(State state);
317 static std::string url_encode(std::string_view value);
319 void init_default_headers();
325 void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
329 void handle_request(
const asio::error_code& ec);
330 void handle_response(
const asio::error_code& ec,
size_t bytes);
332 void onHeadersComplete();
333 void onBody(
const char* at,
size_t length);
336 mutable std::mutex mutex_;
338 std::shared_ptr<log::Logger> logger_;
340 restinio::http_request_header_t header_;
341 std::map<restinio::http_field_t, std::string> headers_;
342 restinio::http_connection_header_t connection_type_ {restinio::http_connection_header_t::close};
348 dht::crypto::Identity client_identity_;
349 std::shared_ptr<dht::crypto::Certificate> server_ca_;
352 static std::atomic_uint ids_;
353 asio::io_context& ctx_;
354 sa_family_t family_ = AF_UNSPEC;
355 std::shared_ptr<Connection> conn_;
356 std::shared_ptr<Resolver> resolver_;
358 Response response_ {};
359 std::string request_;
360 std::atomic<bool> finishing_ {
false};
361 std::unique_ptr<llhttp_t> parser_;
362 std::unique_ptr<llhttp_settings_t> parser_s_;
365 std::shared_ptr<Request> next_;
366 std::weak_ptr<Request> prev_;
367 unsigned num_redirect {0};
368 bool follow_redirect {
true};
370 HandlerCb timeoutCb_ {};
371 std::chrono::seconds timeout_ {0};