mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-09 12:57:03 +00:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68485faf58 | ||
|
|
28de983166 | ||
|
|
4b28278cb1 | ||
|
|
653a4309bd | ||
|
|
48b763f11b | ||
|
|
cbfa12a921 | ||
|
|
3e0d4cd703 | ||
|
|
4bff6d392a | ||
|
|
712b7218a9 | ||
|
|
5a8e252e32 | ||
|
|
b5be4549dc | ||
|
|
bf8fb6f321 | ||
|
|
08cf212c53 | ||
|
|
fc2a597bb2 | ||
|
|
7212b7a28b | ||
|
|
5c610895fe | ||
|
|
a567ca1dc1 | ||
|
|
97b20705a1 | ||
|
|
431da16ba6 | ||
|
|
09818d779e | ||
|
|
934e36ba13 | ||
|
|
2e47b9bab5 | ||
|
|
f938d486d5 | ||
|
|
76b4da089e | ||
|
|
2a72277194 | ||
|
|
e8d96d3b42 | ||
|
|
c92d236c1b | ||
|
|
b680407e9a | ||
|
|
6caf4b0d0b | ||
|
|
7f65fdc7f9 | ||
|
|
b00dfdf572 | ||
|
|
2b1d2fc3f6 | ||
|
|
a0566cf695 | ||
|
|
a3f2b055a1 |
No files matched your search
+3
-3
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required (VERSION 3.1)
|
||||
project (opendht)
|
||||
set (opendht_VERSION_MAJOR 1)
|
||||
set (opendht_VERSION_MINOR 10.1)
|
||||
set (opendht_VERSION_MAJOR 2)
|
||||
set (opendht_VERSION_MINOR 0.0)
|
||||
set (opendht_VERSION ${opendht_VERSION_MAJOR}.${opendht_VERSION_MINOR})
|
||||
set (PACKAGE_VERSION ${opendht_VERSION})
|
||||
set (VERSION "${opendht_VERSION}")
|
||||
@@ -24,7 +24,7 @@ option (OPENDHT_PROXY_OPENSSL "Build DHT proxy with OpenSSL" ON)
|
||||
option (OPENDHT_PROXY_HTTP_PARSER_FORK "Build DHT proxy with custom http_parser to support old API" OFF)
|
||||
option (OPENDHT_INDEX "Build DHT indexation feature" OFF)
|
||||
option (OPENDHT_TESTS "Add unit tests executable" OFF)
|
||||
option (OPENDHT_C "Build C bindings" ON)
|
||||
option (OPENDHT_C "Build C bindings" OFF)
|
||||
|
||||
find_package(Doxygen)
|
||||
option (OPENDHT_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND})
|
||||
|
||||
@@ -99,7 +99,7 @@ for r in results:
|
||||
- (optional) restinio used for the REST API.
|
||||
- (optional) jsoncpp 1.7.4-3+, used for the REST API.
|
||||
- Build tested with GCC 5.2+ (GNU/Linux, Windows with MinGW), Clang/LLVM (GNU/Linux, Android, macOS, iOS).
|
||||
- Build tested with Microsoft Visual Studio 2015
|
||||
- Build tested with Microsoft Visual Studio 2015, 2017, 2019
|
||||
|
||||
## Contact
|
||||
|
||||
|
||||
+124
-25
@@ -2,14 +2,15 @@
|
||||
#include "opendht.h"
|
||||
|
||||
using ValueSp = std::shared_ptr<dht::Value>;
|
||||
using PrivkeySp = std::shared_ptr<dht::crypto::PrivateKey>;
|
||||
using CertSp = std::shared_ptr<dht::crypto::Certificate>;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// dht::InfoHash
|
||||
const char* dht_infohash_print(const dht_infohash* h)
|
||||
{
|
||||
const char* dht_infohash_print(const dht_infohash* h) {
|
||||
return reinterpret_cast<const dht::InfoHash*>(h)->to_c_str();
|
||||
}
|
||||
|
||||
@@ -17,33 +18,28 @@ void dht_infohash_zero(dht_infohash* h) {
|
||||
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash{};
|
||||
}
|
||||
|
||||
void dht_infohash_random(dht_infohash* h)
|
||||
{
|
||||
void dht_infohash_random(dht_infohash* h) {
|
||||
*reinterpret_cast<dht::InfoHash*>(h) = dht::InfoHash::getRandom();
|
||||
}
|
||||
|
||||
void dht_infohash_get(dht_infohash* h, const uint8_t* dat, size_t dat_size)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
bool dht_infohash_is_zero(const dht_infohash* h) {
|
||||
return static_cast<bool>(*reinterpret_cast<const dht::InfoHash*>(h));
|
||||
return !static_cast<bool>(*reinterpret_cast<const dht::InfoHash*>(h));
|
||||
}
|
||||
|
||||
const char* dht_pkid_print(const dht_pkid* h)
|
||||
{
|
||||
const char* dht_pkid_print(const dht_pkid* h) {
|
||||
return reinterpret_cast<const dht::PkId*>(h)->to_c_str();
|
||||
}
|
||||
|
||||
// dht::Blob
|
||||
void dht_blob_delete(dht_blob* data)
|
||||
{
|
||||
void dht_blob_delete(dht_blob* data) {
|
||||
delete reinterpret_cast<dht::Blob*>(data);
|
||||
}
|
||||
|
||||
dht_data_view dht_blob_get_data(const dht_blob* data)
|
||||
{
|
||||
dht_data_view dht_blob_get_data(const dht_blob* data) {
|
||||
dht_data_view view;
|
||||
view.data = reinterpret_cast<const dht::Blob*>(data)->data();
|
||||
view.size = reinterpret_cast<const dht::Blob*>(data)->size();
|
||||
@@ -51,8 +47,7 @@ dht_data_view dht_blob_get_data(const dht_blob* data)
|
||||
}
|
||||
|
||||
// dht::Value
|
||||
dht_data_view dht_value_get_data(const dht_value* data)
|
||||
{
|
||||
dht_data_view dht_value_get_data(const dht_value* data) {
|
||||
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
|
||||
dht_data_view view;
|
||||
view.data = vsp->data.data();
|
||||
@@ -60,6 +55,11 @@ dht_data_view dht_value_get_data(const dht_value* data)
|
||||
return view;
|
||||
}
|
||||
|
||||
dht_value_id dht_value_get_id(const dht_value* data) {
|
||||
const ValueSp& vsp(*reinterpret_cast<const ValueSp*>(data));
|
||||
return vsp->id;
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
@@ -95,14 +95,16 @@ int dht_publickey_pack(dht_publickey* pk, char* out, size_t* outlen) {
|
||||
}
|
||||
|
||||
dht_infohash dht_publickey_get_id(const dht_publickey* pk) {
|
||||
auto pkey = reinterpret_cast<const dht::crypto::PublicKey*>(pk);
|
||||
dht_infohash h;
|
||||
*reinterpret_cast<dht::InfoHash*>(&h) = reinterpret_cast<const dht::crypto::PublicKey*>(pk)->getId();
|
||||
*reinterpret_cast<dht::InfoHash*>(&h) = pkey->getId();
|
||||
return h;
|
||||
}
|
||||
|
||||
dht_pkid dht_publickey_get_long_id(const dht_publickey* pk) {
|
||||
auto pkey = reinterpret_cast<const dht::crypto::PublicKey*>(pk);
|
||||
dht_pkid h;
|
||||
*reinterpret_cast<dht::PkId*>(&h) = reinterpret_cast<const dht::crypto::PublicKey*>(pk)->getLongId();
|
||||
*reinterpret_cast<dht::PkId*>(&h) = pkey->getLongId();
|
||||
return h;
|
||||
}
|
||||
|
||||
@@ -119,23 +121,30 @@ dht_blob* dht_publickey_encrypt(const dht_publickey* pk, const char* data, size_
|
||||
dht_privatekey* dht_privatekey_generate(unsigned key_length_bits) {
|
||||
if (key_length_bits == 0)
|
||||
key_length_bits = 4096;
|
||||
return reinterpret_cast<dht_privatekey*>(new dht::crypto::PrivateKey(dht::crypto::PrivateKey::generate(key_length_bits)));
|
||||
return reinterpret_cast<dht_privatekey*>(new PrivkeySp(std::make_shared<dht::crypto::PrivateKey>(dht::crypto::PrivateKey::generate(key_length_bits))));
|
||||
}
|
||||
|
||||
dht_privatekey* dht_privatekey_import(const uint8_t* dat, size_t dat_size, const char* password) {
|
||||
try {
|
||||
return reinterpret_cast<dht_privatekey*>(new dht::crypto::PrivateKey(dat, dat_size, password));
|
||||
return reinterpret_cast<dht_privatekey*>(new PrivkeySp(std::make_shared<dht::crypto::PrivateKey>(dat, dat_size, password)));
|
||||
} catch (const dht::crypto::CryptoException& e) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* key) {
|
||||
return reinterpret_cast<dht_publickey*>(new dht::crypto::PublicKey(reinterpret_cast<const dht::crypto::PrivateKey*>(key)->getPublicKey()));
|
||||
dht_publickey* dht_privatekey_get_publickey(const dht_privatekey* k) {
|
||||
const auto& key = *reinterpret_cast<const PrivkeySp*>(k);
|
||||
return reinterpret_cast<dht_publickey*>(new dht::crypto::PublicKey(key->getPublicKey()));
|
||||
}
|
||||
|
||||
void dht_privatekey_delete(dht_privatekey* pk) {
|
||||
delete reinterpret_cast<dht::crypto::PrivateKey*>(pk);
|
||||
delete reinterpret_cast<PrivkeySp*>(pk);
|
||||
}
|
||||
|
||||
// config
|
||||
void dht_runner_config_default(dht_runner_config* config) {
|
||||
bzero(config, sizeof(dht_runner_config));
|
||||
config->threaded = true;
|
||||
}
|
||||
|
||||
// dht::DhtRunner
|
||||
@@ -152,6 +161,31 @@ void dht_runner_run(dht_runner* r, in_port_t port) {
|
||||
runner->run(port, {}, true);
|
||||
}
|
||||
|
||||
void dht_runner_run_config(dht_runner* r, in_port_t port, const dht_runner_config* conf) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
dht::DhtRunner::Config config;
|
||||
config.dht_config.node_config.is_bootstrap = conf->dht_config.node_config.is_bootstrap;
|
||||
config.dht_config.node_config.maintain_storage = conf->dht_config.node_config.maintain_storage;
|
||||
config.dht_config.node_config.node_id = *reinterpret_cast<const dht::InfoHash*>(&conf->dht_config.node_config.node_id);
|
||||
config.dht_config.node_config.network = conf->dht_config.node_config.network;
|
||||
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.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);
|
||||
|
||||
config.threaded = conf->threaded;
|
||||
config.proxy_server = conf->proxy_server ? std::string(conf->proxy_server) : std::string{};
|
||||
config.push_node_id = conf->push_node_id ? std::string(conf->push_node_id) : std::string{};
|
||||
config.push_token = conf->push_token ? std::string(conf->push_token) : std::string{};
|
||||
config.peer_discovery = conf->peer_discovery;
|
||||
config.peer_publish = conf->peer_publish;
|
||||
runner->run(port, config);
|
||||
}
|
||||
|
||||
void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
runner->bootstrap(dht::SockAddr(addr, addr_len));
|
||||
@@ -159,7 +193,10 @@ void dht_runner_ping(dht_runner* r, struct sockaddr* addr, socklen_t addr_len) {
|
||||
|
||||
void dht_runner_bootstrap(dht_runner* r, const char* host, const char* service) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
runner->bootstrap(host, service);
|
||||
if (service)
|
||||
runner->bootstrap(host, service);
|
||||
else
|
||||
runner->bootstrap(host);
|
||||
}
|
||||
|
||||
void dht_runner_get(dht_runner* r, const dht_infohash* h, dht_get_cb cb, dht_done_cb done_cb, void* cb_user_data) {
|
||||
@@ -173,11 +210,25 @@ void dht_runner_get(dht_runner* r, const dht_infohash* h, dht_get_cb cb, dht_don
|
||||
});
|
||||
}
|
||||
|
||||
dht_op_token* dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_cb cb, void* cb_user_data) {
|
||||
struct ScopeGuardCb {
|
||||
ScopeGuardCb(dht_shutdown_cb cb, void* data)
|
||||
: onDestroy(cb), userData(data) {}
|
||||
|
||||
~ScopeGuardCb() {
|
||||
if (onDestroy)
|
||||
onDestroy((void*)userData);
|
||||
}
|
||||
private:
|
||||
const dht_shutdown_cb onDestroy;
|
||||
void const* userData;
|
||||
};
|
||||
|
||||
dht_op_token* dht_runner_listen(dht_runner* r, const dht_infohash* h, dht_value_cb cb, dht_shutdown_cb done_cb, void* cb_user_data) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
|
||||
auto fret = new std::future<size_t>;
|
||||
*fret = runner->listen(*hash, [cb,cb_user_data](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) {
|
||||
auto guard = done_cb ? std::make_shared<ScopeGuardCb>(done_cb, cb_user_data) : std::shared_ptr<ScopeGuardCb>{};
|
||||
*fret = runner->listen(*hash, [cb,cb_user_data, guard](const std::vector<std::shared_ptr<dht::Value>>& values, bool expired) {
|
||||
for (const auto& value : values) {
|
||||
if (not cb(reinterpret_cast<const dht_value*>(&value), expired, cb_user_data))
|
||||
return false;
|
||||
@@ -208,6 +259,22 @@ void dht_runner_put(dht_runner* r, const dht_infohash* h, const dht_value* v, dh
|
||||
});
|
||||
}
|
||||
|
||||
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->put(*hash, *value, [done_cb, cb_user_data](bool ok){
|
||||
if (done_cb)
|
||||
done_cb(ok, cb_user_data);
|
||||
}, dht::time_point::max(), true);
|
||||
}
|
||||
|
||||
void dht_runner_cancel_put(dht_runner* r, const dht_infohash* h, dht_value_id value_id) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
auto hash = reinterpret_cast<const dht::InfoHash*>(h);
|
||||
runner->cancelPut(*hash, value_id);
|
||||
}
|
||||
|
||||
void dht_runner_shutdown(dht_runner* r, dht_shutdown_cb done_cb, void* cb_user_data) {
|
||||
auto runner = reinterpret_cast<dht::DhtRunner*>(r);
|
||||
runner->shutdown([done_cb, cb_user_data](){
|
||||
@@ -216,6 +283,38 @@ void dht_runner_shutdown(dht_runner* r, dht_shutdown_cb done_cb, void* cb_user_d
|
||||
});
|
||||
}
|
||||
|
||||
dht_infohash dht_runner_get_node_id(const dht_runner* r) {
|
||||
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
|
||||
dht_infohash ret;
|
||||
*reinterpret_cast<dht::InfoHash*>(&ret) = runner->getNodeId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
dht_infohash dht_runner_get_id(const dht_runner* r) {
|
||||
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
|
||||
dht_infohash ret;
|
||||
*reinterpret_cast<dht::InfoHash*>(&ret) = runner->getId();
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct sockaddr** dht_runner_get_public_address(const dht_runner* r) {
|
||||
auto runner = reinterpret_cast<const dht::DhtRunner*>(r);
|
||||
auto addrs = const_cast<dht::DhtRunner*>(runner)->getPublicAddress();
|
||||
if (addrs.empty())
|
||||
return nullptr;
|
||||
auto ret = (struct sockaddr**)malloc(sizeof(struct sockaddr*) * (addrs.size() + 1));
|
||||
for (size_t i=0; i<addrs.size(); i++) {
|
||||
if (auto len = addrs[i].getLength()) {
|
||||
ret[i] = (struct sockaddr*)malloc(len);
|
||||
memcpy((struct sockaddr*)ret[i], addrs[i].get(), len);
|
||||
} else {
|
||||
ret[i] = nullptr;
|
||||
}
|
||||
}
|
||||
ret[addrs.size()] = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+46
-1
@@ -21,7 +21,9 @@ 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*);
|
||||
@@ -70,6 +72,12 @@ OPENDHT_C_PUBLIC void dht_privatekey_delete(dht_privatekey*);
|
||||
struct OPENDHT_C_PUBLIC dht_certificate;
|
||||
typedef struct dht_certificate dht_certificate;
|
||||
|
||||
struct OPENDHT_PUBLIC dht_identity {
|
||||
dht_privatekey* privkey;
|
||||
dht_certificate* certificate;
|
||||
};
|
||||
typedef struct dht_identity dht_identity;
|
||||
|
||||
// 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);
|
||||
@@ -80,19 +88,56 @@ struct OPENDHT_C_PUBLIC dht_op_token;
|
||||
typedef struct dht_op_token dht_op_token;
|
||||
OPENDHT_C_PUBLIC void dht_op_token_delete(dht_op_token* token);
|
||||
|
||||
// config
|
||||
struct OPENDHT_PUBLIC dht_node_config {
|
||||
dht_infohash node_id;
|
||||
uint32_t network;
|
||||
bool is_bootstrap;
|
||||
bool maintain_storage;
|
||||
const char* persist_path;
|
||||
};
|
||||
typedef struct dht_node_config dht_node_config;
|
||||
|
||||
struct OPENDHT_PUBLIC dht_secure_config
|
||||
{
|
||||
dht_node_config node_config;
|
||||
dht_identity id;
|
||||
};
|
||||
typedef struct dht_secure_config dht_secure_config;
|
||||
|
||||
struct OPENDHT_PUBLIC dht_runner_config {
|
||||
dht_secure_config dht_config;
|
||||
bool threaded;
|
||||
const char* proxy_server;
|
||||
const char* push_node_id;
|
||||
const char* push_token;
|
||||
bool peer_discovery;
|
||||
bool peer_publish;
|
||||
dht_certificate* server_ca;
|
||||
dht_identity client_identity;
|
||||
};
|
||||
typedef struct dht_runner_config dht_runner_config;
|
||||
OPENDHT_C_PUBLIC void dht_runner_config_default(dht_runner_config* config);
|
||||
|
||||
// dht::DhtRunner
|
||||
struct OPENDHT_C_PUBLIC dht_runner;
|
||||
typedef struct dht_runner dht_runner;
|
||||
OPENDHT_C_PUBLIC dht_runner* dht_runner_new();
|
||||
OPENDHT_C_PUBLIC void dht_runner_delete(dht_runner* runner);
|
||||
OPENDHT_C_PUBLIC void dht_runner_run(dht_runner* runner, in_port_t port);
|
||||
OPENDHT_C_PUBLIC void dht_runner_run_config(dht_runner* runner, in_port_t port, const dht_runner_config* config);
|
||||
OPENDHT_C_PUBLIC void dht_runner_ping(dht_runner* runner, struct sockaddr* addr, socklen_t addr_len);
|
||||
OPENDHT_C_PUBLIC void dht_runner_bootstrap(dht_runner* runner, const char* host, const char* service);
|
||||
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, 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);
|
||||
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);
|
||||
OPENDHT_C_PUBLIC dht_infohash dht_runner_get_id(const dht_runner* runner);
|
||||
OPENDHT_C_PUBLIC struct sockaddr** dht_runner_get_public_address(const dht_runner* runner);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
dnl define macros
|
||||
m4_define([opendht_major_version], 1)
|
||||
m4_define([opendht_minor_version], 10)
|
||||
m4_define([opendht_patch_version], 1)
|
||||
m4_define([opendht_major_version], 2)
|
||||
m4_define([opendht_minor_version], 0)
|
||||
m4_define([opendht_patch_version], 0)
|
||||
m4_define([opendht_version],
|
||||
[opendht_major_version.opendht_minor_version.opendht_patch_version])
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
*.lock
|
||||
target
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "opendht"
|
||||
version = "0.1.0"
|
||||
authors = ["Sébastien Blin <sebastien.blin@savoirfairelinux.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
libc="0.2.0"
|
||||
os_socketaddr="0.1.0"
|
||||
@@ -0,0 +1,21 @@
|
||||
# Rust bindings for opendht
|
||||
|
||||
## Build
|
||||
|
||||
Install rust on your system (https://rustup.rs/ is the recommanded way). Once done:
|
||||
|
||||
```
|
||||
cargo build
|
||||
```
|
||||
|
||||
## Run tests
|
||||
|
||||
```
|
||||
cargo test
|
||||
```
|
||||
|
||||
## Run dht node
|
||||
|
||||
```
|
||||
cargo run --example dhtnode
|
||||
```
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern crate opendht;
|
||||
use std::{ thread, time };
|
||||
|
||||
use opendht::{ InfoHash, DhtRunner, DhtRunnerConfig, Value };
|
||||
|
||||
fn main() {
|
||||
println!("{}", InfoHash::random());
|
||||
println!("{}", InfoHash::new());
|
||||
println!("{}", InfoHash::new().is_zero());
|
||||
println!("{}", InfoHash::get("alice"));
|
||||
println!("{}", InfoHash::get("alice").is_zero());
|
||||
|
||||
let mut dht = DhtRunner::new();
|
||||
let config = DhtRunnerConfig::new();
|
||||
dht.run_config(1412, config);
|
||||
dht.bootstrap("bootstrap.jami.net", 4222);
|
||||
|
||||
let /* mut */ data = 42;
|
||||
let mut get_cb = |v: Box<Value>| {
|
||||
//data += 1;
|
||||
println!("GET: VALUE CB - data: {} - v: {}", data, v);
|
||||
};
|
||||
let mut done_cb = |ok: bool| {
|
||||
println!("GET: DONE CB - data: {} - ok: {}", data, ok);
|
||||
};
|
||||
|
||||
dht.get(&InfoHash::get("alice"), &mut get_cb, &mut done_cb);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
println!("Start listening /foo");
|
||||
let mut value_cb = |v, expired| {
|
||||
println!("LISTEN: DONE CB - data: {} - v: {} - expired: {}", data, v, expired);
|
||||
};
|
||||
let token = dht.listen(&InfoHash::get("foo"), &mut value_cb);
|
||||
let one_min = time::Duration::from_secs(10);
|
||||
thread::sleep(one_min);
|
||||
dht.cancel_listen(&InfoHash::get("foo"), token);
|
||||
println!("Public ips: {:#?}", dht.public_addresses());
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::ffi::*;
|
||||
|
||||
pub use crate::ffi::Blob;
|
||||
|
||||
impl Blob {
|
||||
pub fn data(&self) -> DataView {
|
||||
unsafe {
|
||||
dht_blob_get_data(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Blob {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_blob_delete(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use crate::ffi::*;
|
||||
use std::ffi::CString;
|
||||
|
||||
impl PublicKey {
|
||||
pub fn new() -> Box<PublicKey> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_publickey_new())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unpack(&mut self, data: Vec<u8>) -> i32 {
|
||||
unsafe {
|
||||
dht_publickey_unpack(&mut *self, data.as_ptr(), data.len())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pack(&mut self, data: &str) -> i32 {
|
||||
let data = CString::new(data).unwrap();
|
||||
unsafe {
|
||||
dht_publickey_pack(&mut *self,
|
||||
data.as_ptr(),
|
||||
data.as_bytes().len())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> InfoHash {
|
||||
unsafe {
|
||||
dht_publickey_get_id(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn long_id(&self) -> PkId {
|
||||
unsafe {
|
||||
dht_publickey_get_long_id(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_signature(&self, data: &str, signature: &str) -> bool {
|
||||
let data = CString::new(data).unwrap();
|
||||
let signature = CString::new(signature).unwrap();
|
||||
unsafe {
|
||||
dht_publickey_check_signature(self,
|
||||
data.as_ptr(), data.as_bytes().len(),
|
||||
signature.as_ptr(), signature.as_bytes().len())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encrypt(&self, data: &str) -> Box<Blob> {
|
||||
let data = CString::new(data).unwrap();
|
||||
unsafe {
|
||||
Box::from_raw(dht_publickey_encrypt(self,
|
||||
data.as_ptr(), data.as_bytes().len()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PublicKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_publickey_delete(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrivateKey {
|
||||
pub fn new(key_length_bits: u32) -> Box<PrivateKey> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_privatekey_generate(key_length_bits))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn import(data: &str, password: &str) -> Box<PrivateKey> {
|
||||
let password = CString::new(password).unwrap();
|
||||
unsafe {
|
||||
Box::from_raw(dht_privatekey_import(data.as_ptr(),
|
||||
data.as_bytes().len(), password.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> Box<PublicKey> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_privatekey_get_publickey(self))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Drop for PrivateKey {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_privatekey_delete(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use libc::c_void;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
pub use crate::ffi::*;
|
||||
use std::net::SocketAddr;
|
||||
use os_socketaddr::OsSocketAddr;
|
||||
|
||||
impl DhtRunnerConfig {
|
||||
|
||||
pub fn new() -> Box<DhtRunnerConfig> {
|
||||
let mut config: Box<DhtRunnerConfig> = Box::new(DhtRunnerConfig {
|
||||
dht_config: DhtSecureConfig {
|
||||
node_config: DhtNodeConfig {
|
||||
node_id: InfoHash::new(),
|
||||
network: 0,
|
||||
is_bootstrap: false,
|
||||
maintain_storage: false,
|
||||
persist_path: ptr::null(),
|
||||
},
|
||||
id: DhtIdentity {
|
||||
privkey: ptr::null_mut(),
|
||||
certificate: ptr::null_mut(),
|
||||
},
|
||||
},
|
||||
threaded: false,
|
||||
proxy_server: ptr::null(),
|
||||
push_node_id: ptr::null(),
|
||||
push_token: ptr::null(),
|
||||
peer_discovery: false,
|
||||
peer_publish: false,
|
||||
server_ca: ptr::null_mut(),
|
||||
client_identity: DhtIdentity {
|
||||
privkey: ptr::null_mut(),
|
||||
certificate: ptr::null_mut(),
|
||||
},
|
||||
});
|
||||
unsafe {
|
||||
dht_runner_config_default(&mut *config);
|
||||
}
|
||||
config
|
||||
}
|
||||
|
||||
pub fn set_proxy_server(&mut self, proxy_server: &str) {
|
||||
self.proxy_server = CString::new(proxy_server).unwrap().as_ptr();
|
||||
}
|
||||
|
||||
pub fn set_push_node_id(&mut self, push_node_id: &str) {
|
||||
self.push_node_id = CString::new(push_node_id).unwrap().as_ptr();
|
||||
}
|
||||
|
||||
pub fn set_push_token(&mut self, push_token: &str) {
|
||||
self.push_token = CString::new(push_token).unwrap().as_ptr();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl DhtNodeConfig
|
||||
{
|
||||
pub fn set_persist_path(&mut self, persist_path: &str) {
|
||||
self.persist_path = CString::new(persist_path).unwrap().as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
struct GetHandler<'a>
|
||||
{
|
||||
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>) {
|
||||
(self.get_cb)(v)
|
||||
}
|
||||
|
||||
fn done_cb(&mut self, ok: bool) {
|
||||
(self.done_cb)(ok)
|
||||
}
|
||||
}
|
||||
|
||||
extern fn get_handler_cb(v: *mut Value, ptr: *mut c_void) {
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
let handler = ptr as *mut GetHandler;
|
||||
(*handler).get_cb((*v).boxed())
|
||||
}
|
||||
}
|
||||
|
||||
extern fn done_handler_cb(ok: bool, ptr: *mut c_void) {
|
||||
unsafe {
|
||||
let handler = Box::from_raw(ptr as *mut GetHandler);
|
||||
(*handler.done_cb)(ok)
|
||||
}
|
||||
}
|
||||
|
||||
struct PutHandler<'a>
|
||||
{
|
||||
done_cb: &'a mut(dyn FnMut(bool))
|
||||
}
|
||||
|
||||
impl<'a> PutHandler<'a>
|
||||
{
|
||||
fn done_cb(&mut self, ok: bool) {
|
||||
(self.done_cb)(ok)
|
||||
}
|
||||
}
|
||||
|
||||
extern fn put_handler_done(ok: bool, ptr: *mut c_void) {
|
||||
unsafe {
|
||||
let handler = Box::from_raw(ptr as *mut PutHandler);
|
||||
(*handler.done_cb)(ok)
|
||||
}
|
||||
}
|
||||
|
||||
struct ListenHandler<'a>
|
||||
{
|
||||
cb: &'a mut(dyn FnMut(Box<Value>, bool))
|
||||
}
|
||||
|
||||
impl<'a> ListenHandler<'a>
|
||||
{
|
||||
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) {
|
||||
unsafe {
|
||||
let handler = ptr as *mut ListenHandler;
|
||||
(*handler).cb((*v).boxed(), expired)
|
||||
}
|
||||
}
|
||||
|
||||
extern fn listen_handler_done(ptr: *mut c_void) {
|
||||
unsafe {
|
||||
Box::from_raw(ptr as *mut ListenHandler);
|
||||
}
|
||||
}
|
||||
|
||||
impl DhtRunner {
|
||||
pub fn new() -> Box<DhtRunner> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_runner_new())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self, port: u16) {
|
||||
unsafe {
|
||||
dht_runner_run(&mut *self, port)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_config(&mut self, port: u16, config: Box<DhtRunnerConfig>) {
|
||||
unsafe {
|
||||
dht_runner_run_config(&mut *self, port, &*config)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bootstrap(&mut self, host: &str, service: u16) {
|
||||
unsafe {
|
||||
dht_runner_bootstrap(&mut *self,
|
||||
CString::new(host).unwrap().as_ptr(),
|
||||
CString::new(service.to_string()).unwrap().as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn node_id(&self) -> InfoHash {
|
||||
unsafe {
|
||||
dht_runner_get_node_id(&*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> InfoHash {
|
||||
unsafe {
|
||||
dht_runner_get_id(&*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<'a>(&mut self, h: &InfoHash,
|
||||
get_cb: &'a mut(dyn FnMut(Box<Value>)),
|
||||
done_cb: &'a mut(dyn FnMut(bool))) {
|
||||
let handler = Box::new(GetHandler {
|
||||
get_cb,
|
||||
done_cb,
|
||||
});
|
||||
let handler = Box::into_raw(handler) as *mut c_void;
|
||||
unsafe {
|
||||
dht_runner_get(&mut *self, h, get_handler_cb, done_handler_cb, handler)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn 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(&mut *self, h, &*v, put_handler_done, handler)
|
||||
}
|
||||
}
|
||||
|
||||
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_permanent(&mut *self, h, &*v, put_handler_done, handler)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel_put<'a>(&mut self, h: &InfoHash, vid: u64) {
|
||||
unsafe {
|
||||
dht_runner_cancel_put(&mut *self, h, vid)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn listen<'a>(&mut self, h: &InfoHash,
|
||||
cb: &'a mut(dyn FnMut(Box<Value>, bool))) -> Box<OpToken> {
|
||||
let handler = Box::new(ListenHandler {
|
||||
cb,
|
||||
});
|
||||
let handler = Box::into_raw(handler) as *mut c_void;
|
||||
unsafe {
|
||||
Box::from_raw(dht_runner_listen(&mut *self, h, listen_handler, listen_handler_done, handler))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cancel_listen(&mut self, h: &InfoHash, token: Box<OpToken>) {
|
||||
unsafe {
|
||||
dht_runner_cancel_listen(&mut *self, h, &*token)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shutdown(&mut self,
|
||||
done_cb: extern fn(bool, *mut c_void),
|
||||
cb_user_data: *mut c_void)
|
||||
{
|
||||
unsafe {
|
||||
dht_runner_shutdown(&mut *self, done_cb, cb_user_data)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn public_addresses(&self) -> Vec<SocketAddr> {
|
||||
let mut result = Vec::new();
|
||||
unsafe {
|
||||
let mut addresses = dht_runner_get_public_address(&*self);
|
||||
while !addresses.is_null() && !(*addresses).is_null() {
|
||||
let sock = (*(*addresses)).into_addr();
|
||||
if sock.is_some() {
|
||||
result.push(sock.unwrap());
|
||||
}
|
||||
addresses = (addresses as usize + std::mem::size_of::<*mut OsSocketAddr>()) as *mut *mut OsSocketAddr;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DhtRunner {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_runner_delete(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OpToken {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_op_token_delete(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use libc::{c_char, c_int, c_uint, c_void, in_port_t, size_t};
|
||||
use os_socketaddr::OsSocketAddr;
|
||||
|
||||
const HASH_LEN: usize = 20;
|
||||
const PKID_LEN: usize = 32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DataView
|
||||
{
|
||||
pub data: *const u8,
|
||||
pub size: size_t
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Value
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Blob
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct InfoHash
|
||||
{
|
||||
pub d: [u8; HASH_LEN],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PkId
|
||||
{
|
||||
pub d: [u8; PKID_LEN],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PublicKey
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PrivateKey
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct OpToken
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtRunner
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtNodeConfig
|
||||
{
|
||||
pub node_id: InfoHash,
|
||||
pub network: u32,
|
||||
pub is_bootstrap: bool,
|
||||
pub maintain_storage: bool,
|
||||
pub persist_path: *const c_char,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtCertificate
|
||||
{
|
||||
_opaque: [u8; 0]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtIdentity
|
||||
{
|
||||
pub privkey: *mut PrivateKey,
|
||||
pub certificate: *mut DhtCertificate,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtSecureConfig
|
||||
{
|
||||
pub node_config: DhtNodeConfig,
|
||||
pub id: DhtIdentity,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DhtRunnerConfig
|
||||
{
|
||||
pub dht_config: DhtSecureConfig,
|
||||
pub threaded: bool,
|
||||
pub proxy_server: *const c_char,
|
||||
pub push_node_id: *const c_char,
|
||||
pub push_token: *const c_char,
|
||||
pub peer_discovery: bool,
|
||||
pub peer_publish: bool,
|
||||
pub server_ca: *mut DhtCertificate,
|
||||
pub client_identity: DhtIdentity,
|
||||
}
|
||||
|
||||
|
||||
#[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);
|
||||
|
||||
// dht::Blob
|
||||
pub fn dht_blob_get_data(data: *const Blob) -> DataView;
|
||||
pub fn dht_blob_delete(data: *mut Blob);
|
||||
|
||||
// dht::InfoHash
|
||||
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_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_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;
|
||||
pub fn dht_publickey_get_id(pk: *const PublicKey) -> InfoHash;
|
||||
pub fn dht_publickey_get_long_id(pk: *const PublicKey) -> PkId;
|
||||
pub fn dht_publickey_check_signature(pk: *const PublicKey, data: *const c_char, data_size: size_t, signature: *const c_char, signature_size: size_t) -> bool;
|
||||
pub fn dht_publickey_encrypt(pk: *const PublicKey, data: *const c_char, data_size: size_t) -> *mut Blob;
|
||||
|
||||
// dht::crypto::PrivateKey
|
||||
pub fn dht_privatekey_generate(key_length_bits: c_uint) -> *mut PrivateKey;
|
||||
pub fn dht_privatekey_import(dat: *const u8, data_size: size_t, password: *const c_char) -> *mut PrivateKey;
|
||||
pub fn dht_privatekey_get_publickey(pk: *const PrivateKey) -> *mut PublicKey;
|
||||
pub fn dht_privatekey_delete(pk: *mut PrivateKey);
|
||||
|
||||
// dht::OpToken
|
||||
pub fn dht_op_token_delete(token: *mut OpToken);
|
||||
|
||||
// dht::DhtRunner
|
||||
pub fn dht_runner_config_default(config: *mut DhtRunnerConfig);
|
||||
pub fn dht_runner_new() -> *mut DhtRunner;
|
||||
pub fn dht_runner_get_id(dht: *const DhtRunner) -> InfoHash;
|
||||
pub fn dht_runner_get_node_id(dht: *const DhtRunner) -> InfoHash;
|
||||
pub fn dht_runner_delete(dht: *mut DhtRunner);
|
||||
pub fn dht_runner_run(dht: *mut DhtRunner, port: in_port_t);
|
||||
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),
|
||||
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);
|
||||
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),
|
||||
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,
|
||||
token: *const OpToken);
|
||||
pub fn dht_runner_shutdown(dht: *mut DhtRunner, done_cb: extern fn(bool, *mut c_void),
|
||||
cb_user_data: *mut c_void);
|
||||
pub fn dht_runner_get_public_address(dht: *const DhtRunner) -> *mut *mut OsSocketAddr;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::ffi::*;
|
||||
use std::ffi::CStr;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
|
||||
pub use crate::ffi::InfoHash;
|
||||
|
||||
impl InfoHash {
|
||||
pub fn new() -> InfoHash {
|
||||
InfoHash {
|
||||
d: [0; 20]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random() -> InfoHash {
|
||||
let mut h = InfoHash::new();
|
||||
unsafe {
|
||||
dht_infohash_random(&mut h);
|
||||
}
|
||||
h
|
||||
}
|
||||
|
||||
pub fn get(data: &str) -> InfoHash {
|
||||
let mut h = InfoHash::new();
|
||||
unsafe {
|
||||
let c_str = CString::new(data).unwrap();
|
||||
dht_infohash_get(&mut h, c_str.as_ptr() as *mut u8, data.len());
|
||||
}
|
||||
h
|
||||
}
|
||||
|
||||
pub fn is_zero(&self) -> bool {
|
||||
unsafe {
|
||||
dht_infohash_is_zero(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InfoHash {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let self_str = CStr::from_ptr(
|
||||
dht_infohash_print(self)
|
||||
).to_str().unwrap_or("");
|
||||
write!(f, "{}", self_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
extern crate libc;
|
||||
extern crate os_socketaddr;
|
||||
|
||||
mod blob;
|
||||
pub mod crypto;
|
||||
mod dhtrunner;
|
||||
mod ffi;
|
||||
mod infohash;
|
||||
mod pkid;
|
||||
mod value;
|
||||
|
||||
pub use blob::Blob;
|
||||
pub use dhtrunner::{ DhtRunner, DhtRunnerConfig, OpToken };
|
||||
pub use infohash::InfoHash;
|
||||
pub use pkid::PkId;
|
||||
pub use value::{ DataView, Value };
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::ffi::*;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
|
||||
pub use crate::ffi::PkId;
|
||||
|
||||
impl fmt::Display for PkId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let self_str = CStr::from_ptr(
|
||||
dht_pkid_print(self)
|
||||
).to_str().unwrap_or("");
|
||||
write!(f, "{}", self_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Savoir-faire Linux Inc.
|
||||
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::ffi::*;
|
||||
use std::fmt;
|
||||
use std::str;
|
||||
use std::slice;
|
||||
|
||||
pub use crate::ffi::{DataView, Value};
|
||||
|
||||
impl Value {
|
||||
pub fn new(data: &str) -> Box<Value> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_value_new(data.as_bytes().as_ptr(),
|
||||
data.as_bytes().len()))
|
||||
}
|
||||
}
|
||||
pub fn from_bytes(data: &Vec<u8>) -> Box<Value> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_value_new(data.as_ptr(),
|
||||
data.len()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self) -> u64 {
|
||||
unsafe {
|
||||
dht_value_get_id(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn dataview(&self) -> DataView {
|
||||
unsafe {
|
||||
dht_value_get_data(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let dv = dht_value_get_data(self);
|
||||
let slice = slice::from_raw_parts_mut(dv.data as *mut _, dv.size);
|
||||
slice.to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boxed(&mut self) -> Box<Value> {
|
||||
unsafe {
|
||||
Box::from_raw(dht_value_ref(self))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Value {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
dht_value_unref(&mut *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Value {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let dataview = self.dataview();
|
||||
let slice = slice::from_raw_parts(dataview.data, dataview.size);
|
||||
write!(f, "{}", str::from_utf8(slice).unwrap_or(""))
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-12
@@ -105,7 +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());
|
||||
gcm_aes_update(&aes, data_length, data);
|
||||
|
||||
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);
|
||||
@@ -137,18 +136,8 @@ Blob aesDecrypt(const Blob& data, const Blob& key)
|
||||
|
||||
size_t data_sz = data.size() - GCM_IV_SIZE - GCM_DIGEST_SIZE;
|
||||
Blob ret(data_sz);
|
||||
//gcm_aes_update(&aes, data_sz, data.data() + GCM_IV_SIZE);
|
||||
gcm_aes_decrypt(&aes, data_sz, ret.data(), data.data() + GCM_IV_SIZE);
|
||||
//gcm_aes_digest(aes, GCM_DIGEST_SIZE, digest.data());
|
||||
|
||||
// TODO compute the proper digest directly from the decryption pass
|
||||
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());
|
||||
gcm_aes_digest(&aes, GCM_DIGEST_SIZE, digest.data());
|
||||
|
||||
if (not std::equal(digest.begin(), digest.end(), data.end() - GCM_DIGEST_SIZE))
|
||||
throw DecryptError("Can't decrypt data");
|
||||
|
||||
+8
-5
@@ -210,9 +210,12 @@ Connection::data()
|
||||
std::string
|
||||
Connection::read_bytes(const size_t bytes)
|
||||
{
|
||||
std::ostringstream str_s;
|
||||
str_s << &read_buf_;
|
||||
return str_s.str().substr(0, bytes);
|
||||
std::string content;
|
||||
std::istream is(&read_buf_);
|
||||
content.resize(bytes);
|
||||
auto rb = is.readsome(&content[0], bytes);
|
||||
content.resize(rb);
|
||||
return content;
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -917,8 +920,8 @@ Request::handle_response_header(const asio::error_code& ec)
|
||||
// has content-length
|
||||
if (content_length_it != response_.headers.end())
|
||||
{
|
||||
std::getline(is, response_.body);
|
||||
unsigned int content_length = atoi(content_length_it->second.c_str());
|
||||
response_.body.append(conn_->read_bytes(content_length));
|
||||
// full body already in the header
|
||||
if (response_.body.size() + 1 == content_length) {
|
||||
response_.body.append("\n");
|
||||
@@ -985,9 +988,9 @@ Request::handle_response_body(const asio::error_code& ec, const size_t bytes)
|
||||
// read the content-length body
|
||||
unsigned int content_length;
|
||||
if (content_length_it != response_.headers.end() and !response_.body.empty()){
|
||||
response_.body.append(conn_->read_bytes(bytes));
|
||||
// extract the content-length
|
||||
content_length = atoi(content_length_it->second.c_str());
|
||||
response_.body.append(conn_->read_bytes(bytes));
|
||||
// check if fully parsed
|
||||
if (response_.body.size() == content_length)
|
||||
parse_request(response_.body);
|
||||
|
||||
+18
-6
@@ -34,16 +34,28 @@ CryptoTester::testSignatureEncryption() {
|
||||
auto key = dht::crypto::PrivateKey::generate();
|
||||
auto public_key = key.getPublicKey();
|
||||
|
||||
std::vector<uint8_t> data {5, 10};
|
||||
std::vector<uint8_t> signature = key.sign(data);
|
||||
std::vector<uint8_t> data1 {5, 10};
|
||||
std::vector<uint8_t> data2(64 * 1024, 10);
|
||||
|
||||
std::vector<uint8_t> signature1 = key.sign(data1);
|
||||
std::vector<uint8_t> signature2 = key.sign(data2);
|
||||
|
||||
// check signature
|
||||
CPPUNIT_ASSERT(public_key.checkSignature(data, signature));
|
||||
CPPUNIT_ASSERT(public_key.checkSignature(data1, signature1));
|
||||
CPPUNIT_ASSERT(public_key.checkSignature(data2, signature2));
|
||||
|
||||
// encrypt data
|
||||
std::vector<uint8_t> encrypted = public_key.encrypt(data);
|
||||
std::vector<uint8_t> decrypted = key.decrypt(encrypted);
|
||||
CPPUNIT_ASSERT(data == decrypted);
|
||||
{
|
||||
std::vector<uint8_t> encrypted = public_key.encrypt(data1);
|
||||
std::vector<uint8_t> decrypted = key.decrypt(encrypted);
|
||||
CPPUNIT_ASSERT(data1 == decrypted);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<uint8_t> encrypted = public_key.encrypt(data2);
|
||||
std::vector<uint8_t> decrypted = key.decrypt(encrypted);
|
||||
CPPUNIT_ASSERT(data2 == decrypted);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+4
-1
@@ -109,6 +109,8 @@ main(int argc, char **argv)
|
||||
|
||||
bool connected {false};
|
||||
InfoHash room;
|
||||
std::future<size_t> token;
|
||||
|
||||
const InfoHash myid = dht.getId();
|
||||
|
||||
#ifndef WIN32_NATIVE
|
||||
@@ -139,7 +141,7 @@ main(int argc, char **argv)
|
||||
std::cout << "Joining h(" << idstr << ") = " << room << std::endl;
|
||||
}
|
||||
|
||||
dht.listen<dht::ImMessage>(room, [&](dht::ImMessage&& msg) {
|
||||
token = dht.listen<dht::ImMessage>(room, [&](dht::ImMessage&& msg) {
|
||||
if (msg.from != myid)
|
||||
std::cout << msg.from.toString() << " at " << printTime(msg.date)
|
||||
<< " (took " << print_dt(std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t(msg.date))
|
||||
@@ -153,6 +155,7 @@ main(int argc, char **argv)
|
||||
} else {
|
||||
auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
if (op == "d") {
|
||||
dht.cancelListen(room, std::move(token));
|
||||
connected = false;
|
||||
continue;
|
||||
} else if (op == "e") {
|
||||
|
||||
+53
-2
@@ -3,10 +3,16 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
struct op_context {
|
||||
dht_runner* runner;
|
||||
int d;
|
||||
};
|
||||
|
||||
bool dht_value_callback(const dht_value* value, bool expired, void* user_data)
|
||||
{
|
||||
dht_runner* runner = (dht_runner*)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);
|
||||
}
|
||||
@@ -24,6 +30,34 @@ bool dht_done_callback(bool ok, void* user_data)
|
||||
printf("Done callback. %s\n", ok ? "Success !" : "Failure :-(");
|
||||
}
|
||||
|
||||
bool op_context_free(void* user_data)
|
||||
{
|
||||
struct op_context* ctx = (struct op_context*)user_data;
|
||||
printf("op_context_free %d.\n", ctx->d);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
char* print_addr(const struct sockaddr* addr) {
|
||||
char* s = NULL;
|
||||
switch(addr->sa_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
|
||||
s = malloc(INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN);
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
s = malloc(INET6_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
dht_runner* runner = dht_runner_new();
|
||||
@@ -44,10 +78,27 @@ int main()
|
||||
dht_runner_get(runner, &h, dht_get_callback, dht_done_callback, runner);
|
||||
|
||||
// Listen for data
|
||||
dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, runner);
|
||||
struct op_context* ctx = malloc(sizeof(struct op_context));
|
||||
ctx->runner = runner;
|
||||
ctx->d = 42;
|
||||
dht_op_token* token = dht_runner_listen(runner, &h, dht_value_callback, op_context_free, ctx);
|
||||
|
||||
sleep(1);
|
||||
|
||||
dht_runner_bootstrap(runner, "bootstrap.jami.net", NULL);
|
||||
|
||||
sleep(2);
|
||||
|
||||
struct sockaddr** addrs = dht_runner_get_public_address(runner);
|
||||
for (struct sockaddr** addrIt = addrs; *addrIt; addrIt++) {
|
||||
struct sockaddr* addr = *addrIt;
|
||||
char* addr_str = print_addr(addr);
|
||||
free(addr);
|
||||
printf("Found public address: %s\n", addr_str);
|
||||
free(addr_str);
|
||||
}
|
||||
free(addrs);
|
||||
|
||||
dht_runner_cancel_listen(runner, &h, token);
|
||||
dht_op_token_delete(token);
|
||||
|
||||
|
||||
Reference in new issue
Block a user