Merge remote-tracking branch 'origin/master' into dev

pull/174/head
Jeff Becker 6 years ago
commit 8c8172aeb1
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -600,26 +600,30 @@ set(DNS_SRC
)
set(TEST_SRC
test/main.cpp
test/alignedbuffer_unittest.cpp
test/base32_unittest.cpp
test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
test/exit_unittest.cpp
test/hiddenservice_unittest.cpp
test/traffic_transfer_unittest.cpp
test/main.cpp
test/net_unittest.cpp
test/obtain_exit_unittest.cpp
test/pq_unittest.cpp
<<<<<<< HEAD
test/net_unittest.cpp
test/utp_unittest.cpp
=======
>>>>>>> origin/master
test/test_dns_unit.cpp
test/test_dnsc_unit.cpp
test/test_dnsd_unit.cpp
test/test_dnslib.cpp
test/test_llarp_queue.cpp
test/test_llarp_aligned.cpp
test/test_llarp_queue_manager.cpp
test/test_llarp_queue.cpp
test/test_llarp_thread_pool.cpp
test/test_service_address.cpp
test/traffic_transfer_unittest.cpp
)
set(TEST_EXE testAll)

@ -73,7 +73,7 @@ namespace llarp
size_t
operator()(const AddressInfo& addr) const
{
return *addr.pubkey.data_l();
return AlignedBuffer< PUBKEYSIZE >::Hash()(addr.pubkey);
}
};
};

@ -5,50 +5,67 @@
#include <encode.hpp>
#include <logger.hpp>
#include <array>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <memory>
#include <numeric>
#include <type_traits>
#include <algorithm>
extern "C"
{
extern void
randombytes(unsigned char* const ptr, unsigned long long sz);
extern void
sodium_memzero(void* const ptr, const size_t sz);
extern int
sodium_is_zero(const unsigned char* ptr, size_t sz);
}
namespace llarp
{
/// aligned buffer that is sz bytes long and aligns to the nears Long_t
template < size_t sz, bool randomize = false, typename Long_t = uint64_t >
/// aligned buffer that is sz bytes long and aligns to the nearest Alignment
template < size_t sz >
struct AlignedBuffer
{
static constexpr size_t SIZE = sz;
using Data = std::array< byte_t, SIZE >;
AlignedBuffer()
{
if(randomize)
Randomize();
else
Zero();
new(&val) Data;
Zero();
}
AlignedBuffer(const byte_t* data)
{
new(&val) Data;
auto& b = as_array();
for(size_t idx = 0; idx < sz; ++idx)
{
b[idx] = data[idx];
}
}
AlignedBuffer(const Data& buf)
{
new(&val) Data;
std::copy(buf.begin(), buf.end(), as_array().begin());
}
AlignedBuffer&
operator=(const byte_t* data)
{
auto& b = as_array();
for(size_t idx = 0; idx < sz; ++idx)
{
b[idx] = data[idx];
}
return *this;
}
friend std::ostream&
operator<<(std::ostream& out, const AlignedBuffer& self)
{
char tmp[(1 + sz) * 2] = {0};
char tmp[(sz * 2) + 1] = {0};
return out << HexEncode(self, tmp);
}
@ -57,75 +74,72 @@ namespace llarp
operator~() const
{
AlignedBuffer< sz > ret;
size_t idx = 0;
while(idx < sz / sizeof(Long_t))
{
ret.data_l()[idx] = ~data_l()[idx];
++idx;
}
std::transform(as_array().begin(), as_array().end(),
ret.as_array().begin(), [](byte_t a) { return ~a; });
return ret;
}
bool
operator==(const AlignedBuffer& other) const
{
return memcmp(b, other.b, sz) == 0;
return as_array() == other.as_array();
}
bool
operator!=(const AlignedBuffer& other) const
{
return !(*this == other);
return as_array() != other.as_array();
}
bool
operator<(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) < 0;
return as_array() < other.as_array();
}
bool
operator>(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) > 0;
return as_array() > other.as_array();
}
bool
operator<=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) <= 0;
return as_array() <= other.as_array();
}
bool
operator>=(const AlignedBuffer& other) const
{
return memcmp(l, other.l, sz) >= 0;
return as_array() >= other.as_array();
}
AlignedBuffer
operator^(const AlignedBuffer& other) const
{
AlignedBuffer< sz > ret;
for(size_t idx = 0; idx < sz / sizeof(Long_t); ++idx)
ret.l[idx] = l[idx] ^ other.l[idx];
std::transform(as_array().begin(), as_array().end(),
other.as_array().begin(), ret.as_array().begin(),
std::bit_xor< byte_t >());
return ret;
}
AlignedBuffer&
operator^=(const AlignedBuffer& other)
{
for(size_t idx = 0; idx < sz / sizeof(Long_t); ++idx)
l[idx] ^= other.l[idx];
return *this;
}
// Mutate in place instead.
// Well defined for std::transform,
size_t
size() const
{
return sz;
for(size_t i = 0; i < as_array().size(); ++i)
{
as_array()[i] ^= other.as_array()[i];
}
return *this;
}
size_t
static constexpr size_t
size()
{
return sz;
@ -134,66 +148,78 @@ namespace llarp
void
Fill(byte_t f)
{
for(size_t idx = 0; idx < sz; ++idx)
b[idx] = f;
as_array().fill(f);
}
Data&
as_array()
{
return reinterpret_cast< Data& >(val);
}
const Data&
as_array() const
{
return reinterpret_cast< const Data& >(val);
}
bool
IsZero() const
{
return sodium_is_zero(b, sz) != 0;
auto notZero = [](byte_t b) { return b != 0; };
return std::find_if(as_array().begin(), as_array().end(), notZero)
== as_array().end();
}
void
Zero()
{
sodium_memzero(l, sz);
as_array().fill(0);
}
void
Randomize()
{
randombytes(b, sz);
randombytes(as_array().data(), SIZE);
}
byte_t*
data()
{
return b;
return as_array().data();
}
const byte_t*
data() const
{
return b;
return as_array().data();
}
Long_t*
data_l()
operator const byte_t*() const
{
return l;
return as_array().data();
}
const Long_t*
data_l() const
operator byte_t*()
{
return l;
return as_array().data();
}
operator const byte_t*() const
operator const Data&() const
{
return b;
return as_array();
}
operator byte_t*()
operator Data&()
{
return b;
return as_array();
}
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, b, sz);
return bencode_write_bytestring(buf, as_array().data(), sz);
}
bool
@ -201,13 +227,15 @@ namespace llarp
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
{
return false;
}
if(strbuf.sz != sz)
{
llarp::LogError("bdecode buffer size missmatch ", strbuf.sz, "!=", sz);
return false;
}
memcpy(b, strbuf.base, sz);
memcpy(as_array().data(), strbuf.base, sz);
return true;
}
@ -221,17 +249,18 @@ namespace llarp
struct Hash
{
size_t
operator()(const AlignedBuffer< sz, randomize, Long_t >& buf) const
operator()(const AlignedBuffer& buf) const
{
return buf.l[0];
return std::accumulate(buf.as_array().begin(), buf.as_array().end(), 0,
std::bit_xor< size_t >());
}
};
protected:
union {
byte_t b[sz];
Long_t l[(sz / sizeof(Long_t)) + (sz % sizeof(Long_t))];
};
private:
using AlignedStorage =
typename std::aligned_storage< sizeof(Data),
alignof(std::max_align_t) >::type;
AlignedStorage val;
};
} // namespace llarp

