This commit is contained in:
Quentin McGaw
2024-08-01 07:51:35 +00:00
parent ceb6ff4ca4
commit 1a6e8d74d6
12 changed files with 119 additions and 145 deletions

View File

@@ -7,11 +7,12 @@ import (
"fmt"
"net/http"
"github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/provider/surfshark/servers"
)
func addServersFromAPI(ctx context.Context, client *http.Client,
hts hostToServers) (err error) {
hts hostToServer) (err error) {
data, err := fetchAPI(ctx, client)
if err != nil {
return err
@@ -25,12 +26,14 @@ func addServersFromAPI(ctx context.Context, client *http.Client,
retroLoc := locationData.RetroLoc // empty string if the host has no retro-compatible region
tcp, udp := true, true // OpenVPN servers from API supports both TCP and UDP
hts.addOpenVPN(serverData.Host, serverData.Region, serverData.Country,
serverData.Location, retroLoc, tcp, udp)
const wgPubKey = ""
hts.add(serverData.Host, vpn.OpenVPN, serverData.Region, serverData.Country,
serverData.Location, retroLoc, wgPubKey, tcp, udp)
if serverData.PubKey != "" {
hts.addWireguard(serverData.Host, serverData.Region, serverData.Country,
serverData.Location, retroLoc, serverData.PubKey)
const wgTCP, wgUDP = false, false // unused
hts.add(serverData.Host, vpn.Wireguard, serverData.Region, serverData.Country,
serverData.Location, retroLoc, serverData.PubKey, wgTCP, wgUDP)
}
}

View File

@@ -24,9 +24,9 @@ func Test_addServersFromAPI(t *testing.T) {
t.Parallel()
testCases := map[string]struct {
hts hostToServers
hts hostToServer
exchanges []httpExchange
expected hostToServers
expected hostToServer
err error
}{
"fetch API error": {
@@ -37,8 +37,8 @@ func Test_addServersFromAPI(t *testing.T) {
err: errors.New("HTTP status code not OK: 204 No Content"),
},
"success": {
hts: hostToServers{
"existinghost": []models.Server{{Hostname: "existinghost"}},
hts: hostToServer{
"existinghost": models.Server{Hostname: "existinghost"},
},
exchanges: []httpExchange{{
requestURL: "https://api.surfshark.com/v4/server/clusters/generic",
@@ -61,25 +61,19 @@ func Test_addServersFromAPI(t *testing.T) {
responseStatus: http.StatusOK,
responseBody: io.NopCloser(strings.NewReader(`[]`)),
}},
expected: map[string][]models.Server{
"existinghost": {{Hostname: "existinghost"}},
"host1": {{
VPN: vpn.OpenVPN,
expected: map[string]models.Server{
"existinghost": {Hostname: "existinghost"},
"host1": {
VPN: vpn.Both,
Region: "region1",
Country: "country1",
City: "location1",
Hostname: "host1",
TCP: true,
UDP: true,
}, {
VPN: vpn.Wireguard,
Region: "region1",
Country: "country1",
City: "location1",
Hostname: "host1",
WgPubKey: "pubKeyValue",
}},
"host2": {{
},
"host2": {
VPN: vpn.OpenVPN,
Region: "region2",
Country: "country1",
@@ -87,7 +81,7 @@ func Test_addServersFromAPI(t *testing.T) {
Hostname: "host2",
TCP: true,
UDP: true,
}},
},
},
},
}

View File

@@ -7,94 +7,62 @@ import (
"github.com/qdm12/gluetun/internal/models"
)
type hostToServers map[string][]models.Server
type hostToServer map[string]models.Server
func (hts hostToServers) addOpenVPN(host, region, country, city,
retroLoc string, tcp, udp bool) {
// Check for existing server for this host and OpenVPN.
servers := hts[host]
for i, existingServer := range servers {
if existingServer.Hostname != host ||
existingServer.VPN != vpn.OpenVPN {
continue
}
// Update OpenVPN supported protocols and return
if !existingServer.TCP {
servers[i].TCP = tcp
}
if !existingServer.UDP {
servers[i].UDP = udp
func (hts hostToServer) add(host, vpnType, region, country, city,
retroLoc, wgPubKey string, openvpnTCP, openvpnUDP bool) {
server, ok := hts[host]
if !ok {
server := models.Server{
VPN: vpnType,
Region: region,
Country: country,
City: city,
RetroLoc: retroLoc,
Hostname: host,
WgPubKey: wgPubKey,
TCP: openvpnTCP,
UDP: openvpnUDP,
}
hts[host] = server
return
}
server := models.Server{
VPN: vpn.OpenVPN,
Region: region,
Country: country,
City: city,
RetroLoc: retroLoc,
Hostname: host,
TCP: tcp,
UDP: udp,
server.SetVPN(vpnType)
if vpnType == vpn.OpenVPN {
server.TCP = server.TCP || openvpnTCP
server.UDP = server.UDP || openvpnUDP
} else if wgPubKey != "" {
server.WgPubKey = wgPubKey
}
hts[host] = append(servers, server)
hts[host] = server
}
func (hts hostToServers) addWireguard(host, region, country, city, retroLoc,
wgPubKey string) {
// Check for existing server for this host and Wireguard.
servers := hts[host]
for _, existingServer := range servers {
if existingServer.Hostname == host &&
existingServer.VPN == vpn.Wireguard {
// No update necessary for Wireguard
return
}
}
server := models.Server{
VPN: vpn.Wireguard,
Region: region,
Country: country,
City: city,
RetroLoc: retroLoc,
Hostname: host,
WgPubKey: wgPubKey,
}
hts[host] = append(servers, server)
}
func (hts hostToServers) toHostsSlice() (hosts []string) {
const vpnServerTypes = 2 // OpenVPN + Wireguard
hosts = make([]string, 0, vpnServerTypes*len(hts))
func (hts hostToServer) toHostsSlice() (hosts []string) {
hosts = make([]string, 0, len(hts))
for host := range hts {
hosts = append(hosts, host)
}
return hosts
}
func (hts hostToServers) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
for host, IPs := range hostToIPs {
servers := hts[host]
for i := range servers {
servers[i].IPs = IPs
}
hts[host] = servers
}
for host, servers := range hts {
if len(servers[0].IPs) == 0 {
func (hts hostToServer) adaptWithIPs(hostToIPs map[string][]netip.Addr) {
for host, server := range hts {
ips := hostToIPs[host]
if len(ips) == 0 {
delete(hts, host)
continue
}
server.IPs = ips
hts[host] = server
}
}
func (hts hostToServers) toServersSlice() (servers []models.Server) {
const vpnServerTypes = 2 // OpenVPN + Wireguard
servers = make([]models.Server, 0, vpnServerTypes*len(hts))
for _, serversForHost := range hts {
servers = append(servers, serversForHost...)
func (hts hostToServer) toServersSlice() (servers []models.Server) {
servers = make([]models.Server, 0, len(hts))
for _, server := range hts {
servers = append(servers, server)
}
return servers
}

View File

@@ -1,11 +1,12 @@
package updater
import (
"github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/provider/surfshark/servers"
)
// getRemainingServers finds extra servers not found in the API or in the ZIP file.
func getRemainingServers(hts hostToServers) {
func getRemainingServers(hts hostToServer) {
locationData := servers.LocationData()
hostnameToLocationLeft := hostToLocation(locationData)
for _, hostnameDone := range hts.toHostsSlice() {
@@ -15,7 +16,8 @@ func getRemainingServers(hts hostToServers) {
for hostname, locationData := range hostnameToLocationLeft {
// we assume the OpenVPN server supports both TCP and UDP
const tcp, udp = true, true
hts.addOpenVPN(hostname, locationData.Region, locationData.Country,
locationData.City, locationData.RetroLoc, tcp, udp)
const wgPubKey = ""
hts.add(hostname, vpn.OpenVPN, locationData.Region, locationData.Country,
locationData.City, locationData.RetroLoc, wgPubKey, tcp, udp)
}
}

View File

@@ -11,7 +11,7 @@ import (
func (u *Updater) FetchServers(ctx context.Context, minServers int) (
servers []models.Server, err error) {
hts := make(hostToServers)
hts := make(hostToServer)
err = addServersFromAPI(ctx, u.client, hts)
if err != nil {

View File

@@ -4,13 +4,14 @@ import (
"context"
"strings"
"github.com/qdm12/gluetun/internal/constants/vpn"
"github.com/qdm12/gluetun/internal/provider/common"
"github.com/qdm12/gluetun/internal/provider/surfshark/servers"
"github.com/qdm12/gluetun/internal/updater/openvpn"
)
func addOpenVPNServersFromZip(ctx context.Context,
unzipper common.Unzipper, hts hostToServers) (
unzipper common.Unzipper, hts hostToServer) (
warnings []string, err error) {
const url = "https://my.surfshark.com/vpn/api/v1/server/configurations"
contents, err := unzipper.FetchAndExtract(ctx, url)
@@ -66,8 +67,9 @@ func addOpenVPNServersFromZip(ctx context.Context,
continue
}
hts.addOpenVPN(host, data.Region, data.Country, data.City,
data.RetroLoc, tcp, udp)
const wgPubKey = ""
hts.add(host, vpn.OpenVPN, data.Region, data.Country, data.City,
data.RetroLoc, wgPubKey, tcp, udp)
}
return warnings, nil