|  | @@ -11,6 +11,7 @@ import (
 | 
	
		
			
				|  |  |  	"v2ray.com/core"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common"
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/net"
 | 
	
		
			
				|  |  | +	"v2ray.com/core/common/signal"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const (
 | 
	
	
		
			
				|  | @@ -37,6 +38,7 @@ type Server struct {
 | 
	
		
			
				|  |  |  	hosts   map[string]net.IP
 | 
	
		
			
				|  |  |  	records map[string]*DomainRecord
 | 
	
		
			
				|  |  |  	servers []NameServer
 | 
	
		
			
				|  |  | +	task    *signal.PeriodicTask
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func New(ctx context.Context, config *Config) (*Server, error) {
 | 
	
	
		
			
				|  | @@ -45,6 +47,13 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 | 
	
		
			
				|  |  |  		servers: make([]NameServer, len(config.NameServers)),
 | 
	
		
			
				|  |  |  		hosts:   config.GetInternalHosts(),
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	server.task = &signal.PeriodicTask{
 | 
	
		
			
				|  |  | +		Interval: time.Minute * 10,
 | 
	
		
			
				|  |  | +		Execute: func() error {
 | 
	
		
			
				|  |  | +			server.cleanup()
 | 
	
		
			
				|  |  | +			return nil
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  |  	v := core.FromContext(ctx)
 | 
	
		
			
				|  |  |  	if v == nil {
 | 
	
		
			
				|  |  |  		return nil, newError("V is not in context.")
 | 
	
	
		
			
				|  | @@ -75,16 +84,14 @@ func New(ctx context.Context, config *Config) (*Server, error) {
 | 
	
		
			
				|  |  |  	return server, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (*Server) Interface() interface{} {
 | 
	
		
			
				|  |  | -	return (*Server)(nil)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +// Start implements common.Runnable.
 | 
	
		
			
				|  |  |  func (s *Server) Start() error {
 | 
	
		
			
				|  |  | -	return nil
 | 
	
		
			
				|  |  | +	return s.task.Start()
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (*Server) Close() error {
 | 
	
		
			
				|  |  | -	return nil
 | 
	
		
			
				|  |  | +// Close implements common.Runnable.
 | 
	
		
			
				|  |  | +func (s *Server) Close() error {
 | 
	
		
			
				|  |  | +	return s.task.Close()
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (s *Server) GetCached(domain string) []net.IP {
 | 
	
	
		
			
				|  | @@ -98,18 +105,12 @@ func (s *Server) GetCached(domain string) []net.IP {
 | 
	
		
			
				|  |  |  	return nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -func (s *Server) tryCleanup() {
 | 
	
		
			
				|  |  | +func (s *Server) cleanup() {
 | 
	
		
			
				|  |  |  	s.Lock()
 | 
	
		
			
				|  |  |  	defer s.Unlock()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if len(s.records) > 256 {
 | 
	
		
			
				|  |  | -		domains := make([]string, 0, 256)
 | 
	
		
			
				|  |  | -		for d, r := range s.records {
 | 
	
		
			
				|  |  | -			if r.Expired() {
 | 
	
		
			
				|  |  | -				domains = append(domains, d)
 | 
	
		
			
				|  |  | -			}
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -		for _, d := range domains {
 | 
	
		
			
				|  |  | +	for d, r := range s.records {
 | 
	
		
			
				|  |  | +		if r.Expired() {
 | 
	
		
			
				|  |  |  			delete(s.records, d)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -126,8 +127,6 @@ func (s *Server) LookupIP(domain string) ([]net.IP, error) {
 | 
	
		
			
				|  |  |  		return ips, nil
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	s.tryCleanup()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	for _, server := range s.servers {
 | 
	
		
			
				|  |  |  		response := server.QueryA(domain)
 | 
	
		
			
				|  |  |  		select {
 |