package dns

import (
	
)

// 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 () *ServeMux {
	return new(ServeMux)
}

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = NewServeMux()

func ( *ServeMux) ( string,  uint16) Handler {
	.m.RLock()
	defer .m.RUnlock()
	if .z == nil {
		return nil
	}

	 = CanonicalName()

	var  Handler
	for ,  := 0, false; !; ,  = NextLabel(, ) {
		if ,  := .z[[:]];  {
			if  != TypeDS {
				return 
			}
			// Continue for DS to see if we have a parent too, if so delegate to the parent
			 = 
		}
	}

	// Wildcard match, if we have found nothing try the root zone as a last resort.
	if ,  := .z["."];  {
		return 
	}

	return 
}

// Handle adds a handler to the ServeMux for pattern.
func ( *ServeMux) ( string,  Handler) {
	if  == "" {
		panic("dns: invalid pattern " + )
	}
	.m.Lock()
	if .z == nil {
		.z = make(map[string]Handler)
	}
	.z[CanonicalName()] = 
	.m.Unlock()
}

// HandleFunc adds a handler function to the ServeMux for pattern.
func ( *ServeMux) ( string,  func(ResponseWriter, *Msg)) {
	.Handle(, HandlerFunc())
}

// HandleRemove deregisters the handler specific for pattern from the ServeMux.
func ( *ServeMux) ( string) {
	if  == "" {
		panic("dns: invalid pattern " + )
	}
	.m.Lock()
	delete(.z, CanonicalName())
	.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 ( *ServeMux) ( ResponseWriter,  *Msg) {
	var  Handler
	if len(.Question) >= 1 { // allow more than one question
		 = .match(.Question[0].Name, .Question[0].Qtype)
	}

	if  != nil {
		.ServeDNS(, )
	} else {
		handleRefused(, )
	}
}

// Handle registers the handler with the given pattern
// in the DefaultServeMux. The documentation for
// ServeMux explains how patterns are matched.
func ( string,  Handler) { DefaultServeMux.Handle(, ) }

// HandleRemove deregisters the handle with the given pattern
// in the DefaultServeMux.
func ( string) { DefaultServeMux.HandleRemove() }

// HandleFunc registers the handler function with the given pattern
// in the DefaultServeMux.
func ( string,  func(ResponseWriter, *Msg)) {
	DefaultServeMux.HandleFunc(, )
}