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;
101 using clock = std::chrono::steady_clock;
102 using time_point = clock::time_point;
105 uint64_t highPriorityCount {0};
106 uint64_t normalPriorityCount {0};
108 void increment(
bool highPriority) {
112 normalPriorityCount++;
115 Json::Value toJson()
const {
117 val[
"highPriorityCount"] =
static_cast<Json::UInt64
>(highPriorityCount);
118 val[
"normalPriorityCount"] =
static_cast<Json::UInt64
>(normalPriorityCount);
122 std::string toString()
const {
123 return fmt::format(
"{} high priority, {} normal priority", highPriorityCount, normalPriorityCount);
152 std::string toString()
const;
160 std::shared_ptr<ServerStats> stats()
const {
return stats_; }
162 std::shared_ptr<ServerStats> updateStats(std::shared_ptr<NodeInfo> info)
const;
164 std::shared_ptr<DhtRunner> getNode()
const {
return dht_; }
167 class ConnectionListener;
168 struct RestRouterTraitsTls;
169 struct RestRouterTraits;
171 template <
typename HttpResponse>
172 static HttpResponse initHttpResponse(HttpResponse response);
173 static restinio::request_handling_status_t serverError(restinio::request_t& request);
175 template<
typename ServerSettings >
176 void addServerSettings(ServerSettings& serverSettings,
177 const unsigned int max_pipelined_requests = 16);
179 std::unique_ptr<RestRouter> createRestRouter();
181 void onConnectionClosed(restinio::connection_id_t);
190 RequestStatus getNodeInfo(restinio::request_handle_t request,
191 restinio::router::route_params_t params)
const;
199 RequestStatus getStats(restinio::request_handle_t request,
200 restinio::router::route_params_t params);
212 RequestStatus get(restinio::request_handle_t request,
213 restinio::router::route_params_t params);
225 RequestStatus listen(restinio::request_handle_t request,
226 restinio::router::route_params_t params);
237 RequestStatus put(restinio::request_handle_t request,
238 restinio::router::route_params_t params);
240 void handleCancelPermamentPut(
const asio::error_code &ec,
const InfoHash& key, Value::Id vid);
242#ifdef OPENDHT_PROXY_SERVER_IDENTITY
252 RequestStatus putSigned(restinio::request_handle_t request,
253 restinio::router::route_params_t params)
const;
264 RequestStatus putEncrypted(restinio::request_handle_t request,
265 restinio::router::route_params_t params);
279 RequestStatus getFiltered(restinio::request_handle_t request,
280 restinio::router::route_params_t params);
289 RequestStatus options(restinio::request_handle_t request,
290 restinio::router::route_params_t params);
292 struct PushSessionContext {
294 std::string sessionId;
295 PushSessionContext(
const std::string&
id) : sessionId(id) {}
298#ifdef OPENDHT_PUSH_NOTIFICATIONS
299 PushType getTypeFromString(
const std::string& type);
300 std::string getDefaultTopic(PushType type);
302 RequestStatus pingPush(restinio::request_handle_t request,
303 restinio::router::route_params_t );
313 RequestStatus subscribe(restinio::request_handle_t request,
314 restinio::router::route_params_t params);
323 RequestStatus unsubscribe(restinio::request_handle_t request,
324 restinio::router::route_params_t params);
331 void sendPushNotification(
const std::string& key, Json::Value&& json, PushType type,
bool highPriority,
const std::string& topic);
341 void handleNotifyPushListenExpire(
const asio::error_code &ec,
const std::string pushToken,
342 std::function<Json::Value()> json, PushType type,
const std::string& topic);
351 void handleCancelPushListen(
const asio::error_code &ec,
const std::string pushToken,
352 const InfoHash key,
const std::string clientId);
367 bool handlePushListen(
const InfoHash& infoHash,
const std::string& pushToken,
368 PushType type,
const std::string& clientId,
369 const std::shared_ptr<DhtProxyServer::PushSessionContext>& sessionCtx,
const std::string& topic,
370 const std::vector<std::shared_ptr<Value>>& values,
bool expired);
374 void handlePrintStats(
const asio::error_code &ec);
377 template <
typename Os>
378 void saveState(Os& stream);
380 template <
typename Is>
381 void loadState(Is& is,
size_t size);
383 std::shared_ptr<asio::io_context> ioContext_;
384 std::shared_ptr<DhtRunner> dht_;
385 Json::StreamWriterBuilder jsonBuilder_;
386 Json::CharReaderBuilder jsonReaderBuilder_;
387 std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
389 std::string persistPath_;
392 std::thread serverThread_;
393 std::unique_ptr<restinio::http_server_t<RestRouterTraitsTls>> httpsServer_;
394 std::unique_ptr<restinio::http_server_t<RestRouterTraits>> httpServer_;
397 std::pair<std::string, std::string> pushHostPort_;
399 mutable std::mutex requestLock_;
400 std::map<
unsigned int , std::shared_ptr<http::Request>> requests_;
402 std::shared_ptr<log::Logger> logger_;
404 std::shared_ptr<ServerStats> stats_;
405 std::shared_ptr<NodeInfo> nodeInfo_ {};
406 std::unique_ptr<asio::steady_timer> printStatsTimer_;
407 const time_point serverStartTime_;
408 mutable std::mutex pushStatsMutex_;
409 PushStats androidPush_;
411 PushStats unifiedPush_;
414 std::mutex lockListener_;
416 std::map<restinio::connection_id_t, http::ListenerSession> listeners_;
418 std::shared_ptr<ConnectionListener> connListener_;
419 struct PermanentPut {
420 time_point expiration;
421 std::string pushToken;
422 std::string clientId;
423 std::shared_ptr<PushSessionContext> sessionCtx;
424 std::unique_ptr<asio::steady_timer> expireTimer;
425 std::unique_ptr<asio::steady_timer> expireNotifyTimer;
430 template <
typename Packer>
431 void msgpack_pack(Packer& p)
const
433 p.pack_map(2 + (sessionCtx ? 1 : 0) + (clientId.empty() ? 0 : 1) + (type == PushType::None ? 0 : 2) + (topic.empty() ? 0 : 1));
434 p.pack(
"value"); p.pack(value);
435 p.pack(
"exp"); p.pack(to_time_t(expiration));
436 if (not clientId.empty()) {
437 p.pack(
"cid"); p.pack(clientId);
440 std::lock_guard<std::mutex> l(sessionCtx->lock);
441 p.pack(
"sid"); p.pack(sessionCtx->sessionId);
443 if (type != PushType::None) {
444 p.pack(
"t"); p.pack(type);
445 p.pack(
"token"); p.pack(pushToken);
447 if (not topic.empty()) {
448 p.pack(
"top"); p.pack(topic);
452 void msgpack_unpack(
const msgpack::object& o);
455 std::map<dht::Value::Id, PermanentPut> puts;
456 MSGPACK_DEFINE_ARRAY(puts)
458 std::mutex lockSearchPuts_;
459 std::map<InfoHash, SearchPuts> puts_;
461 mutable std::atomic<size_t> requestNum_ {0};
462 mutable std::atomic<time_point> lastStatsReset_ {time_point::min()};
464 std::string pushServer_;
465 std::string bundleId_;
467#ifdef OPENDHT_PUSH_NOTIFICATIONS
469 time_point expiration;
470 std::string clientId;
471 std::shared_ptr<PushSessionContext> sessionCtx;
472 std::future<size_t> internalToken;
473 std::unique_ptr<asio::steady_timer> expireTimer;
474 std::unique_ptr<asio::steady_timer> expireNotifyTimer;
478 template <
typename Packer>
479 void msgpack_pack(Packer& p)
const
481 p.pack_map(3 + (sessionCtx ? 1 : 0) + (topic.empty() ? 0 : 1));
482 p.pack(
"cid"); p.pack(clientId);
483 p.pack(
"exp"); p.pack(to_time_t(expiration));
485 std::lock_guard<std::mutex> l(sessionCtx->lock);
486 p.pack(
"sid"); p.pack(sessionCtx->sessionId);
488 p.pack(
"t"); p.pack(type);
489 if (!topic.empty()) {
490 p.pack(
"top"); p.pack(topic);
494 void msgpack_unpack(
const msgpack::object& o);
496 struct PushListener {
497 std::map<InfoHash, std::vector<Listener>> listeners;
498 MSGPACK_DEFINE_ARRAY(listeners)
500 std::map<std::string, PushListener> pushListeners_;