#include "message_parser.hpp" #include #include #include #include "path_dht_message.hpp" #include "path_confirm_message.hpp" #include "path_latency_message.hpp" #include "path_transfer_message.hpp" #include "transfer_traffic_message.hpp" #include namespace llarp::routing { struct InboundMessageParser::MessageHolder { DataDiscardMessage D; PathLatencyMessage L; PathDHTMessage M; PathConfirmMessage P; PathTransferMessage T; service::ProtocolFrameMessage H; TransferTrafficMessage I; GrantExitMessage G; RejectExitMessage J; ObtainExitMessage O; UpdateExitMessage U; CloseExitMessage C; }; InboundMessageParser::InboundMessageParser() : m_Holder(std::make_unique()) {} InboundMessageParser::~InboundMessageParser() = default; bool InboundMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) { if (key == nullptr && firstKey) { // empty dict return false; } if (!key) return true; if (firstKey) { llarp_buffer_t strbuf; if (!(key->startswith("A"))) return false; if (!bencode_read_string(buffer, &strbuf)) return false; if (strbuf.sz != 1) return false; ourKey = *strbuf.cur; LogDebug("routing message '", std::string{ourKey, 1}, "'"); switch (ourKey) { case 'D': msg = &m_Holder->D; break; case 'L': msg = &m_Holder->L; break; case 'M': msg = &m_Holder->M; break; case 'P': msg = &m_Holder->P; break; case 'T': msg = &m_Holder->T; break; case 'H': msg = &m_Holder->H; break; case 'I': msg = &m_Holder->I; break; case 'G': msg = &m_Holder->G; break; case 'J': msg = &m_Holder->J; break; case 'O': msg = &m_Holder->O; break; case 'U': msg = &m_Holder->U; break; case 'C': msg = &m_Holder->C; break; default: llarp::LogError("invalid routing message id: ", *strbuf.cur); } if (msg) msg->version = version; firstKey = false; return msg != nullptr; } return msg->decode_key(*key, buffer); } bool InboundMessageParser::ParseMessageBuffer( const llarp_buffer_t& buf, AbstractRoutingMessageHandler* h, const PathID_t& from, Router* r) { bool result = false; msg = nullptr; firstKey = true; ManagedBuffer copiedBuf(buf); auto& copy = copiedBuf.underlying; uint64_t v = 0; if (BEncodeSeekDictVersion(v, ©, 'V')) { version = v; } if (bencode_read_dict(*this, ©)) { msg->from = from; LogDebug("handle routing message ", msg->sequence_number, " from ", from); result = msg->handle_message(h, r); if (!result) { llarp::LogWarn("Failed to handle inbound routing message ", ourKey); } } else { llarp::LogError("read dict failed in routing layer"); llarp::DumpBuffer(buf); } if (msg) msg->clear(); msg = nullptr; version = 0; return result; } } // namespace llarp::routing