@ -669,7 +669,12 @@ namespace llarp
"cannot handle exploritory router lookup, no dht peers");
return false;
}
size_t want = std::min(size_t(4), nodeCount);
llarp::LogDebug("We have ", nodes->Size(), " connected nodes into the DHT");
// ourKey should never be in the connected list
// requester is likely in the connected list
// 4 or connection nodes (minus a potential requestor), whatever is less
size_t want = std::min(size_t(4), nodeCount - 1);
llarp::LogDebug("We want ", want, " connected nodes in the DHT");
if(!nodes->GetManyNearExcluding(t, found, want,
std::set< Key_t >{ourKey, requester}))
{

@ -8,6 +8,12 @@ namespace llarp
{
}
void
DHTImmeidateMessage::Clear()
{
msgs.clear();
}
bool
DHTImmeidateMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf)
{
@ -60,8 +66,9 @@ namespace llarp
bool
DHTImmeidateMessage::HandleMessage(llarp::Router *router) const
{
DHTImmeidateMessage reply(session);
bool result = true;
DHTImmeidateMessage reply;
reply.session = session;
bool result = true;
for(auto &msg : msgs)
{
result &= msg->HandleMessage(router->dht, reply.msgs);

@ -3,17 +3,24 @@
#include <aligned.hpp>
#include <array>
namespace llarp
{
namespace dht
{
struct Key_t : public llarp::AlignedBuffer< 32 >
{
Key_t(const byte_t* val) : llarp::AlignedBuffer< 32 >(val)
Key_t(const byte_t* buf) : llarp::AlignedBuffer< SIZE >(buf)
{
}
Key_t(const std::array< byte_t, SIZE >& val)
: llarp::AlignedBuffer< SIZE >(val.data())
{
}
Key_t() : llarp::AlignedBuffer< 32 >()
Key_t() : llarp::AlignedBuffer< SIZE >()
{
}
@ -21,33 +28,34 @@ namespace llarp
operator^(const Key_t& other) const
{
Key_t dist;
for(size_t idx = 0; idx < (size() / sizeof(l[0])); ++idx)
dist.l[idx] = l[idx] ^ other.l[idx];
std::transform(as_array().begin(), as_array().end(),
other.as_array().begin(), dist.as_array().begin(),
std::bit_xor< byte_t >());
return dist;
}
bool
operator==(const Key_t& other) const
{
return memcmp(data(), other.data(), 32) == 0;
return memcmp(data(), other.data(), SIZE) == 0;
}
bool
operator!=(const Key_t& other) const
{
return memcmp(data(), other.data(), 32) != 0;
return memcmp(data(), other.data(), SIZE) != 0;
}
bool
operator<(const Key_t& other) const
{
return memcmp(data(), other.data(), 32) < 0;
return memcmp(data(), other.data(), SIZE) < 0;
}
bool
operator>(const Key_t& other) const
{
return memcmp(data(), other.data(), 32) > 0;
return memcmp(data(), other.data(), SIZE) > 0;
}
};
} // namespace dht

@ -41,7 +41,7 @@ decode_request_name(const std::string &name, llarp::AlignedBuffer< 32 > &addr,
auto pos = name.find(".snode");
if(pos != std::string::npos)
{
if(!llarp::HexDecode(name.substr(0, pos).c_str(), serviceAddr.data(),
if(!llarp::HexDecode(name.substr(0, pos).c_str(), serviceAddr.data().data(),
serviceAddr.size()))
{
return false;
@ -55,7 +55,7 @@ decode_request_name(const std::string &name, llarp::AlignedBuffer< 32 > &addr,
{
return false;
}
addr = serviceAddr.data();
addr = serviceAddr.data().data();
isSNode = false;
}
return true;

@ -1 +1,5 @@
#include <encrypted.hpp>
#include <mem.hpp>
namespace llarp
{
} // namespace llarp

@ -4,6 +4,8 @@
#include <aligned.hpp>
#include <bencode.h>
#include <buffer.h>
#include <mem.hpp>
#include <link_layer.hpp>
#include <vector>
#include <stdexcept>
@ -11,26 +13,66 @@
namespace llarp
{
/// encrypted buffer base type
template < size_t bufsz = MAX_LINK_MSG_SIZE >
struct Encrypted
{
Encrypted(Encrypted&& other);
Encrypted(const Encrypted& other);
Encrypted();
Encrypted(const byte_t* buf, size_t sz);
Encrypted(size_t sz);
~Encrypted();
Encrypted(Encrypted&& other)
{
_sz = std::move(other._sz);
memcpy(_buf, other._buf, _sz);
UpdateBuffer();
}
Encrypted(const Encrypted& other) : Encrypted(other.data(), other.size())
{
UpdateBuffer();
}
Encrypted()
{
Clear();
}
void
Clear()
{
_sz = 0;
UpdateBuffer();
}
Encrypted(const byte_t* buf, size_t sz)
{
if(sz <= bufsz)
{
_sz = sz;
if(buf)
memcpy(_buf, buf, sz);
else
llarp::Zero(_buf, sz);
}
else
_sz = 0;
UpdateBuffer();
}
Encrypted(size_t sz) : Encrypted(nullptr, sz)
{
}
~Encrypted()
{
}
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, data(), size());
return bencode_write_bytestring(buf, _buf, _sz);
}
bool
operator==(const Encrypted& other) const
{
return size() == other.size()
&& memcmp(data(), other.data(), size()) == 0;
return _sz == other._sz && memcmp(_buf, other._buf, _sz) == 0;
}
bool
@ -48,10 +90,10 @@ namespace llarp
Encrypted&
operator=(const llarp_buffer_t& buf)
{
_data.resize(buf.sz);
if(buf.sz)
if(buf.sz <= sizeof(_buf))
{
memcpy(data(), buf.base, buf.sz);
_sz = buf.sz;
memcpy(_buf, buf.base, _sz);
}
UpdateBuffer();
return *this;
@ -60,18 +102,16 @@ namespace llarp
void
Fill(byte_t fill)
{
size_t _sz = size();
size_t idx = 0;
while(idx < _sz)
_data[idx++] = fill;
_buf[idx++] = fill;
}
void
Randomize()
{
size_t _sz = size();
if(_sz)
randombytes(data(), _sz);
randombytes(_buf, _sz);
}
bool
@ -80,10 +120,11 @@ namespace llarp
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz == 0)
if(strbuf.sz > sizeof(_buf))
return false;
_data.resize(strbuf.sz);
memcpy(data(), strbuf.base, size());
_sz = strbuf.sz;
if(_sz)
memcpy(_buf, strbuf.base, _sz);
UpdateBuffer();
return true;
}
@ -103,38 +144,39 @@ namespace llarp
size_t
size()
{
return _data.size();
return _sz;
}
size_t
size() const
{
return _data.size();
return _sz;
}
byte_t*
data()
{
return _data.data();
return _buf;
}
const byte_t*
data() const
{
return _data.data();
return _buf;
}
protected:
void
UpdateBuffer()
{
m_Buffer.base = data();
m_Buffer.cur = data();
m_Buffer.sz = size();
m_Buffer.base = _buf;
m_Buffer.cur = _buf;
m_Buffer.sz = _sz;
}
std::vector< byte_t > _data;
byte_t _buf[bufsz];
size_t _sz;
llarp_buffer_t m_Buffer;
};
}; // namespace llarp
} // namespace llarp
#endif

@ -7,12 +7,6 @@ namespace llarp
{
struct Crypto;
struct EncryptedAck : public Encrypted
{
bool
DecryptInPlace(const byte_t* symkey, const byte_t* nonce,
llarp::Crypto* crypto);
};
} // namespace llarp
#endif

@ -5,39 +5,6 @@
namespace llarp
{
Encrypted::Encrypted()
{
UpdateBuffer();
}
Encrypted::Encrypted(Encrypted&& other)
{
_data = std::move(other._data);
UpdateBuffer();
}
Encrypted::Encrypted(const Encrypted& other)
: Encrypted(other.data(), other.size())
{
}
Encrypted::Encrypted(const byte_t* buf, size_t sz) : _data(sz)
{
if(buf)
memcpy(data(), buf, sz);
else
llarp::Zero(data(), sz);
UpdateBuffer();
}
Encrypted::~Encrypted()
{
}
Encrypted::Encrypted(size_t sz) : Encrypted(nullptr, sz)
{
}
bool
EncryptedFrame::EncryptInPlace(const byte_t* ourSecretKey,
const byte_t* otherPubkey,
@ -63,7 +30,7 @@ namespace llarp
llarp_buffer_t buf;
buf.base = body;
buf.cur = buf.base;
buf.sz = size() - EncryptedFrame::OverheadSize;
buf.sz = size() - EncryptedFrameOverheadSize;
// set our pubkey
memcpy(pubkey, llarp::seckey_topublic(ourSecretKey), PUBKEYSIZE);
@ -101,12 +68,6 @@ namespace llarp
EncryptedFrame::DecryptInPlace(const byte_t* ourSecretKey,
llarp::Crypto* crypto)
{
if(size() <= size_t(EncryptedFrame::OverheadSize))
{
llarp::LogWarn("encrypted frame too small, ", size(),
" <= ", size_t(EncryptedFrame::OverheadSize));
return false;
}
// format of frame is
// <32 bytes keyed hash of following data>
// <32 bytes nonce>
@ -151,7 +112,7 @@ namespace llarp
buf.base = body;
buf.cur = body;
buf.sz = size() - EncryptedFrame::OverheadSize;
buf.sz = size() - EncryptedFrameOverheadSize;
if(!Decrypt(buf, shared, nonce))
{

@ -3,38 +3,37 @@
#include <crypto.h>
#include <encrypted.hpp>
#include <buffer.hpp>
#include <mem.h>
#include <threadpool.h>
namespace llarp
{
struct EncryptedFrame : public Encrypted
{
static constexpr size_t OverheadSize =
PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE;
EncryptedFrame() : EncryptedFrame(256)
{
}
static constexpr size_t EncryptedFrameOverheadSize =
PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE;
static constexpr size_t EncryptedFrameBodySize = 512;
static constexpr size_t EncryptedFrameSize =
EncryptedFrameOverheadSize + EncryptedFrameBodySize;
EncryptedFrame(const EncryptedFrame& other)
: EncryptedFrame(other.data(), other.size())
struct EncryptedFrame : public Encrypted< EncryptedFrameSize >
{
EncryptedFrame() : EncryptedFrame(EncryptedFrameBodySize)
{
}
EncryptedFrame(const byte_t* buf, size_t sz) : Encrypted(buf, sz)
{
}
EncryptedFrame(size_t sz)
: Encrypted(sz + PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE)
: Encrypted< EncryptedFrameSize >(std::min(sz, EncryptedFrameBodySize)
+ EncryptedFrameOverheadSize)
{
UpdateBuffer();
}
EncryptedFrame&
operator=(const EncryptedFrame& other)
{
_data.resize(other.size());
_sz = other._sz;
memcpy(data(), other.data(), size());
UpdateBuffer();
return *this;
}
@ -58,8 +57,8 @@ namespace llarp
AsyncFrameEncrypter< User >* ctx =
static_cast< AsyncFrameEncrypter< User >* >(user);
if(ctx->frame->EncryptInPlace(ctx->seckey, ctx->otherKey, ctx->crypto))
ctx->handler(ctx->frame, ctx->user);
if(ctx->frame.EncryptInPlace(ctx->seckey, ctx->otherKey, ctx->crypto))
ctx->handler(&ctx->frame, ctx->user);
else
{
ctx->handler(nullptr, ctx->user);
@ -69,7 +68,7 @@ namespace llarp
llarp::Crypto* crypto;
byte_t* secretkey;
EncryptHandler handler;
EncryptedFrame* frame;
EncryptedFrame frame;
User* user;
byte_t* otherKey;
@ -84,9 +83,10 @@ namespace llarp
{
// TODO: should we own otherKey?
otherKey = other;
frame = new EncryptedFrame(buf.sz);
memcpy(frame->data() + PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE,
buf.base, buf.sz);
if(buf.sz > EncryptedFrameBodySize)
return;
memcpy(frame.data() + PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE, buf.base,
buf.sz);
user = u;
llarp_threadpool_queue_job(worker, {this, &Encrypt});
}
@ -104,10 +104,10 @@ namespace llarp
AsyncFrameDecrypter< User >* ctx =
static_cast< AsyncFrameDecrypter< User >* >(user);
if(ctx->target->DecryptInPlace(ctx->seckey, ctx->crypto))
if(ctx->target.DecryptInPlace(ctx->seckey, ctx->crypto))
{
auto buf = ctx->target->Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
auto buf = ctx->target.Buffer();
buf->cur = buf->base + EncryptedFrameOverheadSize;
ctx->result(buf, ctx->context);
}
else
@ -124,10 +124,11 @@ namespace llarp
User* context;
llarp::Crypto* crypto;
const byte_t* seckey;
EncryptedFrame* target;
EncryptedFrame target;
void
AsyncDecrypt(llarp_threadpool* worker, EncryptedFrame* frame, User* user)
AsyncDecrypt(llarp_threadpool* worker, const EncryptedFrame& frame,
User* user)
{
target = frame;
context = user;

@ -224,9 +224,9 @@ namespace llarp
}
else if(addr.FromString(qname, ".loki"))
{
if(HasAddress(addr.data()))
if(HasAddress(addr.data().data()))
{
huint32_t ip = ObtainIPForAddr(addr.data(), false);
huint32_t ip = ObtainIPForAddr(addr.data().data(), false);
msg.AddINReply(ip);
}
else
@ -240,8 +240,8 @@ namespace llarp
else if(addr.FromString(qname, ".snode"))
{
// TODO: add hook to EnsurePathToSNode
EnsurePathToSNode(addr.data());
huint32_t ip = ObtainIPForAddr(addr.data(), true);
EnsurePathToSNode(addr.data().data());
huint32_t ip = ObtainIPForAddr(addr.data().data(), true);
msg.AddINReply(ip);
}
else
@ -323,7 +323,7 @@ namespace llarp
{
if(ctx)
{
huint32_t ip = ObtainIPForAddr(addr.data(), false);
huint32_t ip = ObtainIPForAddr(addr.data().data(), false);
request.AddINReply(ip);
}
else
@ -346,9 +346,9 @@ namespace llarp
}
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip);
m_IPToAddr[ip] = addr.data();
m_AddrToIP[addr.data()] = ip;
m_SNodes[addr.data()] = SNode;
m_IPToAddr[ip] = addr.data().data();
m_AddrToIP[addr.data().data()] = ip;
m_SNodes[addr.data().data()] = SNode;
MarkIPActiveForever(ip);
return true;
}
@ -502,9 +502,6 @@ namespace llarp
llarp::LogWarn(Name(), " did not flush packets");
return true;
});
if(m_Exit)
m_Exit->Flush();
FlushSNodeTraffic();
}
bool
@ -642,19 +639,20 @@ namespace llarp
{
// called in the isolated network thread
TunEndpoint *self = static_cast< TunEndpoint * >(tun->user);
// flush user to network
self->FlushSend();
// flush exit traffic queues if it's there
if(self->m_Exit)
self->m_Exit->Flush();
// flush snode traffic
self->FlushSNodeTraffic();
// flush network to user
self->m_NetworkToUserPktQueue.Process([tun](net::IPv4Packet &pkt) {
if(!llarp_ev_tun_async_write(tun, pkt.Buffer()))
llarp::LogWarn("packet dropped");
});
}
void
TunEndpoint::handleNetSend(void *user)
{
TunEndpoint *self = static_cast< TunEndpoint * >(user);
self->FlushSend();
}
void
TunEndpoint::tunifRecvPkt(llarp_tun_io *tun, llarp_buffer_t buf)
{

@ -121,6 +121,12 @@ namespace llarp
return session->GotLIM(this);
}
void
LinkIntroMessage::Clear()
{
rc.Clear();
}
bool
LinkIntroMessage::Sign(
std::function< bool(Signature&, llarp_buffer_t) > signer)

@ -2,6 +2,7 @@
#include <logger.hpp>
#include <messages.hpp>
#include <router_contact.hpp>
#include <link_message_parser.hpp>
namespace llarp
{
@ -45,29 +46,29 @@ namespace llarp
switch(*strbuf.cur)
{
case 'i':
handler->msg = std::make_unique< LinkIntroMessage >(handler->from);
handler->msg = &handler->holder.i;
break;
case 'd':
handler->msg =
std::make_unique< RelayDownstreamMessage >(handler->from);
handler->msg = &handler->holder.d;
break;
case 'u':
handler->msg =
std::make_unique< RelayUpstreamMessage >(handler->from);
handler->msg = &handler->holder.u;
break;
case 'm':
handler->msg = std::make_unique< DHTImmeidateMessage >(handler->from);
handler->msg = &handler->holder.m;
break;
case 'c':
handler->msg = std::make_unique< LR_CommitMessage >(handler->from);
handler->msg = &handler->holder.c;
break;
case 'x':
handler->msg = std::make_unique< DiscardMessage >(handler->from);
handler->msg = &handler->holder.x;
break;
default:
return false;
}
handler->firstkey = false;
handler->msg->Clear();
handler->msg->session = handler->from;
handler->firstkey = false;
return true;
}
// check for last element
@ -107,6 +108,6 @@ namespace llarp
void
InboundMessageParser::Reset()
{
msg.reset(nullptr);
msg = nullptr;
}
} // namespace llarp

@ -19,55 +19,22 @@ namespace llarp
struct ILinkMessage : public IBEncodeMessage
{
/// who did this message come from or is going to
ILinkSession* session;
uint64_t version = 0;
ILinkSession* session = nullptr;
uint64_t version = 0;
ILinkMessage() : ILinkMessage(nullptr)
{
}
ILinkMessage() = default;
ILinkMessage(ILinkSession* from) : session(from)
{
}
virtual ~ILinkMessage()
{
}
virtual bool
HandleMessage(Router* router) const = 0;
};
struct InboundMessageParser
{
InboundMessageParser(Router* router);
dict_reader reader;
static bool
OnKey(dict_reader* r, llarp_buffer_t* buf);
/// start processig message from a link session
bool
ProcessFrom(ILinkSession* from, llarp_buffer_t buf);
/// called when the message is fully read
/// return true when the message was accepted otherwise returns false
bool
MessageDone();
/// resets internal state
void
Reset();
private:
RouterID
GetCurrentFrom();
private:
bool firstkey;
Router* router;
ILinkSession* from = nullptr;
std::unique_ptr< ILinkMessage > msg;
virtual void
Clear() = 0;
};
} // namespace llarp
#endif

@ -0,0 +1,52 @@
#ifndef LLARP_LINK_MESSAGE_PARSER_HPP
#define LLARP_LINK_MESSAGE_PARSER_HPP
#include <link_message.hpp>
#include <messages.hpp>
namespace llarp
{
struct InboundMessageParser
{
InboundMessageParser(Router* router);
dict_reader reader;
static bool
OnKey(dict_reader* r, llarp_buffer_t* buf);
/// start processig message from a link session
bool
ProcessFrom(ILinkSession* from, llarp_buffer_t buf);
/// called when the message is fully read
/// return true when the message was accepted otherwise returns false
bool
MessageDone();
/// resets internal state
void
Reset();
private:
RouterID
GetCurrentFrom();
private:
bool firstkey;
Router* router;
ILinkSession* from = nullptr;
ILinkMessage* msg = nullptr;
struct msg_holder_t
{
LinkIntroMessage i;
RelayDownstreamMessage d;
RelayUpstreamMessage u;
DHTImmeidateMessage m;
LR_CommitMessage c;
DiscardMessage x;
};
msg_holder_t holder;
};
} // namespace llarp
#endif

@ -9,10 +9,6 @@ namespace llarp
{
struct DHTImmeidateMessage : public ILinkMessage
{
DHTImmeidateMessage(ILinkSession* parent) : ILinkMessage(parent)
{
}
DHTImmeidateMessage() : ILinkMessage()
{
}
@ -29,6 +25,9 @@ namespace llarp
bool
HandleMessage(llarp::Router* router) const;
void
Clear() override;
};
} // namespace llarp

@ -10,17 +10,7 @@ namespace llarp
{
struct DiscardMessage final : public ILinkMessage
{
/// who did this message come from or is going to
DiscardMessage() : ILinkMessage(nullptr)
{
}
DiscardMessage(ILinkSession* from) : ILinkMessage(from)
{
}
~DiscardMessage()
DiscardMessage() : ILinkMessage()
{
}
@ -36,6 +26,11 @@ namespace llarp
return bencode_end(buf);
}
void
Clear() override
{
}
bool
DecodeKey(__attribute__((unused)) llarp_buffer_t key,
__attribute__((unused)) llarp_buffer_t* buf) override

@ -16,10 +16,6 @@ namespace llarp
{
}
LinkIntroMessage(ILinkSession* s) : ILinkMessage(s)
{
}
~LinkIntroMessage();
RouterContact rc;
@ -44,6 +40,9 @@ namespace llarp
bool
Verify(llarp::Crypto* c) const;
void
Clear() override;
};
} // namespace llarp

@ -13,7 +13,7 @@ namespace llarp
struct RelayUpstreamMessage : public ILinkMessage
{
PathID_t pathid;
Encrypted X;
Encrypted< MAX_LINK_MSG_SIZE - 128 > X;
TunnelNonce Y;
RelayUpstreamMessage();
@ -21,32 +21,38 @@ namespace llarp
~RelayUpstreamMessage();
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
BEncode(llarp_buffer_t* buf) const;
BEncode(llarp_buffer_t* buf) const override;
bool
HandleMessage(llarp::Router* router) const;
HandleMessage(llarp::Router* router) const override;
void
Clear() override;
};
struct RelayDownstreamMessage : public ILinkMessage
{
PathID_t pathid;
Encrypted X;
Encrypted< MAX_LINK_MSG_SIZE - 128 > X;
TunnelNonce Y;
RelayDownstreamMessage();
RelayDownstreamMessage(ILinkSession* from);
~RelayDownstreamMessage();
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
BEncode(llarp_buffer_t* buf) const;
BEncode(llarp_buffer_t* buf) const override;
bool
HandleMessage(llarp::Router* router) const;
HandleMessage(llarp::Router* router) const override;
void
Clear() override;
};
} // namespace llarp

@ -53,10 +53,6 @@ namespace llarp
{
}
LR_CommitMessage(ILinkSession *from) : ILinkMessage(from)
{
}
~LR_CommitMessage();
void

@ -11,11 +11,12 @@ namespace llarp
{
namespace routing
{
constexpr size_t ExitPadSize = 512 - 48;
constexpr size_t MaxExitMTU = 1500;
constexpr size_t ExitPadSize = 512 - 48;
constexpr size_t MaxExitMTU = 1500;
constexpr size_t ExitOverhead = sizeof(uint64_t);
struct TransferTrafficMessage final : public IMessage
{
std::vector< llarp::Encrypted > X;
std::vector< llarp::Encrypted< MaxExitMTU + ExitOverhead > > X;
size_t _size = 0;
size_t

@ -522,7 +522,7 @@ namespace llarp
Path::Expired(llarp_time_t now) const
{
if(_status == ePathEstablished)
return now - buildStarted > hops[0].lifetime;
return now >= ExpireTime();
else if(_status == ePathBuilding)
return false;
else

@ -25,7 +25,7 @@
#define MAXHOPS (8)
#define DEFAULT_PATH_LIFETIME (10 * 60 * 1000)
#define PATH_BUILD_TIMEOUT (30 * 1000)
#define MESSAGE_PAD_SIZE (512)
#define MESSAGE_PAD_SIZE (128)
#define PATH_ALIVE_TIMEOUT (10 * 1000)
namespace llarp
@ -314,7 +314,7 @@ namespace llarp
void
MarkActive(llarp_time_t now)
{
m_LastRecvMessage = now;
m_LastRecvMessage = std::max(now, m_LastRecvMessage);
}
/// return true if ALL of the specified roles are supported

@ -80,12 +80,13 @@ namespace llarp
record.commkey = llarp::seckey_topublic(hop.commkey);
auto buf = frame.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
buf->cur = buf->base + EncryptedFrameOverheadSize;
// encode record
if(!record.BEncode(buf))
{
// failed to encode?
llarp::LogError("Failed to generate Commit Record");
llarp::DumpBuffer(*buf);
delete ctx;
return;
}

@ -190,7 +190,7 @@ namespace llarp
size_t
operator()(const PathInfo_t& i) const
{
return *i.first.data_l() ^ *i.second.data_l();
return RouterID::Hash()(i.first) ^ PathID_t::Hash()(i.second);
}
};
using Mtx_t = llarp::util::NullMutex;

@ -27,6 +27,19 @@ namespace llarp
return read;
}
void
LR_CommitMessage::Clear()
{
frames[0].Clear();
frames[1].Clear();
frames[2].Clear();
frames[3].Clear();
frames[4].Clear();
frames[5].Clear();
frames[6].Clear();
frames[7].Clear();
}
bool
LR_CommitMessage::BEncode(llarp_buffer_t* buf) const
{
@ -235,7 +248,7 @@ namespace llarp
delete self;
return;
}
buf->cur = buf->base + EncryptedFrame::OverheadSize;
buf->cur = buf->base + EncryptedFrameOverheadSize;
llarp::LogDebug("decrypted LRCM from ", info.downstream);
// successful decrypt
if(!self->record.BDecode(buf))
@ -295,7 +308,7 @@ namespace llarp
frames[5] = self->frames[6];
frames[6] = self->frames[7];
// put our response on the end
frames[7] = EncryptedFrame(sz - EncryptedFrame::OverheadSize);
frames[7] = EncryptedFrame(sz - EncryptedFrameOverheadSize);
// random junk for now
frames[7].Randomize();
self->frames = std::move(frames);
@ -325,7 +338,7 @@ namespace llarp
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(context, decrypter, this);
// decrypt frames async
decrypter->AsyncDecrypt(context->Worker(), &frames->frames[0], frames);
decrypter->AsyncDecrypt(context->Worker(), frames->frames[0], frames);
return true;
}
} // namespace llarp

@ -4,17 +4,18 @@
namespace llarp
{
RelayUpstreamMessage::RelayUpstreamMessage(ILinkSession *from)
: ILinkMessage(from)
RelayUpstreamMessage::RelayUpstreamMessage() : ILinkMessage()
{
}
RelayUpstreamMessage::RelayUpstreamMessage() : ILinkMessage()
RelayUpstreamMessage::~RelayUpstreamMessage()
{
}
RelayUpstreamMessage::~RelayUpstreamMessage()
void
RelayUpstreamMessage::Clear()
{
X.Clear();
}
bool
@ -63,18 +64,20 @@ namespace llarp
return false;
}
RelayDownstreamMessage::RelayDownstreamMessage(ILinkSession *from)
: ILinkMessage(from)
RelayDownstreamMessage::RelayDownstreamMessage() : ILinkMessage()
{
}
RelayDownstreamMessage::RelayDownstreamMessage() : ILinkMessage()
RelayDownstreamMessage::~RelayDownstreamMessage()
{
}
RelayDownstreamMessage::~RelayDownstreamMessage()
void
RelayDownstreamMessage::Clear()
{
X.Clear();
}
bool
RelayDownstreamMessage::BEncode(llarp_buffer_t *buf) const
{

@ -754,7 +754,8 @@ namespace llarp
if(N < minRequiredRouters)
{
llarp::LogInfo("We need at least ", minRequiredRouters,
" service nodes to build paths but we have ", N);
" service nodes to build paths but we have ", N,
" in nodedb");
// TODO: only connect to random subset
if(bootstrapRCList.size())
{

@ -12,7 +12,7 @@
#include <fs.hpp>
#include <handlers/tun.hpp>
#include <link_layer.hpp>
#include <link_message.hpp>
#include <link_message_parser.hpp>
#include <logic.hpp>
#include <mem.hpp>
#include <nodedb.hpp>

@ -7,11 +7,19 @@ namespace llarp
{
struct RouterID : public AlignedBuffer< 32 >
{
RouterID() : AlignedBuffer< 32 >()
static constexpr size_t SIZE = 32;
using Data = std::array< byte_t, SIZE >;
RouterID() : AlignedBuffer< SIZE >()
{
}
RouterID(const byte_t* buf) : AlignedBuffer< SIZE >(buf)
{
}
RouterID(const byte_t* buf) : AlignedBuffer< 32 >(buf)
RouterID(const Data& data) : AlignedBuffer< SIZE >(data)
{
}
@ -24,7 +32,7 @@ namespace llarp
RouterID&
operator=(const byte_t* ptr)
{
memcpy(data(), ptr, 32);
memcpy(data(), ptr, SIZE);
return *this;
}
@ -34,7 +42,7 @@ namespace llarp
return out << id.ToString();
}
using Hash = AlignedBuffer< 32 >::Hash;
using Hash = AlignedBuffer< SIZE >::Hash;
};
} // namespace llarp

@ -163,8 +163,8 @@ namespace llarp
{
router->lokinetRouters.clear();
for(const auto& pk : list)
router->lokinetRouters.insert(
std::make_pair(pk, std::numeric_limits< llarp_time_t >::max()));
router->lokinetRouters.insert(std::make_pair(
pk.data(), std::numeric_limits< llarp_time_t >::max()));
llarp::LogInfo("updated service node list, we have ",
router->lokinetRouters.size(), " authorized routers");
}
@ -225,7 +225,7 @@ namespace llarp
peer.SetObject();
abyss::json::Value ident_val, addr_val;
auto ident = session->GetPubKey().ToHex();
auto ident = RouterID(session->GetPubKey()).ToString();
ident_val.SetString(ident.c_str(), alloc);
auto addr = session->GetRemoteEndpoint().ToString();

@ -121,8 +121,7 @@ namespace llarp
}
/// calculate our address
bool
CalculateAddress(byte_t* buf) const;
bool CalculateAddress(std::array< byte_t, 32 >& data) const;
bool
BDecode(llarp_buffer_t* buf) override

@ -86,7 +86,7 @@ namespace llarp
size_t
operator()(const Introduction& i) const
{
return *i.router.data_l() ^ *i.pathID.data_l();
return PubKey::Hash()(i.router) ^ PathID_t::Hash()(i.pathID);
}
};
};

@ -5,6 +5,8 @@
#include <dht/key.hpp>
#include <router_id.hpp>
#include <functional>
#include <numeric>
#include <string>
namespace llarp
@ -14,6 +16,10 @@ namespace llarp
/// Snapp/Snode Address
struct Address
{
static constexpr size_t SIZE = 32;
using Data = std::array< byte_t, SIZE >;
std::string
ToString(const char* tld = ".loki") const;
@ -27,12 +33,12 @@ namespace llarp
Address(const byte_t* buf)
{
memcpy(b, buf, 32);
std::copy(buf, buf + SIZE, b.begin());
}
Address(const Address& other)
{
memcpy(b, other.b, 32);
b = other.b;
}
byte_t& operator[](size_t idx)
@ -48,7 +54,7 @@ namespace llarp
bool
BEncode(llarp_buffer_t* buf) const
{
return bencode_write_bytestring(buf, b, 32);
return bencode_write_bytestring(buf, b.data(), SIZE);
}
bool
@ -57,49 +63,39 @@ namespace llarp
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
if(strbuf.sz != 32)
if(strbuf.sz != SIZE)
{
llarp::LogErrorTag("Address::BDecode",
"bdecode buffer size missmatch ", strbuf.sz,
"!=32");
return false;
}
memcpy(b, strbuf.base, 32);
std::copy(strbuf.base, strbuf.base + SIZE, b.begin());
return true;
}
size_t
size() const
static constexpr size_t
size()
{
return 32;
return SIZE;
}
bool
IsZero() const
{
size_t sz = 4;
while(sz)
{
if(l[--sz])
return false;
}
return true;
return b == Data{};
}
void
Zero()
{
size_t sz = 4;
while(sz)
{
l[--sz] = 0;
}
b.fill(0);
}
bool
operator<(const Address& other) const
{
return memcmp(data(), other.data(), 32) < 0;
return data() < other.data();
}
friend std::ostream&
@ -111,7 +107,7 @@ namespace llarp
bool
operator==(const Address& other) const
{
return memcmp(data(), other.data(), 32) == 0;
return data() == other.data();
}
bool
@ -121,11 +117,7 @@ namespace llarp
}
Address&
operator=(const Address& other)
{
memcpy(data(), other.data(), 32);
return *this;
}
operator=(const Address& other) = default;
const dht::Key_t
ToKey() const
@ -136,41 +128,33 @@ namespace llarp
const RouterID
ToRouter() const
{
return RouterID(data());
return RouterID(data().data());
}
const byte_t*
const Data&
data() const
{
return b;
}
byte_t*
Data&
data()
{
return b;
}
const uint64_t*
data_l() const
{
return l;
}
struct Hash
{
size_t
operator()(const Address& buf) const
{
return *buf.data_l();
return std::accumulate(buf.data().begin(), buf.data().end(), 0,
std::bit_xor< size_t >());
}
};
private:
union {
byte_t b[32];
uint64_t l[4];
};
Data b;
};
} // namespace service

