github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/ip/cached_resolver.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package ip 19 20 import ( 21 "sync" 22 "time" 23 24 "github.com/rs/zerolog/log" 25 ) 26 27 // CachedResolver resolves IP and caches for some duration. 28 type CachedResolver struct { 29 resolver Resolver 30 cacheDuration time.Duration 31 32 outboundIP string 33 outboundIPLock sync.Mutex 34 outboundIPCachedAt time.Time 35 36 publicIP string 37 publicIPLock sync.Mutex 38 publicIPCachedAt time.Time 39 } 40 41 // NewCachedResolver creates ip resolver with cache duration. 42 func NewCachedResolver(resolver Resolver, cacheDuration time.Duration) *CachedResolver { 43 return &CachedResolver{ 44 resolver: resolver, 45 cacheDuration: cacheDuration, 46 } 47 } 48 49 // GetOutboundIP returns current outbound IP as string for current system. 50 func (r *CachedResolver) GetOutboundIP() (string, error) { 51 r.outboundIPLock.Lock() 52 defer r.outboundIPLock.Unlock() 53 54 if r.outboundIPCachedAt.Add(r.cacheDuration).After(time.Now()) && r.outboundIP != "" { 55 log.Debug().Msgf("Found cached outbound IP") 56 return r.outboundIP, nil 57 } 58 59 log.Debug().Msg("Outbound IP cache is empty, fetching IP") 60 outboundIP, err := r.resolver.GetOutboundIP() 61 if err != nil { 62 return "", err 63 } 64 r.outboundIPCachedAt = time.Now() 65 r.outboundIP = outboundIP 66 return r.outboundIP, nil 67 } 68 69 // GetPublicIP returns current public IP. 70 func (r *CachedResolver) GetPublicIP() (string, error) { 71 r.publicIPLock.Lock() 72 defer r.publicIPLock.Unlock() 73 74 if r.publicIPCachedAt.Add(r.cacheDuration).After(time.Now()) && r.publicIP != "" { 75 log.Debug().Msgf("Found cached public IP") 76 return r.publicIP, nil 77 } 78 79 log.Debug().Msg("Public IP cache is empty, fetching IP") 80 publicIP, err := r.resolver.GetPublicIP() 81 if err != nil { 82 return "", err 83 } 84 r.publicIPCachedAt = time.Now() 85 r.publicIP = publicIP 86 return r.publicIP, nil 87 } 88 89 // GetProxyIP returns proxy public IP. 90 func (r *CachedResolver) GetProxyIP(proxyPort int) (string, error) { 91 publicIP, err := r.resolver.GetProxyIP(proxyPort) 92 if err != nil { 93 return "", err 94 } 95 96 return publicIP, nil 97 } 98 99 // ClearCache clears ip cache. 100 func (r *CachedResolver) ClearCache() { 101 log.Debug().Msg("Clearing ip resolver cache") 102 103 r.outboundIPLock.Lock() 104 r.outboundIP = "" 105 r.outboundIPCachedAt = time.Time{} 106 r.outboundIPLock.Unlock() 107 108 r.publicIPLock.Lock() 109 r.publicIP = "" 110 r.publicIPCachedAt = time.Time{} 111 r.publicIPLock.Unlock() 112 }