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

lightningnetwork / lnd / 17949158775

23 Sep 2025 02:18PM UTC coverage: 66.713% (+0.07%) from 66.647%
17949158775

Pull #10232

github

web-flow
Merge fc770ddb4 into 82f77e542
Pull Request #10232: lnwire: add missing Gossip 1.75 fields and message

491 of 568 new or added lines in 19 files covered. (86.44%)

64 existing lines in 19 files now uncovered.

136915 of 205230 relevant lines covered (66.71%)

21387.93 hits per line

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

79.01
/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 {
44✔
53
        return net.JoinHostPort(d.Hostname, strconv.Itoa(int(d.Port)))
44✔
54
}
44✔
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 {
9✔
60
        if hostname == "" {
10✔
61
                return ErrEmptyDNSHostname
1✔
62
        }
1✔
63

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

69
        if len(hostname) > 255 {
8✔
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 {
82✔
76
                // Check for valid hostname characters, excluding ASCII control
76✔
77
                // characters (0-31), spaces, underscores, delete character
76✔
78
                // (127), and the special characters (like /, \, @, #, $, etc.).
76✔
79
                if !((r >= 'a' && r <= 'z') ||
76✔
80
                        (r >= 'A' && r <= 'Z') ||
76✔
81
                        (r >= '0' && r <= '9') ||
76✔
82
                        r == '-' ||
76✔
83
                        r == '.') {
79✔
84

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

91
        return nil
3✔
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 {
362✔
98
        sizeFunc := func() uint64 {
418✔
99
                // Hostname length + 2 bytes for port.
56✔
100
                return uint64(len(d.Hostname) + 2)
56✔
101
        }
56✔
102

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

108
// dnsAddressEncoder is a TLV encoder for DNSAddress.
109
func dnsAddressEncoder(w io.Writer, val interface{}, _ *[8]byte) error {
157✔
110
        if v, ok := val.(*DNSAddress); ok {
314✔
111
                // Write the hostname as raw bytes (no length prefix for TLV).
157✔
112
                if _, err := w.Write([]byte(v.Hostname)); err != nil {
157✔
NEW
113
                        return err
×
NEW
114
                }
×
115

116
                // Write the port as 2 bytes.
117
                var portBytes [2]byte
157✔
118
                err := WriteUint16(bytes.NewBuffer(portBytes[:0]), v.Port)
157✔
119
                if err != nil {
157✔
NEW
120
                        return err
×
NEW
121
                }
×
122

123
                if _, err := w.Write(portBytes[:]); err != nil {
157✔
NEW
124
                        return err
×
NEW
125
                }
×
126

127
                return nil
157✔
128
        }
129

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

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

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

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

157✔
151
                // Read port (last 2 bytes).
157✔
152
                var portBytes [2]byte
157✔
153
                if _, err := io.ReadFull(r, portBytes[:]); err != nil {
157✔
NEW
154
                        return err
×
NEW
155
                }
×
156

157
                buf := bytes.NewReader(portBytes[:])
157✔
158
                if err := ReadElement(buf, &v.Port); err != nil {
157✔
NEW
159
                        return err
×
NEW
160
                }
×
161

162
                return nil
157✔
163
        }
164

NEW
165
        return tlv.NewTypeForDecodingErr(val, "DNSAddress", l, 0)
×
166
}
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