diff --git a/llarp/dht/message.cpp b/llarp/dht/message.cpp index 991ec1ed1..f33f580b8 100644 --- a/llarp/dht/message.cpp +++ b/llarp/dht/message.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -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 diff --git a/llarp/messages/link_message.cpp b/llarp/messages/link_message.cpp index 82dc49150..096c95973 100644 --- a/llarp/messages/link_message.cpp +++ b/llarp/messages/link_message.cpp @@ -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 diff --git a/llarp/messages/link_message_parser.hpp b/llarp/messages/link_message_parser.hpp index 69eae55ba..4d23a9f01 100644 --- a/llarp/messages/link_message_parser.hpp +++ b/llarp/messages/link_message_parser.hpp @@ -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 diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 02f6d7f46..2791f31ce 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -9,6 +9,8 @@ #include #include +#include + 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 diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp index 60ca6ce52..561d9f449 100644 --- a/llarp/messages/relay_commit.hpp +++ b/llarp/messages/relay_commit.hpp @@ -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 diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp index 261c256f5..770e7be39 100644 --- a/llarp/routing/message_parser.cpp +++ b/llarp/routing/message_parser.cpp @@ -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 diff --git a/llarp/routing/message_parser.hpp b/llarp/routing/message_parser.hpp index 3628ed01e..5c0d7f78d 100644 --- a/llarp/routing/message_parser.hpp +++ b/llarp/routing/message_parser.hpp @@ -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; diff --git a/llarp/util/bencode.cpp b/llarp/util/bencode.cpp index 8c4da586b..b8b32b3ee 100644 --- a/llarp/util/bencode.cpp +++ b/llarp/util/bencode.cpp @@ -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); -} diff --git a/llarp/util/bencode.h b/llarp/util/bencode.h index 1da18078d..04fe12c8a 100644 --- a/llarp/util/bencode.h +++ b/llarp/util/bencode.h @@ -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 diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index 91343ddce..005a25c77 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -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 diff --git a/test/util/test_llarp_util_bencode.cpp b/test/util/test_llarp_util_bencode.cpp index b84517f23..5453baac4 100644 --- a/test/util/test_llarp_util_bencode.cpp +++ b/test/util/test_llarp_util_bencode.cpp @@ -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)); }