The uTP-over-DiscV5 document specifies that all uTP traffic is encapsulated into TALKREQ
packets while TALKRESP
is not used. The problem is that the current DiscV5 implementation kind of insists on doing TALKREQ
/ TALKRESP
packet exchanges and expects a response to every request. See the existing interface here:
type TalkRequestHandler func(enode.ID, *net.UDPAddr, []byte) []byte
func (t *UDPv5) RegisterTalkHandler(protocol string, handler TalkRequestHandler) {
func (t *UDPv5) TalkRequest(n *enode.Node, protocol string, request []byte) ([]byte, error) {
In order to interface uTP to DiscV5 we need to somehow circumvent the internal request/reply logic and just send and receive TALKREQ
packets. I'd suggest modifying handleTalkRequest
so that if the TalkRequestHandler
returns a nil
byte slice then it does not send a response at all. This way the uTP handler can register itself with RegisterTalkHandler('utp', handler)
where the handler
processes incoming messages and always returns nil
. For sending messages without expecting a response I`d suggest adding an alternative send method:
func (t *UDPv5) TalkRequestNoResponse(n *enode.Node, protocol string, message []byte) error {
_, err := t.send(n.ID(), &net.UDPAddr{IP: n.IP(), Port: n.UDP()}, &v5wire.TalkRequest{Protocol: protocol, Message: message})
return err
}
The exported interface of the uTP logic should look something like this:
func (t *UTP) Send(n *enode.Node, connectionID, message []byte) error
func (t *UTP) Receive(n *enode.Node, connectionID []byte) ([]byte, error)