50class OPENDHT_PUBLIC DhtProxyClient final :
public DhtInterface {
55 explicit DhtProxyClient(
56 std::shared_ptr<crypto::Certificate> serverCA,
57 crypto::Identity clientIdentity,
58 std::function<
void()> loopSignal,
59 const std::string& serverHost,
60 const std::string& userAgent =
"",
61 const std::string& pushClientId =
"",
62 const std::string& pushToken =
"",
63 const std::string& pushTopic =
"",
64 const std::string& pushPlatform =
"",
65 std::shared_ptr<Logger> logger = {}
70 virtual void setPushNotificationToken(
const std::string& token)
override;
72 virtual void setPushNotificationTopic(
const std::string& topic)
override {
73#ifdef OPENDHT_PUSH_NOTIFICATIONS
74 notificationTopic_ = topic;
80 virtual void setPushNotificationPlatform(
const std::string& platform)
override {
81#ifdef OPENDHT_PUSH_NOTIFICATIONS
88 virtual ~DhtProxyClient();
93 inline const InfoHash&
getNodeId()
const override {
return myid; }
94 void setOnPublicAddressChanged(PublicAddressChangedCb cb)
override {
95 publicAddressChangedCb_ = std::move(cb);
129 virtual void get(
const InfoHash& key, GetCallback cb, DoneCallback donecb={},
Value::Filter&& f={}, Where&& w = {})
override;
130 virtual void get(
const InfoHash& key, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f={}, Where&& w = {})
override {
131 get(key, cb, bindDoneCb(std::move(donecb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
133 virtual void get(
const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {})
override {
134 get(key, bindGetCb(cb), std::move(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
136 virtual void get(
const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {})
override {
137 get(key, bindGetCb(cb), bindDoneCb(std::move(donecb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
147 void put(
const InfoHash& key,
149 DoneCallback cb=
nullptr,
150 time_point created=time_point::max(),
151 bool permanent =
false)
override;
152 void put(
const InfoHash& key,
154 DoneCallbackSimple cb,
155 time_point created=time_point::max(),
156 bool permanent =
false)
override
158 put(key, v, bindDoneCb(std::move(cb)), created, permanent);
161 void put(
const InfoHash& key,
163 DoneCallback cb=
nullptr,
164 time_point created=time_point::max(),
165 bool permanent =
false)
override
167 put(key, std::make_shared<Value>(std::move(v)), std::move(cb), created, permanent);
169 void put(
const InfoHash& key,
171 DoneCallbackSimple cb,
172 time_point created=time_point::max(),
173 bool permanent =
false)
override
175 put(key, std::forward<Value>(v), bindDoneCb(std::move(cb)), created, permanent);
200 return listen(key, [cb=std::move(cb)](
const std::vector<Sp<Value>>& vals,
bool expired){
204 }, std::forward<Value::Filter>(f), std::forward<Where>(w));
206 virtual size_t listen(
const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w={})
override {
207 return listen(key, bindGetCb(std::move(cb)), std::forward<Value::Filter>(f), std::forward<Where>(w));
213 virtual bool cancelListen(
const InfoHash& key,
size_t token)
override;
221 time_point periodic(
const uint8_t*,
size_t,
SockAddr,
const time_point& now)
override;
222 time_point periodic(
const uint8_t* buf,
size_t buflen,
const sockaddr* from, socklen_t fromlen,
const time_point& now)
override {
223 return periodic(buf, buflen,
SockAddr(from, fromlen), now);
236 virtual void query(
const InfoHash& , QueryCallback , DoneCallback = {},
Query&& = {})
override { }
237 virtual void query(
const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {})
override {
238 query(key, cb, bindDoneCb(std::move(done_cb)), std::forward<Query>(q));
244 std::vector<Sp<Value>>
getPut(
const InfoHash&)
const override;
249 Sp<Value>
getPut(
const InfoHash&,
const Value::Id&)
const override;
255 bool cancelPut(
const InfoHash&,
const Value::Id&)
override;
257 void pingNode(
SockAddr, DoneCallbackSimple&& ={})
override { }
259 virtual void registerType(
const ValueType& type)
override {
260 types.registerType(type);
262 const ValueType& getType(ValueType::Id type_id)
const override {
263 return types.getType(type_id);
267 Sp<Value>
getLocalById(
const InfoHash& k, Value::Id
id)
const override;
274 void insertNode(
const NodeExport&)
override { }
276 std::vector<NodeExport>
exportNodes()
const override {
return {}; }
277 std::vector<ValuesExport> exportValues()
const override {
return {}; }
278 void importValues(
const std::vector<ValuesExport>&)
override {}
279 std::string getStorageLog()
const override {
return {}; }
280 std::string getStorageLog(
const InfoHash&)
const override {
return {}; }
281 std::string getRoutingTablesLog(sa_family_t)
const override {
return {}; }
282 std::string getSearchesLog(sa_family_t)
const override {
return {}; }
283 std::string getSearchLog(
const InfoHash&, sa_family_t)
const override {
return {}; }
284 void dumpTables()
const override {}
285 std::vector<unsigned> getNodeMessageStats(
bool)
override {
return {}; }
287 virtual size_t getStorageLimit()
const override {
return 0; }
291 void connectivityChanged()
override {
296 void listenKeepIdle(uint32_t seconds) {
297 listenKeepIdle_ = seconds;
299 inline uint32_t listenKeepIdle() {
return listenKeepIdle_; }
313 void getProxyInfos();
314 void queryProxyInfo(
const std::shared_ptr<InfoState>& infoState,
const std::shared_ptr<http::Resolver>& resolver, sa_family_t family);
315 void onProxyInfos(
const Json::Value& val,
const sa_family_t family);
316 SockAddr parsePublicAddress(
const Json::Value& val);
320 void handleExpireListener(
const asio::error_code &ec,
const InfoHash& key);
323 struct OperationState;
324 enum class ListenMethod {
329 using CacheValueCallback = std::function<bool(
const std::vector<std::shared_ptr<Value>>& values,
bool expired, system_clock::time_point)>;
334 void sendListen(
const restinio::http_request_header_t& header,
const CacheValueCallback& cb,
335 const Sp<OperationState>& opstate, Listener& listener, ListenMethod method = ListenMethod::LISTEN);
336 void handleResubscribe(
const asio::error_code& ec,
const InfoHash& key,
337 const size_t token, std::shared_ptr<OperationState> opstate);
339 void doPut(
const InfoHash&, Sp<Value>, DoneCallbackSimple, time_point created,
bool permanent);
340 void handleRefreshPut(
const asio::error_code& ec, InfoHash key, Value::Id
id);
345 void getConnectivityStatus();
349 void cancelAllListeners();
351 std::atomic_bool isDestroying_ {
false};
353 std::string proxyUrl_;
354 dht::crypto::Identity clientIdentity_;
355 std::shared_ptr<dht::crypto::Certificate> serverCertificate_;
356 std::string userAgent_ {
"OpenDHT"};
357 std::string pushClientId_;
358 std::string pushSessionId_;
360 mutable std::mutex lockCurrentProxyInfos_;
361 NodeStatus statusIpv4_ {NodeStatus::Disconnected};
362 NodeStatus statusIpv6_ {NodeStatus::Disconnected};
363 NodeStats stats4_ {};
364 NodeStats stats6_ {};
365 SockAddr localAddrv4_;
366 SockAddr localAddrv6_;
367 SockAddr publicAddressV4_;
368 SockAddr publicAddressV6_;
369 std::atomic_bool launchConnectedCbs_ {
false};
370 PublicAddressChangedCb publicAddressChangedCb_ {};
381 asio::io_context httpContext_;
382 mutable std::mutex resolverLock_;
383 std::shared_ptr<http::Resolver> resolver_;
385 mutable std::mutex requestLock_;
386 std::map<unsigned, std::shared_ptr<http::Request>> requests_;
390 std::thread httpClientThread_;
397 mutable std::mutex searchLock_;
398 size_t listenerToken_ {0};
399 std::map<InfoHash, ProxySearch> searches_;
404 uint32_t listenKeepIdle_ {120};
409 std::mutex lockCallbacks_;
410 std::vector<std::function<void()>> callbacks_;
412 Sp<InfoState> infoState_;
417 void handleProxyConfirm(
const asio::error_code &ec);
418 std::unique_ptr<asio::steady_timer> nextProxyConfirmationTimer_;
419 std::unique_ptr<asio::steady_timer> listenerRestartTimer_;
424 void restartListeners(
const asio::error_code &ec);
430 void resubscribe(
const InfoHash& key,
const size_t token, Listener& listener);
436 std::string deviceKey_ {};
441 std::string notificationTopic_ {};
446 std::string platform_
457 const std::function<void()> loopSignal_;
459#ifdef OPENDHT_PUSH_NOTIFICATIONS
460 std::string fillBody(
bool resubscribe);
461 void getPushRequest(Json::Value&)
const;
464 Json::StreamWriterBuilder jsonBuilder_;
465 std::unique_ptr<Json::CharReader> jsonReader_;
467 std::shared_ptr<http::Request> buildRequest(
const std::string& target = {});