From 30c5ffbb759f5407b062bf0b95ba7e33bbeb716d Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 9 Mar 2020 15:30:30 +0800 Subject: [PATCH 01/69] Add instruction for installing from AUR --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a28a594..9b61194 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,21 @@ can now proceed to build `librespeed-cli` with the build script: ## Install from AUR/Homebrew -TODO +To install `librespeed-cli` from AUR, use your favorite AUR helper and install package `librespeed-cli-bin` + +```shell script +$ yay librespeed-cli-bin +``` + +... or, clone it and build it yourself: + +```shell script +$ git clone https://aur.archlinux.org/librespeed-cli-bin.git +$ cd librespeed-cli-bin +$ makepkg -si +``` + +TODO: Homebrew ## Usage From 5866efba705dfa37119b2ec2a45982f133198a8c Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 11 Mar 2020 11:55:36 +0800 Subject: [PATCH 02/69] Add force IPv4/IPv6 option --- defs/options.go | 4 ++ defs/server.go | 10 +++-- go.mod | 3 +- go.sum | 15 ++++++-- main.go | 10 +++++ speedtest/helper.go | 4 +- speedtest/speedtest.go | 86 +++++++++++++++++++++++++++++++----------- 7 files changed, 99 insertions(+), 33 deletions(-) diff --git a/defs/options.go b/defs/options.go index f637490..aee4ce3 100644 --- a/defs/options.go +++ b/defs/options.go @@ -2,6 +2,10 @@ package defs const ( OptionHelp = "help" + OptionIPv4 = "ipv4" + OptionIPv4Alt = "4" + OptionIPv6 = "ipv6" + OptionIPv6Alt = "6" OptionNoDownload = "no-download" OptionNoUpload = "no-upload" OptionBytes = "bytes" diff --git a/defs/server.go b/defs/server.go index 48f54d5..502b33e 100644 --- a/defs/server.go +++ b/defs/server.go @@ -43,6 +43,7 @@ func (s *Server) IsUp() bool { u.Path = path.Join(u.Path, s.PingURL) resp, err := http.Get(u.String()) if err != nil { + log.Debugf("Error checking for server status: %s", err) return false } defer resp.Body.Close() @@ -52,7 +53,7 @@ func (s *Server) IsUp() bool { } // ICMPPingAndJitter pings the server via ICMP echos and calculate the average ping and jitter -func (s *Server) ICMPPingAndJitter(count int, srcIp string) (float64, float64, error) { +func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, float64, error) { t := time.Now() defer func() { s.TLog.Logf("ICMP ping took %s", time.Now().Sub(t).String()) @@ -68,7 +69,8 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp string) (float64, float64, e log.Debugf("Failed to get server URL: %s", err) return 0, 0, err } - p, err := ping.NewPinger(u.Hostname()) + + p, err := ping.NewPinger(u.Hostname(), network) if err != nil { log.Debugf("Failed to initialize pinger: %s", err) return 0, 0, err @@ -214,7 +216,7 @@ func (s *Server) Download(silent bool, useBytes bool) (float64, int, error) { defer resp.Body.Close() if _, err = io.Copy(ioutil.Discard, io.TeeReader(resp.Body, counter)); err != nil { - if !errors.Is(err, context.Canceled) { + if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) { log.Debugf("Failed when reading HTTP response: %s", err) } } @@ -299,7 +301,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes bool) (float64, int, error) doUpload := func() { resp, err := http.DefaultClient.Do(req) - if err != nil && !errors.Is(err, context.Canceled) { + if err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) { log.Debugf("Failed when making HTTP request: %s", err) } else if err == nil { defer resp.Body.Close() diff --git a/go.mod b/go.mod index 373c368..d4335e6 100644 --- a/go.mod +++ b/go.mod @@ -2,14 +2,13 @@ module librespeed-cli go 1.14 -replace github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c => github.com/maddie/go-ping v0.0.0-20200305135031-f8c069280206 +replace github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c => github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6 require ( github.com/briandowns/spinner v1.9.0 github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 github.com/sirupsen/logrus v1.4.2 github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c - github.com/stretchr/testify v1.3.0 // indirect github.com/urfave/cli/v2 v2.1.1 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect ) diff --git a/go.sum b/go.sum index f9439a2..0d35579 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 h1:rRQm5os6ffGTukb4 github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/maddie/go-ping v0.0.0-20200305135031-f8c069280206 h1:wcRUWd5aN1arYHnxsAXx56VEV9RKQxVay24fKBv0s8M= -github.com/maddie/go-ping v0.0.0-20200305135031-f8c069280206/go.mod h1:IYhVIzcOSIO1fLDdEz4JFidYhLPmmW3dchKuengmL9s= +github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6 h1:ApVK0ZXs0wyZmj4dSelnorxkJguUhVLXxT+ghrXtNQY= +github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6/go.mod h1:IYhVIzcOSIO1fLDdEz4JFidYhLPmmW3dchKuengmL9s= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= @@ -26,8 +26,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c h1:gqEdF4VwBu3lTKGHS9rXE9x1/pEaSwCXRLOZRF6qtlw= -github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c/go.mod h1:eMyUVp6f/5jnzM+3zahzl7q6UXLbgSc3MKg/+ow9QW0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -36,13 +34,22 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go index cc93ab7..f66d292 100644 --- a/main.go +++ b/main.go @@ -37,6 +37,16 @@ func main() { Name: defs.OptionVersion, Usage: "Show the version number and exit", }, + &cli.BoolFlag{ + Name: defs.OptionIPv4, + Aliases: []string{defs.OptionIPv4Alt}, + Usage: "Force IPv4 only", + }, + &cli.BoolFlag{ + Name: defs.OptionIPv6, + Aliases: []string{defs.OptionIPv6Alt}, + Usage: "Force IPv6 only", + }, &cli.BoolFlag{ Name: defs.OptionNoDownload, Usage: "Do not perform download test", diff --git a/speedtest/helper.go b/speedtest/helper.go index 951518b..825195f 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -27,7 +27,7 @@ const ( ) // doSpeedTest is where the actual speed test happens -func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.TelemetryServer, silent bool) error { +func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.TelemetryServer, network string, silent bool) error { if serverCount := len(servers); serverCount > 1 { log.Infof("Testing against %d servers", serverCount) } @@ -61,7 +61,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel pb.Start() } - p, jitter, err := currentServer.ICMPPingAndJitter(pingCount, c.String(defs.OptionSource)) + p, jitter, err := currentServer.ICMPPingAndJitter(pingCount, c.String(defs.OptionSource), network) if err != nil { log.Errorf("Failed to get ping and jitter: %s", err) return err diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index a9eba6e..fac24c1 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -1,11 +1,13 @@ package speedtest import ( + "context" "encoding/json" "errors" "io/ioutil" "net" "net/http" + "strings" "sync" "time" @@ -124,28 +126,70 @@ func SpeedTest(c *cli.Context) error { // HTTP requests timeout http.DefaultClient.Timeout = time.Duration(c.Int(defs.OptionTimeout)) * time.Second - // bind to source IP address if given - if src := c.String(defs.OptionSource); src != "" { - // first we parse the IP to see if it's valid - localAddr, err := net.ResolveIPAddr("ip", src) - if err != nil { - log.Errorf("Error parsing source IP: %s", err) - return err + forceIPv4 := c.Bool(defs.OptionIPv4) + forceIPv6 := c.Bool(defs.OptionIPv6) + + var network string + switch { + case forceIPv4: + network = "ip4" + case forceIPv6: + network = "ip6" + default: + network = "ip" + } + + // bind to source IP address if given, or if ipv4/ipv6 is forced + if src := c.String(defs.OptionSource); src != "" || (forceIPv4 || forceIPv6) { + var localTCPAddr *net.TCPAddr + if src != "" { + // first we parse the IP to see if it's valid + addr, err := net.ResolveIPAddr(network, src) + if err != nil { + if strings.Contains(err.Error(), "no suitable address") { + if forceIPv6 { + log.Errorf("Address %s is not a valid IPv6 address", src) + } else { + log.Errorf("Address %s is not a valid IPv4 address", src) + } + } else { + log.Errorf("Error parsing source IP: %s", err) + } + return err + } + + log.Debugf("Using %s as source IP", src) + localTCPAddr = &net.TCPAddr{IP: addr.IP} } - localTCPAddr := net.TCPAddr{IP: localAddr.IP} + var dialContext func(context.Context, string, string) (net.Conn, error) + defaultDialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + } + + if localTCPAddr != nil { + defaultDialer.LocalAddr = localTCPAddr + } + + switch { + case forceIPv4: + dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { + return defaultDialer.DialContext(ctx, "tcp4", address) + } + case forceIPv6: + dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { + return defaultDialer.DialContext(ctx, "tcp6", address) + } + default: + dialContext = defaultDialer.DialContext + } // set default HTTP client's Transport to the one that binds the source address // this is modified from http.DefaultTransport transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - LocalAddr: &localTCPAddr, - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - // although this option is marked deprecated, but it's still used in http.DefaultTransport, keeping as-is - DualStack: true, - }).DialContext, + Proxy: http.ProxyFromEnvironment, + DialContext: dialContext, ForceAttemptHTTP2: true, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, @@ -188,7 +232,7 @@ func SpeedTest(c *cli.Context) error { // if --server is given, do speed tests with all of them if len(c.IntSlice(defs.OptionServer)) > 0 { - return doSpeedTest(c, servers, telemetryServer, silent) + return doSpeedTest(c, servers, telemetryServer, network, silent) } else { // else select the fastest server from the list log.Info("Selecting the fastest server based on ping") @@ -202,7 +246,7 @@ func SpeedTest(c *cli.Context) error { // spawn 10 concurrent pingers for i := 0; i < 10; i++ { - go pingWorker(jobs, results, &wg, c.String(defs.OptionSource)) + go pingWorker(jobs, results, &wg, c.String(defs.OptionSource), network) } // send ping jobs to workers @@ -239,11 +283,11 @@ func SpeedTest(c *cli.Context) error { } // do speed test on the server - return doSpeedTest(c, []defs.Server{servers[serverIdx]}, telemetryServer, silent) + return doSpeedTest(c, []defs.Server{servers[serverIdx]}, telemetryServer, network, silent) } } -func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGroup, srcIp string) { +func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGroup, srcIp, network string) { for { job := <-jobs server := job.Server @@ -258,7 +302,7 @@ func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGro // check the server is up by accessing the ping URL and checking its returned value == empty and status code == 200 if server.IsUp() { // if server is up, get ping - ping, _, err := server.ICMPPingAndJitter(1, srcIp) + ping, _, err := server.ICMPPingAndJitter(1, srcIp, network) if err != nil { log.Debugf("Can't ping server %s (%s), skipping", server.Name, u.Hostname()) wg.Done() From a4afee365f252f6ee520a83afbb8b15462706510 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 11 Mar 2020 12:48:06 +0800 Subject: [PATCH 03/69] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b61194..2714b29 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,8 @@ USAGE: GLOBAL OPTIONS: --help, -h show help (default: false) --version Show the version number and exit (default: false) + --ipv4, -4 Force IPv4 only (default: false) + --ipv6, -6 Force IPv6 only (default: false) --no-download Do not perform download test (default: false) --no-upload Do not perform upload test (default: false) --bytes Display values in bytes instead of bits. Does not affect From 8cafe323bc63005d59c8de8f292c2fb1e5117b01 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 11 Mar 2020 15:11:32 +0800 Subject: [PATCH 04/69] Update dependencies --- go.mod | 1 + go.sum | 9 --------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/go.mod b/go.mod index d4335e6..fc73bc4 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 github.com/sirupsen/logrus v1.4.2 github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c + github.com/stretchr/testify v1.3.0 // indirect github.com/urfave/cli/v2 v2.1.1 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect ) diff --git a/go.sum b/go.sum index 0d35579..be26162 100644 --- a/go.sum +++ b/go.sum @@ -34,22 +34,13 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c h1:IGkKhmfzcztjm6gYkykvu/NiS8kaqbCWAEWWAyf8J5U= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 9df434e8f25f8a8f747175dd1e2541bef07f9146 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 11 Mar 2020 15:50:05 +0800 Subject: [PATCH 05/69] Add instruction for installing from Homebrew --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2714b29..d869679 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ can now proceed to build `librespeed-cli` with the build script: 5. Now you can use the `librespeed-cli` and test your Internet speed! -## Install from AUR/Homebrew +## Install from AUR To install `librespeed-cli` from AUR, use your favorite AUR helper and install package `librespeed-cli-bin` @@ -85,7 +85,9 @@ $ cd librespeed-cli-bin $ makepkg -si ``` -TODO: Homebrew +## Install from Homebrew + +See the [librespeed-cli Homebrew tap](https://github.com/librespeed/homebrew-tap#setup). ## Usage From d5d4fb3389fe4ea2c76f94262ffc757a58cda4d4 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 13 Mar 2020 10:26:21 +0800 Subject: [PATCH 06/69] Add option `--mebibytes` Fixes #1 --- defs/bytes_counter.go | 31 +++++++++++++++++++++++-------- defs/options.go | 1 + defs/server.go | 18 ++++++++++-------- main.go | 4 ++++ speedtest/helper.go | 22 ++++++++++++++-------- 5 files changed, 52 insertions(+), 24 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 9894d1b..84cf31d 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -15,6 +15,7 @@ type BytesCounter struct { total int payload []byte reader io.ReadSeeker + mebi bool } // Write implements io.Writer @@ -33,26 +34,40 @@ func (c *BytesCounter) Read(p []byte) (int, error) { return n, err } +// SetBase sets the base for dividing bytes into megabyte or mebibyte +func (c *BytesCounter) SetMebi(mebi bool) { + c.mebi = mebi +} + // Average returns the average bytes/second func (c *BytesCounter) Average() float64 { return float64(c.total) / time.Now().Sub(c.start).Seconds() } -func (c *BytesCounter) AvgMbits() string { - return fmt.Sprintf("%.02f Mbps", c.Average()/131072) +func (c *BytesCounter) AvgMbps() float64 { + var base float64 = 100000 + if c.mebi { + base = 131072 + } + return c.Average() / base } func (c *BytesCounter) AvgHumanize() string { val := c.Average() - if val < 1024 { + var base float64 = 1000 + if c.mebi { + base = 1024 + } + + if val < base { return fmt.Sprintf("%.2f bytes/s", val) - } else if val/1024 < 1024 { - return fmt.Sprintf("%.2f KB/s", val/1024) - } else if val/1024/1024 < 1024 { - return fmt.Sprintf("%.2f MB/s", val/1024/1024) + } else if val/base < base { + return fmt.Sprintf("%.2f KB/s", val/base) + } else if val/base/base < base { + return fmt.Sprintf("%.2f MB/s", val/base/base) } else { - return fmt.Sprintf("%.2f GB/s", val/1024/1024/1024) + return fmt.Sprintf("%.2f GB/s", val/base/base/base) } } diff --git a/defs/options.go b/defs/options.go index aee4ce3..263339a 100644 --- a/defs/options.go +++ b/defs/options.go @@ -9,6 +9,7 @@ const ( OptionNoDownload = "no-download" OptionNoUpload = "no-upload" OptionBytes = "bytes" + OptionMebiBytes = "mebibytes" OptionDistance = "distance" OptionShare = "share" OptionSimple = "simple" diff --git a/defs/server.go b/defs/server.go index 502b33e..5197e27 100644 --- a/defs/server.go +++ b/defs/server.go @@ -177,13 +177,14 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } // Download performs the actual download test -func (s *Server) Download(silent bool, useBytes bool) (float64, int, error) { +func (s *Server) Download(silent bool, useBytes, useMebi bool) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Download took %s", time.Now().Sub(t).String()) }() counter := &BytesCounter{} + counter.SetMebi(useMebi) ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -233,7 +234,7 @@ func (s *Server) Download(silent bool, useBytes bool) (float64, int, error) { if useBytes { s.Suffix = fmt.Sprintf(" %s", counter.AvgHumanize()) } else { - s.Suffix = fmt.Sprintf(" %s", counter.AvgMbits()) + s.Suffix = fmt.Sprintf(" %.2f Mbps", counter.AvgMbps()) } } @@ -242,7 +243,7 @@ func (s *Server) Download(silent bool, useBytes bool) (float64, int, error) { if useBytes { pb.FinalMSG = fmt.Sprintf("Download rate:\t%s\n", counter.AvgHumanize()) } else { - pb.FinalMSG = fmt.Sprintf("Download rate:\t%s\n", counter.AvgMbits()) + pb.FinalMSG = fmt.Sprintf("Download rate:\t%.2f Mbps\n", counter.AvgMbps()) } pb.Stop() }() @@ -261,17 +262,18 @@ Loop: } } - return counter.Average() / 131072, counter.Total(), nil + return counter.AvgMbps(), counter.Total(), nil } // Upload performs the actual upload test -func (s *Server) Upload(noPrealloc, silent, useBytes bool) (float64, int, error) { +func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Upload took %s", time.Now().Sub(t).String()) }() counter := &BytesCounter{} + counter.SetMebi(useMebi) if noPrealloc { log.Info("Pre-allocation is disabled, performance might be lower!") @@ -322,7 +324,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes bool) (float64, int, error) if useBytes { s.Suffix = fmt.Sprintf(" %s", counter.AvgHumanize()) } else { - s.Suffix = fmt.Sprintf(" %s", counter.AvgMbits()) + s.Suffix = fmt.Sprintf(" %.2f Mbps", counter.AvgMbps()) } } @@ -331,7 +333,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes bool) (float64, int, error) if useBytes { pb.FinalMSG = fmt.Sprintf("Upload rate:\t%s\n", counter.AvgHumanize()) } else { - pb.FinalMSG = fmt.Sprintf("Upload rate:\t%s\n", counter.AvgMbits()) + pb.FinalMSG = fmt.Sprintf("Upload rate:\t%.2f Mbps\n", counter.AvgMbps()) } pb.Stop() }() @@ -350,7 +352,7 @@ Loop: } } - return counter.Average() / 131072, counter.Total(), nil + return counter.AvgMbps(), counter.Total(), nil } // GetIPInfo accesses the backend's getIP.php endpoint and get current client's IP information diff --git a/main.go b/main.go index f66d292..8de019c 100644 --- a/main.go +++ b/main.go @@ -61,6 +61,10 @@ func main() { "\tthe image generated by --share, nor output from\n" + "\t--json or --csv", }, + &cli.BoolFlag{ + Name: defs.OptionMebiBytes, + Usage: "Use 1024 bytes as 1 kilobyte instead of 1000", + }, &cli.StringFlag{ Name: defs.OptionDistance, Usage: "Change distance unit shown in ISP info, use 'mi' for miles,\n" + diff --git a/speedtest/helper.go b/speedtest/helper.go index 825195f..f356213 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -78,7 +78,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoDownload) { log.Info("Download test is disabled") } else { - download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes)) + download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes)) if err != nil { log.Errorf("Failed to get download speed: %s", err) return err @@ -93,7 +93,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoUpload) { log.Info("Upload test is disabled") } else { - upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes)) + upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes)) if err != nil { log.Errorf("Failed to get upload speed: %s", err) return err @@ -105,7 +105,8 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel // print result if --simple is given if c.Bool(defs.OptionSimple) { if c.Bool(defs.OptionBytes) { - log.Warnf("Ping:\t%.0f ms\tJitter:\t%.0f ms\nDownload rate:\t%s\nUpload rate:\t%s", p, jitter, humanizeMbps(downloadValue), humanizeMbps(uploadValue)) + useMebi := c.Bool(defs.OptionMebiBytes) + log.Warnf("Ping:\t%.0f ms\tJitter:\t%.0f ms\nDownload rate:\t%s\nUpload rate:\t%s", p, jitter, humanizeMbps(downloadValue, useMebi), humanizeMbps(uploadValue, useMebi)) } else { log.Warnf("Ping:\t%.0f ms\tJitter:\t%.0f ms\nDownload rate:\t%.2f Mbps\nUpload rate:\t%.2f Mbps", p, jitter, downloadValue, uploadValue) } @@ -299,16 +300,21 @@ func sendTelemetry(telemetryServer defs.TelemetryServer, ispInfo *defs.GetIPResu } } -func humanizeMbps(mbps float64) string { +func humanizeMbps(mbps float64, useMebi bool) string { val := mbps / 8 + var base float64 = 1000 + if useMebi { + base = 1024 + } + if val < 1 { - if kb := val * 1024; kb < 1 { - return fmt.Sprintf("%.2f bytes/s", kb*1024) + if kb := val * base; kb < 1 { + return fmt.Sprintf("%.2f bytes/s", kb*base) } else { return fmt.Sprintf("%.2f KB/s", kb) } - } else if val > 1024 { - return fmt.Sprintf("%.2f GB/s", val/1024) + } else if val > base { + return fmt.Sprintf("%.2f GB/s", val/base) } else { return fmt.Sprintf("%.2f MB/s", val) } From 55bc44329f147039806f26e791a84da540b76e82 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 13 Mar 2020 10:51:43 +0800 Subject: [PATCH 07/69] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d869679..4ee88f9 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ GLOBAL OPTIONS: --bytes Display values in bytes instead of bits. Does not affect the image generated by --share, nor output from --json or --csv (default: false) + --mebibytes Use 1024 bytes as 1 kilobyte instead of 1000 (default: false) --distance value Change distance unit shown in ISP info, use 'mi' for miles, 'km' for kilometres, 'NM' for nautical miles (default: "km") --share Generate and provide a URL to the LibreSpeed.org share results From 799afff0158149f1ed9fac5b0b6e216b65c0452d Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 13 Mar 2020 18:16:34 +0800 Subject: [PATCH 08/69] Fix mbps calculation --- defs/bytes_counter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 84cf31d..09c815b 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -45,7 +45,7 @@ func (c *BytesCounter) Average() float64 { } func (c *BytesCounter) AvgMbps() float64 { - var base float64 = 100000 + var base float64 = 125000 if c.mebi { base = 131072 } From eafdee6d3180d7ec32ea8a65a13975867aae66fd Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 17 Mar 2020 17:45:34 +0800 Subject: [PATCH 09/69] Add --concurrent option and support concurrent requests --- defs/bytes_counter.go | 21 +++++++++++++++++---- defs/options.go | 1 + defs/server.go | 22 ++++++++++++++-------- main.go | 5 +++++ speedtest/helper.go | 4 ++-- speedtest/speedtest.go | 5 +++++ 6 files changed, 44 insertions(+), 14 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 09c815b..93c92cf 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log" + "sync" "time" ) @@ -16,12 +17,22 @@ type BytesCounter struct { payload []byte reader io.ReadSeeker mebi bool + + lock *sync.Mutex +} + +func NewCounter() *BytesCounter { + return &BytesCounter{ + lock: &sync.Mutex{}, + } } // Write implements io.Writer func (c *BytesCounter) Write(p []byte) (int, error) { n := len(p) + c.lock.Lock() c.total += n + c.lock.Unlock() return n, nil } @@ -29,7 +40,9 @@ func (c *BytesCounter) Write(p []byte) (int, error) { // Read implements io.Reader func (c *BytesCounter) Read(p []byte) (int, error) { n, err := c.reader.Read(p) + c.lock.Lock() c.total += n + c.lock.Unlock() return n, err } @@ -39,8 +52,8 @@ func (c *BytesCounter) SetMebi(mebi bool) { c.mebi = mebi } -// Average returns the average bytes/second -func (c *BytesCounter) Average() float64 { +// AvgBytes returns the average bytes/second +func (c *BytesCounter) AvgBytes() float64 { return float64(c.total) / time.Now().Sub(c.start).Seconds() } @@ -49,11 +62,11 @@ func (c *BytesCounter) AvgMbps() float64 { if c.mebi { base = 131072 } - return c.Average() / base + return c.AvgBytes() / base } func (c *BytesCounter) AvgHumanize() string { - val := c.Average() + val := c.AvgBytes() var base float64 = 1000 if c.mebi { diff --git a/defs/options.go b/defs/options.go index 263339a..6e1a29f 100644 --- a/defs/options.go +++ b/defs/options.go @@ -8,6 +8,7 @@ const ( OptionIPv6Alt = "6" OptionNoDownload = "no-download" OptionNoUpload = "no-upload" + OptionConcurrent = "concurrent" OptionBytes = "bytes" OptionMebiBytes = "mebibytes" OptionDistance = "distance" diff --git a/defs/server.go b/defs/server.go index 5197e27..f2de6b7 100644 --- a/defs/server.go +++ b/defs/server.go @@ -177,13 +177,13 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } // Download performs the actual download test -func (s *Server) Download(silent bool, useBytes, useMebi bool) (float64, int, error) { +func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Download took %s", time.Now().Sub(t).String()) }() - counter := &BytesCounter{} + counter := NewCounter() counter.SetMebi(useMebi) ctx, cancel := context.WithCancel(context.Background()) @@ -207,7 +207,7 @@ func (s *Server) Download(silent bool, useBytes, useMebi bool) (float64, int, er req.Header.Set("User-Agent", UserAgent) req.Header.Set("Accept-Encoding", "identity") - downloadDone := make(chan struct{}) + downloadDone := make(chan struct{}, requests) doDownload := func() { resp, err := http.DefaultClient.Do(req) @@ -249,7 +249,10 @@ func (s *Server) Download(silent bool, useBytes, useMebi bool) (float64, int, er }() } - go doDownload() + for i := 0; i < requests; i++ { + go doDownload() + time.Sleep(200 * time.Millisecond) + } timeout := time.After(15 * time.Second) Loop: for { @@ -266,13 +269,13 @@ Loop: } // Upload performs the actual upload test -func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool) (float64, int, error) { +func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Upload took %s", time.Now().Sub(t).String()) }() - counter := &BytesCounter{} + counter := NewCounter() counter.SetMebi(useMebi) if noPrealloc { @@ -299,7 +302,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool) (float64, in req.Header.Set("User-Agent", UserAgent) req.Header.Set("Accept-Encoding", "identity") - uploadDone := make(chan struct{}) + uploadDone := make(chan struct{}, requests) doUpload := func() { resp, err := http.DefaultClient.Do(req) @@ -339,7 +342,10 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool) (float64, in }() } - go doUpload() + for i := 0; i < requests; i++ { + go doUpload() + time.Sleep(200 * time.Millisecond) + } timeout := time.After(15 * time.Second) Loop: for { diff --git a/main.go b/main.go index 8de019c..2642372 100644 --- a/main.go +++ b/main.go @@ -55,6 +55,11 @@ func main() { Name: defs.OptionNoUpload, Usage: "Do not perform upload test", }, + &cli.IntFlag{ + Name: defs.OptionConcurrent, + Usage: "Concurrent HTTP requests being made", + Value: 3, + }, &cli.BoolFlag{ Name: defs.OptionBytes, Usage: "Display values in bytes instead of bits. Does not affect\n" + diff --git a/speedtest/helper.go b/speedtest/helper.go index f356213..a940aca 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -78,7 +78,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoDownload) { log.Info("Download test is disabled") } else { - download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes)) + download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent)) if err != nil { log.Errorf("Failed to get download speed: %s", err) return err @@ -93,7 +93,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoUpload) { log.Info("Upload test is disabled") } else { - upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes)) + upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent)) if err != nil { log.Errorf("Failed to get upload speed: %s", err) return err diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index fac24c1..d2316e7 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -123,6 +123,11 @@ func SpeedTest(c *cli.Context) error { } } + if req := c.Int(defs.OptionConcurrent); req <= 0 { + log.Errorf("Concurrent requests cannot be lower than 1: %d is given", req) + return errors.New("invalid concurrent requests setting") + } + // HTTP requests timeout http.DefaultClient.Timeout = time.Duration(c.Int(defs.OptionTimeout)) * time.Second From 6b0fcc5acc69b6e12e51a29b1f30892259acdbef Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 17 Mar 2020 21:22:49 +0800 Subject: [PATCH 10/69] Correctly reset upload reader --- defs/bytes_counter.go | 9 +++++++-- defs/server.go | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 93c92cf..18c4650 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "log" + "math" "sync" "time" ) @@ -42,6 +43,10 @@ func (c *BytesCounter) Read(p []byte) (int, error) { n, err := c.reader.Read(p) c.lock.Lock() c.total += n + + if math.Mod(float64(c.total), uploadSize) == 0 { + c.resetReader() + } c.lock.Unlock() return n, err @@ -91,8 +96,8 @@ func (c *BytesCounter) GenerateBlob() { c.reader = bytes.NewReader(c.payload) } -// ResetReader resets the `reader` field to 0 position -func (c *BytesCounter) ResetReader() (int64, error) { +// resetReader resets the `reader` field to 0 position +func (c *BytesCounter) resetReader() (int64, error) { return c.reader.Seek(0, 0) } diff --git a/defs/server.go b/defs/server.go index f2de6b7..766b923 100644 --- a/defs/server.go +++ b/defs/server.go @@ -314,7 +314,6 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int log.Debugf("Failed when reading HTTP response: %s", err) } - counter.ResetReader() uploadDone <- struct{}{} } } From 5bb81358cf5e71b1eaf215ce162dba8cc1422752 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 17 Mar 2020 21:31:41 +0800 Subject: [PATCH 11/69] Use a variable to track current reader position ... instead of using `math.Mod` --- defs/bytes_counter.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 18c4650..f2e0a11 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -6,7 +6,6 @@ import ( "fmt" "io" "log" - "math" "sync" "time" ) @@ -14,6 +13,7 @@ import ( // BytesCounter implements io.Reader and io.Writer interface, for counting bytes being read/written in HTTP requests type BytesCounter struct { start time.Time + pos int total int payload []byte reader io.ReadSeeker @@ -43,8 +43,9 @@ func (c *BytesCounter) Read(p []byte) (int, error) { n, err := c.reader.Read(p) c.lock.Lock() c.total += n - - if math.Mod(float64(c.total), uploadSize) == 0 { + c.pos += n + if c.pos == uploadSize { + c.pos = 0 c.resetReader() } c.lock.Unlock() From e61ed2ce5a1739dcdad6c1ec44a5e65da69ed7fe Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 18 Mar 2020 21:23:23 +0800 Subject: [PATCH 12/69] Enable telemetry when any telemetry option is given --- speedtest/helper.go | 2 +- speedtest/speedtest.go | 39 ++++++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/speedtest/helper.go b/speedtest/helper.go index a940aca..6ac7bd1 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -114,7 +114,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel // print share link if --share is given var shareLink string - if c.Bool(defs.OptionShare) && !c.Bool(defs.OptionCSV) && telemetryServer.GetLevel() > 0 { + if !c.Bool(defs.OptionCSV) && telemetryServer.GetLevel() > 0 { var extra defs.TelemetryExtra extra.ServerName = currentServer.Name extra.Extra = c.String(defs.OptionTelemetryExtra) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index d2316e7..31b0fda 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -26,7 +26,7 @@ const ( defaultTelemetryLevel = "basic" defaultTelemetryServer = "https://librespeed.org" defaultTelemetryPath = "/results/telemetry.php" - defaultTeleemtryShare = "/results/" + defaultTelemetryShare = "/results/" ) type PingJob struct { @@ -80,13 +80,18 @@ func SpeedTest(c *cli.Context) error { return nil } - // read telemetry settings if --share is given + // read telemetry settings if --share or any --telemetry option is given var telemetryServer defs.TelemetryServer - if c.Bool(defs.OptionShare) { - if filename := c.String(defs.OptionTelemetryJSON); filename != "" { - b, err := ioutil.ReadFile(filename) + telemetryJSON := c.String(defs.OptionTelemetryJSON) + telemetryLevel := c.String(defs.OptionTelemetryLevel) + telemetryServerString := c.String(defs.OptionTelemetryServer) + telemetryPath := c.String(defs.OptionTelemetryPath) + telemetryShare := c.String(defs.OptionTelemetryShare) + if c.Bool(defs.OptionShare) || telemetryJSON != "" || telemetryLevel != "" || telemetryServerString != "" || telemetryPath != "" || telemetryShare != "" { + if telemetryJSON != "" { + b, err := ioutil.ReadFile(telemetryJSON) if err != nil { - log.Errorf("Cannot read %s: %s", filename, err) + log.Errorf("Cannot read %s: %s", telemetryJSON, err) return err } if err := json.Unmarshal(b, &telemetryServer); err != nil { @@ -95,31 +100,31 @@ func SpeedTest(c *cli.Context) error { } } - if str := c.String(defs.OptionTelemetryLevel); str != "" { - if str != "disabled" && str != "basic" && str != "full" && str != "debug" { - log.Fatalf("Unsupported telemetry level: %s", str) + if telemetryLevel != "" { + if telemetryLevel != "disabled" && telemetryLevel != "basic" && telemetryLevel != "full" && telemetryLevel != "debug" { + log.Fatalf("Unsupported telemetry level: %s", telemetryLevel) } - telemetryServer.Level = str + telemetryServer.Level = telemetryLevel } else if telemetryServer.Level == "" { telemetryServer.Level = defaultTelemetryLevel } - if str := c.String(defs.OptionTelemetryServer); str != "" { - telemetryServer.Server = str + if telemetryServerString != "" { + telemetryServer.Server = telemetryServerString } else if telemetryServer.Server == "" { telemetryServer.Server = defaultTelemetryServer } - if str := c.String(defs.OptionTelemetryPath); str != "" { - telemetryServer.Path = str + if telemetryPath != "" { + telemetryServer.Path = telemetryPath } else if telemetryServer.Path == "" { telemetryServer.Path = defaultTelemetryPath } - if str := c.String(defs.OptionTelemetryShare); str != "" { - telemetryServer.Share = str + if telemetryShare != "" { + telemetryServer.Share = telemetryShare } else if telemetryServer.Share == "" { - telemetryServer.Share = defaultTeleemtryShare + telemetryServer.Share = defaultTelemetryShare } } From c250a39a15f6170e6f713bd6283f9de6a19dd91c Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 18 Mar 2020 22:39:38 +0800 Subject: [PATCH 13/69] Update options descriptions --- main.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 2642372..f2512ca 100644 --- a/main.go +++ b/main.go @@ -159,28 +159,29 @@ func main() { Name: defs.OptionTelemetryJSON, Usage: "Load telemetry server settings from a JSON file. This\n" + "\toptions overrides --" + defs.OptionTelemetryLevel + ", --" + defs.OptionTelemetryServer + ",\n" + - "\t--" + defs.OptionTelemetryPath + ", and --" + defs.OptionTelemetryShare, + "\t--" + defs.OptionTelemetryPath + ", and --" + defs.OptionTelemetryShare + ". Implies --" + defs.OptionShare, }, &cli.StringFlag{ Name: defs.OptionTelemetryLevel, Usage: "Set telemetry data verbosity, available values are:\n" + - "\tdisabled, basic, full, debug", + "\tdisabled, basic, full, debug. Implies --" + defs.OptionShare, }, &cli.StringFlag{ Name: defs.OptionTelemetryServer, - Usage: "Set the telemetry server base URL", + Usage: "Set the telemetry server base URL. Implies --" + defs.OptionShare, }, &cli.StringFlag{ Name: defs.OptionTelemetryPath, - Usage: "Set the telemetry upload path", + Usage: "Set the telemetry upload path. Implies --" + defs.OptionShare, }, &cli.StringFlag{ Name: defs.OptionTelemetryShare, - Usage: "Set the telemetry share link path", + Usage: "Set the telemetry share link path. Implies --" + defs.OptionShare, }, &cli.StringFlag{ - Name: defs.OptionTelemetryExtra, - Usage: "Send a custom message along with the telemetry results", + Name: defs.OptionTelemetryExtra, + Usage: "Send a custom message along with the telemetry results.\n" + + "\tImplies --" + defs.OptionShare, }, }, } From 0ebda01e7ef4180337768dd1e17831ee605bd35a Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 18 Mar 2020 22:39:44 +0800 Subject: [PATCH 14/69] Update README.md --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4ee88f9..dd0a006 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ GLOBAL OPTIONS: --ipv6, -6 Force IPv6 only (default: false) --no-download Do not perform download test (default: false) --no-upload Do not perform upload test (default: false) + --concurrent value Concurrent HTTP requests being made (default: 3) --bytes Display values in bytes instead of bits. Does not affect the image generated by --share, nor output from --json or --csv (default: false) @@ -144,13 +145,14 @@ GLOBAL OPTIONS: option to avoid out of memory errors (default: false) --telemetry-json value Load telemetry server settings from a JSON file. This options overrides --telemetry-level, --telemetry-server, - --telemetry-path, and --telemetry-share + --telemetry-path, and --telemetry-share. Implies --share --telemetry-level value Set telemetry data verbosity, available values are: - disabled, basic, full, debug - --telemetry-server value Set the telemetry server base URL - --telemetry-path value Set the telemetry upload path - --telemetry-share value Set the telemetry share link path - --telemetry-extra value Send a custom message along with the telemetry results + disabled, basic, full, debug. Implies --share + --telemetry-server value Set the telemetry server base URL. Implies --share + --telemetry-path value Set the telemetry upload path. Implies --share + --telemetry-share value Set the telemetry share link path. Implies --share + --telemetry-extra value Send a custom message along with the telemetry results. + Implies --share ``` ## Use a custom backend server list From c3ad222d1a7de9c0cacc104a4ad0b3b9b08b9496 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 19 Mar 2020 10:26:52 +0800 Subject: [PATCH 15/69] Add GoReleaser configuration --- .gitignore | 2 ++ .goreleaser.yml | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ upx.sh | 2 ++ 3 files changed, 72 insertions(+) create mode 100644 .goreleaser.yml create mode 100755 upx.sh diff --git a/.gitignore b/.gitignore index 9db059d..003c6f9 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,5 @@ fabric.properties # Dependency directories (remove the comment below to include it) # vendor/ + +dist/ diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..8400b04 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,68 @@ +project_name: 'librespeed-cli' +#dist: ./out +before: + hooks: + - go mod download +builds: +- main: ./main.go + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" + goos: + - windows + - linux + - darwin + - freebsd + goarch: + - 386 + - amd64 + - arm + - arm64 + - mips + - mipsle + - mips64 + - mips64le + goarm: + - 5 + - 6 + - 7 + gomips: + - hardfloat + - softfloat + ignore: + - goos: darwin + goarch: 386 + hooks: + post: ./upx.sh +archives: + - format_overrides: + - goos: windows + format: zip + files: + - LICENSE +checksum: + name_template: 'checksums.txt' +changelog: + skip: false + sort: asc +brews: + - github: + owner: librespeed + name: homebrew-tap + commit_author: + name: "Maddie Zhan" + email: maddie.zhan@gmail.com + folder: Formula + homepage: "https://github.com/librespeed/speedtest-cli" + description: "Command-line client for LibreSpeed" + skip_upload: true + custom_block: | + head "https://github.com/librespeed/speedtest-cli.git" +release: + github: + owner: librespeed + name: speedtest-cli + disable: false diff --git a/upx.sh b/upx.sh new file mode 100755 index 0000000..32f5c87 --- /dev/null +++ b/upx.sh @@ -0,0 +1,2 @@ +#!/bin/sh +(which upx > /dev/null && ls -1 dist/*/* | xargs -I{} -n1 -P 4 $(which upx) -9 "{}") || echo "not using upx for binary compression" From f0ed59d53f255b24063161b9f5224d025bc1abc0 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 19 Mar 2020 10:33:57 +0800 Subject: [PATCH 16/69] Update README.md for binary releases --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dd0a006..60cbaf1 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,14 @@ This is a command line interface for LibreSpeed speed test backends, written in ## Runtime requirements - Any [Go supported platforms](https://github.com/golang/go/wiki/MinimumRequirements) +## Use prebuilt binaries + +If you don't want to build `librespeed-cli` yourself, you can find different binaries compiled for various platforms in +the [releases page](https://github.com/librespeed/speedtest-cli/releases). + ## Building `librespeed-cli` -1. First, you'll have to install Go. For Windows users, [you can download an installer from golang.org](https://golang.org/dl/). +1. First, you'll have to install Go (at least version 1.11). For Windows users, [you can download an installer from golang.org](https://golang.org/dl/). For Linux users, you can use either the archive from golang.org, or install from your distribution's package manager. For example, Arch Linux: @@ -56,6 +61,7 @@ can now proceed to build `librespeed-cli` with the build script: variables. Run `go tool dist list` to get a list of possible combinations of `GOOS` and `GOARCH`. ```shell script + # If you're using Go version < 1.12, you will need to export GO111MODULE=on # Let's say we're building for 64-bit Windows on Linux $ GOOS=windows GOARCH=amd64 ./build.sh ``` From 9dc19eb3a3423dc07015150f3f12d7df9cb4525d Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 24 Mar 2020 16:16:20 +0800 Subject: [PATCH 17/69] Update README.md for clarity --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 60cbaf1..2006547 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This is a command line interface for LibreSpeed speed test backends, written in [![asciicast](https://asciinema.org/a/J17bUAilWI3qR12JyhfGvPwu2.svg)](https://asciinema.org/a/J17bUAilWI3qR12JyhfGvPwu2) ## Requirements for compiling -- Go 1.14 +- Go 1.14+ ## Runtime requirements - Any [Go supported platforms](https://github.com/golang/go/wiki/MinimumRequirements) @@ -60,8 +60,10 @@ can now proceed to build `librespeed-cli` with the build script: If you want to build for another operating system or system architecture, use the `GOOS` and `GOARCH` environment variables. Run `go tool dist list` to get a list of possible combinations of `GOOS` and `GOARCH`. + Note: Technically, the CLI can be compiled with older Go versions that support Go modules, with `GO111MODULE=on` + set. If you're compiling with an older Go runtime, you might have to change the Go version in `go.mod`. + ```shell script - # If you're using Go version < 1.12, you will need to export GO111MODULE=on # Let's say we're building for 64-bit Windows on Linux $ GOOS=windows GOARCH=amd64 ./build.sh ``` From 9b7219a90088dbb6bf9e80333903d40f621161c2 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 26 Mar 2020 14:26:11 +0800 Subject: [PATCH 18/69] Print server sponsor when available --- defs/bytes_counter.go | 4 +++- defs/server.go | 19 +++++++++++-------- speedtest/helper.go | 21 +++++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index f2e0a11..30181f8 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -45,7 +45,6 @@ func (c *BytesCounter) Read(p []byte) (int, error) { c.total += n c.pos += n if c.pos == uploadSize { - c.pos = 0 c.resetReader() } c.lock.Unlock() @@ -63,6 +62,7 @@ func (c *BytesCounter) AvgBytes() float64 { return float64(c.total) / time.Now().Sub(c.start).Seconds() } +// AvgMbps returns the average mbits/second func (c *BytesCounter) AvgMbps() float64 { var base float64 = 125000 if c.mebi { @@ -71,6 +71,7 @@ func (c *BytesCounter) AvgMbps() float64 { return c.AvgBytes() / base } +// AvgHumanize returns the average bytes/kilobytes/megabytes/gigabytes (or bytes/kibibytes/mebibytes/gibibytes) per second func (c *BytesCounter) AvgHumanize() string { val := c.AvgBytes() @@ -99,6 +100,7 @@ func (c *BytesCounter) GenerateBlob() { // resetReader resets the `reader` field to 0 position func (c *BytesCounter) resetReader() (int64, error) { + c.pos = 0 return c.reader.Seek(0, 0) } diff --git a/defs/server.go b/defs/server.go index 766b923..a3c2d24 100644 --- a/defs/server.go +++ b/defs/server.go @@ -22,14 +22,17 @@ import ( // Server represents a speed test server type Server struct { - Name string `json:"name"` - Server string `json:"server"` - DownloadURL string `json:"dlURL"` - UploadURL string `json:"ulURL"` - PingURL string `json:"pingURL"` - GetIPURL string `json:"getIpURL"` - ICMPFail bool `json:"-"` - TLog TelemetryLog `json:"-"` + Name string `json:"name"` + Server string `json:"server"` + DownloadURL string `json:"dlURL"` + UploadURL string `json:"ulURL"` + PingURL string `json:"pingURL"` + GetIPURL string `json:"getIpURL"` + SponsorName string `json:"sponsorName"` + SponsorURL string `json:"sponsorURL"` + + ICMPFail bool `json:"-"` + TLog TelemetryLog `json:"-"` } // IsUp checks the speed test backend is up by accessing the ping URL diff --git a/speedtest/helper.go b/speedtest/helper.go index 6ac7bd1..216031a 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -8,6 +8,7 @@ import ( "math" "mime/multipart" "net/http" + "net/url" "strconv" "strings" "time" @@ -45,6 +46,26 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel log.Infof("Selected server: %s [%s]", currentServer.Name, u.Hostname()) + var sponsorMsg string + if currentServer.SponsorName != "" { + sponsorMsg += currentServer.SponsorName + + if currentServer.SponsorURL != "" { + su, err := url.Parse(currentServer.SponsorURL) + if err != nil { + log.Debugf("Sponsor URL is invalid: %s", currentServer.SponsorURL) + } else { + if su.Scheme == "" { + su.Scheme = "https" + } + sponsorMsg += " @ " + su.String() + } + } + } + if sponsorMsg != "" { + log.Infof("Sponsored by: %s", sponsorMsg) + } + if currentServer.IsUp() { ispInfo, err := currentServer.GetIPInfo(c.String(defs.OptionDistance)) if err != nil { From e56ed18c3b62d2d6b476fb2448e78ecefe23dfef Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 26 Mar 2020 15:38:50 +0800 Subject: [PATCH 19/69] Also show sponsor info in server list --- defs/server.go | 21 +++++++++++++++++++++ speedtest/helper.go | 19 +------------------ speedtest/speedtest.go | 7 ++++++- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/defs/server.go b/defs/server.go index a3c2d24..8c487e4 100644 --- a/defs/server.go +++ b/defs/server.go @@ -424,3 +424,24 @@ func (s *Server) GetURL() (*url.URL, error) { } return u, nil } + +// Sponsor returns the sponsor's info +func (s *Server) Sponsor() string { + var sponsorMsg string + if s.SponsorName != "" { + sponsorMsg += s.SponsorName + + if s.SponsorURL != "" { + su, err := url.Parse(s.SponsorURL) + if err != nil { + log.Debugf("Sponsor URL is invalid: %s", s.SponsorURL) + } else { + if su.Scheme == "" { + su.Scheme = "https" + } + sponsorMsg += " @ " + su.String() + } + } + } + return sponsorMsg +} diff --git a/speedtest/helper.go b/speedtest/helper.go index 216031a..5efefb8 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -8,7 +8,6 @@ import ( "math" "mime/multipart" "net/http" - "net/url" "strconv" "strings" "time" @@ -46,23 +45,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel log.Infof("Selected server: %s [%s]", currentServer.Name, u.Hostname()) - var sponsorMsg string - if currentServer.SponsorName != "" { - sponsorMsg += currentServer.SponsorName - - if currentServer.SponsorURL != "" { - su, err := url.Parse(currentServer.SponsorURL) - if err != nil { - log.Debugf("Sponsor URL is invalid: %s", currentServer.SponsorURL) - } else { - if su.Scheme == "" { - su.Scheme = "https" - } - sponsorMsg += " @ " + su.String() - } - } - } - if sponsorMsg != "" { + if sponsorMsg := currentServer.Sponsor(); sponsorMsg != "" { log.Infof("Sponsored by: %s", sponsorMsg) } diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 31b0fda..f3af38d 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "fmt" "io/ioutil" "net" "net/http" @@ -235,7 +236,11 @@ func SpeedTest(c *cli.Context) error { // if --list is given, list all the servers fetched and exit if c.Bool(defs.OptionList) { for idx, svr := range servers { - log.Warnf("%d: %s (%s)", idx, svr.Name, svr.Server) + var sponsorMsg string + if svr.Sponsor() != "" { + sponsorMsg = fmt.Sprintf(" [Sponsor: %s]", svr.Sponsor()) + } + log.Warnf("%d: %s (%s) %s", idx, svr.Name, svr.Server, sponsorMsg) } return nil } From 2c4cb90e66803111947a0f0b321951dd5b89a5f1 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 26 Mar 2020 15:54:49 +0800 Subject: [PATCH 20/69] Un-export ICMP failed field --- defs/server.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/defs/server.go b/defs/server.go index 8c487e4..83dc8e3 100644 --- a/defs/server.go +++ b/defs/server.go @@ -31,8 +31,8 @@ type Server struct { SponsorName string `json:"sponsorName"` SponsorURL string `json:"sponsorURL"` - ICMPFail bool `json:"-"` - TLog TelemetryLog `json:"-"` + icmpFailed bool `json:"-"` + TLog TelemetryLog `json:"-"` } // IsUp checks the speed test backend is up by accessing the ping URL @@ -62,7 +62,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f s.TLog.Logf("ICMP ping took %s", time.Now().Sub(t).String()) }() - if s.ICMPFail { + if s.icmpFailed { log.Debug("ICMP ping failed already, using HTTP ping") return s.PingAndJitter(count + 2) } @@ -111,7 +111,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f } if len(stats.Rtts) == 0 { - s.ICMPFail = true + s.icmpFailed = true log.Debugf("No ICMP pings returned for server %s (%s), trying TCP ping", s.Name, u.Hostname()) return s.PingAndJitter(count + 2) } From c9bfcbc77043da73ff669de5611807053c084177 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 30 Mar 2020 16:51:07 +0800 Subject: [PATCH 21/69] Use new backend server list URL --- speedtest/speedtest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index f3af38d..bc6a9ed 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -22,7 +22,7 @@ import ( const ( // serverListUrl is the default remote server JSON URL - serverListUrl = `https://librespeed.org/backend-servers/servers.json` + serverListUrl = `https://librespeed.org/backend-servers/servers.php` defaultTelemetryLevel = "basic" defaultTelemetryServer = "https://librespeed.org" From 4898bfecc9817768b1cb3b3ab838b693d29c02e8 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 31 Mar 2020 18:08:04 +0800 Subject: [PATCH 22/69] Send outputs to stdout instead of stderr Fixes #5 --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index f2512ca..744ed36 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ func init() { // warn level is for suppress modes // error level is for errors + log.SetOutput(os.Stdout) log.SetFormatter(formatter) log.SetLevel(log.InfoLevel) } From 1f8dc728d7126ab36f844ffb9533f8bc6bf94572 Mon Sep 17 00:00:00 2001 From: mildis Date: Fri, 15 May 2020 03:08:55 +0200 Subject: [PATCH 23/69] handle a .well-known URI (#9) * reformat message to match custom url * retry remote fetch with .well-known URI Instead of having to type a whole URI, expect the JSON server list to be served at /.well-known/librespeed Thus, only the base URL should be necessary. --- speedtest/speedtest.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index bc6a9ed..037782e 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -220,13 +220,18 @@ func SpeedTest(c *cli.Context) error { servers, err = getLocalServers(c.Bool(defs.OptionSecure), str, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) } else { // fetch the server list JSON and parse it into the `servers` array - log.Info("Retrieving LibreSpeed.org server list") serverUrl := serverListUrl if str := c.String(defs.OptionServerJSON); str != "" { serverUrl = str } + log.Info("Retrieving server list from %s", serverUrl) servers, err = getServerList(c.Bool(defs.OptionSecure), serverUrl, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + + if err != nil { + log.Info("Retry with /.well-known/librespeed") + servers, err = getServerList(c.Bool(defs.OptionSecure), serverUrl + "/.well-known/librespeed", c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + } } if err != nil { log.Errorf("Error when fetching server list: %s", err) From 166771ba3f20090afbc1b8562be9e766c2636016 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 29 Jun 2020 12:44:13 +0800 Subject: [PATCH 24/69] Fix user-agent on fetching server list JSON Fixes #11 --- speedtest/speedtest.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 037782e..36fe5cd 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -230,7 +230,7 @@ func SpeedTest(c *cli.Context) error { if err != nil { log.Info("Retry with /.well-known/librespeed") - servers, err = getServerList(c.Bool(defs.OptionSecure), serverUrl + "/.well-known/librespeed", c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + servers, err = getServerList(c.Bool(defs.OptionSecure), serverUrl+"/.well-known/librespeed", c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) } } if err != nil { @@ -347,7 +347,13 @@ func getServerList(forceHTTPS bool, serverList string, excludes, specific []int, // getting the server list from remote var servers []defs.Server - resp, err := http.DefaultClient.Get(serverList) + req, err := http.NewRequest(http.MethodGet, serverList, nil) + if err != nil { + return nil, err + } + req.Header.Set("User-Agent", defs.UserAgent) + + resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } From 61990902854e21c3bba96c6f5923dceee75f649d Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 14 Jul 2020 17:28:13 +0800 Subject: [PATCH 25/69] Use ID from server JSON instead of slice index --- README.md | 2 ++ defs/server.go | 1 + speedtest/speedtest.go | 14 +++++++------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2006547..22b81cc 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,7 @@ locally via `--local-json`). The format is as below: ```json [ { + "id": 1, "name": "PHP Backend", "server": "https://example.com/", "dlURL": "garbage.php", @@ -178,6 +179,7 @@ locally via `--local-json`). The format is as below: "getIpURL": "getIP.php" }, { + "id": 2, "name": "Go Backend", "server": "http://example.com/speedtest/", "dlURL": "garbage", diff --git a/defs/server.go b/defs/server.go index 83dc8e3..ced2a9c 100644 --- a/defs/server.go +++ b/defs/server.go @@ -22,6 +22,7 @@ import ( // Server represents a speed test server type Server struct { + ID int `json:"id"` Name string `json:"name"` Server string `json:"server"` DownloadURL string `json:"dlURL"` diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 36fe5cd..4323560 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -224,7 +224,7 @@ func SpeedTest(c *cli.Context) error { if str := c.String(defs.OptionServerJSON); str != "" { serverUrl = str } - log.Info("Retrieving server list from %s", serverUrl) + log.Infof("Retrieving server list from %s", serverUrl) servers, err = getServerList(c.Bool(defs.OptionSecure), serverUrl, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) @@ -240,12 +240,12 @@ func SpeedTest(c *cli.Context) error { // if --list is given, list all the servers fetched and exit if c.Bool(defs.OptionList) { - for idx, svr := range servers { + for _, svr := range servers { var sponsorMsg string if svr.Sponsor() != "" { sponsorMsg = fmt.Sprintf(" [Sponsor: %s]", svr.Sponsor()) } - log.Warnf("%d: %s (%s) %s", idx, svr.Name, svr.Server, sponsorMsg) + log.Warnf("%d: %s (%s) %s", svr.ID, svr.Name, svr.Server, sponsorMsg) } return nil } @@ -415,8 +415,8 @@ func preprocessServers(servers []defs.Server, forceHTTPS bool, excludes, specifi // exclude servers from --exclude if len(excludes) > 0 { var ret []defs.Server - for idx, server := range servers { - if contains(excludes, idx) { + for _, server := range servers { + if contains(excludes, server.ID) { continue } ret = append(ret, server) @@ -428,8 +428,8 @@ func preprocessServers(servers []defs.Server, forceHTTPS bool, excludes, specifi // special value -1 will test all servers if len(specific) > 0 && !contains(specific, -1) { var ret []defs.Server - for idx, server := range servers { - if contains(specific, idx) { + for _, server := range servers { + if contains(specific, server.ID) { ret = append(ret, server) } } From 7063aa41df1818db6f67add1b7fd297023430604 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 14 Jul 2020 17:32:35 +0800 Subject: [PATCH 26/69] Update goreleaser.yml --- .goreleaser.yml | 2 +- upx.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 8400b04..f1e458c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -36,7 +36,7 @@ builds: - goos: darwin goarch: 386 hooks: - post: ./upx.sh + post: ./upx.sh -9 "{{ .Path }}" archives: - format_overrides: - goos: windows diff --git a/upx.sh b/upx.sh index 32f5c87..22b4320 100755 --- a/upx.sh +++ b/upx.sh @@ -1,2 +1,2 @@ #!/bin/sh -(which upx > /dev/null && ls -1 dist/*/* | xargs -I{} -n1 -P 4 $(which upx) -9 "{}") || echo "not using upx for binary compression" +upx "$@" || true \ No newline at end of file From 06859d9a861ea0f2d38946a89d265eef3ab9aaf6 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 15 Jul 2020 17:40:39 +0800 Subject: [PATCH 27/69] Show correct User Agent for IsUp and GetIP --- defs/server.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/defs/server.go b/defs/server.go index ced2a9c..8cd97e3 100644 --- a/defs/server.go +++ b/defs/server.go @@ -45,7 +45,15 @@ func (s *Server) IsUp() bool { u, _ := s.GetURL() u.Path = path.Join(u.Path, s.PingURL) - resp, err := http.Get(u.String()) + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + log.Debugf("Failed when creating HTTP request: %s", err) + return false + } + req.Header.Set("User-Agent", UserAgent) + + resp, err := http.DefaultClient.Do(req) if err != nil { log.Debugf("Error checking for server status: %s", err) return false @@ -120,7 +128,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f return float64(stats.AvgRtt.Milliseconds()), jitter, nil } -// ICMPPingAndJitter pings the server via accessing ping URL and calculate the average ping and jitter +// PingAndJitter pings the server via accessing ping URL and calculate the average ping and jitter func (s *Server) PingAndJitter(count int) (float64, float64, error) { t := time.Now() defer func() { @@ -388,6 +396,8 @@ func (s *Server) GetIPInfo(distanceUnit string) (*GetIPResult, error) { log.Debugf("Failed when creating HTTP request: %s", err) return nil, err } + req.Header.Set("User-Agent", UserAgent) + resp, err := http.DefaultClient.Do(req) if err != nil { log.Debugf("Failed when making HTTP request: %s", err) From 02de79bf8d02fa4a270af6db33e72945e1820d1f Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 16 Sep 2020 14:23:01 +0800 Subject: [PATCH 28/69] Fix variable name collision --- defs/server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/defs/server.go b/defs/server.go index 8cd97e3..7572ef3 100644 --- a/defs/server.go +++ b/defs/server.go @@ -171,9 +171,9 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } var lastPing, jitter float64 - for idx, ping := range pings { + for idx, p := range pings { if idx != 0 { - instJitter := math.Abs(lastPing - ping) + instJitter := math.Abs(lastPing - p) if idx > 1 { if jitter > instJitter { jitter = jitter*0.7 + instJitter*0.3 @@ -182,7 +182,7 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } } } - lastPing = ping + lastPing = p } return getAvg(pings), jitter, nil From eb7f5cb43a7f6034ae34b548c37e1e6bfba3f8de Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 22 Sep 2020 09:45:27 +0800 Subject: [PATCH 29/69] Update go-ping module --- defs/server.go | 10 +++------- go.mod | 5 +---- go.sum | 16 ++++++++++++++++ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/defs/server.go b/defs/server.go index 7572ef3..584720e 100644 --- a/defs/server.go +++ b/defs/server.go @@ -16,8 +16,8 @@ import ( "time" "github.com/briandowns/spinner" + "github.com/go-ping/ping" log "github.com/sirupsen/logrus" - "github.com/sparrc/go-ping" ) // Server represents a speed test server @@ -82,12 +82,8 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f return 0, 0, err } - p, err := ping.NewPinger(u.Hostname(), network) - if err != nil { - log.Debugf("Failed to initialize pinger: %s", err) - return 0, 0, err - } - + p := ping.New(u.Hostname()) + p.SetNetwork(network) p.Count = count p.Timeout = time.Duration(count) * time.Second if srcIp != "" { diff --git a/go.mod b/go.mod index fc73bc4..8df19ee 100644 --- a/go.mod +++ b/go.mod @@ -2,14 +2,11 @@ module librespeed-cli go 1.14 -replace github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c => github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6 - require ( github.com/briandowns/spinner v1.9.0 + github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8 github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 github.com/sirupsen/logrus v1.4.2 - github.com/sparrc/go-ping v0.0.0-20190613174326-4e5b6552494c github.com/stretchr/testify v1.3.0 // indirect github.com/urfave/cli/v2 v2.1.1 - golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect ) diff --git a/go.sum b/go.sum index be26162..5300906 100644 --- a/go.sum +++ b/go.sum @@ -8,12 +8,21 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/go-ping/ping v0.0.0-20200914212621-54d38cd396bf h1:Si56g5S0exdNxcek5HDYtBFR5gkhO80lzOzhVKuyjWg= +github.com/go-ping/ping v0.0.0-20200914212621-54d38cd396bf/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8 h1:shBkr1XYT+CHuE5EGfVkAG+wmjCyFq0N2/IG1uOIaSg= +github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 h1:rRQm5os6ffGTukb42ZgKWOFfdFrocrNkLcjPYRP1tm0= github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6 h1:ApVK0ZXs0wyZmj4dSelnorxkJguUhVLXxT+ghrXtNQY= github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6/go.mod h1:IYhVIzcOSIO1fLDdEz4JFidYhLPmmW3dchKuengmL9s= +github.com/maddie/go-ping v0.0.0-20200915081652-c89bd3fdbeb7 h1:TQhvzZ+MLgKsxVB5eElemqN7SQ5ZL1YDuSD1W63JIGA= +github.com/maddie/go-ping v0.0.0-20200915081652-c89bd3fdbeb7/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/maddie/go-ping v0.0.0-20200916030256-52ca90ca7d12/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/maddie/go-ping v0.0.0-20200916055352-b3642c5a335e h1:7F2YtzZ+fwwzGWd+82Avnt4hswPDXaqZ2fZO6+RW3U8= +github.com/maddie/go-ping v0.0.0-20200916055352-b3642c5a335e/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= @@ -34,13 +43,20 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From dc6eb0fbcea516831b075e0ebd3a4f53b572ffa4 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 25 Nov 2020 10:24:25 +0800 Subject: [PATCH 30/69] Configurable download chunks, upload size and test duration --- defs/bytes_counter.go | 22 ++++++++++++++-------- defs/defs.go | 7 ------- defs/options.go | 3 +++ defs/server.go | 11 ++++++----- main.go | 17 ++++++++++++++++- speedtest/helper.go | 4 ++-- 6 files changed, 41 insertions(+), 23 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 30181f8..1553aff 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -12,12 +12,13 @@ import ( // BytesCounter implements io.Reader and io.Writer interface, for counting bytes being read/written in HTTP requests type BytesCounter struct { - start time.Time - pos int - total int - payload []byte - reader io.ReadSeeker - mebi bool + start time.Time + pos int + total int + payload []byte + reader io.ReadSeeker + mebi bool + uploadSize int lock *sync.Mutex } @@ -44,7 +45,7 @@ func (c *BytesCounter) Read(p []byte) (int, error) { c.lock.Lock() c.total += n c.pos += n - if c.pos == uploadSize { + if c.pos == c.uploadSize { c.resetReader() } c.lock.Unlock() @@ -57,6 +58,11 @@ func (c *BytesCounter) SetMebi(mebi bool) { c.mebi = mebi } +// SetUploadSize sets the size of payload being uploaded +func (c *BytesCounter) SetUploadSize(uploadSize int) { + c.uploadSize = uploadSize * 1024 +} + // AvgBytes returns the average bytes/second func (c *BytesCounter) AvgBytes() float64 { return float64(c.total) / time.Now().Sub(c.start).Seconds() @@ -94,7 +100,7 @@ func (c *BytesCounter) AvgHumanize() string { // GenerateBlob generates a random byte array of `uploadSize` in the `payload` field, and sets the `reader` field to // read from it func (c *BytesCounter) GenerateBlob() { - c.payload = getRandomData(uploadSize) + c.payload = getRandomData(c.uploadSize) c.reader = bytes.NewReader(c.payload) } diff --git a/defs/defs.go b/defs/defs.go index 0197cfa..ad1cb46 100644 --- a/defs/defs.go +++ b/defs/defs.go @@ -1,12 +1,5 @@ package defs -const ( - // chunks to download in download test - downloadChunks = 100 - // payload size per upload request - uploadSize = 1024 * 1024 -) - var ( // values to be filled in by build script BuildDate string diff --git a/defs/options.go b/defs/options.go index 6e1a29f..e029f4d 100644 --- a/defs/options.go +++ b/defs/options.go @@ -24,6 +24,9 @@ const ( OptionServerJSON = "server-json" OptionSource = "source" OptionTimeout = "timeout" + OptionChunks = "chunks" + OptionUploadSize = "upload-size" + OptionDuration = "duration" OptionSecure = "secure" OptionNoPreAllocate = "no-pre-allocate" OptionVersion = "version" diff --git a/defs/server.go b/defs/server.go index 584720e..c65f541 100644 --- a/defs/server.go +++ b/defs/server.go @@ -185,7 +185,7 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } // Download performs the actual download test -func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int) (float64, int, error) { +func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int, chunks int, duration time.Duration) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Download took %s", time.Now().Sub(t).String()) @@ -210,7 +210,7 @@ func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int) (fl return 0, 0, err } q := req.URL.Query() - q.Set("ckSize", strconv.Itoa(downloadChunks)) + q.Set("ckSize", strconv.Itoa(chunks)) req.URL.RawQuery = q.Encode() req.Header.Set("User-Agent", UserAgent) req.Header.Set("Accept-Encoding", "identity") @@ -261,7 +261,7 @@ func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int) (fl go doDownload() time.Sleep(200 * time.Millisecond) } - timeout := time.After(15 * time.Second) + timeout := time.After(duration) Loop: for { select { @@ -277,7 +277,7 @@ Loop: } // Upload performs the actual upload test -func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int) (float64, int, error) { +func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int, uploadSize int, duration time.Duration) (float64, int, error) { t := time.Now() defer func() { s.TLog.Logf("Upload took %s", time.Now().Sub(t).String()) @@ -285,6 +285,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int counter := NewCounter() counter.SetMebi(useMebi) + counter.SetUploadSize(uploadSize) if noPrealloc { log.Info("Pre-allocation is disabled, performance might be lower!") @@ -353,7 +354,7 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int go doUpload() time.Sleep(200 * time.Millisecond) } - timeout := time.After(15 * time.Second) + timeout := time.After(duration) Loop: for { select { diff --git a/main.go b/main.go index 744ed36..4d6d374 100644 --- a/main.go +++ b/main.go @@ -135,9 +135,24 @@ func main() { }, &cli.IntFlag{ Name: defs.OptionTimeout, - Usage: "HTTP `TIMEOUT` in seconds.", + Usage: "HTTP `TIMEOUT` in seconds", Value: 15, }, + &cli.IntFlag{ + Name: defs.OptionDuration, + Usage: "Upload and download test duration in seconds", + Value: 15, + }, + &cli.IntFlag{ + Name: defs.OptionChunks, + Usage: "Chunks to download from server, chunk size depends on server configuration", + Value: 100, + }, + &cli.IntFlag{ + Name: defs.OptionUploadSize, + Usage: "Size of payload being uploaded in KiB", + Value: 1024, + }, &cli.BoolFlag{ Name: defs.OptionSecure, Usage: "Use HTTPS instead of HTTP when communicating with\n" + diff --git a/speedtest/helper.go b/speedtest/helper.go index 5efefb8..12ca450 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -82,7 +82,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoDownload) { log.Info("Download test is disabled") } else { - download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent)) + download, br, err := currentServer.Download(silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent), c.Int(defs.OptionChunks), time.Duration(c.Int(defs.OptionDuration))*time.Second) if err != nil { log.Errorf("Failed to get download speed: %s", err) return err @@ -97,7 +97,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionNoUpload) { log.Info("Upload test is disabled") } else { - upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent)) + upload, bw, err := currentServer.Upload(c.Bool(defs.OptionNoPreAllocate), silent, c.Bool(defs.OptionBytes), c.Bool(defs.OptionMebiBytes), c.Int(defs.OptionConcurrent), c.Int(defs.OptionUploadSize), time.Duration(c.Int(defs.OptionDuration))*time.Second) if err != nil { log.Errorf("Failed to get upload speed: %s", err) return err From 4676b26441baf23bb4ab6ee664cd40104e135dac Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 7 Dec 2020 09:35:25 +0800 Subject: [PATCH 31/69] Allow self signed certs for HTTPS backends (#16) --- defs/options.go | 1 + go.sum | 11 ----------- main.go | 4 ++++ speedtest/speedtest.go | 29 ++++++++++++++++++----------- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/defs/options.go b/defs/options.go index e029f4d..d3a3b01 100644 --- a/defs/options.go +++ b/defs/options.go @@ -28,6 +28,7 @@ const ( OptionUploadSize = "upload-size" OptionDuration = "duration" OptionSecure = "secure" + OptionSkipCertVerify = "skip-cert-verify" OptionNoPreAllocate = "no-pre-allocate" OptionVersion = "version" OptionLocalJSON = "local-json" diff --git a/go.sum b/go.sum index 5300906..f33d4e6 100644 --- a/go.sum +++ b/go.sum @@ -8,21 +8,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/go-ping/ping v0.0.0-20200914212621-54d38cd396bf h1:Si56g5S0exdNxcek5HDYtBFR5gkhO80lzOzhVKuyjWg= -github.com/go-ping/ping v0.0.0-20200914212621-54d38cd396bf/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8 h1:shBkr1XYT+CHuE5EGfVkAG+wmjCyFq0N2/IG1uOIaSg= github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 h1:rRQm5os6ffGTukb42ZgKWOFfdFrocrNkLcjPYRP1tm0= github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6 h1:ApVK0ZXs0wyZmj4dSelnorxkJguUhVLXxT+ghrXtNQY= -github.com/maddie/go-ping v0.0.0-20200311033510-5e9a13ec8da6/go.mod h1:IYhVIzcOSIO1fLDdEz4JFidYhLPmmW3dchKuengmL9s= -github.com/maddie/go-ping v0.0.0-20200915081652-c89bd3fdbeb7 h1:TQhvzZ+MLgKsxVB5eElemqN7SQ5ZL1YDuSD1W63JIGA= -github.com/maddie/go-ping v0.0.0-20200915081652-c89bd3fdbeb7/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= -github.com/maddie/go-ping v0.0.0-20200916030256-52ca90ca7d12/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= -github.com/maddie/go-ping v0.0.0-20200916055352-b3642c5a335e h1:7F2YtzZ+fwwzGWd+82Avnt4hswPDXaqZ2fZO6+RW3U8= -github.com/maddie/go-ping v0.0.0-20200916055352-b3642c5a335e/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= @@ -45,8 +36,6 @@ github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= diff --git a/main.go b/main.go index 4d6d374..1acc53f 100644 --- a/main.go +++ b/main.go @@ -158,6 +158,10 @@ func main() { Usage: "Use HTTPS instead of HTTP when communicating with\n" + "\tLibreSpeed.org operated servers", }, + &cli.BoolFlag{ + Name: defs.OptionSkipCertVerify, + Usage: "Skip verifying SSL certificate for HTTPS connections (self-signed certs)", + }, &cli.BoolFlag{ Name: defs.OptionNoPreAllocate, Usage: "Do not pre allocate upload data. Pre allocation is\n" + diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 4323560..9c2dbe6 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -2,6 +2,7 @@ package speedtest import ( "context" + "crypto/tls" "encoding/json" "errors" "fmt" @@ -150,6 +151,20 @@ func SpeedTest(c *cli.Context) error { network = "ip" } + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + ForceAttemptHTTP2: true, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify)}, + } + // bind to source IP address if given, or if ipv4/ipv6 is forced if src := c.String(defs.OptionSource); src != "" || (forceIPv4 || forceIPv6) { var localTCPAddr *net.TCPAddr @@ -198,19 +213,11 @@ func SpeedTest(c *cli.Context) error { // set default HTTP client's Transport to the one that binds the source address // this is modified from http.DefaultTransport - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: dialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - - http.DefaultClient.Transport = transport + transport.DialContext = dialContext } + http.DefaultClient.Transport = transport + // load server list var servers []defs.Server var err error From 1190984d53e58f7824c01ab2f0176742d1f3e682 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 7 Dec 2020 09:36:32 +0800 Subject: [PATCH 32/69] Update dependencies --- go.mod | 15 ++++++++++----- go.sum | 47 +++++++++++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 8df19ee..0196f7c 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,15 @@ module librespeed-cli go 1.14 require ( - github.com/briandowns/spinner v1.9.0 - github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8 - github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 - github.com/sirupsen/logrus v1.4.2 + github.com/briandowns/spinner v1.12.0 + github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/fatih/color v1.10.0 // indirect + github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663 + github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2 + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sirupsen/logrus v1.7.0 github.com/stretchr/testify v1.3.0 // indirect - github.com/urfave/cli/v2 v2.1.1 + github.com/urfave/cli/v2 v2.3.0 + golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect + golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect ) diff --git a/go.sum b/go.sum index f33d4e6..ab8a305 100644 --- a/go.sum +++ b/go.sum @@ -1,51 +1,66 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/briandowns/spinner v1.9.0 h1:+OMAisemaHar1hjuJ3Z2hIvNhQl9Y7GLPWUwwz2Pxo8= -github.com/briandowns/spinner v1.9.0/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ= +github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= +github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8 h1:shBkr1XYT+CHuE5EGfVkAG+wmjCyFq0N2/IG1uOIaSg= -github.com/go-ping/ping v0.0.0-20200918120429-e8ae07c3cec8/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= -github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58 h1:rRQm5os6ffGTukb42ZgKWOFfdFrocrNkLcjPYRP1tm0= -github.com/gocarina/gocsv v0.0.0-20200302151839-87c60d755c58/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663 h1:jI2GiiRh+pPbey52EVmbU6kuLiXqwy4CXZ4gwUBj8Y0= +github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2 h1:IzQ9tzNTkqDzTxmAcLIq3pl/6epTREBV/mPyBQ2Jwsc= +github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= -github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From fd8af1557cd2ce81090fde12e67d230b394c9aa6 Mon Sep 17 00:00:00 2001 From: Andonome <52453904+Andonome@users.noreply.github.com> Date: Mon, 7 Dec 2020 02:39:02 +0100 Subject: [PATCH 33/69] remove readme 'by default' repetition (#15) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 22b81cc..7fe14a8 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ As you can see in the example, all servers have their schemes defined. In case o `librespeed-cli` will use `http` by default, or `https` when the `--secure` option is enabled. ## Use a custom telemetry server -By default, the telemetry result will be sent to `librespeed.org` by default. You can also customize your telemetry settings +By default, the telemetry result will be sent to `librespeed.org`. You can also customize your telemetry settings via the `--telemetry` prefixed options. In order to load a custom telemetry endpoint configuration, you'll have to use the `--telemetry-json` option to specify a local JSON file containing the configuration bits. The format is as below: From 5cf383b64d1aba74700c0f34d0929a096fbb46a6 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Mon, 7 Dec 2020 09:45:38 +0800 Subject: [PATCH 34/69] Clone the DefaultTransport directly from stdlib --- speedtest/speedtest.go | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 9c2dbe6..a2e8057 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -151,19 +151,8 @@ func SpeedTest(c *cli.Context) error { network = "ip" } - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - TLSClientConfig: &tls.Config{InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify)}, - } + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify)} // bind to source IP address if given, or if ipv4/ipv6 is forced if src := c.String(defs.OptionSource); src != "" || (forceIPv4 || forceIPv6) { From c9903d395ade54fa1f7269888d49992120def20a Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 15 Jan 2021 10:09:24 +0800 Subject: [PATCH 35/69] Allow skipping ICMP pings --- defs/options.go | 1 + defs/server.go | 10 +++++----- main.go | 5 +++++ speedtest/helper.go | 3 +++ speedtest/speedtest.go | 7 +++++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/defs/options.go b/defs/options.go index d3a3b01..255a5b1 100644 --- a/defs/options.go +++ b/defs/options.go @@ -8,6 +8,7 @@ const ( OptionIPv6Alt = "6" OptionNoDownload = "no-download" OptionNoUpload = "no-upload" + OptionNoICMP = "no-icmp" OptionConcurrent = "concurrent" OptionBytes = "bytes" OptionMebiBytes = "mebibytes" diff --git a/defs/server.go b/defs/server.go index c65f541..33417eb 100644 --- a/defs/server.go +++ b/defs/server.go @@ -32,8 +32,8 @@ type Server struct { SponsorName string `json:"sponsorName"` SponsorURL string `json:"sponsorURL"` - icmpFailed bool `json:"-"` - TLog TelemetryLog `json:"-"` + NoICMP bool `json:"-"` + TLog TelemetryLog `json:"-"` } // IsUp checks the speed test backend is up by accessing the ping URL @@ -71,8 +71,8 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f s.TLog.Logf("ICMP ping took %s", time.Now().Sub(t).String()) }() - if s.icmpFailed { - log.Debug("ICMP ping failed already, using HTTP ping") + if s.NoICMP { + log.Debugf("Skipping ICMP for server %s, will use HTTP ping", s.Name) return s.PingAndJitter(count + 2) } @@ -116,7 +116,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f } if len(stats.Rtts) == 0 { - s.icmpFailed = true + s.NoICMP = true log.Debugf("No ICMP pings returned for server %s (%s), trying TCP ping", s.Name, u.Hostname()) return s.PingAndJitter(count + 2) } diff --git a/main.go b/main.go index 1acc53f..4c2193c 100644 --- a/main.go +++ b/main.go @@ -56,6 +56,11 @@ func main() { Name: defs.OptionNoUpload, Usage: "Do not perform upload test", }, + &cli.BoolFlag{ + Name: defs.OptionNoICMP, + Usage: "Do not use ICMP ping. ICMP doesn't work well under Linux\n" + + "at this moment, so you might want to disable it", + }, &cli.IntFlag{ Name: defs.OptionConcurrent, Usage: "Concurrent HTTP requests being made", diff --git a/speedtest/helper.go b/speedtest/helper.go index 12ca450..69e0c56 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -65,6 +65,9 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel pb.Start() } + // skip ICMP if option given + currentServer.NoICMP = c.Bool(defs.OptionNoICMP) + p, jitter, err := currentServer.ICMPPingAndJitter(pingCount, c.String(defs.OptionSource), network) if err != nil { log.Errorf("Failed to get ping and jitter: %s", err) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index a2e8057..f24f4b0 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -262,7 +262,7 @@ func SpeedTest(c *cli.Context) error { // spawn 10 concurrent pingers for i := 0; i < 10; i++ { - go pingWorker(jobs, results, &wg, c.String(defs.OptionSource), network) + go pingWorker(jobs, results, &wg, c.String(defs.OptionSource), network, c.Bool(defs.OptionNoICMP)) } // send ping jobs to workers @@ -303,7 +303,7 @@ func SpeedTest(c *cli.Context) error { } } -func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGroup, srcIp, network string) { +func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGroup, srcIp, network string, noICMP bool) { for { job := <-jobs server := job.Server @@ -317,6 +317,9 @@ func pingWorker(jobs <-chan PingJob, results chan<- PingResult, wg *sync.WaitGro // check the server is up by accessing the ping URL and checking its returned value == empty and status code == 200 if server.IsUp() { + // skip ICMP if option given + server.NoICMP = noICMP + // if server is up, get ping ping, _, err := server.ICMPPingAndJitter(1, srcIp, network) if err != nil { From 5354b7fc8e63bcd2ef71dd26f1919bfd052a8db9 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 18 Mar 2021 22:34:02 +0800 Subject: [PATCH 36/69] Support reading local JSON from stdin Fixes #19 --- main.go | 5 +++-- speedtest/speedtest.go | 33 +++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/main.go b/main.go index 4c2193c..0c7a053 100644 --- a/main.go +++ b/main.go @@ -131,8 +131,9 @@ func main() { Usage: "Use an alternative server list from remote JSON file", }, &cli.StringFlag{ - Name: defs.OptionLocalJSON, - Usage: "Use an alternative server list from local JSON file", + Name: defs.OptionLocalJSON, + Usage: "Use an alternative server list from local JSON file,\n" + + "\tor read from stdin with \"--" + defs.OptionLocalJSON + " -\".", }, &cli.StringFlag{ Name: defs.OptionSource, diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index f24f4b0..b74934e 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -6,9 +6,11 @@ import ( "encoding/json" "errors" "fmt" + "io" "io/ioutil" "net" "net/http" + "os" "strings" "sync" "time" @@ -211,9 +213,16 @@ func SpeedTest(c *cli.Context) error { var servers []defs.Server var err error if str := c.String(defs.OptionLocalJSON); str != "" { - // load server list from local JSON file - log.Infof("Using local JSON server list: %s", str) - servers, err = getLocalServers(c.Bool(defs.OptionSecure), str, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + switch str { + case "-": + // load server list from stdin + log.Info("Using local JSON server list from stdin") + servers, err = getLocalServersReader(c.Bool(defs.OptionSecure), os.Stdin, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + default: + // load server list from local JSON file + log.Infof("Using local JSON server list: %s", str) + servers, err = getLocalServers(c.Bool(defs.OptionSecure), str, c.IntSlice(defs.OptionExclude), c.IntSlice(defs.OptionServer), !c.Bool(defs.OptionList)) + } } else { // fetch the server list JSON and parse it into the `servers` array serverUrl := serverListUrl @@ -370,10 +379,13 @@ func getServerList(forceHTTPS bool, serverList string, excludes, specific []int, return preprocessServers(servers, forceHTTPS, excludes, specific, filter) } -// getLocalServers loads the server JSON from a local file -func getLocalServers(forceHTTPS bool, jsonFile string, excludes, specific []int, filter bool) ([]defs.Server, error) { +// getLocalServersReader loads the server JSON from an io.Reader +func getLocalServersReader(forceHTTPS bool, reader io.ReadCloser, excludes, specific []int, filter bool) ([]defs.Server, error) { + defer reader.Close() + var servers []defs.Server - b, err := ioutil.ReadFile(jsonFile) + + b, err := ioutil.ReadAll(reader) if err != nil { return nil, err } @@ -385,6 +397,15 @@ func getLocalServers(forceHTTPS bool, jsonFile string, excludes, specific []int, return preprocessServers(servers, forceHTTPS, excludes, specific, filter) } +// getLocalServers loads the server JSON from a local file +func getLocalServers(forceHTTPS bool, jsonFile string, excludes, specific []int, filter bool) ([]defs.Server, error) { + f, err := os.OpenFile(jsonFile, os.O_RDONLY, 0644) + if err != nil { + return nil, err + } + return getLocalServersReader(forceHTTPS, f, excludes, specific, filter) +} + // preprocessServers makes some needed modifications to the servers fetched func preprocessServers(servers []defs.Server, forceHTTPS bool, excludes, specific []int, filter bool) ([]defs.Server, error) { for i := range servers { From 67b82aec33b3e2061c941a8bcb749aa41e0103dd Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 18 Mar 2021 22:34:52 +0800 Subject: [PATCH 37/69] Update dependencies --- go.mod | 10 +++++----- go.sum | 33 +++++++++++++-------------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 0196f7c..ef1b7ef 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,12 @@ require ( github.com/briandowns/spinner v1.12.0 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/fatih/color v1.10.0 // indirect - github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663 - github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2 + github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3 + github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4 github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.7.0 + github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.3.0 // indirect github.com/urfave/cli/v2 v2.3.0 - golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect - golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect + golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 // indirect + golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e // indirect ) diff --git a/go.sum b/go.sum index ab8a305..7af654d 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,33 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663 h1:jI2GiiRh+pPbey52EVmbU6kuLiXqwy4CXZ4gwUBj8Y0= -github.com/go-ping/ping v0.0.0-20201115131931-3300c582a663/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= -github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2 h1:IzQ9tzNTkqDzTxmAcLIq3pl/6epTREBV/mPyBQ2Jwsc= -github.com/gocarina/gocsv v0.0.0-20201204095220-fdebcd3dd3f2/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3 h1:zxFSSbYsEgooKeyDYHmLkUpdzkgbk+BBNRLSCSvOy6w= +github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4 h1:Q7s2AN3DhFJKOnzO0uTKLhJTfXTEcXcvw5ylf2BHJw4= +github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= @@ -43,22 +37,21 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e h1:XNp2Flc/1eWQGk5BLzqTAN7fQIwIbfyVTuVxXxZh73M= +golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From f6506bc122d0552eb7989b8a7f7092ff1585d9dd Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 23 Apr 2021 15:13:08 +0800 Subject: [PATCH 38/69] Only print share link when not in JSON/CSV mode Fixes #30 --- speedtest/helper.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/speedtest/helper.go b/speedtest/helper.go index 69e0c56..a357c66 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -121,7 +121,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel // print share link if --share is given var shareLink string - if !c.Bool(defs.OptionCSV) && telemetryServer.GetLevel() > 0 { + if telemetryServer.GetLevel() > 0 { var extra defs.TelemetryExtra extra.ServerName = currentServer.Name extra.Extra = c.String(defs.OptionTelemetryExtra) @@ -130,7 +130,10 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel log.Errorf("Error when sending telemetry data: %s", err) } else { shareLink = link - log.Warnf("Share your result: %s", link) + // only print to stdout when --json and --csv are not used + if !c.Bool(defs.OptionJSON) && !c.Bool(defs.OptionCSV) { + log.Warnf("Share your result: %s", link) + } } } From fd5905b72fe6a1c26cc8e8871c389ff5d155bf58 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 23 Apr 2021 15:14:14 +0800 Subject: [PATCH 39/69] Removed emoji in help message for better compatibility Fixes #28 --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 0c7a053..c467b2f 100644 --- a/main.go +++ b/main.go @@ -29,7 +29,7 @@ func main() { // define cli options app := &cli.App{ Name: "librespeed-cli", - Usage: "Test your Internet speed with LibreSpeed 🚀", + Usage: "Test your Internet speed with LibreSpeed", Action: speedtest.SpeedTest, HideHelp: true, Flags: []cli.Flag{ From 99c044638186fa116c118238034c5a3e698a13fa Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 23 Apr 2021 15:27:48 +0800 Subject: [PATCH 40/69] Do not UPX windows and darwin/arm64 binaries --- .goreleaser.yml | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index f1e458c..3b347f3 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -5,6 +5,7 @@ before: - go mod download builds: - main: ./main.go + id: upx env: - CGO_ENABLED=0 flags: @@ -12,7 +13,6 @@ builds: ldflags: - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" goos: - - windows - linux - darwin - freebsd @@ -35,8 +35,30 @@ builds: ignore: - goos: darwin goarch: 386 + - goos: darwin + goarch: arm64 hooks: post: ./upx.sh -9 "{{ .Path }}" +- main: ./main.go + id: no-upx + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" + goos: + - windows + - darwin + goarch: + - 386 + - amd64 + - arm64 + ignore: + - goos: darwin + goarch: 386 + - goos: darwin + goarch: amd64 archives: - format_overrides: - goos: windows @@ -48,19 +70,6 @@ checksum: changelog: skip: false sort: asc -brews: - - github: - owner: librespeed - name: homebrew-tap - commit_author: - name: "Maddie Zhan" - email: maddie.zhan@gmail.com - folder: Formula - homepage: "https://github.com/librespeed/speedtest-cli" - description: "Command-line client for LibreSpeed" - skip_upload: true - custom_block: | - head "https://github.com/librespeed/speedtest-cli.git" release: github: owner: librespeed From 9459cbb51d40a4de5b7539c6b23a11f4800929bf Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 23 Apr 2021 15:28:37 +0800 Subject: [PATCH 41/69] Update dependencies --- go.mod | 8 ++++---- go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index ef1b7ef..ddc99a7 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,12 @@ require ( github.com/briandowns/spinner v1.12.0 github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/fatih/color v1.10.0 // indirect - github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3 - github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4 + github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741 + github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.3.0 // indirect github.com/urfave/cli/v2 v2.3.0 - golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 // indirect - golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e // indirect + golang.org/x/net v0.0.0-20210421230115-4e50805a0758 // indirect + golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 // indirect ) diff --git a/go.sum b/go.sum index 7af654d..cb424de 100644 --- a/go.sum +++ b/go.sum @@ -10,10 +10,10 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3 h1:zxFSSbYsEgooKeyDYHmLkUpdzkgbk+BBNRLSCSvOy6w= -github.com/go-ping/ping v0.0.0-20210312085107-d90f3778a8a3/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= -github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4 h1:Q7s2AN3DhFJKOnzO0uTKLhJTfXTEcXcvw5ylf2BHJw4= -github.com/gocarina/gocsv v0.0.0-20201208093247-67c824bc04d4/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741 h1:b0sLP++Tsle+s57tqg5sUk1/OQsC6yMCciVeqNzOcwU= +github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d h1:r3mStZSyjKhEcgbJ5xtv7kT5PZw/tDiFBTMgQx2qsXE= +github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -38,8 +38,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 h1:b0LrWgu8+q7z4J+0Y3Umo5q1dL7NXBkKBWkaVkAq17E= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -48,12 +48,12 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e h1:XNp2Flc/1eWQGk5BLzqTAN7fQIwIbfyVTuVxXxZh73M= -golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 h1:qyN5bV+96OX8pL78eXDuz6YlDPzCYgdW74H5yE9BoSU= +golang.org/x/sys v0.0.0-20210421221651-33663a62ff08/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 08d21d65ff3cfb3f181834801c3b276840247366 Mon Sep 17 00:00:00 2001 From: blnprasad Date: Fri, 7 May 2021 09:24:26 +0530 Subject: [PATCH 42/69] Make ping job workers channel buffer length same as len(servers) Original title: changes to avoid race condition seen with ping job workers (#32) Authored-by: blnprasad --- speedtest/speedtest.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index b74934e..e4fbfbb 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -263,8 +263,8 @@ func SpeedTest(c *cli.Context) error { log.Info("Selecting the fastest server based on ping") var wg sync.WaitGroup - jobs := make(chan PingJob, 10) - results := make(chan PingResult, 10) + jobs := make(chan PingJob, len(servers)) + results := make(chan PingResult, len(servers)) done := make(chan struct{}) pingList := make(map[int]float64) From 9a8bca8fa028e4b1565fa5a79ec24c083f60f142 Mon Sep 17 00:00:00 2001 From: Cisco Cervellera <16772290+ciscoski@users.noreply.github.com> Date: Sat, 15 May 2021 14:24:05 +0100 Subject: [PATCH 43/69] Compatibility and Improved output (#34) * Added compatibility for cambridge-fibre backend GetIP for speedtest.cambridgefibre.uk retuns * a body which is not empty when queried with empty parameters * Just a string with IP informaiton (no distance) The code will not stop in this case but will printout a debug message. * Improved format for JSON and CSV output for multiple server. The JSON output is now a list of objects one per server. The CSV output has no empty rows. Co-authored-by: Cisco Cervellera --- defs/server.go | 6 +++++- speedtest/helper.go | 42 ++++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/defs/server.go b/defs/server.go index 33417eb..370b826 100644 --- a/defs/server.go +++ b/defs/server.go @@ -60,8 +60,11 @@ func (s *Server) IsUp() bool { } defer resp.Body.Close() b, _ := ioutil.ReadAll(resp.Body) + if len(b) > 0 { + log.Debugf("Failed when parsing get IP result: %s", b) + } // only return online if the ping URL returns nothing and 200 - return len(b) == 0 && resp.StatusCode == http.StatusOK + return resp.StatusCode == http.StatusOK } // ICMPPingAndJitter pings the server via ICMP echos and calculate the average ping and jitter @@ -412,6 +415,7 @@ func (s *Server) GetIPInfo(distanceUnit string) (*GetIPResult, error) { if err := json.Unmarshal(b, &ipInfo); err != nil { log.Debugf("Failed when parsing get IP result: %s", err) log.Debugf("Received payload: %s", b) + ipInfo.ProcessedString = string(b[:]) } } diff --git a/speedtest/helper.go b/speedtest/helper.go index a357c66..fa8a408 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -32,6 +32,9 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel log.Infof("Testing against %d servers", serverCount) } + var reps_json []report.JSONReport + var reps_csv []report.CSVReport + // fetch current user's IP info for _, currentServer := range servers { // get telemetry level @@ -140,8 +143,6 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel // check for --csv or --json. the program prioritize the --csv before the --json. this is the same behavior as speedtest-cli if c.Bool(defs.OptionCSV) { // print csv if --csv is given - var reps []report.CSVReport - var rep report.CSVReport rep.Timestamp = time.Now() @@ -154,14 +155,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel rep.Share = shareLink rep.IP = ispInfo.RawISPInfo.IP - reps = append(reps, rep) - - var buf bytes.Buffer - if err := gocsv.MarshalWithoutHeaders(&reps, &buf); err != nil { - log.Errorf("Error generating CSV report: %s", err) - } else { - log.Warn(buf.String()) - } + reps_csv = append(reps_csv, rep) } else if c.Bool(defs.OptionJSON) { // print json if --json is given var rep report.JSONReport @@ -180,23 +174,35 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel rep.Client = report.Client{ispInfo.RawISPInfo} rep.Client.Readme = "" - - if b, err := json.Marshal(&rep); err != nil { - log.Errorf("Error generating JSON report: %s", err) - } else { - log.Warnf("%s", b) - } + + reps_json = append(reps_json,rep) } } else { log.Infof("Selected server %s (%s) is not responding at the moment, try again later", currentServer.Name, u.Hostname()) } - // add a new line after each test if testing multiple servers - if len(servers) > 1 { + //add a new line after each test if testing multiple servers + if ( len(servers) > 1 && !silent){ log.Warn() } } + // check for --csv or --json. the program prioritize the --csv before the --json. this is the same behavior as speedtest-cli + if c.Bool(defs.OptionCSV) { + var buf bytes.Buffer + if err := gocsv.MarshalWithoutHeaders(&reps_csv, &buf); err != nil { + log.Errorf("Error generating CSV report: %s", err) + } else { + log.Warn(buf.String()) + } + } else if c.Bool(defs.OptionJSON) { + if b, err := json.Marshal(&reps_json); err != nil { + log.Errorf("Error generating JSON report: %s", err) + } else { + log.Warnf("%s", b) + } + } + return nil } From 8e95ecefd7ad008cee53d7617805632d3d0625d7 Mon Sep 17 00:00:00 2001 From: Mka Madlavana Date: Mon, 5 Jul 2021 08:03:18 +0200 Subject: [PATCH 44/69] send --json and --csv results to stdout and logs to stderr (#39) --- main.go | 2 +- speedtest/helper.go | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index c467b2f..fc4f23a 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,7 @@ func init() { // warn level is for suppress modes // error level is for errors - log.SetOutput(os.Stdout) + log.SetOutput(os.Stderr) log.SetFormatter(formatter) log.SetLevel(log.InfoLevel) } diff --git a/speedtest/helper.go b/speedtest/helper.go index fa8a408..0aa5030 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -8,6 +8,7 @@ import ( "math" "mime/multipart" "net/http" + "os" "strconv" "strings" "time" @@ -193,13 +194,13 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if err := gocsv.MarshalWithoutHeaders(&reps_csv, &buf); err != nil { log.Errorf("Error generating CSV report: %s", err) } else { - log.Warn(buf.String()) + os.Stdout.WriteString(buf.String()) } } else if c.Bool(defs.OptionJSON) { if b, err := json.Marshal(&reps_json); err != nil { log.Errorf("Error generating JSON report: %s", err) } else { - log.Warnf("%s", b) + os.Stdout.Write(b[:]) } } From df77b3ee21b708f82a07c05fcbff990371e856be Mon Sep 17 00:00:00 2001 From: Dries Michiels <32487486+driesmp@users.noreply.github.com> Date: Tue, 18 Jan 2022 10:36:48 +0100 Subject: [PATCH 45/69] Use full link for the module directive in go.mod (#20) --- go.mod | 2 +- main.go | 4 ++-- report/json.go | 2 +- speedtest/helper.go | 4 ++-- speedtest/speedtest.go | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index ddc99a7..7cfa843 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module librespeed-cli +module github.com/librespeed/speedtest-cli go 1.14 diff --git a/main.go b/main.go index fc4f23a..97609cb 100644 --- a/main.go +++ b/main.go @@ -6,8 +6,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "librespeed-cli/defs" - "librespeed-cli/speedtest" + "github.com/librespeed/speedtest-cli/defs" + "github.com/librespeed/speedtest-cli/speedtest" ) // init sets up the essential bits on start up diff --git a/report/json.go b/report/json.go index a8e7dd7..fee05b3 100644 --- a/report/json.go +++ b/report/json.go @@ -3,7 +3,7 @@ package report import ( "time" - "librespeed-cli/defs" + "github.com/librespeed/speedtest-cli/defs" ) // JSONReport represents the output data fields in a JSON file diff --git a/speedtest/helper.go b/speedtest/helper.go index 0aa5030..27ecdf6 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -18,8 +18,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "librespeed-cli/defs" - "librespeed-cli/report" + "github.com/librespeed/speedtest-cli/defs" + "github.com/librespeed/speedtest-cli/report" ) const ( diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index e4fbfbb..94a5134 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -19,8 +19,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" - "librespeed-cli/defs" - "librespeed-cli/report" + "github.com/librespeed/speedtest-cli/defs" + "github.com/librespeed/speedtest-cli/report" ) const ( From c2af01baf5e0549957709b44d347693c07244485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6nning?= Date: Thu, 27 Jan 2022 12:26:47 +0100 Subject: [PATCH 46/69] Update Readme (#46) * Update Readme main.go Formatting README.md Formatting and update of Parameters added in the meantime. --no-icmp, --local-json, --duration, --chunks, --upload-size, --skip-cert-verify * Update README.md syntax --- README.md | 19 +++++++++++++++---- main.go | 6 +++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7fe14a8..1654722 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ GLOBAL OPTIONS: --ipv6, -6 Force IPv6 only (default: false) --no-download Do not perform download test (default: false) --no-upload Do not perform upload test (default: false) + --no-icmp Do not use ICMP ping. ICMP doesn't work well under Linux + at this moment, so you might want to disable it (default: false) --concurrent value Concurrent HTTP requests being made (default: 3) --bytes Display values in bytes instead of bits. Does not affect the image generated by --share, nor output from @@ -126,27 +128,32 @@ GLOBAL OPTIONS: --share Generate and provide a URL to the LibreSpeed.org share results image, not displayed with --csv (default: false) --simple Suppress verbose output, only show basic information - (default: false) + (default: false) --csv Suppress verbose output, only show basic information in CSV format. Speeds listed in bit/s and not affected by --bytes - (default: false) + (default: false) --csv-delimiter CSV_DELIMITER Single character delimiter (CSV_DELIMITER) to use in CSV output. (default: ",") --csv-header Print CSV headers (default: false) --json Suppress verbose output, only show basic information in JSON format. Speeds listed in bit/s and not - affected by --bytes (default: false) + affected by --bytes (default: false) --list Display a list of LibreSpeed.org servers (default: false) --server SERVER Specify a SERVER ID to test against. Can be supplied multiple times. Cannot be used with --exclude --exclude EXCLUDE EXCLUDE a server from selection. Can be supplied multiple times. Cannot be used with --server --server-json value Use an alternative server list from remote JSON file - --local-json value Use an alternative server list from local JSON file + --local-json value Use an alternative server list from local JSON file, + or read from stdin with "--local-json -". --source SOURCE SOURCE IP address to bind to --timeout TIMEOUT HTTP TIMEOUT in seconds. (default: 15) + --duration value Upload and download test duration in seconds (default: 15) + --chunks value Chunks to download from server, chunk size depends on server configuration (default: 100) + --upload-size value Size of payload being uploaded in KiB (default: 1024) --secure Use HTTPS instead of HTTP when communicating with LibreSpeed.org operated servers (default: false) + --skip-cert-verify Skip verifying SSL certificate for HTTPS connections (self-signed certs) (default: false) --no-pre-allocate Do not pre allocate upload data. Pre allocation is enabled by default to improve upload performance. To support systems with insufficient memory, use this @@ -190,6 +197,10 @@ locally via `--local-json`). The format is as below: ] ``` +The `--local-json` option can also read from `stdin`: + +`echo '[{"id": 1,"name": "a","server": "https://speedtest.example.com/","dlURL": "garbage.php","ulURL": "empty.php","pingURL": "empty.php","getIpURL": "getIP.php"}]' | librespeed-cli --local-json - ` + As you can see in the example, all servers have their schemes defined. In case of undefined scheme (e.g. `//example.com`), `librespeed-cli` will use `http` by default, or `https` when the `--secure` option is enabled. diff --git a/main.go b/main.go index 97609cb..a60b437 100644 --- a/main.go +++ b/main.go @@ -59,7 +59,7 @@ func main() { &cli.BoolFlag{ Name: defs.OptionNoICMP, Usage: "Do not use ICMP ping. ICMP doesn't work well under Linux\n" + - "at this moment, so you might want to disable it", + "\tat this moment, so you might want to disable it", }, &cli.IntFlag{ Name: defs.OptionConcurrent, @@ -110,7 +110,7 @@ func main() { Name: defs.OptionJSON, Usage: "Suppress verbose output, only show basic information\n" + "\tin JSON format. Speeds listed in bit/s and not\n" + - "\t affected by --bytes", + "\taffected by --bytes", }, &cli.BoolFlag{ Name: defs.OptionList, @@ -141,7 +141,7 @@ func main() { }, &cli.IntFlag{ Name: defs.OptionTimeout, - Usage: "HTTP `TIMEOUT` in seconds", + Usage: "HTTP `TIMEOUT` in seconds.", Value: 15, }, &cli.IntFlag{ From 954e973203c6068e8d0a45ae86baaa356d508f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6nning?= Date: Fri, 8 Jul 2022 18:43:19 +0200 Subject: [PATCH 47/69] Decimal places at jitter and ping. (#48) * Update README.md ups * stdout for --csv-header and --version Changed output type to stdout for --version and --csv-header. Addition to "send --json and --csv results to stdout and logs to stderr #39" * decimal places at jitter and ping better values with --share The browser version doesn't really seem to use decimal places at ping but this limits/extended ping and jitter to .2 decimal places at --csv / --json and stdout. this prevent 1.0909090909090908 ping times within csv and json and extend those values in rest of the data. The ping value could be adjusted to .0 to match the web version but this way the values are more accurate. +1 for the cli. * Update README.md Formatting adjusted --- README.md | 14 +++++++------- speedtest/helper.go | 20 ++++++++++---------- speedtest/speedtest.go | 3 ++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1654722..8228c50 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ For Linux users, you can use either the archive from golang.org, or install from ```shell script # pacman -S go ``` - + 2. Then, clone the repository: ```shell script @@ -59,10 +59,10 @@ can now proceed to build `librespeed-cli` with the build script: If you want to build for another operating system or system architecture, use the `GOOS` and `GOARCH` environment variables. Run `go tool dist list` to get a list of possible combinations of `GOOS` and `GOARCH`. - + Note: Technically, the CLI can be compiled with older Go versions that support Go modules, with `GO111MODULE=on` set. If you're compiling with an older Go runtime, you might have to change the Go version in `go.mod`. - + ```shell script # Let's say we're building for 64-bit Windows on Linux $ GOOS=windows GOARCH=amd64 ./build.sh @@ -74,7 +74,7 @@ can now proceed to build `librespeed-cli` with the build script: $ ls out librespeed-cli-windows-amd64.exe ``` - + 5. Now you can use the `librespeed-cli` and test your Internet speed! ## Install from AUR @@ -145,7 +145,7 @@ GLOBAL OPTIONS: multiple times. Cannot be used with --server --server-json value Use an alternative server list from remote JSON file --local-json value Use an alternative server list from local JSON file, - or read from stdin with "--local-json -". + or read from stdin with "--local-json -". --source SOURCE SOURCE IP address to bind to --timeout TIMEOUT HTTP TIMEOUT in seconds. (default: 15) --duration value Upload and download test duration in seconds (default: 15) @@ -153,7 +153,7 @@ GLOBAL OPTIONS: --upload-size value Size of payload being uploaded in KiB (default: 1024) --secure Use HTTPS instead of HTTP when communicating with LibreSpeed.org operated servers (default: false) - --skip-cert-verify Skip verifying SSL certificate for HTTPS connections (self-signed certs) (default: false) + --skip-cert-verify Skip verifying SSL certificate for HTTPS connections (self-signed certs) (default: false) --no-pre-allocate Do not pre allocate upload data. Pre allocation is enabled by default to improve upload performance. To support systems with insufficient memory, use this @@ -205,7 +205,7 @@ As you can see in the example, all servers have their schemes defined. In case o `librespeed-cli` will use `http` by default, or `https` when the `--secure` option is enabled. ## Use a custom telemetry server -By default, the telemetry result will be sent to `librespeed.org`. You can also customize your telemetry settings +By default, the telemetry result will be sent to `librespeed.org`. You can also customize your telemetry settings via the `--telemetry` prefixed options. In order to load a custom telemetry endpoint configuration, you'll have to use the `--telemetry-json` option to specify a local JSON file containing the configuration bits. The format is as below: diff --git a/speedtest/helper.go b/speedtest/helper.go index 27ecdf6..ddc9bc1 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -79,7 +79,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel } if pb != nil { - pb.FinalMSG = fmt.Sprintf("Ping: %.0f ms\tJitter: %.0f ms\n", p, jitter) + pb.FinalMSG = fmt.Sprintf("Ping: %.2f ms\tJitter: %.2f ms\n", p, jitter) pb.Stop() } @@ -117,9 +117,9 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel if c.Bool(defs.OptionSimple) { if c.Bool(defs.OptionBytes) { useMebi := c.Bool(defs.OptionMebiBytes) - log.Warnf("Ping:\t%.0f ms\tJitter:\t%.0f ms\nDownload rate:\t%s\nUpload rate:\t%s", p, jitter, humanizeMbps(downloadValue, useMebi), humanizeMbps(uploadValue, useMebi)) + log.Warnf("Ping:\t%.2f ms\tJitter:\t%.2f ms\nDownload rate:\t%s\nUpload rate:\t%s", p, jitter, humanizeMbps(downloadValue, useMebi), humanizeMbps(uploadValue, useMebi)) } else { - log.Warnf("Ping:\t%.0f ms\tJitter:\t%.0f ms\nDownload rate:\t%.2f Mbps\nUpload rate:\t%.2f Mbps", p, jitter, downloadValue, uploadValue) + log.Warnf("Ping:\t%.2f ms\tJitter:\t%.2f ms\nDownload rate:\t%.2f Mbps\nUpload rate:\t%.2f Mbps", p, jitter, downloadValue, uploadValue) } } @@ -149,7 +149,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel rep.Name = currentServer.Name rep.Address = u.String() - rep.Ping = p + rep.Ping = math.Round(p*100) / 100 rep.Jitter = math.Round(jitter*100) / 100 rep.Download = math.Round(downloadValue*100) / 100 rep.Upload = math.Round(uploadValue*100) / 100 @@ -162,7 +162,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel var rep report.JSONReport rep.Timestamp = time.Now() - rep.Ping = p + rep.Ping = math.Round(p*100) / 100 rep.Jitter = math.Round(jitter*100) / 100 rep.Download = math.Round(downloadValue*100) / 100 rep.Upload = math.Round(uploadValue*100) / 100 @@ -175,15 +175,15 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel rep.Client = report.Client{ispInfo.RawISPInfo} rep.Client.Readme = "" - - reps_json = append(reps_json,rep) + + reps_json = append(reps_json, rep) } } else { log.Infof("Selected server %s (%s) is not responding at the moment, try again later", currentServer.Name, u.Hostname()) } //add a new line after each test if testing multiple servers - if ( len(servers) > 1 && !silent){ + if len(servers) > 1 && !silent { log.Warn() } } @@ -240,7 +240,7 @@ func sendTelemetry(telemetryServer defs.TelemetryServer, ispInfo *defs.GetIPResu if fPing, err := wr.CreateFormField("ping"); err != nil { log.Debugf("Error creating form field: %s", err) return "", err - } else if _, err = fPing.Write([]byte(strconv.Itoa(int(pingVal)))); err != nil { + } else if _, err = fPing.Write([]byte(strconv.FormatFloat(pingVal, 'f', 2, 64))); err != nil { log.Debugf("Error writing form field: %s", err) return "", err } @@ -248,7 +248,7 @@ func sendTelemetry(telemetryServer defs.TelemetryServer, ispInfo *defs.GetIPResu if fJitter, err := wr.CreateFormField("jitter"); err != nil { log.Debugf("Error creating form field: %s", err) return "", err - } else if _, err = fJitter.Write([]byte(strconv.Itoa(int(jitter)))); err != nil { + } else if _, err = fJitter.Write([]byte(strconv.FormatFloat(jitter, 'f', 2, 64))); err != nil { log.Debugf("Error writing form field: %s", err) return "", err } diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 94a5134..159ef97 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -64,6 +64,7 @@ func SpeedTest(c *cli.Context) error { // print version if c.Bool(defs.OptionVersion) { + log.SetOutput(os.Stdout) log.Warnf("%s %s (built on %s)", defs.ProgName, defs.ProgVersion, defs.BuildDate) log.Warn("https://github.com/librespeed/speedtest-cli") log.Warn("Licensed under GNU Lesser General Public License v3.0") @@ -80,7 +81,7 @@ func SpeedTest(c *cli.Context) error { if c.Bool(defs.OptionCSVHeader) { var rep []report.CSVReport b, _ := gocsv.MarshalBytes(&rep) - log.Warnf("%s", b) + os.Stdout.WriteString(string(b)) return nil } From c996e515b18a783be6b988fe17eb587122b78e49 Mon Sep 17 00:00:00 2001 From: Daniel Brennand <52419383+dbrennand@users.noreply.github.com> Date: Fri, 8 Jul 2022 17:43:44 +0100 Subject: [PATCH 48/69] Feat/dockerfile (#47) * feat: Add dockerfile to run librespeed-cli in a container. * docs: Instructions to build and run container. --- README.md | 20 ++++++++++++++++++++ dockerfile | 17 +++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 dockerfile diff --git a/README.md b/README.md index 8228c50..816c1cf 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,26 @@ $ makepkg -si See the [librespeed-cli Homebrew tap](https://github.com/librespeed/homebrew-tap#setup). +## Container Image + +You can run `librespeed-cli` in a container. + +1. Build the container image: + + ```shell script + docker build -t librespeed-cli:latest . + ``` + +2. Run the container: + + ```shell script + docker run --rm --name librespeed-cli librespeed-cli:latest + # With options + docker run --rm --name librespeed-cli librespeed-cli:latest --telemetry-level disabled --no-upload + # To avoid "Failed to ping target host: socket: permission denied" errors when using --verbose + docker run --rm --name librespeed-cli --sysctl net.ipv4.ping_group_range="0 2147483647" librespeed-cli:latest --verbose + ``` + ## Usage You can see the full list of supported options with `librespeed-cli -h`: diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..11ae38d --- /dev/null +++ b/dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.17.7-buster as builder + +# Set working directory +WORKDIR /usr/src/librespeed-cli + +# Copy librespeed-cli +COPY . . + +# Build librespeed-cli +RUN ./build.sh + +FROM golang:1.17.7-buster + +# Copy librespeed-cli binary +COPY --from=builder /usr/src/librespeed-cli/out/librespeed-cli* /usr/src/librespeed-cli/librespeed-cli + +ENTRYPOINT ["/usr/src/librespeed-cli/librespeed-cli"] From af2908a51dbb66940d42d10282024ada424e1229 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Sat, 9 Jul 2022 00:50:40 +0800 Subject: [PATCH 49/69] goreleaser: don't upx compress Linux MIPS binaries --- .goreleaser.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 3b347f3..86ea623 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -21,17 +21,10 @@ builds: - amd64 - arm - arm64 - - mips - - mipsle - - mips64 - - mips64le goarm: - 5 - 6 - 7 - gomips: - - hardfloat - - softfloat ignore: - goos: darwin goarch: 386 @@ -48,13 +41,27 @@ builds: ldflags: - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" goos: + - linux - windows - darwin goarch: - 386 - amd64 - arm64 + - mips + - mipsle + - mips64 + - mips64le + gomips: + - hardfloat + - softfloat ignore: + - goos: linux + goarch: 386 + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 - goos: darwin goarch: 386 - goos: darwin From 0f908e806c04c300bcaf14304dc4c3b3ce8e6e06 Mon Sep 17 00:00:00 2001 From: tech189 Date: Thu, 21 Jul 2022 15:22:45 +0100 Subject: [PATCH 50/69] Add Windows installation options to README (#54) --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 816c1cf..c9f7dff 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![LibreSpeed Logo](https://github.com/librespeed/speedtest/blob/master/.logo/logo3.png?raw=true) # LibreSpeed command line tool -Don't have a GUI but wants to use LibreSpeed servers to test your Internet speed? 🚀 +Don't have a GUI but want to use LibreSpeed servers to test your Internet speed? 🚀 `librespeed-cli` comes to rescue! @@ -97,6 +97,20 @@ $ makepkg -si See the [librespeed-cli Homebrew tap](https://github.com/librespeed/homebrew-tap#setup). +## Install on Windows + +If you have either [Scoop](https://scoop.sh/) or [Chocolatey](https://chocolatey.org/) installed you can use one of the following commands: + +- Scoop (ensure you have the `extras` bucket added): + ``` + > scoop install librespeed-cli + ``` + +- Chocolatey: + ``` + > choco install librespeed-cli + ``` + ## Container Image You can run `librespeed-cli` in a container. From 092760f344039e39b6ef8b91c3917a6c1ca1fd53 Mon Sep 17 00:00:00 2001 From: Mka Madlavana Date: Sat, 23 Jul 2022 14:21:18 +0200 Subject: [PATCH 51/69] throw an error if the specified --server is not in server list (#56) --- speedtest/speedtest.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 159ef97..8a68092 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -454,6 +454,10 @@ func preprocessServers(servers []defs.Server, forceHTTPS bool, excludes, specifi ret = append(ret, server) } } + if len(ret) == 0 { + error_message := fmt.Sprintf("specified server(s) not found: %v", specific) + return nil, errors.New(error_message) + } return ret, nil } } From 24b7826d78456728c5ab215d79ebd6d08fa4506e Mon Sep 17 00:00:00 2001 From: Mkhanyisi Madlavana Date: Tue, 10 Sep 2024 16:51:43 +0200 Subject: [PATCH 52/69] make `--version` to report the binary version again (#58) --- build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index ca51d85..b06797a 100755 --- a/build.sh +++ b/build.sh @@ -10,9 +10,10 @@ CURRENT_DIR=$(pwd) OUT_DIR=${CURRENT_DIR}/out PROGNAME="librespeed-cli" +DEFS_PATH="github.com/librespeed/speedtest-cli" BINARY=${PROGNAME}-$(go env GOOS)-$(go env GOARCH) BUILD_DATE=$(date -u "+%Y-%m-%d %H:%M:%S %Z") -LDFLAGS="-w -s -X \"librespeed-cli/defs.ProgName=${PROGNAME}\" -X \"librespeed-cli/defs.ProgVersion=${PROGVER}\" -X \"librespeed-cli/defs.BuildDate=${BUILD_DATE}\"" +LDFLAGS="-w -s -X \"${DEFS_PATH}/defs.ProgName=${PROGNAME}\" -X \"${DEFS_PATH}/defs.ProgVersion=${PROGVER}\" -X \"${DEFS_PATH}/defs.BuildDate=${BUILD_DATE}\"" if [[ -n "${GOARM}" ]] && [[ "${GOARM}" -gt 0 ]]; then BINARY=${BINARY}v${GOARM} From 6059f16e57ea9c9cb89a5ee46fa1c9065e316277 Mon Sep 17 00:00:00 2001 From: czechbol Date: Tue, 10 Sep 2024 16:51:57 +0200 Subject: [PATCH 53/69] Updated dependencies (#62) * updated dependencies * fixed goreleaser config errors * formatted goreleaser config --- .goreleaser.yml | 130 ++++++++++++++++++++++++------------------------ go.mod | 21 ++++---- go.sum | 68 +++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 74 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 86ea623..44b08eb 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,79 +1,81 @@ -project_name: 'librespeed-cli' +project_name: "librespeed-cli" #dist: ./out before: hooks: - go mod download builds: -- main: ./main.go - id: upx - env: - - CGO_ENABLED=0 - flags: - - -trimpath - ldflags: - - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" - goos: - - linux - - darwin - - freebsd - goarch: - - 386 - - amd64 - - arm - - arm64 - goarm: - - 5 - - 6 - - 7 - ignore: - - goos: darwin - goarch: 386 - - goos: darwin - goarch: arm64 - hooks: - post: ./upx.sh -9 "{{ .Path }}" -- main: ./main.go - id: no-upx - env: - - CGO_ENABLED=0 - flags: - - -trimpath - ldflags: - - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" - goos: - - linux - - windows - - darwin - goarch: - - 386 - - amd64 - - arm64 - - mips - - mipsle - - mips64 - - mips64le - gomips: - - hardfloat - - softfloat - ignore: - - goos: linux - goarch: 386 - - goos: linux - goarch: amd64 - - goos: linux - goarch: arm64 - - goos: darwin - goarch: 386 - - goos: darwin - goarch: amd64 + - main: ./main.go + id: upx + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" + goos: + - linux + - darwin + - freebsd + goarch: + - "386" + - amd64 + - arm + - arm64 + goarm: + - "5" + - "6" + - "7" + ignore: + - goos: darwin + goarch: "386" + - goos: darwin + goarch: arm64 + hooks: + post: + - ./upx.sh -9 "{{ .Path }}" + - main: ./main.go + id: no-upx + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -w -s -X "librespeed-cli/defs.ProgName={{ .ProjectName }}" -X "librespeed-cli/defs.ProgVersion=v{{ .Version }}" -X "librespeed-cli/defs.BuildDate={{ .Date }}" + goos: + - linux + - windows + - darwin + goarch: + - "386" + - amd64 + - arm64 + - mips + - mipsle + - mips64 + - mips64le + gomips: + - hardfloat + - softfloat + ignore: + - goos: linux + goarch: "386" + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 + - goos: darwin + goarch: "386" + - goos: darwin + goarch: amd64 archives: - format_overrides: - goos: windows format: zip files: - LICENSE + rlcp: true checksum: - name_template: 'checksums.txt' + name_template: "checksums.txt" changelog: skip: false sort: asc diff --git a/go.mod b/go.mod index 7cfa843..fb1f268 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,16 @@ module github.com/librespeed/speedtest-cli go 1.14 require ( - github.com/briandowns/spinner v1.12.0 - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/fatih/color v1.10.0 // indirect - github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741 - github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d + github.com/briandowns/spinner v1.23.0 + github.com/fatih/color v1.15.0 // indirect + github.com/go-ping/ping v1.1.0 + github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 + github.com/google/uuid v1.3.0 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sirupsen/logrus v1.8.1 - github.com/stretchr/testify v1.3.0 // indirect - github.com/urfave/cli/v2 v2.3.0 - golang.org/x/net v0.0.0-20210421230115-4e50805a0758 // indirect - golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/sirupsen/logrus v1.9.0 + github.com/urfave/cli/v2 v2.25.1 + golang.org/x/net v0.9.0 // indirect + gopkg.in/yaml.v2 v2.2.3 // indirect ) diff --git a/go.sum b/go.sum index cb424de..d8b8382 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,45 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= +github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= +github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741 h1:b0sLP++Tsle+s57tqg5sUk1/OQsC6yMCciVeqNzOcwU= github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= +github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= +github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d h1:r3mStZSyjKhEcgbJ5xtv7kT5PZw/tDiFBTMgQx2qsXE= github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= +github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -28,18 +48,41 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= +github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= +github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -48,12 +91,37 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 h1:qyN5bV+96OX8pL78eXDuz6YlDPzCYgdW74H5yE9BoSU= golang.org/x/sys v0.0.0-20210421221651-33663a62ff08/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 6103965f4480bba8d8f4177470540464a6f7cb04 Mon Sep 17 00:00:00 2001 From: czechbol Date: Tue, 10 Sep 2024 16:52:29 +0200 Subject: [PATCH 54/69] Reduced container image size (#64) * reduced container image size * added upx to builder --- dockerfile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/dockerfile b/dockerfile index 11ae38d..944de29 100644 --- a/dockerfile +++ b/dockerfile @@ -1,4 +1,6 @@ -FROM golang:1.17.7-buster as builder +FROM golang:1.20.3-alpine as builder + +RUN apk add --no-cache bash upx # Set working directory WORKDIR /usr/src/librespeed-cli @@ -9,9 +11,9 @@ COPY . . # Build librespeed-cli RUN ./build.sh -FROM golang:1.17.7-buster +FROM alpine:3.17 # Copy librespeed-cli binary -COPY --from=builder /usr/src/librespeed-cli/out/librespeed-cli* /usr/src/librespeed-cli/librespeed-cli +COPY --from=builder /usr/src/librespeed-cli/out/librespeed-cli* /bin/librespeed-cli -ENTRYPOINT ["/usr/src/librespeed-cli/librespeed-cli"] +CMD ["/bin/librespeed-cli"] From 11183cbf98d1c5ea90b52c3257cd066c63c8c1bb Mon Sep 17 00:00:00 2001 From: Luca Magnabosco Date: Tue, 10 Sep 2024 16:52:45 +0200 Subject: [PATCH 55/69] Add interface option (#65) * speedtest: move source bound Dialer setup to newDialerAddressBound(). * Add "--interface" option. --- README.md | 5 +- defs/options.go | 1 + main.go | 4 ++ speedtest/helper.go | 4 +- speedtest/speedtest.go | 127 +++++++++++++++++++++++--------------- speedtest/util_linux.go | 32 ++++++++++ speedtest/util_windows.go | 10 +++ 7 files changed, 129 insertions(+), 54 deletions(-) create mode 100644 speedtest/util_linux.go create mode 100644 speedtest/util_windows.go diff --git a/README.md b/README.md index c9f7dff..db74ca0 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,10 @@ GLOBAL OPTIONS: --server-json value Use an alternative server list from remote JSON file --local-json value Use an alternative server list from local JSON file, or read from stdin with "--local-json -". - --source SOURCE SOURCE IP address to bind to + --source SOURCE SOURCE IP address to bind to. Incompatible with --interface. + --interface INTERFACE The name of the network interface to bind to. Example: "enp0s3". + Not supported on Windows and incompatible with --source. + Implies --no-icmp. --timeout TIMEOUT HTTP TIMEOUT in seconds. (default: 15) --duration value Upload and download test duration in seconds (default: 15) --chunks value Chunks to download from server, chunk size depends on server configuration (default: 100) diff --git a/defs/options.go b/defs/options.go index 255a5b1..bc7e506 100644 --- a/defs/options.go +++ b/defs/options.go @@ -24,6 +24,7 @@ const ( OptionExclude = "exclude" OptionServerJSON = "server-json" OptionSource = "source" + OptionInterface = "interface" OptionTimeout = "timeout" OptionChunks = "chunks" OptionUploadSize = "upload-size" diff --git a/main.go b/main.go index a60b437..5cb6643 100644 --- a/main.go +++ b/main.go @@ -139,6 +139,10 @@ func main() { Name: defs.OptionSource, Usage: "`SOURCE` IP address to bind to", }, + &cli.StringFlag{ + Name: defs.OptionInterface, + Usage: "network INTERFACE to bind to", + }, &cli.IntFlag{ Name: defs.OptionTimeout, Usage: "HTTP `TIMEOUT` in seconds.", diff --git a/speedtest/helper.go b/speedtest/helper.go index ddc9bc1..4d1d5d7 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -28,7 +28,7 @@ const ( ) // doSpeedTest is where the actual speed test happens -func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.TelemetryServer, network string, silent bool) error { +func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.TelemetryServer, network string, silent bool, noICMP bool) error { if serverCount := len(servers); serverCount > 1 { log.Infof("Testing against %d servers", serverCount) } @@ -70,7 +70,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel } // skip ICMP if option given - currentServer.NoICMP = c.Bool(defs.OptionNoICMP) + currentServer.NoICMP = noICMP p, jitter, err := currentServer.ICMPPingAndJitter(pingCount, c.String(defs.OptionSource), network) if err != nil { diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 8a68092..93e815f 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -74,6 +74,10 @@ func SpeedTest(c *cli.Context) error { return nil } + if c.String(defs.OptionSource) != "" && c.String(defs.OptionInterface) != "" { + return fmt.Errorf("incompatible options '%s' and '%s'", defs.OptionSource, defs.OptionInterface) + } + // set CSV delimiter gocsv.TagSeparator = c.String(defs.OptionCSVDelimiter) @@ -138,6 +142,8 @@ func SpeedTest(c *cli.Context) error { return errors.New("invalid concurrent requests setting") } + noICMP := c.Bool(defs.OptionNoICMP) + // HTTP requests timeout http.DefaultClient.Timeout = time.Duration(c.Int(defs.OptionTimeout)) * time.Second @@ -157,57 +163,48 @@ func SpeedTest(c *cli.Context) error { transport := http.DefaultTransport.(*http.Transport).Clone() transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify)} - // bind to source IP address if given, or if ipv4/ipv6 is forced - if src := c.String(defs.OptionSource); src != "" || (forceIPv4 || forceIPv6) { - var localTCPAddr *net.TCPAddr - if src != "" { - // first we parse the IP to see if it's valid - addr, err := net.ResolveIPAddr(network, src) - if err != nil { - if strings.Contains(err.Error(), "no suitable address") { - if forceIPv6 { - log.Errorf("Address %s is not a valid IPv6 address", src) - } else { - log.Errorf("Address %s is not a valid IPv4 address", src) - } - } else { - log.Errorf("Error parsing source IP: %s", err) - } - return err - } - - log.Debugf("Using %s as source IP", src) - localTCPAddr = &net.TCPAddr{IP: addr.IP} + dialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + } + // bind to source IP address if given + if src := c.String(defs.OptionSource); src != "" { + var err error + dialer, err = newDialerAddressBound(src, network) + if err != nil { + return err } - - var dialContext func(context.Context, string, string) (net.Conn, error) - defaultDialer := &net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - } - - if localTCPAddr != nil { - defaultDialer.LocalAddr = localTCPAddr - } - - switch { - case forceIPv4: - dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { - return defaultDialer.DialContext(ctx, "tcp4", address) - } - case forceIPv6: - dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { - return defaultDialer.DialContext(ctx, "tcp6", address) - } - default: - dialContext = defaultDialer.DialContext - } - - // set default HTTP client's Transport to the one that binds the source address - // this is modified from http.DefaultTransport - transport.DialContext = dialContext } + // bind to interface if given + if iface := c.String(defs.OptionInterface); iface != "" { + var err error + dialer, err = newDialerInterfaceBound(iface) + if err != nil { + return err + } + // ICMP ping does not support interface binding. + noICMP = true + } + + // enforce if ipv4/ipv6 is forced + var dialContext func(context.Context, string, string) (net.Conn, error) + switch { + case forceIPv4: + dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { + return dialer.DialContext(ctx, "tcp4", address) + } + case forceIPv6: + dialContext = func(ctx context.Context, network, address string) (conn net.Conn, err error) { + return dialer.DialContext(ctx, "tcp6", address) + } + default: + dialContext = dialer.DialContext + } + + // set default HTTP client's Transport to the one that binds the source address + // this is modified from http.DefaultTransport + transport.DialContext = dialContext http.DefaultClient.Transport = transport // load server list @@ -258,7 +255,7 @@ func SpeedTest(c *cli.Context) error { // if --server is given, do speed tests with all of them if len(c.IntSlice(defs.OptionServer)) > 0 { - return doSpeedTest(c, servers, telemetryServer, network, silent) + return doSpeedTest(c, servers, telemetryServer, network, silent, noICMP) } else { // else select the fastest server from the list log.Info("Selecting the fastest server based on ping") @@ -272,7 +269,7 @@ func SpeedTest(c *cli.Context) error { // spawn 10 concurrent pingers for i := 0; i < 10; i++ { - go pingWorker(jobs, results, &wg, c.String(defs.OptionSource), network, c.Bool(defs.OptionNoICMP)) + go pingWorker(jobs, results, &wg, c.String(defs.OptionSource), network, noICMP) } // send ping jobs to workers @@ -309,7 +306,7 @@ func SpeedTest(c *cli.Context) error { } // do speed test on the server - return doSpeedTest(c, []defs.Server{servers[serverIdx]}, telemetryServer, network, silent) + return doSpeedTest(c, []defs.Server{servers[serverIdx]}, telemetryServer, network, silent, noICMP) } } @@ -474,3 +471,31 @@ func contains(arr []int, val int) bool { } return false } + +func newDialerAddressBound(src string, network string) (dialer *net.Dialer, err error) { + // first we parse the IP to see if it's valid + addr, err := net.ResolveIPAddr(network, src) + if err != nil { + if strings.Contains(err.Error(), "no suitable address") { + if network == "ip6" { + log.Errorf("Address %s is not a valid IPv6 address", src) + } else { + log.Errorf("Address %s is not a valid IPv4 address", src) + } + } else { + log.Errorf("Error parsing source IP: %s", err) + } + return nil, err + } + + log.Debugf("Using %s as source IP", src) + localTCPAddr := &net.TCPAddr{IP: addr.IP} + + defaultDialer := &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + } + + defaultDialer.LocalAddr = localTCPAddr + return defaultDialer, nil +} diff --git a/speedtest/util_linux.go b/speedtest/util_linux.go new file mode 100644 index 0000000..e2a0a64 --- /dev/null +++ b/speedtest/util_linux.go @@ -0,0 +1,32 @@ +package speedtest + +import ( + "net" + "syscall" + "time" + + "golang.org/x/sys/unix" +) + +func newDialerInterfaceBound(iface string) (dialer *net.Dialer, err error) { + // In linux there is the socket option SO_BINDTODEVICE. + // Therefore we can really bind the socket to the device instead of binding to the address that + // would be affected by the default routes. + control := func(network, address string, c syscall.RawConn) error { + var errSock error + err := c.Control((func(fd uintptr) { + errSock = unix.BindToDevice(int(fd), iface) + })) + if err != nil { + return err + } + return errSock + } + + dialer = &net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + Control: control, + } + return dialer, nil +} diff --git a/speedtest/util_windows.go b/speedtest/util_windows.go new file mode 100644 index 0000000..c4a0cd0 --- /dev/null +++ b/speedtest/util_windows.go @@ -0,0 +1,10 @@ +package speedtest + +import ( + "fmt" + "net" +) + +func newDialerInterfaceBound(iface string) (dialer *net.Dialer, err error) { + return nil, fmt.Errorf("cannot bound to interface on Windows") +} From e5c131fe629cd99cd2b352924f18184473368550 Mon Sep 17 00:00:00 2001 From: Salim B Date: Tue, 10 Sep 2024 16:53:16 +0200 Subject: [PATCH 56/69] Fix code-highlighting (#68) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db74ca0..a0ce7c6 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ You can run `librespeed-cli` in a container. You can see the full list of supported options with `librespeed-cli -h`: -```shell script +``` $ librespeed-cli -h NAME: librespeed-cli - Test your Internet speed with LibreSpeed 🚀 From 67adaa29568b337b305d8cab515a8c01ce00fcf4 Mon Sep 17 00:00:00 2001 From: Mkhanyisi Madlavana Date: Tue, 10 Sep 2024 16:53:33 +0200 Subject: [PATCH 57/69] Fix integer overflow issues at high speeds (#73) --- defs/bytes_counter.go | 8 ++++---- defs/server.go | 4 ++-- report/json.go | 4 ++-- speedtest/helper.go | 13 ++++++------- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/defs/bytes_counter.go b/defs/bytes_counter.go index 1553aff..64c155b 100644 --- a/defs/bytes_counter.go +++ b/defs/bytes_counter.go @@ -14,7 +14,7 @@ import ( type BytesCounter struct { start time.Time pos int - total int + total uint64 payload []byte reader io.ReadSeeker mebi bool @@ -33,7 +33,7 @@ func NewCounter() *BytesCounter { func (c *BytesCounter) Write(p []byte) (int, error) { n := len(p) c.lock.Lock() - c.total += n + c.total += uint64(n) c.lock.Unlock() return n, nil @@ -43,7 +43,7 @@ func (c *BytesCounter) Write(p []byte) (int, error) { func (c *BytesCounter) Read(p []byte) (int, error) { n, err := c.reader.Read(p) c.lock.Lock() - c.total += n + c.total += uint64(n) c.pos += n if c.pos == c.uploadSize { c.resetReader() @@ -116,7 +116,7 @@ func (c *BytesCounter) Start() { } // Total returns the total bytes read/written -func (c *BytesCounter) Total() int { +func (c *BytesCounter) Total() uint64 { return c.total } diff --git a/defs/server.go b/defs/server.go index 370b826..ed2ffad 100644 --- a/defs/server.go +++ b/defs/server.go @@ -188,7 +188,7 @@ func (s *Server) PingAndJitter(count int) (float64, float64, error) { } // Download performs the actual download test -func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int, chunks int, duration time.Duration) (float64, int, error) { +func (s *Server) Download(silent bool, useBytes, useMebi bool, requests int, chunks int, duration time.Duration) (float64, uint64, error) { t := time.Now() defer func() { s.TLog.Logf("Download took %s", time.Now().Sub(t).String()) @@ -280,7 +280,7 @@ Loop: } // Upload performs the actual upload test -func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int, uploadSize int, duration time.Duration) (float64, int, error) { +func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests int, uploadSize int, duration time.Duration) (float64, uint64, error) { t := time.Now() defer func() { s.TLog.Logf("Upload took %s", time.Now().Sub(t).String()) diff --git a/report/json.go b/report/json.go index fee05b3..d399aed 100644 --- a/report/json.go +++ b/report/json.go @@ -11,8 +11,8 @@ type JSONReport struct { Timestamp time.Time `json:"timestamp"` Server Server `json:"server"` Client Client `json:"client"` - BytesSent int `json:"bytes_sent"` - BytesReceived int `json:"bytes_received"` + BytesSent uint64 `json:"bytes_sent"` + BytesReceived uint64 `json:"bytes_received"` Ping float64 `json:"ping"` Jitter float64 `json:"jitter"` Upload float64 `json:"upload"` diff --git a/speedtest/helper.go b/speedtest/helper.go index 4d1d5d7..1be6203 100644 --- a/speedtest/helper.go +++ b/speedtest/helper.go @@ -15,11 +15,10 @@ import ( "github.com/briandowns/spinner" "github.com/gocarina/gocsv" - log "github.com/sirupsen/logrus" - "github.com/urfave/cli/v2" - "github.com/librespeed/speedtest-cli/defs" "github.com/librespeed/speedtest-cli/report" + log "github.com/sirupsen/logrus" +"github.com/urfave/cli/v2" ) const ( @@ -85,7 +84,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel // get download value var downloadValue float64 - var bytesRead int + var bytesRead uint64 if c.Bool(defs.OptionNoDownload) { log.Info("Download test is disabled") } else { @@ -95,12 +94,12 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel return err } downloadValue = download - bytesRead = br + bytesRead = uint64(br) } // get upload value var uploadValue float64 - var bytesWritten int + var bytesWritten uint64 if c.Bool(defs.OptionNoUpload) { log.Info("Upload test is disabled") } else { @@ -110,7 +109,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, telemetryServer defs.Tel return err } uploadValue = upload - bytesWritten = bw + bytesWritten = uint64(bw) } // print result if --simple is given From b1daf1c451ca40863a7b3dccc70e973683ccc274 Mon Sep 17 00:00:00 2001 From: Mkhanyisi Madlavana Date: Tue, 10 Sep 2024 16:53:48 +0200 Subject: [PATCH 58/69] add `--ca-cert` option (#81) --- README.md | 2 ++ defs/options.go | 1 + main.go | 5 +++++ speedtest/speedtest.go | 22 ++++++++++++++++++++-- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0ce7c6..f62a89f 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,8 @@ GLOBAL OPTIONS: --upload-size value Size of payload being uploaded in KiB (default: 1024) --secure Use HTTPS instead of HTTP when communicating with LibreSpeed.org operated servers (default: false) + --ca-cert value Use the specified CA certificate PEM bundle file instead + of the system certificate trust store --skip-cert-verify Skip verifying SSL certificate for HTTPS connections (self-signed certs) (default: false) --no-pre-allocate Do not pre allocate upload data. Pre allocation is enabled by default to improve upload performance. To diff --git a/defs/options.go b/defs/options.go index bc7e506..01101be 100644 --- a/defs/options.go +++ b/defs/options.go @@ -30,6 +30,7 @@ const ( OptionUploadSize = "upload-size" OptionDuration = "duration" OptionSecure = "secure" + OptionCACert = "ca-cert" OptionSkipCertVerify = "skip-cert-verify" OptionNoPreAllocate = "no-pre-allocate" OptionVersion = "version" diff --git a/main.go b/main.go index 5cb6643..0213293 100644 --- a/main.go +++ b/main.go @@ -168,6 +168,11 @@ func main() { Usage: "Use HTTPS instead of HTTP when communicating with\n" + "\tLibreSpeed.org operated servers", }, + &cli.StringFlag{ + Name: defs.OptionCACert, + Usage: "Use the specified CA certificate PEM bundle file instead\n" + + "\tof the system certificate trust store", + }, &cli.BoolFlag{ Name: defs.OptionSkipCertVerify, Usage: "Skip verifying SSL certificate for HTTPS connections (self-signed certs)", diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 93e815f..d461996 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -3,6 +3,7 @@ package speedtest import ( "context" "crypto/tls" + "crypto/x509" "encoding/json" "errors" "fmt" @@ -160,8 +161,25 @@ func SpeedTest(c *cli.Context) error { network = "ip" } - transport := http.DefaultTransport.(*http.Transport).Clone() - transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify)} + transport := http.DefaultTransport.(*http.Transport).Clone() + + if caCertFileName := c.String(defs.OptionCACert); caCertFileName != "" { + caCert, err := ioutil.ReadFile(caCertFileName) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + transport.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), + RootCAs: caCertPool, + } + } else { + transport.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), + } + } dialer := &net.Dialer{ Timeout: 30 * time.Second, From 058cd387c14c42178724e17da7804845f955c38b Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 10 Sep 2024 23:06:31 +0800 Subject: [PATCH 59/69] Update goreleaser config to v2 --- .goreleaser.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 44b08eb..c2f0e63 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,3 +1,4 @@ +version: 2 project_name: "librespeed-cli" #dist: ./out before: @@ -73,11 +74,10 @@ archives: format: zip files: - LICENSE - rlcp: true checksum: name_template: "checksums.txt" changelog: - skip: false + disable: false sort: asc release: github: From d23c1b7b727657cc818f8cf596802d4f651ba00b Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 10 Sep 2024 23:09:08 +0800 Subject: [PATCH 60/69] go mod tidy to fix build --- go.mod | 4 +--- go.sum | 43 +++---------------------------------------- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/go.mod b/go.mod index fb1f268..06659e4 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 github.com/google/uuid v1.3.0 // indirect github.com/mattn/go-isatty v0.0.18 // indirect - github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/sirupsen/logrus v1.9.0 github.com/urfave/cli/v2 v2.25.1 golang.org/x/net v0.9.0 // indirect - gopkg.in/yaml.v2 v2.2.3 // indirect + golang.org/x/sys v0.7.0 ) diff --git a/go.sum b/go.sum index d8b8382..1ce4b62 100644 --- a/go.sum +++ b/go.sum @@ -1,79 +1,50 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/briandowns/spinner v1.12.0 h1:72O0PzqGJb6G3KgrcIOtL/JAGGZ5ptOMCn9cUHmqsmw= -github.com/briandowns/spinner v1.12.0/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ= github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= -github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= -github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741 h1:b0sLP++Tsle+s57tqg5sUk1/OQsC6yMCciVeqNzOcwU= -github.com/go-ping/ping v0.0.0-20210407214646-e4e642a95741/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI= github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= -github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d h1:r3mStZSyjKhEcgbJ5xtv7kT5PZw/tDiFBTMgQx2qsXE= -github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= @@ -85,16 +56,8 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210421221651-33663a62ff08 h1:qyN5bV+96OX8pL78eXDuz6YlDPzCYgdW74H5yE9BoSU= -golang.org/x/sys v0.0.0-20210421221651-33663a62ff08/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -112,7 +75,6 @@ golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= @@ -121,7 +83,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From d33e431b58774807f608f7a38bd5e5fd9cc3dfc4 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Tue, 10 Sep 2024 23:22:34 +0800 Subject: [PATCH 61/69] fix build for non-windows/linux platforms --- speedtest/{util_windows.go => util.go} | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) rename speedtest/{util_windows.go => util.go} (53%) diff --git a/speedtest/util_windows.go b/speedtest/util.go similarity index 53% rename from speedtest/util_windows.go rename to speedtest/util.go index c4a0cd0..ce04c00 100644 --- a/speedtest/util_windows.go +++ b/speedtest/util.go @@ -1,3 +1,6 @@ +//go:build !linux +// +build !linux + package speedtest import ( @@ -6,5 +9,5 @@ import ( ) func newDialerInterfaceBound(iface string) (dialer *net.Dialer, err error) { - return nil, fmt.Errorf("cannot bound to interface on Windows") + return nil, fmt.Errorf("cannot bound to interface on this platform") } From 7573b65ebc89a4cf463334dbdfab5b3edc706149 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Wed, 11 Sep 2024 17:17:37 +0800 Subject: [PATCH 62/69] Upgrade to Go 1.18 as minimum required version With dependency upgrade. Fixes issue #90 --- go.mod | 29 +++++++++++++++++--------- go.sum | 64 +++++++++++++++++++++++++--------------------------------- 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/go.mod b/go.mod index 06659e4..b5a75f0 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,25 @@ module github.com/librespeed/speedtest-cli -go 1.14 +go 1.18 require ( - github.com/briandowns/spinner v1.23.0 - github.com/fatih/color v1.15.0 // indirect + github.com/briandowns/spinner v1.23.1 github.com/go-ping/ping v1.1.0 - github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 - github.com/google/uuid v1.3.0 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/sirupsen/logrus v1.9.0 - github.com/urfave/cli/v2 v2.25.1 - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.7.0 + github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 + github.com/sirupsen/logrus v1.9.3 + github.com/urfave/cli/v2 v2.27.4 + golang.org/x/sys v0.25.0 +) + +require ( + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/fatih/color v1.17.0 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/term v0.24.0 // indirect ) diff --git a/go.sum b/go.sum index 1ce4b62..83f949f 100644 --- a/go.sum +++ b/go.sum @@ -1,90 +1,80 @@ -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= +github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650= +github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ= +github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= +github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= +github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 63c75be0fc1191b4cebd2886526780f914ac1470 Mon Sep 17 00:00:00 2001 From: Anton Kudriavtsev Date: Thu, 12 Jun 2025 12:28:34 +0300 Subject: [PATCH 63/69] Fix telemetry parsing error log (#91) --- speedtest/speedtest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index d461996..1cdda3f 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -105,7 +105,7 @@ func SpeedTest(c *cli.Context) error { return err } if err := json.Unmarshal(b, &telemetryServer); err != nil { - log.Errorf("Error parsing %s: %s", err) + log.Errorf("Error parsing %s: %s", telemetryJSON, err) return err } } From 78c9095ca9062bb8387031b2a22fb161ef99a9d3 Mon Sep 17 00:00:00 2001 From: An Date: Thu, 12 Jun 2025 17:29:06 +0800 Subject: [PATCH 64/69] add fwmark (#92) --- defs/options.go | 1 + main.go | 7 ++++++- speedtest/speedtest.go | 42 ++++++++++++++++++++++------------------- speedtest/util_linux.go | 10 ++++++++-- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/defs/options.go b/defs/options.go index 01101be..84662b5 100644 --- a/defs/options.go +++ b/defs/options.go @@ -42,4 +42,5 @@ const ( OptionTelemetryPath = "telemetry-path" OptionTelemetryShare = "telemetry-share" OptionTelemetryExtra = "telemetry-extra" + OptionFwmark = "fwmark" ) diff --git a/main.go b/main.go index 0213293..cc948cc 100644 --- a/main.go +++ b/main.go @@ -171,7 +171,7 @@ func main() { &cli.StringFlag{ Name: defs.OptionCACert, Usage: "Use the specified CA certificate PEM bundle file instead\n" + - "\tof the system certificate trust store", + "\tof the system certificate trust store", }, &cli.BoolFlag{ Name: defs.OptionSkipCertVerify, @@ -218,6 +218,11 @@ func main() { Usage: "Send a custom message along with the telemetry results.\n" + "\tImplies --" + defs.OptionShare, }, + &cli.IntFlag{ + Name: defs.OptionFwmark, + Usage: "firewall mark to set on socket.", + Value: 0, + }, }, } diff --git a/speedtest/speedtest.go b/speedtest/speedtest.go index 1cdda3f..20018ac 100644 --- a/speedtest/speedtest.go +++ b/speedtest/speedtest.go @@ -161,25 +161,25 @@ func SpeedTest(c *cli.Context) error { network = "ip" } - transport := http.DefaultTransport.(*http.Transport).Clone() + transport := http.DefaultTransport.(*http.Transport).Clone() - if caCertFileName := c.String(defs.OptionCACert); caCertFileName != "" { - caCert, err := ioutil.ReadFile(caCertFileName) - if err != nil { - log.Fatal(err) - } - caCertPool := x509.NewCertPool() - caCertPool.AppendCertsFromPEM(caCert) + if caCertFileName := c.String(defs.OptionCACert); caCertFileName != "" { + caCert, err := ioutil.ReadFile(caCertFileName) + if err != nil { + log.Fatal(err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) - transport.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), - RootCAs: caCertPool, - } - } else { - transport.TLSClientConfig = &tls.Config{ - InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), - } - } + transport.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), + RootCAs: caCertPool, + } + } else { + transport.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: c.Bool(defs.OptionSkipCertVerify), + } + } dialer := &net.Dialer{ Timeout: 30 * time.Second, @@ -195,9 +195,13 @@ func SpeedTest(c *cli.Context) error { } // bind to interface if given - if iface := c.String(defs.OptionInterface); iface != "" { + // bind to interface if given + iface := c.String(defs.OptionInterface) + fwmark := c.Int(defs.OptionFwmark) + + if iface != "" || fwmark > 0 { var err error - dialer, err = newDialerInterfaceBound(iface) + dialer, err = newDialerInterfaceOrFwmarkBound(iface, fwmark) if err != nil { return err } diff --git a/speedtest/util_linux.go b/speedtest/util_linux.go index e2a0a64..e153e87 100644 --- a/speedtest/util_linux.go +++ b/speedtest/util_linux.go @@ -8,14 +8,20 @@ import ( "golang.org/x/sys/unix" ) -func newDialerInterfaceBound(iface string) (dialer *net.Dialer, err error) { +func newDialerInterfaceOrFwmarkBound(iface string, fwmark int) (dialer *net.Dialer, err error) { // In linux there is the socket option SO_BINDTODEVICE. // Therefore we can really bind the socket to the device instead of binding to the address that // would be affected by the default routes. control := func(network, address string, c syscall.RawConn) error { var errSock error err := c.Control((func(fd uintptr) { - errSock = unix.BindToDevice(int(fd), iface) + if iface != "" { + errSock = unix.BindToDevice(int(fd), iface) + } + + if fwmark > 0 { + errSock = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, fwmark) + } })) if err != nil { return err From c9decb3fda109b0aed3bd9692ea6dec7b7a20297 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Thu, 12 Jun 2025 17:30:36 +0800 Subject: [PATCH 65/69] Enable riscv64 release (#95) --- .goreleaser.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.goreleaser.yml b/.goreleaser.yml index c2f0e63..4fabfbe 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -54,6 +54,7 @@ builds: - mipsle - mips64 - mips64le + - riscv64 gomips: - hardfloat - softfloat From 0c565b724b05c3e38bb270b6cd6bab1309989fd3 Mon Sep 17 00:00:00 2001 From: Vivek Kumar <167422483+Vivekkumar-IN@users.noreply.github.com> Date: Thu, 12 Jun 2025 15:00:49 +0530 Subject: [PATCH 66/69] Update Go version requirement to 1.18+ in README (#101) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f62a89f..d3945cf 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This is a command line interface for LibreSpeed speed test backends, written in [![asciicast](https://asciinema.org/a/J17bUAilWI3qR12JyhfGvPwu2.svg)](https://asciinema.org/a/J17bUAilWI3qR12JyhfGvPwu2) ## Requirements for compiling -- Go 1.14+ +- Go 1.18+ ## Runtime requirements - Any [Go supported platforms](https://github.com/golang/go/wiki/MinimumRequirements) From 7ed6fe234c247d13ba7dd0cb323c9926d8ee8b55 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 12 Jun 2025 17:33:06 +0800 Subject: [PATCH 67/69] fix: goreleaser archives.format_overrides.format deprecation --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 4fabfbe..a0ee28a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -72,7 +72,7 @@ builds: archives: - format_overrides: - goos: windows - format: zip + formats: ['zip'] files: - LICENSE checksum: From 95f2c8207ae62acd6806e4cc6dbe3ea588a55640 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 12 Jun 2025 17:36:59 +0800 Subject: [PATCH 68/69] fix: fix build for non-linux platform --- speedtest/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/speedtest/util.go b/speedtest/util.go index ce04c00..0a35393 100644 --- a/speedtest/util.go +++ b/speedtest/util.go @@ -8,6 +8,6 @@ import ( "net" ) -func newDialerInterfaceBound(iface string) (dialer *net.Dialer, err error) { +func newDialerInterfaceOrFwmarkBound(iface string, fwmark int) (dialer *net.Dialer, err error) { return nil, fmt.Errorf("cannot bound to interface on this platform") } From 14717ac78b0125d17e7c8d450215d3f271cb7ef3 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Thu, 12 Jun 2025 17:39:18 +0800 Subject: [PATCH 69/69] chore: update github.com/go-ping/ping dependency update due to CVE in indirect dependency golang.org/x/net --- go.mod | 14 ++++++++------ go.sum | 46 +++++++++++----------------------------------- 2 files changed, 19 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index b5a75f0..da5d4ff 100644 --- a/go.mod +++ b/go.mod @@ -1,14 +1,16 @@ module github.com/librespeed/speedtest-cli -go 1.18 +go 1.23.0 + +toolchain go1.24.2 require ( github.com/briandowns/spinner v1.23.1 - github.com/go-ping/ping v1.1.0 + github.com/go-ping/ping v1.2.0 github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/sirupsen/logrus v1.9.3 github.com/urfave/cli/v2 v2.27.4 - golang.org/x/sys v0.25.0 + golang.org/x/sys v0.33.0 ) require ( @@ -19,7 +21,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/term v0.24.0 // indirect + golang.org/x/net v0.41.0 // indirect + golang.org/x/sync v0.15.0 // indirect + golang.org/x/term v0.32.0 // indirect ) diff --git a/go.sum b/go.sum index 83f949f..51dbae2 100644 --- a/go.sum +++ b/go.sum @@ -1,80 +1,56 @@ -github.com/briandowns/spinner v1.23.0 h1:alDF2guRWqa/FOZZYWjlMIx2L6H0wyewPxo/CH4Pt2A= -github.com/briandowns/spinner v1.23.0/go.mod h1:rPG4gmXeN3wQV/TsAY4w8lPdIM6RX3yqeBQJSrbXjuE= github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650= github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= -github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= -github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= -github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= -github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/go-ping/ping v1.2.0 h1:vsJ8slZBZAXNCK4dPcI2PEE9eM9n9RbXbGouVQ/Y4yQ= +github.com/go-ping/ping v1.2.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ= github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= -github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8= github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=