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