From aa7d4d14fd81dfe8ccee377fcfc060b25e188a13 Mon Sep 17 00:00:00 2001 From: Joe Turki Date: Mon, 27 Jan 2025 15:13:22 -0600 Subject: [PATCH] Upgrade golangci-lint, more linters Introduces new linters, upgrade golangci-lint to version (v1.63.4) --- .golangci.yml | 47 +++++---- config.go | 4 +- conn.go | 212 ++++++++++++++++++++++++++++------------- conn_test.go | 178 +++++++++++++++++----------------- examples/query/main.go | 2 +- 5 files changed, 273 insertions(+), 170 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index a3235be..88cb4fb 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -25,17 +25,32 @@ linters-settings: - ^os.Exit$ - ^panic$ - ^print(ln)?$ + varnamelen: + max-distance: 12 + min-name-length: 2 + ignore-type-assert-ok: true + ignore-map-index-ok: true + ignore-chan-recv-ok: true + ignore-decls: + - i int + - n int + - w io.Writer + - r io.Reader + - b []byte linters: enable: - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - bodyclose # checks whether HTTP response body is closed successfully + - containedctx # containedctx is a linter that detects struct contained context.Context field - contextcheck # check the function whether use a non-inherited context + - cyclop # checks function and package cyclomatic complexity - decorder # check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together + - err113 # Golang linter to check the errors handling expressions - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occations, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. @@ -46,18 +61,17 @@ linters: - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - gochecknoglobals # Checks that no globals are present in Go code - - gochecknoinits # Checks that no init functions are present in Go code - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter + - gocyclo # Computes and checks the cyclomatic complexity of functions + - godot # Check if comments end in a period - godox # Tool for detection of FIXME, TODO and other comment keywords - - err113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems - gosimple # Linter for Go source code that specializes in simplifying a code @@ -65,9 +79,15 @@ linters: - grouper # An analyzer to analyze expression groups. - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + - lll # Reports long lines + - maintidx # maintidx measures the maintainability index of each function. + - makezero # Finds slice declarations with non-zero initial length - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. + - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - noctx # noctx finds sending http request without context.Context - predeclared # find code that shadows one of Go's predeclared identifiers - revive # golint replacement, finds style mistakes @@ -75,28 +95,22 @@ linters: - stylecheck # Stylecheck is a replacement for golint - tagliatelle # Checks the struct tags. - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types + - varnamelen # checks that the length of a variable's name matches its scope - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - depguard # Go linter that checks if package imports are in a list of acceptable packages - - containedctx # containedctx is a linter that detects struct contained context.Context field - - cyclop # checks function and package cyclomatic complexity - funlen # Tool for detection of long functions - - gocyclo # Computes and checks the cyclomatic complexity of functions - - godot # Check if comments end in a period - - gomnd # An analyzer to detect magic numbers. + - gochecknoinits # Checks that no init functions are present in Go code + - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. + - interfacebloat # A linter that checks length of interface. - ireturn # Accept Interfaces, Return Concrete Types - - lll # Reports long lines - - maintidx # maintidx measures the maintainability index of each function. - - makezero # Finds slice declarations with non-zero initial length - - nakedret # Finds naked returns in functions greater than a specified function length - - nestif # Reports deeply nested if statements - - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - mnd # An analyzer to detect magic numbers - nolintlint # Reports ill-formed or insufficient nolint directives - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated @@ -104,8 +118,7 @@ linters: - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - testpackage # linter that makes you use a separate _test package - - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - - varnamelen # checks that the length of a variable's name matches its scope + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - wrapcheck # Checks that errors returned from external packages are wrapped - wsl # Whitespace Linter - Forces you to use empty lines! diff --git a/config.go b/config.go index 4659e06..1356fab 100644 --- a/config.go +++ b/config.go @@ -13,12 +13,12 @@ import ( const ( // DefaultAddressIPv4 is the default used by mDNS // and in most cases should be the address that the - // ipv4.PacketConn passed to Server is bound to + // ipv4.PacketConn passed to Server is bound to. DefaultAddressIPv4 = "224.0.0.0:5353" // DefaultAddressIPv6 is the default IPv6 address used // by mDNS and in most cases should be the address that - // the ipv6.PacketConn passed to Server is bound to + // the ipv6.PacketConn passed to Server is bound to. DefaultAddressIPv6 = "[FF02::]:5353" ) diff --git a/conn.go b/conn.go index 7211ac5..509e4f4 100644 --- a/conn.go +++ b/conn.go @@ -18,7 +18,7 @@ import ( "golang.org/x/net/ipv6" ) -// Conn represents a mDNS Server +// Conn represents a mDNS Server. type Conn struct { mu sync.RWMutex name string @@ -86,7 +86,7 @@ type netInterface struct { // sent if an ipv4.PacketConn is also provided. In the future, we may // add a QueryAddr method that allows specifying this more clearly. // -//nolint:gocognit +//nolint:gocognit,gocyclo,cyclop,maintidx func Server( multicastPktConnV4 *ipv4.PacketConn, multicastPktConnV6 *ipv6.PacketConn, @@ -101,14 +101,14 @@ func Server( } log := loggerFactory.NewLogger("mdns") - c := &Conn{ + conn := &Conn{ queryInterval: defaultQueryInterval, log: log, closed: make(chan interface{}), } - c.name = config.Name - if c.name == "" { - c.name = fmt.Sprintf("%p", &c) + conn.name = config.Name + if conn.name == "" { + conn.name = fmt.Sprintf("%p", &conn) } if multicastPktConnV4 == nil && multicastPktConnV6 == nil { @@ -133,7 +133,10 @@ func Server( unicastConnV4, err := net.ListenUDP("udp4", addr4) if err != nil { - log.Warnf("[%s] failed to listen on unicast IPv4 %s: %s; will not be able to receive unicast responses on IPv4", c.name, addr4, err) + log.Warnf( + "[%s] failed to listen on unicast IPv4 %s: %s; will not be able to receive unicast responses on IPv4", + conn.name, addr4, err, + ) } else { unicastPktConnV4 = ipv4.NewPacketConn(unicastConnV4) } @@ -148,7 +151,10 @@ func Server( unicastConnV6, err := net.ListenUDP("udp6", addr6) if err != nil { - log.Warnf("[%s] failed to listen on unicast IPv6 %s: %s; will not be able to receive unicast responses on IPv6", c.name, addr6, err) + log.Warnf( + "[%s] failed to listen on unicast IPv6 %s: %s; will not be able to receive unicast responses on IPv6", + conn.name, addr6, err, + ) } else { unicastPktConnV6 = ipv6.NewPacketConn(unicastConnV6) } @@ -226,6 +232,7 @@ func Server( } if !atLeastOneJoin { joinErrCount++ + continue } @@ -268,73 +275,98 @@ func Server( localNames = append(localNames, l+".") } - c.dstAddr4 = dstAddr4 - c.dstAddr6 = dstAddr6 - c.localNames = localNames - c.ifaces = ifacesToUse + conn.dstAddr4 = dstAddr4 + conn.dstAddr6 = dstAddr6 + conn.localNames = localNames + conn.ifaces = ifacesToUse if config.QueryInterval != 0 { - c.queryInterval = config.QueryInterval + conn.queryInterval = config.QueryInterval } if multicastPktConnV4 != nil { if err := multicastPktConnV4.SetControlMessage(ipv4.FlagInterface, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on multicast IPv4 PacketConn %v", c.name, err) + conn.log.Warnf( + "[%s] failed to SetControlMessage(ipv4.FlagInterface) on multicast IPv4 PacketConn %v", + conn.name, err, + ) } if err := multicastPktConnV4.SetControlMessage(ipv4.FlagDst, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagDst) on multicast IPv4 PacketConn %v", c.name, err) + conn.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagDst) on multicast IPv4 PacketConn %v", conn.name, err) } - c.multicastPktConnV4 = ipPacketConn4{c.name, multicastPktConnV4, log} + conn.multicastPktConnV4 = ipPacketConn4{conn.name, multicastPktConnV4, log} } if multicastPktConnV6 != nil { if err := multicastPktConnV6.SetControlMessage(ipv6.FlagInterface, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", c.name, err) + conn.log.Warnf( + "[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", + conn.name, err, + ) } if err := multicastPktConnV6.SetControlMessage(ipv6.FlagDst, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", c.name, err) + conn.log.Warnf( + "[%s] failed to SetControlMessage(ipv6.FlagInterface) on multicast IPv6 PacketConn %v", + conn.name, err, + ) } - c.multicastPktConnV6 = ipPacketConn6{c.name, multicastPktConnV6, log} + conn.multicastPktConnV6 = ipPacketConn6{conn.name, multicastPktConnV6, log} } if unicastPktConnV4 != nil { if err := unicastPktConnV4.SetControlMessage(ipv4.FlagInterface, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", c.name, err) + conn.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", conn.name, err) } if err := unicastPktConnV4.SetControlMessage(ipv4.FlagDst, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", c.name, err) + conn.log.Warnf("[%s] failed to SetControlMessage(ipv4.FlagInterface) on unicast IPv4 PacketConn %v", conn.name, err) } - c.unicastPktConnV4 = ipPacketConn4{c.name, unicastPktConnV4, log} + conn.unicastPktConnV4 = ipPacketConn4{conn.name, unicastPktConnV4, log} } if unicastPktConnV6 != nil { if err := unicastPktConnV6.SetControlMessage(ipv6.FlagInterface, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", c.name, err) + conn.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", conn.name, err) } if err := unicastPktConnV6.SetControlMessage(ipv6.FlagDst, true); err != nil { - c.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", c.name, err) + conn.log.Warnf("[%s] failed to SetControlMessage(ipv6.FlagInterface) on unicast IPv6 PacketConn %v", conn.name, err) } - c.unicastPktConnV6 = ipPacketConn6{c.name, unicastPktConnV6, log} + conn.unicastPktConnV6 = ipPacketConn6{conn.name, unicastPktConnV6, log} } - if config.IncludeLoopback { + if config.IncludeLoopback { //nolint:nestif // this is an efficient way for us to send ourselves a message faster instead of it going // further out into the network stack. if multicastPktConnV4 != nil { if err := multicastPktConnV4.SetMulticastLoopback(true); err != nil { - c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on multicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + conn.log.Warnf( + //nolint:lll + "[%s] failed to SetMulticastLoopback(true) on multicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", + conn.name, err, + ) } } if multicastPktConnV6 != nil { if err := multicastPktConnV6.SetMulticastLoopback(true); err != nil { - c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on multicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + conn.log.Warnf( + //nolint:lll + "[%s] failed to SetMulticastLoopback(true) on multicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", + conn.name, err, + ) } } if unicastPktConnV4 != nil { if err := unicastPktConnV4.SetMulticastLoopback(true); err != nil { - c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on unicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + conn.log.Warnf( + //nolint:lll + "[%s] failed to SetMulticastLoopback(true) on unicast IPv4 PacketConn %v; this may cause inefficient network path c.name,communications", + conn.name, err, + ) } } if unicastPktConnV6 != nil { if err := unicastPktConnV6.SetMulticastLoopback(true); err != nil { - c.log.Warnf("[%s] failed to SetMulticastLoopback(true) on unicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", c.name, err) + conn.log.Warnf( + //nolint:lll + "[%s] failed to SetMulticastLoopback(true) on unicast IPv6 PacketConn %v; this may cause inefficient network path c.name,communications", + conn.name, err, + ) } } } @@ -344,13 +376,14 @@ func Server( // physical interface, less the space required for the IP header (20 // bytes for IPv4; 40 bytes for IPv6) and the UDP header (8 bytes). started := make(chan struct{}) - go c.start(started, inboundBufferSize-20-8, config) + go conn.start(started, inboundBufferSize-20-8, config) <-started - return c, nil + + return conn, nil } -// Close closes the mDNS Conn -func (c *Conn) Close() error { +// Close closes the mDNS Conn. +func (c *Conn) Close() error { //nolint:cyclop select { case <-c.closed: return nil @@ -385,6 +418,7 @@ func (c *Conn) Close() error { if len(errs) == 0 { <-c.closed + return nil } @@ -392,6 +426,7 @@ func (c *Conn) Close() error { for _, err := range errs { rtrn = fmt.Errorf("%w\n%w", err, rtrn) } + return rtrn } @@ -404,6 +439,7 @@ func (c *Conn) Query(ctx context.Context, name string) (dnsmessage.ResourceHeade if err != nil { return header, nil, err } + return header, &net.IPAddr{ IP: addr.AsSlice(), Zone: addr.Zone(), @@ -411,7 +447,7 @@ func (c *Conn) Query(ctx context.Context, name string) (dnsmessage.ResourceHeade } // QueryAddr sends mDNS Queries for the following name until -// either the Context is canceled/expires or we get a result +// either the Context is canceled/expires or we get a result. func (c *Conn) QueryAddr(ctx context.Context, name string) (dnsmessage.ResourceHeader, netip.Addr, error) { select { case <-c.closed: @@ -469,7 +505,7 @@ func (err ipToBytesError) Error() string { return fmt.Sprintf("ip (%s) is not %s", err.addr, err.expectedType) } -// assumes ipv4-to-ipv6 mapping has been checked +// assumes ipv4-to-ipv6 mapping has been checked. func ipv4ToBytes(ipAddr netip.Addr) ([4]byte, error) { if !ipAddr.Is4() { return [4]byte{}, ipToBytesError{ipAddr, "IPv4"} @@ -483,10 +519,11 @@ func ipv4ToBytes(ipAddr netip.Addr) ([4]byte, error) { // net.IPs are stored in big endian / network byte order var out [4]byte copy(out[:], md) + return out, nil } -// assumes ipv4-to-ipv6 mapping has been checked +// assumes ipv4-to-ipv6 mapping has been checked. func ipv6ToBytes(ipAddr netip.Addr) ([16]byte, error) { if !ipAddr.Is6() { return [16]byte{}, ipToBytesError{ipAddr, "IPv6"} @@ -499,6 +536,7 @@ func ipv6ToBytes(ipAddr netip.Addr) ([16]byte, error) { // net.IPs are stored in big endian / network byte order var out [16]byte copy(out[:], md) + return out, nil } @@ -530,6 +568,7 @@ func interfaceForRemote(remote string) (*netip.Addr, error) { return nil, ipToAddrError{localAddr.IP} } ipAddr = addrWithOptionalZone(ipAddr, localAddr.Zone) + return &ipAddr, nil } @@ -544,6 +583,7 @@ func (c *Conn) sendQuestion(name string) { packedName, err := dnsmessage.NewName(name) if err != nil { c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return } @@ -587,13 +627,14 @@ func (c *Conn) sendQuestion(name string) { rawQuery, err := msg.Pack() if err != nil { c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return } c.writeToSocket(-1, rawQuery, false, false, writeTypeQuestion, nil) } -//nolint:gocognit +//nolint:gocognit,gocyclo,cyclop func (c *Conn) writeToSocket( ifIndex int, b []byte, @@ -603,7 +644,7 @@ func (c *Conn) writeToSocket( unicastDst *net.UDPAddr, ) { var dst4, dst6 net.Addr - if wType == writeTypeAnswer { + if wType == writeTypeAnswer { //nolint:nestif if unicastDst == nil { dst4 = c.dstAddr4 dst6 = c.dstAddr6 @@ -616,20 +657,23 @@ func (c *Conn) writeToSocket( } } - if ifIndex != -1 { + if ifIndex != -1 { //nolint:nestif if wType == writeTypeQuestion { c.log.Errorf("[%s] Unexpected question using specific interface index %d; dropping question", c.name, ifIndex) + return } ifc, ok := c.ifaces[ifIndex] if !ok { c.log.Warnf("[%s] no interface for %d", c.name, ifIndex) + return } if hasLoopbackData && ifc.Flags&net.FlagLoopback == 0 { // avoid accidentally tricking the destination that itself is the same as us c.log.Debugf("[%s] interface is not loopback %d", c.name, ifIndex) + return } @@ -656,10 +700,11 @@ func (c *Conn) writeToSocket( ifc := c.ifaces[ifcIdx] if hasLoopbackData { c.log.Debugf("[%s] Refusing to send loopback data with non-specific interface", c.name) + continue } - if wType == writeTypeQuestion { + if wType == writeTypeQuestion { //nolint:nestif // we'll write via unicast if we can in case the responder chooses to respond to the address the request // came from (i.e. not respecting unicast-response bit). If we were to use the multicast packet // conn here, we'd be writing from a specific multicast address which won't be able to receive unicast @@ -761,12 +806,14 @@ func (c *Conn) sendAnswer(queryID uint16, name string, ifIndex int, result netip answer, err := createAnswer(queryID, name, result) if err != nil { c.log.Warnf("[%s] failed to create mDNS answer %v", c.name, err) + return } rawAnswer, err := answer.Pack() if err != nil { c.log.Warnf("[%s] failed to construct mDNS packet %v", c.name, err) + return } @@ -802,6 +849,7 @@ func (c ipPacketConn4) ReadFrom(b []byte) (n int, cm *ipControlMessage, src net. if err != nil || cm4 == nil { return n, nil, src, err } + return n, &ipControlMessage{IfIndex: cm4.IfIndex, Dst: cm4.Dst}, src, err } @@ -814,8 +862,10 @@ func (c ipPacketConn4) WriteTo(b []byte, via *net.Interface, cm *ipControlMessag } if err := c.conn.SetMulticastInterface(via); err != nil { c.log.Warnf("[%s] failed to set multicast interface for %d: %v", c.name, via.Index, err) + return 0, err } + return c.conn.WriteTo(b, cm4, dst) } @@ -834,6 +884,7 @@ func (c ipPacketConn6) ReadFrom(b []byte) (n int, cm *ipControlMessage, src net. if err != nil || cm6 == nil { return n, nil, src, err } + return n, &ipControlMessage{IfIndex: cm6.IfIndex, Dst: cm6.Dst}, src, err } @@ -846,8 +897,10 @@ func (c ipPacketConn6) WriteTo(b []byte, via *net.Interface, cm *ipControlMessag } if err := c.conn.SetMulticastInterface(via); err != nil { c.log.Warnf("[%s] failed to set multicast interface for %d: %v", c.name, via.Index, err) + return 0, err } + return c.conn.WriteTo(b, cm6, dst) } @@ -855,9 +908,10 @@ func (c ipPacketConn6) Close() error { return c.conn.Close() } -func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int, config *Config) { //nolint:gocognit +//nolint:gocognit,gocyclo,cyclop,maintidx +func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int, config *Config) { b := make([]byte, inboundBufferSize) - p := dnsmessage.Parser{} + parser := dnsmessage.Parser{} for { n, cm, src, err := pktConn.ReadFrom(b) @@ -866,6 +920,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int return } c.log.Warnf("[%s] failed to ReadFrom %q %v", c.name, src, err) + continue } c.log.Debugf("[%s] got read on %s from %s", c.name, name, src) @@ -881,26 +936,29 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int srcAddr, ok := src.(*net.UDPAddr) if !ok { c.log.Warnf("[%s] expected source address %s to be UDP but got %", c.name, src, src) + continue } func() { - header, err := p.Start(b[:n]) + header, err := parser.Start(b[:n]) if err != nil { c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return } for i := 0; i <= maxMessageRecords; i++ { - q, err := p.Question() + question, err := parser.Question() if errors.Is(err, dnsmessage.ErrSectionDone) { break } else if err != nil { c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return } - if q.Type != dnsmessage.TypeA && q.Type != dnsmessage.TypeAAAA { + if question.Type != dnsmessage.TypeA && question.Type != dnsmessage.TypeAAAA { continue } @@ -910,7 +968,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int // multicast address 224.0.0.251 or its IPv6 equivalent FF02::FB, except // when generating a reply to a query that explicitly requested a // unicast response - shouldUnicastResponse := (q.Class&(1<<15)) != 0 || // via the unicast-response bit + shouldUnicastResponse := (question.Class&(1<<15)) != 0 || // via the unicast-response bit srcAddr.Port != 5353 || // by virtue of being a legacy query (Section 6.7), or (len(pktDst) != 0 && !(pktDst.Equal(c.dstAddr4.IP) || // by virtue of being a direct unicast query pktDst.Equal(c.dstAddr6.IP))) @@ -919,10 +977,10 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int dst = srcAddr } - queryWantsV4 := q.Type == dnsmessage.TypeA + queryWantsV4 := question.Type == dnsmessage.TypeA for _, localName := range c.localNames { - if localName == q.Name.String() { + if localName == question.Name.String() { //nolint:nestif var localAddress *netip.Addr if config.LocalAddress != nil { // this means the LocalAddress does not support link-local since @@ -930,6 +988,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int ipAddr, ok := netip.AddrFromSlice(config.LocalAddress) if !ok { c.log.Warnf("[%s] failed to convert config.LocalAddress '%s' to netip.Addr", c.name, config.LocalAddress) + continue } if c.multicastPktConnV4 != nil { @@ -952,6 +1011,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int ifc, ok := c.ifaces[ifIndex] if !ok { c.log.Warnf("[%s] no interface for %d", c.name, ifIndex) + return } var selectedAddrs []netip.Addr @@ -973,6 +1033,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int } if !isSupportedIPv6(addrCopy, c.multicastPktConnV4 == nil) { c.log.Debugf("[%s] interface %d address not a supported IPv6 address %s", c.name, ifIndex, &addrCopy) + continue } } @@ -980,7 +1041,10 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int selectedAddrs = append(selectedAddrs, addrCopy) } if len(selectedAddrs) == 0 { - c.log.Debugf("[%s] failed to find suitable IP for interface %d; deriving address from source address c.name,instead", c.name, ifIndex) + c.log.Debugf( + "[%s] failed to find suitable IP for interface %d; deriving address from source address c.name,instead", + c.name, ifIndex, + ) } else { // choose the best match var choice *netip.Addr @@ -989,6 +1053,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int if option.Is4() { // select first choice = &optCopy + break } // we're okay with 4In6 for now but ideally we get a an actual IPv6. @@ -1011,22 +1076,32 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int localAddress, err = interfaceForRemote(src.String()) if err != nil { c.log.Warnf("[%s] failed to get local interface to communicate with %s: %v", c.name, src.String(), err) + continue } } } if queryWantsV4 { if !localAddress.Is4() { - c.log.Debugf("[%s] have IPv6 address %s to respond with but question is for A not c.name,AAAA", c.name, localAddress) + c.log.Debugf( + "[%s] have IPv6 address %s to respond with but question is for A not c.name,AAAA", + c.name, localAddress, + ) + continue } } else { if !localAddress.Is6() { - c.log.Debugf("[%s] have IPv4 address %s to respond with but question is for AAAA not c.name,A", c.name, localAddress) + c.log.Debugf( + "[%s] have IPv4 address %s to respond with but question is for AAAA not c.name,A", + c.name, localAddress, + ) + continue } if !isSupportedIPv6(*localAddress, c.multicastPktConnV4 == nil) { c.log.Debugf("[%s] got local interface address but not a supported IPv6 address %v", c.name, localAddress) + continue } } @@ -1040,25 +1115,30 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int // the other side can only infer this via the response interface on the other // side (some IPv6 interface). c.log.Debugf("[%s] refusing to send link-local address %s to an IPv4 destination %s", c.name, localAddress, dst) + continue } - c.log.Debugf("[%s] sending response for %s on ifc %d of %s to %s", c.name, q.Name, ifIndex, *localAddress, dst) - c.sendAnswer(header.ID, q.Name.String(), ifIndex, *localAddress, dst) + c.log.Debugf( + "[%s] sending response for %s on ifc %d of %s to %s", + c.name, question.Name, ifIndex, *localAddress, dst, + ) + c.sendAnswer(header.ID, question.Name.String(), ifIndex, *localAddress, dst) } } } for i := 0; i <= maxMessageRecords; i++ { - a, err := p.AnswerHeader() + answer, err := parser.AnswerHeader() if errors.Is(err, dnsmessage.ErrSectionDone) { return } if err != nil { c.log.Warnf("[%s] failed to parse mDNS packet %v", c.name, err) + return } - if a.Type != dnsmessage.TypeA && a.Type != dnsmessage.TypeAAAA { + if answer.Type != dnsmessage.TypeA && answer.Type != dnsmessage.TypeAAAA { continue } @@ -1070,10 +1150,11 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int var answered []*query for _, query := range queries { queryCopy := query - if queryCopy.nameWithSuffix == a.Name.String() { - addr, err := addrFromAnswerHeader(a, p) + if queryCopy.nameWithSuffix == answer.Name.String() { + addr, err := addrFromAnswerHeader(answer, parser) if err != nil { c.log.Warnf("[%s] failed to parse mDNS answer %v", c.name, err) + return } @@ -1086,7 +1167,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int resultAddr = addrWithOptionalZone(resultAddr, srcAddr.Zone) select { - case queryCopy.queryResultChan <- queryResult{a, resultAddr}: + case queryCopy.queryResultChan <- queryResult{answer, resultAddr}: answered = append(answered, queryCopy) default: } @@ -1100,6 +1181,7 @@ func (c *Conn) readLoop(name string, pktConn ipPacketConn, inboundBufferSize int c.queries = append(c.queries[:queryIdx], c.queries[queryIdx+1:]...) answered = append(answered[:answerIdx], answered[answerIdx+1:]...) queryIdx-- + break } } @@ -1170,10 +1252,10 @@ func (c *Conn) start(started chan<- struct{}, inboundBufferSize int, config *Con } } -func addrFromAnswerHeader(a dnsmessage.ResourceHeader, p dnsmessage.Parser) (addr *netip.Addr, err error) { - switch a.Type { +func addrFromAnswerHeader(header dnsmessage.ResourceHeader, parser dnsmessage.Parser) (addr *netip.Addr, err error) { + switch header.Type { case dnsmessage.TypeA: - resource, err := p.AResource() + resource, err := parser.AResource() if err != nil { return nil, err } @@ -1185,7 +1267,7 @@ func addrFromAnswerHeader(a dnsmessage.ResourceHeader, p dnsmessage.Parser) (add return &ipAddr, nil case dnsmessage.TypeAAAA: - resource, err := p.AAAAResource() + resource, err := parser.AAAAResource() if err != nil { return nil, err } @@ -1196,7 +1278,7 @@ func addrFromAnswerHeader(a dnsmessage.ResourceHeader, p dnsmessage.Parser) (add return &ipAddr, nil default: - return nil, fmt.Errorf("unsupported record type %d", a.Type) //nolint:err113 // Never happens + return nil, fmt.Errorf("unsupported record type %d", header.Type) //nolint:err113 // Never happens } } @@ -1209,6 +1291,7 @@ func isSupportedIPv6(addr netip.Addr, ipv6Only bool) bool { if !ipv6Only && addr.Is4In6() { return false } + return true } @@ -1219,5 +1302,6 @@ func addrWithOptionalZone(addr netip.Addr, zone string) netip.Addr { if addr.Is6() && (addr.IsLinkLocalUnicast() || addr.IsLinkLocalMulticast()) { return addr.WithZone(zone) } + return addr } diff --git a/conn_test.go b/conn_test.go index 2ae4e18..b6685ad 100644 --- a/conn_test.go +++ b/conn_test.go @@ -24,21 +24,21 @@ import ( const localAddress = "1.2.3.4" -func check(err error, t *testing.T) { +func check(t *testing.T, err error) { t.Helper() if err != nil { t.Fatal(err) } } -func checkIPv4(addr netip.Addr, t *testing.T) { +func checkIPv4(t *testing.T, addr netip.Addr) { t.Helper() if !addr.Is4() { t.Fatalf("expected IPv4 for answer but got %s", addr) } } -func checkIPv6(addr netip.Addr, t *testing.T) { +func checkIPv6(t *testing.T, addr netip.Addr) { t.Helper() if !addr.Is6() { t.Fatalf("expected IPv6 for answer but got %s", addr) @@ -46,21 +46,23 @@ func checkIPv6(addr netip.Addr, t *testing.T) { } func createListener4(t *testing.T) *net.UDPConn { + t.Helper() addr, err := net.ResolveUDPAddr("udp", DefaultAddressIPv4) - check(err, t) + check(t, err) sock, err := net.ListenUDP("udp4", addr) - check(err, t) + check(t, err) return sock } func createListener6(t *testing.T) *net.UDPConn { + t.Helper() addr, err := net.ResolveUDPAddr("udp", DefaultAddressIPv6) - check(err, t) + check(t, err) sock, err := net.ListenUDP("udp6", addr) - check(err, t) + check(t, err) return sock } @@ -78,24 +80,24 @@ func TestValidCommunication(t *testing.T) { aServer, err := Server(ipv4.NewPacketConn(aSock), nil, &Config{ LocalNames: []string{"pion-mdns-1.local", "pion-mdns-2.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(ipv4.NewPacketConn(bSock), nil, &Config{}) - check(err, t) + check(t, err) _, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } - checkIPv4(addr, t) + checkIPv4(t, addr) _, addr, err = bServer.QueryAddr(context.TODO(), "pion-mdns-2.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } - checkIPv4(addr, t) + checkIPv4(t, addr) // test against regression from https://github.com/pion/mdns/commit/608f20b // where by properly sending mDNS responses to all interfaces, we significantly @@ -103,18 +105,18 @@ func TestValidCommunication(t *testing.T) { // unwillingly to use loopback addresses (the default in pion/ice). for i := 0; i < 100; i++ { _, addr, err = bServer.QueryAddr(context.TODO(), "pion-mdns-2.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } if addr.String() == "127.0.0.1" { t.Fatal("unexpected loopback") } - checkIPv4(addr, t) + checkIPv4(t, addr) } - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -137,15 +139,15 @@ func TestValidCommunicationWithAddressConfig(t *testing.T) { LocalNames: []string{"pion-mdns-1.local", "pion-mdns-2.local"}, LocalAddress: net.ParseIP(localAddress), }) - check(err, t) + check(t, err) _, addr, err := aServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if addr.String() != localAddress { t.Fatalf("address mismatch: expected %s, but got %v\n", localAddress, addr) } - check(aServer.Close(), t) + check(t, aServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") } @@ -167,15 +169,15 @@ func TestValidCommunicationWithLoopbackAddressConfig(t *testing.T) { LocalAddress: loopbackIP, IncludeLoopback: true, // the test would fail if this was false }) - check(err, t) + check(t, err) _, addr, err := aServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if addr.String() != loopbackIP.String() { t.Fatalf("address mismatch: expected %s, but got %v\n", localAddress, addr) } - check(aServer.Close(), t) + check(t, aServer.Close()) } func TestValidCommunicationWithLoopbackInterface(t *testing.T) { @@ -188,7 +190,7 @@ func TestValidCommunicationWithLoopbackInterface(t *testing.T) { aSock := createListener4(t) ifaces, err := net.Interfaces() - check(err, t) + check(t, err) ifacesToUse := make([]net.Interface, 0, len(ifaces)) for _, ifc := range ifaces { if ifc.Flags&net.FlagLoopback != net.FlagLoopback { @@ -209,14 +211,14 @@ func TestValidCommunicationWithLoopbackInterface(t *testing.T) { IncludeLoopback: true, // the test would fail if this was false Interfaces: ifacesToUse, }) - check(err, t) + check(t, err) _, addr, err := aServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) var found bool for _, iface := range ifacesToUse { addrs, err := iface.Addrs() - check(err, t) + check(t, err) for _, ifaceAddr := range addrs { ipAddr, ok := ifaceAddr.(*net.IPNet) if !ok { @@ -224,6 +226,7 @@ func TestValidCommunicationWithLoopbackInterface(t *testing.T) { } if addr.String() == ipAddr.IP.String() { found = true + break } } @@ -235,10 +238,10 @@ func TestValidCommunicationWithLoopbackInterface(t *testing.T) { t.Fatalf("address mismatch: expected loopback address, but got %v\n", addr) } - check(aServer.Close(), t) + check(t, aServer.Close()) } -func TestValidCommunicationIPv6(t *testing.T) { +func TestValidCommunicationIPv6(t *testing.T) { //nolint:cyclop if runtime.GOARCH == "386" { t.Skip("IPv6 not supported on 386 for some reason") } @@ -261,13 +264,13 @@ func TestValidCommunicationIPv6(t *testing.T) { aServer, err := Server(nil, ipv6.NewPacketConn(aSock), &Config{ LocalNames: []string{"pion-mdns-1.local", "pion-mdns-2.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(nil, ipv6.NewPacketConn(bSock), &Config{}) - check(err, t) + check(t, err) header, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeAAAA { t.Fatalf("expected AAAA but got %s", header.Type) } @@ -275,7 +278,7 @@ func TestValidCommunicationIPv6(t *testing.T) { if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } - checkIPv6(addr, t) + checkIPv6(t, addr) if addr.Is4In6() { // probably within docker t.Logf("address %s is an IPv4-to-IPv6 mapped address even though the stack is IPv6", addr) @@ -285,7 +288,7 @@ func TestValidCommunicationIPv6(t *testing.T) { } header, addr, err = bServer.QueryAddr(context.TODO(), "pion-mdns-2.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeAAAA { t.Fatalf("expected AAAA but got %s", header.Type) } @@ -293,13 +296,13 @@ func TestValidCommunicationIPv6(t *testing.T) { if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } - checkIPv6(addr, t) + checkIPv6(t, addr) if !addr.Is4In6() && addr.Zone() == "" { t.Fatalf("expected IPv6 to have zone but got %s", addr) } - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -328,26 +331,26 @@ func TestValidCommunicationIPv46(t *testing.T) { aServer, err := Server(ipv4.NewPacketConn(aSock4), ipv6.NewPacketConn(aSock6), &Config{ LocalNames: []string{"pion-mdns-1.local", "pion-mdns-2.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(ipv4.NewPacketConn(bSock4), ipv6.NewPacketConn(bSock6), &Config{}) - check(err, t) + check(t, err) _, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } _, addr, err = bServer.QueryAddr(context.TODO(), "pion-mdns-2.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -381,24 +384,24 @@ func TestValidCommunicationIPv46Mixed(t *testing.T) { aServer, err := Server(ipv4.NewPacketConn(aSock4), nil, &Config{ Name: "aServer", }) - check(err, t) + check(t, err) bServer, err := Server(nil, ipv6.NewPacketConn(bSock6), &Config{ Name: "bServer", LocalNames: []string{"pion-mdns-1.local"}, }) - check(err, t) + check(t, err) header, addr, err := aServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeA { t.Fatalf("expected A but got %s", header.Type) } - checkIPv4(addr, t) + checkIPv4(t, addr) - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -426,10 +429,10 @@ func TestValidCommunicationIPv46MixedLocalAddress(t *testing.T) { LocalAddress: net.IPv4(1, 2, 3, 4), LocalNames: []string{"pion-mdns-1.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(nil, ipv6.NewPacketConn(bSock6), &Config{}) - check(err, t) + check(t, err) ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() @@ -440,8 +443,8 @@ func TestValidCommunicationIPv46MixedLocalAddress(t *testing.T) { t.Fatalf("Query expired but returned unexpected error %v", err) } - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -468,13 +471,13 @@ func TestValidCommunicationIPv66Mixed(t *testing.T) { aServer, err := Server(nil, ipv6.NewPacketConn(aSock6), &Config{ LocalNames: []string{"pion-mdns-1.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(nil, ipv6.NewPacketConn(bSock6), &Config{}) - check(err, t) + check(t, err) header, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeAAAA { t.Fatalf("expected AAAA but got %s", header.Type) } @@ -484,10 +487,10 @@ func TestValidCommunicationIPv66Mixed(t *testing.T) { if addr.Is4In6() { t.Fatalf("expected address to not be ipv4-to-ipv6 mapped: %v", addr) } - checkIPv6(addr, t) + checkIPv6(t, addr) - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -515,13 +518,13 @@ func TestValidCommunicationIPv66MixedLocalAddress(t *testing.T) { LocalAddress: net.IPv4(1, 2, 3, 4), LocalNames: []string{"pion-mdns-1.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(nil, ipv6.NewPacketConn(bSock6), &Config{}) - check(err, t) + check(t, err) header, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeAAAA { t.Fatalf("expected AAAA but got %s", header.Type) } @@ -532,10 +535,10 @@ func TestValidCommunicationIPv66MixedLocalAddress(t *testing.T) { if addr.Unmap().String() != localAddress { t.Fatalf("unexpected local address: %v", addr) } - checkIPv6(addr, t) + checkIPv6(t, addr) - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -562,20 +565,20 @@ func TestValidCommunicationIPv64Mixed(t *testing.T) { aServer, err := Server(nil, ipv6.NewPacketConn(aSock6), &Config{ LocalNames: []string{"pion-mdns-1.local", "pion-mdns-2.local"}, }) - check(err, t) + check(t, err) bServer, err := Server(ipv4.NewPacketConn(bSock4), nil, &Config{}) - check(err, t) + check(t, err) _, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-1.local") - check(err, t) + check(t, err) if addr.String() == localAddress { t.Fatalf("unexpected local address: %v", addr) } header, addr, err := bServer.QueryAddr(context.TODO(), "pion-mdns-2.local") - check(err, t) + check(t, err) if header.Type != dnsmessage.TypeA { t.Fatalf("expected A but got %s", header.Type) } @@ -583,8 +586,8 @@ func TestValidCommunicationIPv64Mixed(t *testing.T) { t.Fatalf("unexpected local address: %v", addr) } - check(aServer.Close(), t) - check(bServer.Close(), t) + check(t, aServer.Close()) + check(t, bServer.Close()) if len(aServer.queries) > 0 { t.Fatalf("Queries not cleaned up after aServer close") @@ -604,10 +607,10 @@ func TestMultipleClose(t *testing.T) { aSock := createListener4(t) server, err := Server(ipv4.NewPacketConn(aSock), nil, &Config{}) - check(err, t) + check(t, err) - check(server.Close(), t) - check(server.Close(), t) + check(t, server.Close()) + check(t, server.Close()) if len(server.queries) > 0 { t.Fatalf("Queries not cleaned up after server close") @@ -624,7 +627,7 @@ func TestQueryRespectTimeout(t *testing.T) { aSock := createListener4(t) server, err := Server(ipv4.NewPacketConn(aSock), nil, &Config{}) - check(err, t) + check(t, err) ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond) defer cancel() @@ -652,11 +655,11 @@ func TestQueryRespectClose(t *testing.T) { aSock := createListener4(t) server, err := Server(ipv4.NewPacketConn(aSock), nil, &Config{}) - check(err, t) + check(t, err) go func() { time.Sleep(3 * time.Second) - check(server.Close(), t) + check(t, server.Close()) }() if _, _, err = server.QueryAddr(context.TODO(), "invalid-host"); !errors.Is(err, errConnectionClosed) { @@ -673,27 +676,29 @@ func TestQueryRespectClose(t *testing.T) { } func TestResourceParsing(t *testing.T) { - lookForIP := func(msg dnsmessage.Message, expectedIP []byte, t *testing.T) { + lookForIP := func(t *testing.T, msg dnsmessage.Message, expectedIP []byte) { + t.Helper() + buf, err := msg.Pack() if err != nil { t.Fatal(err) } - var p dnsmessage.Parser - if _, err = p.Start(buf); err != nil { + var parser dnsmessage.Parser + if _, err = parser.Start(buf); err != nil { t.Fatal(err) } - if err = p.SkipAllQuestions(); err != nil { + if err = parser.SkipAllQuestions(); err != nil { t.Fatal(err) } - h, err := p.AnswerHeader() + h, err := parser.AnswerHeader() if err != nil { t.Fatal(err) } - actualAddr, err := addrFromAnswerHeader(h, p) + actualAddr, err := addrFromAnswerHeader(h, parser) if err != nil { t.Fatal(err) } @@ -710,7 +715,7 @@ func TestResourceParsing(t *testing.T) { if err != nil { t.Fatal(err) } - lookForIP(answer, []byte{127, 0, 0, 1}, t) + lookForIP(t, answer, []byte{127, 0, 0, 1}) }) t.Run("AAAA Record", func(t *testing.T) { @@ -718,7 +723,7 @@ func TestResourceParsing(t *testing.T) { if err != nil { t.Fatal(err) } - lookForIP(answer, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, t) + lookForIP(t, answer, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) }) } @@ -727,10 +732,11 @@ func mustAddr(ip net.IP) netip.Addr { if !ok { panic(ipToAddrError{ip}) } + return addr } -func TestIPToBytes(t *testing.T) { +func TestIPToBytes(t *testing.T) { //nolint:cyclop expectedIP := []byte{127, 0, 0, 1} actualAddr4, err := ipv4ToBytes(netip.MustParseAddr("127.0.0.1")) if err != nil { diff --git a/examples/query/main.go b/examples/query/main.go index 3539d05..4ead548 100644 --- a/examples/query/main.go +++ b/examples/query/main.go @@ -15,7 +15,7 @@ import ( "golang.org/x/net/ipv6" ) -func main() { +func main() { //nolint:cyclop var useV4, useV6 bool if len(os.Args) > 1 { switch os.Args[1] {