// sd-test-srv runs a simple service discovery system; it returns two hardcoded
// IP addresses for every A query.
package main

import (
	"flag"
	"log"
	"net"
	"strings"
	"time"

	"github.com/miekg/dns"
)

func dnsHandler(w dns.ResponseWriter, r *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = false
	m.Rcode = dns.RcodeSuccess

	if len(r.Question) != 1 {
		m.Rcode = dns.RcodeServerFailure
		w.WriteMsg(m)
		return
	}
	if !strings.HasSuffix(r.Question[0].Name, ".boulder.") {
		m.Rcode = dns.RcodeServerFailure
		w.WriteMsg(m)
		return
	}
	if r.Question[0].Qtype != dns.TypeA {
		// Just return a NOERROR message for non-A questions
		w.WriteMsg(m)
		return
	}

	hdr := dns.RR_Header{
		Name:   r.Question[0].Name,
		Rrtype: dns.TypeA,
		Class:  dns.ClassINET,
		Ttl:    0,
	}

	// These two hardcoded IPs correspond to the configured addresses for boulder
	// in docker-compose.yml. In our Docker setup, boulder is present on two
	// networks, rednet and bluenet, with a different IP address on each. This
	// allows us to test load balance across gRPC backends.
	m.Answer = append(m.Answer, &dns.A{
		A:   net.ParseIP("10.77.77.77"),
		Hdr: hdr,
	}, &dns.A{
		A:   net.ParseIP("10.88.88.88"),
		Hdr: hdr,
	})

	w.WriteMsg(m)
}

func main() {
	listen := flag.String("listen", ":53", "Address and port to listen on.")
	flag.Parse()
	if *listen == "" {
		flag.Usage()
		return
	}
	dns.HandleFunc(".", dnsHandler)
	go func() {
		srv := dns.Server{
			Addr:         *listen,
			Net:          "tcp",
			ReadTimeout:  time.Second,
			WriteTimeout: time.Second,
		}
		err := srv.ListenAndServe()
		if err != nil {
			log.Fatal(err)
		}
	}()
	srv := dns.Server{
		Addr:         *listen,
		Net:          "udp",
		ReadTimeout:  time.Second,
		WriteTimeout: time.Second,
	}
	err := srv.ListenAndServe()
	if err != nil {
		log.Fatal(err)
	}
}
