diff --git a/holepunch/holepunch.go b/holepunch/holepunch.go index 8000837..d7e1c14 100644 --- a/holepunch/holepunch.go +++ b/holepunch/holepunch.go @@ -27,17 +27,17 @@ type ExitNode struct { // Manager handles UDP hole punching operations type Manager struct { - mu sync.Mutex - running bool - stopChan chan struct{} - sharedBind *bind.SharedBind - ID string - token string - publicKey string - clientType string - exitNodes map[string]ExitNode // key is endpoint - updateChan chan struct{} // signals the goroutine to refresh exit nodes - publicDNS []string + mu sync.Mutex + running bool + stopChan chan struct{} + sharedBind *bind.SharedBind + ID string + token string + publicKey string + clientType string + exitNodes map[string]ExitNode // key is endpoint + updateChan chan struct{} // signals the goroutine to refresh exit nodes + publicDNS []string sendHolepunchInterval time.Duration sendHolepunchIntervalMin time.Duration @@ -56,7 +56,7 @@ func NewManager(sharedBind *bind.SharedBind, ID string, clientType string, publi ID: ID, clientType: clientType, publicKey: publicKey, - publicDNS: publicDNS, + publicDNS: publicDNS, exitNodes: make(map[string]ExitNode), sendHolepunchInterval: defaultSendHolepunchIntervalMin, sendHolepunchIntervalMin: defaultSendHolepunchIntervalMin, @@ -73,6 +73,14 @@ func (m *Manager) SetToken(token string) { m.token = token } +// SetPublicDNS replaces the list of DNS servers used to resolve exit-node +// endpoints. The servers must be in "host:port" format (e.g. "8.8.8.8:53"). +func (m *Manager) SetPublicDNS(servers []string) { + m.mu.Lock() + defer m.mu.Unlock() + m.publicDNS = servers +} + // IsRunning returns whether hole punching is currently active func (m *Manager) IsRunning() bool { m.mu.Lock() diff --git a/holepunch/tester.go b/holepunch/tester.go index 85b8c89..6fa2934 100644 --- a/holepunch/tester.go +++ b/holepunch/tester.go @@ -43,17 +43,17 @@ func DefaultTestOptions() TestConnectionOptions { // cachedAddr holds a cached resolved UDP address type cachedAddr struct { - addr *net.UDPAddr + addr *net.UDPAddr resolvedAt time.Time } // HolepunchTester monitors holepunch connectivity using magic packets type HolepunchTester struct { - sharedBind *bind.SharedBind - publicDNS []string - mu sync.RWMutex - running bool - stopChan chan struct{} + sharedBind *bind.SharedBind + publicDNS []string + mu sync.RWMutex + running bool + stopChan chan struct{} // Pending requests waiting for responses (key: echo data as string) pendingRequests sync.Map // map[string]*pendingRequest @@ -88,12 +88,24 @@ type pendingRequest struct { func NewHolepunchTester(sharedBind *bind.SharedBind, publicDNS []string) *HolepunchTester { return &HolepunchTester{ sharedBind: sharedBind, - publicDNS: publicDNS, + publicDNS: publicDNS, addrCache: make(map[string]*cachedAddr), addrCacheTTL: 5 * time.Minute, // Cache addresses for 5 minutes } } +// SetPublicDNS replaces the list of DNS servers used to resolve peer endpoints. +// The servers must be in "host:port" format (e.g. "8.8.8.8:53"). +func (t *HolepunchTester) SetPublicDNS(servers []string) { + t.mu.Lock() + defer t.mu.Unlock() + t.publicDNS = servers + // Invalidate the address cache so endpoints are re-resolved with the new DNS. + t.addrCacheMu.Lock() + t.addrCache = make(map[string]*cachedAddr) + t.addrCacheMu.Unlock() +} + // SetCallback sets the callback for connection status changes func (t *HolepunchTester) SetCallback(callback HolepunchStatusCallback) { t.mu.Lock()