mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-15 12:13:24 +00:00
* implement path transfer message
* update dht docs * update other docs * start working on dht for hidden services * fix up unit tests for dht * update makefile and other build files
This commit is contained in:
parent
7d9bffdf9c
commit
18b50f4a74
@ -170,9 +170,11 @@ set(LIB_SRC
|
|||||||
llarp/api/client.cpp
|
llarp/api/client.cpp
|
||||||
llarp/api/message.cpp
|
llarp/api/message.cpp
|
||||||
llarp/api/parser.cpp
|
llarp/api/parser.cpp
|
||||||
|
llarp/routing/dht_message.cpp
|
||||||
llarp/routing/message_parser.cpp
|
llarp/routing/message_parser.cpp
|
||||||
llarp/routing/path_confirm.cpp
|
llarp/routing/path_confirm.cpp
|
||||||
llarp/routing/path_latency.cpp
|
llarp/routing/path_latency.cpp
|
||||||
|
llarp/routing/path_transfer.cpp
|
||||||
vendor/cppbackport-master/lib/fs/rename.cpp
|
vendor/cppbackport-master/lib/fs/rename.cpp
|
||||||
vendor/cppbackport-master/lib/fs/filestatus.cpp
|
vendor/cppbackport-master/lib/fs/filestatus.cpp
|
||||||
vendor/cppbackport-master/lib/fs/filetype.cpp
|
vendor/cppbackport-master/lib/fs/filetype.cpp
|
||||||
|
2
Makefile
2
Makefile
@ -70,7 +70,7 @@ testnet-build: testnet-configure
|
|||||||
|
|
||||||
testnet: testnet-build
|
testnet: testnet-build
|
||||||
mkdir -p $(TESTNET_ROOT)
|
mkdir -p $(TESTNET_ROOT)
|
||||||
python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=10 --clients=1 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
|
python3 contrib/testnet/genconf.py --bin=$(REPO)/llarpd --svc=30 --clients=100 --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF)
|
||||||
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
|
supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
|
||||||
|
|
||||||
test: debug-configure
|
test: debug-configure
|
||||||
|
131
doc/dht_v0.txt
131
doc/dht_v0.txt
@ -2,13 +2,12 @@ DHT messages
|
|||||||
|
|
||||||
these messages can be either wrapped in a LIDM message or sent anonymously over a path
|
these messages can be either wrapped in a LIDM message or sent anonymously over a path
|
||||||
|
|
||||||
|
This document is currently out of date (probably)
|
||||||
|
|
||||||
|
|
||||||
find introduction message (FIM)
|
find introduction message (FIM)
|
||||||
|
|
||||||
recursively find an IS.
|
recursively find an IS by SA
|
||||||
|
|
||||||
variant 1, by SA
|
|
||||||
|
|
||||||
{
|
{
|
||||||
A: "F",
|
A: "F",
|
||||||
@ -18,16 +17,6 @@ variant 1, by SA
|
|||||||
V: 0
|
V: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
variant 2, by claimed name
|
|
||||||
|
|
||||||
{
|
|
||||||
A: "F",
|
|
||||||
N: "service.name.tld",
|
|
||||||
R: r_counter,
|
|
||||||
T: transaction_id_uin64,
|
|
||||||
V: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Transactions will persist until replied to by a GIM or 60 seconds, whichever
|
Transactions will persist until replied to by a GIM or 60 seconds, whichever
|
||||||
is reached first.
|
is reached first.
|
||||||
|
|
||||||
@ -80,9 +69,9 @@ got introduction message (GIM)
|
|||||||
|
|
||||||
{
|
{
|
||||||
A: "G",
|
A: "G",
|
||||||
|
I: [IS],
|
||||||
T: transaction_id_uint64,
|
T: transaction_id_uint64,
|
||||||
V: 0,
|
V: 0,
|
||||||
X: [ IS, IS, IS, ... ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if we have a transaction with id T:
|
if we have a transaction with id T:
|
||||||
@ -95,115 +84,36 @@ when a linked transaction gets a GIM:
|
|||||||
* set T to the current transaction id
|
* set T to the current transaction id
|
||||||
* foward the GIM to the requester of T
|
* foward the GIM to the requester of T
|
||||||
|
|
||||||
|
|
||||||
publish introduction message (PIM)
|
publish introduction message (PIM)
|
||||||
|
|
||||||
publish one or many IM into the dht at once.
|
publish one IS to the DHT.
|
||||||
each IS will be placed in the dht
|
|
||||||
|
|
||||||
version 0 uses the SA of each IS as the keyspace location.
|
version 0 uses the SA of the IS as the keyspace location.
|
||||||
|
|
||||||
in the future the location will be determined by the dht kdf
|
in the future the location will be determined by the dht kdf
|
||||||
which uses a shared random source to obfuscate keyspace location.
|
which uses a shared random source to obfuscate keyspace location.
|
||||||
|
|
||||||
|
|
||||||
R is currently set to 3 +/- 2 by the sender.
|
R is currently set to 0 by the sender.
|
||||||
|
|
||||||
{
|
{
|
||||||
A: "P",
|
A: "I",
|
||||||
|
I: IS,
|
||||||
R: r_counter,
|
R: r_counter,
|
||||||
V: 0,
|
S: optional member 0 for immediate store otherwise non zero,
|
||||||
X: [ IS, IS, IS, ... ]
|
V: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
The following steps happen in order:
|
if R is greater than 0, do a random walk, otherwise if we are
|
||||||
|
closer to the SA of the IS than anyone else we know in the DHT
|
||||||
|
store the IS for later lookup.
|
||||||
|
|
||||||
first stage: reduction
|
If S is provided store the IS for later lookup unconditionally,
|
||||||
|
decrement S by 1 and forward to dht peer who is next closest to
|
||||||
|
the SA of the IS. If S is greater than 3, don't store and discard
|
||||||
|
this message.
|
||||||
|
|
||||||
if X's length is divisble by 2:
|
|
||||||
|
|
||||||
* split X in half as J and K
|
|
||||||
* generate 2 new PIM with the same values as the parent with empty X
|
|
||||||
* put J and K into the new PIM's X values
|
|
||||||
* associate the 2 new PIM with the current PIM batch
|
|
||||||
|
|
||||||
if X's length is not divisible by 2 and greater than 1:
|
|
||||||
|
|
||||||
* pop off an IS from X as A
|
|
||||||
* generate a new PIM with the same values as the parent with an X value of A
|
|
||||||
* associate the new PIM with the current PIM batch
|
|
||||||
* associate the old PIM having A removed from X with the current PIM batch
|
|
||||||
|
|
||||||
if X's length is 1:
|
|
||||||
|
|
||||||
* associate the PIM with the current PIM batch
|
|
||||||
|
|
||||||
any other cases for X are ignored.
|
|
||||||
|
|
||||||
for each PIM in the current batch:
|
|
||||||
|
|
||||||
if R is greater than 0:
|
|
||||||
|
|
||||||
* decrement R by 1
|
|
||||||
* queue the PIM for shuffle (second stage)
|
|
||||||
|
|
||||||
if R is 0:
|
|
||||||
|
|
||||||
* queue the PIM for distribution (third stage)
|
|
||||||
|
|
||||||
if R is less than 0:
|
|
||||||
|
|
||||||
* drop the message entirely
|
|
||||||
|
|
||||||
second stage: shuffle
|
|
||||||
|
|
||||||
* The dht node waits until we have collected 10 or more PIM or for 5 seconds,
|
|
||||||
which ever comes first.
|
|
||||||
* shuffle the list of IS randomly
|
|
||||||
* re-combine the IS into new PIMs
|
|
||||||
* queue each newly shuffled PIM for distribution (third stage)
|
|
||||||
|
|
||||||
if we collected 10 or more PIM:
|
|
||||||
|
|
||||||
* X holds 5 IS at most
|
|
||||||
|
|
||||||
if we collected less than 10 but more than 1 PIM:
|
|
||||||
|
|
||||||
* X holds 2 IS at most
|
|
||||||
|
|
||||||
if we only collected 1 PIM:
|
|
||||||
|
|
||||||
* the single PIM is unmodified
|
|
||||||
|
|
||||||
|
|
||||||
third stage: distribution
|
|
||||||
|
|
||||||
if R is less than 0:
|
|
||||||
|
|
||||||
* drop message and terminate current transaction, this should never happen but
|
|
||||||
this case is left here in the event of implementation bugs.
|
|
||||||
|
|
||||||
if R is greater than 0:
|
|
||||||
|
|
||||||
* pick a random dht capable router, N
|
|
||||||
* forward the PIM to N
|
|
||||||
|
|
||||||
if R is equal to 0:
|
|
||||||
|
|
||||||
for each IS in X as A:
|
|
||||||
|
|
||||||
* find the router closest to the SA in A, N
|
|
||||||
|
|
||||||
if N is our router:
|
|
||||||
|
|
||||||
* create dht positon S from SA in A
|
|
||||||
* store A for lookup at S
|
|
||||||
|
|
||||||
if N is not our router:
|
|
||||||
|
|
||||||
* send a PIM with X value containing just A to N
|
|
||||||
|
|
||||||
In the future post random walk keyspace batching may be done here.
|
|
||||||
As of version 0, none is done.
|
|
||||||
|
|
||||||
find router contact message (FRCM)
|
find router contact message (FRCM)
|
||||||
|
|
||||||
@ -254,8 +164,3 @@ sent in reply to FRCM only
|
|||||||
* send a GRCM with R to requesters in all linked transactions
|
* send a GRCM with R to requesters in all linked transactions
|
||||||
* terminate transaction with id T
|
* terminate transaction with id T
|
||||||
|
|
||||||
notes:
|
|
||||||
|
|
||||||
if we get a GRCM with empty R on one Tx and then one with a filled R on another
|
|
||||||
with the same K, the request is terminated by the first message as not found.
|
|
||||||
A backtrack case is needed.
|
|
||||||
|
@ -153,14 +153,14 @@ the "network address" of a hidden service, which is computed as the blake2b
|
|||||||
|
|
||||||
HS(BE(SI))
|
HS(BE(SI))
|
||||||
|
|
||||||
introducer (I)
|
introduction (I)
|
||||||
|
|
||||||
a descriptor annoucing a path to a hidden service
|
a descriptor annoucing a path to a hidden service
|
||||||
|
|
||||||
k is the rc.k value of the router to contact
|
k is the rc.k value of the router to contact
|
||||||
p is the path id on the router that is owned by the service
|
p is the path id on the router that is owned by the service
|
||||||
v is the protocol version
|
v is the protocol version
|
||||||
x is the timestamp seconds since epoch that this introducer expires at
|
x is the timestamp seconds since epoch that this introduction expires at
|
||||||
|
|
||||||
{
|
{
|
||||||
k: "<32 bytes public identity key of router>",
|
k: "<32 bytes public identity key of router>",
|
||||||
@ -169,12 +169,13 @@ x is the timestamp seconds since epoch that this introducer expires at
|
|||||||
x: time_expires_seconds_since_epoch_uint64
|
x: time_expires_seconds_since_epoch_uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
introducer set (IS)
|
introduction set (IS)
|
||||||
|
|
||||||
a signed set of introducers for a hidden service
|
a signed set of introductions for a hidden service
|
||||||
a is the service info
|
a is the service info
|
||||||
i is the list of introducers that this service is advertising with
|
i is the list of introductions that this service is advertising with
|
||||||
v is the protocol version
|
v is the protocol version
|
||||||
|
w is an optinal proof of work for DoS protection (slot for future)
|
||||||
z is the signature of the entire IS where z is set to zero signed by the hidden
|
z is the signature of the entire IS where z is set to zero signed by the hidden
|
||||||
service's signing key.
|
service's signing key.
|
||||||
|
|
||||||
@ -182,6 +183,7 @@ service's signing key.
|
|||||||
a: SI,
|
a: SI,
|
||||||
i: [ I, I, I, ... ],
|
i: [ I, I, I, ... ],
|
||||||
v: 0,
|
v: 0,
|
||||||
|
w: optional proof of work,
|
||||||
z: "<64 bytes signature using service info signing key>"
|
z: "<64 bytes signature using service info signing key>"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,10 +192,6 @@ service's signing key.
|
|||||||
|
|
||||||
Encrypted frames:
|
Encrypted frames:
|
||||||
|
|
||||||
{
|
|
||||||
v: 0,
|
|
||||||
w: "<32+32+32+N bytes payload>"
|
|
||||||
}
|
|
||||||
|
|
||||||
Encrypted frames are encrypted containers for link message records like LRCR.
|
Encrypted frames are encrypted containers for link message records like LRCR.
|
||||||
|
|
||||||
@ -502,7 +500,7 @@ sent in response to an OXAM to indicate that exit traffic is not allowed or
|
|||||||
was denied.
|
was denied.
|
||||||
|
|
||||||
{
|
{
|
||||||
A: "R",
|
A: "J",
|
||||||
B: backoff_milliseconds_uint64,
|
B: backoff_milliseconds_uint64,
|
||||||
I: "<32 bytes signing public key of requester>",
|
I: "<32 bytes signing public key of requester>",
|
||||||
R: "<optional reject metadata>",
|
R: "<optional reject metadata>",
|
||||||
@ -596,3 +594,13 @@ The address used in exit MAY be reused later.
|
|||||||
Y: "<16 bytes nounce>",
|
Y: "<16 bytes nounce>",
|
||||||
Z: "<64 bytes signagure using previously provided signing key>"
|
Z: "<64 bytes signagure using previously provided signing key>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DHT message holder message:
|
||||||
|
|
||||||
|
wrapper message for sending many dht messages down a path.
|
||||||
|
|
||||||
|
{
|
||||||
|
A: "M",
|
||||||
|
M: [many, dht, messages, here],
|
||||||
|
V: 0
|
||||||
|
}
|
@ -6,6 +6,8 @@
|
|||||||
#include <llarp/router_contact.h>
|
#include <llarp/router_contact.h>
|
||||||
#include <llarp/time.h>
|
#include <llarp/time.h>
|
||||||
#include <llarp/aligned.hpp>
|
#include <llarp/aligned.hpp>
|
||||||
|
#include <llarp/path_types.hpp>
|
||||||
|
#include <llarp/service.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -46,23 +48,40 @@ namespace llarp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Node
|
struct RCNode
|
||||||
{
|
{
|
||||||
llarp_rc* rc;
|
llarp_rc* rc;
|
||||||
|
|
||||||
Key_t ID;
|
Key_t ID;
|
||||||
|
|
||||||
Node() : rc(nullptr)
|
RCNode() : rc(nullptr)
|
||||||
{
|
{
|
||||||
ID.Zero();
|
ID.Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node(llarp_rc* other) : rc(other)
|
RCNode(llarp_rc* other) : rc(other)
|
||||||
{
|
{
|
||||||
ID = other->pubkey;
|
ID = other->pubkey;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ISNode
|
||||||
|
{
|
||||||
|
llarp::service::IntroSet* introset;
|
||||||
|
|
||||||
|
Key_t ID;
|
||||||
|
|
||||||
|
ISNode() : introset(nullptr)
|
||||||
|
{
|
||||||
|
ID.Zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
ISNode(llarp::service::IntroSet* other) : introset(other)
|
||||||
|
{
|
||||||
|
other->A.CalculateAddress(ID);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SearchJob
|
struct SearchJob
|
||||||
{
|
{
|
||||||
const static uint64_t JobTimeout = 30000;
|
const static uint64_t JobTimeout = 30000;
|
||||||
@ -128,24 +147,65 @@ namespace llarp
|
|||||||
DecodeMesssageList(const Key_t& from, llarp_buffer_t* buf,
|
DecodeMesssageList(const Key_t& from, llarp_buffer_t* buf,
|
||||||
std::vector< IMessage* >& dst);
|
std::vector< IMessage* >& dst);
|
||||||
|
|
||||||
|
template < typename Val_t >
|
||||||
struct Bucket
|
struct Bucket
|
||||||
{
|
{
|
||||||
typedef std::map< Key_t, Node, XorMetric > BucketStorage_t;
|
typedef std::map< Key_t, Val_t, XorMetric > BucketStorage_t;
|
||||||
|
|
||||||
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
|
Bucket(const Key_t& us) : nodes(XorMetric(us)){};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
FindClosest(const Key_t& target, Key_t& result) const;
|
FindClosest(const Key_t& target, Key_t& result) const
|
||||||
|
{
|
||||||
|
Key_t mindist;
|
||||||
|
mindist.Fill(0xff);
|
||||||
|
for(const auto& item : nodes)
|
||||||
|
{
|
||||||
|
auto curDist = item.first ^ target;
|
||||||
|
if(curDist < mindist)
|
||||||
|
{
|
||||||
|
mindist = curDist;
|
||||||
|
result = item.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
FindCloseExcluding(const Key_t& target, Key_t& result,
|
FindCloseExcluding(const Key_t& target, Key_t& result,
|
||||||
const std::set< Key_t >& exclude) const;
|
const std::set< Key_t >& exclude) const
|
||||||
|
{
|
||||||
|
Key_t maxdist;
|
||||||
|
maxdist.Fill(0xff);
|
||||||
|
Key_t mindist;
|
||||||
|
mindist.Fill(0xff);
|
||||||
|
for(const auto& item : nodes)
|
||||||
|
{
|
||||||
|
if(exclude.find(item.first) != exclude.end())
|
||||||
|
continue;
|
||||||
|
auto curDist = item.first ^ target;
|
||||||
|
if(curDist < mindist)
|
||||||
|
{
|
||||||
|
mindist = curDist;
|
||||||
|
result = item.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mindist < maxdist;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PutNode(const Node& val);
|
PutNode(const Val_t& val)
|
||||||
|
{
|
||||||
|
nodes[val.ID] = val;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DelNode(const Key_t& key);
|
DelNode(const Key_t& key)
|
||||||
|
{
|
||||||
|
auto itr = nodes.find(key);
|
||||||
|
if(itr != nodes.end())
|
||||||
|
nodes.erase(itr);
|
||||||
|
}
|
||||||
|
|
||||||
BucketStorage_t nodes;
|
BucketStorage_t nodes;
|
||||||
};
|
};
|
||||||
@ -177,6 +237,10 @@ namespace llarp
|
|||||||
const Key_t& target, bool recursive,
|
const Key_t& target, bool recursive,
|
||||||
std::vector< IMessage* >& replies);
|
std::vector< IMessage* >& replies);
|
||||||
|
|
||||||
|
bool
|
||||||
|
RelayRequestForPath(const llarp::PathID_t& localPath,
|
||||||
|
const IMessage* msg);
|
||||||
|
|
||||||
void
|
void
|
||||||
Init(const Key_t& us, llarp_router* router);
|
Init(const Key_t& us, llarp_router* router);
|
||||||
|
|
||||||
@ -190,8 +254,12 @@ namespace llarp
|
|||||||
queue_router_lookup(void* user);
|
queue_router_lookup(void* user);
|
||||||
|
|
||||||
llarp_router* router = nullptr;
|
llarp_router* router = nullptr;
|
||||||
Bucket* nodes = nullptr;
|
// for router contacts
|
||||||
bool allowTransit = false;
|
Bucket< RCNode >* nodes = nullptr;
|
||||||
|
|
||||||
|
// for introduction sets
|
||||||
|
Bucket< ISNode >* services = nullptr;
|
||||||
|
bool allowTransit = false;
|
||||||
|
|
||||||
const Key_t&
|
const Key_t&
|
||||||
OurKey() const
|
OurKey() const
|
||||||
|
31
include/llarp/messages/dht.hpp
Normal file
31
include/llarp/messages/dht.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef LLARP_MESSAGES_DHT_HPP
|
||||||
|
#define LLARP_MESSAGES_DHT_HPP
|
||||||
|
#include <llarp/dht.hpp>
|
||||||
|
#include <llarp/routing/message.hpp>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llarp
|
||||||
|
{
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
struct DHTMessage : public IMessage
|
||||||
|
{
|
||||||
|
std::vector< llarp::dht::IMessage* > M;
|
||||||
|
uint64_t V = 0;
|
||||||
|
|
||||||
|
~DHTMessage();
|
||||||
|
|
||||||
|
bool
|
||||||
|
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
|
||||||
|
|
||||||
|
bool
|
||||||
|
BEncode(llarp_buffer_t* buf) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
HandleMessage(IMessageHandler* h, llarp_router* r) const;
|
||||||
|
};
|
||||||
|
} // namespace routing
|
||||||
|
} // namespace llarp
|
||||||
|
|
||||||
|
#endif
|
@ -25,6 +25,6 @@ namespace llarp
|
|||||||
bool
|
bool
|
||||||
HandleMessage(llarp_router* router) const;
|
HandleMessage(llarp_router* router) const;
|
||||||
};
|
};
|
||||||
}
|
} // namespace llarp
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,7 +13,20 @@ namespace llarp
|
|||||||
{
|
{
|
||||||
PathID_t P;
|
PathID_t P;
|
||||||
Encrypted T;
|
Encrypted T;
|
||||||
|
uint64_t V = 0;
|
||||||
TunnelNonce Y;
|
TunnelNonce Y;
|
||||||
|
|
||||||
|
PathTransferMessage();
|
||||||
|
~PathTransferMessage();
|
||||||
|
|
||||||
|
bool
|
||||||
|
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
|
||||||
|
|
||||||
|
bool
|
||||||
|
BEncode(llarp_buffer_t* buf) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
HandleMessage(IMessageHandler*, llarp_router* r) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace routing
|
} // namespace routing
|
||||||
|
@ -23,8 +23,9 @@ namespace llarp
|
|||||||
TunnelNonce tunnelNonce;
|
TunnelNonce tunnelNonce;
|
||||||
PathID_t txid, rxid;
|
PathID_t txid, rxid;
|
||||||
|
|
||||||
PoW *work = nullptr;
|
PoW *work = nullptr;
|
||||||
uint64_t version = 0;
|
uint64_t version = 0;
|
||||||
|
uint64_t lifetime = 0;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BDecode(llarp_buffer_t *buf);
|
BDecode(llarp_buffer_t *buf);
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
#include <llarp/aligned.hpp>
|
#include <llarp/aligned.hpp>
|
||||||
#include <llarp/bencode.hpp>
|
#include <llarp/bencode.hpp>
|
||||||
#include <llarp/crypto.hpp>
|
#include <llarp/crypto.hpp>
|
||||||
|
#include <llarp/path_types.hpp>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
{
|
{
|
||||||
@ -22,7 +25,7 @@ namespace llarp
|
|||||||
|
|
||||||
/// calculate our address
|
/// calculate our address
|
||||||
void
|
void
|
||||||
CalculateAddress(llarp_crypto* c, Address& addr) const;
|
CalculateAddress(Address& addr) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BEncode(llarp_buffer_t* buf) const;
|
BEncode(llarp_buffer_t* buf) const;
|
||||||
@ -49,6 +52,33 @@ namespace llarp
|
|||||||
// load from file
|
// load from file
|
||||||
bool
|
bool
|
||||||
LoadFromFile(const std::string& fpath);
|
LoadFromFile(const std::string& fpath);
|
||||||
|
|
||||||
|
bool
|
||||||
|
BEncode(llarp_buffer_t* buf) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Introduction : public llarp::IBEncodeMessage
|
||||||
|
{
|
||||||
|
llarp::PubKey router;
|
||||||
|
llarp::PathID_t pathID;
|
||||||
|
uint64_t version = 0;
|
||||||
|
uint64_t expiresAt;
|
||||||
|
|
||||||
|
bool
|
||||||
|
BEncode(llarp_buffer_t* buf) const;
|
||||||
|
|
||||||
|
bool
|
||||||
|
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntroSet : public llarp::IBEncodeMessage
|
||||||
|
{
|
||||||
|
Info A;
|
||||||
|
std::set< Introduction > I;
|
||||||
|
llarp::Signature Z;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace service
|
}; // namespace service
|
||||||
|
164
llarp/dht.cpp
164
llarp/dht.cpp
@ -426,59 +426,6 @@ namespace llarp
|
|||||||
return now - started >= JobTimeout;
|
return now - started >= JobTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Bucket::FindClosest(const Key_t &target, Key_t &result) const
|
|
||||||
{
|
|
||||||
Key_t mindist;
|
|
||||||
mindist.Fill(0xff);
|
|
||||||
for(const auto &item : nodes)
|
|
||||||
{
|
|
||||||
auto curDist = item.first ^ target;
|
|
||||||
if(curDist < mindist)
|
|
||||||
{
|
|
||||||
mindist = curDist;
|
|
||||||
result = item.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nodes.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Bucket::FindCloseExcluding(const Key_t &target, Key_t &result,
|
|
||||||
const std::set< Key_t > &exclude) const
|
|
||||||
{
|
|
||||||
Key_t maxdist;
|
|
||||||
maxdist.Fill(0xff);
|
|
||||||
Key_t mindist;
|
|
||||||
mindist.Fill(0xff);
|
|
||||||
for(const auto &item : nodes)
|
|
||||||
{
|
|
||||||
if(exclude.find(item.first) != exclude.end())
|
|
||||||
continue;
|
|
||||||
auto curDist = item.first ^ target;
|
|
||||||
if(curDist < mindist)
|
|
||||||
{
|
|
||||||
mindist = curDist;
|
|
||||||
result = item.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mindist < maxdist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Bucket::PutNode(const Node &v)
|
|
||||||
{
|
|
||||||
nodes[v.ID] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Bucket::DelNode(const Key_t &k)
|
|
||||||
{
|
|
||||||
auto itr = nodes.find(k);
|
|
||||||
if(itr != nodes.end())
|
|
||||||
nodes.erase(itr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context::Context()
|
Context::Context()
|
||||||
{
|
{
|
||||||
randombytes((byte_t *)&ids, sizeof(uint64_t));
|
randombytes((byte_t *)&ids, sizeof(uint64_t));
|
||||||
@ -488,6 +435,8 @@ namespace llarp
|
|||||||
{
|
{
|
||||||
if(nodes)
|
if(nodes)
|
||||||
delete nodes;
|
delete nodes;
|
||||||
|
if(services)
|
||||||
|
delete services;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -603,9 +552,10 @@ namespace llarp
|
|||||||
void
|
void
|
||||||
Context::Init(const Key_t &us, llarp_router *r)
|
Context::Init(const Key_t &us, llarp_router *r)
|
||||||
{
|
{
|
||||||
router = r;
|
router = r;
|
||||||
ourKey = us;
|
ourKey = us;
|
||||||
nodes = new Bucket(ourKey);
|
nodes = new Bucket< RCNode >(ourKey);
|
||||||
|
services = new Bucket< ISNode >(ourKey);
|
||||||
llarp::Debug("intialize dht with key ", ourKey);
|
llarp::Debug("intialize dht with key ", ourKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -616,6 +566,13 @@ namespace llarp
|
|||||||
{1000, this, &handle_cleaner_timer});
|
{1000, this, &handle_cleaner_timer});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Context::RelayRequestForPath(const llarp::PathID_t &id, const IMessage *msg)
|
||||||
|
{
|
||||||
|
// TODO: implement me
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Context::LookupRouter(const Key_t &target, const Key_t &whoasked,
|
Context::LookupRouter(const Key_t &target, const Key_t &whoasked,
|
||||||
uint64_t txid, const Key_t &askpeer,
|
uint64_t txid, const Key_t &askpeer,
|
||||||
@ -673,60 +630,61 @@ llarp_dht_context::llarp_dht_context(llarp_router *router)
|
|||||||
parent = router;
|
parent = router;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C"
|
||||||
struct llarp_dht_context *
|
|
||||||
llarp_dht_context_new(struct llarp_router *router)
|
|
||||||
{
|
{
|
||||||
return new llarp_dht_context(router);
|
struct llarp_dht_context *
|
||||||
}
|
llarp_dht_context_new(struct llarp_router *router)
|
||||||
|
{
|
||||||
|
return new llarp_dht_context(router);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_context_free(struct llarp_dht_context *ctx)
|
llarp_dht_context_free(struct llarp_dht_context *ctx)
|
||||||
{
|
{
|
||||||
delete ctx;
|
delete ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_put_peer(struct llarp_dht_context *ctx, struct llarp_rc *rc)
|
llarp_dht_put_peer(struct llarp_dht_context *ctx, struct llarp_rc *rc)
|
||||||
|
|
||||||
{
|
{
|
||||||
llarp::dht::Node n(rc);
|
llarp::dht::RCNode n(rc);
|
||||||
ctx->impl.nodes->PutNode(n);
|
ctx->impl.nodes->PutNode(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_remove_peer(struct llarp_dht_context *ctx, const byte_t *id)
|
llarp_dht_remove_peer(struct llarp_dht_context *ctx, const byte_t *id)
|
||||||
{
|
{
|
||||||
llarp::dht::Key_t k = id;
|
llarp::dht::Key_t k = id;
|
||||||
ctx->impl.nodes->DelNode(k);
|
ctx->impl.nodes->DelNode(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_set_msg_handler(struct llarp_dht_context *ctx,
|
llarp_dht_set_msg_handler(struct llarp_dht_context *ctx,
|
||||||
llarp_dht_msg_handler handler)
|
llarp_dht_msg_handler handler)
|
||||||
{
|
{
|
||||||
ctx->impl.custom_handler = handler;
|
ctx->impl.custom_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_allow_transit(llarp_dht_context *ctx)
|
llarp_dht_allow_transit(llarp_dht_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->impl.allowTransit = true;
|
ctx->impl.allowTransit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
|
llarp_dht_context_start(struct llarp_dht_context *ctx, const byte_t *key)
|
||||||
{
|
{
|
||||||
ctx->impl.Init(key, ctx->parent);
|
ctx->impl.Init(key, ctx->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
llarp_dht_lookup_router(struct llarp_dht_context *ctx,
|
llarp_dht_lookup_router(struct llarp_dht_context *ctx,
|
||||||
struct llarp_router_lookup_job *job)
|
struct llarp_router_lookup_job *job)
|
||||||
{
|
{
|
||||||
job->dht = ctx;
|
job->dht = ctx;
|
||||||
job->found = false;
|
job->found = false;
|
||||||
llarp_logic_queue_job(ctx->parent->logic,
|
llarp_logic_queue_job(ctx->parent->logic,
|
||||||
{job, &llarp::dht::Context::queue_router_lookup});
|
{job, &llarp::dht::Context::queue_router_lookup});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ namespace llarp
|
|||||||
" when we are not allowing transit");
|
" when we are not allowing transit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
llarp::Info("Got LRCM from ", remote);
|
|
||||||
return AsyncDecrypt(&router->paths);
|
return AsyncDecrypt(&router->paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,6 +72,11 @@ namespace llarp
|
|||||||
return false;
|
return false;
|
||||||
if(!BEncodeWriteDictEntry("i", nextHop, buf))
|
if(!BEncodeWriteDictEntry("i", nextHop, buf))
|
||||||
return false;
|
return false;
|
||||||
|
if(lifetime > 10 && lifetime < 600)
|
||||||
|
{
|
||||||
|
if(!BEncodeWriteDictInt(buf, "i", lifetime))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if(!BEncodeWriteDictEntry("n", tunnelNonce, buf))
|
if(!BEncodeWriteDictEntry("n", tunnelNonce, buf))
|
||||||
return false;
|
return false;
|
||||||
if(!BEncodeWriteDictEntry("r", rxid, buf))
|
if(!BEncodeWriteDictEntry("r", rxid, buf))
|
||||||
@ -107,6 +111,8 @@ namespace llarp
|
|||||||
return false;
|
return false;
|
||||||
if(!BEncodeMaybeReadDictEntry("i", self->nextHop, read, *key, r->buffer))
|
if(!BEncodeMaybeReadDictEntry("i", self->nextHop, read, *key, r->buffer))
|
||||||
return false;
|
return false;
|
||||||
|
if(!BEncodeMaybeReadDictInt("l", self->lifetime, read, *key, r->buffer))
|
||||||
|
return false;
|
||||||
if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key,
|
if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key,
|
||||||
r->buffer))
|
r->buffer))
|
||||||
return false;
|
return false;
|
||||||
@ -247,6 +253,12 @@ namespace llarp
|
|||||||
self->record.work->extendedLifetime, " seconds for ", info);
|
self->record.work->extendedLifetime, " seconds for ", info);
|
||||||
self->hop->lifetime += 1000 * self->record.work->extendedLifetime;
|
self->hop->lifetime += 1000 * self->record.work->extendedLifetime;
|
||||||
}
|
}
|
||||||
|
else if(self->record.lifetime < 600 && self->record.lifetime > 10)
|
||||||
|
{
|
||||||
|
self->hop->lifetime = self->record.lifetime;
|
||||||
|
llarp::Info("LRCM short lifespan set to ", self->hop->lifetime,
|
||||||
|
" seconds for ", info);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check if we really want to accept it
|
// TODO: check if we really want to accept it
|
||||||
self->hop->started = llarp_time_now_ms();
|
self->hop->started = llarp_time_now_ms();
|
||||||
|
61
llarp/routing/dht_message.cpp
Normal file
61
llarp/routing/dht_message.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <llarp/messages/dht.hpp>
|
||||||
|
#include "../router.hpp"
|
||||||
|
|
||||||
|
namespace llarp
|
||||||
|
{
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
DHTMessage::~DHTMessage()
|
||||||
|
{
|
||||||
|
for(auto& msg : M)
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DHTMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
|
||||||
|
{
|
||||||
|
llarp::dht::Key_t from;
|
||||||
|
from.Zero();
|
||||||
|
if(llarp_buffer_eq(key, "M"))
|
||||||
|
{
|
||||||
|
return llarp::dht::DecodeMesssageList(from, val, M);
|
||||||
|
}
|
||||||
|
else if(llarp_buffer_eq(key, "V"))
|
||||||
|
{
|
||||||
|
return bencode_read_integer(val, &V);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DHTMessage::BEncode(llarp_buffer_t* buf) const
|
||||||
|
{
|
||||||
|
if(!bencode_start_dict(buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(!BEncodeWriteDictMsgType(buf, "A", "M"))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictBEncodeList("M", M, buf))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictInt(buf, "V", LLARP_PROTO_VERSION))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return bencode_end(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DHTMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
|
||||||
|
{
|
||||||
|
// set source as us
|
||||||
|
llarp::dht::Key_t us = r->pubkey();
|
||||||
|
for(auto& msg : M)
|
||||||
|
{
|
||||||
|
msg->From = us;
|
||||||
|
if(!r->dht->impl.RelayRequestForPath(from, msg))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace routing
|
||||||
|
} // namespace llarp
|
@ -1,5 +1,7 @@
|
|||||||
|
#include <llarp/messages/dht.hpp>
|
||||||
#include <llarp/messages/path_confirm.hpp>
|
#include <llarp/messages/path_confirm.hpp>
|
||||||
#include <llarp/messages/path_latency.hpp>
|
#include <llarp/messages/path_latency.hpp>
|
||||||
|
#include <llarp/messages/path_transfer.hpp>
|
||||||
#include <llarp/routing/message.hpp>
|
#include <llarp/routing/message.hpp>
|
||||||
|
|
||||||
namespace llarp
|
namespace llarp
|
||||||
@ -40,9 +42,15 @@ namespace llarp
|
|||||||
case 'L':
|
case 'L':
|
||||||
self->msg = new PathLatencyMessage;
|
self->msg = new PathLatencyMessage;
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
self->msg = new DHTMessage;
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
self->msg = new PathConfirmMessage;
|
self->msg = new PathConfirmMessage;
|
||||||
break;
|
break;
|
||||||
|
case 'T':
|
||||||
|
self->msg = new PathTransferMessage;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
llarp::Error("invalid routing message id: ", *strbuf.cur);
|
llarp::Error("invalid routing message id: ", *strbuf.cur);
|
||||||
}
|
}
|
||||||
|
65
llarp/routing/path_transfer.cpp
Normal file
65
llarp/routing/path_transfer.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include <llarp/messages/path_transfer.hpp>
|
||||||
|
#include "../router.hpp"
|
||||||
|
|
||||||
|
namespace llarp
|
||||||
|
{
|
||||||
|
namespace routing
|
||||||
|
{
|
||||||
|
PathTransferMessage::PathTransferMessage() : IMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PathTransferMessage::~PathTransferMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathTransferMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
|
||||||
|
{
|
||||||
|
bool read = false;
|
||||||
|
if(!BEncodeMaybeReadDictEntry("P", P, read, key, val))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeMaybeReadDictInt("V", V, read, key, val))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeMaybeReadDictEntry("Y", Y, read, key, val))
|
||||||
|
return false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathTransferMessage::BEncode(llarp_buffer_t* buf) const
|
||||||
|
{
|
||||||
|
if(!bencode_start_dict(buf))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictMsgType(buf, "A", "T"))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictEntry("P", P, buf))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictEntry("T", T, buf))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictInt(buf, "V", LLARP_PROTO_VERSION))
|
||||||
|
return false;
|
||||||
|
if(!BEncodeWriteDictEntry("Y", Y, buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return bencode_end(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PathTransferMessage::HandleMessage(IMessageHandler* h,
|
||||||
|
llarp_router* r) const
|
||||||
|
{
|
||||||
|
auto path = r->paths.GetByUpstream(r->pubkey(), P);
|
||||||
|
if(path)
|
||||||
|
{
|
||||||
|
return path->HandleDownstream(T.Buffer(), Y, r);
|
||||||
|
}
|
||||||
|
llarp::Warn("No such local path for path transfer src=", from,
|
||||||
|
" dst=", P);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // namespace routing
|
||||||
|
|
||||||
|
} // namespace llarp
|
@ -72,8 +72,8 @@ namespace llarp
|
|||||||
|
|
||||||
r->crypto.xchacha20(buf, pathKey, Y);
|
r->crypto.xchacha20(buf, pathKey, Y);
|
||||||
msg->X = buf;
|
msg->X = buf;
|
||||||
llarp::Info("relay ", msg->X.size(), " bytes downstream from ",
|
llarp::Debug("relay ", msg->X.size(), " bytes downstream from ",
|
||||||
info.upstream, " to ", info.downstream);
|
info.upstream, " to ", info.downstream);
|
||||||
return r->SendToOrQueue(info.downstream, msg);
|
return r->SendToOrQueue(info.downstream, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,8 +93,8 @@ namespace llarp
|
|||||||
msg->Y = Y;
|
msg->Y = Y;
|
||||||
|
|
||||||
msg->X = buf;
|
msg->X = buf;
|
||||||
llarp::Info("relay ", msg->X.size(), " bytes upstream from ",
|
llarp::Debug("relay ", msg->X.size(), " bytes upstream from ",
|
||||||
info.downstream, " to ", info.upstream);
|
info.downstream, " to ", info.upstream);
|
||||||
return r->SendToOrQueue(info.upstream, msg);
|
return r->SendToOrQueue(info.upstream, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +113,6 @@ namespace llarp
|
|||||||
{
|
{
|
||||||
llarp::routing::PathLatencyMessage reply;
|
llarp::routing::PathLatencyMessage reply;
|
||||||
reply.L = msg->T;
|
reply.L = msg->T;
|
||||||
llarp::Info("got latency message ", msg->T);
|
|
||||||
return SendRoutingMessage(&reply, r);
|
return SendRoutingMessage(&reply, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <llarp/dht.hpp>
|
#include <llarp/dht.hpp>
|
||||||
|
|
||||||
using Node = llarp::dht::Node;
|
using Key_t = llarp::dht::Key_t;
|
||||||
using Key_t = llarp::dht::Key_t;
|
|
||||||
using Bucket = llarp::dht::Bucket;
|
|
||||||
|
|
||||||
class KademliaDHTTest : public ::testing::Test
|
class KademliaDHTTest : public ::testing::Test
|
||||||
{
|
{
|
||||||
@ -19,12 +17,12 @@ class KademliaDHTTest : public ::testing::Test
|
|||||||
SetUp()
|
SetUp()
|
||||||
{
|
{
|
||||||
us.Fill(16);
|
us.Fill(16);
|
||||||
nodes = new Bucket(us);
|
nodes = new llarp::dht::Bucket< llarp::dht::RCNode >(us);
|
||||||
size_t numNodes = 10;
|
size_t numNodes = 10;
|
||||||
byte_t fill = 1;
|
byte_t fill = 1;
|
||||||
while(numNodes)
|
while(numNodes)
|
||||||
{
|
{
|
||||||
Node n;
|
llarp::dht::RCNode n;
|
||||||
n.ID.Fill(fill);
|
n.ID.Fill(fill);
|
||||||
nodes->PutNode(n);
|
nodes->PutNode(n);
|
||||||
--numNodes;
|
--numNodes;
|
||||||
@ -38,15 +36,15 @@ class KademliaDHTTest : public ::testing::Test
|
|||||||
delete nodes;
|
delete nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket* nodes = nullptr;
|
llarp::dht::Bucket< llarp::dht::RCNode >* nodes = nullptr;
|
||||||
Key_t us;
|
llarp::dht::Key_t us;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(KademliaDHTTest, TestBucketFindClosest)
|
TEST_F(KademliaDHTTest, TestBucketFindClosest)
|
||||||
{
|
{
|
||||||
Key_t result;
|
llarp::dht::Key_t result;
|
||||||
Key_t target;
|
llarp::dht::Key_t target;
|
||||||
Key_t oldResult;
|
llarp::dht::Key_t oldResult;
|
||||||
target.Fill(5);
|
target.Fill(5);
|
||||||
ASSERT_TRUE(nodes->FindClosest(target, result));
|
ASSERT_TRUE(nodes->FindClosest(target, result));
|
||||||
ASSERT_TRUE(target == result);
|
ASSERT_TRUE(target == result);
|
||||||
@ -61,13 +59,13 @@ TEST_F(KademliaDHTTest, TestBucketRandomzied)
|
|||||||
size_t moreNodes = 100;
|
size_t moreNodes = 100;
|
||||||
while(moreNodes--)
|
while(moreNodes--)
|
||||||
{
|
{
|
||||||
Node n;
|
llarp::dht::RCNode n;
|
||||||
n.ID.Randomize();
|
n.ID.Randomize();
|
||||||
nodes->PutNode(n);
|
nodes->PutNode(n);
|
||||||
}
|
}
|
||||||
Key_t result;
|
llarp::dht::Key_t result;
|
||||||
Key_t target;
|
llarp::dht::Key_t target;
|
||||||
Key_t oldResult;
|
llarp::dht::Key_t oldResult;
|
||||||
target.Randomize();
|
target.Randomize();
|
||||||
ASSERT_TRUE(nodes->FindClosest(target, result));
|
ASSERT_TRUE(nodes->FindClosest(target, result));
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user