Compare commits

...
Author SHA1 Message Date
Adrien Béraud d80aab9399 pingpong: cleanup 2019-03-29 13:13:29 -04:00
Adrien Béraud 9b881d4e95 crypto: add initial certificate request support 2019-03-29 13:13:29 -04:00
Adrien Béraud b4c3c2cba0 update to version 1.8.2 2019-03-18 13:47:41 -04:00
Sébastien Blin 4519a23996 Merge pull request #386 from savoirfairelinux/parse_perf
Network: improve parsing performance
2019-03-18 13:13:57 -04:00
Adrien Béraud 1ac4e08f45 build: add clang-tidy configuration 2019-03-17 19:23:26 -04:00
Adrien Béraud 5e92777702 fix clang-tidy warnings 2019-03-17 19:22:28 -04:00
Adrien Béraud 4401e47002 cleanup, fix clang-tidy warnings 2019-03-17 17:43:52 -04:00
Adrien Béraud 215b44ca3b search: don't store filter in search
Filter is not supported anymore at the search listen stage.
Filters are now stored and called by the op cache.
2019-03-17 17:30:30 -04:00
Adrien Béraud 379fdae212 cmake: don't explicitly disable stack protector 2019-03-17 16:07:20 -04:00
Adrien Béraud 1e10e28fd7 network: improve message parsing performance 2019-03-17 16:07:20 -04:00
Adrien Béraud dccdb84836 tests: add Value tester 2019-03-16 14:27:46 -04:00
Adrien Béraud 71599da8ea value: add "not" method 2019-03-16 14:27:23 -04:00
Adrien Béraud f418b3651f update copyright date 2019-03-16 12:37:23 -04:00
Adrien Béraud 313f54c840 dht: disable some verbose logs 2019-03-10 17:27:37 -04:00
Adrien Béraud cdb721ade4 dht: move store logic to storage 2019-03-10 17:04:26 -04:00
Adrien Béraud 57ea09808e value: fix chain null check 2019-03-10 16:39:31 -04:00
Adrien Béraud fec5a6ede7 make move operators noexcept 2019-03-10 16:39:16 -04:00
Adrien Béraud 5f8e9d9480 storage: make non-movable 2019-03-10 16:39:16 -04:00
Adrien Béraud 311a8981fc thread pool: add computation, io pools 2019-03-10 16:39:16 -04:00
Adrien Béraud 04850e1701 dht: add configuration to persist state 2019-03-10 16:39:16 -04:00
Adrien Béraud a30f1b8032 dht: make exportNodes const 2019-03-10 16:39:16 -04:00
89 changed files with 1133 additions and 606 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
Checks: '-*,clang-diagnostic-*,performance-*,bugprone-*,llvm-*,clang-analyzer-*,misc-*,-llvm-namespace-comment,-misc-unused-parameters,-misc-non-private-member-variables-in-classes,-llvm-header-guard,-llvm-include-order,-bugprone-suspicious-string-compare'
+3 -3
View File
@@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 3.1)
project (opendht)
set (opendht_VERSION_MAJOR 1)
set (opendht_VERSION_MINOR 8.1)
set (opendht_VERSION_MINOR 8.2)
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
set (PACKAGE_VERSION ${opendht_VERSION})
set (VERSION "${opendht_VERSION}")
@@ -70,8 +70,6 @@ set (CMAKE_CXX_STANDARD_REQUIRED on)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type -Wall -Wextra -Wnon-virtual-dtor -pedantic-errors -fvisibility=hidden")
if (OPENDHT_SANITIZE)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fstack-protector-strong")
else ()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-stack-protector")
endif ()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMSGPACK_DISABLE_LEGACY_NIL -DMSGPACK_DISABLE_LEGACY_CONVERT")
if (NOT CMAKE_BUILD_TYPE)
@@ -306,6 +304,8 @@ if (OPENDHT_TESTS)
list (APPEND test_FILES
tests/infohashtester.h
tests/infohashtester.cpp
tests/valuetester.h
tests/valuetester.cpp
tests/cryptotester.h
tests/cryptotester.cpp
tests/dhtrunnertester.h
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
*
* Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
*
+1 -1
View File
@@ -106,7 +106,7 @@ for r in results:
IRC: join us on Freenode at [`#opendht`](https://webchat.freenode.net/?channels=%23opendht).
## License
Copyright (C) 2014-2018 Savoir-faire Linux Inc.
Copyright (C) 2014-2019 Savoir-faire Linux Inc.
OpenDHT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+1 -1
View File
@@ -1,7 +1,7 @@
dnl define macros
m4_define([opendht_major_version], 1)
m4_define([opendht_minor_version], 8)
m4_define([opendht_patch_version], 1)
m4_define([opendht_patch_version], 2)
m4_define([opendht_version],
[opendht_major_version.opendht_minor_version.opendht_patch_version])
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+10 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -103,6 +103,9 @@ struct OPENDHT_PUBLIC Config {
/** Makes the DHT responsible to maintain its stored values. Consumes more ressources. */
bool maintain_storage;
/** If set, the dht will load its state from this file on start and save its state in this file on shutdown */
std::string persist_path;
};
/**
@@ -128,8 +131,8 @@ using CertificateStoreQuery = std::function<std::vector<std::shared_ptr<crypto::
typedef bool (*GetCallbackRaw)(std::shared_ptr<Value>, void *user_data);
OPENDHT_PUBLIC GetCallbackSimple bindGetCb(GetCallbackRaw raw_cb, void* user_data);
OPENDHT_PUBLIC GetCallback bindGetCb(GetCallbackSimple cb);
OPENDHT_PUBLIC GetCallbackSimple bindGetCb(const GetCallbackRaw& raw_cb, void* user_data);
OPENDHT_PUBLIC GetCallback bindGetCb(const GetCallbackSimple& cb);
using DoneCallback = std::function<void(bool success, const std::vector<std::shared_ptr<Node>>& nodes)>;
typedef void (*DoneCallbackRaw)(bool, std::vector<std::shared_ptr<Node>>*, void *user_data);
@@ -139,10 +142,10 @@ typedef bool (*FilterRaw)(const Value&, void *user_data);
using DoneCallbackSimple = std::function<void(bool success)>;
OPENDHT_PUBLIC ShutdownCallback bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data);
OPENDHT_PUBLIC ShutdownCallback bindShutdownCb(const ShutdownCallbackRaw& shutdown_cb_raw, void* user_data);
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackSimple donecb);
OPENDHT_PUBLIC DoneCallback bindDoneCb(DoneCallbackRaw raw_cb, void* user_data);
OPENDHT_PUBLIC DoneCallbackSimple bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data);
OPENDHT_PUBLIC Value::Filter bindFilterRaw(FilterRaw raw_filter, void* user_data);
OPENDHT_PUBLIC DoneCallback bindDoneCb(const DoneCallbackRaw& raw_cb, void* user_data);
OPENDHT_PUBLIC DoneCallbackSimple bindDoneCbSimple(const DoneCallbackSimpleRaw& raw_cb, void* user_data);
OPENDHT_PUBLIC Value::Filter bindFilterRaw(const FilterRaw& raw_filter, void* user_data);
}
+54 -17
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -66,7 +66,7 @@ using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certific
*/
struct OPENDHT_PUBLIC PublicKey
{
PublicKey() {}
PublicKey();
/**
* Takes ownership of an existing gnutls_pubkey.
@@ -115,7 +115,9 @@ struct OPENDHT_PUBLIC PublicKey
void msgpack_unpack(msgpack::object o);
gnutls_pubkey_t pk {};
gnutls_digest_algorithm_t getPreferredDigest() const;
gnutls_pubkey_t pk {nullptr};
private:
PublicKey(const PublicKey&) = delete;
PublicKey& operator=(const PublicKey&) = delete;
@@ -186,7 +188,7 @@ class OPENDHT_PUBLIC RevocationList
public:
RevocationList();
RevocationList(const Blob& b);
RevocationList(RevocationList&& o) : crl(o.crl) { o.crl = nullptr; }
RevocationList(RevocationList&& o) noexcept : crl(o.crl) { o.crl = nullptr; }
~RevocationList();
RevocationList& operator=(RevocationList&& o) { crl = o.crl; o.crl = nullptr; return *this; }
@@ -254,14 +256,48 @@ private:
RevocationList& operator=(const RevocationList&) = delete;
};
enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
class OPENDHT_PUBLIC CertificateRequest {
public:
CertificateRequest();
CertificateRequest(const uint8_t* data, size_t size);
CertificateRequest(const Blob& data) : CertificateRequest(data.data(), data.size()) {}
CertificateRequest(CertificateRequest&& o) noexcept : request(std::move(o.request)) {
o.request = nullptr;
}
CertificateRequest& operator=(CertificateRequest&& o) noexcept;
~CertificateRequest();
void setName(const std::string& name);
void setUID(const std::string& name);
void setAltName(NameType type, const std::string& name);
std::string getName() const;
std::string getUID() const;
void sign(const PrivateKey& key, const std::string& password = {});
bool verify() const;
Blob pack() const;
gnutls_x509_crq_t get() const { return request; }
private:
CertificateRequest(const CertificateRequest& o) = delete;
CertificateRequest& operator=(const CertificateRequest& o) = delete;
gnutls_x509_crq_t request {nullptr};
};
struct OPENDHT_PUBLIC Certificate {
Certificate() {}
Certificate() noexcept {}
/**
* Take ownership of existing gnutls structure
*/
Certificate(gnutls_x509_crt_t crt) : cert(crt) {}
Certificate(gnutls_x509_crt_t crt) noexcept : cert(crt) {}
Certificate(Certificate&& o) noexcept : cert(o.cert), issuer(std::move(o.issuer)) { o.cert = nullptr; };
@@ -392,8 +428,6 @@ struct OPENDHT_PUBLIC Certificate {
/** Read certificate issuer User ID (UID) */
std::string getIssuerUID() const;
enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
/** Read certificate alternative names */
std::vector<std::pair<NameType, std::string>> getAltNames() const;
@@ -431,7 +465,8 @@ struct OPENDHT_PUBLIC Certificate {
void addRevocationList(RevocationList&&);
void addRevocationList(std::shared_ptr<RevocationList>);
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", Identity ca = {}, bool is_ca = false);
static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false);
static Certificate generate(const CertificateRequest& request, const Identity& ca);
gnutls_x509_crt_t getCopy() const {
if (not cert)
@@ -472,7 +507,9 @@ struct OPENDHT_PUBLIC Certificate {
return {crts, crls};
}
gnutls_x509_crt_t cert {};
gnutls_digest_algorithm_t getPreferredDigest() const;
gnutls_x509_crt_t cert {nullptr};
std::shared_ptr<Certificate> issuer {};
private:
Certificate(const Certificate&) = delete;
@@ -500,10 +537,10 @@ struct OPENDHT_PUBLIC TrustList
};
TrustList();
TrustList(TrustList&& o) : trust(std::move(o.trust)) {
TrustList(TrustList&& o) noexcept : trust(std::move(o.trust)) {
o.trust = nullptr;
}
TrustList& operator=(TrustList&& o);
TrustList& operator=(TrustList&& o) noexcept;
~TrustList();
void add(const Certificate& crt);
void add(const RevocationList& crl);
@@ -513,7 +550,7 @@ struct OPENDHT_PUBLIC TrustList
private:
TrustList(const TrustList& o) = delete;
TrustList& operator=(const TrustList& o) = delete;
gnutls_x509_trust_list_t trust;
gnutls_x509_trust_list_t trust {nullptr};
};
template <class T>
@@ -611,11 +648,11 @@ using SecureBlob = secure_vector<uint8_t>;
* If not set, the generated certificate will be a self-signed CA.
* @param key_length stength of the generated private key (bits).
*/
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name, Identity ca, unsigned key_length, bool is_ca);
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode", Identity ca = {}, unsigned key_length = 4096);
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name, const Identity& ca, unsigned key_length, bool is_ca);
OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode", const Identity& ca = {}, unsigned key_length = 4096);
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name, Identity ca, bool is_ca);
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name = "dhtnode", Identity ca = {});
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name, const Identity& ca, bool is_ca);
OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name = "dhtnode", const Identity& ca = {});
/**
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ class OPENDHT_PUBLIC DhtMessage : public Value::Serializable<DhtMessage>
public:
static const ValueType TYPE;
DhtMessage(std::string s = {}, Blob msg = {}) : service(s), data(msg) {}
DhtMessage(const std::string& s = {}, const Blob& msg = {}) : service(s), data(msg) {}
std::string getService() const {
return service;
@@ -48,7 +48,7 @@ public:
static bool storePolicy(InfoHash key, std::shared_ptr<Value>& value, const InfoHash& from, const SockAddr&);
static Value::Filter ServiceFilter(std::string s);
static Value::Filter ServiceFilter(const std::string& s);
/** print value for debugging */
friend std::ostream& operator<< (std::ostream&, const DhtMessage&);
+16 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -68,7 +68,7 @@ public:
* Initialise the Dht with two open sockets (for IPv4 and IP6)
* and an ID for the node.
*/
Dht(const int& s, const int& s6, Config config);
Dht(const int& s, const int& s6, const Config& config);
virtual ~Dht();
/**
@@ -261,11 +261,14 @@ public:
* Get the list of good nodes for local storage saving purposes
* The list is ordered to minimize the back-to-work delay.
*/
std::vector<NodeExport> exportNodes();
std::vector<NodeExport> exportNodes() const;
std::vector<ValuesExport> exportValues() const;
void importValues(const std::vector<ValuesExport>&);
void saveState(const std::string& path) const;
void loadState(const std::string& path);
NodeStats getNodesStats(sa_family_t af) const;
std::string getStorageLog() const;
@@ -359,13 +362,6 @@ private:
// registred types
TypeStore types;
// are we a bootstrap node ?
// note: Any running node can be used as a bootstrap node.
// Only nodes running only as bootstrap nodes should
// be put in bootstrap mode.
const bool is_bootstrap {false};
const bool maintain_storage {false};
// the stuff
RoutingTable buckets4 {};
RoutingTable buckets6 {};
@@ -400,6 +396,15 @@ private:
std::mt19937_64 rd {crypto::getSeededRandomEngine<std::mt19937_64>()};
std::string persistPath;
// are we a bootstrap node ?
// note: Any running node can be used as a bootstrap node.
// Only nodes running only as bootstrap nodes should
// be put in bootstrap mode.
const bool is_bootstrap {false};
const bool maintain_storage {false};
void rotateSecrets();
Blob makeToken(const SockAddr&, bool old) const;
@@ -425,7 +430,7 @@ private:
* nodes.
*/
void dataPersistence(InfoHash id);
size_t maintainStorage(decltype(store)::value_type&, bool force=false, DoneCallback donecb=nullptr);
size_t maintainStorage(decltype(store)::value_type&, bool force=false, const DoneCallback& donecb={});
// Buckets
RoutingTable& buckets(sa_family_t af) { return af == AF_INET ? buckets4 : buckets6; }
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -181,7 +181,7 @@ public:
* Get the list of good nodes for local storage saving purposes
* The list is ordered to minimize the back-to-work delay.
*/
virtual std::vector<NodeExport> exportNodes() = 0;
virtual std::vector<NodeExport> exportNodes() const = 0;
virtual std::vector<ValuesExport> exportValues() const = 0;
virtual void importValues(const std::vector<ValuesExport>&) = 0;
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
@@ -235,7 +235,7 @@ public:
void insertNode(const InfoHash&, const sockaddr*, socklen_t) { }
void insertNode(const NodeExport&) { }
std::pair<size_t, size_t> getStoreSize() const { return {}; }
std::vector<NodeExport> exportNodes() { return {}; }
std::vector<NodeExport> exportNodes() const { return {}; }
std::vector<ValuesExport> exportValues() const { return {}; }
void importValues(const std::vector<ValuesExport>&) {}
std::string getStorageLog() const { return {}; }
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Savoir-faire Linux Inc.
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+6 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -354,7 +354,8 @@ public:
/*.node_id = */{},
/*.network = */network,
/*.is_bootstrap = */false,
/*.maintain_storage*/false
/*.maintain_storage = */false,
/*.persist_path = */{}
},
/*.id = */identity
},
@@ -363,7 +364,7 @@ public:
/*.push_node_id = */""
});
}
void run(in_port_t port, Config config);
void run(in_port_t port, const Config& config);
/**
* @param local4: Local IPv4 address and port to bind. Can be null.
@@ -373,12 +374,12 @@ public:
* @param threaded: If false, loop() must be called periodically. Otherwise a thread is launched.
* @param cb: Optional callback to receive general state information.
*/
void run(const SockAddr& local4, const SockAddr& local6, Config config);
void run(const SockAddr& local4, const SockAddr& local6, const Config& config);
/**
* Same as @run(sockaddr_in, sockaddr_in6, Identity, bool, StatusCallback), but with string IP addresses and service (port).
*/
void run(const char* ip4, const char* ip6, const char* service, Config config);
void run(const char* ip4, const char* ip6, const char* service, const Config& config);
void setOnStatusChanged(StatusCallback&& cb) {
statusCb = std::move(cb);
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Nicolas Reynaud <nicolas.reynaud@savoirfairelinux.com>
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+10 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2018 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -206,15 +206,15 @@ public:
NetworkEngine(Logger& log, Scheduler& scheduler, const int& s = -1, const int& s6 = -1);
NetworkEngine(InfoHash& myid, NetId net, const int& s, const int& s6, Logger& log, Scheduler& scheduler,
decltype(NetworkEngine::onError) onError,
decltype(NetworkEngine::onNewNode) onNewNode,
decltype(NetworkEngine::onReportedAddr) onReportedAddr,
decltype(NetworkEngine::onPing) onPing,
decltype(NetworkEngine::onFindNode) onFindNode,
decltype(NetworkEngine::onGetValues) onGetValues,
decltype(NetworkEngine::onListen) onListen,
decltype(NetworkEngine::onAnnounce) onAnnounce,
decltype(NetworkEngine::onRefresh) onRefresh);
decltype(NetworkEngine::onError)&& onError,
decltype(NetworkEngine::onNewNode)&& onNewNode,
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
decltype(NetworkEngine::onPing)&& onPing,
decltype(NetworkEngine::onFindNode)&& onFindNode,
decltype(NetworkEngine::onGetValues)&& onGetValues,
decltype(NetworkEngine::onListen)&& onListen,
decltype(NetworkEngine::onAnnounce)&& onAnnounce,
decltype(NetworkEngine::onRefresh)&& onRefresh);
virtual ~NetworkEngine();
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Savoir-faire Linux Inc.
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -43,8 +43,8 @@ public:
* result_type is unsigned int so this is currently safe.
*/
static_assert(
sizeof(result_type) == 2 ||
sizeof(result_type) == 4 ||
sizeof(result_type) == 2 ||
sizeof(result_type) == 4 ||
sizeof(result_type) == 8,
"result_type must be 16, 32 or 64 bits");
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+8 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -37,9 +37,9 @@ public:
using Config = SecureDhtConfig;
static dht::Config& getConfig(SecureDht::Config& conf)
static dht::Config getConfig(const SecureDht::Config& conf)
{
auto& c = conf.node_config;
auto c = conf.node_config;
if (not c.node_id and conf.id.second)
c.node_id = InfoHash::get("node:"+conf.id.second->getId().toString());
return c;
@@ -127,8 +127,8 @@ public:
Value decrypt(const Value& v);
void findCertificate(const InfoHash& node, std::function<void(const Sp<crypto::Certificate>)> cb);
void findPublicKey(const InfoHash& node, std::function<void(const Sp<const crypto::PublicKey>)> cb);
void findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<const crypto::PublicKey>)>& cb);
const Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
void registerCertificate(Sp<crypto::Certificate>& cert);
@@ -168,7 +168,7 @@ public:
void setStorageLimit(size_t limit = DEFAULT_STORAGE_LIMIT) override {
dht_->setStorageLimit(limit);
}
std::vector<NodeExport> exportNodes() override {
std::vector<NodeExport> exportNodes() const override {
return dht_->exportNodes();
}
std::vector<ValuesExport> exportValues() const override {
@@ -332,8 +332,8 @@ private:
SecureDht& operator=(const SecureDht&) = delete;
Sp<Value> checkValue(const Sp<Value>& v);
ValueCallback getCallbackFilter(ValueCallback, Value::Filter&&);
GetCallback getCallbackFilter(GetCallback, Value::Filter&&);
ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
Sp<crypto::PrivateKey> key_ {};
Sp<crypto::Certificate> certificate_ {};
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ public:
SockAddr(const SockAddr& o) {
set(o.get(), o.getLength());
}
SockAddr(SockAddr&& o) : len(o.len), addr(std::move(o.addr)) {
SockAddr(SockAddr&& o) noexcept : len(o.len), addr(std::move(o.addr)) {
o.len = 0;
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+17 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -79,7 +79,7 @@ static constexpr const size_t MAX_VALUE_SIZE {1024 * 64};
struct OPENDHT_PUBLIC ValueType {
typedef uint16_t Id;
static bool DEFAULT_STORE_POLICY(InfoHash, std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
static bool DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&);
static bool DEFAULT_EDIT_POLICY(InfoHash, const std::shared_ptr<Value>&, std::shared_ptr<Value>&, const InfoHash&, const SockAddr&) {
return false;
}
@@ -165,8 +165,15 @@ struct OPENDHT_PUBLIC Value
return chainOr(std::move(f1), std::move(f2));
}
static Filter chain(Filter&& f1, Filter&& f2) {
if (not f1) return std::move(f1);
if (not f2) return std::move(f2);
if (not f1) return std::move(f2);
if (not f2) return std::move(f1);
return [f1,f2](const Value& v) {
return f1(v) and f2(v);
};
}
static Filter chain(const Filter& f1, const Filter& f2) {
if (not f1) return f2;
if (not f2) return f1;
return [f1,f2](const Value& v) {
return f1(v) and f2(v);
};
@@ -189,6 +196,10 @@ struct OPENDHT_PUBLIC Value
return f1(v) or f2(v);
};
}
static Filter notFilter(Filter&& f) {
if (not f) return [](const Value&) { return false; };
return [f](const Value& v) { return not f(v); };
}
std::vector<Sp<Value>> filter(const std::vector<Sp<Value>>& values) {
if (not (*this))
return values;
@@ -874,7 +885,7 @@ struct OPENDHT_PUBLIC Query
{
static const std::string QUERY_PARSE_ERROR;
Query(Select s = {}, Where w = {}, bool none = false) : select(s), where(w), none(none) { };
Query(Select s = {}, Where w = {}, bool none = false) : select(std::move(s)), where(std::move(w)), none(none) { };
/**
* Initializes a query based on a SQL-ish formatted string. The abstract
@@ -936,7 +947,7 @@ struct OPENDHT_PUBLIC Query
*/
struct OPENDHT_PUBLIC FieldValueIndex {
FieldValueIndex() {}
FieldValueIndex(const Value& v, Select s = {});
FieldValueIndex(const Value& v, const Select& s = {});
/**
* Tells if all the fields of this are contained in the other
* FieldValueIndex with the same value.
+1 -1
View File
@@ -5,7 +5,7 @@
# distutils: libraries = opendht gnutls
# cython: language_level=3
#
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
# Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
+1 -1
View File
@@ -1,4 +1,4 @@
# Copyright (C) 2015-2017 Savoir-faire Linux Inc.
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2015-2016 Savoir-faire Linux Inc.
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
#
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2015 Savoir-Faire Linux Inc.
# Copyright (C) 2015-2019 Savoir-Faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
# Simon Désaulniers <sim.desaulniers@gmail.com>
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2015-2017 Savoir-faire Linux Inc.
# Copyright (C) 2015-2019 Savoir-faire Linux Inc.
# Author(s): Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2016 Savoir-faire Linux Inc.
# Copyright (c) 2016-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+3 -3
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2017 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
@@ -27,7 +27,7 @@ ping_node.run()
pong_node = dht.DhtRunner()
pong_node.run()
#pong_node.enableLogging()
pong_node.ping(ping_node.getBound());
pong_node.ping(ping_node.getBound())
loc_ping = dht.InfoHash.get("toto99")
loc_pong = dht.InfoHash.get(str(loc_ping))
@@ -42,7 +42,7 @@ def done(h, ok):
def ping(node, h):
global i
time.sleep(0.0075)
time.sleep(0.0075)
i += 1
if i < MAX:
node.put(h, dht.Value(b"hey"), lambda ok, nodes: done(node.getNodeId().decode(), ok))
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) 2015-2016 Savoir-faire Linux Inc.
# Copyright (c) 2015-2019 Savoir-faire Linux Inc.
# Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
#
# This program is free software; you can redistribute it and/or modify
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 Savoir-faire Linux Inc.
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,8 +17,8 @@
#include "base64.h"
#include <stdint.h>
#include <stdlib.h>
#include <cstdint>
#include <cstdlib>
/* Mainly based on the following stackoverflow question:
* http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2004-2017 Savoir-faire Linux Inc.
* Copyright (C) 2004-2019 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+5 -5
View File
@@ -4,7 +4,7 @@ namespace dht {
GetCallbackSimple
bindGetCb(GetCallbackRaw raw_cb, void* user_data)
bindGetCb(const GetCallbackRaw& raw_cb, void* user_data)
{
if (not raw_cb) return {};
return [=](const std::shared_ptr<Value>& value) {
@@ -13,7 +13,7 @@ bindGetCb(GetCallbackRaw raw_cb, void* user_data)
}
GetCallback
bindGetCb(GetCallbackSimple cb)
bindGetCb(const GetCallbackSimple& cb)
{
if (not cb) return {};
return [=](const std::vector<std::shared_ptr<Value>>& values) {
@@ -25,7 +25,7 @@ bindGetCb(GetCallbackSimple cb)
}
ShutdownCallback
bindShutdownCb(ShutdownCallbackRaw shutdown_cb_raw, void* user_data)
bindShutdownCb(const ShutdownCallbackRaw& shutdown_cb_raw, void* user_data)
{
return [=]() { shutdown_cb_raw(user_data); };
}
@@ -39,7 +39,7 @@ bindDoneCb(DoneCallbackSimple donecb)
}
DoneCallback
bindDoneCb(DoneCallbackRaw raw_cb, void* user_data)
bindDoneCb(const DoneCallbackRaw& raw_cb, void* user_data)
{
if (not raw_cb) return {};
return [=](bool success, const std::vector<std::shared_ptr<Node>>& nodes) {
@@ -48,7 +48,7 @@ bindDoneCb(DoneCallbackRaw raw_cb, void* user_data)
}
DoneCallbackSimple
bindDoneCbSimple(DoneCallbackSimpleRaw raw_cb, void* user_data) {
bindDoneCbSimple(const DoneCallbackSimpleRaw& raw_cb, void* user_data) {
if (not raw_cb) return {};
return [=](bool success) {
raw_cb(success, user_data);
+265 -106
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -40,31 +40,6 @@ static std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint
static std::uniform_int_distribution<uint8_t> rand_byte;
#endif
static gnutls_digest_algorithm_t get_dig_for_pub(gnutls_pubkey_t pubkey)
{
gnutls_digest_algorithm_t dig;
int result = gnutls_pubkey_get_preferred_hash_algorithm(pubkey, &dig, nullptr);
if (result < 0)
return GNUTLS_DIG_UNKNOWN;
return dig;
}
static gnutls_digest_algorithm_t get_dig(gnutls_x509_crt_t crt)
{
gnutls_pubkey_t pubkey;
gnutls_pubkey_init(&pubkey);
int result = gnutls_pubkey_import_x509(pubkey, crt, 0);
if (result < 0) {
gnutls_pubkey_deinit(pubkey);
return GNUTLS_DIG_UNKNOWN;
}
gnutls_digest_algorithm_t dig = get_dig_for_pub(pubkey);
gnutls_pubkey_deinit(pubkey);
return dig;
}
// support for GnuTLS < 3.4.
#if GNUTLS_VERSION_NUMBER < 0x030400
#define GNUTLS_PKCS_PKCS12_3DES GNUTLS_PKCS_USE_PKCS12_3DES
@@ -377,15 +352,19 @@ PrivateKey::serialize(const std::string& password) const
PublicKey
PrivateKey::getPublicKey() const
{
gnutls_pubkey_t pk;
gnutls_pubkey_init(&pk);
PublicKey pk_ret {pk};
if (gnutls_pubkey_import_privkey(pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0) != GNUTLS_E_SUCCESS)
return {};
return pk_ret;
PublicKey pk;
if (auto err = gnutls_pubkey_import_privkey(pk.pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0))
throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err));
return pk;
}
PublicKey::PublicKey(const Blob& dat) : pk(nullptr)
PublicKey::PublicKey()
{
if (auto err = gnutls_pubkey_init(&pk))
throw CryptoException(std::string("Can't initialize public key: ") + gnutls_strerror(err));
}
PublicKey::PublicKey(const Blob& dat) : PublicKey()
{
unpack(dat.data(), dat.size());
}
@@ -415,8 +394,7 @@ PublicKey::pack(Blob& b) const
throw CryptoException(std::string("Could not export public key: null key"));
std::vector<uint8_t> tmp(2048);
size_t sz = tmp.size();
int err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_DER, tmp.data(), &sz);
if (err != GNUTLS_E_SUCCESS)
if (int err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_DER, tmp.data(), &sz))
throw CryptoException(std::string("Could not export public key: ") + gnutls_strerror(err));
tmp.resize(sz);
b.insert(b.end(), tmp.begin(), tmp.end());
@@ -425,9 +403,6 @@ PublicKey::pack(Blob& b) const
void
PublicKey::unpack(const uint8_t* data, size_t data_size)
{
if (pk)
gnutls_pubkey_deinit(pk);
gnutls_pubkey_init(&pk);
const gnutls_datum_t dat {(uint8_t*)data, (unsigned)data_size};
int err = gnutls_pubkey_import(pk, &dat, GNUTLS_X509_FMT_PEM);
if (err != GNUTLS_E_SUCCESS)
@@ -446,10 +421,9 @@ PublicKey::toString() const
int err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_PEM, (void*)ret.data(), &sz);
if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) {
ret.resize(sz);
int err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_PEM, (void*)ret.data(), &sz);
if (err != GNUTLS_E_SUCCESS)
throw CryptoException(std::string("Could not print public key: ") + gnutls_strerror(err));
} else if (err != GNUTLS_E_SUCCESS)
err = gnutls_pubkey_export(pk, GNUTLS_X509_FMT_PEM, (void*)ret.data(), &sz);
}
if (err != GNUTLS_E_SUCCESS)
throw CryptoException(std::string("Could not print public key: ") + gnutls_strerror(err));
return ret;
}
@@ -572,7 +546,180 @@ PublicKey::getLongId() const
#endif
}
Certificate::Certificate(const Blob& certData) : cert(nullptr)
gnutls_digest_algorithm_t
PublicKey::getPreferredDigest() const
{
gnutls_digest_algorithm_t dig;
int result = gnutls_pubkey_get_preferred_hash_algorithm(pk, &dig, nullptr);
if (result < 0)
return GNUTLS_DIG_UNKNOWN;
return dig;
}
// Certificate Request
static NameType
typeFromGnuTLS(gnutls_x509_subject_alt_name_t type)
{
switch(type) {
case GNUTLS_SAN_DNSNAME:
return NameType::DNS;
case GNUTLS_SAN_RFC822NAME:
return NameType::RFC822;
case GNUTLS_SAN_URI:
return NameType::URI;
case GNUTLS_SAN_IPADDRESS:
return NameType::IP;
default:
return NameType::UNKNOWN;
}
}
static gnutls_x509_subject_alt_name_t
GnuTLSFromType(NameType type)
{
switch(type) {
case NameType::DNS:
return GNUTLS_SAN_DNSNAME;
case NameType::RFC822:
return GNUTLS_SAN_RFC822NAME;
case NameType::URI:
return GNUTLS_SAN_URI;
case NameType::IP:
return GNUTLS_SAN_IPADDRESS;
default:
return (gnutls_x509_subject_alt_name_t)0;
}
}
static std::string
getDN(gnutls_x509_crq_t request, const char* oid)
{
std::string dn;
dn.resize(512);
size_t dn_sz = dn.size();
int ret = gnutls_x509_crq_get_dn_by_oid(request, oid, 0, 0, &(*dn.begin()), &dn_sz);
if (ret != GNUTLS_E_SUCCESS)
return {};
dn.resize(dn_sz);
return dn;
}
CertificateRequest::CertificateRequest()
{
if (auto err = gnutls_x509_crq_init(&request))
throw CryptoException(std::string("Can't initialize certificate request: ") + gnutls_strerror(err));
}
CertificateRequest::CertificateRequest(const uint8_t* data, size_t size) : CertificateRequest()
{
const gnutls_datum_t dat {(uint8_t*)data, (unsigned)size};
if (auto err = gnutls_x509_crq_import(request, &dat, GNUTLS_X509_FMT_PEM))
throw CryptoException(std::string("Can't import certificate request: ") + gnutls_strerror(err));
}
CertificateRequest::~CertificateRequest()
{
if (request) {
gnutls_x509_crq_deinit(request);
request = nullptr;
}
}
CertificateRequest&
CertificateRequest::operator=(CertificateRequest&& o) noexcept
{
if (request)
gnutls_x509_crq_deinit(request);
request = o.request;
o.request = nullptr;
return *this;
}
void
CertificateRequest::setAltName(NameType type, const std::string& name)
{
gnutls_x509_crq_set_subject_alt_name(request, GnuTLSFromType(type), name.data(), name.size(), 0);
}
void
CertificateRequest::setName(const std::string& name)
{
gnutls_x509_crq_set_dn_by_oid(request, GNUTLS_OID_X520_COMMON_NAME, 0, name.data(), name.length());
}
std::string
CertificateRequest::getName() const
{
return getDN(request, GNUTLS_OID_X520_COMMON_NAME);
}
std::string
CertificateRequest::getUID() const
{
return getDN(request, GNUTLS_OID_LDAP_UID);
}
void
CertificateRequest::setUID(const std::string& uid)
{
gnutls_x509_crq_set_dn_by_oid(request, GNUTLS_OID_LDAP_UID, 0, uid.data(), uid.length());
}
void
CertificateRequest::sign(const PrivateKey& key, const std::string& password)
{
gnutls_x509_crq_set_version(request, 1);
if (not password.empty())
gnutls_x509_crq_set_challenge_password(request, password.c_str());
if (auto err = gnutls_x509_crq_set_key(request, key.x509_key))
throw CryptoException(std::string("Can't set certificate request key: ") + gnutls_strerror(err));
#if GNUTLS_VERSION_NUMBER < 0x030601
if (auto err = gnutls_x509_crq_privkey_sign(request, key.key, key.getPublicKey().getPreferredDigest(), 0))
throw CryptoException(std::string("Can't sign certificate request: ") + gnutls_strerror(err));
#else
if (auto err = gnutls_x509_crq_privkey_sign(request, key.key, GNUTLS_DIG_UNKNOWN, 0))
throw CryptoException(std::string("Can't sign certificate request: ") + gnutls_strerror(err));
#endif
}
bool
CertificateRequest::verify() const
{
return gnutls_x509_crq_verify(request, 0) >= 0;
}
Blob
CertificateRequest::pack() const
{
gnutls_datum_t dat {nullptr, 0};
if (auto err = gnutls_x509_crq_export2(request, GNUTLS_X509_FMT_PEM, &dat))
throw CryptoException(std::string("Can't export certificate request: ") + gnutls_strerror(err));
Blob ret(dat.data, dat.data + dat.size);
gnutls_free(dat.data);
return ret;
}
// Certificate
static std::string
getDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false)
{
std::string dn;
dn.resize(512);
size_t dn_sz = dn.size();
int ret = issuer
? gnutls_x509_crt_get_issuer_dn_by_oid(cert, oid, 0, 0, &(*dn.begin()), &dn_sz)
: gnutls_x509_crt_get_dn_by_oid( cert, oid, 0, 0, &(*dn.begin()), &dn_sz);
if (ret != GNUTLS_E_SUCCESS)
return {};
dn.resize(dn_sz);
return dn;
}
Certificate::Certificate(const Blob& certData)
{
unpack(certData.data(), certData.size());
}
@@ -656,11 +803,9 @@ Certificate::~Certificate()
PublicKey
Certificate::getPublicKey() const
{
gnutls_pubkey_t pk;
gnutls_pubkey_init(&pk);
PublicKey pk_ret(pk);
if (gnutls_pubkey_import_x509(pk, cert, 0) != GNUTLS_E_SUCCESS)
return {};
PublicKey pk_ret;
if (auto err = gnutls_pubkey_import_x509(pk_ret.pk, cert, 0))
throw CryptoException(std::string("Can't get certificate public key: ") + gnutls_strerror(err));
return pk_ret;
}
@@ -696,21 +841,6 @@ Certificate::getLongId() const
#endif
}
static std::string
getDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false)
{
std::string dn;
dn.resize(512);
size_t dn_sz = dn.size();
int ret = issuer
? gnutls_x509_crt_get_issuer_dn_by_oid(cert, oid, 0, 0, &(*dn.begin()), &dn_sz)
: gnutls_x509_crt_get_dn_by_oid( cert, oid, 0, 0, &(*dn.begin()), &dn_sz);
if (ret != GNUTLS_E_SUCCESS)
return {};
dn.resize(dn_sz);
return dn;
}
std::string
Certificate::getName() const
{
@@ -735,24 +865,7 @@ Certificate::getIssuerUID() const
return getDN(cert, GNUTLS_OID_LDAP_UID, true);
}
static Certificate::NameType
typeFromGnuTLS(gnutls_x509_subject_alt_name_t type)
{
switch(type) {
case GNUTLS_SAN_DNSNAME:
return Certificate::NameType::DNS;
case GNUTLS_SAN_RFC822NAME:
return Certificate::NameType::RFC822;
case GNUTLS_SAN_URI:
return Certificate::NameType::URI;
case GNUTLS_SAN_IPADDRESS:
return Certificate::NameType::IP;
default:
return Certificate::NameType::UNKNOWN;
}
}
std::vector<std::pair<Certificate::NameType, std::string>>
std::vector<std::pair<NameType, std::string>>
Certificate::getAltNames() const
{
std::vector<std::pair<NameType, std::string>> names;
@@ -867,6 +980,14 @@ Certificate::getExpiration() const
return std::chrono::system_clock::from_time_t(t);
}
gnutls_digest_algorithm_t
Certificate::getPreferredDigest() const
{
return getPublicKey().getPreferredDigest();
}
// PrivateKey
PrivateKey
PrivateKey::generate(unsigned key_length)
{
@@ -896,7 +1017,7 @@ PrivateKey::generateEC()
}
Identity
generateIdentity(const std::string& name, crypto::Identity ca, unsigned key_length, bool is_ca)
generateIdentity(const std::string& name, const Identity& ca, unsigned key_length, bool is_ca)
{
auto key = std::make_shared<PrivateKey>(PrivateKey::generate(key_length));
auto cert = std::make_shared<Certificate>(Certificate::generate(*key, name, ca, is_ca));
@@ -905,12 +1026,12 @@ generateIdentity(const std::string& name, crypto::Identity ca, unsigned key_leng
Identity
generateIdentity(const std::string& name, Identity ca, unsigned key_length) {
generateIdentity(const std::string& name, const Identity& ca, unsigned key_length) {
return generateIdentity(name, ca, key_length, !ca.first || !ca.second);
}
Identity
generateEcIdentity(const std::string& name, crypto::Identity ca, bool is_ca)
generateEcIdentity(const std::string& name, const Identity& ca, bool is_ca)
{
auto key = std::make_shared<PrivateKey>(PrivateKey::generateEC());
auto cert = std::make_shared<Certificate>(Certificate::generate(*key, name, ca, is_ca));
@@ -918,25 +1039,40 @@ generateEcIdentity(const std::string& name, crypto::Identity ca, bool is_ca)
}
Identity
generateEcIdentity(const std::string& name, Identity ca) {
generateEcIdentity(const std::string& name, const Identity& ca) {
return generateEcIdentity(name, ca, !ca.first || !ca.second);
}
void
setValidityPeriod(gnutls_x509_crt_t cert, int64_t validity)
{
int64_t now = time(nullptr);
/* 2038 bug: don't allow time wrap */
auto boundTime = [](int64_t t) -> time_t {
return std::min<int64_t>(t, std::numeric_limits<time_t>::max());
};
gnutls_x509_crt_set_activation_time(cert, boundTime(now));
gnutls_x509_crt_set_expiration_time(cert, boundTime(now + validity));
}
void
setRandomSerial(gnutls_x509_crt_t cert)
{
random_device rdev;
std::uniform_int_distribution<uint64_t> dist{};
uint64_t cert_serial = dist(rdev);
gnutls_x509_crt_set_serial(cert, &cert_serial, sizeof(cert_serial));
}
Certificate
Certificate::generate(const PrivateKey& key, const std::string& name, Identity ca, bool is_ca)
Certificate::generate(const PrivateKey& key, const std::string& name, const Identity& ca, bool is_ca)
{
gnutls_x509_crt_t cert;
if (not key.x509_key or gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
return {};
Certificate ret {cert};
int64_t now = time(NULL);
/* 2038 bug: don't allow time wrap */
auto boundTime = [](int64_t t) -> time_t {
return std::min<int64_t>(t, std::numeric_limits<time_t>::max());
};
gnutls_x509_crt_set_activation_time(cert, boundTime(now));
gnutls_x509_crt_set_expiration_time(cert, boundTime(now + (10 * 365 * 24 * 60 * 60)));
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
if (gnutls_x509_crt_set_key(cert, key.x509_key) != GNUTLS_E_SUCCESS) {
std::cerr << "Error when setting certificate key" << std::endl;
return {};
@@ -947,19 +1083,15 @@ Certificate::generate(const PrivateKey& key, const std::string& name, Identity c
}
// TODO: compute the subject key using the recommended RFC method
auto pk_id = key.getPublicKey().getId();
auto pk = key.getPublicKey();
auto pk_id = pk.getId();
const std::string uid_str = pk_id.toString();
gnutls_x509_crt_set_subject_key_id(cert, &pk_id, sizeof(pk_id));
gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0, name.data(), name.length());
gnutls_x509_crt_set_dn_by_oid(cert, GNUTLS_OID_LDAP_UID, 0, uid_str.data(), uid_str.length());
{
random_device rdev;
std::uniform_int_distribution<uint64_t> dist{};
uint64_t cert_serial = dist(rdev);
gnutls_x509_crt_set_serial(cert, &cert_serial, sizeof(cert_serial));
}
setRandomSerial(cert);
unsigned key_usage = 0;
if (is_ca) {
@@ -975,15 +1107,13 @@ Certificate::generate(const PrivateKey& key, const std::string& name, Identity c
// Signing certificate must be CA.
return {};
}
//if (gnutls_x509_crt_sign2(cert, ca.second->cert, ca.first->x509_key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if (gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if (gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, pk.getPreferredDigest(), 0) != GNUTLS_E_SUCCESS) {
std::cerr << "Error when signing certificate" << std::endl;
return {};
}
ret.issuer = ca.second;
} else {
//if (gnutls_x509_crt_sign2(cert, cert, key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if (gnutls_x509_crt_privkey_sign(cert, cert, key.key, get_dig(cert), 0) != GNUTLS_E_SUCCESS) {
if (gnutls_x509_crt_privkey_sign(cert, cert, key.key, pk.getPreferredDigest(), 0) != GNUTLS_E_SUCCESS) {
std::cerr << "Error when signing certificate" << std::endl;
return {};
}
@@ -992,6 +1122,31 @@ Certificate::generate(const PrivateKey& key, const std::string& name, Identity c
return ret.getPacked();
}
Certificate
Certificate::generate(const CertificateRequest& request, const Identity& ca)
{
gnutls_x509_crt_t cert;
if (auto err = gnutls_x509_crt_init(&cert))
throw CryptoException(std::string("Can't initialize certificate: ") + gnutls_strerror(err));
Certificate ret {cert};
if (auto err = gnutls_x509_crt_set_crq(cert, request.get()))
throw CryptoException(std::string("Can't initialize certificate: ") + gnutls_strerror(err));
if (auto err = gnutls_x509_crt_set_version(cert, 3)) {
throw CryptoException(std::string("Can't set certificate version: ") + gnutls_strerror(err));
}
setValidityPeriod(cert, 10 * 365 * 24 * 60 * 60);
setRandomSerial(cert);
if (auto err = gnutls_x509_crt_privkey_sign(cert, ca.second->cert, ca.first->key, ca.second->getPreferredDigest(), 0)) {
throw CryptoException(std::string("Can't sign certificate: ") + gnutls_strerror(err));
}
ret.issuer = ca.second;
return ret.getPacked();
}
std::vector<std::shared_ptr<RevocationList>>
Certificate::getRevocationLists() const
{
@@ -1002,6 +1157,8 @@ Certificate::getRevocationLists() const
return ret;
}
// RevocationList
RevocationList::RevocationList()
{
gnutls_x509_crl_init(&crl);
@@ -1219,6 +1376,8 @@ RevocationList::toString() const
return ret;
}
// TrustList
TrustList::TrustList() {
gnutls_x509_trust_list_init(&trust, 0);
}
@@ -1228,11 +1387,11 @@ TrustList::~TrustList() {
}
TrustList&
TrustList::operator=(TrustList&& o)
TrustList::operator=(TrustList&& o) noexcept
{
if (trust)
gnutls_x509_trust_list_deinit(trust, true);
trust = std::move(o.trust);
trust = o.trust;
o.trust = nullptr;
return *this;
}
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -38,7 +38,7 @@ DhtMessage::storePolicy(InfoHash h, std::shared_ptr<Value>& v, const InfoHash& f
}
Value::Filter
DhtMessage::ServiceFilter(std::string s)
DhtMessage::ServiceFilter(const std::string& s)
{
return Value::Filter::chain(
Value::TypeFilter(TYPE),
+92 -48
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2018 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -29,6 +29,7 @@
#include <algorithm>
#include <random>
#include <sstream>
#include <fstream>
namespace dht {
@@ -54,6 +55,9 @@ Dht::getStatus(sa_family_t af) const
void
Dht::shutdown(ShutdownCallback cb)
{
if (not persistPath.empty())
saveState(persistPath);
if (not maintain_storage) {
if (cb) cb();
return;
@@ -533,7 +537,7 @@ Dht::searchSynchedNodeListen(const Sp<Search>& sr, SearchNode& n)
if (auto sr = ws.lock()) {
auto l = sr->listeners.find(list_token);
if (l != sr->listeners.end()) {
l->second.get_cb(l->second.filter.filter(values), expired);
l->second.get_cb(values, expired);
}
}
}, [ws,list_token] (ListenSyncStatus status) {
@@ -832,41 +836,28 @@ Dht::listen(const InfoHash& id, ValueCallback cb, Value::Filter f, Where where)
{
scheduler.syncTime();
Query q {{}, where};
auto vals = std::make_shared<std::map<Value::Id, Sp<Value>>>();
auto token = ++listener_token;
auto gcb = OpValueCache::cacheCallback(std::move(cb), [this, id, token]{
cancelListen(id, token);
});
auto query = std::make_shared<Query>(q);
auto filter = f.chain(q.where.getFilter());
size_t tokenlocal = 0;
auto query = std::make_shared<Query>(Select{}, std::move(where));
auto filter = f.chain(query->where.getFilter());
auto st = store.find(id);
if (st == store.end() && store.size() < MAX_HASHES)
st = store.emplace(id, scheduler.time() + MAX_STORAGE_MAINTENANCE_EXPIRE_TIME).first;
size_t tokenlocal = 0;
if (st != store.end()) {
if (not st->second.empty()) {
std::vector<Sp<Value>> newvals = st->second.get(filter);
if (not newvals.empty()) {
if (!gcb(newvals, false))
return 0;
for (const auto& v : newvals) {
auto it = vals->emplace(v->id, v);
if (not it.second)
it.first->second = v;
}
}
}
tokenlocal = ++st->second.listener_token;
st->second.local_listeners.emplace(tokenlocal, LocalListener{query, filter, gcb});
tokenlocal = st->second.listen(gcb, filter, query);
if (tokenlocal == 0)
return 0;
}
auto token4 = Dht::listenTo(id, AF_INET, gcb, filter, query);
auto token6 = token4 == 0 ? 0 : Dht::listenTo(id, AF_INET6, gcb, filter, query);
if (token6 == 0 && st != store.end()) {
st->second.local_listeners.erase(tokenlocal);
st->second.cancelListen(tokenlocal);
return 0;
}
@@ -885,15 +876,17 @@ Dht::cancelListen(const InfoHash& id, size_t token)
return false;
}
DHT_LOG.d(id, "cancelListen %s with token %d", id.toString().c_str(), token);
auto st = store.find(id);
auto tokenlocal = std::get<0>(it->second);
if (st != store.end() && tokenlocal)
st->second.local_listeners.erase(tokenlocal);
if (auto tokenlocal = std::get<0>(it->second)) {
auto st = store.find(id);
if (st != store.end())
st->second.cancelListen(tokenlocal);
}
auto searches_cancel_listen = [this,&id](std::map<InfoHash, Sp<Search>>& srs, size_t token) {
auto srp = srs.find(id);
if (srp != srs.end() and token)
srp->second->cancelListen(token, scheduler);
if (token) {
auto srp = srs.find(id);
if (srp != srs.end())
srp->second->cancelListen(token, scheduler);
}
};
searches_cancel_listen(searches4, std::get<1>(it->second));
searches_cancel_listen(searches6, std::get<2>(it->second));
@@ -1272,16 +1265,16 @@ Dht::storageAddListener(const InfoHash& id, const Sp<Node>& node, size_t socket_
return;
st = store.emplace(id, now).first;
}
auto node_listeners = st->second.listeners.emplace(node, std::map<size_t, Listener> {}).first;
auto l = node_listeners->second.find(socket_id);
if (l == node_listeners->second.end()) {
auto& node_listeners = st->second.listeners[node];
auto l = node_listeners.find(socket_id);
if (l == node_listeners.end()) {
auto vals = st->second.get(query.where.getFilter());
if (not vals.empty()) {
network_engine.tellListener(node, socket_id, id, WANT4 | WANT6, makeToken(node->getAddr(), false),
buckets4.findClosestNodes(id, now, TARGET_NODES), buckets6.findClosestNodes(id, now, TARGET_NODES),
std::move(vals), query);
}
node_listeners->second.emplace(socket_id, Listener {now, std::forward<Query>(query)});
node_listeners.emplace(socket_id, Listener {now, std::forward<Query>(query)});
}
else
l->second.refresh(now, std::forward<Query>(query));
@@ -1721,10 +1714,8 @@ Dht::~Dht()
Dht::Dht() : store(), network_engine(DHT_LOG, scheduler) {}
Dht::Dht(const int& s, const int& s6, Config config)
: myid(config.node_id ? config.node_id : InfoHash::getRandom()),
is_bootstrap(config.is_bootstrap),
maintain_storage(config.maintain_storage), store(), store_quota(),
Dht::Dht(const int& s, const int& s6, const Config& config)
: myid(config.node_id ? config.node_id : InfoHash::getRandom()), store(), store_quota(),
network_engine(myid, config.network, s, s6, DHT_LOG, scheduler,
std::bind(&Dht::onError, this, _1, _2),
std::bind(&Dht::onNewNode, this, _1, _2),
@@ -1734,7 +1725,10 @@ Dht::Dht(const int& s, const int& s6, Config config)
std::bind(&Dht::onGetValues, this, _1, _2, _3, _4),
std::bind(&Dht::onListen, this, _1, _2, _3, _4, _5),
std::bind(&Dht::onAnnounce, this, _1, _2, _3, _4, _5),
std::bind(&Dht::onRefresh, this, _1, _2, _3, _4))
std::bind(&Dht::onRefresh, this, _1, _2, _3, _4)),
persistPath(config.persist_path),
is_bootstrap(config.is_bootstrap),
maintain_storage(config.maintain_storage)
{
scheduler.syncTime();
if (s < 0 && s6 < 0)
@@ -1765,8 +1759,10 @@ Dht::Dht(const int& s, const int& s6, Config config)
expire();
DHT_LOG.d("DHT initialised with node ID %s", myid.toString().c_str());
}
if (not persistPath.empty())
loadState(persistPath);
}
bool
Dht::neighbourhoodMaintenance(RoutingTable& list)
@@ -1850,12 +1846,12 @@ Dht::bucketMaintenance(RoutingTable& list)
}
DHT_LOG.d(id, n->id, "[node %s] sending find %s for bucket maintenance", n->toString().c_str(), id.toString().c_str());
auto start = scheduler.time();
network_engine.sendFindNode(n, id, want, nullptr, [this,start,n](const net::Request&, bool over) {
//auto start = scheduler.time();
network_engine.sendFindNode(n, id, want, nullptr, [this,n](const net::Request&, bool over) {
if (over) {
const auto& end = scheduler.time();
using namespace std::chrono;
DHT_LOG.d(n->id, "[node %s] bucket maintenance op expired after %llu ms", n->toString().c_str(), duration_cast<milliseconds>(end-start).count());
// using namespace std::chrono;
// DHT_LOG.d(n->id, "[node %s] bucket maintenance op expired after %llu ms", n->toString().c_str(), duration_cast<milliseconds>(end-start).count());
scheduler.edit(nextNodesConfirmation, end + Node::MAX_RESPONSE_TIME);
}
});
@@ -1881,7 +1877,7 @@ Dht::dataPersistence(InfoHash id)
}
size_t
Dht::maintainStorage(decltype(store)::value_type& storage, bool force, DoneCallback donecb)
Dht::maintainStorage(decltype(store)::value_type& storage, bool force, const DoneCallback& donecb)
{
const auto& now = scheduler.time();
size_t announce_per_af = 0;
@@ -2056,7 +2052,7 @@ Dht::importValues(const std::vector<ValuesExport>& import)
std::vector<NodeExport>
Dht::exportNodes()
Dht::exportNodes() const
{
const auto& now = scheduler.time();
std::vector<NodeExport> nodes;
@@ -2283,7 +2279,7 @@ Dht::onListen(Sp<Node> node, const InfoHash& hash, const Blob& token, size_t soc
}
void
Dht::onListenDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>& sr)
Dht::onListenDone(const Sp<Node>& /* node */, net::RequestAnswer& /* answer */, Sp<Search>& sr)
{
// DHT_LOG.d(sr->id, node->id, "[search %s] [node %s] got listen confirmation",
// sr->id.toString().c_str(), node->toString().c_str(), answer.values.size());
@@ -2424,4 +2420,52 @@ Dht::onAnnounceDone(const Sp<Node>& node, net::RequestAnswer& answer, Sp<Search>
sr->checkAnnounced(answer.vid);
}
void
Dht::saveState(const std::string& path) const
{
std::ofstream file(path);
msgpack::pack(file, exportNodes());
msgpack::pack(file, exportValues());
}
void
Dht::loadState(const std::string& path)
{
DHT_LOG.d("Importing state from %s", path.c_str());
try {
// Import nodes from binary file
msgpack::unpacker pac;
{
// Read whole file
std::ifstream file(path, std::ios::binary|std::ios::ate);
if (!file.is_open()) {
return;
}
auto size = file.tellg();
file.seekg (0, std::ios::beg);
pac.reserve_buffer(size);
file.read (pac.buffer(), size);
pac.buffer_consumed(size);
}
// Import nodes
msgpack::object_handle oh;
if (pac.next(oh)) {
{
auto imported_nodes = oh.get().as<std::vector<NodeExport>>();
DHT_LOG.d("Importing %zu nodes", imported_nodes.size());
for (const auto& node : imported_nodes)
insertNode(node);
}
if (pac.next(oh)) {
auto imported_values = oh.get().as<std::vector<ValuesExport>>();
DHT_LOG.d("Importing %zu values", imported_values.size());
importValues(imported_values);
}
}
} catch (const std::exception& e) {
DHT_LOG.w("Error importing state from %s: %s", path.c_str(), e.what());
}
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016-2018 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Savoir-faire Linux Inc.
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
* Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+14 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -75,7 +75,7 @@ DhtRunner::~DhtRunner()
}
void
DhtRunner::run(in_port_t port, DhtRunner::Config config)
DhtRunner::run(in_port_t port, const DhtRunner::Config& config)
{
SockAddr sin4;
sin4.setFamily(AF_INET);
@@ -87,7 +87,7 @@ DhtRunner::run(in_port_t port, DhtRunner::Config config)
}
void
DhtRunner::run(const char* ip4, const char* ip6, const char* service, DhtRunner::Config config)
DhtRunner::run(const char* ip4, const char* ip6, const char* service, const DhtRunner::Config& config)
{
auto res4 = SockAddr::resolve(ip4, service);
auto res6 = SockAddr::resolve(ip6, service);
@@ -96,7 +96,7 @@ DhtRunner::run(const char* ip4, const char* ip6, const char* service, DhtRunner:
}
void
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, DhtRunner::Config config)
DhtRunner::run(const SockAddr& local4, const SockAddr& local6, const DhtRunner::Config& config)
{
if (running)
return;
@@ -629,7 +629,7 @@ DhtRunner::get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops.emplace([=](SecureDht& dht) mutable {
dht.get(hash, vcb, dcb, std::move(f), std::move(w));
dht.get(hash, std::move(vcb), std::move(dcb), std::move(f), std::move(w));
});
}
cv.notify_all();
@@ -638,14 +638,14 @@ DhtRunner::get(InfoHash hash, GetCallback vcb, DoneCallback dcb, Value::Filter f
void
DhtRunner::get(const std::string& key, GetCallback vcb, DoneCallbackSimple dcb, Value::Filter f, Where w)
{
get(InfoHash::get(key), vcb, dcb, f, w);
get(InfoHash::get(key), std::move(vcb), std::move(dcb), std::move(f), std::move(w));
}
void
DhtRunner::query(const InfoHash& hash, QueryCallback cb, DoneCallback done_cb, Query q) {
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops.emplace([=](SecureDht& dht) mutable {
dht.query(hash, cb, done_cb, std::move(q));
dht.query(hash, std::move(cb), std::move(done_cb), std::move(q));
});
}
cv.notify_all();
@@ -678,7 +678,7 @@ DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
listeners_.emplace(tokenbGlobal, std::move(listener));
ret_token->set_value(tokenbGlobal);
#else
ret_token->set_value(dht.listen(hash, vcb, f, w));
ret_token->set_value(dht.listen(hash, std::move(vcb), std::move(f), std::move(w)));
#endif
});
}
@@ -689,7 +689,7 @@ DhtRunner::listen(InfoHash hash, ValueCallback vcb, Value::Filter f, Where w)
std::future<size_t>
DhtRunner::listen(const std::string& key, GetCallback vcb, Value::Filter f, Where w)
{
return listen(InfoHash::get(key), vcb, f, w);
return listen(InfoHash::get(key), std::move(vcb), std::move(f), std::move(w));
}
void
@@ -768,7 +768,7 @@ DhtRunner::put(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, tim
void
DhtRunner::put(const std::string& key, Value&& value, DoneCallbackSimple cb, time_point created, bool permanent)
{
put(InfoHash::get(key), std::forward<Value>(value), cb, created, permanent);
put(InfoHash::get(key), std::forward<Value>(value), std::move(cb), created, permanent);
}
void
@@ -798,13 +798,13 @@ DhtRunner::putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback c
void
DhtRunner::putSigned(InfoHash hash, Value&& value, DoneCallback cb)
{
putSigned(hash, std::make_shared<Value>(std::move(value)), cb);
putSigned(hash, std::make_shared<Value>(std::move(value)), std::move(cb));
}
void
DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb)
{
putSigned(InfoHash::get(key), std::forward<Value>(value), cb);
putSigned(InfoHash::get(key), std::forward<Value>(value), std::move(cb));
}
void
@@ -822,13 +822,13 @@ DhtRunner::putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value
void
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb)
{
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), cb);
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb));
}
void
DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb)
{
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), cb);
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb));
}
void
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Nicolas Reynaud <nicolas.reynaud@savoirfairelinux.com>
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+139 -131
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -142,19 +142,27 @@ RequestAnswer::RequestAnswer(ParsedMessage&& msg)
NetworkEngine::NetworkEngine(Logger& log, Scheduler& scheduler, const int& s, const int& s6)
: myid(zeroes), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{}
NetworkEngine::NetworkEngine(InfoHash& myid, NetId net, const int& s, const int& s6, Logger& log, Scheduler& scheduler,
decltype(NetworkEngine::onError) onError,
decltype(NetworkEngine::onNewNode) onNewNode,
decltype(NetworkEngine::onReportedAddr) onReportedAddr,
decltype(NetworkEngine::onPing) onPing,
decltype(NetworkEngine::onFindNode) onFindNode,
decltype(NetworkEngine::onGetValues) onGetValues,
decltype(NetworkEngine::onListen) onListen,
decltype(NetworkEngine::onAnnounce) onAnnounce,
decltype(NetworkEngine::onRefresh) onRefresh) :
onError(onError), onNewNode(onNewNode), onReportedAddr(onReportedAddr), onPing(onPing), onFindNode(onFindNode),
onGetValues(onGetValues), onListen(onListen), onAnnounce(onAnnounce), onRefresh(onRefresh), myid(myid),
network(net), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
decltype(NetworkEngine::onError)&& onError,
decltype(NetworkEngine::onNewNode)&& onNewNode,
decltype(NetworkEngine::onReportedAddr)&& onReportedAddr,
decltype(NetworkEngine::onPing)&& onPing,
decltype(NetworkEngine::onFindNode)&& onFindNode,
decltype(NetworkEngine::onGetValues)&& onGetValues,
decltype(NetworkEngine::onListen)&& onListen,
decltype(NetworkEngine::onAnnounce)&& onAnnounce,
decltype(NetworkEngine::onRefresh)&& onRefresh) :
onError(std::move(onError)),
onNewNode(std::move(onNewNode)),
onReportedAddr(std::move(onReportedAddr)),
onPing(std::move(onPing)),
onFindNode(std::move(onFindNode)),
onGetValues(std::move(onGetValues)),
onListen(std::move(onListen)),
onAnnounce(std::move(onAnnounce)),
onRefresh(std::move(onRefresh)),
myid(myid), network(net), dht_socket(s), dht_socket6(s6), DHT_LOG(log), scheduler(scheduler)
{
if (dht_socket >= 0) {
if (!set_nonblocking(dht_socket, 1))
@@ -191,23 +199,23 @@ NetworkEngine::tellListenerRefreshed(Sp<Node> n, Tid socket_id, const InfoHash&,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("u"));
pk.pack(KEY_U);
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (not token.empty()) {
pk.pack(std::string("token")); packToken(pk, token);
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(std::string("re"));
pk.pack(KEY_REQ_REFRESHED);
pk.pack(values);
DHT_LOG.d(n->id, "[node %s] sending %zu refreshed values", n->toString().c_str(), values.size());
}
pk.pack(std::string("t")); pk.pack(socket_id);
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_TID); pk.pack(socket_id);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
// send response
@@ -221,23 +229,23 @@ NetworkEngine::tellListenerExpired(Sp<Node> n, Tid socket_id, const InfoHash&, c
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("u"));
pk.pack(KEY_U);
pk.pack_map(1 + (not values.empty()?1:0) + (not token.empty()?1:0));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_REQ_ID); pk.pack(myid);
if (not token.empty()) {
pk.pack(std::string("token")); packToken(pk, token);
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
if (not values.empty()) {
pk.pack(std::string("exp"));
pk.pack(KEY_REQ_EXPIRED);
pk.pack(values);
DHT_LOG.d(n->id, "[node %s] sending %zu expired values", n->toString().c_str(), values.size());
}
pk.pack(std::string("t")); pk.pack(socket_id);
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_TID); pk.pack(socket_id);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
// send response
@@ -687,16 +695,16 @@ NetworkEngine::sendPing(Sp<Node> node, RequestCb&& on_done, RequestExpiredCb&& o
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(1);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_A); pk.pack_map(1);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(std::string("q")); pk.pack(std::string("ping"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Q); pk.pack(QUERY_PING);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::Ping, tid.toInt(), node,
@@ -724,17 +732,17 @@ NetworkEngine::sendPong(const SockAddr& addr, Tid tid) {
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_R); pk.pack_map(2);
pk.pack(KEY_REQ_ID); pk.pack(myid);
insertAddr(pk, addr);
TransId t (tid);
pk.pack(std::string("t")); pk.pack_bin(t.size());
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, addr);
@@ -748,23 +756,23 @@ NetworkEngine::sendFindNode(Sp<Node> n, const InfoHash& target, want_t want,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(2 + (want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("target")); pk.pack(target);
pk.pack(KEY_A); pk.pack_map(2 + (want>0?1:0));
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_TARGET); pk.pack(target);
if (want > 0) {
pk.pack(std::string("w"));
pk.pack(KEY_REQ_WANT);
pk.pack_array(((want & WANT4)?1:0) + ((want & WANT6)?1:0));
if (want & WANT4) pk.pack(AF_INET);
if (want & WANT6) pk.pack(AF_INET6);
}
pk.pack(std::string("q")); pk.pack(std::string("find"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Q); pk.pack(QUERY_FIND);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::FindNode, tid.toInt(), n,
@@ -794,26 +802,26 @@ NetworkEngine::sendGetValues(Sp<Node> n, const InfoHash& info_hash, const Query&
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(2 +
pk.pack(KEY_A); pk.pack_map(2 +
(query.where.getFilter() or not query.select.getSelection().empty() ? 1:0) +
(want>0?1:0));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("h")); pk.pack(info_hash);
pk.pack(std::string("q")); pk.pack(query);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_H); pk.pack(info_hash);
pk.pack(KEY_Q); pk.pack(query);
if (want > 0) {
pk.pack(std::string("w"));
pk.pack(KEY_REQ_WANT);
pk.pack_array(((want & WANT4)?1:0) + ((want & WANT6)?1:0));
if (want & WANT4) pk.pack(AF_INET);
if (want & WANT6) pk.pack(AF_INET6);
}
pk.pack(std::string("q")); pk.pack(std::string("get"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Q); pk.pack(QUERY_GET);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::GetValues, tid.toInt(), n,
@@ -901,13 +909,13 @@ NetworkEngine::packValueHeader(msgpack::sbuffer& buffer, const std::vector<Sp<Va
total_size += v.size();
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack(std::string("values"));
pk.pack(KEY_REQ_VALUES);
pk.pack_array(svals.size());
// try to put everything in a single UDP packet
if (svals.size() < 50 && total_size < MAX_PACKET_VALUE_SIZE) {
for (const auto& b : svals)
buffer.write((const char*)b.data(), b.size());
DHT_LOG.d("sending %lu bytes of values", total_size);
// DHT_LOG.d("sending %lu bytes of values", total_size);
svals.clear();
} else {
for (const auto& b : svals)
@@ -929,12 +937,12 @@ NetworkEngine::sendValueParts(const TransId& tid, const std::vector<Blob>& svals
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(3+(network?1:0));
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
pk.pack(std::string("y")); pk.pack(std::string("v"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Y); pk.pack(KEY_V);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("p")); pk.pack_map(1);
pk.pack(KEY_V); pk.pack_map(1);
pk.pack(i); pk.pack_map(2);
pk.pack(std::string("o")); pk.pack(start);
pk.pack(std::string("d")); pk.pack_bin(end-start);
@@ -954,22 +962,22 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r"));
pk.pack(KEY_R);
pk.pack_map(2 + (not st.empty()?1:0) + (nodes.size()>0?1:0) + (nodes6.size()>0?1:0) + (not token.empty()?1:0));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_REQ_ID); pk.pack(myid);
insertAddr(pk, addr);
if (nodes.size() > 0) {
pk.pack(std::string("n4"));
pk.pack(KEY_REQ_NODES4);
pk.pack_bin(nodes.size());
pk.pack_bin_body((const char*)nodes.data(), nodes.size());
}
if (nodes6.size() > 0) {
pk.pack(std::string("n6"));
pk.pack(KEY_REQ_NODES6);
pk.pack_bin(nodes6.size());
pk.pack_bin_body((const char*)nodes6.data(), nodes6.size());
}
if (not token.empty()) {
pk.pack(std::string("token")); packToken(pk, token);
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
}
std::vector<Blob> svals {};
if (not st.empty()) { /* pack complete values */
@@ -977,7 +985,7 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
if (fields.empty()) {
svals = packValueHeader(buffer, st);
} else { /* pack fields */
pk.pack(std::string("fields"));
pk.pack(KEY_REQ_FIELDS);
pk.pack_map(2);
pk.pack(std::string("f")); pk.pack(fields);
pk.pack(std::string("v")); pk.pack_array(st.size()*fields.size());
@@ -989,12 +997,12 @@ NetworkEngine::sendNodesValues(const SockAddr& addr, Tid tid, const Blob& nodes,
}
TransId t (tid);
pk.pack(std::string("t")); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
// send response
@@ -1086,23 +1094,23 @@ NetworkEngine::sendListen(Sp<Node> n,
pk.pack_map(5+(network?1:0));
auto has_query = query.where.getFilter() or not query.select.getSelection().empty();
pk.pack(std::string("a")); pk.pack_map(4 + has_query);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("h")); pk.pack(hash);
pk.pack(std::string("token")); packToken(pk, token);
pk.pack(std::string("sid")); pk.pack_bin(sid.size());
pk.pack_bin_body((const char*)sid.data(), sid.size());
pk.pack(KEY_A); pk.pack_map(4 + has_query);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_H); pk.pack(hash);
pk.pack(KEY_REQ_TOKEN); packToken(pk, token);
pk.pack(KEY_REQ_SID); pk.pack_bin(sid.size());
pk.pack_bin_body((const char*)sid.data(), sid.size());
if (has_query) {
pk.pack(std::string("q")); pk.pack(query);
pk.pack(KEY_REQ_QUERY); pk.pack(query);
}
pk.pack(std::string("q")); pk.pack(std::string("listen"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Q); pk.pack(QUERY_LISTEN);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::Listen, tid.toInt(), n,
@@ -1128,17 +1136,17 @@ NetworkEngine::sendListenConfirmation(const SockAddr& addr, Tid tid) {
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(2);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_R); pk.pack_map(2);
pk.pack(KEY_REQ_ID); pk.pack(myid);
insertAddr(pk, addr);
TransId t (tid);
pk.pack(std::string("t")); pk.pack_bin(t.size());
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, addr);
@@ -1158,23 +1166,23 @@ NetworkEngine::sendAnnounceValue(Sp<Node> n,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map((created < scheduler.time() ? 5 : 4));
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("h")); pk.pack(infohash);
pk.pack(KEY_A); pk.pack_map((created < scheduler.time() ? 5 : 4));
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_H); pk.pack(infohash);
auto v = packValueHeader(buffer, {value});
if (created < scheduler.time()) {
pk.pack(std::string("c"));
pk.pack(KEY_REQ_CREATION);
pk.pack(to_time_t(created));
}
pk.pack(std::string("token")); pk.pack(token);
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
pk.pack(std::string("q")); pk.pack(std::string("put"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Q); pk.pack(QUERY_PUT);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::AnnounceValue, tid.toInt(), n,
@@ -1216,19 +1224,19 @@ NetworkEngine::sendRefreshValue(Sp<Node> n,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(5+(network?1:0));
pk.pack(std::string("a")); pk.pack_map(4);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("h")); pk.pack(infohash);
pk.pack(std::string("vid")); pk.pack(vid);
pk.pack(std::string("token")); pk.pack(token);
pk.pack(KEY_A); pk.pack_map(4);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_H); pk.pack(infohash);
pk.pack(KEY_REQ_VALUE_ID); pk.pack(vid);
pk.pack(KEY_REQ_TOKEN); pk.pack(token);
pk.pack(std::string("q")); pk.pack(std::string("refresh"));
pk.pack(std::string("t")); pk.pack_bin(tid.size());
pk.pack(KEY_Q); pk.pack(QUERY_REFRESH);
pk.pack(KEY_TID); pk.pack_bin(tid.size());
pk.pack_bin_body((const char*)tid.data(), tid.size());
pk.pack(std::string("y")); pk.pack(std::string("q"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_Q);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
auto req = std::make_shared<Request>(MessageType::Refresh, tid.toInt(), n,
@@ -1261,18 +1269,18 @@ NetworkEngine::sendValueAnnounced(const SockAddr& addr, Tid tid, Value::Id vid)
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4+(network?1:0));
pk.pack(std::string("r")); pk.pack_map(3);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(std::string("vid")); pk.pack(vid);
pk.pack(KEY_R); pk.pack_map(3);
pk.pack(KEY_REQ_ID); pk.pack(myid);
pk.pack(KEY_REQ_VALUE_ID); pk.pack(vid);
insertAddr(pk, addr);
TransId t(tid);
pk.pack(std::string("t")); pk.pack_bin(t.size());
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(std::string("y")); pk.pack(std::string("r"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_R);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, addr);
@@ -1289,22 +1297,22 @@ NetworkEngine::sendError(const SockAddr& addr,
msgpack::packer<msgpack::sbuffer> pk(&buffer);
pk.pack_map(4 + (include_id?1:0));
pk.pack(std::string("e")); pk.pack_array(2);
pk.pack(KEY_E); pk.pack_array(2);
pk.pack(code);
pk.pack(message);
if (include_id) {
pk.pack(std::string("r")); pk.pack_map(1);
pk.pack(std::string("id")); pk.pack(myid);
pk.pack(KEY_R); pk.pack_map(1);
pk.pack(KEY_REQ_ID); pk.pack(myid);
}
TransId t(tid);
pk.pack(std::string("t")); pk.pack_bin(t.size());
pk.pack(KEY_TID); pk.pack_bin(t.size());
pk.pack_bin_body((const char*)t.data(), t.size());
pk.pack(std::string("y")); pk.pack(std::string("e"));
pk.pack(std::string("v")); pk.pack(my_v);
pk.pack(KEY_Y); pk.pack(KEY_E);
pk.pack(KEY_UA); pk.pack(my_v);
if (network) {
pk.pack(std::string("n")); pk.pack(network);
pk.pack(KEY_NETID); pk.pack(network);
}
send(buffer.data(), buffer.size(), 0, addr);
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -49,7 +49,7 @@ Node::isGood(time_point now) const
bool
Node::isPendingMessage() const
{
for (auto r : requests_) {
for (const auto& r : requests_) {
if (r.second->pending())
return true;
}
@@ -60,7 +60,7 @@ size_t
Node::getPendingMessageCount() const
{
size_t count {0};
for (auto r : requests_) {
for (const auto& r : requests_) {
if (r.second->pending())
count++;
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+4 -4
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -160,7 +160,7 @@ SearchCache::getOp(const Sp<Query>& q) const
}
size_t
SearchCache::listen(ValueCallback get_cb, Sp<Query> q, Value::Filter filter, OnListen onListen)
SearchCache::listen(const ValueCallback& get_cb, const Sp<Query>& q, const Value::Filter& filter, const OnListen& onListen)
{
// find exact match
auto op = getOp(q);
@@ -192,7 +192,7 @@ SearchCache::cancelListen(size_t gtoken, const time_point& now) {
}
void
SearchCache::cancelAll(std::function<void(size_t)> onCancel) {
SearchCache::cancelAll(const std::function<void(size_t)>& onCancel) {
for (auto& op : ops) {
auto cache = std::move(op.second);
cache->removeAll();
@@ -202,7 +202,7 @@ SearchCache::cancelAll(std::function<void(size_t)> onCancel) {
}
time_point
SearchCache::expire(const time_point& now, std::function<void(size_t)> onCancel) {
SearchCache::expire(const time_point& now, const std::function<void(size_t)>& onCancel) {
nextExpiration_ = time_point::max();
auto ret = nextExpiration_;
for (auto it = ops.begin(); it != ops.end();) {
+7 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -32,8 +32,8 @@ struct OpCacheValueStorage
class OpValueCache {
public:
OpValueCache(ValueCallback&& cb) : callback(std::forward<ValueCallback>(cb)) {}
OpValueCache(OpValueCache&& o) : values(std::move(o.values)), callback(std::move(o.callback)) {
OpValueCache(ValueCallback&& cb) noexcept : callback(std::forward<ValueCallback>(cb)) {}
OpValueCache(OpValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)) {
o.callback = {};
}
@@ -104,7 +104,7 @@ public:
void onValuesAdded(const std::vector<Sp<Value>>& vals);
void onValuesExpired(const std::vector<Sp<Value>>& vals);
bool addListener(size_t token, ValueCallback cb, Sp<Query> q, Value::Filter filter) {
bool addListener(size_t token, const ValueCallback& cb, const Sp<Query>& q, const Value::Filter& filter) {
listeners.emplace(token, LocalListener{q, filter, cb});
auto cached = cache.get(filter);
if (not cached.empty()) {
@@ -163,12 +163,12 @@ public:
SearchCache(SearchCache&&) = default;
using OnListen = std::function<size_t(Sp<Query>, ValueCallback, SyncCallback)>;
size_t listen(ValueCallback get_cb, Sp<Query> q, Value::Filter filter, OnListen onListen);
size_t listen(const ValueCallback& get_cb, const Sp<Query>& q, const Value::Filter& filter, const OnListen& onListen);
bool cancelListen(size_t gtoken, const time_point& now);
void cancelAll(std::function<void(size_t)> onCancel);
void cancelAll(const std::function<void(size_t)>& onCancel);
time_point expire(const time_point& now, std::function<void(size_t)> onCancel);
time_point expire(const time_point& now, const std::function<void(size_t)>& onCancel);
time_point getExpiration() const {
return nextExpiration_;
}
+156 -93
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,42 @@
namespace dht {
namespace net {
static const std::string KEY_Y {"y"};
static const std::string KEY_R {"r"};
static const std::string KEY_U {"u"};
static const std::string KEY_E {"e"};
static const std::string KEY_V {"p"};
static const std::string KEY_TID {"t"};
static const std::string KEY_UA {"v"};
static const std::string KEY_NETID {"n"};
static const std::string KEY_ISCLIENT {"s"};
static const std::string KEY_Q {"q"};
static const std::string KEY_A {"a"};
static const std::string KEY_REQ_SID {"sid"};
static const std::string KEY_REQ_ID {"id"};
static const std::string KEY_REQ_H {"h"};
static const std::string KEY_REQ_TARGET {"target"};
static const std::string KEY_REQ_QUERY {"q"};
static const std::string KEY_REQ_TOKEN {"token"};
static const std::string KEY_REQ_VALUE_ID {"vid"};
static const std::string KEY_REQ_NODES4 {"n4"};
static const std::string KEY_REQ_NODES6 {"n6"};
static const std::string KEY_REQ_CREATION {"c"};
static const std::string KEY_REQ_ADDRESS {"sa"};
static const std::string KEY_REQ_VALUES {"values"};
static const std::string KEY_REQ_EXPIRED {"exp"};
static const std::string KEY_REQ_REFRESHED {"re"};
static const std::string KEY_REQ_FIELDS {"fileds"};
static const std::string KEY_REQ_WANT {"w"};
static const std::string QUERY_PING {"ping"};
static const std::string QUERY_FIND {"find"};
static const std::string QUERY_GET {"get"};
static const std::string QUERY_PUT {"put"};
static const std::string QUERY_LISTEN {"listen"};
static const std::string QUERY_REFRESH {"refresh"};
Tid unpackTid(const msgpack::object& o) {
switch (o.type) {
case msgpack::type::POSITIVE_INTEGER:
@@ -78,7 +114,7 @@ struct ParsedMessage {
/* reported address by the distant node */
std::string ua;
SockAddr addr;
void msgpack_unpack(msgpack::object o);
void msgpack_unpack(const msgpack::object& o);
bool append(const ParsedMessage& block);
bool complete();
@@ -123,63 +159,79 @@ ParsedMessage::complete()
}
void
ParsedMessage::msgpack_unpack(msgpack::object msg)
ParsedMessage::msgpack_unpack(const msgpack::object& msg)
{
auto y = findMapValue(msg, "y");
auto r = findMapValue(msg, "r");
auto u = findMapValue(msg, "u");
auto e = findMapValue(msg, "e");
auto v = findMapValue(msg, "p");
if (msg.type != msgpack::type::MAP) throw msgpack::type_error();
if (auto t = findMapValue(msg, "t"))
tid = unpackTid(*t);
struct ParsedMsg {
msgpack::object* y;
msgpack::object* r;
msgpack::object* u;
msgpack::object* e;
msgpack::object* v;
msgpack::object* a;
std::string q;
} parsed {};
if (auto rv = findMapValue(msg, "v"))
ua = rv->as<std::string>();
if (auto netid = findMapValue(msg, "n"))
network = netid->as<NetId>();
if (auto is_client_v = findMapValue(msg, "s"))
is_client = is_client_v->as<bool>();
std::string q;
if (auto rq = findMapValue(msg, "q")) {
if (rq->type != msgpack::type::STR)
throw msgpack::type_error();
q = rq->as<std::string>();
for (unsigned i = 0; i < msg.via.map.size; i++) {
auto& o = msg.via.map.ptr[i];
if (o.key.type != msgpack::type::STR)
continue;
auto key = o.key.as<std::string>();
if (key == KEY_Y)
parsed.y = &o.val;
else if (key == KEY_R)
parsed.r = &o.val;
else if (key == KEY_U)
parsed.u = &o.val;
else if (key == KEY_E)
parsed.e = &o.val;
else if (key == KEY_V)
parsed.v = &o.val;
else if (key == KEY_TID)
tid = unpackTid(o.val);
else if (key == KEY_UA)
ua = o.val.as<std::string>();
else if (key == KEY_NETID)
network = o.val.as<NetId>();
else if (key == KEY_ISCLIENT)
is_client = o.val.as<bool>();
else if (key == KEY_Q)
parsed.q = o.val.as<std::string>();
else if (key == KEY_A)
parsed.a = &o.val;
}
if (e)
if (parsed.e)
type = MessageType::Error;
else if (r)
else if (parsed.r)
type = MessageType::Reply;
else if (v)
else if (parsed.v)
type = MessageType::ValueData;
else if (u)
else if (parsed.u)
type = MessageType::ValueUpdate;
else if (y and y->as<std::string>() != "q")
else if (parsed.y and parsed.y->as<std::string>() != "q")
throw msgpack::type_error();
else if (q == "ping")
else if (parsed.q == QUERY_PING)
type = MessageType::Ping;
else if (q == "find")
else if (parsed.q == QUERY_FIND)
type = MessageType::FindNode;
else if (q == "get")
else if (parsed.q == QUERY_GET)
type = MessageType::GetValues;
else if (q == "listen")
else if (parsed.q == QUERY_LISTEN)
type = MessageType::Listen;
else if (q == "put")
else if (parsed.q == QUERY_PUT)
type = MessageType::AnnounceValue;
else if (q == "refresh")
else if (parsed.q == QUERY_REFRESH)
type = MessageType::Refresh;
else
throw msgpack::type_error();
if (type == MessageType::ValueData) {
if (v->type != msgpack::type::MAP)
if (parsed.v->type != msgpack::type::MAP)
throw msgpack::type_error();
for (size_t i = 0; i < v->via.map.size; ++i) {
auto& vdat = v->via.map.ptr[i];
for (size_t i = 0; i < parsed.v->via.map.size; ++i) {
auto& vdat = parsed.v->via.map.ptr[i];
auto o = findMapValue(vdat.val, "o");
auto d = findMapValue(vdat.val, "d");
if (not o or not d)
@@ -189,70 +241,85 @@ ParsedMessage::msgpack_unpack(msgpack::object msg)
return;
}
auto a = findMapValue(msg, "a");
if (!a && !r && !e && !u)
if (!parsed.a && !parsed.r && !parsed.e && !parsed.u)
throw msgpack::type_error();
auto& req = a ? *a : (r ? *r : (u ? *u : *e));
auto& req = parsed.a ? *parsed.a : (parsed.r ? *parsed.r : (parsed.u ? *parsed.u : *parsed.e));
if (e) {
if (e->type != msgpack::type::ARRAY)
if (parsed.e) {
if (parsed.e->type != msgpack::type::ARRAY)
throw msgpack::type_error();
error_code = e->via.array.ptr[0].as<uint16_t>();
error_code = parsed.e->via.array.ptr[0].as<uint16_t>();
}
if (auto t = findMapValue(req, "sid"))
socket_id = unpackTid(*t);
struct ParsedReq {
msgpack::object* values;
msgpack::object* fields;
msgpack::object* sa;
msgpack::object* want;
} parsedReq {};
if (auto rid = findMapValue(req, "id"))
id = {*rid};
for (unsigned i = 0; i < req.via.map.size; i++) {
auto& o = req.via.map.ptr[i];
if (o.key.type != msgpack::type::STR)
continue;
auto key = o.key.as<std::string>();
if (key == KEY_REQ_SID)
socket_id = unpackTid(o.val);
else if (key == KEY_REQ_ID)
id = {o.val};
else if (key == KEY_REQ_H)
info_hash = {o.val};
else if (key == KEY_REQ_TARGET)
target = {o.val};
else if (key == KEY_REQ_QUERY)
query.msgpack_unpack(o.val);
else if (key == KEY_REQ_TOKEN)
token = unpackBlob(o.val);
else if (key == KEY_REQ_VALUE_ID)
value_id = o.val.as<Value::Id>();
else if (key == KEY_REQ_NODES4)
nodes4_raw = unpackBlob(o.val);
else if (key == KEY_REQ_NODES6)
nodes6_raw = unpackBlob(o.val);
else if (key == KEY_REQ_ADDRESS)
parsedReq.sa = &o.val;
else if (key == KEY_REQ_CREATION)
created = from_time_t(o.val.as<std::time_t>());
else if (key == KEY_REQ_VALUES)
parsedReq.values = &o.val;
else if (key == KEY_REQ_EXPIRED)
expired_values = o.val.as<decltype(expired_values)>();
else if (key == KEY_REQ_REFRESHED)
refreshed_values = o.val.as<decltype(refreshed_values)>();
else if (key == KEY_REQ_FIELDS)
parsedReq.fields = &o.val;
else if (key == KEY_REQ_WANT)
parsedReq.want = &o.val;
}
if (auto rh = findMapValue(req, "h"))
info_hash = {*rh};
if (auto rtarget = findMapValue(req, "target"))
target = {*rtarget};
if (auto rquery = findMapValue(req, "q"))
query.msgpack_unpack(*rquery);
if (auto otoken = findMapValue(req, "token"))
token = unpackBlob(*otoken);
if (auto vid = findMapValue(req, "vid"))
value_id = vid->as<Value::Id>();
if (auto rnodes4 = findMapValue(req, "n4"))
nodes4_raw = unpackBlob(*rnodes4);
if (auto rnodes6 = findMapValue(req, "n6"))
nodes6_raw = unpackBlob(*rnodes6);
if (auto sa = findMapValue(req, "sa")) {
if (sa->type != msgpack::type::BIN)
if (parsedReq.sa) {
if (parsedReq.sa->type != msgpack::type::BIN)
throw msgpack::type_error();
auto l = sa->via.bin.size;
auto l = parsedReq.sa->via.bin.size;
if (l == sizeof(in_addr)) {
addr.setFamily(AF_INET);
auto& a = addr.getIPv4();
a.sin_port = 0;
std::copy_n(sa->via.bin.ptr, l, (char*)&a.sin_addr);
std::copy_n(parsedReq.sa->via.bin.ptr, l, (char*)&a.sin_addr);
} else if (l == sizeof(in6_addr)) {
addr.setFamily(AF_INET6);
auto& a = addr.getIPv6();
a.sin6_port = 0;
std::copy_n(sa->via.bin.ptr, l, (char*)&a.sin6_addr);
std::copy_n(parsedReq.sa->via.bin.ptr, l, (char*)&a.sin6_addr);
}
} else
addr = {};
if (auto rcreated = findMapValue(req, "c"))
created = from_time_t(rcreated->as<std::time_t>());
if (auto rvalues = findMapValue(req, "values")) {
if (rvalues->type != msgpack::type::ARRAY)
if (parsedReq.values) {
if (parsedReq.values->type != msgpack::type::ARRAY)
throw msgpack::type_error();
for (size_t i = 0; i < rvalues->via.array.size; i++) {
auto& packed_v = rvalues->via.array.ptr[i];
for (size_t i = 0; i < parsedReq.values->via.array.size; i++) {
auto& packed_v = parsedReq.values->via.array.ptr[i];
if (packed_v.type == msgpack::type::POSITIVE_INTEGER) {
// Skip oversize values with a small margin for header overhead
if (packed_v.via.u64 > MAX_VALUE_SIZE + 32)
@@ -260,16 +327,16 @@ ParsedMessage::msgpack_unpack(msgpack::object msg)
value_parts.emplace(i, std::make_pair(packed_v.via.u64, Blob{}));
} else {
try {
values.emplace_back(std::make_shared<Value>(rvalues->via.array.ptr[i]));
values.emplace_back(std::make_shared<Value>(parsedReq.values->via.array.ptr[i]));
} catch (const std::exception& e) {
//DHT_LOG_WARN("Error reading value: %s", e.what());
}
}
}
} else if (auto raw_fields = findMapValue(req, "fields")) {
if (auto rfields = findMapValue(*raw_fields, "f")) {
} else if (parsedReq.fields) {
if (auto rfields = findMapValue(*parsedReq.fields, "f")) {
auto vfields = rfields->as<std::set<Value::Field>>();
if (auto rvalues = findMapValue(*raw_fields, "v")) {
if (auto rvalues = findMapValue(*parsedReq.fields, "v")) {
if (rvalues->type != msgpack::type::ARRAY)
throw msgpack::type_error();
size_t val_num = rvalues->via.array.size / vfields.size();
@@ -284,18 +351,14 @@ ParsedMessage::msgpack_unpack(msgpack::object msg)
} else {
throw msgpack::type_error();
}
} else if (auto raw_fields = findMapValue(req, "exp")) {
expired_values = raw_fields->as<decltype(expired_values)>();
} else if (auto raw_fields = findMapValue(req, "re")) {
refreshed_values = raw_fields->as<decltype(refreshed_values)>();
}
if (auto w = findMapValue(req, "w")) {
if (w->type != msgpack::type::ARRAY)
if (parsedReq.want) {
if (parsedReq.want->type != msgpack::type::ARRAY)
throw msgpack::type_error();
want = 0;
for (unsigned i=0; i<w->via.array.size; i++) {
auto& val = w->via.array.ptr[i];
for (unsigned i=0; i<parsedReq.want->via.array.size; i++) {
auto& val = parsedReq.want->via.array.ptr[i];
try {
auto w = val.as<sa_family_t>();
if (w == AF_INET)
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Copyright (C) 2016-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -92,7 +92,7 @@ RoutingTable::middle(const RoutingTable::const_iterator& it) const
throw std::out_of_range("End of table");
InfoHash id = it->first;
id.setBit(bit, 1);
id.setBit(bit, true);
return id;
}
+4 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2018 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -387,7 +387,6 @@ struct Dht::Search {
/* listeners */
struct SearchListener {
Sp<Query> query;
Value::Filter filter;
ValueCallback get_cb;
SyncCallback sync_cb;
};
@@ -489,7 +488,7 @@ struct Dht::Search {
bool isAnnounced(Value::Id id) const;
bool isListening(time_point now) const;
void get(Value::Filter f, const Sp<Query>& q, const QueryCallback& qcb, const GetCallback& gcb, const DoneCallback& dcb, Scheduler& scheduler) {
void get(const Value::Filter& f, const Sp<Query>& q, const QueryCallback& qcb, const GetCallback& gcb, const DoneCallback& dcb, Scheduler& scheduler) {
if (gcb or qcb) {
if (not cache.get(f, q, gcb, dcb)) {
const auto& now = scheduler.time();
@@ -499,12 +498,12 @@ struct Dht::Search {
}
}
size_t listen(ValueCallback cb, Value::Filter f, const Sp<Query>& q, Scheduler& scheduler) {
size_t listen(const ValueCallback& cb, const Value::Filter& f, const Sp<Query>& q, Scheduler& scheduler) {
//DHT_LOG.e(id, "[search %s IPv%c] listen", id.toString().c_str(), (af == AF_INET) ? '4' : '6');
return cache.listen(cb, q, f, [&](const Sp<Query>& q, ValueCallback vcb, SyncCallback scb){
done = false;
auto token = ++listener_token;
listeners.emplace(token, SearchListener{q, f, vcb, scb});
listeners.emplace(token, SearchListener{q, vcb, scb});
scheduler.edit(nextSearchStep, scheduler.time());
return token;
});
+6 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
* Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -61,8 +61,7 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf)
}
}
SecureDht::~SecureDht()
{}
SecureDht::~SecureDht() = default;
ValueType
SecureDht::secureType(ValueType&& type)
@@ -166,7 +165,7 @@ SecureDht::registerCertificate(Sp<crypto::Certificate>& cert)
}
void
SecureDht::findCertificate(const InfoHash& node, std::function<void(const Sp<crypto::Certificate>)> cb)
SecureDht::findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb)
{
Sp<crypto::Certificate> b = getCertificate(node);
if (b && *b) {
@@ -207,7 +206,7 @@ SecureDht::findCertificate(const InfoHash& node, std::function<void(const Sp<cry
}
void
SecureDht::findPublicKey(const InfoHash& node, std::function<void(const Sp<const crypto::PublicKey>)> cb)
SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp<const crypto::PublicKey>)>& cb)
{
auto pk = getPublicKey(node);
if (pk && *pk) {
@@ -280,7 +279,7 @@ SecureDht::checkValue(const Sp<Value>& v)
}
ValueCallback
SecureDht::getCallbackFilter(ValueCallback cb, Value::Filter&& filter)
SecureDht::getCallbackFilter(const ValueCallback& cb, Value::Filter&& filter)
{
return [=](const std::vector<Sp<Value>>& values, bool expired) {
std::vector<Sp<Value>> tmpvals {};
@@ -299,7 +298,7 @@ SecureDht::getCallbackFilter(ValueCallback cb, Value::Filter&& filter)
GetCallback
SecureDht::getCallbackFilter(GetCallback cb, Value::Filter&& filter)
SecureDht::getCallbackFilter(const GetCallback& cb, Value::Filter&& filter)
{
return [=](const std::vector<Sp<Value>>& values) {
std::vector<Sp<Value>> tmpvals {};
+23 -14
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -90,20 +90,7 @@ struct Storage {
Storage() {}
Storage(time_point t) : maintenance_time(t) {}
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 || defined(_WIN32)
// GCC-bug: remove me when support of GCC < 4.9.2 is abandoned
Storage(Storage&& o) noexcept
: maintenance_time(std::move(o.maintenance_time))
, listeners(std::move(o.listeners))
, local_listeners(std::move(o.local_listeners))
, listener_token(std::move(o.listener_token))
, values(std::move(o.values))
, total_size(std::move(o.total_size)) {}
#else
Storage(Storage&& o) noexcept = default;
#endif
Storage& operator=(Storage&& o) = default;
bool empty() const {
@@ -166,6 +153,12 @@ struct Storage {
return time_point::max();
}
size_t listen(ValueCallback& cb, Value::Filter& f, const Sp<Query>& q);
void cancelListen(size_t token) {
local_listeners.erase(token);
}
StoreDiff remove(const InfoHash& id, Value::Id);
std::pair<ssize_t, std::vector<Sp<Value>>> expire(const InfoHash& id, time_point now);
@@ -179,6 +172,22 @@ private:
};
size_t
Storage::listen(ValueCallback& gcb, Value::Filter& filter, const Sp<Query>& query)
{
if (not empty()) {
std::vector<Sp<Value>> newvals = get(filter);
if (not newvals.empty()) {
if (!gcb(newvals, false))
return 0;
}
}
auto tokenlocal = ++listener_token;
local_listeners.emplace(tokenlocal, LocalListener{query, filter, gcb});
return tokenlocal;
}
std::pair<ValueStorage*, Storage::StoreDiff>
Storage::store(const InfoHash& id, const Sp<Value>& value, time_point created, time_point expiration, StorageBucket* sb)
{
+17
View File
@@ -26,12 +26,29 @@
namespace dht {
constexpr const size_t IO_THREADS_MAX {64};
struct ThreadPool::ThreadState
{
std::thread thread {};
std::atomic_bool run {true};
};
ThreadPool&
ThreadPool::computation()
{
static ThreadPool pool;
return pool;
}
ThreadPool&
ThreadPool::io()
{
static ThreadPool pool(IO_THREADS_MAX);
return pool;
}
ThreadPool::ThreadPool(size_t maxThreads) : maxThreads_(maxThreads)
{
threads_.reserve(maxThreads_);
+2 -4
View File
@@ -29,10 +29,8 @@ namespace dht {
class ThreadPool {
public:
static ThreadPool& instance() {
static ThreadPool pool;
return pool;
}
static ThreadPool& computation();
static ThreadPool& io();
ThreadPool();
ThreadPool(size_t maxThreads);
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
+7 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
*
@@ -65,8 +65,8 @@ std::ostream& operator<< (std::ostream& s, const Value& v)
} else {
s << "Data (type: " << v.type << " ): ";
s << std::hex;
for (size_t i=0; i<v.data.size(); i++)
s << std::setfill('0') << std::setw(2) << (unsigned)v.data[i];
for (auto i : v.data)
s << std::setfill('0') << std::setw(2) << (unsigned)i;
s << std::dec;
}
}
@@ -78,7 +78,7 @@ std::ostream& operator<< (std::ostream& s, const Value& v)
const ValueType ValueType::USER_DATA = {0, "User Data"};
bool
ValueType::DEFAULT_STORE_POLICY(InfoHash, std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&)
ValueType::DEFAULT_STORE_POLICY(InfoHash, const std::shared_ptr<Value>& v, const InfoHash&, const SockAddr&)
{
return v->size() <= MAX_VALUE_SIZE;
}
@@ -292,7 +292,7 @@ FieldValue::getLocalFilter() const
}
}
FieldValueIndex::FieldValueIndex(const Value& v, Select s)
FieldValueIndex::FieldValueIndex(const Value& v, const Select& s)
{
auto selection = s.getSelection();
if (not selection.empty()) {
@@ -399,8 +399,8 @@ FieldValueIndex::msgpack_unpack_fields(const std::set<Value::Field>& fields, con
}
void trim_str(std::string& str) {
auto first = std::min(str.size(), str.find_first_not_of(" "));
auto last = std::min(str.size(), str.find_last_not_of(" "));
auto first = std::min(str.size(), str.find_first_not_of(' '));
auto last = std::min(str.size(), str.find_last_not_of(' '));
str = str.substr(first, last - first + 1);
}
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author(s) : Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@ public:
if (syncCallback)
syncCallback(ListenSyncStatus::ADDED);
}
ValueCache(ValueCache&& o) : values(std::move(o.values)), callback(std::move(o.callback)), syncCallback(std::move(o.syncCallback)) {
ValueCache(ValueCache&& o) noexcept : values(std::move(o.values)), callback(std::move(o.callback)), syncCallback(std::move(o.syncCallback)) {
o.callback = {};
o.syncCallback = {};
}
+2 -2
View File
@@ -3,7 +3,7 @@ bin_PROGRAMS = opendht_unit_tests
AM_CPPFLAGS = -I../include
nobase_include_HEADERS = infohashtester.h cryptotester.h dhtrunnertester.h dhtproxytester.h
opendht_unit_tests_SOURCES = tests_runner.cpp cryptotester.cpp infohashtester.cpp dhtrunnertester.cpp dhtproxytester.cpp
nobase_include_HEADERS = infohashtester.h valuetester.h cryptotester.h dhtrunnertester.h dhtproxytester.h
opendht_unit_tests_SOURCES = tests_runner.cpp cryptotester.cpp infohashtester.cpp valuetester.cpp dhtrunnertester.cpp dhtproxytester.cpp
opendht_unit_tests_LDFLAGS = -lopendht -lcppunit -L@top_builddir@/src/.libs @GnuTLS_LIBS@
endif
+30 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
@@ -54,7 +54,6 @@ CryptoTester::testCertificateRevocation()
auto device11 = dht::crypto::generateIdentity("dev11", account1);
auto device12 = dht::crypto::generateIdentity("dev12", account1);
dht::crypto::TrustList list;
list.add(*ca1.second);
auto v = list.verify(*account1.second);
@@ -72,7 +71,7 @@ CryptoTester::testCertificateRevocation()
v = list.verify(*device2.second);
CPPUNIT_ASSERT_MESSAGE(v.toString(), !v);
account1.second->revoke(*account1.first, *device11.second);
dht::crypto::TrustList list2;
list2.add(*account1.second);
@@ -83,6 +82,34 @@ CryptoTester::testCertificateRevocation()
CPPUNIT_ASSERT_MESSAGE(v.toString(), v);
}
void
CryptoTester::testCertificateRequest()
{
// Generate CA
auto ca = dht::crypto::generateIdentity("Test CA");
// Generate signed request
auto deviceKey = dht::crypto::PrivateKey::generate();
auto request = dht::crypto::CertificateRequest();
request.setName("Test Device");
request.sign(deviceKey);
// Export/import request
auto importedRequest = dht::crypto::CertificateRequest(request.pack());
CPPUNIT_ASSERT(importedRequest.verify());
// Generate/sign certificate from request
auto signedCert = dht::crypto::Certificate::generate(request, ca);
CPPUNIT_ASSERT_EQUAL(ca.second->getName(), signedCert.getIssuerName());
CPPUNIT_ASSERT_EQUAL(request.getName(), signedCert.getName());
// Check generated certificate
dht::crypto::TrustList list;
list.add(*ca.second);
auto v = list.verify(signedCert);
CPPUNIT_ASSERT_MESSAGE(v.toString(), v);
}
void
CryptoTester::tearDown() {
+6 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
@@ -29,6 +29,7 @@ class CryptoTester : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(CryptoTester);
CPPUNIT_TEST(testSignatureEncryption);
CPPUNIT_TEST(testCertificateRevocation);
CPPUNIT_TEST(testCertificateRequest);
CPPUNIT_TEST_SUITE_END();
public:
@@ -48,6 +49,10 @@ class CryptoTester : public CppUnit::TestFixture {
* Test certificate generation, validation and revocation
*/
void testCertificateRevocation();
/**
* Test certificate requests
*/
void testCertificateRequest();
};
} // namespace test
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+5 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
@@ -38,14 +38,13 @@ void
InfoHashTester::testConstructors() {
// Default constructor creates a null infohash
auto nullHash = dht::InfoHash();
CPPUNIT_ASSERT(nullHash.size() == 20);
CPPUNIT_ASSERT_EQUAL((size_t)20u, nullHash.size());
CPPUNIT_ASSERT(!nullHash);
// Build from a uint8_t. if length to short, should get a null infohash
uint8_t to_short[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
auto infohash = dht::InfoHash(to_short, 8);
CPPUNIT_ASSERT(infohash.size() == 20);
CPPUNIT_ASSERT_EQUAL(infohash.toString(),
std::string("0000000000000000000000000000000000000000"));
CPPUNIT_ASSERT_EQUAL((size_t)20u, infohash.size());
CPPUNIT_ASSERT_EQUAL(std::string("0000000000000000000000000000000000000000"), infohash.toString());
// Build from a uint8_t. if length is enough, data should contains the uint8_t
uint8_t enough[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa};
@@ -66,7 +65,7 @@ InfoHashTester::testConstructors() {
}
// Build from string
auto infohashFromStr = dht::InfoHash("0102030405060708090A0102030405060708090A");
CPPUNIT_ASSERT(infohashFromStr.size() == 20);
CPPUNIT_ASSERT_EQUAL((size_t)20u, infohashFromStr.size());
const auto* dataStr = infohashFromStr.data();
for (auto i = 0; i < 20; ++i) {
CPPUNIT_ASSERT_EQUAL((int)dataStr[i], (int)data[i]);
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Savoir-faire Linux Inc.
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
+2 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Savoir-faire Linux Inc.
* Copyright (C) 2017-2019 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -21,7 +21,7 @@
#include <cppunit/CompilerOutputter.h>
#include <iostream>
int main(int argc, char** argv) {
int main(int /*argc*/, char** /*argv*/) {
CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
CppUnit::Test *suite = registry.makeTest();
if (suite->countTestCases() == 0) {
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "valuetester.h"
#include <iostream>
#include <string>
// opendht
#include "opendht/value.h"
namespace test {
CPPUNIT_TEST_SUITE_REGISTRATION(ValueTester);
void
ValueTester::setUp() {
}
void
ValueTester::testConstructors() {
std::string the_data {"42 cats"};
dht::Value the_dht_value {(const uint8_t*)the_data.data(), the_data.size()};
std::string from_value {the_dht_value.data.begin(), the_dht_value.data.end()};
CPPUNIT_ASSERT_EQUAL(the_data, from_value);
}
void
ValueTester::testFilter()
{
dht::Value::Filter defaultFiler {};
auto isPairSize = dht::Value::Filter([](const dht::Value& v) {
return v.data.size() % 2 == 0;
});
auto isUserTypeTest = dht::Value::Filter([](const dht::Value& v) {
return v.user_type == "test";
});
std::string data1 {"42 cats"};
dht::Value value1 {(const uint8_t*)data1.data(), data1.size()};
value1.user_type = "test";
std::string data2 {"420 cats"};
dht::Value value2 {(const uint8_t*)data2.data(), data2.size()};
dht::Value value3 {(const uint8_t*)data2.data(), data2.size()};
value3.user_type = "test";
CPPUNIT_ASSERT(!isPairSize(value1));
CPPUNIT_ASSERT(isUserTypeTest(value1));
auto isBoth = dht::Value::Filter::chain(isPairSize, isUserTypeTest);
auto isUserTypeTest2 = dht::Value::Filter::chain(defaultFiler, isUserTypeTest);
CPPUNIT_ASSERT(isUserTypeTest2(value1));
CPPUNIT_ASSERT(!isUserTypeTest2(value2));
CPPUNIT_ASSERT(!isBoth(value1));
CPPUNIT_ASSERT(!isBoth(value2));
CPPUNIT_ASSERT(isBoth(value3));
}
void
ValueTester::tearDown() {
}
} // namespace test
+53
View File
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
// cppunit
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
namespace test {
class ValueTester : public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(ValueTester);
CPPUNIT_TEST(testConstructors);
CPPUNIT_TEST(testFilter);
CPPUNIT_TEST_SUITE_END();
public:
/**
* Method automatically called before each test by CppUnit
*/
void setUp();
/**
* Method automatically called after each test CppUnit
*/
void tearDown();
/**
* Test the differents behaviors of constructors
*/
void testConstructors();
/**
* Test compare operators
*/
void testFilter();
};
} // namespace test
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+6 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Authors: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Simon Désaulniers <simon.desaulniers@savoirfairelinux.com>
@@ -307,7 +307,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
}, [start](bool ok) {
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Get: " << (ok ? "completed" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
}, {}, dht::Where {std::move(rem)});
}, {}, dht::Where {rem});
}
else if (op == "q") {
std::string rem;
@@ -322,7 +322,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
}, [start](bool ok) {
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Query: " << (ok ? "completed" : "failure") << " (took " << print_dt(end-start) << "s)" << std::endl;
}, dht::Query {std::move(rem)});
}, dht::Query {rem});
}
else if (op == "l") {
std::string rem;
@@ -332,7 +332,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
for (const auto& value : values)
std::cout << "\t" << *value << std::endl;
return true;
}, {}, dht::Where {std::move(rem)});
}, {}, dht::Where {rem});
auto t = token.get();
std::cout << "Listening, token: " << t << std::endl;
}
@@ -431,7 +431,7 @@ void cmd_loop(std::shared_ptr<DhtRunner>& dht, dht_params& params
<< p.toString() << std::endl
<< " hash: " << p.hash() << std::endl;
std::cout << " entries:" << std::endl;
for (auto v : vals)
for (const auto& v : vals)
std::cout << " " << v->first.toString() << "[vid: " << v->second << "]" << std::endl;
},
[start](bool ok) {
@@ -500,6 +500,7 @@ main(int argc, char **argv)
dht::DhtRunner::Config config {};
config.dht_config.node_config.network = params.network;
config.dht_config.node_config.maintain_storage = false;
config.dht_config.node_config.persist_path = params.persist_path;
config.dht_config.id = crt;
config.threaded = true;
config.proxy_server = params.proxyclient;
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
*
+7 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2017 Savoir-faire Linux Inc.
* Copyright (C) 2014-2019 Savoir-faire Linux Inc.
*
* Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
@@ -103,6 +103,7 @@ struct dht_params {
std::string proxyclient {};
std::string pushserver {};
std::string devicekey {};
std::string persist_path {};
};
static const constexpr struct option long_options[] = {
@@ -114,6 +115,7 @@ static const constexpr struct option long_options[] = {
{"verbose", no_argument , nullptr, 'v'},
{"daemonize", no_argument , nullptr, 'd'},
{"service", no_argument , nullptr, 's'},
{"persist", required_argument, nullptr, 'f'},
{"logfile", required_argument, nullptr, 'l'},
{"syslog", no_argument , nullptr, 'L'},
{"proxyserver",required_argument, nullptr, 'S'},
@@ -127,7 +129,7 @@ dht_params
parseArgs(int argc, char **argv) {
dht_params params;
int opt;
while ((opt = getopt_long(argc, argv, "hidsvp:n:b:l:", long_options, nullptr)) != -1) {
while ((opt = getopt_long(argc, argv, "hidsvp:n:b:f:l:", long_options, nullptr)) != -1) {
switch (opt) {
case 'p': {
int port_arg = atoi(optarg);
@@ -154,6 +156,9 @@ parseArgs(int argc, char **argv) {
case 'D':
params.devicekey = optarg;
break;
case 'f':
params.persist_path = optarg;
break;
case 'n':
params.network = strtoul(optarg, nullptr, 0);
break;