@ -538,7 +538,7 @@ namespace llarp
Endpoint::PublishIntroSet(llarp::Router* r)
{
// publish via near router
RouterID location = m_Identity.pub.Addr().data();
RouterID location = m_Identity.pub.Addr().data().data();
auto path = GetEstablishedPathClosestTo(location);
return path && PublishIntroSetVia(r, path);
}
@ -833,9 +833,10 @@ namespace llarp
if(msg->proto == eProtocolTraffic)
{
auto buf = llarp::Buffer(msg->payload);
return HandleWriteIPPacket(buf,
std::bind(&Endpoint::ObtainIPForAddr, this,
msg->sender.Addr().data(), false));
return HandleWriteIPPacket(
buf,
std::bind(&Endpoint::ObtainIPForAddr, this,
msg->sender.Addr().data().data(), false));
}
else if(msg->proto == eProtocolText)
{

@ -56,15 +56,14 @@ namespace llarp
return m_CachedAddr.ToString();
}
bool
ServiceInfo::CalculateAddress(byte_t* addr) const
bool ServiceInfo::CalculateAddress(std::array< byte_t, 32 >& data) const
{
byte_t tmp[256] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
if(!BEncode(&buf))
return false;
return crypto_generichash_blake2b(addr, 32, buf.base, buf.cur - buf.base,
nullptr, 0)
return crypto_generichash_blake2b(data.data(), data.size(), buf.base,
buf.cur - buf.base, nullptr, 0)
!= -1;
}

