Compare commits

..
Author SHA1 Message Date
Adrien Béraud 68485faf58 crypto: improve authenticated encryption performance 2019-10-22 13:04:30 -04:00
Adrien Béraud 28de983166 update to version 2.0.0 2019-10-22 10:52:49 -04:00
Adrien Béraud 4b28278cb1 Update README.md 2019-10-22 10:48:50 -04:00
Sébastien Blin 653a4309bd rust: value to bytes 2019-10-22 10:47:43 -04:00
Sébastien Blin 48b763f11b rust: add from_bytes for value 2019-10-22 10:47:43 -04:00
Sébastien Blin cbfa12a921 rust: add permanent put, get_id(), get_node_id(), get_public_addresses() 2019-10-22 10:47:43 -04:00
Sébastien Blin 3e0d4cd703 rust: link DhtRunnerConfig 2019-10-22 10:47:43 -04:00
Sébastien Blin 4bff6d392a rust: clean warnings 2019-10-22 10:47:43 -04:00
Sébastien Blin 712b7218a9 rust: clean listen API 2019-10-22 10:47:43 -04:00
Sébastien Blin 5a8e252e32 rust: get2 -> get 2019-10-22 10:47:43 -04:00
Sébastien Blin b5be4549dc rust: clean dhtnode.rs 2019-10-22 10:47:43 -04:00
Sébastien Blin bf8fb6f321 rust: clean listen API 2019-10-22 10:47:43 -04:00
Sébastien Blin 08cf212c53 rust: split in files 2019-10-22 10:47:43 -04:00
Sébastien Blin fc2a597bb2 rust: update bootstrap api 2019-10-22 10:47:43 -04:00
Sébastien Blin 7212b7a28b rust: change put api 2019-10-22 10:47:43 -04:00
Sébastien Blin 5c610895fe rust: add support for all functions available in the C wrapper 2019-10-22 10:47:43 -04:00
Sébastien Blin a567ca1dc1 rust: add support for listen/cancel_listen 2019-10-22 10:47:43 -04:00
Sébastien Blin 97b20705a1 rust: add put bindings 2019-10-22 10:47:43 -04:00
Sébastien Blin 431da16ba6 dhtnode: add example with get 2019-10-22 10:47:43 -04:00
Sébastien Blin 09818d779e rust: start dhtnode example 2019-10-22 10:47:43 -04:00
Sébastien Blin 934e36ba13 rust: ffi POC 2019-10-22 10:47:43 -04:00
Adrien Béraud 2e47b9bab5 c wrapper: add dht_runner_get_public_address to dhtcnode 2019-10-21 15:56:35 -04:00
Adrien Béraud f938d486d5 c wrapper: add listen context to dhtcnode 2019-10-21 15:09:56 -04:00
Adrien Béraud 76b4da089e c wrapper: add dht_runner_get_public_address 2019-10-21 14:33:37 -04:00
Adrien Béraud 2a72277194 c wrapper: add dht_runner_get_id, get_node_id 2019-10-21 14:19:29 -04:00
Adrien Béraud e8d96d3b42 c wrapper: add support for permanent put 2019-10-21 14:04:12 -04:00
Adrien Béraud c92d236c1b c wrapper: handle null string in config 2019-10-21 12:37:36 -04:00
Adrien Béraud b680407e9a c wrapper: add callback to free listen context data 2019-10-21 11:08:42 -04:00
Seva 6caf4b0d0b http: ensure no data is lost in read_bytes 2019-10-18 15:44:26 -04:00
Seva 7f65fdc7f9 http: try to read full content-length after headers 2019-10-18 10:45:34 -04:00
Adrien Béraud b00dfdf572 c wrapper: reverse is_zero value 2019-10-17 10:29:37 -04:00
Adrien Béraud 2b1d2fc3f6 c wrapper: use shared_ptr for dht_privatekey 2019-10-16 17:23:04 -04:00
Adrien Béraud a0566cf695 dhtchat: cancel listen on channel disconnect 2019-10-16 16:18:38 -04:00
Adrien Béraud a3f2b055a1 c wrapper: don't build by default 2019-10-16 16:17:09 -04:00
22 changed files with 1221 additions and 59 deletions

No files matched your search

+3 -3
View File
@@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 3.1)
project (opendht)
set (opendht_VERSION_MAJOR 1)
set (opendht_VERSION_MINOR 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})
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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])
+2
View File
@@ -0,0 +1,2 @@
*.lock
target
+11
View File
@@ -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"
+21
View File
@@ -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
```
+62
View File
@@ -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());
}
+37
View File
@@ -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)
}
}
}
+114
View File
@@ -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)
}
}
}
+299
View File
@@ -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
View File
@@ -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;
}
+66
View File
@@ -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)
}
}
}
+34
View File
@@ -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 };
+34
View File
@@ -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)
}
}
}
+83
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);