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  }