Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.4 KiB
122 lines
3.4 KiB
package dns |
|
|
|
import ( |
|
"sync" |
|
) |
|
|
|
// ServeMux is an DNS request multiplexer. It matches the zone name of |
|
// each incoming request against a list of registered patterns add calls |
|
// the handler for the pattern 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 is also registered), otherwise |
|
// the child gets the query. |
|
// |
|
// ServeMux is also safe for concurrent access from multiple goroutines. |
|
// |
|
// The zero ServeMux is empty and ready for use. |
|
type ServeMux struct { |
|
z map[string]Handler |
|
m sync.RWMutex |
|
} |
|
|
|
// NewServeMux allocates and returns a new ServeMux. |
|
func NewServeMux() *ServeMux { |
|
return new(ServeMux) |
|
} |
|
|
|
// DefaultServeMux is the default ServeMux used by Serve. |
|
var DefaultServeMux = NewServeMux() |
|
|
|
func (mux *ServeMux) match(q string, t uint16) Handler { |
|
mux.m.RLock() |
|
defer mux.m.RUnlock() |
|
if mux.z == nil { |
|
return nil |
|
} |
|
|
|
q = CanonicalName(q) |
|
|
|
var handler Handler |
|
for off, end := 0, false; !end; off, end = NextLabel(q, off) { |
|
if h, ok := mux.z[q[off:]]; ok { |
|
if t != TypeDS { |
|
return h |
|
} |
|
// Continue for DS to see if we have a parent too, if so delegate to the parent |
|
handler = h |
|
} |
|
} |
|
|
|
// Wildcard match, if we have found nothing try the root zone as a last resort. |
|
if h, ok := mux.z["."]; ok { |
|
return h |
|
} |
|
|
|
return handler |
|
} |
|
|
|
// Handle adds a handler to the ServeMux for pattern. |
|
func (mux *ServeMux) Handle(pattern string, handler Handler) { |
|
if pattern == "" { |
|
panic("dns: invalid pattern " + pattern) |
|
} |
|
mux.m.Lock() |
|
if mux.z == nil { |
|
mux.z = make(map[string]Handler) |
|
} |
|
mux.z[CanonicalName(pattern)] = handler |
|
mux.m.Unlock() |
|
} |
|
|
|
// HandleFunc adds a handler function to the ServeMux for pattern. |
|
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { |
|
mux.Handle(pattern, HandlerFunc(handler)) |
|
} |
|
|
|
// HandleRemove deregisters the handler specific for pattern from the ServeMux. |
|
func (mux *ServeMux) HandleRemove(pattern string) { |
|
if pattern == "" { |
|
panic("dns: invalid pattern " + pattern) |
|
} |
|
mux.m.Lock() |
|
delete(mux.z, CanonicalName(pattern)) |
|
mux.m.Unlock() |
|
} |
|
|
|
// ServeDNS dispatches the request to the handler whose pattern most |
|
// closely matches the request message. |
|
// |
|
// ServeDNS is DNSSEC aware, meaning that queries for the DS record |
|
// are redirected to the parent zone (if that is also registered), |
|
// otherwise the child gets the query. |
|
// |
|
// If no handler is found, or there is no question, a standard REFUSED |
|
// message is returned |
|
func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) { |
|
var h Handler |
|
if len(req.Question) >= 1 { // allow more than one question |
|
h = mux.match(req.Question[0].Name, req.Question[0].Qtype) |
|
} |
|
|
|
if h != nil { |
|
h.ServeDNS(w, req) |
|
} else { |
|
handleRefused(w, req) |
|
} |
|
} |
|
|
|
// Handle registers the handler with the given pattern |
|
// in the DefaultServeMux. The documentation for |
|
// ServeMux explains how patterns are matched. |
|
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } |
|
|
|
// HandleRemove deregisters the handle with the given pattern |
|
// in the DefaultServeMux. |
|
func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) } |
|
|
|
// HandleFunc registers the handler function with the given pattern |
|
// in the DefaultServeMux. |
|
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { |
|
DefaultServeMux.HandleFunc(pattern, handler) |
|
}
|
|
|