Skip to content

Commit f60e6fb

Browse files
committed
feat: LeoMoeAPI 优选 IP
1 parent de0f49d commit f60e6fb

3 files changed

Lines changed: 133 additions & 11 deletions

File tree

wshandle/client.go

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package wshandle
22

33
import (
4+
"crypto/tls"
45
"log"
6+
"net"
7+
"net/http"
58
"net/url"
69
"os"
710
"os/signal"
11+
"strings"
812
"sync"
913
"time"
1014

@@ -25,6 +29,7 @@ type WsConn struct {
2529

2630
var wsconn *WsConn
2731
var hostP = GetenvDefault("NEXTTRACE_HOSTPORT", "api.leo.moe")
32+
var host, port, fast_ip string
2833

2934
func (c *WsConn) keepAlive() {
3035
go func() {
@@ -105,10 +110,16 @@ func (c *WsConn) messageSendHandler() {
105110
}
106111

107112
func (c *WsConn) recreateWsConn() {
108-
u := url.URL{Scheme: "wss", Host: hostP, Path: "/v2/ipGeoWs"}
113+
u := url.URL{Scheme: "wss", Host: fast_ip + ":" + port, Path: "/v2/ipGeoWs"}
109114
// log.Printf("connecting to %s", u.String())
110-
111-
ws, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
115+
requestHeader := http.Header{
116+
"Host": []string{host},
117+
}
118+
dialer := websocket.DefaultDialer
119+
dialer.TLSClientConfig = &tls.Config{
120+
ServerName: host,
121+
}
122+
ws, _, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
112123
c.Conn = ws
113124
if err != nil {
114125
log.Println("dial:", err)
@@ -129,11 +140,47 @@ func createWsConn() *WsConn {
129140
// 设置终端中断通道
130141
interrupt := make(chan os.Signal, 1)
131142
signal.Notify(interrupt, os.Interrupt)
143+
// 解析域名
144+
hostArr := strings.Split(hostP, ":")
145+
// 判断是否有指定端口
146+
if len(hostArr) > 1 {
147+
// 判断是否为 IPv6
148+
if strings.HasPrefix(hostP, "[") {
149+
tmp := strings.Split(hostP, "]")
150+
host = tmp[0]
151+
host = host[1:]
152+
if port = tmp[1]; port != "" {
153+
port = port[1:]
154+
}
155+
} else {
156+
host, port = hostArr[0], hostArr[1]
157+
}
158+
} else {
159+
host = hostP
160+
}
161+
if port == "" {
162+
// 默认端口
163+
port = "443"
164+
}
165+
// 默认配置完成,开始寻找最优 IP
166+
fast_ip = GetFastIP(host, port)
132167

133-
u := url.URL{Scheme: "wss", Host: hostP, Path: "/v2/ipGeoWs"}
168+
// 如果 host 是一个 IP 使用默认域名
169+
if valid := net.ParseIP(host); valid != nil {
170+
host = "api.leo.moe"
171+
}
172+
// 判断是否是一个 IP
173+
requestHeader := http.Header{
174+
"Host": []string{host},
175+
}
176+
dialer := websocket.DefaultDialer
177+
dialer.TLSClientConfig = &tls.Config{
178+
ServerName: host,
179+
}
180+
u := url.URL{Scheme: "wss", Host: fast_ip + ":" + port, Path: "/v2/ipGeoWs"}
134181
// log.Printf("connecting to %s", u.String())
135182

136-
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
183+
c, _, err := websocket.DefaultDialer.Dial(u.String(), requestHeader)
137184

138185
wsconn = &WsConn{
139186
Conn: c,
@@ -169,9 +216,9 @@ func GetWsConn() *WsConn {
169216
return wsconn
170217
}
171218
func GetenvDefault(key, defVal string) string {
172-
val, ok := os.LookupEnv(key)
173-
if ok {
174-
return val
175-
}
176-
return defVal
177-
}
219+
val, ok := os.LookupEnv(key)
220+
if ok {
221+
return val
222+
}
223+
return defVal
224+
}

wshandle/latency.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package wshandle
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"net"
7+
"strings"
8+
"time"
9+
10+
"github.com/fatih/color"
11+
)
12+
13+
var (
14+
result string
15+
results = make(chan string)
16+
)
17+
18+
func GetFastIP(domain string, port string) string {
19+
20+
ips, err := net.LookupIP(domain)
21+
if err != nil {
22+
log.Fatal("DNS 解析失败,请检查您的系统 DNS 设置")
23+
return ""
24+
}
25+
26+
for _, ip := range ips {
27+
go checkLatency(ip.String(), port)
28+
}
29+
30+
select {
31+
case result = <-results:
32+
case <-time.After(1 * time.Second):
33+
34+
}
35+
if result == "" {
36+
log.Fatal("IP 连接均超时,请检查您的网络")
37+
}
38+
res := strings.Split(result, "-")
39+
40+
if len(ips) > 1 {
41+
fmt.Fprintf(color.Output, "%s 已为您优选最近的节点 %s - %s\n",
42+
color.New(color.FgWhite, color.Bold).Sprintf("[NextTrace API]"),
43+
color.New(color.FgGreen, color.Bold).Sprintf("%s", res[0]),
44+
color.New(color.FgCyan, color.Bold).Sprintf("%sms", res[1]),
45+
)
46+
}
47+
48+
return res[0]
49+
}
50+
51+
func checkLatency(ip string, port string) {
52+
start := time.Now()
53+
if !strings.Contains(ip, ".") {
54+
ip = "[" + ip + "]"
55+
}
56+
conn, err := net.DialTimeout("tcp", ip+":"+port, time.Second*1)
57+
if err != nil {
58+
return
59+
}
60+
defer conn.Close()
61+
if result == "" {
62+
result = fmt.Sprintf("%s-%.2f", ip, float64(time.Since(start))/float64(time.Millisecond))
63+
results <- result
64+
return
65+
}
66+
}

wshandle/latency_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package wshandle
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestGetFastIP(t *testing.T) {
8+
GetFastIP("api.leo.moe", "443")
9+
}

0 commit comments

Comments
 (0)