Skip to content

Commit d61a8af

Browse files
committed
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.
1 parent ea6cc81 commit d61a8af

File tree

1 file changed

+154
-137
lines changed

1 file changed

+154
-137
lines changed

lnwire/lnwire.go

Lines changed: 154 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -744,146 +744,19 @@ func ReadElement(r io.Reader, element interface{}) error {
744744
)
745745

746746
for addrBytesRead < addrsLen {
747-
var descriptor [1]byte
748-
if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
749-
return err
747+
bytesRead, address, err := ReadAddress(
748+
addrBuf, addrsLen-addrBytesRead,
749+
)
750+
if err != nil {
751+
return fmt.Errorf("unable to read address: %w",
752+
err)
750753
}
754+
addrBytesRead += bytesRead
751755

752-
addrBytesRead++
753-
754-
var address net.Addr
755-
switch aType := addressType(descriptor[0]); aType {
756-
case noAddr:
756+
// If we encounter a noAddr descriptor, then we'll move
757+
// on to the next address.
758+
if address == nil {
757759
continue
758-
759-
case tcp4Addr:
760-
var ip [4]byte
761-
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
762-
return err
763-
}
764-
765-
var port [2]byte
766-
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
767-
return err
768-
}
769-
770-
address = &net.TCPAddr{
771-
IP: net.IP(ip[:]),
772-
Port: int(binary.BigEndian.Uint16(port[:])),
773-
}
774-
addrBytesRead += tcp4AddrLen
775-
776-
case tcp6Addr:
777-
var ip [16]byte
778-
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
779-
return err
780-
}
781-
782-
var port [2]byte
783-
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
784-
return err
785-
}
786-
787-
address = &net.TCPAddr{
788-
IP: net.IP(ip[:]),
789-
Port: int(binary.BigEndian.Uint16(port[:])),
790-
}
791-
addrBytesRead += tcp6AddrLen
792-
793-
case v2OnionAddr:
794-
var h [tor.V2DecodedLen]byte
795-
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
796-
return err
797-
}
798-
799-
var p [2]byte
800-
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
801-
return err
802-
}
803-
804-
onionService := tor.Base32Encoding.EncodeToString(h[:])
805-
onionService += tor.OnionSuffix
806-
port := int(binary.BigEndian.Uint16(p[:]))
807-
808-
address = &tor.OnionAddr{
809-
OnionService: onionService,
810-
Port: port,
811-
}
812-
addrBytesRead += v2OnionAddrLen
813-
814-
case v3OnionAddr:
815-
var h [tor.V3DecodedLen]byte
816-
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
817-
return err
818-
}
819-
820-
var p [2]byte
821-
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
822-
return err
823-
}
824-
825-
onionService := tor.Base32Encoding.EncodeToString(h[:])
826-
onionService += tor.OnionSuffix
827-
port := int(binary.BigEndian.Uint16(p[:]))
828-
829-
address = &tor.OnionAddr{
830-
OnionService: onionService,
831-
Port: port,
832-
}
833-
addrBytesRead += v3OnionAddrLen
834-
835-
case dnsAddr:
836-
var hostnameLen [1]byte
837-
_, err := io.ReadFull(addrBuf, hostnameLen[:])
838-
if err != nil {
839-
return err
840-
}
841-
842-
hostname := make([]byte, hostnameLen[0])
843-
_, err = io.ReadFull(addrBuf, hostname)
844-
if err != nil {
845-
return err
846-
}
847-
848-
var port [2]byte
849-
_, err = io.ReadFull(addrBuf, port[:])
850-
if err != nil {
851-
return err
852-
}
853-
854-
address = &DNSAddress{
855-
Hostname: string(hostname),
856-
Port: binary.BigEndian.Uint16(
857-
port[:],
858-
),
859-
}
860-
addrBytesRead += dnsAddrOverhead +
861-
uint16(len(hostname))
862-
863-
default:
864-
// If we don't understand this address type,
865-
// we just store it along with the remaining
866-
// address bytes as type OpaqueAddrs. We need
867-
// to hold onto the bytes so that we can still
868-
// write them back to the wire when we
869-
// propagate this message.
870-
payloadLen := 1 + addrsLen - addrBytesRead
871-
payload := make([]byte, payloadLen)
872-
873-
// First write a byte for the address type that
874-
// we already read.
875-
payload[0] = byte(aType)
876-
877-
// Now append the rest of the address bytes.
878-
_, err := io.ReadFull(addrBuf, payload[1:])
879-
if err != nil {
880-
return err
881-
}
882-
883-
address = &OpaqueAddrs{
884-
Payload: payload,
885-
}
886-
addrBytesRead = addrsLen
887760
}
888761

