70 lines
1.4 KiB
Go
70 lines
1.4 KiB
Go
package netcheck
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"vpnclient/internal/protocols/naive"
|
|
)
|
|
|
|
// Result is a TCP reachability measurement to a proxy host.
|
|
type Result struct {
|
|
Name string `json:"name"`
|
|
Host string `json:"host"`
|
|
Port string `json:"port"`
|
|
Ms int64 `json:"ms"`
|
|
OK bool `json:"ok"`
|
|
Error string `json:"error,omitempty"`
|
|
}
|
|
|
|
// PingProxyURI measures TCP connect time to the host in a naive share/proxy URI.
|
|
func PingProxyURI(ctx context.Context, name, proxyURI string) Result {
|
|
res := Result{Name: name}
|
|
if strings.TrimSpace(proxyURI) == "" {
|
|
res.Error = "нет ссылки сервера"
|
|
return res
|
|
}
|
|
normalized, err := naive.NormalizeProxyURI(proxyURI)
|
|
if err != nil {
|
|
res.Error = err.Error()
|
|
return res
|
|
}
|
|
u, err := url.Parse(normalized)
|
|
if err != nil {
|
|
res.Error = err.Error()
|
|
return res
|
|
}
|
|
host := u.Hostname()
|
|
port := u.Port()
|
|
if port == "" {
|
|
switch strings.ToLower(u.Scheme) {
|
|
case "https", "quic":
|
|
port = "443"
|
|
default:
|
|
port = "80"
|
|
}
|
|
}
|
|
res.Host = host
|
|
res.Port = port
|
|
if host == "" {
|
|
res.Error = "нет хоста"
|
|
return res
|
|
}
|
|
|
|
d := net.Dialer{Timeout: 4 * time.Second}
|
|
start := time.Now()
|
|
conn, err := d.DialContext(ctx, "tcp", net.JoinHostPort(host, port))
|
|
if err != nil {
|
|
res.Error = fmt.Sprintf("недоступен: %v", err)
|
|
return res
|
|
}
|
|
_ = conn.Close()
|
|
res.Ms = time.Since(start).Milliseconds()
|
|
res.OK = true
|
|
return res
|
|
}
|