mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-11-10 14:17:56 +01:00
lnwire: re-usable address descriptor parsers
In this commit, the logic in ReadElements that is used to read a single address descriptor from a io.Reader is separated out into a new function so that the logic can be re-used elsewhere.
This commit is contained in:
291
lnwire/lnwire.go
291
lnwire/lnwire.go
@@ -744,146 +744,19 @@ func ReadElement(r io.Reader, element interface{}) error {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for addrBytesRead < addrsLen {
|
for addrBytesRead < addrsLen {
|
||||||
var descriptor [1]byte
|
bytesRead, address, err := ReadAddress(
|
||||||
if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
addrBuf, addrsLen-addrBytesRead,
|
||||||
return err
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to read address: %w",
|
||||||
|
err)
|
||||||
}
|
}
|
||||||
|
addrBytesRead += bytesRead
|
||||||
|
|
||||||
addrBytesRead++
|
// If we encounter a noAddr descriptor, then we'll move
|
||||||
|
// on to the next address.
|
||||||
var address net.Addr
|
if address == nil {
|
||||||
switch aType := addressType(descriptor[0]); aType {
|
|
||||||
case noAddr:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case tcp4Addr:
|
|
||||||
var ip [4]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &net.TCPAddr{
|
|
||||||
IP: net.IP(ip[:]),
|
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
|
||||||
}
|
|
||||||
addrBytesRead += tcp4AddrLen
|
|
||||||
|
|
||||||
case tcp6Addr:
|
|
||||||
var ip [16]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &net.TCPAddr{
|
|
||||||
IP: net.IP(ip[:]),
|
|
||||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
|
||||||
}
|
|
||||||
addrBytesRead += tcp6AddrLen
|
|
||||||
|
|
||||||
case v2OnionAddr:
|
|
||||||
var h [tor.V2DecodedLen]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var p [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
|
||||||
onionService += tor.OnionSuffix
|
|
||||||
port := int(binary.BigEndian.Uint16(p[:]))
|
|
||||||
|
|
||||||
address = &tor.OnionAddr{
|
|
||||||
OnionService: onionService,
|
|
||||||
Port: port,
|
|
||||||
}
|
|
||||||
addrBytesRead += v2OnionAddrLen
|
|
||||||
|
|
||||||
case v3OnionAddr:
|
|
||||||
var h [tor.V3DecodedLen]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var p [2]byte
|
|
||||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
|
||||||
onionService += tor.OnionSuffix
|
|
||||||
port := int(binary.BigEndian.Uint16(p[:]))
|
|
||||||
|
|
||||||
address = &tor.OnionAddr{
|
|
||||||
OnionService: onionService,
|
|
||||||
Port: port,
|
|
||||||
}
|
|
||||||
addrBytesRead += v3OnionAddrLen
|
|
||||||
|
|
||||||
case dnsAddr:
|
|
||||||
var hostnameLen [1]byte
|
|
||||||
_, err := io.ReadFull(addrBuf, hostnameLen[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname := make([]byte, hostnameLen[0])
|
|
||||||
_, err = io.ReadFull(addrBuf, hostname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var port [2]byte
|
|
||||||
_, err = io.ReadFull(addrBuf, port[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &DNSAddress{
|
|
||||||
Hostname: string(hostname),
|
|
||||||
Port: binary.BigEndian.Uint16(
|
|
||||||
port[:],
|
|
||||||
),
|
|
||||||
}
|
|
||||||
addrBytesRead += dnsAddrOverhead +
|
|
||||||
uint16(len(hostname))
|
|
||||||
|
|
||||||
default:
|
|
||||||
// If we don't understand this address type,
|
|
||||||
// we just store it along with the remaining
|
|
||||||
// address bytes as type OpaqueAddrs. We need
|
|
||||||
// to hold onto the bytes so that we can still
|
|
||||||
// write them back to the wire when we
|
|
||||||
// propagate this message.
|
|
||||||
payloadLen := 1 + addrsLen - addrBytesRead
|
|
||||||
payload := make([]byte, payloadLen)
|
|
||||||
|
|
||||||
// First write a byte for the address type that
|
|
||||||
// we already read.
|
|
||||||
payload[0] = byte(aType)
|
|
||||||
|
|
||||||
// Now append the rest of the address bytes.
|
|
||||||
_, err := io.ReadFull(addrBuf, payload[1:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
address = &OpaqueAddrs{
|
|
||||||
Payload: payload,
|
|
||||||
}
|
|
||||||
addrBytesRead = addrsLen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addresses = append(addresses, address)
|
addresses = append(addresses, address)
|
||||||
@@ -949,3 +822,147 @@ func ReadElements(r io.Reader, elements ...interface{}) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAddress attempts to read a single address descriptor (as defined in
|
||||||
|
// Bolt 7) from the passed io.Reader. The total length of the address section
|
||||||
|
// (in bytes) must be provided so that we can ensure we don't read beyond the
|
||||||
|
// end of the address section. The number of bytes read from the reader and the
|
||||||
|
// parsed net.Addr are returned.
|
||||||
|
//
|
||||||
|
// NOTE: it is possible for the number of bytes read to be 1 even if a nil
|
||||||
|
// address is returned.
|
||||||
|
func ReadAddress(addrBuf io.Reader, addrsLen uint16) (uint16, net.Addr, error) {
|
||||||
|
var descriptor [1]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addrBytesRead := uint16(1)
|
||||||
|
|
||||||
|
var address net.Addr
|
||||||
|
switch aType := addressType(descriptor[0]); aType {
|
||||||
|
case noAddr:
|
||||||
|
return addrBytesRead, nil, nil
|
||||||
|
|
||||||
|
case tcp4Addr:
|
||||||
|
var ip [4]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &net.TCPAddr{
|
||||||
|
IP: net.IP(ip[:]),
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
}
|
||||||
|
addrBytesRead += tcp4AddrLen
|
||||||
|
|
||||||
|
case tcp6Addr:
|
||||||
|
var ip [16]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &net.TCPAddr{
|
||||||
|
IP: net.IP(ip[:]),
|
||||||
|
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||||
|
}
|
||||||
|
addrBytesRead += tcp6AddrLen
|
||||||
|
|
||||||
|
case v2OnionAddr:
|
||||||
|
var h [tor.V2DecodedLen]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var p [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||||
|
onionService += tor.OnionSuffix
|
||||||
|
port := int(binary.BigEndian.Uint16(p[:]))
|
||||||
|
|
||||||
|
address = &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
addrBytesRead += v2OnionAddrLen
|
||||||
|
|
||||||
|
case v3OnionAddr:
|
||||||
|
var h [tor.V3DecodedLen]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var p [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||||
|
onionService += tor.OnionSuffix
|
||||||
|
port := int(binary.BigEndian.Uint16(p[:]))
|
||||||
|
|
||||||
|
address = &tor.OnionAddr{
|
||||||
|
OnionService: onionService,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
addrBytesRead += v3OnionAddrLen
|
||||||
|
|
||||||
|
case dnsAddr:
|
||||||
|
var hostnameLen [1]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, hostnameLen[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname := make([]byte, hostnameLen[0])
|
||||||
|
if _, err := io.ReadFull(addrBuf, hostname); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &DNSAddress{
|
||||||
|
Hostname: string(hostname),
|
||||||
|
Port: binary.BigEndian.Uint16(port[:]),
|
||||||
|
}
|
||||||
|
addrBytesRead += dnsAddrOverhead + uint16(len(hostname))
|
||||||
|
|
||||||
|
default:
|
||||||
|
// If we don't understand this address type, we just store it
|
||||||
|
// along with the remaining address bytes as type OpaqueAddrs.
|
||||||
|
// We need to hold onto the bytes so that we can still write
|
||||||
|
// them back to the wire when we propagate this message.
|
||||||
|
payloadLen := 1 + addrsLen - addrBytesRead
|
||||||
|
payload := make([]byte, payloadLen)
|
||||||
|
|
||||||
|
// First write a byte for the address type that we already read.
|
||||||
|
payload[0] = byte(aType)
|
||||||
|
|
||||||
|
// Now append the rest of the address bytes.
|
||||||
|
if _, err := io.ReadFull(addrBuf, payload[1:]); err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address = &OpaqueAddrs{
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
addrBytesRead = addrsLen
|
||||||
|
}
|
||||||
|
|
||||||
|
return addrBytesRead, address, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user