889762
addresses = append(addresses, address)
@@ -949,3 +822,147 @@ func ReadElements(r io.Reader, elements ...interface{}) error {
949822
}
950823
return nil
951824
}
825+
826+
// ReadAddress attempts to read a single address descriptor (as defined in
827+
// Bolt 7) from the passed io.Reader. The total length of the address section
828+
// (in bytes) must be provided so that we can ensure we don't read beyond the
829+
// end of the address section. The number of bytes read from the reader and the
830+
// parsed net.Addr are returned.
831+
//
832+
// NOTE: it is possible for the number of bytes read to be 1 even if a nil
833+
// address is returned.
834+
func ReadAddress(addrBuf io.Reader, addrsLen uint16) (uint16, net.Addr, error) {
835+
var descriptor [1]byte
836+
if _, err := io.ReadFull(addrBuf, descriptor[:]); err != nil {
837+
return 0, nil, err
838+
}
839+
840+
addrBytesRead := uint16(1)
841+
842+
var address net.Addr
843+
switch aType := addressType(descriptor[0]); aType {
844+
case noAddr:
845+
return addrBytesRead, nil, nil
846+
847+
case tcp4Addr:
848+
var ip [4]byte
849+
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
850+
return 0, nil, err
851+
}
852+
853+
var port [2]byte
854+
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
855+
return 0, nil, err
856+
}
857+
858+
address = &net.TCPAddr{
859+
IP: net.IP(ip[:]),
860+
Port: int(binary.BigEndian.Uint16(port[:])),
861+
}
862+
addrBytesRead += tcp4AddrLen
863+
864+
case tcp6Addr:
865+
var ip [16]byte
866+
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
867+
return 0, nil, err
868+
}
869+
870+
var port [2]byte
871+
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
872+
return 0, nil, err
873+
}
874+
875+
address = &net.TCPAddr{
876+
IP: net.IP(ip[:]),
877+
Port: int(binary.BigEndian.Uint16(port[:])),
878+
}
879+
addrBytesRead += tcp6AddrLen
880+
881+
case v2OnionAddr:
882+
var h [tor.V2DecodedLen]byte
883+
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
884+
return 0, nil, err
885+
}
886+
887+
var p [2]byte
888+
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
889+
return 0, nil, err
890+
}
891+
892+
onionService := tor.Base32Encoding.EncodeToString(h[:])
893+
onionService += tor.OnionSuffix
894+
port := int(binary.BigEndian.Uint16(p[:]))
895+
896+
address = &tor.OnionAddr{
897+
OnionService: onionService,
898+
Port: port,
899+
}
900+
addrBytesRead += v2OnionAddrLen
901+
902+
case v3OnionAddr:
903+
var h [tor.V3DecodedLen]byte
904+
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
905+
return 0, nil, err
906+
}
907+
908+
var p [2]byte
909+
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
910+
return 0, nil, err
911+
}
912+
913+
onionService := tor.Base32Encoding.EncodeToString(h[:])
914+
onionService += tor.OnionSuffix
915+
port := int(binary.BigEndian.Uint16(p[:]))
916+
917+
address = &tor.OnionAddr{
918+
OnionService: onionService,
919+
Port: port,
920+
}
921+
addrBytesRead += v3OnionAddrLen
922+
923+
case dnsAddr:
924+
var hostnameLen [1]byte
925+
if _, err := io.ReadFull(addrBuf, hostnameLen[:]); err != nil {
926+
return 0, nil, err
927+
}
928+
929+
hostname := make([]byte, hostnameLen[0])
930+
if _, err := io.ReadFull(addrBuf, hostname); err != nil {
931+
return 0, nil, err
932+
}
933+
934+
var port [2]byte
935+
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
936+
return 0, nil, err
937+
}
938+
939+
address = &DNSAddress{
940+
Hostname: string(hostname),
941+
Port: binary.BigEndian.Uint16(port[:]),
942+
}
943+
addrBytesRead += dnsAddrOverhead + uint16(len(hostname))
944+
945+
default:
946+
// If we don't understand this address type, we just store it
947+
// along with the remaining address bytes as type OpaqueAddrs.
948+
// We need to hold onto the bytes so that we can still write
949+
// them back to the wire when we propagate this message.
950+
payloadLen := 1 + addrsLen - addrBytesRead
951+
payload := make([]byte, payloadLen)
952+
953+
// First write a byte for the address type that we already read.
954+
payload[0] = byte(aType)
955+
956+
// Now append the rest of the address bytes.
957+
if _, err := io.ReadFull(addrBuf, payload[1:]); err != nil {
958+
return 0, nil, err
959+
}
960+
961+
address = &OpaqueAddrs{
962+
Payload: payload,
963+
}
964+
addrBytesRead = addrsLen
965+
}
966+
967+
return addrBytesRead, address, nil
968+
}

0 commit comments

Comments
 (0)