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 = {});
113 T wrapCallback(T cb)
const
115 return [t = shared_from_this(), cb = std::move(cb)](
auto... params) {
120 mutable std::mutex mutex_;
123 static std::atomic_uint ids_;
125 asio::io_context& ctx_;
126 std::unique_ptr<socket_t> socket_;
127 std::shared_ptr<asio::ssl::context> ssl_ctx_;
128 std::unique_ptr<ssl_socket_t> ssl_socket_;
130 asio::ip::tcp::endpoint endpoint_;
132 asio::streambuf write_buf_;
133 asio::streambuf read_buf_;
134 std::istream istream_;
136 asio::ip::address local_address_;
138 std::unique_ptr<asio::steady_timer> timeout_timer_;
139 std::shared_ptr<log::Logger> logger_;
140 bool checkOcsp_ {
false};
146class OPENDHT_PUBLIC Resolver
150 = std::function<void(
const asio::error_code& ec,
const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
152 Resolver(asio::io_context& ctx,
const std::string& url, std::shared_ptr<log::Logger> logger = {});
153 Resolver(asio::io_context& ctx,
154 std::string_view host,
155 std::string_view service,
156 const bool ssl =
false,
157 std::shared_ptr<log::Logger> logger = {});
160 Resolver(asio::io_context& ctx,
161 std::vector<asio::ip::tcp::endpoint> endpoints,
162 const bool ssl =
false,
163 std::shared_ptr<log::Logger> logger = {});
164 Resolver(asio::io_context& ctx,
165 const std::string& url,
166 std::vector<asio::ip::tcp::endpoint> endpoints,
167 std::shared_ptr<log::Logger> logger = {});
171 inline const Url& get_url()
const {
return url_; }
173 void add_callback(ResolverCb cb, sa_family_t family = AF_UNSPEC);
175 std::shared_ptr<log::Logger> getLogger()
const {
return logger_; }
180 void resolve(std::string_view host, std::string_view service);
182 mutable std::mutex mutex_;
185 asio::error_code ec_;
186 asio::ip::tcp::resolver resolver_;
187 std::shared_ptr<bool> destroyed_;
188 std::vector<asio::ip::tcp::endpoint> endpoints_;
190 bool completed_ {
false};
191 std::queue<ResolverCb> cbs_;
193 std::shared_ptr<log::Logger> logger_;
207class OPENDHT_PUBLIC Request :
public std::enable_shared_from_this<Request>
210 enum class State { CREATED, SENDING, HEADER_RECEIVED, RECEIVING, DONE };
211 using OnStatusCb = std::function<void(
unsigned status_code)>;
212 using OnDataCb = std::function<void(
const char* at,
size_t length)>;
213 using OnStateChangeCb = std::function<void(State state,
const Response& response)>;
214 using OnJsonCb = std::function<void(Json::Value value,
const Response& response)>;
215 using OnDoneCb = std::function<void(
const Response& response)>;
218 Request(asio::io_context& ctx,
219 const std::string& url,
220 const Json::Value& json,
222 std::shared_ptr<log::Logger> logger = {});
223 Request(asio::io_context& ctx,
const std::string& url, OnJsonCb jsoncb, std::shared_ptr<log::Logger> logger = {});
225 Request(asio::io_context& ctx,
const std::string& url, std::shared_ptr<log::Logger> logger = {});
226 Request(asio::io_context& ctx,
227 std::string_view host,
228 std::string_view service,
229 const bool ssl =
false,
230 std::shared_ptr<log::Logger> logger = {});
231 Request(asio::io_context& ctx,
const std::string& url, OnDoneCb onDone, std::shared_ptr<log::Logger> logger = {});
234 Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
235 Request(asio::io_context& ctx,
236 std::shared_ptr<Resolver> resolver,
237 const std::string& target,
238 sa_family_t family = AF_UNSPEC);
241 Request(asio::io_context& ctx,
242 std::vector<asio::ip::tcp::endpoint>&& endpoints,
243 const bool ssl =
false,
244 std::shared_ptr<log::Logger> logger = {});
248 inline unsigned int id()
const {
return id_; };
249 void set_connection(std::shared_ptr<Connection> connection);
250 std::shared_ptr<Connection> get_connection()
const;
251 inline const Url& get_url()
const {
return resolver_->get_url(); };
253 void timeout(
const std::chrono::seconds& timeout, HandlerCb cb = {})
260 std::shared_ptr<Request>
getPrevious()
const {
return prev_.lock(); }
262 inline std::string& to_string() {
return request_; }
264 void set_certificate_authority(std::shared_ptr<dht::crypto::Certificate> certificate);
265 void set_identity(
const dht::crypto::Identity& identity);
266 void set_logger(std::shared_ptr<log::Logger> logger);
272 void set_method(restinio::http_method_id_t method);
273 void set_target(std::string target);
274 void set_header_field(restinio::http_field_t field, std::string value);
275 void set_connection_type(restinio::http_connection_header_t connection);
276 void set_body(std::string body);
277 void set_body(
const uint8_t* data,
size_t length);
278 void set_auth(
const std::string& username,
const std::string& password);
280 void add_on_status_callback(OnStatusCb cb);
281 void add_on_body_callback(OnDataCb cb);
282 void add_on_state_change_callback(OnStateChangeCb cb);
283 void add_on_done_callback(OnDoneCb cb);
294 void terminate(
const asio::error_code& ec);
297 using OnCompleteCb = std::function<void()>;
301 OnStatusCb on_status;
302 OnDataCb on_header_field;
303 OnDataCb on_header_value;
305 OnStateChangeCb on_state_change;
308 static std::string getRelativePath(
const Url& origin,
const std::string& path);
310 void notify_state_change(State state);
314 static std::string url_encode(std::string_view value);
316 void init_default_headers();
322 void connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb = {});
326 void handle_request(
const asio::error_code& ec);
327 void handle_response(
const asio::error_code& ec,
size_t bytes);
329 void onHeadersComplete();
330 void onBody(
const char* at,
size_t length);
333 mutable std::mutex mutex_;
335 std::shared_ptr<log::Logger> logger_;
337 restinio::http_request_header_t header_;
338 std::map<restinio::http_field_t, std::string> headers_;
339 restinio::http_connection_header_t connection_type_ {restinio::http_connection_header_t::close};
345 dht::crypto::Identity client_identity_;
346 std::shared_ptr<dht::crypto::Certificate> server_ca_;
347 std::string service_;
351 static std::atomic_uint ids_;
352 asio::io_context& ctx_;
353 sa_family_t family_ = AF_UNSPEC;
354 std::shared_ptr<Connection> conn_;
355 std::shared_ptr<Resolver> resolver_;
357 Response response_ {};
358 std::string request_;
359 std::atomic<bool> finishing_ {
false};
360 std::unique_ptr<llhttp_t> parser_;
361 std::unique_ptr<llhttp_settings_t> parser_s_;
364 std::shared_ptr<Request> next_;
365 std::weak_ptr<Request> prev_;
366 unsigned num_redirect {0};
367 bool follow_redirect {
true};
369 HandlerCb timeoutCb_ {};
370 std::chrono::seconds timeout_ {0};