@ -157,8 +157,8 @@ namespace llarp
const byte_t* sharedkey,
ProtocolMessage& msg) const
{
Encrypted tmp = D;
auto buf = tmp.Buffer();
Encrypted_t tmp = D;
auto buf = tmp.Buffer();
crypto->xchacha20(*buf, sharedkey, N);
return msg.BDecode(buf);
}

@ -59,8 +59,9 @@ namespace llarp
/// outer message
struct ProtocolFrame final : public llarp::routing::IMessage
{
using Encrypted_t = llarp::Encrypted< 2048 >;
llarp::PQCipherBlock C;
llarp::Encrypted D;
Encrypted_t D;
llarp::KeyExchangeNonce N;
llarp::Signature Z;
llarp::service::ConvoTag T;

@ -54,14 +54,7 @@ namespace llarp
return ToString().empty();
}
struct Hash
{
std::size_t
operator()(const Tag& t) const
{
return *t.data_l();
}
};
using Hash = AlignedBuffer< SIZE >::Hash;
};
} // namespace service
} // namespace llarp

@ -2,6 +2,10 @@
# this shell script will be replaced by a proper program in the future (probably)
#
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
if [ -z "$1" ]
then
url="https://i2p.rocks/i2procks.signed"
@ -16,4 +20,6 @@ then
mkdir $HOME/.lokinet
fi
wget -O $HOME/.lokinet/bootstrap.signed "$url" || echo "failed to download bootstrap from $url"
# MacOS does not have wget without homebrew but does have curl
# Rick also had indicated most BSDs have curl too
curl "$url" > $HOME/.lokinet/bootstrap.signed; echo -e "${GREEN}lokinet successfully bootstrapped${NC}" || echo -e "${RED}failed to download bootstrap from $url${NC}"

