Skip to content

Commit

Permalink
feat: ensure server ip correct, check http status
Browse files Browse the repository at this point in the history
  • Loading branch information
ztelliot committed Jun 6, 2024
1 parent 3a85b77 commit 3db6ee6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 90 deletions.
76 changes: 49 additions & 27 deletions defs/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type Server struct {
Name string `json:"name"`
IP string `json:"ip"`
IPv6 string `json:"ipv6"`
Target string `json:"_"`
Host string `json:"host"`
Port uint16 `json:"port"`
Prov uint8 `json:"province"`
Expand All @@ -82,67 +83,78 @@ type Server struct {
NoICMP bool `json:"-"`
}

func (s *Server) GetHost() string {
if s.Port != 80 {
return net.JoinHostPort(s.Host, strconv.Itoa(int(s.Port)))
} else {
return s.Host
}
}

func (s *Server) URL() *url.URL {
u := url.URL{
Scheme: "http",
Host: net.JoinHostPort(s.Host, strconv.Itoa(int(s.Port))),
Host: net.JoinHostPort(s.Target, strconv.Itoa(int(s.Port))),
}
return &u
}

func (s *Server) DownloadURL() string {
func (s *Server) DownloadURL() *url.URL {
if s.DownloadURI != "" {
return fmt.Sprintf("%s%s", s.URL().String(), s.DownloadURI)
return s.URL().JoinPath(s.DownloadURI)
} else {
switch s.Type {
case Perception:
return fmt.Sprintf("%s/speedtest/download", s.URL().String())
return s.URL().JoinPath("/speedtest/download")
case WirelessSpeed:
return fmt.Sprintf("%s/GSpeedTestServer/download", s.URL().String())
return s.URL().JoinPath("/GSpeedTestServer/download")
default:
return fmt.Sprintf("%s/speed/File(1G).dl", s.URL().String())
return s.URL().JoinPath("/speed/File(1G).dl")
}
}
}

func (s *Server) UploadURL() string {
func (s *Server) UploadURL() *url.URL {
if s.UploadURI != "" {
return fmt.Sprintf("%s%s", s.URL().String(), s.UploadURI)
return s.URL().JoinPath(s.UploadURI)
} else {
switch s.Type {
case Perception:
return fmt.Sprintf("%s/speedtest/upload", s.URL().String())
return s.URL().JoinPath("/speedtest/upload")
case WirelessSpeed:
return fmt.Sprintf("%s/GSpeedTestServer/upload", s.URL().String())
return s.URL().JoinPath("/GSpeedTestServer/upload")
default:
return fmt.Sprintf("%s/speed/doAnalsLoad.do", s.URL().String())
return s.URL().JoinPath("/speed/doAnalsLoad.do")
}
}
}

func (s *Server) PingURL() string {
func (s *Server) PingURL() *url.URL {
if s.PingURI != "" {
return fmt.Sprintf("%s%s", s.URL().String(), s.PingURI)
return s.URL().JoinPath(s.PingURI)
} else {
switch s.Type {
case Perception:
return fmt.Sprintf("%s/speedtest/ping", s.URL().String())
return s.URL().JoinPath("/speedtest/ping")
case WirelessSpeed:
return fmt.Sprintf("%s/GSpeedTestServer/", s.URL().String())
return s.URL().JoinPath("/GSpeedTestServer/")
default:
return fmt.Sprintf("%s/speed/", s.URL().String())
return s.URL().JoinPath("/speed/")
}
}
}

// IsUp checks the speed test backend is up by accessing the ping URL
func (s *Server) IsUp() bool {
req, err := http.NewRequest(http.MethodGet, s.PingURL(), nil)
req, err := http.NewRequest(http.MethodGet, s.PingURL().String(), nil)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return false
}

if s.Host != "" {
req.Host = s.GetHost()
}
req.Header.Set("User-Agent", AndroidUA)

resp, err := http.DefaultClient.Do(req)
Expand All @@ -163,11 +175,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f
return s.PingAndJitter(count + 2)
}

p, err := ping.NewPinger(s.Host)
if err != nil {
log.Debugf("ICMP ping failed: %s, will use HTTP ping", err)
return s.PingAndJitter(count + 2)
}
p := ping.New(s.Target)
p.SetPrivileged(true)
p.SetNetwork(network)
p.Count = count
Expand Down Expand Up @@ -203,7 +211,7 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f

if len(stats.Rtts) == 0 {
s.NoICMP = true
log.Debugf("No ICMP pings returned for server %s (%s), trying TCP ping", s.Name, s.IP)
log.Debugf("No ICMP pings returned for server %s (%s), trying TCP ping", s.Name, s.Target)
return s.PingAndJitter(count + 2)
}

Expand All @@ -214,12 +222,15 @@ func (s *Server) ICMPPingAndJitter(count int, srcIp, network string) (float64, f
func (s *Server) PingAndJitter(count int) (float64, float64, error) {
var pings []float64

req, err := http.NewRequest(http.MethodGet, s.PingURL(), nil)
req, err := http.NewRequest(http.MethodGet, s.PingURL().String(), nil)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return 0, 0, err
}

if s.Host != "" {
req.Host = s.GetHost()
}
req.Header.Set("User-Agent", AndroidUA)

for i := 0; i < count; i++ {
Expand Down Expand Up @@ -268,15 +279,18 @@ func (s *Server) Download(silent, useBytes, useMebi bool, requests int, duration

uri := s.DownloadURL()
if s.Type == GlobalSpeed {
uri = fmt.Sprintf("%s?key=%s", uri, token)
uri.RawQuery = fmt.Sprintf("key=%s", token)
}

req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return 0, 0, err
}

if s.Host != "" {
req.Host = s.GetHost()
}
req.Header.Set("User-Agent", BrowserUA)
req.Header.Set("Accept", "*/*")
req.Header.Set("Connection", "close")
Expand All @@ -292,6 +306,11 @@ func (s *Server) Download(silent, useBytes, useMebi bool, requests int, duration
} else {
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
log.Debugf("Failed to test download speed: %s", resp.Status)
return
}

if _, err = io.Copy(io.Discard, io.TeeReader(resp.Body, counter)); err != nil {
if !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) && !os.IsTimeout(err) {
log.Debugf("Failed when reading HTTP response: %s", err)
Expand Down Expand Up @@ -360,12 +379,15 @@ func (s *Server) Upload(noPrealloc, silent, useBytes, useMebi bool, requests, up
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

req, err := http.NewRequestWithContext(ctx, http.MethodPost, s.UploadURL(), counter)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, s.UploadURL().String(), counter)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return 0, 0, err
}

if s.Host != "" {
req.Host = s.GetHost()
}
req.Header.Set("User-Agent", AndroidUA)
if s.Type != WirelessSpeed {
req.Header.Set("Connection", "close")
Expand Down
67 changes: 27 additions & 40 deletions speedtest/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ func getServerList(c *cli.Context, servers *[]string, groups *[]string) ([]defs.
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, errors.New(resp.Status)
}
Expand All @@ -156,7 +158,7 @@ func getServerList(c *cli.Context, servers *[]string, groups *[]string) ([]defs.
if err != nil {
return nil, err
}
defer resp.Body.Close()

log.Debugf("Time taken to get server list: %s", time.Since(start))

var res struct {
Expand Down Expand Up @@ -187,6 +189,8 @@ func getVersion(c *cli.Context) (*defs.Version, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, errors.New(resp.Status)
}
Expand All @@ -199,7 +203,6 @@ func getVersion(c *cli.Context) (*defs.Version, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()

var res struct {
Code int `json:"code"`
Expand All @@ -226,12 +229,16 @@ func getGlobalServerList(ip string, ipv6 int) ([]defs.Server, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, errors.New(resp.Status)
}

b, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if err = json.Unmarshal(b, &serversT); err != nil {
return nil, err
Expand All @@ -240,12 +247,7 @@ func getGlobalServerList(ip string, ipv6 int) ([]defs.Server, error) {
var servers []defs.Server
for _, s := range serversT {
port, _ := strconv.Atoi(s.Port)
_s := defs.Server{ID: strconv.Itoa(s.ID), Name: s.Name, Host: s.IP, Port: uint16(port), Province: s.Prov, City: s.City, ISP: s.GetISP().ID}
if ipv6 == 0 {
_s.IP = s.IP
} else {
_s.IPv6 = s.IP
}
_s := defs.Server{ID: strconv.Itoa(s.ID), Name: s.Name, Target: s.IP, Port: uint16(port), Province: s.Prov, City: s.City, ISP: s.GetISP().ID}
servers = append(servers, _s)
}
return servers, nil
Expand All @@ -260,9 +262,10 @@ func enQueue(s defs.Server) string {
md5Ctx.Write([]byte(fmt.Sprintf("model=Android&imei=%s&stime=%s", imei, ts)))
token := hex.EncodeToString(md5Ctx.Sum(nil))

url := fmt.Sprintf("%s/speed/dovalid?key=&flag=true&bandwidth=200&model=Android&imei=%s&time=%s&token=%s", s.URL().String(), imei, ts, token)
uri := s.URL().JoinPath("/speed/dovalid")
uri.RawQuery = fmt.Sprintf("key=&flag=true&bandwidth=200&model=Android&imei=%s&time=%s&token=%s", imei, ts, token)

req, err := http.NewRequest(http.MethodGet, url, nil)
req, err := http.NewRequest(http.MethodGet, uri.String(), nil)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return ""
Expand All @@ -276,28 +279,22 @@ func enQueue(s defs.Server) string {
}
defer resp.Body.Close()

b, err := io.ReadAll(resp.Body)
if err != nil {
if b, err := io.ReadAll(resp.Body); err != nil {
log.Debugf("Failed when reading HTTP response: %s", err)
return ""
}

if resp.StatusCode != http.StatusOK {
} else if resp.StatusCode != http.StatusOK || len(b) <= 0 {
log.Debugf("Failed with %d: %s", resp.StatusCode, b)
return ""
} else {
return string(b)[2:]
}

if len(b) <= 0 {
return ""
}

return string(b)[2:]
}

func deQueue(s defs.Server, key string) bool {
url := fmt.Sprintf("%s/speed/dovalid?key=%s", s.URL().String(), key)
uri := s.URL().JoinPath("/speed/dovalid")
uri.RawQuery = fmt.Sprintf("key=%s", key)

req, err := http.NewRequest(http.MethodPost, url, nil)
req, err := http.NewRequest(http.MethodPost, uri.String(), nil)
if err != nil {
log.Debugf("Failed when creating HTTP request: %s", err)
return false
Expand All @@ -313,13 +310,11 @@ func deQueue(s defs.Server, key string) bool {
}
defer resp.Body.Close()

b, err := io.ReadAll(resp.Body)
if err != nil {
if b, err := io.ReadAll(resp.Body); err != nil {
log.Debugf("Failed when reading HTTP response: %s", err)
return false
}

if len(b) <= 0 {
} else if resp.StatusCode != http.StatusOK || len(b) <= 0 {
log.Debugf("Failed with %d: %s", resp.StatusCode, b)
return false
}

Expand Down Expand Up @@ -386,14 +381,11 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, network string, silent,
// fetch current user's IP info
for _, currentServer := range servers {
if !silent || c.Bool(defs.OptionSimple) {
name, ip := currentServer.Name, currentServer.IP
name := currentServer.Name
if currentServer.Type == defs.Perception {
name = fmt.Sprintf("%s - %s", currentServer.Name, defs.ISPMap[currentServer.ISP].Name)
}
if network == "ip6" {
ip = currentServer.IPv6
}
fmt.Printf("Server:\t\t%s [%s] (id = %s)\n", name, ip, currentServer.ID)
fmt.Printf("Server:\t\t%s [%s] (id = %s)\n", name, currentServer.Target, currentServer.ID)
}

if currentServer.IsUp() {
Expand Down Expand Up @@ -493,12 +485,7 @@ func doSpeedTest(c *cli.Context, servers []defs.Server, network string, silent,
rep.BytesSent = bytesWritten

rep.ID = currentServer.ID
switch network {
case "ip6":
rep.IP = currentServer.IPv6
default:
rep.IP = currentServer.IP
}
rep.IP = currentServer.Target
rep.Name = currentServer.Name
rep.Province = currentServer.Province
rep.City = currentServer.City
Expand Down
Loading

0 comments on commit 3db6ee6

Please sign in to comment.