...

Source file src/github.com/miekg/dns/serve_mux.go

Documentation: github.com/miekg/dns

     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  }
   123  

View as plain text