lnwire: add encoding/decoding for DNS addr
Co-authored-by: Elle Mouton <elle.mouton@gmail.com>
This commit is contained in:
1 parent
a0057c2026
commit
670b26ba3d
4 files changed
+117
-9
No files matched your search
@@ -44,6 +44,10 @@ const (
|
|||||||
// v3OnionAddrLen is the length of a version 3 Tor onion service address
|
// v3OnionAddrLen is the length of a version 3 Tor onion service address
|
||||||
// (35 bytes decoded onion + 2 bytes port).
|
// (35 bytes decoded onion + 2 bytes port).
|
||||||
v3OnionAddrLen = 37
|
v3OnionAddrLen = 37
|
||||||
|
|
||||||
|
// dnsAddrOverhead is the fixed overhead for a DNS address: 1 byte for
|
||||||
|
// the hostname length and 2 bytes for the port.
|
||||||
|
dnsAddrOverhead = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
// PkScript is simple type definition which represents a raw serialized public
|
// PkScript is simple type definition which represents a raw serialized public
|
||||||
@@ -70,6 +74,9 @@ const (
|
|||||||
|
|
||||||
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
||||||
v3OnionAddr addressType = 4
|
v3OnionAddr addressType = 4
|
||||||
|
|
||||||
|
// dnsAddr denotes a DNS address.
|
||||||
|
dnsAddr addressType = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteElement is a one-stop shop to write the big endian representation of
|
// WriteElement is a one-stop shop to write the big endian representation of
|
||||||
@@ -347,6 +354,11 @@ func WriteElement(w *bytes.Buffer, element interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case *DNSAddress:
|
||||||
|
if err := WriteDNSAddress(w, e); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
case *OpaqueAddrs:
|
case *OpaqueAddrs:
|
||||||
if err := WriteOpaqueAddrs(w, e); err != nil {
|
if err := WriteOpaqueAddrs(w, e); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -820,6 +832,34 @@ func ReadElement(r io.Reader, element interface{}) error {
|
|||||||
}
|
}
|
||||||
addrBytesRead += v3OnionAddrLen
|
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:
|
default:
|
||||||
// If we don't understand this address type,
|
// If we don't understand this address type,
|
||||||
// we just store it along with the remaining
|
// we just store it along with the remaining
|
||||||
|
|||||||
+20
-1
@@ -1000,13 +1000,32 @@ func randV3OnionAddr(t testing.TB, r *rand.Rand) *tor.OnionAddr {
|
|||||||
return &tor.OnionAddr{OnionService: onionService, Port: addrPort}
|
return &tor.OnionAddr{OnionService: onionService, Port: addrPort}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// randDNSAddr generates a random DNS address for testing purposes.
|
||||||
|
func randDNSAddr(t testing.TB, r *rand.Rand) *lnwire.DNSAddress {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
var domain [1]byte
|
||||||
|
_, err := r.Read(domain[:])
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var port [2]byte
|
||||||
|
_, err = r.Read(port[:])
|
||||||
|
require.NoError(t, err, "unable to read port")
|
||||||
|
|
||||||
|
return &lnwire.DNSAddress{
|
||||||
|
Hostname: string(domain[:]),
|
||||||
|
Port: uint16(port[0]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func randAddrs(t testing.TB, r *rand.Rand) []net.Addr {
|
func randAddrs(t testing.TB, r *rand.Rand) []net.Addr {
|
||||||
tcp4Addr := randTCP4Addr(t, r)
|
tcp4Addr := randTCP4Addr(t, r)
|
||||||
tcp6Addr := randTCP6Addr(t, r)
|
tcp6Addr := randTCP6Addr(t, r)
|
||||||
v2OnionAddr := randV2OnionAddr(t, r)
|
v2OnionAddr := randV2OnionAddr(t, r)
|
||||||
v3OnionAddr := randV3OnionAddr(t, r)
|
v3OnionAddr := randV3OnionAddr(t, r)
|
||||||
|
dnsAddr := randDNSAddr(t, r)
|
||||||
|
|
||||||
return []net.Addr{tcp4Addr, tcp6Addr, v2OnionAddr, v3OnionAddr}
|
return []net.Addr{tcp4Addr, tcp6Addr, v2OnionAddr, v3OnionAddr, dnsAddr}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randAlias(r *rand.Rand) lnwire.NodeAlias {
|
func randAlias(r *rand.Rand) lnwire.NodeAlias {
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ var (
|
|||||||
// ErrNilOpaqueAddrs is returned when the supplied address is nil.
|
// ErrNilOpaqueAddrs is returned when the supplied address is nil.
|
||||||
ErrNilOpaqueAddrs = errors.New("cannot write nil OpaqueAddrs")
|
ErrNilOpaqueAddrs = errors.New("cannot write nil OpaqueAddrs")
|
||||||
|
|
||||||
|
// ErrNilDNSAddress is returned when the supplied address is nil.
|
||||||
|
ErrNilDNSAddress = errors.New("cannot write nil DNS address")
|
||||||
|
|
||||||
// ErrNilPublicKey is returned when a nil pubkey is used.
|
// ErrNilPublicKey is returned when a nil pubkey is used.
|
||||||
ErrNilPublicKey = errors.New("cannot write nil pubkey")
|
ErrNilPublicKey = errors.New("cannot write nil pubkey")
|
||||||
|
|
||||||
@@ -364,6 +367,28 @@ func WriteOnionAddr(buf *bytes.Buffer, addr *tor.OnionAddr) error {
|
|||||||
return WriteUint16(buf, uint16(addr.Port))
|
return WriteUint16(buf, uint16(addr.Port))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteDNSAddress appends the DNS address to the provided buffer.
|
||||||
|
func WriteDNSAddress(buf *bytes.Buffer, addr *DNSAddress) error {
|
||||||
|
if addr == nil {
|
||||||
|
return ErrNilDNSAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the descriptor, the hostname length, and the hostname.
|
||||||
|
if _, err := buf.Write([]byte{byte(dnsAddr)}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := WriteUint8(buf, uint8(len(addr.Hostname))); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(addr.Hostname); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return WriteUint16(buf, addr.Port)
|
||||||
|
}
|
||||||
|
|
||||||
// WriteOpaqueAddrs appends the payload of the given OpaqueAddrs to buffer.
|
// WriteOpaqueAddrs appends the payload of the given OpaqueAddrs to buffer.
|
||||||
func WriteOpaqueAddrs(buf *bytes.Buffer, addr *OpaqueAddrs) error {
|
func WriteOpaqueAddrs(buf *bytes.Buffer, addr *OpaqueAddrs) error {
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
@@ -397,6 +422,10 @@ func WriteNetAddrs(buf *bytes.Buffer, addresses []net.Addr) error {
|
|||||||
if err := WriteOpaqueAddrs(addrBuf, a); err != nil {
|
if err := WriteOpaqueAddrs(addrBuf, a); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case *DNSAddress:
|
||||||
|
if err := WriteDNSAddress(addrBuf, a); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return ErrNilNetAddress
|
return ErrNilNetAddress
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-8
@@ -559,7 +559,8 @@ func TestWriteOnionAddr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteNetAddrs(t *testing.T) {
|
func TestWriteNetAddrs(t *testing.T) {
|
||||||
buf := new(bytes.Buffer)
|
t.Parallel()
|
||||||
|
|
||||||
tcpAddr := &net.TCPAddr{
|
tcpAddr := &net.TCPAddr{
|
||||||
IP: net.IP{127, 0, 0, 1},
|
IP: net.IP{127, 0, 0, 1},
|
||||||
Port: 8080,
|
Port: 8080,
|
||||||
@@ -568,6 +569,10 @@ func TestWriteNetAddrs(t *testing.T) {
|
|||||||
OnionService: "abcdefghijklmnop.onion",
|
OnionService: "abcdefghijklmnop.onion",
|
||||||
Port: 9065,
|
Port: 9065,
|
||||||
}
|
}
|
||||||
|
dnsAddr := &DNSAddress{
|
||||||
|
Hostname: "example.com",
|
||||||
|
Port: 8080,
|
||||||
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -587,24 +592,27 @@ func TestWriteNetAddrs(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// Check empty address slice.
|
// Check empty address slice.
|
||||||
name: "empty address slice",
|
name: "empty address slice",
|
||||||
addr: []net.Addr{},
|
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
// Use two bytes to encode the address size.
|
// Use two bytes to encode the address size.
|
||||||
expectedBytes: []byte{0, 0},
|
expectedBytes: []byte{0, 0},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Check a successful writes of a slice of addresses.
|
// Check a successful writes of a slice of addresses.
|
||||||
name: "two addresses",
|
name: "multiple addresses",
|
||||||
addr: []net.Addr{tcpAddr, onionAddr},
|
addr: []net.Addr{tcpAddr, onionAddr, dnsAddr},
|
||||||
expectedErr: nil,
|
expectedErr: nil,
|
||||||
expectedBytes: []byte{
|
expectedBytes: []byte{
|
||||||
// 7 bytes for TCP and 13 bytes for onion.
|
// 7 bytes for TCP and 13 bytes for onion,
|
||||||
0x0, 0x14,
|
// 15 bytes for DNS.
|
||||||
|
0x0, 0x23,
|
||||||
// TCP address.
|
// TCP address.
|
||||||
0x1, 0x7f, 0x0, 0x0, 0x1, 0x1f, 0x90,
|
0x1, 0x7f, 0x0, 0x0, 0x1, 0x1f, 0x90,
|
||||||
// Onion address.
|
// Onion address.
|
||||||
0x3, 0x0, 0x44, 0x32, 0x14, 0xc7, 0x42,
|
0x3, 0x0, 0x44, 0x32, 0x14, 0xc7, 0x42,
|
||||||
0x54, 0xb6, 0x35, 0xcf, 0x23, 0x69,
|
0x54, 0xb6, 0x35, 0xcf, 0x23, 0x69,
|
||||||
|
// DNS address.
|
||||||
|
0x5, 0xb, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
|
||||||
|
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x1f, 0x90,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -612,13 +620,25 @@ func TestWriteNetAddrs(t *testing.T) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
oldLen := buf.Len()
|
buf := new(bytes.Buffer)
|
||||||
|
|
||||||
err := WriteNetAddrs(buf, tc.addr)
|
err := WriteNetAddrs(buf, tc.addr)
|
||||||
require.Equal(t, tc.expectedErr, err)
|
require.Equal(t, tc.expectedErr, err)
|
||||||
|
|
||||||
bytesWritten := buf.Bytes()[oldLen:buf.Len()]
|
bytesWritten := buf.Bytes()[:buf.Len()]
|
||||||
require.Equal(t, tc.expectedBytes, bytesWritten)
|
require.Equal(t, tc.expectedBytes, bytesWritten)
|
||||||
|
|
||||||
|
if tc.expectedErr != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the addresses from the buffer and ensure
|
||||||
|
// they match the original addresses.
|
||||||
|
var addrs []net.Addr
|
||||||
|
err = ReadElement(buf, &addrs)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, tc.addr, addrs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user