Fix: server data version diff when reading file
This commit is contained in:
@@ -3,26 +3,280 @@ package storage
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
)
|
||||
|
||||
func readFromFile(filepath string) (servers models.AllServers, err error) {
|
||||
// readFromFile reads the servers from server.json.
|
||||
// It only reads servers that have the same version as the hardcoded servers version
|
||||
// to avoid JSON unmarshaling errors.
|
||||
func (s *Storage) readFromFile(filepath string, hardcoded models.AllServers) (
|
||||
servers models.AllServers, err error) {
|
||||
file, err := os.Open(filepath)
|
||||
if os.IsNotExist(err) {
|
||||
return servers, nil
|
||||
} else if err != nil {
|
||||
return servers, err
|
||||
}
|
||||
decoder := json.NewDecoder(file)
|
||||
if err := decoder.Decode(&servers); err != nil {
|
||||
_ = file.Close()
|
||||
if errors.Is(err, io.EOF) {
|
||||
return servers, nil
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return servers, err
|
||||
}
|
||||
return servers, file.Close()
|
||||
|
||||
if err := file.Close(); err != nil {
|
||||
return servers, err
|
||||
}
|
||||
|
||||
return s.extractServersFromBytes(b, hardcoded)
|
||||
}
|
||||
|
||||
var (
|
||||
errDecodeVersions = errors.New("cannot decode versions")
|
||||
errDecodeServers = errors.New("cannot decode servers")
|
||||
errDecodeProvider = errors.New("cannot decode servers for provider")
|
||||
)
|
||||
|
||||
func (s *Storage) extractServersFromBytes(b []byte, hardcoded models.AllServers) ( //nolint:gocognit,gocyclo
|
||||
servers models.AllServers, err error) {
|
||||
var versions allVersions
|
||||
if err := json.Unmarshal(b, &versions); err != nil {
|
||||
return servers, fmt.Errorf("%w: %s", errDecodeVersions, err)
|
||||
}
|
||||
|
||||
var rawMessages allJSONRawMessages
|
||||
if err := json.Unmarshal(b, &rawMessages); err != nil {
|
||||
return servers, fmt.Errorf("%w: %s", errDecodeServers, err)
|
||||
}
|
||||
|
||||
// TODO simplify with generics in Go 1.18
|
||||
|
||||
if hardcoded.Cyberghost.Version != versions.Cyberghost.Version {
|
||||
s.logVersionDiff("Cyberghost", hardcoded.Cyberghost.Version, versions.Cyberghost.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Cyberghost, &servers.Cyberghost)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Cyberghost", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Expressvpn.Version != versions.Expressvpn.Version {
|
||||
s.logVersionDiff("Expressvpn", hardcoded.Expressvpn.Version, versions.Expressvpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Expressvpn, &servers.Expressvpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Expressvpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Fastestvpn.Version != versions.Fastestvpn.Version {
|
||||
s.logVersionDiff("Fastestvpn", hardcoded.Fastestvpn.Version, versions.Fastestvpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Fastestvpn, &servers.Fastestvpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Fastestvpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.HideMyAss.Version != versions.HideMyAss.Version {
|
||||
s.logVersionDiff("HideMyAss", hardcoded.HideMyAss.Version, versions.HideMyAss.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.HideMyAss, &servers.HideMyAss)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "HideMyAss", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Ipvanish.Version != versions.Ipvanish.Version {
|
||||
s.logVersionDiff("Ipvanish", hardcoded.Ipvanish.Version, versions.Ipvanish.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Ipvanish, &servers.Ipvanish)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Ipvanish", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Ivpn.Version != versions.Ivpn.Version {
|
||||
s.logVersionDiff("Ivpn", hardcoded.Ivpn.Version, versions.Ivpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Ivpn, &servers.Ivpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Ivpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Mullvad.Version != versions.Mullvad.Version {
|
||||
s.logVersionDiff("Mullvad", hardcoded.Mullvad.Version, versions.Mullvad.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Mullvad, &servers.Mullvad)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Mullvad", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Nordvpn.Version != versions.Nordvpn.Version {
|
||||
s.logVersionDiff("Nordvpn", hardcoded.Nordvpn.Version, versions.Nordvpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Nordvpn, &servers.Nordvpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Nordvpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Privado.Version != versions.Privado.Version {
|
||||
s.logVersionDiff("Privado", hardcoded.Privado.Version, versions.Privado.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Privado, &servers.Privado)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Privado", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Pia.Version != versions.Pia.Version {
|
||||
s.logVersionDiff("Pia", hardcoded.Pia.Version, versions.Pia.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Pia, &servers.Pia)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Pia", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Privatevpn.Version != versions.Privatevpn.Version {
|
||||
s.logVersionDiff("Privatevpn", hardcoded.Privatevpn.Version, versions.Privatevpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Privatevpn, &servers.Privatevpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Privatevpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Protonvpn.Version != versions.Protonvpn.Version {
|
||||
s.logVersionDiff("Protonvpn", hardcoded.Protonvpn.Version, versions.Protonvpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Protonvpn, &servers.Protonvpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Protonvpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Purevpn.Version != versions.Purevpn.Version {
|
||||
s.logVersionDiff("Purevpn", hardcoded.Purevpn.Version, versions.Purevpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Purevpn, &servers.Purevpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Purevpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Surfshark.Version != versions.Surfshark.Version {
|
||||
s.logVersionDiff("Surfshark", hardcoded.Surfshark.Version, versions.Surfshark.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Surfshark, &servers.Surfshark)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Surfshark", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Torguard.Version != versions.Torguard.Version {
|
||||
s.logVersionDiff("Torguard", hardcoded.Torguard.Version, versions.Torguard.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Torguard, &servers.Torguard)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Torguard", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.VPNUnlimited.Version != versions.VPNUnlimited.Version {
|
||||
s.logVersionDiff("VPNUnlimited", hardcoded.VPNUnlimited.Version, versions.VPNUnlimited.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.VPNUnlimited, &servers.VPNUnlimited)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "VPNUnlimited", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Vyprvpn.Version != versions.Vyprvpn.Version {
|
||||
s.logVersionDiff("Vyprvpn", hardcoded.Vyprvpn.Version, versions.Vyprvpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Vyprvpn, &servers.Vyprvpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Vyprvpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Wevpn.Version != versions.Wevpn.Version {
|
||||
s.logVersionDiff("Wevpn", hardcoded.Wevpn.Version, versions.Wevpn.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Wevpn, &servers.Wevpn)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Wevpn", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hardcoded.Windscribe.Version != versions.Windscribe.Version {
|
||||
s.logVersionDiff("Windscribe", hardcoded.Windscribe.Version, versions.Windscribe.Version)
|
||||
} else {
|
||||
err = json.Unmarshal(rawMessages.Windscribe, &servers.Windscribe)
|
||||
if err != nil {
|
||||
return servers, fmt.Errorf("%w: %s: %s", errDecodeProvider, "Windscribe", err)
|
||||
}
|
||||
}
|
||||
|
||||
return servers, nil
|
||||
}
|
||||
|
||||
// allVersions is a subset of models.AllServers structure used to track
|
||||
// versions to avoid unmarshaling errors.
|
||||
type allVersions struct {
|
||||
Version uint16 `json:"version"` // used for migration of the top level scheme
|
||||
Cyberghost serverVersion `json:"cyberghost"`
|
||||
Expressvpn serverVersion `json:"expressvpn"`
|
||||
Fastestvpn serverVersion `json:"fastestvpn"`
|
||||
HideMyAss serverVersion `json:"hidemyass"`
|
||||
Ipvanish serverVersion `json:"ipvanish"`
|
||||
Ivpn serverVersion `json:"ivpn"`
|
||||
Mullvad serverVersion `json:"mullvad"`
|
||||
Nordvpn serverVersion `json:"nordvpn"`
|
||||
Privado serverVersion `json:"privado"`
|
||||
Pia serverVersion `json:"pia"`
|
||||
Privatevpn serverVersion `json:"privatevpn"`
|
||||
Protonvpn serverVersion `json:"protonvpn"`
|
||||
Purevpn serverVersion `json:"purevpn"`
|
||||
Surfshark serverVersion `json:"surfshark"`
|
||||
Torguard serverVersion `json:"torguard"`
|
||||
VPNUnlimited serverVersion `json:"vpnunlimited"`
|
||||
Vyprvpn serverVersion `json:"vyprvpn"`
|
||||
Wevpn serverVersion `json:"wevpn"`
|
||||
Windscribe serverVersion `json:"windscribe"`
|
||||
}
|
||||
|
||||
type serverVersion struct {
|
||||
Version uint16 `json:"version"`
|
||||
}
|
||||
|
||||
// allJSONRawMessages is to delay decoding of each provider servers.
|
||||
type allJSONRawMessages struct {
|
||||
Version uint16 `json:"version"` // used for migration of the top level scheme
|
||||
Cyberghost json.RawMessage `json:"cyberghost"`
|
||||
Expressvpn json.RawMessage `json:"expressvpn"`
|
||||
Fastestvpn json.RawMessage `json:"fastestvpn"`
|
||||
HideMyAss json.RawMessage `json:"hidemyass"`
|
||||
Ipvanish json.RawMessage `json:"ipvanish"`
|
||||
Ivpn json.RawMessage `json:"ivpn"`
|
||||
Mullvad json.RawMessage `json:"mullvad"`
|
||||
Nordvpn json.RawMessage `json:"nordvpn"`
|
||||
Privado json.RawMessage `json:"privado"`
|
||||
Pia json.RawMessage `json:"pia"`
|
||||
Privatevpn json.RawMessage `json:"privatevpn"`
|
||||
Protonvpn json.RawMessage `json:"protonvpn"`
|
||||
Purevpn json.RawMessage `json:"purevpn"`
|
||||
Surfshark json.RawMessage `json:"surfshark"`
|
||||
Torguard json.RawMessage `json:"torguard"`
|
||||
VPNUnlimited json.RawMessage `json:"vpnunlimited"`
|
||||
Vyprvpn json.RawMessage `json:"vyprvpn"`
|
||||
Wevpn json.RawMessage `json:"wevpn"`
|
||||
Windscribe json.RawMessage `json:"windscribe"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user