mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
Replace dict_reader/list_reader with version which doesn't involve indirection
This commit is contained in:
parent
83ede0c961
commit
7ca0927d8f
|
@ -1,5 +1,6 @@
|
|||
#include <dht/context.hpp>
|
||||
|
||||
#include <util/bencode.hpp>
|
||||
#include <dht/messages/findintro.hpp>
|
||||
#include <dht/messages/findrouter.hpp>
|
||||
#include <dht/messages/gotintro.hpp>
|
||||
|
@ -17,57 +18,57 @@ namespace llarp
|
|||
bool firstKey = true;
|
||||
bool relayed = false;
|
||||
|
||||
MessageDecoder(const Key_t &from) : From(from)
|
||||
MessageDecoder(const Key_t &from, bool wasRelayed)
|
||||
: From(from), relayed(wasRelayed)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
on_key(dict_reader *r, llarp_buffer_t *key)
|
||||
bool
|
||||
operator()(llarp_buffer_t *buffer, llarp_buffer_t *key)
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
MessageDecoder *dec = static_cast< MessageDecoder * >(r->user);
|
||||
// check for empty dict
|
||||
if(!key)
|
||||
return !dec->firstKey;
|
||||
return !firstKey;
|
||||
|
||||
// first key
|
||||
if(dec->firstKey)
|
||||
if(firstKey)
|
||||
{
|
||||
if(!(*key == "A"))
|
||||
return false;
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
if(!bencode_read_string(buffer, &strbuf))
|
||||
return false;
|
||||
// bad msg size?
|
||||
if(strbuf.sz != 1)
|
||||
return false;
|
||||
llarp::LogInfo("Handle DHT message ", *strbuf.base,
|
||||
" relayed=", dec->relayed);
|
||||
" relayed=", relayed);
|
||||
switch(*strbuf.base)
|
||||
{
|
||||
case 'F':
|
||||
dec->msg.reset(new FindIntroMessage(dec->From, dec->relayed));
|
||||
msg.reset(new FindIntroMessage(From, relayed));
|
||||
break;
|
||||
case 'R':
|
||||
if(dec->relayed)
|
||||
dec->msg.reset(new RelayedFindRouterMessage(dec->From));
|
||||
if(relayed)
|
||||
msg.reset(new RelayedFindRouterMessage(From));
|
||||
else
|
||||
dec->msg.reset(new FindRouterMessage(dec->From));
|
||||
msg.reset(new FindRouterMessage(From));
|
||||
break;
|
||||
case 'S':
|
||||
dec->msg.reset(new GotRouterMessage(dec->From, dec->relayed));
|
||||
msg.reset(new GotRouterMessage(From, relayed));
|
||||
break;
|
||||
case 'I':
|
||||
dec->msg.reset(new PublishIntroMessage());
|
||||
msg.reset(new PublishIntroMessage());
|
||||
break;
|
||||
case 'G':
|
||||
if(dec->relayed)
|
||||
if(relayed)
|
||||
{
|
||||
dec->msg.reset(new RelayedGotIntroMessage());
|
||||
msg.reset(new RelayedGotIntroMessage());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dec->msg.reset(new GotIntroMessage(dec->From));
|
||||
msg.reset(new GotIntroMessage(From));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -75,23 +76,19 @@ namespace llarp
|
|||
// bad msg type
|
||||
return false;
|
||||
}
|
||||
dec->firstKey = false;
|
||||
return dec->msg != nullptr;
|
||||
firstKey = false;
|
||||
return msg != nullptr;
|
||||
}
|
||||
else
|
||||
return dec->msg->DecodeKey(*key, r->buffer);
|
||||
return msg->DecodeKey(*key, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
IMessage::Ptr_t
|
||||
DecodeMesssage(const Key_t &from, llarp_buffer_t *buf, bool relayed)
|
||||
{
|
||||
MessageDecoder dec(from);
|
||||
dec.relayed = relayed;
|
||||
dict_reader r;
|
||||
r.user = &dec;
|
||||
r.on_key = &MessageDecoder::on_key;
|
||||
if(!bencode_read_dict(buf, &r))
|
||||
MessageDecoder dec(from, relayed);
|
||||
if(!bencode_read_dict(dec, buf))
|
||||
return nullptr;
|
||||
|
||||
return std::move(dec.msg);
|
||||
|
@ -99,25 +96,25 @@ namespace llarp
|
|||
|
||||
struct ListDecoder
|
||||
{
|
||||
ListDecoder(const Key_t &from, std::vector< IMessage::Ptr_t > &list)
|
||||
: From(from), l(list)
|
||||
ListDecoder(bool hasRelayed, const Key_t &from,
|
||||
std::vector< IMessage::Ptr_t > &list)
|
||||
: relayed(hasRelayed), From(from), l(list)
|
||||
{
|
||||
}
|
||||
|
||||
bool relayed = false;
|
||||
bool relayed;
|
||||
const Key_t &From;
|
||||
std::vector< IMessage::Ptr_t > &l;
|
||||
|
||||
static bool
|
||||
on_item(list_reader *r, bool has)
|
||||
bool
|
||||
operator()(llarp_buffer_t *buffer, bool has)
|
||||
{
|
||||
ListDecoder *dec = static_cast< ListDecoder * >(r->user);
|
||||
if(!has)
|
||||
return true;
|
||||
auto msg = DecodeMesssage(dec->From, r->buffer, dec->relayed);
|
||||
auto msg = DecodeMesssage(From, buffer, relayed);
|
||||
if(msg)
|
||||
{
|
||||
dec->l.emplace_back(std::move(msg));
|
||||
l.emplace_back(std::move(msg));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -129,12 +126,8 @@ namespace llarp
|
|||
DecodeMesssageList(Key_t from, llarp_buffer_t *buf,
|
||||
std::vector< IMessage::Ptr_t > &list, bool relayed)
|
||||
{
|
||||
ListDecoder dec(from, list);
|
||||
dec.relayed = relayed;
|
||||
list_reader r;
|
||||
r.user = &dec;
|
||||
r.on_item = &ListDecoder::on_item;
|
||||
return bencode_read_list(buf, &r);
|
||||
ListDecoder dec(relayed, from, list);
|
||||
return bencode_read_list(dec, buf);
|
||||
}
|
||||
} // namespace dht
|
||||
} // namespace llarp
|
||||
|
|
|
@ -38,13 +38,10 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
InboundMessageParser::OnKey(dict_reader* r, llarp_buffer_t* key)
|
||||
InboundMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
InboundMessageParser* handler =
|
||||
static_cast< InboundMessageParser* >(r->user);
|
||||
|
||||
// we are reading the first key
|
||||
if(handler->firstkey)
|
||||
if(firstkey)
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
// check for empty dict
|
||||
|
@ -57,7 +54,7 @@ namespace llarp
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
if(!bencode_read_string(buffer, &strbuf))
|
||||
{
|
||||
llarp::LogWarn("could not read value of message type");
|
||||
return false;
|
||||
|
@ -74,23 +71,23 @@ namespace llarp
|
|||
switch(*strbuf.cur)
|
||||
{
|
||||
case 'i':
|
||||
handler->msg = &handler->holder->i;
|
||||
isLIM = true;
|
||||
msg = &holder->i;
|
||||
isLIM = true;
|
||||
break;
|
||||
case 'd':
|
||||
handler->msg = &handler->holder->d;
|
||||
msg = &holder->d;
|
||||
break;
|
||||
case 'u':
|
||||
handler->msg = &handler->holder->u;
|
||||
msg = &holder->u;
|
||||
break;
|
||||
case 'm':
|
||||
handler->msg = &handler->holder->m;
|
||||
msg = &holder->m;
|
||||
break;
|
||||
case 'c':
|
||||
handler->msg = &handler->holder->c;
|
||||
msg = &holder->c;
|
||||
break;
|
||||
case 'x':
|
||||
handler->msg = &handler->holder->x;
|
||||
msg = &holder->x;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -98,20 +95,19 @@ namespace llarp
|
|||
|
||||
if(!isLIM)
|
||||
{
|
||||
const std::string host =
|
||||
"RX_" + RouterID(handler->from->GetPubKey()).ToString();
|
||||
METRICS_DYNAMIC_INCREMENT(handler->msg->Name(), host.c_str());
|
||||
const std::string host = "RX_" + RouterID(from->GetPubKey()).ToString();
|
||||
METRICS_DYNAMIC_INCREMENT(msg->Name(), host.c_str());
|
||||
}
|
||||
|
||||
handler->msg->session = handler->from;
|
||||
handler->firstkey = false;
|
||||
msg->session = from;
|
||||
firstkey = false;
|
||||
return true;
|
||||
}
|
||||
// check for last element
|
||||
if(!key)
|
||||
return handler->MessageDone();
|
||||
return MessageDone();
|
||||
|
||||
return handler->msg->DecodeKey(*key, r->buffer);
|
||||
return msg->DecodeKey(*key, buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -135,12 +131,11 @@ namespace llarp
|
|||
llarp::LogWarn("no link session");
|
||||
return false;
|
||||
}
|
||||
reader.user = this;
|
||||
reader.on_key = &OnKey;
|
||||
from = src;
|
||||
firstkey = true;
|
||||
|
||||
from = src;
|
||||
firstkey = true;
|
||||
ManagedBuffer copy(buf);
|
||||
return bencode_read_dict(©.underlying, &reader);
|
||||
return bencode_read_dict(*this, ©.underlying);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -16,10 +16,9 @@ namespace llarp
|
|||
{
|
||||
InboundMessageParser(AbstractRouter* router);
|
||||
~InboundMessageParser();
|
||||
dict_reader reader;
|
||||
|
||||
static bool
|
||||
OnKey(dict_reader* r, llarp_buffer_t* buf);
|
||||
bool
|
||||
operator()(llarp_buffer_t* buffer, llarp_buffer_t* key);
|
||||
|
||||
/// start processig message from a link session
|
||||
bool
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <util/logic.hpp>
|
||||
#include <nodedb.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
LR_CommitMessage::~LR_CommitMessage()
|
||||
|
@ -113,47 +115,44 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
LR_CommitRecord::OnKey(dict_reader* r, llarp_buffer_t* key)
|
||||
LR_CommitRecord::OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
if(!key)
|
||||
return true;
|
||||
|
||||
LR_CommitRecord* self = static_cast< LR_CommitRecord* >(r->user);
|
||||
|
||||
bool read = false;
|
||||
|
||||
if(!BEncodeMaybeReadDictEntry("c", self->commkey, read, *key, r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("c", commkey, read, *key, buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("i", self->nextHop, read, *key, r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("i", nextHop, read, *key, buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("l", self->lifetime, read, *key, r->buffer))
|
||||
if(!BEncodeMaybeReadDictInt("l", lifetime, read, *key, buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("n", self->tunnelNonce, read, *key,
|
||||
r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("n", tunnelNonce, read, *key, buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("r", self->rxid, read, *key, r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("r", rxid, read, *key, buffer))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("t", self->txid, read, *key, r->buffer))
|
||||
if(!BEncodeMaybeReadDictEntry("t", txid, read, *key, buffer))
|
||||
return false;
|
||||
if(*key == "u")
|
||||
{
|
||||
self->nextRC = std::make_unique< RouterContact >();
|
||||
return self->nextRC->BDecode(r->buffer);
|
||||
nextRC = std::make_unique< RouterContact >();
|
||||
return nextRC->BDecode(buffer);
|
||||
}
|
||||
if(!BEncodeMaybeReadVersion("v", self->version, LLARP_PROTO_VERSION, read,
|
||||
*key, r->buffer))
|
||||
if(!BEncodeMaybeReadVersion("v", version, LLARP_PROTO_VERSION, read, *key,
|
||||
buffer))
|
||||
return false;
|
||||
if(*key == "w")
|
||||
{
|
||||
// check for duplicate
|
||||
if(self->work)
|
||||
if(work)
|
||||
{
|
||||
llarp::LogWarn("duplicate POW in LRCR");
|
||||
return false;
|
||||
}
|
||||
|
||||
self->work = std::make_unique< PoW >();
|
||||
return self->work->BDecode(r->buffer);
|
||||
work = std::make_unique< PoW >();
|
||||
return work->BDecode(buffer);
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
@ -161,10 +160,9 @@ namespace llarp
|
|||
bool
|
||||
LR_CommitRecord::BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
dict_reader r;
|
||||
r.user = this;
|
||||
r.on_key = &OnKey;
|
||||
return bencode_read_dict(buf, &r);
|
||||
using namespace std::placeholders;
|
||||
return bencode_read_dict(std::bind(&LR_CommitRecord::OnKey, this, _1, _2),
|
||||
buf);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace llarp
|
|||
operator==(const LR_CommitRecord &other) const;
|
||||
|
||||
private:
|
||||
static bool
|
||||
OnKey(dict_reader *r, llarp_buffer_t *buf);
|
||||
bool
|
||||
OnKey(llarp_buffer_t *buffer, llarp_buffer_t *key);
|
||||
};
|
||||
|
||||
struct LR_CommitMessage : public ILinkMessage
|
||||
|
|
|
@ -32,12 +32,10 @@ namespace llarp
|
|||
|
||||
InboundMessageParser::InboundMessageParser()
|
||||
: firstKey(false)
|
||||
, key('\0')
|
||||
, ourKey('\0')
|
||||
, msg(nullptr)
|
||||
, m_Holder(std::make_unique< MessageHolder >())
|
||||
{
|
||||
reader.user = this;
|
||||
reader.on_key = &OnKey;
|
||||
}
|
||||
|
||||
InboundMessageParser::~InboundMessageParser()
|
||||
|
@ -45,76 +43,74 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
InboundMessageParser::OnKey(dict_reader* r, llarp_buffer_t* key)
|
||||
InboundMessageParser::operator()(llarp_buffer_t* buffer,
|
||||
llarp_buffer_t* key)
|
||||
{
|
||||
InboundMessageParser* self =
|
||||
static_cast< InboundMessageParser* >(r->user);
|
||||
|
||||
if(key == nullptr && self->firstKey)
|
||||
if(key == nullptr && firstKey)
|
||||
{
|
||||
// empty dict
|
||||
return false;
|
||||
}
|
||||
if(!key)
|
||||
return true;
|
||||
if(self->firstKey)
|
||||
if(firstKey)
|
||||
{
|
||||
llarp_buffer_t strbuf;
|
||||
if(!(*key == "A"))
|
||||
return false;
|
||||
if(!bencode_read_string(r->buffer, &strbuf))
|
||||
if(!bencode_read_string(buffer, &strbuf))
|
||||
return false;
|
||||
if(strbuf.sz != 1)
|
||||
return false;
|
||||
self->key = *strbuf.cur;
|
||||
LogDebug("routing message '", self->key, "'");
|
||||
switch(self->key)
|
||||
ourKey = *strbuf.cur;
|
||||
LogDebug("routing message '", key, "'");
|
||||
switch(ourKey)
|
||||
{
|
||||
case 'D':
|
||||
self->msg = &self->m_Holder->D;
|
||||
msg = &m_Holder->D;
|
||||
break;
|
||||
case 'L':
|
||||
self->msg = &self->m_Holder->L;
|
||||
msg = &m_Holder->L;
|
||||
break;
|
||||
case 'M':
|
||||
self->msg = &self->m_Holder->M;
|
||||
msg = &m_Holder->M;
|
||||
break;
|
||||
case 'P':
|
||||
self->msg = &self->m_Holder->P;
|
||||
msg = &m_Holder->P;
|
||||
break;
|
||||
case 'T':
|
||||
self->msg = &self->m_Holder->T;
|
||||
msg = &m_Holder->T;
|
||||
break;
|
||||
case 'H':
|
||||
self->msg = &self->m_Holder->H;
|
||||
msg = &m_Holder->H;
|
||||
break;
|
||||
case 'I':
|
||||
self->msg = &self->m_Holder->I;
|
||||
msg = &m_Holder->I;
|
||||
break;
|
||||
case 'G':
|
||||
self->msg = &self->m_Holder->G;
|
||||
msg = &m_Holder->G;
|
||||
break;
|
||||
case 'J':
|
||||
self->msg = &self->m_Holder->J;
|
||||
msg = &m_Holder->J;
|
||||
break;
|
||||
case 'O':
|
||||
self->msg = &self->m_Holder->O;
|
||||
msg = &m_Holder->O;
|
||||
break;
|
||||
case 'U':
|
||||
self->msg = &self->m_Holder->U;
|
||||
msg = &m_Holder->U;
|
||||
break;
|
||||
case 'C':
|
||||
self->msg = &self->m_Holder->C;
|
||||
msg = &m_Holder->C;
|
||||
break;
|
||||
default:
|
||||
llarp::LogError("invalid routing message id: ", *strbuf.cur);
|
||||
}
|
||||
self->firstKey = false;
|
||||
return self->msg != nullptr;
|
||||
firstKey = false;
|
||||
return msg != nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return self->msg->DecodeKey(*key, r->buffer);
|
||||
return msg->DecodeKey(*key, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,13 +125,13 @@ namespace llarp
|
|||
firstKey = true;
|
||||
ManagedBuffer copiedBuf(buf);
|
||||
auto& copy = copiedBuf.underlying;
|
||||
if(bencode_read_dict(©, &reader))
|
||||
if(bencode_read_dict(*this, ©))
|
||||
{
|
||||
msg->from = from;
|
||||
result = msg->HandleMessage(h, r);
|
||||
if(!result)
|
||||
{
|
||||
llarp::LogWarn("Failed to handle inbound routing message ", key);
|
||||
llarp::LogWarn("Failed to handle inbound routing message ", ourKey);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -25,13 +25,12 @@ namespace llarp
|
|||
ParseMessageBuffer(const llarp_buffer_t& buf, IMessageHandler* handler,
|
||||
const PathID_t& from, AbstractRouter* r);
|
||||
|
||||
private:
|
||||
static bool
|
||||
OnKey(dict_reader* r, llarp_buffer_t* key);
|
||||
bool
|
||||
operator()(llarp_buffer_t* buffer, llarp_buffer_t* key);
|
||||
|
||||
private:
|
||||
bool firstKey;
|
||||
char key;
|
||||
dict_reader reader;
|
||||
char ourKey;
|
||||
|
||||
struct MessageHolder;
|
||||
|
||||
|
|
|
@ -121,59 +121,3 @@ bencode_end(llarp_buffer_t* buff)
|
|||
assert(std::distance(std::begin(letter), std::end(letter)) == 1);
|
||||
return buff->write(std::begin(letter), std::end(letter));
|
||||
}
|
||||
|
||||
bool
|
||||
bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r)
|
||||
{
|
||||
if(buff->size_left() < 2) // minimum case is 'de'
|
||||
return false;
|
||||
llarp_buffer_t strbuf; // temporary buffer for current element
|
||||
r->buffer = buff; // set up dict_reader
|
||||
if(*r->buffer->cur != 'd') // ensure is a dictionary
|
||||
return false;
|
||||
r->buffer->cur++;
|
||||
while(r->buffer->size_left() && *r->buffer->cur != 'e')
|
||||
{
|
||||
if(bencode_read_string(r->buffer, &strbuf))
|
||||
{
|
||||
if(!r->on_key(r, &strbuf)) // check for early abort
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if(*r->buffer->cur != 'e')
|
||||
{
|
||||
llarp::LogWarn("reading dict not ending on 'e'");
|
||||
// make sure we're at dictionary end
|
||||
return false;
|
||||
}
|
||||
r->buffer->cur++;
|
||||
return r->on_key(r, nullptr);
|
||||
}
|
||||
|
||||
bool
|
||||
bencode_read_list(llarp_buffer_t* buff, struct list_reader* r)
|
||||
{
|
||||
if(buff->size_left() < 2) // minimum case is 'le'
|
||||
return false;
|
||||
r->buffer = buff;
|
||||
if(*r->buffer->cur != 'l') // ensure is a list
|
||||
{
|
||||
llarp::LogWarn("bencode::bencode_read_list - expecting list got ",
|
||||
*r->buffer->cur);
|
||||
return false;
|
||||
}
|
||||
|
||||
r->buffer->cur++;
|
||||
while(r->buffer->size_left() && *r->buffer->cur != 'e')
|
||||
{
|
||||
if(!r->on_item(r, true)) // check for early abort
|
||||
return false;
|
||||
}
|
||||
if(*r->buffer->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
r->buffer->cur++;
|
||||
return r->on_item(r, false);
|
||||
}
|
||||
|
|
|
@ -41,38 +41,4 @@ bencode_start_dict(llarp_buffer_t* buff);
|
|||
bool
|
||||
bencode_end(llarp_buffer_t* buff);
|
||||
|
||||
struct dict_reader
|
||||
{
|
||||
/// makes passing data into on_key easier
|
||||
llarp_buffer_t* buffer;
|
||||
/// not currently used, maybe used in the future to pass additional
|
||||
/// information to on_key
|
||||
void* user;
|
||||
/**
|
||||
* called when we got a key string, return true to continue iteration
|
||||
* called with null key on done iterating
|
||||
*/
|
||||
std::function< bool(dict_reader*, llarp_buffer_t*) > on_key;
|
||||
};
|
||||
|
||||
bool
|
||||
bencode_read_dict(llarp_buffer_t* buff, struct dict_reader* r);
|
||||
|
||||
struct list_reader
|
||||
{
|
||||
/// makes passing data into on_item easier
|
||||
llarp_buffer_t* buffer;
|
||||
/// not currently used, maybe used in the future to pass additional
|
||||
/// information to on_item
|
||||
void* user;
|
||||
/**
|
||||
* called with true when we got an element, return true to continue iteration
|
||||
* called with false on iteration completion
|
||||
*/
|
||||
std::function< bool(list_reader*, bool) > on_item;
|
||||
};
|
||||
|
||||
bool
|
||||
bencode_read_list(llarp_buffer_t* buff, struct list_reader* r);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -140,28 +140,6 @@ namespace llarp
|
|||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
template < typename Array >
|
||||
bool
|
||||
BEncodeReadArray(Array& array, llarp_buffer_t* buf)
|
||||
{
|
||||
if(*buf->cur != 'l') // ensure is a list
|
||||
return false;
|
||||
|
||||
buf->cur++;
|
||||
size_t idx = 0;
|
||||
while(buf->size_left() && *buf->cur != 'e')
|
||||
{
|
||||
if(idx >= array.size())
|
||||
return false;
|
||||
if(!array[idx++].BDecode(buf))
|
||||
return false;
|
||||
}
|
||||
if(*buf->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
buf->cur++;
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename Iter >
|
||||
bool
|
||||
BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf)
|
||||
|
@ -176,44 +154,97 @@ namespace llarp
|
|||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
template < typename Sink >
|
||||
bool
|
||||
bencode_read_dict(Sink&& sink, llarp_buffer_t* buffer)
|
||||
{
|
||||
if(buffer->size_left() < 2) // minimum case is 'de'
|
||||
return false;
|
||||
if(*buffer->cur != 'd') // ensure is a dictionary
|
||||
return false;
|
||||
buffer->cur++;
|
||||
while(buffer->size_left() && *buffer->cur != 'e')
|
||||
{
|
||||
llarp_buffer_t strbuf; // temporary buffer for current element
|
||||
if(bencode_read_string(buffer, &strbuf))
|
||||
{
|
||||
if(!sink(buffer, &strbuf)) // check for early abort
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if(*buffer->cur != 'e')
|
||||
{
|
||||
llarp::LogWarn("reading dict not ending on 'e'");
|
||||
// make sure we're at dictionary end
|
||||
return false;
|
||||
}
|
||||
buffer->cur++;
|
||||
return sink(buffer, nullptr);
|
||||
}
|
||||
|
||||
template < typename Sink >
|
||||
bool
|
||||
bencode_read_list(Sink&& sink, llarp_buffer_t* buffer)
|
||||
{
|
||||
if(buffer->size_left() < 2) // minimum case is 'le'
|
||||
return false;
|
||||
if(*buffer->cur != 'l') // ensure is a list
|
||||
{
|
||||
llarp::LogWarn("bencode::bencode_read_list - expecting list got ",
|
||||
*buffer->cur);
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->cur++;
|
||||
while(buffer->size_left() && *buffer->cur != 'e')
|
||||
{
|
||||
if(!sink(buffer, true)) // check for early abort
|
||||
return false;
|
||||
}
|
||||
if(*buffer->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
buffer->cur++;
|
||||
return sink(buffer, false);
|
||||
}
|
||||
|
||||
template < typename Array >
|
||||
bool
|
||||
BEncodeReadArray(Array& array, llarp_buffer_t* buf)
|
||||
{
|
||||
size_t idx = 0;
|
||||
return bencode_read_list(
|
||||
[&array, &idx](llarp_buffer_t* buffer, bool has) {
|
||||
if(has)
|
||||
{
|
||||
if(idx >= array.size())
|
||||
return false;
|
||||
if(!array[idx++].BDecode(buffer))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buf);
|
||||
}
|
||||
|
||||
template < typename List_t >
|
||||
bool
|
||||
BEncodeReadList(List_t& result, llarp_buffer_t* buf)
|
||||
{
|
||||
if(*buf->cur != 'l') // ensure is a list
|
||||
return false;
|
||||
|
||||
buf->cur++;
|
||||
while(buf->size_left() && *buf->cur != 'e')
|
||||
{
|
||||
if(!result.emplace(result.end())->BDecode(buf))
|
||||
return false;
|
||||
}
|
||||
if(*buf->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
buf->cur++;
|
||||
return true;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
bool
|
||||
BEncodeReadSet(std::set< T >& result, llarp_buffer_t* buf)
|
||||
{
|
||||
if(*buf->cur != 'l') // ensure is a list
|
||||
return false;
|
||||
|
||||
buf->cur++;
|
||||
while(buf->size_left() && *buf->cur != 'e')
|
||||
{
|
||||
T item;
|
||||
if(!item.BDecode(buf))
|
||||
return false;
|
||||
return result.insert(item).second;
|
||||
}
|
||||
if(*buf->cur != 'e') // make sure we're at a list end
|
||||
return false;
|
||||
buf->cur++;
|
||||
return true;
|
||||
return bencode_read_list(
|
||||
[&result](llarp_buffer_t* buffer, bool has) {
|
||||
if(has)
|
||||
{
|
||||
if(!result.emplace(result.end())->BDecode(buffer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
buf);
|
||||
}
|
||||
|
||||
template < typename List_t >
|
||||
|
@ -245,19 +276,16 @@ namespace llarp
|
|||
virtual bool
|
||||
BDecode(llarp_buffer_t* buf)
|
||||
{
|
||||
dict_reader r;
|
||||
r.user = this;
|
||||
r.on_key = &OnKey;
|
||||
return bencode_read_dict(buf, &r);
|
||||
return bencode_read_dict(*this, buf);
|
||||
}
|
||||
|
||||
// TODO: check for shadowed values elsewhere
|
||||
uint64_t version = 0;
|
||||
|
||||
static bool
|
||||
OnKey(dict_reader* r, llarp_buffer_t* k)
|
||||
bool
|
||||
operator()(llarp_buffer_t* buffer, llarp_buffer_t* key)
|
||||
{
|
||||
return static_cast< IBEncodeMessage* >(r->user)->HandleKey(k, r->buffer);
|
||||
return HandleKey(key, buffer);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -387,15 +387,15 @@ TEST_P(DictReadTest, readtest)
|
|||
|
||||
std::vector< std::string > result;
|
||||
|
||||
dict_reader reader{nullptr, nullptr, [&](dict_reader*, llarp_buffer_t* buf) {
|
||||
if(buf)
|
||||
{
|
||||
result.emplace_back(buf->base, buf->base + buf->sz);
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
|
||||
ASSERT_TRUE(bencode_read_dict(&buffer, &reader));
|
||||
ASSERT_TRUE(llarp::bencode_read_dict(
|
||||
[&](llarp_buffer_t*, llarp_buffer_t* key) {
|
||||
if(key)
|
||||
{
|
||||
result.emplace_back(key->base, key->base + key->sz);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
&buffer));
|
||||
ASSERT_EQ(result, d.output);
|
||||
}
|
||||
|
||||
|
@ -422,18 +422,17 @@ TEST_P(ListReadTest, readtest)
|
|||
|
||||
std::vector< std::string > result;
|
||||
|
||||
list_reader reader{nullptr, nullptr, [&](list_reader* r, bool cont) {
|
||||
if(cont)
|
||||
{
|
||||
auto b = r->buffer;
|
||||
llarp_buffer_t tmp;
|
||||
bencode_read_string(b, &tmp);
|
||||
result.emplace_back(tmp.base, tmp.base + tmp.sz);
|
||||
}
|
||||
return true;
|
||||
}};
|
||||
|
||||
ASSERT_TRUE(bencode_read_list(&buffer, &reader));
|
||||
ASSERT_TRUE(llarp::bencode_read_list(
|
||||
[&](llarp_buffer_t* b, bool cont) {
|
||||
if(cont)
|
||||
{
|
||||
llarp_buffer_t tmp;
|
||||
bencode_read_string(b, &tmp);
|
||||
result.emplace_back(tmp.base, tmp.base + tmp.sz);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
&buffer));
|
||||
ASSERT_EQ(result, d.output);
|
||||
}
|
||||
|
||||
|
@ -446,8 +445,6 @@ INSTANTIATE_TEST_CASE_P(TestBencode, ListReadTest,
|
|||
TEST(TestBencode, ReadDictEmptyBuffer)
|
||||
{
|
||||
llarp_buffer_t buf((byte_t*)nullptr, 0);
|
||||
dict_reader reader;
|
||||
reader.on_key = [](dict_reader*, llarp_buffer_t*) -> bool { return true; };
|
||||
reader.user = nullptr;
|
||||
ASSERT_FALSE(bencode_read_dict(&buf, &reader));
|
||||
ASSERT_FALSE(llarp::bencode_read_dict(
|
||||
[](llarp_buffer_t*, llarp_buffer_t*) { return true; }, &buf));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue