| Tim Windelschmidt | 6d33a43 | 2025-02-04 14:34:25 +0100 | [diff] [blame] | 1 | // Copyright The Monogon Project Authors. |
| 2 | // SPDX-License-Identifier: Apache-2.0 |
| 3 | |
| Jan Schär | 4a18022 | 2024-07-29 16:32:54 +0200 | [diff] [blame] | 4 | package test |
| 5 | |
| 6 | // Taken and modified from CoreDNS, under Apache 2.0. |
| 7 | |
| 8 | import ( |
| 9 | "fmt" |
| 10 | "net" |
| 11 | |
| 12 | "github.com/miekg/dns" |
| 13 | ) |
| 14 | |
| 15 | // A Server is an DNS server listening on a system-chosen port on the local |
| 16 | // loopback interface, for use in end-to-end DNS tests. |
| 17 | type Server struct { |
| 18 | Addr string // Address where the server listening. |
| 19 | |
| 20 | s1 *dns.Server // udp |
| 21 | s2 *dns.Server // tcp |
| 22 | } |
| 23 | |
| 24 | // NewServer starts and returns a new Server. The caller should call Close when |
| 25 | // finished, to shut it down. |
| 26 | func NewServer(f dns.HandlerFunc) *Server { |
| 27 | ch1 := make(chan bool) |
| 28 | ch2 := make(chan bool) |
| 29 | |
| 30 | s1 := &dns.Server{Handler: f} // udp |
| 31 | s2 := &dns.Server{Handler: f} // tcp |
| 32 | |
| 33 | for i := 0; i < 5; i++ { // 5 attempts |
| 34 | s2.Listener, _ = net.Listen("tcp", "[::1]:0") |
| 35 | if s2.Listener == nil { |
| 36 | continue |
| 37 | } |
| 38 | |
| 39 | s1.PacketConn, _ = net.ListenPacket("udp", s2.Listener.Addr().String()) |
| 40 | if s1.PacketConn != nil { |
| 41 | break |
| 42 | } |
| 43 | |
| 44 | // perhaps UDP port is in use, try again |
| 45 | s2.Listener.Close() |
| 46 | s2.Listener = nil |
| 47 | } |
| 48 | if s2.Listener == nil { |
| 49 | panic("dnstest.NewServer(): failed to create new server") |
| 50 | } |
| 51 | |
| 52 | s1.NotifyStartedFunc = func() { close(ch1) } |
| 53 | s2.NotifyStartedFunc = func() { close(ch2) } |
| 54 | go s1.ActivateAndServe() |
| 55 | go s2.ActivateAndServe() |
| 56 | |
| 57 | <-ch1 |
| 58 | <-ch2 |
| 59 | |
| 60 | return &Server{s1: s1, s2: s2, Addr: s2.Listener.Addr().String()} |
| 61 | } |
| 62 | |
| 63 | // Close shuts down the server. |
| 64 | func (s *Server) Close() { |
| 65 | s.s1.Shutdown() |
| 66 | s.s2.Shutdown() |
| 67 | } |
| 68 | |
| 69 | // RR parses s as a DNS resource record. |
| 70 | func RR(s string) dns.RR { |
| 71 | rr, err := dns.NewRR(s) |
| 72 | if err != nil { |
| 73 | panic(fmt.Sprintf("Failed to parse rr %q: %v", s, err)) |
| 74 | } |
| 75 | return rr |
| 76 | } |