Compare commits

..
Author SHA1 Message Date
Adrien Béraud 68485faf58 crypto: improve authenticated encryption performance 2019-10-22 13:04:30 -04:00
26 changed files with 562 additions and 792 deletions

No files matched your search

+31 -134
View File
@@ -3,7 +3,6 @@
using ValueSp = std::shared_ptr<dht::Value>;
using PrivkeySp = std::shared_ptr<dht::crypto::PrivateKey>;
using PubkeySp = std::shared_ptr<const dht::crypto::PublicKey>;
using CertSp = std::shared_ptr<dht::crypto::Certificate>;
#ifdef __cplusplus
@@ -11,19 +10,6 @@ extern "C" {
#endif
// dht::InfoHash
inline dht_infohash dht_infohash_to_c(const dht::InfoHash& h) {
dht_infohash ret;
*reinterpret_cast<dht::InfoHash*>(&ret) = h;
return ret;
}
inline dht_pkid dht_pkid_to_c(const dht::PkId& h) {
dht_pkid ret;
*reinterpret_cast<dht::PkId*>(&ret) = h;
return ret;
}
const char* dht_infohash_print(const dht_infohash* h) {
return reinterpret_cast<const dht::InfoHash*>(h)->to_c_str();
}
@@ -40,18 +26,10 @@ void dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size) {
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::get(dat, dat_size);
}
void dht_infohash_get_from_string(dht_infohash* h, const char* dat) {
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::get((const uint8_t*)dat, (size_t)strlen(dat));
}
bool dht_infohash_is_zero(const dht_infohash* h) {
return !static_cast<bool>(*reinterpret_cast<const dht::InfoHash*>(h));
}
void dht_infohash_from_hex(dht_infohash* h, const char* dat) {
*h = dht_infohash_to_c(dht::InfoHash(std::string(dat, HASH_LEN*2)));
}
const char* dht_pkid_print(const dht_pkid* h) {
return reinterpret_cast<const dht::PkId*>(h)->to_c_str();
}
@@ -82,21 +60,6 @@ dht_value_id dht_value_get_id(const dht_value* data) {
return vsp->id;
}
dht_publickey* dht_value_get_owner(const dht_value* data) {
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return vsp->owner ? reinterpret_cast<dht_publickey*>(new PubkeySp(vsp->owner)) : nullptr;
}
dht_infohash dht_value_get_recipient(const dht_value* data) {
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return dht_infohash_to_c(vsp->recipient);
}
const char* dht_value_get_user_type(const dht_value* data) {
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
return vsp->user_type.c_str();
}
dht_value* dht_value_new(const uint8_t* data, size_t size) {
return reinterpret_cast<dht_value*>(new ValueSp(std::make_shared<dht::Value>(data, size)));
}
@@ -110,46 +73,51 @@ void dht_value_unref(dht_value* v) {
}
// dht::crypto::PublicKey
dht_publickey* dht_publickey_import(const uint8_t* dat, size_t dat_size) {
try {
return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<const dht::crypto::PublicKey>(dat, dat_size)));
} catch (const dht::crypto::CryptoException& e) {
return nullptr;
}
dht_publickey* dht_publickey_new() {
return reinterpret_cast<dht_publickey*>(new dht::crypto::PublicKey);
}
void dht_publickey_delete(dht_publickey* pk) {
delete reinterpret_cast<PubkeySp*>(pk);
delete reinterpret_cast<dht::crypto::PublicKey*>(pk);
}
int dht_publickey_unpack(dht_publickey* pk, const uint8_t* dat, size_t dat_size) {
try {
reinterpret_cast<dht::crypto::PublicKey*>(pk)->unpack(dat, dat_size);
} catch (const dht::crypto::CryptoException& e) {
return -1;
}
return 0;
}
int dht_publickey_pack(dht_publickey* pk, char* out, size_t* outlen) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return gnutls_pubkey_export(pkey->pk, GNUTLS_X509_FMT_DER, out, outlen);
return gnutls_pubkey_export(reinterpret_cast<dht::crypto::PublicKey*>(pk)->pk, GNUTLS_X509_FMT_DER, out, outlen);
}
dht_infohash dht_publickey_get_id(const dht_publickey* pk) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return dht_infohash_to_c(pkey->getId());
auto pkey = reinterpret_cast<const dht::crypto::PublicKey*>(pk);
dht_infohash h;
*reinterpret_cast<dht::InfoHash*>(&h) = pkey->getId();
return h;
}
dht_pkid dht_publickey_get_long_id(const dht_publickey* pk) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return dht_pkid_to_c(pkey->getLongId());
auto pkey = reinterpret_cast<const dht::crypto::PublicKey*>(pk);
dht_pkid h;
*reinterpret_cast<dht::PkId*>(&h) = pkey->getLongId();
return h;
}
bool dht_publickey_check_signature(const dht_publickey* pk, const char* data, size_t data_size, const char* signature, size_t signature_size) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
return pkey->checkSignature((const uint8_t*)data, data_size, (const uint8_t*)signature, signature_size);
return reinterpret_cast<const dht::crypto::PublicKey*>(pk)->checkSignature((const uint8_t*)data, data_size, (const uint8_t*)signature, signature_size);
}
dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_t data_size) {
const auto& pkey = *reinterpret_cast<const PubkeySp*>(pk);
auto rdata = new dht::Blob;
*rdata = pkey->encrypt((const uint8_t*)data, data_size);
*rdata = reinterpret_cast<const dht::crypto::PublicKey*>(pk)->encrypt((const uint8_t*)data, data_size);
return (dht_blob*)rdata;
}
// dht::crypto::PrivateKey
dht_privatekey* dht_privatekey_generate(unsigned key_length_bits) {
if (key_length_bits == 0)
key_length_bits = 4096;
@@ -166,73 +134,13 @@ dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const
dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(key->getPublicKey())));
return reinterpret_cast<dht_publickey*>(new dht::crypto::PublicKey(key->getPublicKey()));
}
void dht_privatekey_delete(dht_privatekey* pk) {
delete reinterpret_cast<PrivkeySp*>(pk);
}
// dht::crypto::Certificate
dht_certificate* dht_certificate_import(const uint8_t* dat, size_t dat_size) {
try {
return reinterpret_cast<dht_certificate*>(new CertSp(std::make_shared<dht::crypto::Certificate>(dat, dat_size)));
} catch (const dht::crypto::CryptoException& e) {
return nullptr;
}
}
void dht_certificate_delete(dht_certificate* c) {
delete reinterpret_cast<CertSp*>(c);
}
dht_infohash dht_certificate_get_id(const dht_certificate* c) {
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return dht_infohash_to_c(cert->getId());
}
dht_pkid dht_certificate_get_long_id(const dht_certificate* c) {
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return dht_pkid_to_c(cert->getLongId());
}
dht_publickey* dht_certificate_get_publickey(const dht_certificate* c) {
const auto& cert = *reinterpret_cast<const CertSp*>(c);
return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(cert->getPublicKey())));
}
// dht::crypto::Identity
inline dht::crypto::Identity dht_identity_from_c(const dht_identity* cid) {
dht::crypto::Identity id {};
if (cid and cid->privatekey)
id.first = *reinterpret_cast<const PrivkeySp*>(cid->privatekey);
if (cid and cid->certificate)
id.second = *reinterpret_cast<const CertSp*>(cid->certificate);
return id;
}
inline dht_identity dht_identity_to_c(const dht::crypto::Identity& id) {
dht_identity cid {};
cid.privatekey = id.first ? reinterpret_cast<dht_privatekey*>(new PrivkeySp(id.first)) : NULL;
cid.certificate = id.second ? reinterpret_cast<dht_certificate*>(new CertSp(id.second)) : NULL;
return cid;
}
OPENDHT_C_PUBLIC dht_identity dht_identity_generate(const char* common_name, const dht_identity* ca) {
return dht_identity_to_c(dht::crypto::generateIdentity(common_name, dht_identity_from_c(ca)));
}
OPENDHT_C_PUBLIC void dht_identity_delete(dht_identity* id) {
if (id->certificate) {
dht_certificate_delete(id->certificate);
id->certificate = NULL;
}
if (id->privatekey) {
dht_privatekey_delete(id->privatekey);
id->privatekey = NULL;
}
}
// config
void dht_runner_config_default(dht_runner_config* config) {
bzero(config, sizeof(dht_runner_config));
@@ -263,8 +171,8 @@ void dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_confi
config.dht_config.node_config.persist_path = conf->dht_config.node_config.persist_path
? std::string(conf->dht_config.node_config.persist_path) : std::string{};
if (conf->dht_config.id.privatekey)
config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privatekey);
if (conf->dht_config.id.privkey)
config.dht_config.id.first = *reinterpret_cast<const PrivkeySp*>(conf->dht_config.id.privkey);
if (conf->dht_config.id.certificate)
config.dht_config.id.second = *reinterpret_cast<const CertSp*>(conf->dht_config.id.certificate);
@@ -341,35 +249,24 @@ void dht_op_token_delete(dht_op_token* token) {
delete reinterpret_cast<std::future<size_t>*>(token);
}
void dht_runner_put(dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data, bool permanent) {
void dht_runner_put(dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->put(*hash, *value, [done_cb, cb_user_data](bool ok){
if (done_cb)
done_cb(ok, cb_user_data);
}, dht::time_point::max(), permanent);
});
}
void dht_runner_put_signed(dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data, bool permanent) {
void dht_runner_put_permanent(dht_runner* r, const dht_infohash* h, const dht_value* v, dht_done_cb done_cb, void* cb_user_data) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->putSigned(*hash, *value, [done_cb, cb_user_data](bool ok){
runner->put(*hash, *value, [done_cb, cb_user_data](bool ok){
if (done_cb)
done_cb(ok, cb_user_data);
}, permanent);
}
void dht_runner_put_encrypted(dht_runner* r, const dht_infohash* h, const dht_infohash* to, const dht_value* v, dht_done_cb done_cb, void* cb_user_data, bool permanent) {
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
auto toHash = reinterpret_cast<const dht::InfoHash*>(to);
auto value = reinterpret_cast<const ValueSp*>(v);
runner->putEncrypted(*hash, *toHash, *value, [done_cb, cb_user_data](bool ok){
if (done_cb)
done_cb(ok, cb_user_data);
}, permanent);
}, dht::time_point::max(), true);
}
void dht_runner_cancel_put(dht_runner* r, const dht_infohash* h, dht_value_id value_id) {
+19 -30
View File
@@ -18,6 +18,16 @@ struct OPENDHT_C_PUBLIC dht_data_view {
};
typedef struct dht_data_view dht_data_view;
// dht::Value
struct OPENDHT_C_PUBLIC dht_value;
typedef struct dht_value dht_value;
typedef uint64_t dht_value_id;
OPENDHT_C_PUBLIC dht_data_view dht_value_get_data(const dht_value* data);
OPENDHT_C_PUBLIC dht_value_id dht_value_get_id(const dht_value* data);
OPENDHT_C_PUBLIC dht_value* dht_value_new(const uint8_t* data, size_t size);
OPENDHT_C_PUBLIC dht_value* dht_value_ref(const dht_value*);
OPENDHT_C_PUBLIC void dht_value_unref(dht_value*);
// dht::Blob
struct OPENDHT_C_PUBLIC dht_blob;
typedef struct dht_blob dht_blob;
@@ -29,9 +39,7 @@ struct OPENDHT_C_PUBLIC dht_infohash { uint8_t d[HASH_LEN]; };
typedef struct dht_infohash dht_infohash;
OPENDHT_C_PUBLIC void dht_infohash_zero(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_random(dht_infohash* h);
OPENDHT_C_PUBLIC void dht_infohash_from_hex(dht_infohash* h, const char* dat);
OPENDHT_C_PUBLIC void dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC void dht_infohash_get_from_string(dht_infohash* h, const char* str);
OPENDHT_C_PUBLIC const char* dht_infohash_print(const dht_infohash* h);
OPENDHT_C_PUBLIC bool dht_infohash_is_zero(const dht_infohash* h);
@@ -43,8 +51,9 @@ OPENDHT_C_PUBLIC const char* dht_pkid_print(const dht_pkid* h);
// dht::crypto::PublicKey
struct OPENDHT_C_PUBLIC dht_publickey;
typedef struct dht_publickey dht_publickey;
OPENDHT_C_PUBLIC dht_publickey* dht_publickey_import(const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC dht_publickey* dht_publickey_new();
OPENDHT_C_PUBLIC void dht_publickey_delete(dht_publickey* pk);
OPENDHT_C_PUBLIC int dht_publickey_unpack(dht_publickey* pk, const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC int dht_publickey_pack(dht_publickey* pk, char* out, size_t* out_size);
OPENDHT_C_PUBLIC dht_infohash dht_publickey_get_id(const dht_publickey* pk);
OPENDHT_C_PUBLIC dht_pkid dht_publickey_get_long_id(const dht_publickey* pk);
@@ -62,38 +71,18 @@ OPENDHT_C_PUBLIC void dht_privatekey_delete(dht_privatekey*);
// dht::crypto::Certificate
struct OPENDHT_C_PUBLIC dht_certificate;
typedef struct dht_certificate dht_certificate;
OPENDHT_C_PUBLIC dht_certificate* dht_certificate_import(const uint8_t* dat, size_t dat_size);
OPENDHT_C_PUBLIC dht_infohash dht_certificate_get_id(const dht_certificate*);
OPENDHT_C_PUBLIC dht_pkid dht_certificate_get_long_id(const dht_certificate*);
OPENDHT_C_PUBLIC dht_publickey* dht_certificate_get_publickey(const dht_certificate*);
OPENDHT_C_PUBLIC void dht_certificate_delete(dht_certificate*);
struct OPENDHT_PUBLIC dht_identity {
dht_privatekey* privatekey;
dht_privatekey* privkey;
dht_certificate* certificate;
};
typedef struct dht_identity dht_identity;
OPENDHT_C_PUBLIC dht_identity dht_identity_generate(const char* common_name, const dht_identity* ca);
OPENDHT_C_PUBLIC void dht_identity_delete(dht_identity*);
// dht::Value
struct OPENDHT_C_PUBLIC dht_value;
typedef struct dht_value dht_value;
typedef uint64_t dht_value_id;
OPENDHT_C_PUBLIC dht_value* dht_value_new(const uint8_t* data, size_t size);
OPENDHT_C_PUBLIC dht_value* dht_value_ref(const dht_value*);
OPENDHT_C_PUBLIC void dht_value_unref(dht_value*);
OPENDHT_C_PUBLIC dht_data_view dht_value_get_data(const dht_value* data);
OPENDHT_C_PUBLIC dht_value_id dht_value_get_id(const dht_value* data);
OPENDHT_C_PUBLIC dht_publickey* dht_value_get_owner(const dht_value* data);
OPENDHT_C_PUBLIC dht_infohash dht_value_get_recipient(const dht_value* data);
OPENDHT_C_PUBLIC const char* dht_value_get_user_type(const dht_value* data);
// callbacks
typedef bool (*dht_get_cb)(const dht_value* value, void* user_data);
typedef bool (*dht_value_cb)(const dht_value* value, bool expired, void* user_data);
typedef void (*dht_done_cb)(bool ok, void* user_data);
typedef void (*dht_shutdown_cb)(void* user_data);
typedef bool (*dht_done_cb)(bool ok, void* user_data);
typedef bool (*dht_shutdown_cb)(void* user_data);
struct OPENDHT_C_PUBLIC dht_op_token;
typedef struct dht_op_token dht_op_token;
@@ -109,7 +98,8 @@ struct OPENDHT_PUBLIC dht_node_config {
};
typedef struct dht_node_config dht_node_config;
struct OPENDHT_PUBLIC dht_secure_config {
struct OPENDHT_PUBLIC dht_secure_config
{
dht_node_config node_config;
dht_identity id;
};
@@ -141,9 +131,8 @@ OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host,
OPENDHT_C_PUBLIC void dht_runner_get(dht_runner* runner, const dht_infohash* hash, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_op_token* dht_runner_listen(dht_runner* runner, const dht_infohash* hash, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_cancel_listen(dht_runner* runner, const dht_infohash* hash, dht_op_token* token);
OPENDHT_C_PUBLIC void dht_runner_put(dht_runner* runner, const dht_infohash* hash, const dht_value* value, dht_done_cb done_cb, void* cb_user_data, bool permanent);
OPENDHT_C_PUBLIC void dht_runner_put_signed(dht_runner* runner, const dht_infohash* hash, const dht_value* value, dht_done_cb done_cb, void* cb_user_data, bool permanent);
OPENDHT_C_PUBLIC void dht_runner_put_encrypted(dht_runner* runner, const dht_infohash* hash, const dht_infohash* to, const dht_value* value, dht_done_cb done_cb, void* cb_user_data, bool permanent);
OPENDHT_C_PUBLIC void dht_runner_put(dht_runner* runner, const dht_infohash* hash, const dht_value* value, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_put_permanent(dht_runner* runner, const dht_infohash* hash, const dht_value* value, dht_done_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC void dht_runner_cancel_put(dht_runner* runner, const dht_infohash* hash, dht_value_id value_id);
OPENDHT_C_PUBLIC void dht_runner_shutdown(dht_runner* runner, dht_shutdown_cb done_cb, void* cb_user_data);
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_node_id(const dht_runner* runner);
+7 -4
View File
@@ -2,7 +2,7 @@ FROM ubuntu:16.04
MAINTAINER Adrien Béraud <adrien.beraud@savoirfairelinux.com>
RUN apt-get update && apt-get install -y \
build-essential cmake git wget libncurses5-dev libreadline-dev nettle-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev python3-setuptools libcppunit-dev libjsoncpp-dev \
libgnutls28-dev libuv1-dev cython3 python3-dev libcppunit-dev libjsoncpp-dev \
autotools-dev autoconf libasio-dev \
&& apt-get clean
@@ -28,11 +28,14 @@ RUN echo "** Building a recent version of asio ***" \
&& make install \
&& cd ../../ && rm -rf asio*
#patch for https://github.com/Stiffstream/restinio-conan-example/issues/2
RUN apt-get update && apt-get install -y python3-pip && pip3 install --upgrade cmake
RUN echo "*** Downloading RESTinio ***" \
&& mkdir restinio && cd restinio \
&& wget https://github.com/aberaud/restinio/archive/8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59.tar.gz \
&& ls -l && tar -xzf 8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59.tar.gz \
&& cd restinio-8d5d3e8237e0947adb9ba1ffc8281f4ad7cb2a59/dev \
&& wget https://github.com/Stiffstream/restinio/archive/v.0.5.1.2.tar.gz \
&& ls -l && tar -xzf v.0.5.1.2.tar.gz \
&& cd restinio-v.0.5.1.2/dev \
&& cmake -DCMAKE_INSTALL_PREFIX=/usr -DRESTINIO_TEST=OFF -DRESTINIO_SAMPLE=OFF \
-DRESTINIO_INSTALL_SAMPLES=OFF -DRESTINIO_BENCH=OFF -DRESTINIO_INSTALL_BENCHES=OFF \
-DRESTINIO_FIND_DEPS=ON -DRESTINIO_ALLOW_SOBJECTIZER=Off -DRESTINIO_USE_BOOST_ASIO=none . \
+1 -2
View File
@@ -72,8 +72,7 @@ struct OPENDHT_PUBLIC PublicKey
* Takes ownership of an existing gnutls_pubkey.
*/
PublicKey(gnutls_pubkey_t k) : pk(k) {}
PublicKey(const uint8_t* dat, size_t dat_size);
PublicKey(const Blob& pk) : PublicKey(pk.data(), pk.size()) {}
PublicKey(const Blob& pk);
PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; };
~PublicKey();
+23 -23
View File
@@ -285,7 +285,9 @@ private:
*/
struct InfoState;
void getProxyInfos();
void queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t family, std::shared_ptr<http::Resolver> resolver);
void handleProxyStatus(const asio::error_code &ec, std::shared_ptr<InfoState> infoState);
void queryProxyInfo(std::shared_ptr<InfoState> infoState, const sa_family_t family,
std::vector<asio::ip::tcp::endpoint>&& endpoints);
void onProxyInfos(const Json::Value& val, const sa_family_t family);
SockAddr parsePublicAddress(const Json::Value& val);
@@ -308,8 +310,9 @@ private:
void handleResubscribe(const asio::error_code& ec, const InfoHash& key,
const size_t token, std::shared_ptr<OperationState> opstate);
void doPut(const InfoHash&, Sp<Value>, DoneCallbackSimple, time_point created, bool permanent);
void handleRefreshPut(const asio::error_code& ec, InfoHash key, Value::Id id);
void doPut(const InfoHash&, Sp<Value>, DoneCallback, time_point created, bool permanent);
void handleRefreshPut(const asio::error_code& ec, const InfoHash& key, const Value::Id id,
std::shared_ptr<std::atomic_bool> ok);
/**
* Initialize statusIpvX_
@@ -324,12 +327,23 @@ private:
*/
void cancelAllOperations();
std::string proxyUrl_;
dht::crypto::Identity clientIdentity_;
std::shared_ptr<dht::crypto::Certificate> serverCertificate_;
//std::pair<std::string, std::string> serverHostService_;
std::pair<std::string, std::string> serverHostService_;
std::string pushClientId_;
/*
* ASIO I/O Context for sockets in httpClient_
* Note: Each context is used in one thread only
*/
asio::io_context httpContext_;
std::shared_ptr<http::Resolver> resolver_;
std::map<unsigned int /*id*/, std::shared_ptr<http::Request>> requests_;
/*
* Thread for executing the http io_context.run() blocking call
*/
std::thread httpClientThread_;
mutable std::mutex lockCurrentProxyInfos_;
NodeStatus statusIpv4_ {NodeStatus::Disconnected};
NodeStatus statusIpv6_ {NodeStatus::Disconnected};
@@ -343,34 +357,24 @@ private:
// registred types
TypeStore types;
/*
* ASIO I/O Context for sockets in httpClient_
* Note: Each context is used in one thread only
*/
asio::io_context httpContext_;
std::shared_ptr<http::Resolver> resolver_;
std::map<unsigned int /*id*/, std::shared_ptr<http::Request>> requests_;
/*
* Thread for executing the http io_context.run() blocking call
*/
std::thread httpClientThread_;
/**
* Store listen requests.
*/
struct ProxySearch;
mutable std::mutex searchLock_;
size_t listenerToken_ {0};
std::map<InfoHash, ProxySearch> searches_;
mutable std::mutex searchLock_;
/**
* Callbacks should be executed in the main thread.
*/
std::mutex lockCallbacks_;
std::vector<std::function<void()>> callbacks_;
std::mutex lockCallbacks_;
Sp<InfoState> infoState_;
Sp<asio::steady_timer> statusTimer_;
mutable std::mutex statusLock_;
/**
* Retrieve if we can connect to the proxy (update statusIpvX_)
@@ -405,11 +409,7 @@ private:
std::atomic_bool isDestroying_ {false};
Json::StreamWriterBuilder jsonBuilder_;
Json::CharReaderBuilder jsonReaderBuilder_;
std::shared_ptr<dht::Logger> logger_;
std::shared_ptr<http::Request> buildRequest(const std::string& target = {});
};
}
+3 -5
View File
@@ -149,8 +149,6 @@ private:
std::unique_ptr<RestRouter> createRestRouter();
void onConnectionClosed(restinio::connection_id_t);
/**
* Return the PublicKey id, the node id and node stats
* Method: GET "/"
@@ -319,7 +317,6 @@ private:
std::shared_ptr<DhtRunner> dht_;
Json::StreamWriterBuilder jsonBuilder_;
Json::CharReaderBuilder jsonReaderBuilder_;
// http server
std::thread serverThread_;
@@ -338,9 +335,10 @@ private:
std::unique_ptr<asio::steady_timer> printStatsTimer_;
// Thread-safe access to listeners map.
std::mutex lockListener_;
std::shared_ptr<std::mutex> lockListener_;
// Shared with connection listener.
std::map<restinio::connection_id_t, http::ListenerSession> listeners_;
std::shared_ptr<std::map<restinio::connection_id_t,
http::ListenerSession>> listeners_;
// Connection Listener observing conn state changes.
std::shared_ptr<ConnectionListener> connListener_;
+15 -16
View File
@@ -230,30 +230,29 @@ public:
}
void put(const std::string& key, Value&& value, DoneCallbackSimple cb={}, time_point created=time_point::max(), bool permanent = false);
void cancelPut(const InfoHash& h, Value::Id id);
void cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value);
void cancelPut(const InfoHash& h, const Value::Id& id);
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
putSigned(hash, value, bindDoneCb(cb), permanent);
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb={});
void putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallbackSimple cb) {
putSigned(hash, value, bindDoneCb(cb));
}
void putSigned(InfoHash hash, Value&& value, DoneCallback cb={}, bool permanent = false);
void putSigned(InfoHash hash, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
putSigned(hash, std::forward<Value>(value), bindDoneCb(cb), permanent);
void putSigned(InfoHash hash, Value&& value, DoneCallback cb={});
void putSigned(InfoHash hash, Value&& value, DoneCallbackSimple cb) {
putSigned(hash, std::forward<Value>(value), bindDoneCb(cb));
}
void putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb={}, bool permanent = false);
void putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb={});
void putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
void putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
void putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb={});
void putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallbackSimple cb) {
putEncrypted(hash, to, value, bindDoneCb(cb));
}
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb={}, bool permanent = false);
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb={});
void putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallbackSimple cb) {
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb));
}
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb={}, bool permanent = false);
void putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb={});
/**
* Insert known nodes to the routing table, without necessarly ping them.
+6 -14
View File
@@ -147,7 +147,7 @@ class OPENDHT_PUBLIC Resolver
{
public:
using ResolverCb = std::function<void(const asio::error_code& ec,
const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
std::vector<asio::ip::tcp::endpoint> endpoints)>;
Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger = {});
Resolver(asio::io_context& ctx, const std::string& host, const std::string& service,
@@ -156,20 +156,14 @@ public:
// use already resolved endpoints with classes using this resolver
Resolver(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint> endpoints,
const bool ssl = false, std::shared_ptr<dht::Logger> logger = {});
Resolver(asio::io_context& ctx, const std::string& url, std::vector<asio::ip::tcp::endpoint> endpoints,
std::shared_ptr<dht::Logger> logger = {});
~Resolver();
inline const Url& get_url() const {
return url_;
}
};
void add_callback(ResolverCb cb, sa_family_t family = AF_UNSPEC);
std::shared_ptr<Logger> getLogger() const {
return logger_;
}
void add_callback(ResolverCb cb);
private:
void resolve(const std::string& host, const std::string& service);
@@ -218,8 +212,7 @@ public:
const bool ssl = false, std::shared_ptr<dht::Logger> logger = {});
// user defined resolver
Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, const std::string& target, sa_family_t family = AF_UNSPEC);
Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, std::shared_ptr<dht::Logger> logger = {});
// user defined resolved endpoints
Request(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint>&& endpoints,
@@ -314,7 +307,7 @@ private:
std::string body_;
std::mutex cbs_mutex_;
Callbacks cbs_;
std::unique_ptr<Callbacks> cbs_;
State state_;
dht::crypto::Identity client_identity_;
@@ -323,9 +316,8 @@ private:
std::string host_;
unsigned int id_;
asio::io_context& ctx_;
sa_family_t family_ = AF_UNSPEC;
static unsigned int ids_;
asio::io_context& ctx_;
std::shared_ptr<Connection> conn_;
std::shared_ptr<Resolver> resolver_;
+3 -9
View File
@@ -43,15 +43,9 @@ public:
template<class T>
std::future<T> get(std::function<T()>&& cb) {
auto ret = std::make_shared<std::promise<T>>();
run([cb = std::move(cb), ret]() mutable {
try {
ret->set_value(cb());
} catch (...) {
try {
ret->set_exception(std::current_exception());
} catch(...) {}
}
});
run(std::bind([=](std::function<T()>& mcb) mutable {
ret->set_value(mcb());
}, std::move(cb)));
return ret->get_future();
}
template<class T>
+4 -4
View File
@@ -167,7 +167,7 @@ struct OPENDHT_PUBLIC Value
static Filter chain(Filter&& f1, Filter&& f2) {
if (not f1) return std::move(f2);
if (not f2) return std::move(f1);
return [f1 = std::move(f1), f2 = std::move(f2)](const Value& v) {
return [f1,f2](const Value& v) {
return f1(v) and f2(v);
};
}
@@ -180,12 +180,12 @@ struct OPENDHT_PUBLIC Value
}
static Filter chainAll(std::vector<Filter>&& set) {
if (set.empty()) return {};
return [set = std::move(set)](const Value& v) {
for (const auto& f : set)
return std::bind([](const Value& v, std::vector<Filter>& s) {
for (const auto& f : s)
if (f and not f(v))
return false;
return true;
};
}, std::placeholders::_1, std::move(set));
}
static Filter chain(std::initializer_list<Filter> l) {
return chainAll(std::vector<Filter>(l.begin(), l.end()));
+2 -13
View File
@@ -20,7 +20,6 @@ extern crate opendht;
use std::{ thread, time };
use opendht::{ InfoHash, DhtRunner, DhtRunnerConfig, Value };
// use opendht::crypto::*;
fn main() {
println!("{}", InfoHash::random());
@@ -29,24 +28,15 @@ fn main() {
println!("{}", InfoHash::get("alice"));
println!("{}", InfoHash::get("alice").is_zero());
let mut dht = DhtRunner::new();
let /*mut*/ config = DhtRunnerConfig::new();
//// If you want to inject a certificate, uncomment the following lines and previous mut.
//// Note: you can generate a certificate with
//// openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout example.key -out example.crt -subj /CN=example.com
//let cert = DhtCertificate::import("example.crt").ok().expect("Invalid cert file");
//let pk = PrivateKey::import("example.key", "");
//config.set_identity(cert, pk);
let config = DhtRunnerConfig::new();
dht.run_config(1412, config);
dht.bootstrap("bootstrap.jami.net", 4222);
println!("Current node id: {}", dht.node_id());
let /* mut */ data = 42;
let mut get_cb = |v: Box<Value>| {
//data += 1;
println!("GET: VALUE CB - data: {} - v: {}", data, v);
true
};
let mut done_cb = |ok: bool| {
println!("GET: DONE CB - data: {} - ok: {}", data, ok);
@@ -57,13 +47,12 @@ fn main() {
let mut put_done_cb = |ok: bool| {
println!("PUT: DONE CB - data: {} - ok: {}", data, ok);
};
dht.put(&InfoHash::get("bob"), Value::new("hi!"), &mut put_done_cb, false);
dht.put(&InfoHash::get("bob"), Value::new("hi!"), &mut put_done_cb);
println!("Start listening /foo");
let mut value_cb = |v, expired| {
println!("LISTEN: DONE CB - data: {} - v: {} - expired: {}", data, v, expired);
true
};
let token = dht.listen(&InfoHash::get("foo"), &mut value_cb);
let one_min = time::Duration::from_secs(10);
+7 -87
View File
@@ -18,17 +18,13 @@
#![allow(dead_code)]
pub use crate::ffi::*;
use crate::ffi::*;
use std::ffi::CString;
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::ptr;
impl PublicKey {
pub fn new(data: &str) -> Box<PublicKey> {
pub fn new() -> Box<PublicKey> {
unsafe {
Box::from_raw(dht_publickey_import(data.as_ptr(), data.len()))
Box::from_raw(dht_publickey_new())
}
}
@@ -93,17 +89,11 @@ impl PrivateKey {
}
}
pub fn import(file: &str, password: &str) -> io::Result<Box<PrivateKey>> {
let mut f = File::open(file)?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?;
Ok(PrivateKey::from_bytes(&buffer, password))
}
pub fn from_bytes(buffer: &Vec<u8>, password: &str) -> Box<PrivateKey> {
pub fn import(data: &str, password: &str) -> Box<PrivateKey> {
let password = CString::new(password).unwrap();
unsafe {
Box::from_raw(dht_privatekey_import((&*buffer).as_ptr(), buffer.len(),
password.as_ptr() as *const i8))
Box::from_raw(dht_privatekey_import(data.as_ptr(),
data.as_bytes().len(), password.as_ptr()))
}
}
@@ -121,74 +111,4 @@ impl Drop for PrivateKey {
dht_privatekey_delete(&mut *self)
}
}
}
impl DhtCertificate {
pub fn import(file: &str) -> io::Result<Box<DhtCertificate>> {
let mut f = File::open(file)?;
let mut buffer = Vec::new();
f.read_to_end(&mut buffer)?;
Ok(DhtCertificate::from_bytes(&buffer))
}
pub fn from_bytes(buffer: &Vec<u8>) -> Box<DhtCertificate> {
unsafe {
Box::from_raw(dht_certificate_import((&*buffer).as_ptr(), buffer.len()))
}
}
pub fn from_slice(buffer: &str) -> Box<DhtCertificate> {
unsafe {
Box::from_raw(dht_certificate_import((&*buffer).as_ptr(), buffer.len()))
}
}
pub fn id(&self) -> InfoHash {
unsafe {
dht_certificate_get_id(&*self)
}
}
pub fn long_id(&self) -> PkId {
unsafe {
dht_certificate_get_long_id(&*self)
}
}
pub fn publickey(&self) -> Box<PublicKey> {
unsafe {
Box::from_raw(dht_certificate_get_publickey(&*self))
}
}
}
impl Drop for DhtCertificate {
fn drop(&mut self) {
unsafe {
dht_certificate_delete(&mut *self)
}
}
}
impl DhtIdentity {
pub fn new(common_name: &str) -> DhtIdentity {
unsafe {
DhtIdentity::generate(common_name, Box::from_raw(ptr::null_mut()))
}
}
pub fn generate(common_name: &str, ca: Box<DhtIdentity>) -> DhtIdentity {
let common_name = CString::new(common_name).unwrap();
unsafe {
dht_identity_generate(common_name.as_ptr(), &*ca)
}
}
}
impl Drop for DhtIdentity {
fn drop(&mut self) {
unsafe {
dht_identity_delete(&mut *self)
}
}
}
+16 -32
View File
@@ -39,7 +39,7 @@ impl DhtRunnerConfig {
persist_path: ptr::null(),
},
id: DhtIdentity {
privatekey: ptr::null_mut(),
privkey: ptr::null_mut(),
certificate: ptr::null_mut(),
},
},
@@ -51,7 +51,7 @@ impl DhtRunnerConfig {
peer_publish: false,
server_ca: ptr::null_mut(),
client_identity: DhtIdentity {
privatekey: ptr::null_mut(),
privkey: ptr::null_mut(),
certificate: ptr::null_mut(),
},
});
@@ -73,11 +73,6 @@ impl DhtRunnerConfig {
self.push_token = CString::new(push_token).unwrap().as_ptr();
}
pub fn set_identity(&mut self, certificate: Box<DhtCertificate>, privatekey: Box<PrivateKey>) {
self.dht_config.id.privatekey = Box::into_raw(privatekey);
self.dht_config.id.certificate = Box::into_raw(certificate);
}
}
impl DhtNodeConfig
@@ -89,13 +84,13 @@ impl DhtNodeConfig
struct GetHandler<'a>
{
get_cb: &'a mut(dyn FnMut(Box<Value>) -> bool),
get_cb: &'a mut(dyn FnMut(Box<Value>)),
done_cb: &'a mut(dyn FnMut(bool))
}
impl<'a> GetHandler<'a>
{
fn get_cb(&mut self, v: Box<Value>) -> bool{
fn get_cb(&mut self, v: Box<Value>) {
(self.get_cb)(v)
}
@@ -104,9 +99,9 @@ impl<'a> GetHandler<'a>
}
}
extern fn get_handler_cb(v: *mut Value, ptr: *mut c_void) -> bool {
extern fn get_handler_cb(v: *mut Value, ptr: *mut c_void) {
if ptr.is_null() {
return true;
return;
}
unsafe {
let handler = ptr as *mut GetHandler;
@@ -142,17 +137,17 @@ extern fn put_handler_done(ok: bool, ptr: *mut c_void) {
struct ListenHandler<'a>
{
cb: &'a mut(dyn FnMut(Box<Value>, bool) -> bool)
cb: &'a mut(dyn FnMut(Box<Value>, bool))
}
impl<'a> ListenHandler<'a>
{
fn cb(&mut self, v: Box<Value>, expired: bool) -> bool {
fn cb(&mut self, v: Box<Value>, expired: bool) {
(self.cb)(v, expired)
}
}
extern fn listen_handler(v: *mut Value, expired: bool, ptr: *mut c_void) -> bool {
extern fn listen_handler(v: *mut Value, expired: bool, ptr: *mut c_void) {
unsafe {
let handler = ptr as *mut ListenHandler;
(*handler).cb((*v).boxed(), expired)
@@ -205,7 +200,7 @@ impl DhtRunner {
}
pub fn get<'a>(&mut self, h: &InfoHash,
get_cb: &'a mut(dyn FnMut(Box<Value>) -> bool),
get_cb: &'a mut(dyn FnMut(Box<Value>)),
done_cb: &'a mut(dyn FnMut(bool))) {
let handler = Box::new(GetHandler {
get_cb,
@@ -218,35 +213,24 @@ impl DhtRunner {
}
pub fn put<'a>(&mut self, h: &InfoHash, v: Box<Value>,
done_cb: &'a mut(dyn FnMut(bool)), permanent: bool) {
done_cb: &'a mut(dyn FnMut(bool))) {
let handler = Box::new(PutHandler {
done_cb,
});
let handler = Box::into_raw(handler) as *mut c_void;
unsafe {
dht_runner_put(&mut *self, h, &*v, put_handler_done, handler, permanent)
dht_runner_put(&mut *self, h, &*v, put_handler_done, handler)
}
}
pub fn put_signed<'a>(&mut self, h: &InfoHash, v: Box<Value>,
done_cb: &'a mut(dyn FnMut(bool)), permanent: bool) {
pub fn permanent_put<'a>(&mut self, h: &InfoHash, v: Box<Value>,
done_cb: &'a mut(dyn FnMut(bool))) {
let handler = Box::new(PutHandler {
done_cb,
});
let handler = Box::into_raw(handler) as *mut c_void;
unsafe {
dht_runner_put_signed(&mut *self, h, &*v, put_handler_done, handler, permanent)
}
}
pub fn put_encrypted<'a>(&mut self, h: &InfoHash, to: &InfoHash, v: Box<Value>,
done_cb: &'a mut(dyn FnMut(bool)), permanent: bool) {
let handler = Box::new(PutHandler {
done_cb,
});
let handler = Box::into_raw(handler) as *mut c_void;
unsafe {
dht_runner_put_encrypted(&mut *self, h, to, &*v, put_handler_done, handler, permanent)
dht_runner_put_permanent(&mut *self, h, &*v, put_handler_done, handler)
}
}
@@ -257,7 +241,7 @@ impl DhtRunner {
}
pub fn listen<'a>(&mut self, h: &InfoHash,
cb: &'a mut(dyn FnMut(Box<Value>, bool) -> bool)) -> Box<OpToken> {
cb: &'a mut(dyn FnMut(Box<Value>, bool))) -> Box<OpToken> {
let handler = Box::new(ListenHandler {
cb,
});
+10 -35
View File
@@ -44,7 +44,6 @@ pub struct Blob
}
#[repr(C)]
#[derive(PartialEq)]
pub struct InfoHash
{
pub d: [u8; HASH_LEN],
@@ -99,7 +98,7 @@ pub struct DhtCertificate
#[repr(C)]
pub struct DhtIdentity
{
pub privatekey: *mut PrivateKey,
pub privkey: *mut PrivateKey,
pub certificate: *mut DhtCertificate,
}
@@ -128,14 +127,11 @@ pub struct DhtRunnerConfig
#[link(name = "opendht-c")]
extern {
// dht::Value
pub fn dht_value_get_id(data: *const Value) -> u64;
pub fn dht_value_get_data(data: *const Value) -> DataView;
pub fn dht_value_new(data: *const u8, size: size_t) -> *mut Value;
pub fn dht_value_ref(data: *const Value) -> *mut Value;
pub fn dht_value_unref(data: *mut Value);
pub fn dht_value_get_data(data: *const Value) -> DataView;
pub fn dht_value_get_id(data: *const Value) -> u64;
pub fn dht_value_get_owner(data: *const Value) -> *mut PublicKey;
pub fn dht_value_get_recipient(data: *const Value) -> InfoHash;
pub fn dht_value_get_user_type(data: *const Value) -> *const c_char;
// dht::Blob
pub fn dht_blob_get_data(data: *const Blob) -> DataView;
@@ -145,14 +141,13 @@ extern {
pub fn dht_infohash_print(h: *const InfoHash) -> *const c_char;
pub fn dht_infohash_random(h: *mut InfoHash);
pub fn dht_infohash_get(h: *mut InfoHash, dat: *mut u8, dat_size: size_t);
pub fn dht_infohash_from_hex(h: *mut InfoHash, dat: *const c_char);
pub fn dht_infohash_is_zero(j: *const InfoHash) -> bool;
// dht::PkId
pub fn dht_pkid_print(h: *const PkId) -> *const c_char;
// dht::crypto::PublicKey
pub fn dht_publickey_import(dat: *const u8, dat_size: size_t) -> *mut PublicKey;
pub fn dht_publickey_new() -> *mut PublicKey;
pub fn dht_publickey_delete(pk: *mut PublicKey);
pub fn dht_publickey_unpack(pk: *mut PublicKey, dat: *const u8, dat_size: size_t) -> c_int;
pub fn dht_publickey_pack(pk: *mut PublicKey, out: *const c_char, out_size: size_t) -> c_int;
@@ -167,16 +162,6 @@ extern {
pub fn dht_privatekey_get_publickey(pk: *const PrivateKey) -> *mut PublicKey;
pub fn dht_privatekey_delete(pk: *mut PrivateKey);
// dht::crypto::Certificate
pub fn dht_certificate_import(dat: *const u8, dat_size: size_t) -> *mut DhtCertificate;
pub fn dht_certificate_get_id(cert: *const DhtCertificate) -> InfoHash;
pub fn dht_certificate_get_long_id(cert: *const DhtCertificate) -> PkId;
pub fn dht_certificate_get_publickey(cert: *const DhtCertificate) -> *mut PublicKey;
pub fn dht_certificate_delete(cert: *mut DhtCertificate);
pub fn dht_identity_generate(common_name: *const c_char, ca: *const DhtIdentity) -> DhtIdentity;
pub fn dht_identity_delete(ca: *mut DhtIdentity);
// dht::OpToken
pub fn dht_op_token_delete(token: *mut OpToken);
@@ -190,28 +175,18 @@ extern {
pub fn dht_runner_run_config(dht: *mut DhtRunner, port: in_port_t, config: *const DhtRunnerConfig);
pub fn dht_runner_bootstrap(dht: *mut DhtRunner, host: *const c_char, service: *const c_char);
pub fn dht_runner_get(dht: *mut DhtRunner, h: *const InfoHash,
get_cb: extern fn(*mut Value, *mut c_void) -> bool,
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void);
get_cb: extern fn(*mut Value, *mut c_void),
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void);
pub fn dht_runner_put(dht: *mut DhtRunner, h: *const InfoHash, v: *const Value,
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void,
permanent: bool);
pub fn dht_runner_put_signed(dht: *mut DhtRunner, h: *const InfoHash, v: *const Value,
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void,
permanent: bool);
pub fn dht_runner_put_encrypted(dht: *mut DhtRunner, h: *const InfoHash,
to: *const InfoHash, v: *const Value,
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void,
permanent: bool);
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void);
pub fn dht_runner_put_permanent(dht: *mut DhtRunner, h: *const InfoHash, v: *const Value,
done_cb: extern fn(bool, *mut c_void),
cb_user_data: *mut c_void);
pub fn dht_runner_cancel_put(dht: *mut DhtRunner, h: *const InfoHash, vid: u64);
pub fn dht_runner_listen(dht: *mut DhtRunner, h: *const InfoHash,
cb: extern fn(*mut Value, bool, *mut c_void) -> bool,
cb: extern fn(*mut Value, bool, *mut c_void),
done_cb: extern fn(*mut c_void),
cb_user_data: *mut c_void) -> *mut OpToken;
pub fn dht_runner_cancel_listen(dht: *mut DhtRunner, h: *const InfoHash,
-17
View File
@@ -47,23 +47,6 @@ impl InfoHash {
h
}
pub fn from_bytes(data: &Vec<u8>) -> InfoHash {
let mut h = InfoHash::new();
unsafe {
dht_infohash_get(&mut h, data.as_ptr() as *mut u8, data.len());
}
h
}
pub fn from_hex(data: &str) -> InfoHash {
let mut h = InfoHash::new();
unsafe {
let c_str = CString::new(data).unwrap();
dht_infohash_from_hex(&mut h, c_str.as_ptr());
}
h
}
pub fn is_zero(&self) -> bool {
unsafe {
dht_infohash_is_zero(self)
-24
View File
@@ -15,11 +15,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#![allow(dead_code)]
use crate::ffi::*;
use std::fmt;
use std::ffi::{ CString, IntoStringError };
use std::str;
use std::slice;
@@ -64,28 +62,6 @@ impl Value {
Box::from_raw(dht_value_ref(self))
}
}
pub fn recipient(&self) -> InfoHash {
unsafe {
dht_value_get_recipient(self)
}
}
pub fn owner(&self) -> Option<Box<PublicKey>> {
unsafe {
let ptr = dht_value_get_owner(self);
if ptr.is_null() {
return None;
}
Some(Box::from_raw(ptr))
}
}
pub fn user_type(&self) -> Result<String, IntoStringError> {
unsafe {
CString::from_raw(dht_value_get_user_type(self) as *mut _).into_string()
}
}
}
impl Drop for Value {
+3 -24
View File
@@ -52,9 +52,6 @@ static std::uniform_int_distribution<uint8_t> rand_byte;
#define GNUTLS_PKCS_PBES2_AES_256 GNUTLS_PKCS_USE_PBES2_AES_256
#endif
#define DHT_AES_LEGACY_ENCRYPT 1
#define DHT_AES_LEGACY_DECRYPT 1
namespace dht {
namespace crypto {
@@ -108,9 +105,6 @@ Blob aesEncrypt(const uint8_t* data, size_t data_length, const Blob& key)
struct gcm_aes_ctx aes;
gcm_aes_set_key(&aes, key.size(), key.data());
gcm_aes_set_iv(&aes, GCM_IV_SIZE, ret.data());
#if DHT_AES_LEGACY_ENCRYPT
gcm_aes_update(&aes, data_length, data);
#endif
gcm_aes_encrypt(&aes, data_length, ret.data() + GCM_IV_SIZE, data);
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, ret.data() + GCM_IV_SIZE + data_length);
@@ -145,23 +139,8 @@ Blob aesDecrypt(const Blob& data, const Blob& key)
gcm_aes_decrypt(&aes, data_sz, ret.data(), data.data() + GCM_IV_SIZE);
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, digest.data());
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE)) {
#if DHT_AES_LEGACY_DECRYPT
//gcm_aes_decrypt(&aes, data_sz, ret.data(), data.data() + GCM_IV_SIZE);
Blob ret_tmp(data_sz);
struct gcm_aes_ctx aes_d;
gcm_aes_set_key(&aes_d, key.size(), key.data());
gcm_aes_set_iv(&aes_d, GCM_IV_SIZE, data.data());
gcm_aes_update(&aes_d, ret.size(), ret.data());
gcm_aes_encrypt(&aes_d, ret.size(), ret_tmp.data(), ret.data());
gcm_aes_digest(&aes_d, GCM_DIGEST_SIZE, digest.data());
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE))
throw DecryptError("Can't decrypt data");
#else
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE))
throw DecryptError("Can't decrypt data");
#endif
}
return ret;
}
@@ -374,9 +353,9 @@ PublicKey::PublicKey()
throw CryptoException(std::string("Can't initialize public key: ") + gnutls_strerror(err));
}
PublicKey::PublicKey(const uint8_t* dat, size_t dat_size) : PublicKey()
PublicKey::PublicKey(const Blob& dat) : PublicKey()
{
unpack(dat, dat_size);
unpack(dat.data(), dat.size());
}
PublicKey::~PublicKey()
+2 -1
View File
@@ -921,7 +921,8 @@ Dht::put(const InfoHash& id, Sp<Value> val, DoneCallback callback, time_point cr
}
if (val->id == Value::INVALID_ID) {
crypto::random_device rdev;
val->id = std::uniform_int_distribution<Value::Id>{1}(rdev);
std::uniform_int_distribution<Value::Id> rand_id {};
val->id = rand_id(rdev);
}
scheduler.syncTime();
const auto& now = scheduler.time();
+229 -115
View File
@@ -80,10 +80,9 @@ DhtProxyClient::DhtProxyClient(
pushClientId_(pushClientId), loopSignal_(signal), logger_(logger)
{
// build http client
proxyUrl_ = serverHost;
jsonBuilder_["commentStyle"] = "None";
jsonBuilder_["indentation"] = "";
serverHostService_ = splitPort(serverHost);
serverHostService_.second = serverHostService_.second.empty() ? "80" :
serverHostService_.second;
if (logger_){
if (serverCertificate_)
logger_->d("[proxy:client] using ca certificate for ssl:\n%s",
@@ -92,6 +91,8 @@ DhtProxyClient::DhtProxyClient(
logger_->d("[proxy:client] using client certificate for ssl:\n%s",
clientIdentity_.second->toString(false/*chain*/).c_str());
}
// resolve once
resolver_ = std::make_shared<http::Resolver>(httpContext_, serverHost, logger_);
// run http client
httpClientThread_ = std::thread([this](){
try {
@@ -108,18 +109,18 @@ DhtProxyClient::DhtProxyClient(
logger_->e("[proxy:client] run error: %s", ex.what());
}
});
if (!proxyUrl_.empty())
if (!serverHostService_.first.empty())
startProxy();
}
void
DhtProxyClient::startProxy()
{
if (proxyUrl_.empty())
if (serverHostService_.first.empty())
return;
if (logger_)
logger_->d("[proxy:client] start proxy with %s", proxyUrl_.c_str());
logger_->d("[proxy:client] start proxy with %s", serverHostService_.first.c_str());
nextProxyConfirmationTimer_ = std::make_shared<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now());
nextProxyConfirmationTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyConfirm, this, std::placeholders::_1));
@@ -139,7 +140,7 @@ DhtProxyClient::handleProxyConfirm(const asio::error_code &ec)
logger_->e("[proxy:client] confirm error: %s", ec.message().c_str());
return;
}
if (proxyUrl_.empty())
if (serverHostService_.first.empty())
return;
getConnectivityStatus();
}
@@ -157,6 +158,8 @@ DhtProxyClient::stop()
cancelAllListeners();
if (infoState_)
infoState_->cancel = true;
if (statusTimer_)
statusTimer_->cancel();
if (httpClientThread_.joinable())
httpClientThread_.join();
}
@@ -260,6 +263,9 @@ DhtProxyClient::periodic(const uint8_t*, size_t, SockAddr)
void
DhtProxyClient::setHeaderFields(http::Request& request){
request.set_header_field(restinio::http_field_t::host,
serverHostService_.first + ":" + serverHostService_.second);
request.set_header_field(restinio::http_field_t::user_agent, "RESTinio client");
request.set_header_field(restinio::http_field_t::accept, "*/*");
request.set_header_field(restinio::http_field_t::content_type, "application/json");
}
@@ -270,18 +276,27 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
if (logger_)
logger_->d("[proxy:client] [get] [search %s]", key.to_c_str());
auto request = buildRequest("/" + key.toString());
auto request = std::make_shared<http::Request>(httpContext_, resolver_, logger_);
auto reqid = request->id();
try {
request->set_connection_type(restinio::http_connection_header_t::keep_alive);
request->set_target("/" + key.toString());
request->set_method(restinio::http_method_get());
setHeaderFields(*request);
auto opstate = std::make_shared<OperationState>();
Value::Filter filter = w.empty() ? f : f.chain(w.getFilter());
request->add_on_status_callback([this, key, opstate](unsigned int status_code){
if (status_code != 200){
if (logger_)
logger_->e("[proxy:client] [get %s] status error: %i", key.to_c_str(), status_code);
opstate->ok.store(false);
}
});
request->add_on_body_callback([this, key, opstate, filter, cb](const char* at, size_t length){
try {
Json::CharReaderBuilder rbuilder;
auto body = std::string(at, length);
// one value per body line
std::string data_line;
@@ -290,7 +305,7 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
std::string err;
Json::Value json;
auto* char_data = static_cast<const char*>(&data_line[0]);
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(char_data, char_data + data_line.size(), &json, &err)){
opstate->ok.store(false);
return;
@@ -321,8 +336,6 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
if (logger_)
logger_->e("[proxy:client] [get %s] failed with code=%i", key.to_c_str(), response.status_code);
opstate->ok.store(false);
if (response.status_code == 0)
opFailed();
}
if (donecb){
{
@@ -337,6 +350,10 @@ DhtProxyClient::get(const InfoHash& key, GetCallback cb, DoneCallback donecb, Va
requests_.erase(reqid);
}
});
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->send();
requests_[reqid] = request;
}
@@ -360,43 +377,35 @@ DhtProxyClient::put(const InfoHash& key, Sp<Value> val, DoneCallback cb, time_po
if (val->id == Value::INVALID_ID) {
crypto::random_device rdev;
val->id = std::uniform_int_distribution<Value::Id>{1}(rdev);
std::uniform_int_distribution<Value::Id> rand_id {};
val->id = rand_id(rdev);
}
std::shared_ptr<std::atomic_bool> ok;
if (permanent) {
std::lock_guard<std::mutex> lock(searchLock_);
auto id = val->id;
auto& search = searches_[key];
auto refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now() +
proxy::OP_TIMEOUT - proxy::OP_MARGIN);
refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
auto ok = std::make_shared<std::atomic_bool>();
ok->store(true);
refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this,
std::placeholders::_1, key, id, ok));
search.puts.erase(id);
ok = std::make_shared<std::atomic_bool>(true);
search.puts.emplace(std::piecewise_construct,
std::forward_as_tuple(id),
std::forward_as_tuple(val, std::move(refreshPutTimer), ok));
}
doPut(key, val, [this, cb, ok](bool result){
if (ok)
*ok = result;
if (cb) {
std::lock_guard<std::mutex> lock(lockCallbacks_);
callbacks_.emplace_back([cb, result](){
cb(result, {});
});
}
loopSignal_();
}, created, permanent);
doPut(key, val, std::move(cb), created, permanent);
}
void
DhtProxyClient::handleRefreshPut(const asio::error_code &ec, InfoHash key, Value::Id id)
DhtProxyClient::handleRefreshPut(const asio::error_code &ec, const InfoHash& key, const Value::Id id,
std::shared_ptr<std::atomic_bool> ok)
{
if (ec == asio::error::operation_aborted)
return;
else if (ec){
if (logger_)
logger_->e("[proxy:client] [put] [refresh %s] %s", key.toString().c_str(), ec.message().c_str());
logger_->e("[proxy:client] [listener] [refresh %s] %s", key.toString().c_str(), ec.message().c_str());
return;
}
if (logger_)
@@ -406,41 +415,26 @@ DhtProxyClient::handleRefreshPut(const asio::error_code &ec, InfoHash key, Value
if (search != searches_.end()) {
auto p = search->second.puts.find(id);
if (p != search->second.puts.end()){
doPut(key, p->second.value, [ok = p->second.ok](bool result){
doPut(key, p->second.value, [ok](bool result, const std::vector<std::shared_ptr<dht::Node>>&){
*ok = result;
}, time_point::max(), true);
p->second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() + proxy::OP_TIMEOUT - proxy::OP_MARGIN);
p->second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id));
p->second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() +
proxy::OP_TIMEOUT - proxy::OP_MARGIN);
p->second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, id, ok));
}
}
}
std::shared_ptr<http::Request>
DhtProxyClient::buildRequest(const std::string& target)
{
auto resolver = resolver_;
if (not resolver)
resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
auto request = target.empty()
? std::make_shared<http::Request>(httpContext_, resolver)
: std::make_shared<http::Request>(httpContext_, resolver, target);
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->set_header_field(restinio::http_field_t::user_agent, "RESTinio client");
return request;
}
void
DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb, time_point /*created*/, bool permanent)
DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallback cb, time_point /*created*/, bool permanent)
{
if (logger_)
logger_->d("[proxy:client] [put] [search %s] executing for %s", key.to_c_str(), val->toString().c_str());
auto request = buildRequest("/" + key.toString());
auto request = std::make_shared<http::Request>(httpContext_, resolver_, logger_);
auto reqid = request->id();
try {
request->set_target("/" + key.toString());
request->set_method(restinio::http_method_post());
setHeaderFields(*request);
@@ -458,22 +452,45 @@ DhtProxyClient::doPut(const InfoHash& key, Sp<Value> val, DoneCallbackSimple cb,
#endif
}
}
request->set_body(Json::writeString(jsonBuilder_, json));
request->add_on_state_change_callback([this, reqid, cb]
Json::StreamWriterBuilder wbuilder;
wbuilder["commentStyle"] = "None";
wbuilder["indentation"] = "";
auto body = Json::writeString(wbuilder, json);
request->set_body(body);
auto ok = std::make_shared<std::atomic_bool>();
ok->store(true);
request->add_on_status_callback([this, key, ok](unsigned int status_code){
if (status_code != 200){
if (logger_)
logger_->e("[proxy:client] [put %s] status error: %i", key.to_c_str(), status_code);
ok->store(false);
}
return 0;
});
request->add_on_state_change_callback([this, reqid, ok, cb, key]
(http::Request::State state, const http::Response& response){
if (state == http::Request::State::DONE){
bool ok = response.status_code == 200;
if (not ok) {
if (response.status_code != 200)
if (logger_)
logger_->e("[proxy:client] [status] failed with code=%i", response.status_code);
if (response.status_code == 0)
opFailed();
if (cb){
{
std::lock_guard<std::mutex> lock(lockCallbacks_);
callbacks_.emplace_back([cb, ok](){
cb(ok->load(), {});
});
}
loopSignal_();
}
if (cb)
cb(ok);
requests_.erase(reqid);
}
});
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->send();
requests_[reqid] = request;
}
@@ -539,58 +556,127 @@ DhtProxyClient::getProxyInfos()
{
if (logger_)
logger_->d("[proxy:client] [info] requesting proxy server node information");
std::lock_guard<std::mutex> l(statusLock_);
auto infoState = std::make_shared<InfoState>();
if (infoState_)
infoState_->cancel = true;
infoState_ = infoState;
{
std::lock_guard<std::mutex> l(lockCurrentProxyInfos_);
if (infoState_)
infoState_->cancel = true;
infoState_ = infoState;
if (statusIpv4_ == NodeStatus::Disconnected)
statusIpv4_ = NodeStatus::Connecting;
if (statusIpv6_ == NodeStatus::Disconnected)
statusIpv6_ = NodeStatus::Connecting;
}
if (logger_)
logger_->d("[proxy:client] [status] sending request");
auto resolver = std::make_shared<http::Resolver>(httpContext_, proxyUrl_, logger_);
queryProxyInfo(infoState, AF_INET, resolver);
queryProxyInfo(infoState, AF_INET6, resolver);
resolver_ = resolver;
// Try to contact the proxy and set the status to connected when done.
// will change the connectivity status
if (!statusTimer_)
statusTimer_ = std::make_shared<asio::steady_timer>(httpContext_);
statusTimer_->expires_at(std::chrono::steady_clock::now());
statusTimer_->async_wait(std::bind(&DhtProxyClient::handleProxyStatus, this,
std::placeholders::_1, infoState));
}
void
DhtProxyClient::queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t family, std::shared_ptr<http::Resolver> resolver)
DhtProxyClient::handleProxyStatus(const asio::error_code& ec, std::shared_ptr<InfoState> infoState)
{
if (ec == asio::error::operation_aborted)
return;
else if (ec){
if (logger_)
logger_->e("[proxy:client] [status] handling error: %s", ec.message().c_str());
return;
}
if (logger_)
logger_->d("[proxy:client] [status] sending request");
resolver_->add_callback([this, infoState](const asio::error_code& ec,
std::vector<asio::ip::tcp::endpoint> endpoints)
{
if (ec){
if (logger_)
logger_->e("[proxy:client] [status] resolve error: %s", ec.message().c_str());
return;
}
std::vector<asio::ip::tcp::endpoint> endpointsIpv4;
std::vector<asio::ip::tcp::endpoint> endpointsIpv6;
for (auto& endpoint: endpoints){
try {
if (endpoint.address().is_v6())
endpointsIpv6.push_back(endpoint);
if (endpoint.address().is_v4())
endpointsIpv4.push_back(endpoint);
} catch (const std::exception&){};
}
// avoiding nested add_callback call
if (!endpointsIpv4.empty())
queryProxyInfo(infoState, AF_INET, std::move(endpointsIpv4));
if (!endpointsIpv6.empty())
queryProxyInfo(infoState, AF_INET6, std::move(endpointsIpv6));
});
}
void
DhtProxyClient::queryProxyInfo(std::shared_ptr<InfoState> infoState, const sa_family_t family,
std::vector<asio::ip::tcp::endpoint>&& endpoints)
{
if (logger_)
logger_->d("[proxy:client] [status] query ipv%i info", family == AF_INET ? 4 : 6);
auto request = std::make_shared<http::Request>(httpContext_, resolver, family);
auto request = std::make_shared<http::Request>(httpContext_, std::move(endpoints),
resolver_->get_url().protocol == "https" ? /*ssl*/ true : false, logger_);
auto reqid = request->id();
try {
request->set_method(restinio::http_method_get());
request->set_connection_type(restinio::http_connection_header_t::keep_alive);
request->set_target("/");
request->set_method(restinio::http_method_get());
setHeaderFields(*request);
auto ok = std::make_shared<std::atomic_bool>();
ok->store(true);
request->add_on_status_callback([this, ok, family](unsigned int status_code){
if (status_code != 200){
if (logger_)
logger_->e("[proxy:client] [status] ipv%i status code error: %i", family, status_code);
ok->store(false);
}
});
request->add_on_body_callback([this, ok, infoState, family](const char* at, size_t length){
try{
std::string err;
Json::Value proxyInfos;
Json::CharReaderBuilder rbuilder;
auto body = std::string(at, length);
auto* char_data = static_cast<const char*>(&body[0]);
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(char_data, char_data + body.size(), &proxyInfos, &err)){
ok->store(false);
return;
}
if (not infoState->cancel)
onProxyInfos(proxyInfos, family);
}
catch (const std::exception& e) {
if (logger_)
logger_->e("[proxy:client] [status] body error: %s", e.what());
ok->store(false);
}
});
request->add_on_state_change_callback([this, reqid, family, infoState]
(http::Request::State state, const http::Response& response){
if (state == http::Request::State::DONE) {
if (infoState->cancel.load())
return;
if (response.status_code != 200) {
if (state == http::Request::State::DONE){
if (response.status_code != 200)
if (logger_)
logger_->e("[proxy:client] [status] ipv%i failed with code=%i",
family == AF_INET ? 4 : 6, response.status_code);
if (infoState->cancel.load()){
// pass along the failures
if ((family == AF_INET and infoState->ipv4 == 0) or (family == AF_INET6 and infoState->ipv6 == 0))
onProxyInfos(Json::Value{}, family);
} else {
std::string err;
Json::Value proxyInfos;
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
if (!reader->parse(response.body.data(), response.body.data() + response.body.size(), &proxyInfos, &err)){
onProxyInfos(Json::Value{}, family);
return;
}
if (not infoState->cancel)
onProxyInfos(proxyInfos, family);
if (family == AF_INET and infoState->ipv4 == 0)
onProxyInfos(Json::Value{}, AF_INET);
if (family == AF_INET6 and infoState->ipv6 == 0)
onProxyInfos(Json::Value{}, AF_INET6);
}
requests_.erase(reqid);
}
@@ -599,8 +685,12 @@ DhtProxyClient::queryProxyInfo(std::shared_ptr<InfoState> infoState, sa_family_t
if (infoState->cancel.load())
return;
requests_[reqid] = request;
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->send();
requests_[reqid] = request;
}
catch (const std::exception &e){
if (logger_)
@@ -843,29 +933,43 @@ DhtProxyClient::handleExpireListener(const asio::error_code &ec, const InfoHash&
if (not deviceKey_.empty()) {
// UNSUBSCRIBE
auto request = buildRequest("/" + key.toString());
auto request = std::make_shared<http::Request>(httpContext_, resolver_, logger_);
auto reqid = request->id();
try {
request->set_target("/" + key.toString());
request->set_method(restinio::http_method_unsubscribe());
setHeaderFields(*request);
Json::Value body;
body["key"] = deviceKey_;
body["client_id"] = pushClientId_;
request->set_body(Json::writeString(jsonBuilder_, body));
Json::StreamWriterBuilder wbuilder;
wbuilder["commentStyle"] = "None";
wbuilder["indentation"] = "";
auto content = Json::writeString(wbuilder, body) + "\n";
std::replace(content.begin(), content.end(), '\n', ' ');
request->set_body(content);
request->add_on_status_callback([this, key](unsigned int status_code){
if (status_code != 200)
if (logger_)
logger_->e("[proxy:client] [unsubscribe %s] failed with code=%i",
key.to_c_str(), status_code);
});
request->add_on_state_change_callback([this, reqid, key]
(http::Request::State state, const http::Response& response){
if (state == http::Request::State::DONE){
if (response.status_code != 200) {
if (response.status_code != 200)
if (logger_)
logger_->e("[proxy:client] [unsubscribe %s] failed with code=%i",
key.to_c_str(), response.status_code);
if (response.status_code == 0)
opFailed();
}
requests_.erase(reqid);
}
});
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->send();
requests_[reqid] = request;
}
@@ -899,9 +1003,7 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
const Sp<OperationState>& opstate,
Listener& listener, ListenMethod method)
{
if (logger_)
logger_->e("[proxy:client] [listen] sendListen: %d", (int)method);
auto request = buildRequest();
auto request = std::make_shared<http::Request>(httpContext_, resolver_, logger_);
listener.request = request;
auto reqid = request->id();
try {
@@ -909,16 +1011,25 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
setHeaderFields(*request);
if (method == ListenMethod::LISTEN)
request->set_connection_type(restinio::http_connection_header_t::keep_alive);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
std::string body;
#ifdef OPENDHT_PUSH_NOTIFICATIONS
if (method != ListenMethod::LISTEN)
body = fillBody(method == ListenMethod::RESUBSCRIBE);
request->set_body(body);
#endif
request->set_body(body);
request->add_on_status_callback([this, reqid, opstate](unsigned int status_code){
if (status_code != 200){
if (logger_)
logger_->e("[proxy:client] [listen] send request #%i status error: %i", reqid, status_code);
opstate->ok.store(false);
}
});
request->add_on_body_callback([this, reqid, opstate, cb](const char* at, size_t length){
try {
Json::CharReaderBuilder rbuilder;
auto body = std::string(at, length);
std::vector<dht::Sp<dht::Value>> values;
// one value per body line
std::string data_line;
std::stringstream body_stream(body);
@@ -926,7 +1037,7 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
std::string err;
Json::Value json;
auto* char_data = static_cast<const char*>(&data_line[0]);
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(char_data, char_data + data_line.size(), &json, &err)){
opstate->ok.store(false);
return;
@@ -954,20 +1065,20 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
opstate->ok.store(false);
}
});
request->add_on_state_change_callback([this, opstate, reqid]
request->add_on_state_change_callback([this, reqid]
(http::Request::State state, const http::Response& response){
if (state == http::Request::State::DONE){
if (response.status_code != 200) {
if (response.status_code != 200)
if (logger_)
logger_->e("[proxy:client] [listen] send request #%i failed with code=%i",
reqid, response.status_code);
opstate->ok.store(false);
if (response.status_code == 0)
opFailed();
}
requests_.erase(reqid);
}
});
if (serverCertificate_)
request->set_certificate_authority(serverCertificate_);
if (clientIdentity_.first and clientIdentity_.second)
request->set_identity(clientIdentity_);
request->send();
requests_[reqid] = request;
}
@@ -981,8 +1092,6 @@ DhtProxyClient::sendListen(const restinio::http_request_header_t header,
void
DhtProxyClient::opFailed()
{
if (isDestroying_)
return;
if (logger_)
logger_->e("[proxy:client] proxy request failed");
{
@@ -1016,15 +1125,17 @@ DhtProxyClient::restartListeners()
auto key = search.first;
for (auto& put : search.second.puts) {
if (!*put.second.ok) {
doPut(key, put.second.value, [ok = put.second.ok](bool result){
auto ok = put.second.ok;
doPut(key, put.second.value, [ok](bool result, const std::vector<std::shared_ptr<dht::Node>>&){
*ok = result;
}, time_point::max(), true);
if (!put.second.refreshPutTimer){
put.second.refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_);
}
put.second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() + proxy::OP_TIMEOUT - proxy::OP_MARGIN);
put.second.refreshPutTimer->expires_at(std::chrono::steady_clock::now() +
proxy::OP_TIMEOUT - proxy::OP_MARGIN);
put.second.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this,
std::placeholders::_1, key, put.first));
std::placeholders::_1, key, put.first, put.second.ok));
}
}
}
@@ -1096,7 +1207,7 @@ DhtProxyClient::pushNotificationReceived(const std::map<std::string, std::string
put.refreshPutTimer = std::make_unique<asio::steady_timer>(httpContext_, std::chrono::steady_clock::now());
else
put.refreshPutTimer->expires_at(std::chrono::steady_clock::now());
put.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, vid));
put.refreshPutTimer->async_wait(std::bind(&DhtProxyClient::handleRefreshPut, this, std::placeholders::_1, key, vid, put.ok));
} else {
// Refresh listen
for (auto& list : search.listeners)
@@ -1222,7 +1333,10 @@ DhtProxyClient::fillBody(bool resubscribe)
// This is the first listen, we want to retrieve previous values.
body["refresh"] = true;
}
auto content = Json::writeString(jsonBuilder_, body) + "\n";
Json::StreamWriterBuilder wbuilder;
wbuilder["commentStyle"] = "None";
wbuilder["indentation"] = "";
auto content = Json::writeString(wbuilder, body) + "\n";
std::replace(content.begin(), content.end(), '\n', ' ');
return content;
}
+63 -26
View File
@@ -110,7 +110,10 @@ class DhtProxyServer::ConnectionListener
{
public:
ConnectionListener() {};
ConnectionListener(std::function<void(restinio::connection_id_t)> onClosed) : onClosed_(std::move(onClosed)) {};
ConnectionListener(std::shared_ptr<dht::DhtRunner> dht,
std::shared_ptr<std::map<restinio::connection_id_t, http::ListenerSession>> listeners,
std::shared_ptr<std::mutex> lock, std::shared_ptr<dht::Logger> logger):
dht_(dht), lock_(lock), listeners_(listeners), logger_(logger) {};
~ConnectionListener() {};
/**
@@ -120,28 +123,54 @@ public:
void state_changed(const restinio::connection_state::notice_t& notice) noexcept;
private:
std::function<void(restinio::connection_id_t)> onClosed_;
std::string to_str( restinio::connection_state::cause_t cause ) noexcept;
std::shared_ptr<dht::DhtRunner> dht_;
std::shared_ptr<std::mutex> lock_;
std::shared_ptr<std::map<restinio::connection_id_t, http::ListenerSession>> listeners_;
std::shared_ptr<dht::Logger> logger_;
};
void
DhtProxyServer::ConnectionListener::state_changed(const restinio::connection_state::notice_t& notice) noexcept
{
if (restinio::holds_alternative<restinio::connection_state::closed_t>(notice.cause())) {
onClosed_(notice.connection_id());
std::lock_guard<std::mutex> lock(*lock_);
auto id = notice.connection_id();
auto cause = to_str(notice.cause());
if (listeners_->find(id) != listeners_->end()){
if (notice.cause() == restinio::connection_state::cause_t::closed){
if (logger_)
logger_->d("[proxy:server] [connection:%li] cancelling listener", id);
dht_->cancelListen(listeners_->at(id).hash,
std::move(listeners_->at(id).token));
listeners_->erase(id);
if (logger_)
logger_->d("[proxy:server] %li listeners are connected", listeners_->size());
}
}
}
void
DhtProxyServer::onConnectionClosed(restinio::connection_id_t id)
std::string
DhtProxyServer::ConnectionListener::to_str(restinio::connection_state::cause_t cause) noexcept
{
std::lock_guard<std::mutex> lock(lockListener_);
auto it = listeners_.find(id);
if (it != listeners_.end()) {
dht_->cancelListen(it->second.hash, std::move(it->second.token));
listeners_.erase(it);
if (logger_)
logger_->d("[proxy:server] [connection:%li] listener cancelled, %li still connected", id, listeners_.size());
std::string result;
switch(cause)
{
case restinio::connection_state::cause_t::accepted:
result = "accepted";
break;
case restinio::connection_state::cause_t::closed:
result = "closed";
break;
case restinio::connection_state::cause_t::upgraded_to_websocket:
result = "upgraded";
break;
default:
result = "unknown";
}
return result;
}
struct DhtProxyServer::RestRouterTraitsTls : public restinio::default_tls_traits_t
@@ -170,8 +199,9 @@ DhtProxyServer::DhtProxyServer(
std::shared_ptr<DhtRunner> dht, in_port_t port, const std::string& pushServer,
std::shared_ptr<dht::Logger> logger
)
: dht_(dht), logger_(logger),
connListener_(std::make_shared<ConnectionListener>(std::bind(&DhtProxyServer::onConnectionClosed, this, std::placeholders::_1))),
: dht_(dht), logger_(logger), lockListener_(std::make_shared<std::mutex>()),
listeners_(std::make_shared<std::map<restinio::connection_id_t, http::ListenerSession>>()),
connListener_(std::make_shared<ConnectionListener>(dht, listeners_, lockListener_, logger)),
pushServer_(pushServer)
{
if (not dht_)
@@ -335,7 +365,7 @@ DhtProxyServer::updateStats() const
stats_.pushListenersCount = pushListeners_.size();
#endif
stats_.putCount = puts_.size();
stats_.listenCount = listeners_.size();
stats_.listenCount = listeners_->size();
stats_.nodeInfo = nodeInfo_;
}
@@ -555,9 +585,9 @@ DhtProxyServer::listen(restinio::request_handle_t request,
this->initHttpResponse(request->create_response<ResponseByParts>()));
response->flush();
try {
std::lock_guard<std::mutex> lock(lockListener_);
std::lock_guard<std::mutex> lock(*lockListener_);
// save the listener to handle a disconnect
auto &session = listeners_[request->connection_id()];
auto &session = (*listeners_)[request->connection_id()];
session.hash = infoHash;
session.response = response;
session.token = dht_->listen(infoHash, [this, response]
@@ -603,8 +633,9 @@ DhtProxyServer::subscribe(restinio::request_handle_t request,
try {
std::string err;
Json::Value root;
Json::CharReaderBuilder rbuilder;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(char_data, char_data + request->body().size(), &root, &err)){
auto response = this->initHttpResponse(
request->create_response(restinio::status_bad_request()));
@@ -744,8 +775,9 @@ DhtProxyServer::unsubscribe(restinio::request_handle_t request,
try {
std::string err;
Json::Value root;
Json::CharReaderBuilder rbuilder;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (!reader->parse(char_data, char_data + request->body().size(), &root, &err)){
auto response = this->initHttpResponse(
@@ -799,7 +831,7 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st
if (logger_)
logger_->d("[proxy:server] [listen:push %s] cancelled for %s",
key.toString().c_str(), clientId.c_str());
std::lock_guard<std::mutex> lock(lockListener_);
std::lock_guard<std::mutex> lock(*lockListener_);
auto pushListener = pushListeners_.find(pushToken);
if (pushListener == pushListeners_.end())
@@ -921,12 +953,14 @@ DhtProxyServer::put(restinio::request_handle_t request,
infoHash = dht::InfoHash::get(params["hash"].to_string());
if (!dht_){
auto response = initHttpResponse(request->create_response(restinio::status_service_unavailable()));
auto response = this->initHttpResponse(
request->create_response(restinio::status_service_unavailable()));
response.set_body(RESP_MSG_SERVICE_UNAVAILABLE);
return response.done();
}
else if (request->body().empty()){
auto response = initHttpResponse(request->create_response(restinio::status_bad_request()));
auto response = this->initHttpResponse(
request->create_response(restinio::status_bad_request()));
response.set_body(RESP_MSG_MISSING_PARAMS);
return response.done();
}
@@ -934,8 +968,9 @@ DhtProxyServer::put(restinio::request_handle_t request,
try {
std::string err;
Json::Value root;
Json::CharReaderBuilder rbuilder;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (reader->parse(char_data, char_data + request->body().size(), &root, &err)){
auto value = std::make_shared<dht::Value>(root);
@@ -1047,8 +1082,9 @@ RequestStatus DhtProxyServer::putSigned(restinio::request_handle_t request,
try {
std::string err;
Json::Value root;
Json::CharReaderBuilder rbuilder;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (reader->parse(char_data, char_data + request->body().size(), &root, &err)){
@@ -1109,8 +1145,9 @@ DhtProxyServer::putEncrypted(restinio::request_handle_t request,
try {
std::string err;
Json::Value root;
Json::CharReaderBuilder rbuilder;
auto* char_data = reinterpret_cast<const char*>(request->body().data());
auto reader = std::unique_ptr<Json::CharReader>(jsonReaderBuilder_.newCharReader());
auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
if (reader->parse(char_data, char_data + request->body().size(), &root, &err)){
InfoHash to(root["to"].asString());
+21 -33
View File
@@ -708,7 +708,7 @@ DhtRunner::put(const std::string& key, Value&& value, DoneCallbackSimple cb, tim
}
void
DhtRunner::cancelPut(const InfoHash& h, Value::Id id)
DhtRunner::cancelPut(const InfoHash& h , const Value::Id& id)
{
{
std::lock_guard<std::mutex> lck(storage_mtx);
@@ -720,63 +720,51 @@ DhtRunner::cancelPut(const InfoHash& h, Value::Id id)
}
void
DhtRunner::cancelPut(const InfoHash& h, const std::shared_ptr<Value>& value)
DhtRunner::putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb)
{
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops.emplace([=](SecureDht& dht) {
dht.cancelPut(h, value->id);
dht.putSigned(hash, value, cb);
});
}
cv.notify_all();
}
void
DhtRunner::putSigned(InfoHash hash, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
DhtRunner::putSigned(InfoHash hash, Value&& value, DoneCallback 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), std::move(cb));
}
void
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb)
{
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops.emplace([=](SecureDht& dht) {
dht.putSigned(hash, value, cb, permanent);
dht.putEncrypted(hash, to, value, cb);
});
}
cv.notify_all();
}
void
DhtRunner::putSigned(InfoHash hash, Value&& value, DoneCallback cb, bool permanent)
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb)
{
putSigned(hash, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb));
}
void
DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple cb, bool permanent)
DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb)
{
putSigned(InfoHash::get(key), std::forward<Value>(value), std::move(cb), permanent);
}
void
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
{
{
std::lock_guard<std::mutex> lck(storage_mtx);
pending_ops.emplace([=](SecureDht& dht) {
dht.putEncrypted(hash, to, value, cb, permanent);
});
}
cv.notify_all();
}
void
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, Value&& value, DoneCallback cb, bool permanent)
{
putEncrypted(hash, to, std::make_shared<Value>(std::move(value)), std::move(cb), permanent);
}
void
DhtRunner::putEncrypted(const std::string& key, InfoHash to, Value&& value, DoneCallback cb, bool permanent)
{
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb), permanent);
putEncrypted(InfoHash::get(key), to, std::forward<Value>(value), std::move(cb));
}
void
+84 -100
View File
@@ -142,9 +142,9 @@ Connection::close()
if (!is_open())
return;
asio::error_code ec;
if (ssl_socket_)
if (ssl_ctx_)
ssl_socket_->close(ec);
else if (socket_)
else
socket_->close(ec);
if (ec and logger_)
logger_->e("[http:client] [connection:%i] error closing: %s", id_, ec.message().c_str());
@@ -159,12 +159,10 @@ Connection::id()
bool
Connection::is_open()
{
if (ssl_socket_)
if (ssl_ctx_)
return ssl_socket_->is_open();
else if (socket_)
return socket_->is_open();
else
return false;
return socket_->is_open();
}
bool
@@ -176,7 +174,7 @@ Connection::is_ssl()
void
Connection::set_ssl_verification(const asio::ip::tcp::endpoint& endpoint, const asio::ssl::verify_mode verify_mode)
{
if (ssl_socket_ and verify_mode != asio::ssl::verify_none){
if (ssl_ctx_ and verify_mode != asio::ssl::verify_none){
auto hostname = endpoint.address().to_string();
ssl_socket_->asio_ssl_stream().set_verify_mode(verify_mode);
ssl_socket_->asio_ssl_stream().set_verify_callback(
@@ -232,18 +230,16 @@ Connection::read_until(const char delim)
void
Connection::async_connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, ConnectHandlerCb cb)
{
if (ssl_socket_)
if (ssl_ctx_)
asio::async_connect(ssl_socket_->lowest_layer(), std::move(endpoints), cb);
else if (socket_)
else
asio::async_connect(*socket_, std::move(endpoints), cb);
else if (cb)
cb(asio::error::operation_aborted, {});
}
void
Connection::async_handshake(HandlerCb cb)
{
if (ssl_socket_)
if (ssl_ctx_)
ssl_socket_->async_handshake(asio::ssl::stream<asio::ip::tcp::socket>::client,
[this, cb](const asio::error_code& ec)
{
@@ -262,8 +258,6 @@ Connection::async_handshake(HandlerCb cb)
});
else if (socket_)
cb(asio::error::no_protocol_option);
else if (cb)
cb(asio::error::operation_aborted);
}
void
@@ -271,12 +265,10 @@ Connection::async_write(BytesHandlerCb cb)
{
if (!is_open())
return;
if (ssl_socket_)
if (ssl_ctx_)
asio::async_write(*ssl_socket_, write_buf_, cb);
else if (socket_)
else
asio::async_write(*socket_, write_buf_, cb);
else if (cb)
cb(asio::error::operation_aborted, 0);
}
void
@@ -284,12 +276,10 @@ Connection::async_read_until(const char* delim, BytesHandlerCb cb)
{
if (!is_open())
return;
if (ssl_socket_)
if (ssl_ctx_)
asio::async_read_until(*ssl_socket_, read_buf_, delim, cb);
else if (socket_)
else
asio::async_read_until(*socket_, read_buf_, delim, cb);
else if (cb)
cb(asio::error::operation_aborted, 0);
}
void
@@ -299,10 +289,8 @@ Connection::async_read(const size_t bytes, BytesHandlerCb cb)
return;
if (ssl_socket_)
asio::async_read(*ssl_socket_, read_buf_, asio::transfer_exactly(bytes), cb);
else if (socket_)
else
asio::async_read(*socket_, read_buf_, asio::transfer_exactly(bytes), cb);
else if (cb)
cb(asio::error::operation_aborted, 0);
}
void
@@ -311,8 +299,6 @@ Connection::timeout(const std::chrono::seconds timeout, HandlerCb cb)
if (!is_open()){
if (logger_)
logger_->e("[http:client] [connection:%i] closed, can't timeout", id_);
if (cb)
cb(asio::error::operation_aborted);
return;
}
if (!timeout_timer_)
@@ -373,35 +359,14 @@ Resolver::~Resolver()
*destroyed_ = true;
}
inline
std::vector<asio::ip::tcp::endpoint>
filter(const std::vector<asio::ip::tcp::endpoint>& epts, sa_family_t family)
{
if (family == AF_UNSPEC)
return epts;
std::vector<asio::ip::tcp::endpoint> ret;
for (const auto& ep : epts) {
if (family == AF_INET && ep.address().is_v4())
ret.emplace_back(ep);
else if (family == AF_INET6 && ep.address().is_v6())
ret.emplace_back(ep);
}
return ret;
}
void
Resolver::add_callback(ResolverCb cb, sa_family_t family)
Resolver::add_callback(ResolverCb cb)
{
std::lock_guard<std::mutex> lock(mutex_);
if (!completed_)
cbs_.emplace(family == AF_UNSPEC ? std::move(cb) : [cb, family](const asio::error_code& ec, const std::vector<asio::ip::tcp::endpoint>& endpoints){
if (ec)
cb(ec, endpoints);
else
cb(ec, filter(endpoints, family));
});
cbs_.emplace(std::move(cb));
else
cb(ec_, family == AF_UNSPEC ? endpoints_ : filter(endpoints_, family));
cb(ec_, endpoints_);
}
void
@@ -418,6 +383,14 @@ Resolver::resolve(const std::string& host, const std::string& service)
if (ec)
logger_->e("[http:client] [resolver] error for %s:%s: %s",
host.c_str(), service.c_str(), ec.message().c_str());
else {
for (auto it = endpoints.begin(); it != endpoints.end(); ++it){
asio::ip::tcp::endpoint endpoint = *it;
logger_->d("[http:client] [resolver] %s:%s endpoint (ipv%i): %s",
host.c_str(), service.c_str(), endpoint.address().is_v6() ? 6 : 4,
endpoint.address().to_string().c_str());
}
}
}
decltype(cbs_) cbs;
{
@@ -443,7 +416,7 @@ unsigned int Request::ids_ = 1;
Request::Request(asio::io_context& ctx, const std::string& url, const Json::Value& json, OnJsonCb jsoncb,
std::shared_ptr<dht::Logger> logger)
: id_(Request::ids_++), ctx_(ctx),
: cbs_(std::make_unique<Callbacks>()), id_(Request::ids_++), ctx_(ctx),
resolver_(std::make_shared<Resolver>(ctx, url, logger)), logger_(logger)
{
init_default_headers();
@@ -466,7 +439,7 @@ Request::Request(asio::io_context& ctx, const std::string& url, const Json::Valu
}
Request::Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger)
: id_(Request::ids_++), ctx_(ctx),
: cbs_(std::make_unique<Callbacks>()), id_(Request::ids_++), ctx_(ctx),
resolver_(std::make_shared<Resolver>(ctx, url, logger)), logger_(logger)
{
init_default_headers();
@@ -474,33 +447,26 @@ Request::Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<
Request::Request(asio::io_context& ctx, const std::string& host, const std::string& service,
const bool ssl, std::shared_ptr<dht::Logger> logger)
: id_(Request::ids_++), ctx_(ctx),
: cbs_(std::make_unique<Callbacks>()), id_(Request::ids_++), ctx_(ctx),
resolver_(std::make_shared<Resolver>(ctx, host, service, ssl, logger)), logger_(logger)
{
init_default_headers();
}
Request::Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family)
: id_(Request::ids_++), ctx_(ctx), family_(family), resolver_(resolver), logger_(resolver->getLogger())
Request::Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, std::shared_ptr<dht::Logger> logger)
: cbs_(std::make_unique<Callbacks>()), id_(Request::ids_++), ctx_(ctx), resolver_(resolver), logger_(logger)
{
init_default_headers();
}
Request::Request(asio::io_context& ctx, std::vector<asio::ip::tcp::endpoint>&& endpoints, const bool ssl,
std::shared_ptr<dht::Logger> logger)
: id_(Request::ids_++), ctx_(ctx),
: cbs_(std::make_unique<Callbacks>()), id_(Request::ids_++), ctx_(ctx),
resolver_(std::make_shared<Resolver>(ctx, std::move(endpoints), ssl, logger)), logger_(logger)
{
init_default_headers();
}
Request::Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, const std::string& target, sa_family_t family)
: id_(Request::ids_++), ctx_(ctx), family_(family), resolver_(resolver), logger_(resolver->getLogger())
{
set_header_field(restinio::http_field_t::host, get_url().host + ":" + get_url().service);
set_target(target);
}
Request::~Request()
{
}
@@ -508,16 +474,14 @@ Request::~Request()
void
Request::init_default_headers()
{
const auto& url = resolver_->get_url();
set_header_field(restinio::http_field_t::host, url.host + ":" + url.service);
set_target(url.target);
set_header_field(restinio::http_field_t::host, get_url().host + ":" + get_url().service);
set_target(resolver_->get_url().target);
}
void
Request::cancel()
{
if (auto c = conn_)
c->close();
conn_->close();
}
unsigned int
@@ -649,29 +613,29 @@ void
Request::add_on_status_callback(OnStatusCb cb)
{
std::lock_guard<std::mutex> lock(cbs_mutex_);
cbs_.on_status = std::move(cb);
cbs_->on_status = std::move(cb);
}
void
Request::add_on_body_callback(OnDataCb cb)
{
std::lock_guard<std::mutex> lock(cbs_mutex_);
cbs_.on_body = std::move(cb);
cbs_->on_body = std::move(cb);
}
void
Request::add_on_state_change_callback(OnStateChangeCb cb)
{
std::lock_guard<std::mutex> lock(cbs_mutex_);
cbs_.on_state_change = std::move(cb);
cbs_->on_state_change = std::move(cb);
}
void
Request::notify_state_change(const State state)
{
state_ = state;
if (cbs_.on_state_change)
cbs_.on_state_change(state, response_);
if (cbs_ and cbs_->on_state_change)
cbs_->on_state_change(state, response_);
}
void
@@ -680,7 +644,7 @@ Request::init_parser()
if (!parser_)
parser_ = std::make_unique<http_parser>();
http_parser_init(parser_.get(), HTTP_RESPONSE);
parser_->data = static_cast<void*>(&cbs_);
parser_->data = static_cast<void*>(cbs_.get());
if (!parser_s_)
parser_s_ = std::make_unique<http_parser_settings>();
@@ -688,30 +652,36 @@ Request::init_parser()
{
// user registered callbacks wrappers to store its data in the response
std::lock_guard<std::mutex> lock(cbs_mutex_);
cbs_.on_status = [this, statusCb = std::move(cbs_.on_status)](unsigned int status_code){
auto on_status_cb = cbs_->on_status;
cbs_->on_status = [this, on_status_cb](unsigned int status_code){
response_.status_code = status_code;
if (statusCb)
statusCb(status_code);
if (on_status_cb)
on_status_cb(status_code);
};
auto header_field = std::make_shared<std::string>();
cbs_.on_header_field = [header_field, headerFieldCb = std::move(cbs_.on_header_field)](const char* at, size_t length) {
*header_field = std::string(at, length);
if (headerFieldCb)
headerFieldCb(at, length);
auto header_field = std::make_shared<std::string>("");
auto on_header_field_cb = cbs_->on_header_field;
cbs_->on_header_field = [header_field, on_header_field_cb](const char* at, size_t length) {
header_field->erase();
auto field = std::string(at, length);
header_field->append(field);
if (on_header_field_cb)
on_header_field_cb(at, length);
};
cbs_.on_header_value = [this, header_field, headerValueCb = std::move(cbs_.on_header_value)](const char* at, size_t length) {
auto on_header_value_cb = cbs_->on_header_value;
cbs_->on_header_value = [this, header_field, on_header_value_cb](const char* at, size_t length) {
response_.headers[*header_field] = std::string(at, length);
if (headerValueCb)
headerValueCb(at, length);
if (on_header_value_cb)
on_header_value_cb(at, length);
};
cbs_.on_headers_complete = [this](){
cbs_->on_headers_complete = [this](){
notify_state_change(State::HEADER_RECEIVED);
};
cbs_.on_body = [bodyCb = std::move(cbs_.on_body)](const char* at, size_t length) {
if (bodyCb)
bodyCb(at, length);
auto on_body_cb = cbs_->on_body;
cbs_->on_body = [on_body_cb](const char* at, size_t length) {
if (on_body_cb)
on_body_cb(at, length);
};
cbs_.on_message_complete = [this](){
cbs_->on_message_complete = [this](){
if (logger_)
logger_->d("[http:client] [request:%i] response: message complete", id_);
message_complete_.store(true);
@@ -719,27 +689,39 @@ Request::init_parser()
}
// http_parser raw c callback (note: no context can be passed into them)
parser_s_->on_status = [](http_parser* parser, const char* /*at*/, size_t /*length*/) -> int {
static_cast<Callbacks*>(parser->data)->on_status(parser->status_code);
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_status)
cbs->on_status(parser->status_code);
return 0;
};
parser_s_->on_header_field = [](http_parser* parser, const char* at, size_t length) -> int {
static_cast<Callbacks*>(parser->data)->on_header_field(at, length);
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_header_field)
cbs->on_header_field(at, length);
return 0;
};
parser_s_->on_header_value = [](http_parser* parser, const char* at, size_t length) -> int {
static_cast<Callbacks*>(parser->data)->on_header_value(at, length);
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_header_value)
cbs->on_header_value(at, length);
return 0;
};
parser_s_->on_body = [](http_parser* parser, const char* at, size_t length) -> int {
static_cast<Callbacks*>(parser->data)->on_body(at, length);
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_body)
cbs->on_body(at, length);
return 0;
};
parser_s_->on_headers_complete = [](http_parser* parser) -> int {
static_cast<Callbacks*>(parser->data)->on_headers_complete();
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_headers_complete)
cbs->on_headers_complete();
return 0;
};
parser_s_->on_message_complete = [](http_parser* parser) -> int {
static_cast<Callbacks*>(parser->data)->on_message_complete();
auto cbs = static_cast<Callbacks*>(parser->data);
if (cbs->on_message_complete)
cbs->on_message_complete();
return 0;
};
}
@@ -756,7 +738,7 @@ Request::connect(std::vector<asio::ip::tcp::endpoint>&& endpoints, HandlerCb cb)
}
if (logger_){
std::string eps = "";
for (const auto& endpoint : endpoints)
for (auto& endpoint : endpoints)
eps.append(endpoint.address().to_string() + " ");
logger_->d("[http:client] [request:%i] connect begin: %s", id_, eps.c_str());
}
@@ -831,7 +813,7 @@ Request::send()
}
else
post();
}, family_);
});
}
void
@@ -860,12 +842,14 @@ Request::post()
void
Request::terminate(const asio::error_code& ec)
{
if (finishing_.exchange(true))
if (finishing_.load())
return;
if (ec != asio::error::eof and ec != asio::error::operation_aborted and logger_)
logger_->e("[http:client] [request:%i] end with error: %s", id_, ec.message().c_str());
finishing_.store(true);
// set response outcome, ignore end of file and abort
if (!ec or ec == asio::error::eof or ec == asio::error::operation_aborted)
response_.status_code = 200;
-13
View File
@@ -56,19 +56,6 @@ CryptoTester::testSignatureEncryption() {
std::vector<uint8_t> decrypted = key.decrypt(encrypted);
CPPUNIT_ASSERT(data2 == decrypted);
}
// encrypt data (invalid)
{
std::vector<uint8_t> encrypted = public_key.encrypt(data1);
encrypted[1]++;
CPPUNIT_ASSERT_THROW(key.decrypt(encrypted), dht::crypto::DecryptError);
}
{
std::vector<uint8_t> encrypted = public_key.encrypt(data2);
encrypted[2]++;
CPPUNIT_ASSERT_THROW(key.decrypt(encrypted), dht::crypto::DecryptError);
}
}
void
+9 -10
View File
@@ -55,13 +55,13 @@ DhtProxyTester::setUp() {
clientConfig.dht_config.node_config.maintain_storage = false;
clientConfig.threaded = true;
clientConfig.push_node_id = "dhtnode";
clientConfig.proxy_server = "https://127.0.0.1:8080";
dht::DhtRunner::Context clientContext {};
clientContext.logger = logger;
nodeClient = std::make_shared<dht::DhtRunner>();
nodeClient->run(0, clientConfig, std::move(clientContext));
nodeClient->bootstrap(nodePeer.getBound());
nodeClient->setProxyServer("https://127.0.0.1:8080");
nodeClient->enableProxy(true); // creates DhtProxyClient
}
void
@@ -159,13 +159,12 @@ DhtProxyTester::testResubscribeGetValues() {
std::unique_lock<std::mutex> lk(cv_m);
auto key = dht::InfoHash::get("GLaDOs");
// If a peer sent a value, the listen operation from the client
// If a peer send a value, the listen operation from the client
// should retrieve this value
dht::Value firstVal {"Hey! It's been a long time. How have you been?"};
auto firstVal_data = firstVal.data;
nodePeer.put(key, std::move(firstVal), [&](bool ok) {
nodePeer.put(key, std::move(firstVal), [&](bool) {
std::lock_guard<std::mutex> lk(cv_m);
CPPUNIT_ASSERT(ok);
done = true;
cv.notify_all();
});
@@ -181,11 +180,11 @@ DhtProxyTester::testResubscribeGetValues() {
// Reboot node (to avoid cache)
nodeClient->join();
clientConfig.push_token = "atlas";
dht::DhtRunner::Context clientContext {};
clientContext.logger = logger;
nodeClient->run(0, clientConfig, std::move(clientContext));
nodeClient->bootstrap(nodePeer.getBound());
nodeClient->setProxyServer("https://127.0.0.1:8080");
nodeClient->enableProxy(true);
nodeClient->setPushNotificationToken("atlas");
// For the second subscribe, the proxy will return the value in the body
auto values = std::vector<dht::Blob>();
+1
View File
@@ -72,6 +72,7 @@ class DhtProxyTester : public CppUnit::TestFixture {
std::shared_ptr<dht::DhtRunner> nodeProxy;
std::unique_ptr<dht::DhtProxyServer> serverProxy;
dht::DhtRunner::Context clientContext {};
dht::DhtRunner::Config clientConfig {};
std::shared_ptr<dht::Logger> logger {};
};
+3 -21
View File
@@ -15,7 +15,6 @@ bool dht_value_callback(const dht_value* value, bool expired, void* user_data)
{
dht_data_view data = dht_value_get_data(value);
printf("Value callback %s: %.*s.\n", expired ? "expired" : "new", (int)data.size, data.data);
return true;
}
bool dht_get_callback(const dht_value* value, void* user_data)
@@ -23,16 +22,15 @@ bool dht_get_callback(const dht_value* value, void* user_data)
dht_runner* runner = (dht_runner*)user_data;
dht_data_view data = dht_value_get_data(value);
printf("Get callback: %.*s.\n", (int)data.size, data.data);
return true;
}
void dht_done_callback(bool ok, void* user_data)
bool dht_done_callback(bool ok, void* user_data)
{
dht_runner* runner = (dht_runner*)user_data;
printf("Done callback. %s\n", ok ? "Success !" : "Failure :-(");
}
void op_context_free(void* user_data)
bool op_context_free(void* user_data)
{
struct op_context* ctx = (struct op_context*)user_data;
printf("op_context_free %d.\n", ctx->d);
@@ -62,22 +60,6 @@ char* print_addr(const struct sockaddr* addr) {
int main()
{
dht_identity id = dht_identity_generate("testNode", NULL);
dht_infohash cert_id = dht_certificate_get_id(id.certificate);
printf("Cert ID: %s\n", dht_infohash_print(&cert_id));
dht_publickey* pk = dht_certificate_get_publickey(id.certificate);
dht_infohash pk_id = dht_publickey_get_id(pk);
printf("PK ID: %s\n", dht_infohash_print(&pk_id));
dht_publickey_delete(pk);
pk = dht_privatekey_get_publickey(id.privatekey);
pk_id = dht_publickey_get_id(pk);
printf("Key ID: %s\n", dht_infohash_print(&pk_id));
dht_publickey_delete(pk);
dht_identity_delete(&id);
dht_runner* runner = dht_runner_new();
dht_runner_run(runner, 4040);
@@ -89,7 +71,7 @@ int main()
// Put data
const char* data_str = "yo, this is some data";
dht_value* val = dht_value_new(data_str, strlen(data_str));
dht_runner_put(runner, &h, val, dht_done_callback, runner, false);
dht_runner_put(runner, &h, val, dht_done_callback, runner);
dht_value_unref(val);
// Get data