79 lines
1.8 KiB
Go
79 lines
1.8 KiB
Go
package app
|
|
|
|
import (
|
|
"net/http"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
egressIdentityFreshTTL = 3 * time.Minute
|
|
egressIdentityBackoffMin = 3 * time.Second
|
|
egressIdentityBackoffMax = 2 * time.Minute
|
|
egressIdentityProbeTimeout = 4 * time.Second
|
|
egressIdentityGeoTimeout = 4 * time.Second
|
|
egressIdentityGeoCacheTTL = 24 * time.Hour
|
|
egressIdentityGeoFailTTL = 30 * time.Second
|
|
egressIdentityMaxConcurrency = 2
|
|
)
|
|
|
|
var (
|
|
egressIdentitySWR = newEgressIdentityService(
|
|
envInt("SVPN_EGRESS_MAX_PARALLEL", egressIdentityMaxConcurrency),
|
|
)
|
|
egressHTTPClient = &http.Client{}
|
|
)
|
|
|
|
type egressScopeTarget struct {
|
|
Scope string
|
|
Source string
|
|
SourceID string
|
|
}
|
|
|
|
type egressSourceProvider interface {
|
|
Probe(target egressScopeTarget) (string, error)
|
|
}
|
|
|
|
type egressIdentityEntry struct {
|
|
item EgressIdentity
|
|
swr refreshCoordinator
|
|
}
|
|
|
|
type egressGeoCacheEntry struct {
|
|
CountryCode string
|
|
CountryName string
|
|
LastError string
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
type egressIdentityService struct {
|
|
mu sync.Mutex
|
|
entries map[string]*egressIdentityEntry
|
|
sem chan struct{}
|
|
providers map[string]egressSourceProvider
|
|
|
|
geoMu sync.Mutex
|
|
geoCache map[string]egressGeoCacheEntry
|
|
}
|
|
|
|
type egressSystemProvider struct{}
|
|
type egressAdGuardProvider struct{}
|
|
type egressTransportProvider struct{}
|
|
|
|
func newEgressIdentityService(maxConcurrent int) *egressIdentityService {
|
|
n := maxConcurrent
|
|
if n <= 0 {
|
|
n = egressIdentityMaxConcurrency
|
|
}
|
|
return &egressIdentityService{
|
|
entries: map[string]*egressIdentityEntry{},
|
|
sem: make(chan struct{}, n),
|
|
providers: map[string]egressSourceProvider{
|
|
"system": egressSystemProvider{},
|
|
"adguardvpn": egressAdGuardProvider{},
|
|
"transport": egressTransportProvider{},
|
|
},
|
|
geoCache: map[string]egressGeoCacheEntry{},
|
|
}
|
|
}
|