|
|
|
@ -10,14 +10,10 @@ import (
|
|
|
|
|
"v2ray.com/core/common/buf"
|
|
|
|
|
"v2ray.com/core/common/dice"
|
|
|
|
|
"v2ray.com/core/common/net"
|
|
|
|
|
"v2ray.com/core/common/signal"
|
|
|
|
|
"v2ray.com/core/transport/internet/udp"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
CleanupInterval = time.Second * 120
|
|
|
|
|
CleanupThreshold = 512
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
multiQuestionDNS = map[net.Address]bool{
|
|
|
|
|
net.IPAddress([]byte{8, 8, 8, 8}): true,
|
|
|
|
@ -45,7 +41,7 @@ type UDPNameServer struct {
|
|
|
|
|
address net.Destination
|
|
|
|
|
requests map[uint16]*PendingRequest
|
|
|
|
|
udpServer *udp.Dispatcher
|
|
|
|
|
nextCleanup time.Time
|
|
|
|
|
cleanup *signal.PeriodicTask
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewUDPNameServer(address net.Destination, dispatcher core.Dispatcher) *UDPNameServer {
|
|
|
|
@ -54,36 +50,35 @@ func NewUDPNameServer(address net.Destination, dispatcher core.Dispatcher) *UDPN
|
|
|
|
|
requests: make(map[uint16]*PendingRequest),
|
|
|
|
|
udpServer: udp.NewDispatcher(dispatcher),
|
|
|
|
|
}
|
|
|
|
|
s.cleanup = &signal.PeriodicTask{
|
|
|
|
|
Interval: time.Minute,
|
|
|
|
|
Execute: s.Cleanup,
|
|
|
|
|
}
|
|
|
|
|
s.cleanup.Start()
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *UDPNameServer) Cleanup() {
|
|
|
|
|
expiredRequests := make([]uint16, 0, 16)
|
|
|
|
|
func (s *UDPNameServer) Cleanup() error {
|
|
|
|
|
now := time.Now()
|
|
|
|
|
s.Lock()
|
|
|
|
|
for id, r := range s.requests {
|
|
|
|
|
if r.expire.Before(now) {
|
|
|
|
|
expiredRequests = append(expiredRequests, id)
|
|
|
|
|
close(r.response)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, id := range expiredRequests {
|
|
|
|
|
delete(s.requests, id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s.Unlock()
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *UDPNameServer) AssignUnusedID(response chan<- *ARecord) uint16 {
|
|
|
|
|
var id uint16
|
|
|
|
|
s.Lock()
|
|
|
|
|
if len(s.requests) > CleanupThreshold && s.nextCleanup.Before(time.Now()) {
|
|
|
|
|
s.nextCleanup = time.Now().Add(CleanupInterval)
|
|
|
|
|
go s.Cleanup()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
id = dice.RollUint16()
|
|
|
|
|
if _, found := s.requests[id]; found {
|
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
newError("add pending request id ", id).AtDebug().WriteToLog()
|
|
|
|
|