github.com/chwjbn/xclash@v0.2.0/dns/server.go (about)

     1  package dns
     2  
     3  import (
     4  	"errors"
     5  	"net"
     6  
     7  	"github.com/chwjbn/xclash/common/sockopt"
     8  	"github.com/chwjbn/xclash/context"
     9  	"github.com/chwjbn/xclash/log"
    10  
    11  	D "github.com/miekg/dns"
    12  )
    13  
    14  var (
    15  	address string
    16  	server  = &Server{}
    17  
    18  	dnsDefaultTTL uint32 = 600
    19  )
    20  
    21  type Server struct {
    22  	*D.Server
    23  	handler handler
    24  }
    25  
    26  // ServeDNS implement D.Handler ServeDNS
    27  func (s *Server) ServeDNS(w D.ResponseWriter, r *D.Msg) {
    28  	msg, err := handlerWithContext(s.handler, r)
    29  	if err != nil {
    30  		D.HandleFailed(w, r)
    31  		return
    32  	}
    33  	msg.Compress = true
    34  	w.WriteMsg(msg)
    35  }
    36  
    37  func handlerWithContext(handler handler, msg *D.Msg) (*D.Msg, error) {
    38  	if len(msg.Question) == 0 {
    39  		return nil, errors.New("at least one question is required")
    40  	}
    41  
    42  	ctx := context.NewDNSContext(msg)
    43  	return handler(ctx, msg)
    44  }
    45  
    46  func (s *Server) setHandler(handler handler) {
    47  	s.handler = handler
    48  }
    49  
    50  func ReCreateServer(addr string, resolver *Resolver, mapper *ResolverEnhancer) {
    51  	if addr == address && resolver != nil {
    52  		handler := newHandler(resolver, mapper)
    53  		server.setHandler(handler)
    54  		return
    55  	}
    56  
    57  	if server.Server != nil {
    58  		server.Shutdown()
    59  		server = &Server{}
    60  		address = ""
    61  	}
    62  
    63  	var err error
    64  	defer func() {
    65  		if err != nil {
    66  			log.Errorln("Start DNS server error: %s", err.Error())
    67  		}
    68  	}()
    69  
    70  	_, port, err := net.SplitHostPort(addr)
    71  	if port == "0" || port == "" || err != nil {
    72  		return
    73  	}
    74  
    75  	udpAddr, err := net.ResolveUDPAddr("udp", addr)
    76  	if err != nil {
    77  		return
    78  	}
    79  
    80  	p, err := net.ListenUDP("udp", udpAddr)
    81  	if err != nil {
    82  		return
    83  	}
    84  
    85  	err = sockopt.UDPReuseaddr(p)
    86  	if err != nil {
    87  		log.Warnln("Failed to Reuse UDP Address: %s", err)
    88  
    89  		err = nil
    90  	}
    91  
    92  	address = addr
    93  	handler := newHandler(resolver, mapper)
    94  	server = &Server{handler: handler}
    95  	server.Server = &D.Server{Addr: addr, PacketConn: p, Handler: server}
    96  
    97  	go func() {
    98  		server.ActivateAndServe()
    99  	}()
   100  
   101  	log.Infoln("DNS server listening at: %s", p.LocalAddr().String())
   102  }