Summary
The current /libp2p/dcutr implementation in dart_libp2p (lib/p2p/protocol/holepunch/service.dart and holepuncher.dart) sends and expects raw Protobuf payload bytes without length-delimited message framing.
However, the libp2p DCUtR protocol specification and standard go-libp2p implementation (github.com/libp2p/go-libp2p/p2p/protocol/holepunch) frame stream messages using pbio (unsigned varint length prefix).
Problem Impact
When a dart_libp2p node attempts DCUtR hole punching with a go-libp2p peer over a circuit relay:
go-libp2p sends a CONNECT message prefixed by a uvarint length byte (for example, 0x1e).
dart_libp2p performs HolePunch.fromBuffer() on the unstripped stream, failing to parse the Protobuf tag.
- The stream is reset, breaking the NAT hole-punching upgrade.
Fix
- Wrap outbound
HolePunch Protobuf messages using encodeDelimitedMessage() to prepend the uvarint length.
- Use
BufferedP2PStreamReader in _incomingHolePunch and _initiateHolePunchImpl to read the uvarint length prefix followed by the exact payload bytes.
- Cover single-byte and multi-byte uvarint prefixes and fragmented stream reads with unit tests.
Summary
The current
/libp2p/dcutrimplementation indart_libp2p(lib/p2p/protocol/holepunch/service.dartandholepuncher.dart) sends and expects raw Protobuf payload bytes without length-delimited message framing.However, the libp2p DCUtR protocol specification and standard
go-libp2pimplementation (github.com/libp2p/go-libp2p/p2p/protocol/holepunch) frame stream messages usingpbio(unsigned varint length prefix).Problem Impact
When a
dart_libp2pnode attempts DCUtR hole punching with ago-libp2ppeer over a circuit relay:go-libp2psends aCONNECTmessage prefixed by auvarintlength byte (for example,0x1e).dart_libp2pperformsHolePunch.fromBuffer()on the unstripped stream, failing to parse the Protobuf tag.Fix
HolePunchProtobuf messages usingencodeDelimitedMessage()to prepend the uvarint length.BufferedP2PStreamReaderin_incomingHolePunchand_initiateHolePunchImplto read the uvarint length prefix followed by the exact payload bytes.