mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 20:44:38 +03:00
172 lines
3.6 KiB
Go
172 lines
3.6 KiB
Go
package grpc_server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"grpc_server/gen"
|
|
"io"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/matsuridayo/libneko/neko_common"
|
|
"github.com/matsuridayo/libneko/speedtest"
|
|
)
|
|
|
|
func getBetweenStr(str, start, end string) string {
|
|
n := strings.Index(str, start)
|
|
if n == -1 {
|
|
n = 0
|
|
}
|
|
str = string([]byte(str)[n:])
|
|
m := strings.Index(str, end)
|
|
if m == -1 {
|
|
m = len(str)
|
|
}
|
|
str = string([]byte(str)[:m])
|
|
return str[len(start):]
|
|
}
|
|
|
|
func DoFullTest(ctx context.Context, in *gen.TestReq, instance interface{}) (out *gen.TestResp, _ error) {
|
|
out = &gen.TestResp{}
|
|
httpClient := neko_common.CreateProxyHttpClient(instance)
|
|
|
|
// Latency
|
|
var latency string
|
|
if in.FullLatency {
|
|
t, _ := speedtest.UrlTest(httpClient, in.Url, in.Timeout)
|
|
out.Ms = t
|
|
if t > 0 {
|
|
latency = fmt.Sprint(t, "ms")
|
|
} else {
|
|
latency = "Error"
|
|
}
|
|
}
|
|
|
|
// UDP Latency
|
|
var udpLatency string
|
|
if in.FullUdpLatency {
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
|
|
result := make(chan string)
|
|
|
|
go func() {
|
|
var startTime = time.Now()
|
|
pc, err := neko_common.DialContext(ctx, instance, "udp", "8.8.8.8:53")
|
|
if err == nil {
|
|
defer pc.Close()
|
|
dnsPacket, _ := hex.DecodeString("0000010000010000000000000377777706676f6f676c6503636f6d0000010001")
|
|
_, err = pc.Write(dnsPacket)
|
|
if err == nil {
|
|
var buf [1400]byte
|
|
_, err = pc.Read(buf[:])
|
|
}
|
|
}
|
|
if err == nil {
|
|
var endTime = time.Now()
|
|
result <- fmt.Sprint(endTime.Sub(startTime).Abs().Milliseconds(), "ms")
|
|
} else {
|
|
log.Println("UDP Latency test error:", err)
|
|
result <- "Error"
|
|
}
|
|
close(result)
|
|
}()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
udpLatency = "Timeout"
|
|
case r := <-result:
|
|
udpLatency = r
|
|
}
|
|
cancel()
|
|
}
|
|
|
|
// 入口 IP
|
|
var in_ip string
|
|
if in.FullInOut {
|
|
_in_ip, err := net.ResolveIPAddr("ip", in.InAddress)
|
|
if err == nil {
|
|
in_ip = _in_ip.String()
|
|
} else {
|
|
in_ip = err.Error()
|
|
}
|
|
}
|
|
|
|
// 出口 IP
|
|
var out_ip string
|
|
if in.FullInOut {
|
|
resp, err := httpClient.Get("https://www.cloudflare.com/cdn-cgi/trace")
|
|
if err == nil {
|
|
b, _ := io.ReadAll(resp.Body)
|
|
out_ip = getBetweenStr(string(b), "ip=", "\n")
|
|
resp.Body.Close()
|
|
} else {
|
|
out_ip = "Error"
|
|
}
|
|
}
|
|
|
|
// 下载
|
|
var speed string
|
|
if in.FullSpeed {
|
|
if in.FullSpeedTimeout <= 0 {
|
|
in.FullSpeedTimeout = 30
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(in.FullSpeedTimeout))
|
|
result := make(chan string)
|
|
var bodyClose io.Closer
|
|
|
|
go func() {
|
|
req, _ := http.NewRequestWithContext(ctx, "GET", in.FullSpeedUrl, nil)
|
|
resp, err := httpClient.Do(req)
|
|
if err == nil && resp != nil && resp.Body != nil {
|
|
bodyClose = resp.Body
|
|
defer resp.Body.Close()
|
|
//
|
|
time_start := time.Now()
|
|
n, _ := io.Copy(io.Discard, resp.Body)
|
|
time_end := time.Now()
|
|
result <- fmt.Sprintf("%.2fMiB/s", (float64(n)/time_end.Sub(time_start).Seconds())/1048576)
|
|
} else {
|
|
result <- "Error"
|
|
}
|
|
close(result)
|
|
}()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
speed = "Timeout"
|
|
case s := <-result:
|
|
speed = s
|
|
}
|
|
|
|
cancel()
|
|
if bodyClose != nil {
|
|
bodyClose.Close()
|
|
}
|
|
}
|
|
|
|
fr := make([]string, 0)
|
|
if latency != "" {
|
|
fr = append(fr, fmt.Sprintf("Latency: %s", latency))
|
|
}
|
|
if udpLatency != "" {
|
|
fr = append(fr, fmt.Sprintf("UDPLatency: %s", udpLatency))
|
|
}
|
|
if speed != "" {
|
|
fr = append(fr, fmt.Sprintf("Speed: %s", speed))
|
|
}
|
|
if in_ip != "" {
|
|
fr = append(fr, fmt.Sprintf("In: %s", in_ip))
|
|
}
|
|
if out_ip != "" {
|
|
fr = append(fr, fmt.Sprintf("Out: %s", out_ip))
|
|
}
|
|
|
|
out.FullReport = strings.Join(fr, " / ")
|
|
|
|
return
|
|
}
|