@ -1,33 +0,0 @@
#include <gtest/gtest.h>
#include <crypto.hpp>
using Buffer_t = llarp::AlignedBuffer< 32 >;
using Map_t = std::unordered_map< Buffer_t, int, Buffer_t::Hash >;
struct AlignedBufferTest : public ::testing::Test
{
AlignedBufferTest() : crypto(llarp::Crypto::sodium{})
{
}
llarp::Crypto crypto;
};
TEST_F(AlignedBufferTest, TestHash)
{
Buffer_t k, other_k;
k.Randomize();
other_k.Randomize();
Map_t m;
ASSERT_TRUE(m.empty());
ASSERT_TRUE(m.emplace(k, 1).second);
ASSERT_TRUE(m.find(k) != m.end());
ASSERT_TRUE(m[k] == 1);
ASSERT_FALSE(m.find(other_k) != m.end());
ASSERT_TRUE(m.size() == 1);
Buffer_t k_copy = k;
ASSERT_FALSE(m.emplace(k_copy, 2).second);
ASSERT_FALSE(m[k_copy] == 2);
ASSERT_TRUE(m[k_copy] == 1);
};

@ -11,11 +11,10 @@ using LRCR = llarp::LR_CommitRecord;
class FrameTest : public ::testing::Test
{
public:
llarp::Crypto crypto;
llarp::Crypto crypto;
SecretKey alice, bob;
FrameTest()
: crypto(llarp::Crypto::sodium{})
FrameTest() : crypto(llarp::Crypto::sodium{})
{
}
@ -47,12 +46,12 @@ TEST_F(FrameTest, TestFrameCrypto)
record.txid.Fill(4);
auto buf = f.Buffer();
buf->cur = buf->base + EncryptedFrame::OverheadSize;
buf->cur = buf->base + llarp::EncryptedFrameOverheadSize;
ASSERT_TRUE(record.BEncode(buf));
// rewind buffer
buf->cur = buf->base + EncryptedFrame::OverheadSize;
buf->cur = buf->base + llarp::EncryptedFrameOverheadSize;
// encrypt to alice
ASSERT_TRUE(f.EncryptInPlace(alice, llarp::seckey_topublic(bob), &crypto));
// decrypt from alice

@ -6,7 +6,7 @@
struct AbyssTestBase : public ::testing::Test
{
llarp::Crypto crypto;
llarp::Crypto crypto;
llarp_threadpool* threadpool = nullptr;
llarp_ev_loop* loop = nullptr;
llarp::Logic* logic = nullptr;
@ -15,6 +15,10 @@ struct AbyssTestBase : public ::testing::Test
const std::string method = "test.method";
bool called = false;
AbyssTestBase() : crypto(llarp::Crypto::sodium{})
{
}
void
AssertMethod(const std::string& meth) const
{
@ -25,7 +29,6 @@ struct AbyssTestBase : public ::testing::Test
SetUp()
{
// for llarp::randint
llarp_crypto_init(&crypto);
}
static void
@ -41,7 +44,7 @@ struct AbyssTestBase : public ::testing::Test
{
threadpool = llarp_init_same_process_threadpool();
llarp_ev_loop_alloc(&loop);
logic = llarp_init_single_process_logic(threadpool);
logic = new llarp::Logic(threadpool);
sockaddr_in addr;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@ -75,7 +78,8 @@ struct AbyssTestBase : public ::testing::Test
{
if(loop && threadpool && logic)
{
llarp_free_logic(&logic);
delete logic;
logic = nullptr;
llarp_ev_loop_free(&loop);
llarp_free_threadpool(&threadpool);
}

@ -0,0 +1,232 @@
#include <gtest/gtest.h>
#include <aligned.hpp>
#include <crypto.hpp>
#include <iostream>
#include <sstream>
#include <type_traits>
#include <unordered_map>
using TestSizes =
::testing::Types< std::integral_constant< std::size_t, 2 >,
std::integral_constant< std::size_t, 3 >,
std::integral_constant< std::size_t, 4 >,
std::integral_constant< std::size_t, 8 >,
std::integral_constant< std::size_t, 16 >,
std::integral_constant< std::size_t, 32 >,
std::integral_constant< std::size_t, 64 >,
std::integral_constant< std::size_t, 1024 > >;
template < typename T >
struct AlignedBufferTest : public ::testing::Test
{
AlignedBufferTest() : crypto(llarp::Crypto::sodium{})
{
}
llarp::Crypto crypto;
};
TYPED_TEST_CASE(AlignedBufferTest, TestSizes);
TYPED_TEST(AlignedBufferTest, Constructor)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
EXPECT_EQ(b.size(), TypeParam::value);
}
TYPED_TEST(AlignedBufferTest, CopyConstructor)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
Buffer c = b;
EXPECT_TRUE(c.IsZero());
c.Fill(1);
EXPECT_FALSE(c.IsZero());
Buffer d = c;
EXPECT_FALSE(d.IsZero());
}
TYPED_TEST(AlignedBufferTest, AltConstructors)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
b.Fill(2);
Buffer c(b.as_array());
EXPECT_FALSE(c.IsZero());
Buffer d(c.data());
EXPECT_FALSE(d.IsZero());
}
TYPED_TEST(AlignedBufferTest, Assignment)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
Buffer c;
c = b;
EXPECT_TRUE(c.IsZero());
c.Fill(1);
EXPECT_FALSE(c.IsZero());
Buffer d;
d = c;
EXPECT_FALSE(d.IsZero());
}
TYPED_TEST(AlignedBufferTest, StreamOut)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
std::stringstream stream;
stream << b;
EXPECT_EQ(stream.str(), std::string(TypeParam::value * 2, '0'));
stream.str("");
b.Fill(255);
stream << b;
EXPECT_EQ(stream.str(), std::string(TypeParam::value * 2, 'f'));
}
TYPED_TEST(AlignedBufferTest, BitwiseNot)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
Buffer c = ~b;
EXPECT_FALSE(c.IsZero());
for(auto val : c.as_array())
{
EXPECT_EQ(255, val);
}
Buffer d = ~c;
EXPECT_TRUE(d.IsZero());
}
TYPED_TEST(AlignedBufferTest, Operators)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
Buffer c = b;
EXPECT_EQ(b, c);
EXPECT_GE(b, c);
EXPECT_LE(b, c);
EXPECT_GE(c, b);
EXPECT_LE(c, b);
c.Fill(1);
EXPECT_NE(b, c);
EXPECT_LT(b, c);
EXPECT_GT(c, b);
}
TYPED_TEST(AlignedBufferTest, Xor)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
Buffer c;
b.Fill(255);
c.Fill(255);
EXPECT_FALSE(b.IsZero());
EXPECT_FALSE(c.IsZero());
Buffer d = b ^ c;
// 1 ^ 1 = 0
EXPECT_TRUE(d.IsZero());
// Verify unchanged
EXPECT_FALSE(b.IsZero());
EXPECT_FALSE(c.IsZero());
Buffer e, f;
e.Fill(255);
Buffer g = e ^ f;
// 1 ^ 0 = 1
EXPECT_FALSE(g.IsZero());
Buffer h, i;
i.Fill(255);
Buffer j = h ^ i;
// 0 ^ 1 = 1
EXPECT_FALSE(j.IsZero());
}
TYPED_TEST(AlignedBufferTest, XorAssign)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b, c;
b.Fill(255);
c.Fill(255);
EXPECT_FALSE(b.IsZero());
EXPECT_FALSE(c.IsZero());
b ^= c;
EXPECT_TRUE(b.IsZero());
}
TYPED_TEST(AlignedBufferTest, Zero)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
Buffer b;
EXPECT_TRUE(b.IsZero());
b.Fill(127);
EXPECT_FALSE(b.IsZero());
b.Zero();
EXPECT_TRUE(b.IsZero());
}
TYPED_TEST(AlignedBufferTest, TestHash)
{
using Buffer = llarp::AlignedBuffer< TypeParam::value >;
using Map_t = std::unordered_map< Buffer, int, typename Buffer::Hash >;
Buffer k, other_k;
k.Randomize();
other_k.Randomize();
Map_t m;
EXPECT_TRUE(m.empty());
EXPECT_TRUE(m.emplace(k, 1).second);
EXPECT_TRUE(m.find(k) != m.end());
EXPECT_TRUE(m[k] == 1);
EXPECT_FALSE(m.find(other_k) != m.end());
EXPECT_TRUE(m.size() == 1);
Buffer k_copy = k;
EXPECT_FALSE(m.emplace(k_copy, 2).second);
EXPECT_FALSE(m[k_copy] == 2);
EXPECT_TRUE(m[k_copy] == 1);
};
// TEST_P(Copy, )
Loading…
Cancel
Save