Compare commits

...
Author SHA1 Message Date
Adrien Béraud b3511d223b sockaddr: use more precise exception 2018-12-17 16:41:00 -05:00
Adrien Béraud d1aca77809 securedht: move crypto ops to Value 2018-12-17 16:41:00 -05:00
Adrien Béraud 306d573223 proxy client: fix race condition 2018-12-17 16:41:00 -05:00
Sébastien Blin 20f4355b73 Merge pull request #356 from savoirfairelinux/build
securedht: add override
2018-12-11 14:52:07 -05:00
Adrien Béraud a2d7cd56a8 Merge pull request #358 from atraczyk/master
replace _write with send when building for windows
2018-12-11 14:48:26 -05:00
Andreas Traczyk 5cd53f3624 replace _write with send when building for windows 2018-12-11 14:37:14 -05:00
Adrien Béraud 32eea55f10 autotools: don't build doc if doxygen not found 2018-12-11 14:04:35 -05:00
Adrien Béraud f2f913f93f securedht: add override for relevant methods 2018-12-11 14:04:35 -05:00
Adrien Béraud cb9fe9d1fe Merge pull request #354 from atraczyk/master
msvc: replace write with _write when building on windows
2018-12-06 12:23:36 -05:00
Andreas Traczyk dcab32ef4f replace write with _write when building with msvc 2018-12-06 12:16:59 -05:00
Adrien Béraud 4948bd7ad3 node cache: remove expired weak pointers from cache
Remove expired Node weak pointers regularly,
in a way that ensures that:
* every expired pointer gets eventually cleaned up
* expired pointer ratio remains reasonably low
* no cleanup pass blocks the node for too long,
* impact on performance is negligible

