瀏覽代碼

Support listening on multiple interfaces, simplify json status function

Ask Bjørn Hansen 13 年之前
父節點
當前提交
5ff2de2be9
共有 2 個文件被更改,包括 50 次插入21 次删除
  1. 32 4
      geodns.go
  2. 18 17
      serve.go

+ 32 - 4
geodns.go

@@ -3,22 +3,26 @@ package main
 import (
 	"flag"
 	"log"
+	"net"
 	"os"
 	"os/signal"
 	"runtime/pprof"
+	"strings"
 	"time"
 )
 
 var VERSION string = "2.0"
 var gitVersion string
+var serverId string
 
 var timeStarted = time.Now()
 var qCounter uint64 = 0
 
 var (
-	listen  = flag.String("listen", ":8053", "set the listener address")
-	flaglog = flag.Bool("log", false, "be more verbose")
-	flagrun = flag.Bool("run", false, "run server")
+	flagint  = flag.String("interface", "*", "set the listener address")
+	flagport = flag.String("port", "53", "default port number")
+	flaglog  = flag.Bool("log", false, "be more verbose")
+	flagrun  = flag.Bool("run", false, "run server")
 
 	cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
 	memprofile = flag.String("memprofile", "", "write memory profile to this file")
@@ -64,7 +68,31 @@ func main() {
 	setupPgeodnsZone(Zones)
 
 	go configReader(dirName, Zones)
-	go listenAndServe(&Zones)
+	for _, host := range strings.Split(*flagint, ",") {
+		ip, port, err := net.SplitHostPort(host)
+		if err != nil {
+			switch {
+			case strings.Contains(err.Error(), "missing port in address"):
+				// 127.0.0.1
+				ip = host
+			case strings.Contains(err.Error(), "too many colons in address") &&
+				// [a:b::c]
+				strings.LastIndex(host, "]") == len(host)-1:
+				ip = host[1 : len(host)-1]
+				port = ""
+			default:
+				log.Fatalf("Could not parse %s: %s\n", host, err)
+			}
+		}
+		if len(port) == 0 {
+			port = *flagport
+		}
+		host = net.JoinHostPort(ip, port)
+		if len(serverId) == 0 {
+			serverId = ip
+		}
+		go listenAndServe(host, &Zones)
+	}
 
 	if *flagrun {
 		terminate := make(chan os.Signal)

+ 18 - 17
serve.go

@@ -102,14 +102,10 @@ func serve(w dns.ResponseWriter, req *dns.Msg, z *Zone) {
 }
 
 func statusRR(z *Zone) []dns.RR {
-	var h dns.RR_Header
-	h.Ttl = 1
-	h.Class = dns.ClassINET
-	h.Rrtype = dns.TypeTXT
+	h := dns.RR_Header{Ttl: 1, Class: dns.ClassINET, Rrtype: dns.TypeTXT}
 	h.Name = "_status." + z.Origin + "."
-	rr := &dns.RR_TXT{Hdr: h}
 
-	status := map[string]string{"v": VERSION, "id": *listen}
+	status := map[string]string{"v": VERSION, "id": serverId}
 
 	var hostname, err = os.Hostname()
 	if err == nil {
@@ -119,11 +115,8 @@ func statusRR(z *Zone) []dns.RR {
 	status["qs"] = strconv.FormatUint(qCounter, 10)
 
 	js, err := json.Marshal(status)
-	//log.Println("status", status, string(js), err)
-	rr.Txt = []string{string(js)}
-	rrs := make([]dns.RR, 1)
-	rrs[0] = rr
-	return rrs
+
+	return []dns.RR{&dns.RR_TXT{Hdr: h, Txt: []string{string(js)}}}
 }
 
 func setupServerFunc(Zone *Zone) func(dns.ResponseWriter, *dns.Msg) {
@@ -132,12 +125,20 @@ func setupServerFunc(Zone *Zone) func(dns.ResponseWriter, *dns.Msg) {
 	}
 }
 
-func listenAndServe(Zones *Zones) {
+func listenAndServe(ip string, Zones *Zones) {
+
+	prots := []string{"udp", "tcp"}
+
+	for _, prot := range prots {
+		go func(p string) {
+			server := &dns.Server{Addr: ip, Net: p}
 
-	// Only listen on UDP for now
-	log.Printf("Opening on %s %s", *listen, "udp")
-	if err := dns.ListenAndServe(*listen, "udp", nil); err != nil {
-		log.Fatalf("geodns: failed to setup %s %s", *listen, "udp")
+			log.Printf("Opening on %s %s", ip, p)
+			if err := server.ListenAndServe(); err != nil {
+				log.Fatalf("geodns: failed to setup %s %s: %s", ip, p, err)
+			}
+			log.Fatalf("geodns: ListenAndServe unexpectedly returned")
+		}(prot)
 	}
-	log.Fatalf("geodns: ListenAndServe unexpectedly returned")
+
 }