• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 19155841408

07 Nov 2025 02:03AM UTC coverage: 66.675% (-0.04%) from 66.712%
19155841408

Pull #10352

github

web-flow
Merge e4313eba8 into 096ab65b1
Pull Request #10352: [WIP] chainrpc: return Unavailable while notifier starts

137328 of 205965 relevant lines covered (66.68%)

21333.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.16
/lnwire/dns_addr.go
1
package lnwire
2

3
import (
4
        "bytes"
5
        "errors"
6
        "fmt"
7
        "io"
8
        "net"
9
        "strconv"
10

11
        "github.com/lightningnetwork/lnd/tlv"
12
)
13

14
var (
15
        // ErrEmptyDNSHostname is returned when a DNS hostname is empty.
16
        ErrEmptyDNSHostname = errors.New("hostname cannot be empty")
17

18
        // ErrZeroPort is returned when a DNS port is zero.
19
        ErrZeroPort = errors.New("port cannot be zero")
20

21
        // ErrHostnameTooLong is returned when a DNS hostname exceeds 255 bytes.
22
        ErrHostnameTooLong = errors.New("DNS hostname length exceeds limit " +
23
                "of 255 bytes")
24

25
        // ErrInvalidHostnameCharacter is returned when a DNS hostname contains
26
        // an invalid character.
27
        ErrInvalidHostnameCharacter = errors.New("hostname contains invalid " +
28
                "character")
29
)
30

31
// DNSAddress is used to represent a DNS address of a node.
32
type DNSAddress struct {
33
        // Hostname is the DNS hostname of the address. This MUST only contain
34
        // ASCII characters as per Bolt #7. The maximum length that this may
35
        // be is 255 bytes.
36
        Hostname string
37

38
        // Port is the port number of the address.
39
        Port uint16
40
}
41

42
// A compile-time check to ensure that DNSAddress implements the net.Addr
43
// interface.
44
var _ net.Addr = (*DNSAddress)(nil)
45

46
// Network returns the network that this address uses, which is "tcp".
47
func (d *DNSAddress) Network() string {
×
48
        return "tcp"
×
49
}
×
50

51
// String returns the address in the form "hostname:port".
52
func (d *DNSAddress) String() string {
980✔
53
        return net.JoinHostPort(d.Hostname, strconv.Itoa(int(d.Port)))
980✔
54
}
980✔
55

56
// ValidateDNSAddr validates that the DNS hostname is not empty and contains
57
// only ASCII characters and of max length 255 characters and port is non zero
58
// according to BOLT #7.
59
func ValidateDNSAddr(hostname string, port uint16) error {
181✔
60
        if hostname == "" {
183✔
61
                return ErrEmptyDNSHostname
2✔
62
        }
2✔
63

64
        // Per BOLT 7, ports must not be zero for type 5 address (DNS address).
65
        if port == 0 {
181✔
66
                return ErrZeroPort
2✔
67
        }
2✔
68

69
        if len(hostname) > 255 {
178✔
70
                return fmt.Errorf("%w: DNS hostname length %d",
1✔
71
                        ErrHostnameTooLong, len(hostname))
1✔
72
        }
1✔
73

74
        // Check if hostname contains only ASCII characters.
75
        for i, r := range hostname {
11,302✔
76
                // Check for valid hostname characters, excluding ASCII control
11,126✔
77
                // characters (0-31), spaces, underscores, delete character
11,126✔
78
                // (127), and the special characters (like /, \, @, #, $, etc.).
11,126✔
79
                if !((r >= 'a' && r <= 'z') ||
11,126✔
80
                        (r >= 'A' && r <= 'Z') ||
11,126✔
81
                        (r >= '0' && r <= '9') ||
11,126✔
82
                        r == '-' ||
11,126✔
83
                        r == '.') {
11,136✔
84

10✔
85
                        return fmt.Errorf("%w: hostname '%s' contains invalid "+
10✔
86
                                "character '%c' at position %d",
10✔
87
                                ErrInvalidHostnameCharacter, hostname, r, i)
10✔
88
                }
10✔
89
        }
90

91
        return nil
166✔
92
}
93

94
// Record returns a TLV record that can be used to encode/decode the DNSAddress.
95
//
96
// NOTE: this is part of the tlv.RecordProducer interface.
97
func (d *DNSAddress) Record() tlv.Record {
484✔
98
        sizeFunc := func() uint64 {
539✔
99
                // Hostname length + 2 bytes for port.
55✔
100
                return uint64(len(d.Hostname) + 2)
55✔
101
        }
55✔
102

103
        return tlv.MakeDynamicRecord(
484✔
104
                0, d, sizeFunc, dnsAddressEncoder, dnsAddressDecoder,
484✔
105
        )
484✔
106
}
107

108
// dnsAddressEncoder is a TLV encoder for DNSAddress.
109
func dnsAddressEncoder(w io.Writer, val any, _ *[8]byte) error {
156✔
110
        if v, ok := val.(*DNSAddress); ok {
312✔
111
                var buf bytes.Buffer
156✔
112

156✔
113
                // Write the hostname as raw bytes (no length prefix for TLV).
156✔
114
                if _, err := buf.WriteString(v.Hostname); err != nil {
156✔
115
                        return err
×
116
                }
×
117

118
                // Write the port as 2 bytes.
119
                err := WriteUint16(&buf, v.Port)
156✔
120
                if err != nil {
156✔
121
                        return err
×
122
                }
×
123

124
                _, err = w.Write(buf.Bytes())
156✔
125

156✔
126
                return err
156✔
127
        }
128

129
        return tlv.NewTypeForEncodingErr(val, "DNSAddress")
×
130
}
131

132
// dnsAddressDecoder is a TLV decoder for DNSAddress.
133
func dnsAddressDecoder(r io.Reader, val any, _ *[8]byte,
134
        l uint64) error {
177✔
135

177✔
136
        if v, ok := val.(*DNSAddress); ok {
354✔
137
                if l < 2 {
180✔
138
                        return fmt.Errorf("DNS address must be at least 2 " +
3✔
139
                                "bytes")
3✔
140
                }
3✔
141

142
                // Read hostname (all bytes except last 2).
143
                hostnameLen := l - 2
174✔
144
                hostnameBytes := make([]byte, hostnameLen)
174✔
145
                if _, err := io.ReadFull(r, hostnameBytes); err != nil {
175✔
146
                        return err
1✔
147
                }
1✔
148
                v.Hostname = string(hostnameBytes)
173✔
149

173✔
150
                // Read port (last 2 bytes).
173✔
151
                if err := ReadElement(r, &v.Port); err != nil {
174✔
152
                        return err
1✔
153
                }
1✔
154

155
                return ValidateDNSAddr(v.Hostname, v.Port)
172✔
156
        }
157

158
        return tlv.NewTypeForDecodingErr(val, "DNSAddress", l, 0)
×
159
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc