discv4/discv4_pong.cpp¶
Namespaces¶
| Name |
|---|
| discv4 |
Source code¶
// discv4_pong.cpp
#include "discv4/discv4_pong.hpp"
#include "discv4/discv4_constants.hpp"
namespace discv4 {
rlp::Result<discv4_pong> discv4_pong::Parse(rlp::ByteView raw) {
// Skipping hash (kWireHashSize bytes), sig (kWireSigSize bytes), packet type (kWirePacketTypeSize byte)
if ( raw.size() <= kWireHeaderSize - kWirePacketTypeSize )
{
return rlp::DecodingError::kUnexpectedString;
}
if ( raw.at(kWirePacketTypeOffset) != kPacketTypePong )
{
return rlp::DecodingError::kUnexpectedString;
}
// Omitting header and packet type byte as it is not RLP data
rlp::ByteView pong_payload(raw.data() + kWireHeaderSize, raw.size() - kWireHeaderSize);
rlp::RlpDecoder decoder(pong_payload);
discv4_pong pong;
// Check if the packet is a list (PONG should be a list with 3 elements)
BOOST_OUTCOME_TRY( bool is_list, decoder.IsList() );
if ( !is_list )
{
return rlp::DecodingError::kUnexpectedString;
}
// Read the list header
BOOST_OUTCOME_TRY( size_t list_length, decoder.ReadListHeaderBytes() );
// Parse to_endpoint (first element - should be a list of 3 elements)
BOOST_OUTCOME_TRY( ParseEndpoint( decoder, pong.toEndpoint ) );
// Parse ping_hash (second element - 32 bytes)
BOOST_OUTCOME_TRY( decoder.read( pong.pingHash ) );
rlp::ByteView hashBv( pong.pingHash.data(), pong.pingHash.size() );
// Parse expiration — variable-length RLP uint64 (go-ethereum encodes as uint64)
uint64_t expiration = 0;
BOOST_OUTCOME_TRY( decoder.read( expiration ) );
pong.expiration = static_cast<uint32_t>(expiration);
// Optional ENR sequence number (EIP-868) — variable-length uint64, may be absent.
// Any further unknown fields are silently consumed for forward compatibility
// (mirrors go-ethereum's Rest []rlp.RawValue `rlp:"tail"`).
if ( !decoder.IsFinished() )
{
BOOST_OUTCOME_TRY( decoder.read( pong.ersErq ) );
}
while ( !decoder.IsFinished() )
{
BOOST_OUTCOME_TRY( decoder.SkipItem() );
}
return pong;
}
rlp::DecodingResult discv4_pong::ParseEndpoint( rlp::RlpDecoder& decoder, discv4_pong::Endpoint& endpoint )
{
// Check if next item is a list (endpoint should be [ip, udp_port, tcp_port])
BOOST_OUTCOME_TRY( bool is_list, decoder.IsList() );
if ( !is_list )
{
return rlp::DecodingError::kUnexpectedString;
}
// Read endpoint list header
BOOST_OUTCOME_TRY( size_t endpointListLength, decoder.ReadListHeaderBytes() );
// Parse IP address (4 bytes)
BOOST_OUTCOME_TRY( decoder.read( endpoint.ip ) );
// Parse UDP port — variable-length RLP uint16
BOOST_OUTCOME_TRY( decoder.read( endpoint.udpPort ) );
// Parse TCP port — variable-length RLP uint16
BOOST_OUTCOME_TRY( decoder.read( endpoint.tcpPort ) );
return rlp::outcome::success();
}
}
Updated on 2026-04-13 at 23:22:46 -0700