diff --git a/backend/backend.go b/backend/backend.go index c80841e..59df4d7 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -6,11 +6,13 @@ import "gopkg.in/hlandau/madns.v1/merr" import "github.com/hlandau/ncdns/namecoin" import "github.com/hlandau/ncdns/util" import "github.com/hlandau/ncdns/ncdomain" +import "github.com/hlandau/xlog" import "sync" import "fmt" import "net" import "net/mail" import "strings" +import "time" // Provides an abstract zone file for the Namecoin .bit TLD. type Backend struct { @@ -23,6 +25,8 @@ type Backend struct { const defaultMaxEntries = 100 +var log, Log = xlog.New("ncdns.backend") + // Backend configuration. type Config struct { NamecoinConn namecoin.Conn @@ -337,12 +341,22 @@ func (b *Backend) resolveName(name string) (jsonValue string, err error) { return fv, nil } - v, err := b.nc.Query(name) - if err != nil { - return "", err - } + // The btcjson package has quite a long timeout, far in excess of standard + // DNS timeouts. We need to return an error response rapidly if we can't + // query the backend. Be generous with the timeout as responses from the + // Namecoin JSON-RPC seem sluggish sometimes. + result := make(chan struct{}, 1) + go func() { + jsonValue, err = b.nc.Query(name) + result <- struct{}{} + }() - return v, nil + select { + case <-result: + return + case <-time.After(1500 * time.Millisecond): + return "", fmt.Errorf("timeout") + } } func (b *Backend) jsonToDomain(name, jsonValue string) (*domain, error) { diff --git a/server/server.go b/server/server.go index d873259..8a118da 100644 --- a/server/server.go +++ b/server/server.go @@ -1,7 +1,6 @@ package server import "gopkg.in/hlandau/madns.v1" -import "github.com/hlandau/degoutils/log" import "github.com/hlandau/ncdns/backend" import "github.com/hlandau/ncdns/namecoin" import "github.com/miekg/dns" @@ -12,9 +11,12 @@ import "sync" import "strings" import "path/filepath" import "crypto" +import "github.com/hlandau/xlog" const version = "1.0" +var log, Log = xlog.New("ncdns.server") + type Server struct { cfg ServerConfig @@ -49,6 +51,8 @@ type ServerConfig struct { Hostmaster string `default:"" usage:"Hostmaster e. mail address"` VanityIPs string `default:"" usage:"Comma separated list of IP addresses to place in A/AAAA records at the zone apex (default: don't add any records)"` vanityIPs []net.IP + TplSet string `default:"std" usage:"The template set to use"` + TplPath string `default:"" usage:"The path to the tpl directory (empty: autodetect)"` ConfigDir string // path to interpret filenames relative to } @@ -170,7 +174,6 @@ func (s *Server) loadKey(fn, privateFn string) (k *dns.DNSKEY, privatek crypto.P } func (s *Server) Start() error { - s.mux = dns.NewServeMux() s.mux.Handle(".", s.engine) @@ -179,6 +182,7 @@ func (s *Server) Start() error { s.tcpListener = s.runListener("tcp") s.wgStart.Wait() + log.Info("Listeners started") return nil } diff --git a/server/web.go b/server/web.go index 5d73044..43b0627 100644 --- a/server/web.go +++ b/server/web.go @@ -2,7 +2,6 @@ package server import "net/http" import "html/template" -import "github.com/hlandau/degoutils/log" import "github.com/hlandau/ncdns/util" import "github.com/hlandau/ncdns/ncdomain" import "github.com/miekg/dns" @@ -11,35 +10,28 @@ import "path/filepath" import "time" import "strings" import "fmt" -import "flag" var layoutTpl *template.Template var mainPageTpl *template.Template var lookupPageTpl *template.Template -var tplSetFlag = flag.String("tplset", "std", "Subdirectory of tpl/ to look for templates in (default: std)") - -func initTemplates(configDir string) error { +func (s *Server) initTemplates() error { if lookupPageTpl != nil { return nil } - if *tplSetFlag == "" { - *tplSetFlag = "std" - } - var err error - layoutTpl, err = template.ParseFiles(tplFilename(configDir, "layout")) + layoutTpl, err = template.ParseFiles(s.tplFilename("layout")) if err != nil { return err } - mainPageTpl, err = deriveTemplate(tplFilename(configDir, "main")) + mainPageTpl, err = deriveTemplate(s.tplFilename("main")) if err != nil { return err } - lookupPageTpl, err = deriveTemplate(tplFilename(configDir, "lookup")) + lookupPageTpl, err = deriveTemplate(s.tplFilename("lookup")) if err != nil { return err } @@ -55,9 +47,13 @@ func deriveTemplate(filename string) (*template.Template, error) { return cl.ParseFiles(filename) } -func tplFilename(configDir, filename string) string { - s := "tpl/" + *tplSetFlag + "/" + filename + ".tpl" - return filepath.Join(configDir, "..", s) +func (s *Server) tplFilename(filename string) string { + td := filepath.Join(s.cfg.ConfigDir, "..", "tpl") + if s.cfg.TplPath != "" { + td = s.cfg.TplPath + } + + return filepath.Join(td, s.cfg.TplSet, filename+".tpl") } type webServer struct { @@ -83,6 +79,11 @@ func (ws *webServer) layoutInfo() *layoutInfo { cshtml = `` + csparts[0] + `.` + csparts[1] + `` } + var tld string + if len(csparts) > 1 { + tld = "." + csparts[1] + } + li := &layoutInfo{ SelfName: ws.s.ServerName(), Time: time.Now().Format("2006-01-02 15:04:05"), @@ -90,7 +91,7 @@ func (ws *webServer) layoutInfo() *layoutInfo { CanonicalNameservers: ws.s.cfg.canonicalNameservers, Hostmaster: ws.s.cfg.Hostmaster, CanonicalSuffixHTML: template.HTML(cshtml), - TLD: "." + csparts[1], + TLD: tld, HasDNSSEC: ws.s.cfg.ZonePublicKey != "", } @@ -200,7 +201,7 @@ func clearAllCookies(rw http.ResponseWriter, req *http.Request) { } func webStart(listenAddr string, server *Server) error { - err := initTemplates(server.cfg.ConfigDir) + err := server.initTemplates() if err != nil { return err }