#include #include #include #include #include #include #include #include #include #include #include #include namespace llarp { struct LinkMessageParser::msg_holder_t { LinkIntroMessage i; RelayDownstreamMessage d; RelayUpstreamMessage u; DHTImmediateMessage m; LR_CommitMessage c; DiscardMessage x; msg_holder_t() = default; }; LinkMessageParser::LinkMessageParser(AbstractRouter* _router) : router(_router) , from(nullptr) , msg(nullptr) , holder(std::make_unique< msg_holder_t >()) { } LinkMessageParser::~LinkMessageParser() { } bool LinkMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) { // we are reading the first key if(firstkey) { llarp_buffer_t strbuf; // check for empty dict if(!key) return false; // we are expecting the first key to be 'a' if(!(*key == "a")) { llarp::LogWarn("message has no message type"); return false; } if(!bencode_read_string(buffer, &strbuf)) { llarp::LogWarn("could not read value of message type"); return false; } // bad key size if(strbuf.sz != 1) { llarp::LogWarn("bad mesage type size: ", strbuf.sz); return false; } // create the message to parse based off message type llarp::LogDebug("inbound message ", *strbuf.cur); bool isLIM = false; switch(*strbuf.cur) { case 'i': msg = &holder->i; isLIM = true; break; case 'd': msg = &holder->d; break; case 'u': msg = &holder->u; break; case 'm': msg = &holder->m; break; case 'c': msg = &holder->c; break; case 'x': msg = &holder->x; break; default: return false; } if(!isLIM) { metrics::integerTick(msg->Name(), "RX", 1, "id", RouterID(from->GetPubKey()).ToString()); } msg->session = from; firstkey = false; return true; } // check for last element if(!key) return MessageDone(); return msg->DecodeKey(*key, buffer); } bool LinkMessageParser::MessageDone() { bool result = false; if(msg) { result = msg->HandleMessage(router); } Reset(); return result; } bool LinkMessageParser::ProcessFrom(ILinkSession* src, const llarp_buffer_t& buf) { if(!src) { llarp::LogWarn("no link session"); return false; } from = src; firstkey = true; ManagedBuffer copy(buf); return bencode_read_dict(*this, ©.underlying); } void LinkMessageParser::Reset() { if(msg) msg->Clear(); msg = nullptr; } } // namespace llarp