Add network test command
This commit is contained in:
@@ -45,7 +45,15 @@ func main() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.AddCommand(versionCmd, clearDownloadsCmd, clearTorrentsCmd)
|
var networkTestCmd = &cobra.Command{
|
||||||
|
Use: "network-test",
|
||||||
|
Short: "Test your network with RD servers",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
internal.NetworkTest()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rootCmd.AddCommand(versionCmd, clearDownloadsCmd, clearTorrentsCmd, networkTestCmd)
|
||||||
|
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|||||||
@@ -52,8 +52,10 @@ func MainApp(configPath string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
repoClient4 := http.NewHTTPClient("", 0, 1, false, []string{}, config, log.Named("network_test"))
|
proxyURL := os.Getenv("PROXY")
|
||||||
repoClient6 := http.NewHTTPClient("", 0, 1, true, []string{}, config, log.Named("network_test"))
|
|
||||||
|
repoClient4 := http.NewHTTPClient("", 0, 1, false, []string{}, proxyURL, log.Named("network_test"))
|
||||||
|
repoClient6 := http.NewHTTPClient("", 0, 1, true, []string{}, proxyURL, log.Named("network_test"))
|
||||||
repo := http.NewIPRepository(repoClient4, repoClient6, log.Named("network_test"))
|
repo := http.NewIPRepository(repoClient4, repoClient6, log.Named("network_test"))
|
||||||
repo.NetworkTest(false)
|
repo.NetworkTest(false)
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@ func MainApp(configPath string) {
|
|||||||
config.GetApiTimeoutSecs(), // default api timeout = 60
|
config.GetApiTimeoutSecs(), // default api timeout = 60
|
||||||
false, // no need for ipv6 support
|
false, // no need for ipv6 support
|
||||||
[]string{}, // no optimal hosts needed
|
[]string{}, // no optimal hosts needed
|
||||||
config,
|
proxyURL,
|
||||||
log.Named("api_client"),
|
log.Named("api_client"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ func MainApp(configPath string) {
|
|||||||
config.GetDownloadTimeoutSecs(), // default download timeout = 10
|
config.GetDownloadTimeoutSecs(), // default download timeout = 10
|
||||||
false, // no need for ipv6 support
|
false, // no need for ipv6 support
|
||||||
[]string{}, // no optimal hosts needed
|
[]string{}, // no optimal hosts needed
|
||||||
config,
|
proxyURL,
|
||||||
log.Named("unrestrict_client"),
|
log.Named("unrestrict_client"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ func MainApp(configPath string) {
|
|||||||
config.GetDownloadTimeoutSecs(),
|
config.GetDownloadTimeoutSecs(),
|
||||||
config.ShouldForceIPv6(),
|
config.ShouldForceIPv6(),
|
||||||
hosts,
|
hosts,
|
||||||
config,
|
proxyURL,
|
||||||
log.Named("download_client"),
|
log.Named("download_client"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/debridmediamanager/zurg/internal/clear"
|
"github.com/debridmediamanager/zurg/internal/clear"
|
||||||
"github.com/debridmediamanager/zurg/internal/version"
|
"github.com/debridmediamanager/zurg/internal/version"
|
||||||
"github.com/debridmediamanager/zurg/pkg/realdebrid"
|
"github.com/debridmediamanager/zurg/pkg/http"
|
||||||
|
"github.com/debridmediamanager/zurg/pkg/logutil"
|
||||||
|
"github.com/debridmediamanager/zurg/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ShowVersion() {
|
func ShowVersion() {
|
||||||
@@ -16,8 +19,19 @@ func ShowVersion() {
|
|||||||
version.GetBuiltAt(), version.GetGitCommit(), version.GetVersion())
|
version.GetBuiltAt(), version.GetGitCommit(), version.GetVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
func NetworkTest(testType string) {
|
func NetworkTest() {
|
||||||
realdebrid.RunTest(testType)
|
utils.EnsureDirExists("logs")
|
||||||
|
utils.EnsureDirExists("data")
|
||||||
|
|
||||||
|
dateStr := time.Now().Format(time.DateOnly)
|
||||||
|
timeStr := strings.ReplaceAll(time.Now().Format(time.TimeOnly), ":", "-")
|
||||||
|
logPath := fmt.Sprintf("logs/network-test-%s-%s.log", dateStr, timeStr)
|
||||||
|
log := logutil.NewLogger(logPath)
|
||||||
|
|
||||||
|
repoClient4 := http.NewHTTPClient("", 0, 1, false, []string{}, os.Getenv("PROXY"), log.Named("network_test"))
|
||||||
|
repoClient6 := http.NewHTTPClient("", 0, 1, true, []string{}, os.Getenv("PROXY"), log.Named("network_test"))
|
||||||
|
repo := http.NewIPRepository(repoClient4, repoClient6, log.Named("network_test"))
|
||||||
|
repo.NetworkTest(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClearDownloads() {
|
func ClearDownloads() {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ type ConfigInterface interface {
|
|||||||
GetPort() string
|
GetPort() string
|
||||||
GetUsername() string
|
GetUsername() string
|
||||||
GetPassword() string
|
GetPassword() string
|
||||||
GetProxy() string
|
|
||||||
GetDirectories() []string
|
GetDirectories() []string
|
||||||
MeetsConditions(directory, torrentName string, torrentSize int64, torrentIDs, fileNames []string, fileSizes []int64, mediaInfos []*ffprobe.ProbeData) bool
|
MeetsConditions(directory, torrentName string, torrentSize int64, torrentIDs, fileNames []string, fileSizes []int64, mediaInfos []*ffprobe.ProbeData) bool
|
||||||
GetOnLibraryUpdate() string
|
GetOnLibraryUpdate() string
|
||||||
@@ -101,13 +100,6 @@ func (z *ZurgConfig) GetPassword() string {
|
|||||||
return z.Password
|
return z.Password
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *ZurgConfig) GetProxy() string {
|
|
||||||
if os.Getenv("PROXY") != "" {
|
|
||||||
return os.Getenv("PROXY")
|
|
||||||
}
|
|
||||||
return z.Proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
func (z *ZurgConfig) GetNumOfWorkers() int {
|
func (z *ZurgConfig) GetNumOfWorkers() int {
|
||||||
if z.NumOfWorkers == 0 {
|
if z.NumOfWorkers == 0 {
|
||||||
return 20
|
return 20
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/debridmediamanager/zurg/internal/config"
|
|
||||||
"github.com/debridmediamanager/zurg/pkg/logutil"
|
"github.com/debridmediamanager/zurg/pkg/logutil"
|
||||||
http_dialer "github.com/mwitkow/go-http-dialer"
|
http_dialer "github.com/mwitkow/go-http-dialer"
|
||||||
"golang.org/x/net/proxy"
|
"golang.org/x/net/proxy"
|
||||||
@@ -23,15 +22,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type HTTPClient struct {
|
type HTTPClient struct {
|
||||||
client *http.Client
|
client *http.Client
|
||||||
maxRetries int
|
maxRetries int
|
||||||
timeoutSecs int
|
timeoutSecs int
|
||||||
backoff func(attempt int) time.Duration
|
rateLimitSleepSecs int
|
||||||
bearerToken string
|
backoff func(attempt int) time.Duration
|
||||||
cfg config.ConfigInterface
|
bearerToken string
|
||||||
dnsCache cmap.ConcurrentMap[string, string]
|
dnsCache cmap.ConcurrentMap[string, string]
|
||||||
optimalHosts []string
|
optimalHosts []string
|
||||||
log *logutil.Logger
|
log *logutil.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiErrorResponse struct {
|
type ApiErrorResponse struct {
|
||||||
@@ -49,26 +48,26 @@ func NewHTTPClient(
|
|||||||
timeoutSecs int,
|
timeoutSecs int,
|
||||||
forceIPv6 bool,
|
forceIPv6 bool,
|
||||||
optimalHosts []string,
|
optimalHosts []string,
|
||||||
cfg config.ConfigInterface,
|
proxyURL string,
|
||||||
log *logutil.Logger,
|
log *logutil.Logger,
|
||||||
) *HTTPClient {
|
) *HTTPClient {
|
||||||
client := HTTPClient{
|
client := HTTPClient{
|
||||||
bearerToken: token,
|
bearerToken: token,
|
||||||
client: &http.Client{},
|
client: &http.Client{},
|
||||||
maxRetries: maxRetries,
|
maxRetries: maxRetries,
|
||||||
timeoutSecs: timeoutSecs,
|
timeoutSecs: timeoutSecs,
|
||||||
backoff: backoffFunc,
|
rateLimitSleepSecs: 4,
|
||||||
cfg: cfg,
|
backoff: backoffFunc,
|
||||||
dnsCache: cmap.New[string](),
|
dnsCache: cmap.New[string](),
|
||||||
optimalHosts: optimalHosts,
|
optimalHosts: optimalHosts,
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialer proxy.Dialer = &net.Dialer{
|
var dialer proxy.Dialer = &net.Dialer{
|
||||||
Timeout: time.Duration(timeoutSecs) * time.Second, // timeout for dns resolution, tcp handshake
|
Timeout: time.Duration(timeoutSecs) * time.Second, // timeout for dns resolution, tcp handshake
|
||||||
}
|
}
|
||||||
|
|
||||||
if proxyURLString := cfg.GetProxy(); proxyURLString != "" {
|
if proxyURLString := proxyURL; proxyURLString != "" {
|
||||||
proxyURL, err := url.Parse(proxyURLString)
|
proxyURL, err := url.Parse(proxyURLString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to parse proxy URL: %v", err)
|
log.Errorf("Failed to parse proxy URL: %v", err)
|
||||||
@@ -81,15 +80,10 @@ func NewHTTPClient(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
maxConnections := cfg.GetNumOfWorkers()
|
|
||||||
if maxConnections > 32 {
|
|
||||||
maxConnections = 32 // real-debrid has a limit of 32 connections per server/host
|
|
||||||
}
|
|
||||||
|
|
||||||
client.client.Transport = &http.Transport{
|
client.client.Transport = &http.Transport{
|
||||||
ResponseHeaderTimeout: time.Duration(timeoutSecs) * time.Second,
|
ResponseHeaderTimeout: time.Duration(timeoutSecs) * time.Second,
|
||||||
MaxIdleConns: 0,
|
MaxIdleConns: 0,
|
||||||
MaxConnsPerHost: maxConnections,
|
MaxConnsPerHost: 32,
|
||||||
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
return dialer.Dial(network, address)
|
return dialer.Dial(network, address)
|
||||||
},
|
},
|
||||||
@@ -168,7 +162,7 @@ func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
incr := r.shouldRetry(req, resp, err, r.cfg.GetRateLimitSleepSecs())
|
incr := r.shouldRetry(req, resp, err, r.rateLimitSleepSecs)
|
||||||
if incr > 0 {
|
if incr > 0 {
|
||||||
attempt += incr
|
attempt += incr
|
||||||
if attempt > r.maxRetries {
|
if attempt > r.maxRetries {
|
||||||
|
|||||||
@@ -53,12 +53,15 @@ func (r *IPRepository) NetworkTest(forceRun bool) {
|
|||||||
}
|
}
|
||||||
if ipv4Loaded && ipv6Loaded {
|
if ipv4Loaded && ipv6Loaded {
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
r.log.Warn("Network test files not found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.log.Info("Network test will start now (this will only run once). IGNORE THE WARNINGS!")
|
r.log.Info("Network test will start now. IGNORE THE WARNINGS!")
|
||||||
r.runLatencyTest()
|
r.runLatencyTest()
|
||||||
r.log.Infof("Network test completed. Saving the results to %s and %s", ipv4latencyFile, ipv6latencyFile)
|
r.log.Info("Network test completed!")
|
||||||
|
r.log.Infof("To rerun the network test, run 'zurg network-test', or delete the files %s and %s and run zurg again", ipv4latencyFile, ipv6latencyFile)
|
||||||
r.writeLatencyFile(ipv4latencyFile, r.ipv4latencyMap)
|
r.writeLatencyFile(ipv4latencyFile, r.ipv4latencyMap)
|
||||||
r.writeLatencyFile(ipv6latencyFile, r.ipv6latencyMap)
|
r.writeLatencyFile(ipv6latencyFile, r.ipv6latencyMap)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user