Remove the radix.Radix dependency
Put everything in maps. This removes to a major dependency and makes Go DNS only depend on the core Go packages. This will probably also be faster than the current setup -- although this needs to be benchmarked.
This commit is contained in:
parent
cb4c191bd3
commit
45775dff76
64
server.go
64
server.go
|
@ -7,7 +7,6 @@
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/miekg/radix"
|
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -28,7 +27,7 @@ type ResponseWriter interface {
|
||||||
Write([]byte) (int, error)
|
Write([]byte) (int, error)
|
||||||
// Close closes the connection.
|
// Close closes the connection.
|
||||||
Close() error
|
Close() error
|
||||||
// TsigStatus returns the status of the Tsig.
|
// TsigStatus returns the status of the Tsig.
|
||||||
TsigStatus() error
|
TsigStatus() error
|
||||||
// TsigTimersOnly sets the tsig timers only boolean.
|
// TsigTimersOnly sets the tsig timers only boolean.
|
||||||
TsigTimersOnly(bool)
|
TsigTimersOnly(bool)
|
||||||
|
@ -49,19 +48,19 @@ type response struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeMux is an DNS request multiplexer. It matches the
|
// ServeMux is an DNS request multiplexer. It matches the
|
||||||
// zone name of each incoming request against a list of
|
// zone name of each incoming request against a list of
|
||||||
// registered patterns add calls the handler for the pattern
|
// registered patterns add calls the handler for the pattern
|
||||||
// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
|
// that most closely matches the zone name. ServeMux is DNSSEC aware, meaning
|
||||||
// that queries for the DS record are redirected to the parent zone (if that
|
// that queries for the DS record are redirected to the parent zone (if that
|
||||||
// is also registered), otherwise the child gets the query.
|
// is also registered), otherwise the child gets the query.
|
||||||
// ServeMux is also safe for concurrent access from multiple goroutines.
|
// ServeMux is also safe for concurrent access from multiple goroutines.
|
||||||
type ServeMux struct {
|
type ServeMux struct {
|
||||||
r *radix.Radix
|
z map[string]Handler
|
||||||
m *sync.RWMutex
|
m *sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServeMux allocates and returns a new ServeMux.
|
// NewServeMux allocates and returns a new ServeMux.
|
||||||
func NewServeMux() *ServeMux { return &ServeMux{r: radix.New(), m: new(sync.RWMutex)} }
|
func NewServeMux() *ServeMux { return &ServeMux{z: make(map[string]Handler), m: new(sync.RWMutex)} }
|
||||||
|
|
||||||
// DefaultServeMux is the default ServeMux used by Serve.
|
// DefaultServeMux is the default ServeMux used by Serve.
|
||||||
var DefaultServeMux = NewServeMux()
|
var DefaultServeMux = NewServeMux()
|
||||||
|
@ -70,7 +69,7 @@ var DefaultServeMux = NewServeMux()
|
||||||
var Authors = []string{"Miek Gieben", "Ask Bjørn Hansen", "Dave Cheney", "Dusty Wilson", "Peter van Dijk"}
|
var Authors = []string{"Miek Gieben", "Ask Bjørn Hansen", "Dave Cheney", "Dusty Wilson", "Peter van Dijk"}
|
||||||
|
|
||||||
// Version holds the current version.
|
// Version holds the current version.
|
||||||
var Version = "v1.0"
|
var Version = "v1.1"
|
||||||
|
|
||||||
// The HandlerFunc type is an adapter to allow the use of
|
// The HandlerFunc type is an adapter to allow the use of
|
||||||
// ordinary functions as DNS handlers. If f is a function
|
// ordinary functions as DNS handlers. If f is a function
|
||||||
|
@ -83,7 +82,7 @@ func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) {
|
||||||
f(w, r)
|
f(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FailedHandler returns a HandlerFunc
|
// FailedHandler returns a HandlerFunc
|
||||||
// returns SERVFAIL for every request it gets.
|
// returns SERVFAIL for every request it gets.
|
||||||
func HandleFailed(w ResponseWriter, r *Msg) {
|
func HandleFailed(w ResponseWriter, r *Msg) {
|
||||||
m := new(Msg)
|
m := new(Msg)
|
||||||
|
@ -165,27 +164,40 @@ func ListenAndServe(addr string, network string, handler Handler) error {
|
||||||
return server.ListenAndServe()
|
return server.ListenAndServe()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mux *ServeMux) match(zone string, t uint16) Handler {
|
func (mux *ServeMux) match(q string, t uint16) Handler {
|
||||||
mux.m.RLock()
|
mux.m.RLock()
|
||||||
defer mux.m.RUnlock()
|
defer mux.m.RUnlock()
|
||||||
if h, e := mux.r.Find(toRadixName(zone)); e {
|
var (
|
||||||
// If we got queried for a DS record, we must see if we
|
handler Handler
|
||||||
// if we also serve the parent. We then redirect the query to it.
|
lastdot int
|
||||||
if t != TypeDS {
|
lastbyte byte
|
||||||
return h.Value.(Handler)
|
seendot bool = true
|
||||||
|
)
|
||||||
|
// TODO(mg): check for .
|
||||||
|
for i := 0; i < len(q); i++ {
|
||||||
|
if seendot {
|
||||||
|
if h, ok := mux.z[q[lastdot:]]; ok {
|
||||||
|
if t != TypeDS {
|
||||||
|
return h
|
||||||
|
} else {
|
||||||
|
// Continue for DS to see if we have a parent too, if so delegeate to the parent
|
||||||
|
handler = h
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if d := h.Up(); d != nil {
|
|
||||||
return d.Value.(Handler)
|
if q[i] == '.' && lastbyte != '\\' {
|
||||||
|
lastdot = i
|
||||||
|
seendot = true
|
||||||
|
} else {
|
||||||
|
seendot = false
|
||||||
}
|
}
|
||||||
// No parent zone found, let the original handler take care of it
|
lastbyte = q[i]
|
||||||
return h.Value.(Handler)
|
|
||||||
} else {
|
|
||||||
if h == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return h.Value.(Handler)
|
|
||||||
}
|
}
|
||||||
panic("dns: not reached")
|
if handler != nil {
|
||||||
|
return handler
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle adds a handler to the ServeMux for pattern.
|
// Handle adds a handler to the ServeMux for pattern.
|
||||||
|
@ -194,7 +206,7 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
|
||||||
panic("dns: invalid pattern " + pattern)
|
panic("dns: invalid pattern " + pattern)
|
||||||
}
|
}
|
||||||
mux.m.Lock()
|
mux.m.Lock()
|
||||||
mux.r.Insert(toRadixName(Fqdn(pattern)), handler)
|
mux.z[Fqdn(pattern)] = handler
|
||||||
mux.m.Unlock()
|
mux.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +221,7 @@ func (mux *ServeMux) HandleRemove(pattern string) {
|
||||||
panic("dns: invalid pattern " + pattern)
|
panic("dns: invalid pattern " + pattern)
|
||||||
}
|
}
|
||||||
mux.m.Lock()
|
mux.m.Lock()
|
||||||
mux.r.Remove(toRadixName(Fqdn(pattern)))
|
delete(mux.z, Fqdn(pattern))
|
||||||
mux.m.Unlock()
|
mux.m.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +313,7 @@ forever:
|
||||||
for {
|
for {
|
||||||
rw, e := l.AcceptTCP()
|
rw, e := l.AcceptTCP()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
// don't bail out, but wait for a new request
|
// don't bail out, but wait for a new request
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if srv.ReadTimeout != 0 {
|
if srv.ReadTimeout != 0 {
|
||||||
|
|
Loading…
Reference in New Issue