90 const std::shared_ptr<log::Logger>& logger = {});
92 virtual ~DhtProxyServer();
94 DhtProxyServer(
const DhtProxyServer& other) =
delete;
95 DhtProxyServer(DhtProxyServer&& other) =
delete;
96 DhtProxyServer& operator=(
const DhtProxyServer& other) =
delete;
97 DhtProxyServer& operator=(DhtProxyServer&& other) =
delete;
99 asio::io_context& io_context()
const;
115 std::string toString()
const {
116 std::ostringstream ss;
117 ss <<
"Listens: " << listenCount <<
" Puts: " << putCount <<
" PushListeners: " << pushListenersCount << std::endl;
118 ss <<
"Requests: " << requestRate <<
" per second." << std::endl;
120 auto& ipv4 = nodeInfo->ipv4;
121 if (ipv4.table_depth > 1)
122 ss <<
"IPv4 Network estimation: " << ipv4.getNetworkSizeEstimation() << std::endl;;
123 auto& ipv6 = nodeInfo->ipv6;
124 if (ipv6.table_depth > 1)
125 ss <<
"IPv6 Network estimation: " << ipv6.getNetworkSizeEstimation() << std::endl;;
135 result[
"listenCount"] =
static_cast<Json::UInt64
>(
listenCount);
136 result[
"putCount"] =
static_cast<Json::UInt64
>(
putCount);
141 result[
"nodeInfo"] =
nodeInfo->toJson();
146 std::shared_ptr<ServerStats> stats()
const {
return stats_; }
148 std::shared_ptr<ServerStats> updateStats(std::shared_ptr<NodeInfo> info)
const;
150 std::shared_ptr<DhtRunner> getNode()
const {
return dht_; }
153 class ConnectionListener;
154 struct RestRouterTraitsTls;
155 struct RestRouterTraits;
157 template <
typename HttpResponse>
158 static HttpResponse initHttpResponse(HttpResponse response);
159 static restinio::request_handling_status_t serverError(restinio::request_t& request);
161 template<
typename ServerSettings >
162 void addServerSettings(ServerSettings& serverSettings,
163 const unsigned int max_pipelined_requests = 16);
165 std::unique_ptr<RestRouter> createRestRouter();
167 void onConnectionClosed(restinio::connection_id_t);
176 RequestStatus getNodeInfo(restinio::request_handle_t request,
177 restinio::router::route_params_t params)
const;
185 RequestStatus getStats(restinio::request_handle_t request,
186 restinio::router::route_params_t params);
198 RequestStatus get(restinio::request_handle_t request,
199 restinio::router::route_params_t params);
211 RequestStatus listen(restinio::request_handle_t request,
212 restinio::router::route_params_t params);
223 RequestStatus put(restinio::request_handle_t request,
224 restinio::router::route_params_t params);
226 void handleCancelPermamentPut(
const asio::error_code &ec,
const InfoHash& key, Value::Id vid);
228#ifdef OPENDHT_PROXY_SERVER_IDENTITY
238 RequestStatus putSigned(restinio::request_handle_t request,
239 restinio::router::route_params_t params)
const;
250 RequestStatus putEncrypted(restinio::request_handle_t request,
251 restinio::router::route_params_t params);
265 RequestStatus getFiltered(restinio::request_handle_t request,
266 restinio::router::route_params_t params);
275 RequestStatus options(restinio::request_handle_t request,
276 restinio::router::route_params_t params);
278 struct PushSessionContext {
280 std::string sessionId;
281 PushSessionContext(
const std::string&
id) : sessionId(id) {}
284#ifdef OPENDHT_PUSH_NOTIFICATIONS
285 PushType getTypeFromString(
const std::string& type);
286 std::string getDefaultTopic(PushType type);
288 RequestStatus pingPush(restinio::request_handle_t request,
289 restinio::router::route_params_t );
299 RequestStatus subscribe(restinio::request_handle_t request,
300 restinio::router::route_params_t params);
309 RequestStatus unsubscribe(restinio::request_handle_t request,
310 restinio::router::route_params_t params);
317 void sendPushNotification(
const std::string& key, Json::Value&& json, PushType type,
bool highPriority,
const std::string& topic);
327 void handleNotifyPushListenExpire(
const asio::error_code &ec,
const std::string pushToken,
328 std::function<Json::Value()> json, PushType type,
const std::string& topic);
337 void handleCancelPushListen(
const asio::error_code &ec,
const std::string pushToken,
338 const InfoHash key,
const std::string clientId);
353 bool handlePushListen(
const InfoHash& infoHash,
const std::string& pushToken,
354 PushType type,
const std::string& clientId,
355 const std::shared_ptr<DhtProxyServer::PushSessionContext>& sessionCtx,
const std::string& topic,
356 const std::vector<std::shared_ptr<Value>>& values,
bool expired);
360 void handlePrintStats(
const asio::error_code &ec);
363 template <
typename Os>
364 void saveState(Os& stream);
366 template <
typename Is>
367 void loadState(Is& is,
size_t size);
369 using clock = std::chrono::steady_clock;
370 using time_point = clock::time_point;
372 std::shared_ptr<asio::io_context> ioContext_;
373 std::shared_ptr<DhtRunner> dht_;
374 Json::StreamWriterBuilder jsonBuilder_;
375 Json::CharReaderBuilder jsonReaderBuilder_;
376 std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
378 std::string persistPath_;
381 std::thread serverThread_;
382 std::unique_ptr<restinio::http_server_t<RestRouterTraitsTls>> httpsServer_;
383 std::unique_ptr<restinio::http_server_t<RestRouterTraits>> httpServer_;
386 std::pair<std::string, std::string> pushHostPort_;
388 mutable std::mutex requestLock_;
389 std::map<
unsigned int , std::shared_ptr<http::Request>> requests_;
391 std::shared_ptr<log::Logger> logger_;
393 std::shared_ptr<ServerStats> stats_;
394 std::shared_ptr<NodeInfo> nodeInfo_ {};
395 std::unique_ptr<asio::steady_timer> printStatsTimer_;
398 std::mutex lockListener_;
400 std::map<restinio::connection_id_t, http::ListenerSession> listeners_;
402 std::shared_ptr<ConnectionListener> connListener_;
403 struct PermanentPut {
404 time_point expiration;
405 std::string pushToken;
406 std::string clientId;
407 std::shared_ptr<PushSessionContext> sessionCtx;
408 std::unique_ptr<asio::steady_timer> expireTimer;
409 std::unique_ptr<asio::steady_timer> expireNotifyTimer;
414 template <
typename Packer>
415 void msgpack_pack(Packer& p)
const
417 p.pack_map(2 + (sessionCtx ? 1 : 0) + (clientId.empty() ? 0 : 1) + (type == PushType::None ? 0 : 2) + (topic.empty() ? 0 : 1));
418 p.pack(
"value"); p.pack(value);
419 p.pack(
"exp"); p.pack(to_time_t(expiration));
420 if (not clientId.empty()) {
421 p.pack(
"cid"); p.pack(clientId);
424 std::lock_guard<std::mutex> l(sessionCtx->lock);
425 p.pack(
"sid"); p.pack(sessionCtx->sessionId);
427 if (type != PushType::None) {
428 p.pack(
"t"); p.pack(type);
429 p.pack(
"token"); p.pack(pushToken);
431 if (not topic.empty()) {
432 p.pack(
"top"); p.pack(topic);
436 void msgpack_unpack(
const msgpack::object& o);
439 std::map<dht::Value::Id, PermanentPut> puts;
440 MSGPACK_DEFINE_ARRAY(puts)
442 std::mutex lockSearchPuts_;
443 std::map<InfoHash, SearchPuts> puts_;
445 mutable std::atomic<size_t> requestNum_ {0};
446 mutable std::atomic<time_point> lastStatsReset_ {time_point::min()};
448 std::string pushServer_;
449 std::string bundleId_;
451#ifdef OPENDHT_PUSH_NOTIFICATIONS
453 time_point expiration;
454 std::string clientId;
455 std::shared_ptr<PushSessionContext> sessionCtx;
456 std::future<size_t> internalToken;
457 std::unique_ptr<asio::steady_timer> expireTimer;
458 std::unique_ptr<asio::steady_timer> expireNotifyTimer;
462 template <
typename Packer>
463 void msgpack_pack(Packer& p)
const
465 p.pack_map(3 + (sessionCtx ? 1 : 0) + (topic.empty() ? 0 : 1));
466 p.pack(
"cid"); p.pack(clientId);
467 p.pack(
"exp"); p.pack(to_time_t(expiration));
469 std::lock_guard<std::mutex> l(sessionCtx->lock);
470 p.pack(
"sid"); p.pack(sessionCtx->sessionId);
472 p.pack(
"t"); p.pack(type);
473 if (!topic.empty()) {
474 p.pack(
"top"); p.pack(topic);
478 void msgpack_unpack(
const msgpack::object& o);
480 struct PushListener {
481 std::map<InfoHash, std::vector<Listener>> listeners;
482 MSGPACK_DEFINE_ARRAY(listeners)
484 std::map<std::string, PushListener> pushListeners_;