Files
gluetun/internal/configuration/sources/env/serverselection.go
2023-06-01 09:07:22 +00:00

134 lines
3.2 KiB
Go

package env
import (
"errors"
"fmt"
"net/netip"
"strconv"
"strings"
"github.com/qdm12/gluetun/internal/configuration/settings"
"github.com/qdm12/gluetun/internal/constants/providers"
)
var (
ErrServerNumberNotValid = errors.New("server number is not valid")
)
func (s *Source) readServerSelection(vpnProvider, vpnType string) (
ss settings.ServerSelection, err error) {
ss.VPN = vpnType
ss.TargetIP, err = s.readOpenVPNTargetIP()
if err != nil {
return ss, err
}
countriesKey, _ := s.getEnvWithRetro("SERVER_COUNTRIES", []string{"COUNTRY"})
ss.Countries = s.env.CSV(countriesKey)
if vpnProvider == providers.Cyberghost && len(ss.Countries) == 0 {
// Retro-compatibility for Cyberghost using the REGION variable
ss.Countries = s.env.CSV("REGION")
if len(ss.Countries) > 0 {
s.onRetroActive("REGION", "SERVER_COUNTRIES")
}
}
regionsKey, _ := s.getEnvWithRetro("SERVER_REGIONS", []string{"REGION"})
ss.Regions = s.env.CSV(regionsKey)
citiesKey, _ := s.getEnvWithRetro("SERVER_CITIES", []string{"CITY"})
ss.Cities = s.env.CSV(citiesKey)
ss.ISPs = s.env.CSV("ISP")
hostnamesKey, _ := s.getEnvWithRetro("SERVER_HOSTNAMES", []string{"SERVER_HOSTNAME"})
ss.Hostnames = s.env.CSV(hostnamesKey)
serverNamesKey, _ := s.getEnvWithRetro("SERVER_NAMES", []string{"SERVER_NAME"})
ss.Names = s.env.CSV(serverNamesKey)
if csv := s.env.Get("SERVER_NUMBER"); csv != nil {
numbersStrings := strings.Split(*csv, ",")
numbers := make([]uint16, len(numbersStrings))
for i, numberString := range numbersStrings {
const base, bitSize = 10, 16
number, err := strconv.ParseInt(numberString, base, bitSize)
if err != nil {
return ss, fmt.Errorf("%w: %s",
ErrServerNumberNotValid, numberString)
} else if number < 0 || number > 65535 {
return ss, fmt.Errorf("%w: %d must be between 0 and 65535",
ErrServerNumberNotValid, number)
}
numbers[i] = uint16(number)
}
ss.Numbers = numbers
}
// Mullvad only
ss.OwnedOnly, err = s.readOwnedOnly()
if err != nil {
return ss, err
}
// VPNUnlimited and ProtonVPN only
ss.FreeOnly, err = s.env.BoolPtr("FREE_ONLY")
if err != nil {
return ss, err
}
// VPNSecure only
ss.PremiumOnly, err = s.env.BoolPtr("PREMIUM_ONLY")
if err != nil {
return ss, err
}
// VPNUnlimited only
ss.MultiHopOnly, err = s.env.BoolPtr("MULTIHOP_ONLY")
if err != nil {
return ss, err
}
// VPNUnlimited only
ss.MultiHopOnly, err = s.env.BoolPtr("STREAM_ONLY")
if err != nil {
return ss, err
}
ss.OpenVPN, err = s.readOpenVPNSelection()
if err != nil {
return ss, err
}
ss.Wireguard, err = s.readWireguardSelection()
if err != nil {
return ss, err
}
return ss, nil
}
var (
ErrInvalidIP = errors.New("invalid IP address")
)
func (s *Source) readOpenVPNTargetIP() (ip netip.Addr, err error) {
envKey, value := s.getEnvWithRetro("VPN_ENDPOINT_IP", []string{"OPENVPN_TARGET_IP"})
if value == nil {
return ip, nil
}
ip, err = netip.ParseAddr(*value)
if err != nil {
return ip, fmt.Errorf("environment variable %s: %w", envKey, err)
}
return ip, nil
}
func (s *Source) readOwnedOnly() (ownedOnly *bool, err error) {
envKey, _ := s.getEnvWithRetro("OWNED_ONLY", []string{"OWNED"})
return s.env.BoolPtr(envKey)
}