Impact on performance:
Every N insertions, at most N nodes are tested by iterating the map
-> performance impact in O(1) (constant).
2018-11-29 19:27:32 -05:00
Adrien Béraud 4416b91461 update to version 1.8.0 2018-11-28 18:44:03 -05:00
Adrien Béraud 378ae396f0 Merge pull request #351 from hanyf/master
A obvious bug on network engine
2018-11-28 12:48:02 -05:00
Yanfei Han dc4a790a38 A obviouse bug on network engine 2018-11-29 00:47:00 +08:00
Sébastien Blin 07dd8f5648 Merge pull request #350 from savoirfairelinux/feature/cache
Feature/cache
2018-11-28 09:22:06 -05:00
Adrien Béraud f7433a2289 travis: update to xenial 2018-11-26 16:48:00 -05:00
Adrien Béraud ce4a65ff00 dhtrunner: add APIs for listen<T> with expiration information 2018-11-26 16:34:19 -05:00
Adrien Béraud 092f5cfef0 network_engine: fix warning 2018-11-26 16:34:19 -05:00
Adrien Béraud 12a45e7558 cmake: remove unnecessary flags for lto 2018-11-26 16:30:18 -05:00
Adrien Béraud 18d359a7d2 dht: refresh value if already exists 2018-11-26 01:57:57 -05:00
Adrien Béraud c6bb67d1ac dht: add storageRefresh 2018-11-26 01:57:57 -05:00
Adrien Béraud f4cd7636ce securedht: use signature cache in storePolicy, editPolicy 2018-11-26 01:57:57 -05:00
Adrien Béraud 2dd4e640c4 dhtrunner: add APIs for listen<T> with expiration information 2018-11-25 23:01:03 -05:00
Adrien Béraud 9a301e3590 Revert "cmake: use CMAKE_INTERPROCEDURAL_OPTIMIZATION for LTO"
This reverts commit b7b5152348.
2018-11-24 15:32:29 -05:00
Sébastien Blin aa16b9a235 Merge pull request #348 from savoirfairelinux/feature/probepermanent
dht: don't send probe query for non permanent puts
2018-11-23 10:10:35 -05:00
19 changed files with 216 additions and 122 deletions

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
dist: xenial
sudo: required
services:
+8 -3
View File
@@ -1,8 +1,7 @@
cmake_minimum_required (VERSION 3.1)
project (opendht)
cmake_policy (SET CMP0069 NEW)
set (opendht_VERSION_MAJOR 1)
set (opendht_VERSION_MINOR 7.4)
set (opendht_VERSION_MINOR 8.0)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -82,7 +81,13 @@ else ()
add_definitions(-DOPENDHT_LOG=false)
endif()
if (OPENDHT_LTO)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
if (CMAKE_COMPILER_IS_GNUCC)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-linker-plugin")
set (CMAKE_AR "gcc-ar")
set (CMAKE_NM "gcc-nm")
set (CMAKE_RANLIB "gcc-ranlib")
endif ()
endif ()
if (MSGPACK_INCLUDE_DIRS)
+2
View File
@@ -16,7 +16,9 @@ if ENABLE_TESTS
SUBDIRS += tests
endif
if HAVE_DOXYGEN
SUBDIRS += doc
endif
ACLOCAL_AMFLAGS = -I m4
+6 -4
View File
@@ -1,7 +1,7 @@
dnl define macros
m4_define([opendht_major_version], 1)
m4_define([opendht_minor_version], 7)
m4_define([opendht_patch_version], 4)
m4_define([opendht_minor_version], 8)
m4_define([opendht_patch_version], 0)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
@@ -130,7 +130,7 @@ PKG_CHECK_MODULES([GnuTLS], [gnutls >= 3.3])
PKG_CHECK_MODULES([MsgPack], [msgpack >= 1.2])
AC_ARG_WITH([jsoncpp], AS_HELP_STRING([--without-jsoncpp], [Build without JsonCpp support]))
AS_IF([test "x$with_jsoncpp" != "xno"],
AS_IF([test "x$with_jsoncpp" != "xno"],
[PKG_CHECK_MODULES([JsonCpp], [jsoncpp >= 1.7.2], [have_jsoncpp=yes], [have_jsoncpp=no])],
[have_jsoncpp=no])
AS_IF([test "x$have_jsoncpp" = "xyes"], [
@@ -193,7 +193,9 @@ AM_COND_IF(ENABLE_PROXY_SERVER_IDENTITY,
[CPPFLAGS+=" -DOPENDHT_PROXY_SERVER_IDENTITY=true"],
[CPPFLAGS+=" -DOPENDHT_PROXY_SERVER_IDENTITY=false"])
AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])
AM_COND_IF([HAVE_DOXYGEN], [
AC_CONFIG_FILES([doc/Doxyfile doc/Makefile])
])
dnl Configure setup.py if we build the python module
AM_COND_IF([USE_CYTHON], [
-2
View File
@@ -173,8 +173,6 @@ private:
PrivateKey(const PrivateKey&) = delete;
PrivateKey& operator=(const PrivateKey&) = delete;
Blob decryptBloc(const uint8_t* src, size_t src_size) const;
//friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length);
};
+1
View File
@@ -411,6 +411,7 @@ private:
void storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t tid, Query&& = {});
bool storageStore(const InfoHash& id, const Sp<Value>& value, time_point created, const SockAddr& sa = {}, bool permanent = false);
bool storageErase(const InfoHash& id, Value::Id vid);
bool storageRefresh(const InfoHash& id, Value::Id vid);
void expireStore();
void expireStorage(InfoHash h);
void expireStore(decltype(store)::iterator);
+1 -1
View File
@@ -375,7 +375,7 @@ private:
void getPushRequest(Json::Value&) const;
#endif // OPENDHT_PUSH_NOTIFICATIONS
bool isDestroying_ {false};
std::atomic_bool isDestroying_ {false};
};
}
+25
View File
@@ -158,6 +158,15 @@ public:
},
getFilterSet<T>());
}
template <class T>
std::future<size_t> listen(InfoHash hash, std::function<bool(std::vector<T>&&, bool)> cb)
{
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
return cb(unpackVector<T>(vals), expired);
},
getFilterSet<T>());
}
template <typename T>
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&)> cb, Value::Filter f = Value::AllFilter(), Where w = {})
{
@@ -174,6 +183,22 @@ public:
},
getFilterSet<T>(f), w);
}
template <typename T>
std::future<size_t> listen(InfoHash hash, std::function<bool(T&&, bool)> cb, Value::Filter f = Value::AllFilter(), Where w = {})
{
return listen(hash, [=](const std::vector<std::shared_ptr<Value>>& vals, bool expired) {
for (const auto& v : vals) {
try {
if (not cb(Value::unpack<T>(*v), expired))
return false;
} catch (const std::exception&) {
continue;
}
}
return true;
},
getFilterSet<T>(f), w);
}
void cancelListen(InfoHash h, size_t token);
void cancelListen(InfoHash h, std::shared_future<size_t> token);
+5 -1
View File
@@ -40,12 +40,16 @@ struct NodeCache {
~NodeCache();
private:
class NodeMap : public std::map<InfoHash, std::weak_ptr<Node>> {
class NodeMap : private std::map<InfoHash, std::weak_ptr<Node>> {
public:
Sp<Node> getNode(const InfoHash& id);
Sp<Node> getNode(const InfoHash& id, const SockAddr&, time_point now, bool confirmed, bool client);
std::vector<Sp<Node>> getCachedNodes(const InfoHash& id, size_t count) const;
void clearBadNodes();
void setExpired();
void cleanup();
private:
size_t cleanup_counter {0};
};
const NodeMap& cache(sa_family_t af) const { return af == AF_INET ? cache_4 : cache_6; }
+52 -51
View File
@@ -71,7 +71,7 @@ public:
return secureType(std::move(tmp_type));
}
void registerType(const ValueType& type) {
void registerType(const ValueType& type) override {
if (dht_)
dht_->registerType(secureType(type));
}
@@ -89,14 +89,14 @@ public:
* If the signature can't be checked, or if the data can't be decrypted, it is not returned.
* Public, non-signed & non-encrypted data is retransmitted as-is.
*/
void get(const InfoHash& id, GetCallback cb, DoneCallback donecb={}, Value::Filter&& = {}, Where&& w = {});
void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}, Where&& w = {}) {
void get(const InfoHash& id, GetCallback cb, DoneCallback donecb={}, Value::Filter&& = {}, Where&& w = {}) override;
void get(const InfoHash& id, GetCallback cb, DoneCallbackSimple donecb={}, Value::Filter&& f = {}, Where&& w = {}) override {
get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) {
void get(const InfoHash& key, GetCallbackSimple cb, DoneCallback donecb={}, Value::Filter&& f={}, Where&& w = {}) override {
get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
}
void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) {
void get(const InfoHash& key, GetCallbackSimple cb, DoneCallbackSimple donecb, Value::Filter&& f={}, Where&& w = {}) override {
get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
}
@@ -148,99 +148,100 @@ public:
/**
* SecureDht to Dht proxy
*/
void shutdown(ShutdownCallback cb) {
void shutdown(ShutdownCallback cb) override {
dht_->shutdown(cb);
}
void dumpTables() const {
void dumpTables() const override {
dht_->dumpTables();
}
inline const InfoHash& getNodeId() const { return dht_->getNodeId(); }
std::pair<size_t, size_t> getStoreSize() const {
inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
std::pair<size_t, size_t> getStoreSize() const override {
return dht_->getStoreSize();
}
std::string getStorageLog() const {
std::string getStorageLog() const override {
return dht_->getStorageLog();
}
std::string getStorageLog(const InfoHash& h) const {
std::string getStorageLog(const InfoHash& h) const override {
return dht_->getStorageLog(h);
}
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) {
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
dht_->setStorageLimit(limit);
}
std::vector<NodeExport> exportNodes() {
std::vector<NodeExport> exportNodes() override {
return dht_->exportNodes();
}
std::vector<ValuesExport> exportValues() const {
std::vector<ValuesExport> exportValues() const override {
return dht_->exportValues();
}
void importValues(const std::vector<ValuesExport>& v) {
void importValues(const std::vector<ValuesExport>& v) override {
dht_->importValues(v);
}
NodeStats getNodesStats(sa_family_t af) const {
NodeStats getNodesStats(sa_family_t af) const override {
return dht_->getNodesStats(af);
}
std::vector<unsigned> getNodeMessageStats(bool in = false) {
std::vector<unsigned> getNodeMessageStats(bool in = false) override {
return dht_->getNodeMessageStats(in);
}
std::string getRoutingTablesLog(sa_family_t af) const {
std::string getRoutingTablesLog(sa_family_t af) const override {
return dht_->getRoutingTablesLog(af);
}
std::string getSearchesLog(sa_family_t af) const {
std::string getSearchesLog(sa_family_t af) const override {
return dht_->getSearchesLog(af);
}
std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const {
std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override {
return dht_->getSearchLog(h, af);
}
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) {
std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override {
return dht_->getPublicAddress(family);
}
time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr& sa) {
time_point periodic(const uint8_t *buf, size_t buflen, const SockAddr& sa) override {
return dht_->periodic(buf, buflen, sa);
}
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) {
time_point periodic(const uint8_t *buf, size_t buflen, const sockaddr* from, socklen_t fromlen) override {
return dht_->periodic(buf, buflen, from, fromlen);
}
NodeStatus getStatus(sa_family_t af) const {
NodeStatus getStatus(sa_family_t af) const override {
return dht_->getStatus(af);
}
NodeStatus getStatus() const {
NodeStatus getStatus() const override {
return dht_->getStatus();
}
bool isRunning(sa_family_t af = 0) const {
bool isRunning(sa_family_t af = 0) const override {
return dht_->isRunning(af);
}
const ValueType& getType(ValueType::Id type_id) const {
const ValueType& getType(ValueType::Id type_id) const override {
return dht_->getType(type_id);
}
void insertNode(const InfoHash& id, const SockAddr& sa) {
void insertNode(const InfoHash& id, const SockAddr& sa) override {
dht_->insertNode(id, sa);
}
void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) {
void insertNode(const InfoHash& id, const sockaddr* sa, socklen_t salen) override {
dht_->insertNode(id, sa, salen);
}
void insertNode(const NodeExport& n) {
void insertNode(const NodeExport& n) override {
dht_->insertNode(n);
}
void pingNode(const sockaddr* sa, socklen_t salen, DoneCallbackSimple&& cb={}) {
void pingNode(const sockaddr* sa, socklen_t salen, DoneCallbackSimple&& cb={}) override {
dht_->pingNode(sa, salen, std::move(cb));
}
void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) {
void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override {
dht_->query(key, cb, done_cb, std::move(q));
}
void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) {
void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override {
dht_->query(key, cb, done_cb, std::move(q));
}
std::vector<Sp<Value>> getLocal(const InfoHash& key, Value::Filter f = Value::AllFilter()) const {
std::vector<Sp<Value>> getLocal(const InfoHash& key, Value::Filter f = Value::AllFilter()) const override {
return dht_->getLocal(key, f);
}
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const {
Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override {
return dht_->getLocalById(key, vid);
}
void put(const InfoHash& key,
Sp<Value> v,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
dht_->put(key, v, cb, created, permanent);
}
@@ -248,7 +249,7 @@ public:
const Sp<Value>& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
dht_->put(key, v, cb, created, permanent);
}
@@ -257,7 +258,7 @@ public:
Value&& v,
DoneCallback cb=nullptr,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
dht_->put(key, std::move(v), cb, created, permanent);
}
@@ -265,32 +266,32 @@ public:
Value&& v,
DoneCallbackSimple cb,
time_point created=time_point::max(),
bool permanent = false)
bool permanent = false) override
{
dht_->put(key, std::move(v), cb, created, permanent);
}
std::vector<Sp<Value>> getPut(const InfoHash& h) {
std::vector<Sp<Value>> getPut(const InfoHash& h) override {
return dht_->getPut(h);
}
Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) {
Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) override {
return dht_->getPut(h, vid);
}
bool cancelPut(const InfoHash& h, const Value::Id& vid) {
bool cancelPut(const InfoHash& h, const Value::Id& vid) override {
return dht_->cancelPut(h, vid);
}
size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={});
size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {});
size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) {
size_t listen(const InfoHash& key, ValueCallback, Value::Filter={}, Where={}) override;
size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f={}, Where w = {}) override {
return listen(key, bindGetCb(cb), f, w);
}
bool cancelListen(const InfoHash& h, size_t token) {
bool cancelListen(const InfoHash& h, size_t token) override {
return dht_->cancelListen(h, token);
}
void connectivityChanged(sa_family_t af) {
void connectivityChanged(sa_family_t af) override {
dht_->connectivityChanged(af);
}
void connectivityChanged() {
void connectivityChanged() override {
dht_->connectivityChanged();
}
@@ -298,7 +299,7 @@ public:
forward_all_ = forward;
}
void setPushNotificationToken(const std::string& token = "") {
void setPushNotificationToken(const std::string& token = "") override {
dht_->setPushNotificationToken(token);
}
@@ -306,7 +307,7 @@ public:
* Call linked callback with push_notification
* @param notification to process
*/
void pushNotificationReceived(const std::map<std::string, std::string>& notification) {
void pushNotificationReceived(const std::map<std::string, std::string>& notification) override {
dht_->pushNotificationReceived(notification);
}
@@ -319,7 +320,7 @@ public:
/**
* Only print logs related to the given InfoHash (if given), or disable filter (if zeroes).
*/
void setLogFilter(const InfoHash& f) {
void setLogFilter(const InfoHash& f) override {
DHT_LOG.setFilter(f);
dht_->setLogFilter(f);
}
+2 -2
View File
@@ -67,7 +67,7 @@ public:
*/
SockAddr(const sockaddr* sa, socklen_t length) {
if (length > sizeof(sockaddr_storage))
throw std::runtime_error("Socket address length is too large");
throw std::invalid_argument("Socket address length is too large");
set(sa, length);
}
SockAddr(const sockaddr* sa) {
@@ -78,7 +78,7 @@ public:
else if(sa->sa_family == AF_INET6)
len = sizeof(sockaddr_in6);
else
throw std::runtime_error("Unknown address family");
throw std::invalid_argument("Unknown address family");
}
set(sa, len);
}
+4 -2
View File
@@ -577,7 +577,7 @@ struct OPENDHT_PUBLIC Value
std::string user_type {};
/**
* Sequence number to avoid replay attacks
* Sequence number
*/
uint16_t seq {0};
@@ -591,8 +591,10 @@ struct OPENDHT_PUBLIC Value
*/
Blob cypher {};
bool checkSignature();
Sp<Value> decrypt(const crypto::PrivateKey& key);
private:
friend class SecureDht;
/* Cache for crypto ops */
bool signatureChecked {false};
bool signatureValid {false};
+17 -8
View File
@@ -2344,7 +2344,8 @@ Dht::onAnnounce(Sp<Node> n,
Sp<Value> vc = v;
if (lv) {
if (*lv == *vc) {
DHT_LOG.d(hash, node.id, "[store %s] nothing to do for %s", hash.toString().c_str(), lv->toString().c_str());
storageRefresh(hash, v->id);
DHT_LOG.d(hash, node.id, "[store %s] [node %s] refreshed value %s", hash.toString().c_str(), node.toString().c_str(), std::to_string(v->id).c_str());
} else {
const auto& type = getType(lv->type);
if (type.editPolicy(hash, lv, vc, node.id, node.getAddr())) {
@@ -2376,17 +2377,11 @@ Dht::onRefresh(Sp<Node> node, const InfoHash& hash, const Blob& token, const Val
{
using namespace net;
const auto& now = scheduler.time();
if (not tokenMatch(token, node->getAddr())) {
DHT_LOG.w(hash, node->id, "[node %s] incorrect token %s for 'put'", node->toString().c_str(), hash.toString().c_str());
throw DhtProtocolException {DhtProtocolException::UNAUTHORIZED, DhtProtocolException::PUT_WRONG_TOKEN};
}
auto s = store.find(hash);
if (s != store.end()) {
auto expiration = s->second.refresh(now, vid, types);
if (expiration != time_point::max())
scheduler.add(expiration, std::bind(&Dht::expireStorage, this, hash));
if (storageRefresh(hash, vid)) {
DHT_LOG.d(hash, node->id, "[store %s] [node %s] refreshed value %s", hash.toString().c_str(), node->toString().c_str(), std::to_string(vid).c_str());
} else {
DHT_LOG.d(hash, node->id, "[store %s] [node %s] got refresh for unknown value",
@@ -2396,6 +2391,20 @@ Dht::onRefresh(Sp<Node> node, const InfoHash& hash, const Blob& token, const Val
return {};
}
bool
Dht::storageRefresh(const InfoHash& id, Value::Id vid)
{
const auto& now = scheduler.time();
auto s = store.find(id);
if (s != store.end()) {
auto expiration = s->second.refresh(now, vid, types);
if (expiration != time_point::max())
scheduler.add(expiration, std::bind(&Dht::expireStorage, this, id));
return true;
}
return false;
}
void
Dht::onAnnounceDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>& sr)
{
+4 -1
View File
@@ -578,6 +578,8 @@ DhtProxyClient::getProxyInfos()
void
DhtProxyClient::onProxyInfos(const Json::Value& proxyInfos, sa_family_t family)
{
if (isDestroying_)
return;
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
auto oldStatus = std::max(statusIpv4_, statusIpv6_);
auto& status = family == AF_INET ? statusIpv4_ : statusIpv6_;
@@ -951,6 +953,8 @@ DhtProxyClient::getConnectivityStatus()
void
DhtProxyClient::restartListeners()
{
if (isDestroying_) return;
std::lock_guard<std::mutex> lock(searchLock_);
DHT_LOG.d("Refresh permanent puts");
for (auto& search : searches_) {
for (auto& put : search.second.puts) {
@@ -974,7 +978,6 @@ DhtProxyClient::restartListeners()
return;
}
DHT_LOG.d("Restarting listeners");
std::lock_guard<std::mutex> lock(searchLock_);
for (auto& search: searches_) {
for (auto& l: search.second.listeners) {
auto& listener = l.second;
+1
View File
@@ -37,6 +37,7 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#define close(x) closesocket(x)
#define write(s, b, f) send(s, b, (int)strlen(b), 0)
#endif
namespace dht {
+3 -3
View File
@@ -185,7 +185,7 @@ NetworkEngine::tellListener(Sp<Node> node, Tid socket_id, const InfoHash& hash,
}
void
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& token, const std::vector<Value::Id>& values)
NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
@@ -215,7 +215,7 @@ NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&
}
void
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash& hash, const Blob& token, const std::vector<Value::Id>& values)
NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, const Blob& token, const std::vector<Value::Id>& values)
{
msgpack::sbuffer buffer;
msgpack::packer<msgpack::sbuffer> pk(&buffer);
@@ -551,7 +551,7 @@ NetworkEngine::process(std::unique_ptr<ParsedMessage>&& msg, const SockAddr& fro
}
case MessageType::Reply:
if (req) { /* request reply */
if (msg->type == MessageType::AnnounceValue or msg->type == MessageType::Listen)
if (req->getType() == MessageType::AnnounceValue or req->getType() == MessageType::Listen)
req->node->authSuccess();
req->reply_time = scheduler.time();
+38 -11
View File
@@ -20,6 +20,9 @@
namespace dht {
constexpr size_t CLEANUP_MAX_NODES {1024};
constexpr size_t CLEANUP_FREQ {1024};
NodeCache::~NodeCache()
{
cache_4.setExpired();
@@ -41,29 +44,33 @@ NodeCache::getNode(const InfoHash& id, const SockAddr& addr, time_point now, boo
std::vector<Sp<Node>>
NodeCache::getCachedNodes(const InfoHash& id, sa_family_t sa_f, size_t count) const
{
const auto& c = cache(sa_f);
return cache(sa_f).getCachedNodes(id, count);
}
std::vector<Sp<Node>>
NodeCache::NodeMap::getCachedNodes(const InfoHash& id, size_t count) const
{
std::vector<Sp<Node>> nodes;
nodes.reserve(std::min(c.size(), count));
NodeMap::const_iterator it;
auto dec_it = [&c](NodeMap::const_iterator& it) {
nodes.reserve(std::min(size(), count));
const_iterator it;
auto dec_it = [this](const_iterator& it) {
auto ret = it;
it = (it == c.cbegin()) ? c.cend() : std::prev(it);
it = (it == cbegin()) ? cend() : std::prev(it);
return ret;
};
auto it_p = c.lower_bound(id),
auto it_p = lower_bound(id),
it_n = it_p;
if (not c.empty())
if (not empty())
dec_it(it_p); /* Create 2 separate iterator if we could */
while (nodes.size() < count and (it_n != c.cend() or it_p != c.cend())) {
while (nodes.size() < count and (it_n != cend() or it_p != cend())) {
/* If one of the iterator is at the end, then take the other one
If they are both in middle of somewhere comapre both and take
the closest to the id. */
if (it_p == c.cend()) it = it_n++;
else if (it_n == c.cend()) it = dec_it(it_p);
else it = id.xorCmp(it_p->first, it_n->first) < 0 ? dec_it(it_p) : it_n++;
if (it_p == cend()) it = it_n++;
else if (it_n == cend()) it = dec_it(it_p);
else it = id.xorCmp(it_p->first, it_n->first) < 0 ? dec_it(it_p) : it_n++;
if (auto n = it->second.lock())
if ( not n->isExpired() and not n->isClient() )
@@ -104,6 +111,10 @@ NodeCache::NodeMap::getNode(const InfoHash& id, const SockAddr& addr, time_point
if (not node) {
node = std::make_shared<Node>(id, addr, client);
it.first->second = node;
if (cleanup_counter++ == CLEANUP_FREQ) {
cleanup();
cleanup_counter = 0;
}
} else if (confirm or node->isOld(now)) {
node->update(addr);
}
@@ -120,6 +131,7 @@ NodeCache::NodeMap::clearBadNodes() {
erase(it++);
}
}
cleanup_counter = 0;
}
void
@@ -128,6 +140,21 @@ NodeCache::NodeMap::setExpired() {
if (auto n = wn.second.lock())
n->setExpired();
clear();
cleanup_counter = 0;
}
void
NodeCache::NodeMap::cleanup()
{
auto it = lower_bound(InfoHash::getRandom());
for (size_t n = 0, maxNodes = std::min(size(), CLEANUP_MAX_NODES); n != maxNodes; n++) {
if (it == end())
it = begin();
if (it->second.expired())
erase(it++);
else
++it;
}
}
}
+13 -33
View File
@@ -68,27 +68,19 @@ ValueType
SecureDht::secureType(ValueType&& type)
{
type.storePolicy = [this,type](InfoHash id, Sp<Value>& v, const InfoHash& nid, const SockAddr& a) {
if (v->isSigned()) {
if (!v->owner or !v->owner->checkSignature(v->getToSign(), v->signature)) {
DHT_LOG.WARN("Signature verification failed");
return false;
}
else
DHT_LOG.WARN("Signature verification succeeded");
}
if (v->isSigned())
return v->checkSignature();
return type.storePolicy(id, v, nid, a);
};
type.editPolicy = [this,type](InfoHash id, const Sp<Value>& o, Sp<Value>& n, const InfoHash& nid, const SockAddr& a) {
if (!o->isSigned())
if (not o->isSigned())
return type.editPolicy(id, o, n, nid, a);
if (o->owner != n->owner) {
if (o->owner != n->owner or not n->isSigned()) {
DHT_LOG.WARN("Edition forbidden: owner changed.");
return false;
}
if (!o->owner or !o->owner->checkSignature(n->getToSign(), n->signature)) {
DHT_LOG.WARN("Edition forbidden: signature verification failed.");
if (not n->checkSignature())
return false;
}
if (o->seq == n->seq) {
// If the data is exactly the same,
// it can be reannounced, possibly by someone else.
@@ -235,35 +227,23 @@ SecureDht::checkValue(const Sp<Value>& v)
#endif
return {};
}
if (v->decrypted) {
return v->decryptedValue;
}
v->decrypted = true;
try {
Value decrypted_val (decrypt(*v));
if (decrypted_val.recipient == getId()) {
if (decrypted_val.owner)
nodesPubKeys_[decrypted_val.owner->getId()] = decrypted_val.owner;
v->decryptedValue = std::make_shared<Value>(std::move(decrypted_val));
return v->decryptedValue;
if (auto decrypted_val = v->decrypt(*key_)) {
if (decrypted_val->owner)
nodesPubKeys_[decrypted_val->owner->getId()] = decrypted_val->owner;
return decrypted_val;
}
// Ignore values belonging to other people
} catch (const std::exception& e) {
DHT_LOG.WARN("Could not decrypt value %s : %s", v->toString().c_str(), e.what());
}
}
// Check signed values
else if (v->isSigned()) {
if (v->signatureChecked) {
return v->signatureValid ? v : Sp<Value>{};
}
v->signatureChecked = true;
if (v->owner and v->owner->checkSignature(v->getToSign(), v->signature)) {
v->signatureValid = true;
nodesPubKeys_[v->owner->getId()] = v->owner;
if (v->checkSignature()) {
if (v->owner)
nodesPubKeys_[v->owner->getId()] = v->owner;
return v;
}
else
} else
DHT_LOG.WARN("Signature verification failed for %s", v->toString().c_str());
}
// Forward normal values
+33
View File
@@ -233,6 +233,39 @@ Value::toJson() const
return val;
}
bool
Value::checkSignature()
{
if (!signatureChecked) {
signatureChecked = true;
if (isSigned()) {
signatureValid = owner and owner->checkSignature(getToSign(), signature);
}
}
return signatureValid;
}
Sp<Value>
Value::decrypt(const crypto::PrivateKey& key)
{
if (not decrypted) {
decrypted = true;
if (isEncrypted()) {
auto decryptedBlob = key.decrypt(cypher);
std::unique_ptr<Value> v {new Value(id)};
auto msg = msgpack::unpack((const char*)decryptedBlob.data(), decryptedBlob.size());
v->msgpack_unpack_body(msg.get());
if (v->recipient != key.getPublicKey().getId())
throw crypto::DecryptError("Recipient mismatch");
// Ignore values belonging to other people
if (not v->owner or not v->owner->checkSignature(v->getToSign(), v->signature))
throw crypto::DecryptError("Signature mismatch");
decryptedValue = std::move(v);
}
}
return decryptedValue;
}
uint64_t
unpackId(const Json::Value& json, const std::string& key) {
uint64_t ret = 0;