Moved the server startup code out of main.go

This commit is contained in:
Michael Bridgen committed 2014-10-10 11:53:21 +01:00
1 parent d48548b1b7
commit b1b75c4a8a
2 files changed
+121 -113

No files matched your search

+4 -113
View File
@@ -2,135 +2,26 @@ package main
import (
"flag"
"fmt"
"github.com/miekg/dns"
"github.com/zettio/weavedns/server"
"log"
"net"
"time"
)
const (
LOCAL_DOMAIN = "weave"
)
var zone = new(weavedns.ZoneDb)
func makeDNSReply(r *dns.Msg, name string, addr net.IP) *dns.Msg {
m := new(dns.Msg)
m.SetReply(r)
hdr := dns.RR_Header{Name: name, Rrtype: dns.TypeA,
Class: dns.ClassINET, Ttl: 3600}
a := &dns.A{hdr, addr}
m.Answer = append(m.Answer, a)
return m
}
var (
mdnsClient *weavedns.MDNSClient
mdnsServer *weavedns.MDNSServer
)
func handleLocal(w dns.ResponseWriter, r *dns.Msg) {
q := r.Question[0]
ip, err := zone.MatchLocal(q.Name)
if err == nil {
m := makeDNSReply(r, q.Name, ip)
w.WriteMsg(m)
} else {
log.Printf("Failed lookup for %s; sending mDNS query", q.Name)
// We don't know the answer; see if someone else does
channel := make(chan *weavedns.ResponseA, 4)
go func() {
// Loop terminates when channel is closed by MDNSClient on timeout
for resp := range channel {
log.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
m := makeDNSReply(r, resp.Name, resp.Addr)
w.WriteMsg(m)
}
}()
mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
}
return
}
func ensureInterface(ifaceName string, wait int) (iface *net.Interface, err error) {
iface, err = findInterface(ifaceName)
if err == nil || wait == 0 {
return
}
log.Println("Waiting for interface", ifaceName, "to come up")
for ; err != nil && wait > 0; wait -= 1 {
time.Sleep(1 * time.Second)
iface, err = findInterface(ifaceName)
}
if err == nil {
log.Println("Interface", ifaceName, "is up")
}
return
}
func findInterface(ifaceName string) (iface *net.Interface, err error) {
iface, err = net.InterfaceByName(ifaceName)
if err != nil {
return iface, fmt.Errorf("Unable to find interface %s", ifaceName)
}
if 0 == (net.FlagUp & iface.Flags) {
return iface, fmt.Errorf("Interface %s is not up", ifaceName)
}
return
}
func main() {
var (
ifaceName string
dnsPort int
httpPort int
wait int
)
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up (defaults to 0)")
flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to dns requests (defaults to 53)")
flag.IntVar(&httpPort, "httpport", 6785, "port to listen to HTTP requests (defaults to 6785)")
flag.Parse()
var iface *net.Interface = nil
if ifaceName != "" {
var err error
iface, err = ensureInterface(ifaceName, wait)
if err != nil {
log.Fatal(err)
}
}
LocalServeMux := dns.NewServeMux()
LocalServeMux.HandleFunc(LOCAL_DOMAIN, handleLocal)
go weavedns.ListenHttp(zone)
var err error
mdnsClient, err = weavedns.NewMDNSClient()
err := weavedns.StartServer(ifaceName, dnsPort, httpPort, wait)
if err != nil {
log.Fatal(err)
} else {
log.Printf("Using mDNS on %s", ifaceName)
}
err = mdnsClient.Start(iface)
if err != nil {
log.Fatal(err)
}
mdnsServer, err = weavedns.NewMDNSServer(zone)
if err != nil {
log.Fatal(err)
}
err = mdnsServer.Start(iface)
if err != nil {
log.Fatal(err)
}
address := fmt.Sprintf(":%d", dnsPort)
err = dns.ListenAndServe(address, "udp", LocalServeMux)
if err != nil {
log.Fatal(err)
} else {
log.Printf("Listening for DNS on %s", address)
log.Fatalf("Failed to start server: %s", err)
}
}
+117
View File
@@ -0,0 +1,117 @@
package weavedns
import (
"fmt"
"github.com/miekg/dns"
"log"
"net"
"time"
)
const (
LOCAL_DOMAIN = "weave"
)
func ensureInterface(ifaceName string, wait int) (iface *net.Interface, err error) {
iface, err = findInterface(ifaceName)
if err == nil || wait == 0 {
return
}
log.Println("Waiting for interface", ifaceName, "to come up")
for ; err != nil && wait > 0; wait -= 1 {
time.Sleep(1 * time.Second)
iface, err = findInterface(ifaceName)
}
if err == nil {
log.Println("Interface", ifaceName, "is up")
}
return
}
func findInterface(ifaceName string) (iface *net.Interface, err error) {
iface, err = net.InterfaceByName(ifaceName)
if err != nil {
return iface, fmt.Errorf("Unable to find interface %s", ifaceName)
}
if 0 == (net.FlagUp & iface.Flags) {
return iface, fmt.Errorf("Interface %s is not up", ifaceName)
}
return
}
func queryHandler(zone Zone, mdnsClient *MDNSClient) dns.HandlerFunc {
return func(w dns.ResponseWriter, r *dns.Msg) {
q := r.Question[0]
ip, err := zone.MatchLocal(q.Name)
if err == nil {
m := makeDNSReply(r, q.Name, ip)
w.WriteMsg(m)
} else {
log.Printf("Failed lookup for %s; sending mDNS query", q.Name)
// We don't know the answer; see if someone else does
channel := make(chan *ResponseA, 4)
go func() {
// Loop terminates when channel is closed by MDNSClient on timeout
for resp := range channel {
log.Printf("Got address response %s to query %s addr %s", resp.Name, q.Name, resp.Addr)
m := makeDNSReply(r, resp.Name, resp.Addr)
w.WriteMsg(m)
}
}()
mdnsClient.SendQuery(q.Name, dns.TypeA, channel)
}
return
}
}
func StartServer(ifaceName string, dnsPort int, httpPort int, wait int) error {
var zone = new(ZoneDb)
go ListenHttp(zone)
var (
mdnsClient *MDNSClient
mdnsServer *MDNSServer
)
var iface *net.Interface = nil
if ifaceName != "" {
var err error
iface, err = ensureInterface(ifaceName, wait)
if err != nil {
log.Fatal(err)
}
}
LocalServeMux := dns.NewServeMux()
LocalServeMux.HandleFunc(LOCAL_DOMAIN, queryHandler(zone, mdnsClient))
var err error
mdnsClient, err = NewMDNSClient()
if err != nil {
log.Fatal(err)
} else {
log.Printf("Using mDNS on %s", ifaceName)
}
err = mdnsClient.Start(iface)
if err != nil {
log.Fatal(err)
}
mdnsServer, err = NewMDNSServer(zone)
if err != nil {
log.Fatal(err)
}
err = mdnsServer.Start(iface)
if err != nil {
log.Fatal(err)
}
address := fmt.Sprintf(":%d", dnsPort)
err = dns.ListenAndServe(address, "udp", LocalServeMux)
if err != nil {
log.Fatal(err)
} else {
log.Printf("Listening for DNS on %s", address)
}
return nil
}