gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

serve_mux.go (3449B)


      1 package dns
      2 
      3 import (
      4 	"sync"
      5 )
      6 
      7 // ServeMux is an DNS request multiplexer. It matches the zone name of
      8 // each incoming request against a list of registered patterns add calls
      9 // the handler for the pattern that most closely matches the zone name.
     10 //
     11 // ServeMux is DNSSEC aware, meaning that queries for the DS record are
     12 // redirected to the parent zone (if that is also registered), otherwise
     13 // the child gets the query.
     14 //
     15 // ServeMux is also safe for concurrent access from multiple goroutines.
     16 //
     17 // The zero ServeMux is empty and ready for use.
     18 type ServeMux struct {
     19 	z map[string]Handler
     20 	m sync.RWMutex
     21 }
     22 
     23 // NewServeMux allocates and returns a new ServeMux.
     24 func NewServeMux() *ServeMux {
     25 	return new(ServeMux)
     26 }
     27 
     28 // DefaultServeMux is the default ServeMux used by Serve.
     29 var DefaultServeMux = NewServeMux()
     30 
     31 func (mux *ServeMux) match(q string, t uint16) Handler {
     32 	mux.m.RLock()
     33 	defer mux.m.RUnlock()
     34 	if mux.z == nil {
     35 		return nil
     36 	}
     37 
     38 	q = CanonicalName(q)
     39 
     40 	var handler Handler
     41 	for off, end := 0, false; !end; off, end = NextLabel(q, off) {
     42 		if h, ok := mux.z[q[off:]]; ok {
     43 			if t != TypeDS {
     44 				return h
     45 			}
     46 			// Continue for DS to see if we have a parent too, if so delegate to the parent
     47 			handler = h
     48 		}
     49 	}
     50 
     51 	// Wildcard match, if we have found nothing try the root zone as a last resort.
     52 	if h, ok := mux.z["."]; ok {
     53 		return h
     54 	}
     55 
     56 	return handler
     57 }
     58 
     59 // Handle adds a handler to the ServeMux for pattern.
     60 func (mux *ServeMux) Handle(pattern string, handler Handler) {
     61 	if pattern == "" {
     62 		panic("dns: invalid pattern " + pattern)
     63 	}
     64 	mux.m.Lock()
     65 	if mux.z == nil {
     66 		mux.z = make(map[string]Handler)
     67 	}
     68 	mux.z[CanonicalName(pattern)] = handler
     69 	mux.m.Unlock()
     70 }
     71 
     72 // HandleFunc adds a handler function to the ServeMux for pattern.
     73 func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
     74 	mux.Handle(pattern, HandlerFunc(handler))
     75 }
     76 
     77 // HandleRemove deregisters the handler specific for pattern from the ServeMux.
     78 func (mux *ServeMux) HandleRemove(pattern string) {
     79 	if pattern == "" {
     80 		panic("dns: invalid pattern " + pattern)
     81 	}
     82 	mux.m.Lock()
     83 	delete(mux.z, CanonicalName(pattern))
     84 	mux.m.Unlock()
     85 }
     86 
     87 // ServeDNS dispatches the request to the handler whose pattern most
     88 // closely matches the request message.
     89 //
     90 // ServeDNS is DNSSEC aware, meaning that queries for the DS record
     91 // are redirected to the parent zone (if that is also registered),
     92 // otherwise the child gets the query.
     93 //
     94 // If no handler is found, or there is no question, a standard REFUSED
     95 // message is returned
     96 func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) {
     97 	var h Handler
     98 	if len(req.Question) >= 1 { // allow more than one question
     99 		h = mux.match(req.Question[0].Name, req.Question[0].Qtype)
    100 	}
    101 
    102 	if h != nil {
    103 		h.ServeDNS(w, req)
    104 	} else {
    105 		handleRefused(w, req)
    106 	}
    107 }
    108 
    109 // Handle registers the handler with the given pattern
    110 // in the DefaultServeMux. The documentation for
    111 // ServeMux explains how patterns are matched.
    112 func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }
    113 
    114 // HandleRemove deregisters the handle with the given pattern
    115 // in the DefaultServeMux.
    116 func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) }
    117 
    118 // HandleFunc registers the handler function with the given pattern
    119 // in the DefaultServeMux.
    120 func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) {
    121 	DefaultServeMux.HandleFunc(pattern, handler)
    122 }