重命名客户端相关术语为节点;移动 utils 包到根路径;优化网关对节点各种连接状态的处理,并在节点断联后统一清理资源

This commit is contained in:
2025-05-17 10:00:28 +08:00
parent 20ac7dbd91
commit 84e01d3b50
14 changed files with 150 additions and 129 deletions

View File

@@ -16,7 +16,7 @@ import (
"proxy-server/edge/env"
"proxy-server/edge/geo"
"proxy-server/edge/report"
"proxy-server/pkg/utils"
"proxy-server/utils"
"time"
)
@@ -103,7 +103,8 @@ func ctrl(ctx context.Context, id int32, host string) error {
var reader = bufio.NewReader(conn)
// 发送节点连接命令
err = sendOpen(reader, conn, id)
slog.Debug("发送节点连接命令")
err = sendOpen(conn, id)
if err != nil {
return fmt.Errorf("发送节点信息失败: %w", err)
}
@@ -117,7 +118,8 @@ func ctrl(ctx context.Context, id int32, host string) error {
case <-ctx.Done():
return
case tick := <-ticker.C:
err := sendPing(reader, conn)
slog.Debug("发送心跳", "time", tick)
err := sendPing(conn)
if err != nil {
slog.Error("发送心跳失败", "time", tick, "err", err)
}
@@ -125,23 +127,51 @@ func ctrl(ctx context.Context, id int32, host string) error {
}
}()
// 等待用户连接
// 读写失败后退出重连,防止后续数据读写顺序错位导致卡死控制通道
// 异步等待连接命令
slog.Info("等待用户连接")
var cmdCh = make(chan ConnCmd)
go func() {
for {
cmd, err := reader.ReadByte()
if errors.Is(err, net.ErrClosed) {
slog.Debug("控制通道关闭")
return
}
if errors.Is(err, io.EOF) {
slog.Debug("网关关闭了控制通道")
return
}
if err != nil {
slog.Error("读取命令失败", "err", err)
return
}
switch cmd {
case 1:
// 忽略网关响应的 pong 命令
case 5:
tag, addr, err := onConn(reader)
if err != nil {
slog.Error("接收连接命令失败", "err", err)
return
}
cmdCh <- ConnCmd{
Tag: tag,
Addr: addr,
}
}
}
}()
// 等待建立数据通道
for loop := true; loop; {
select {
case <-ctx.Done():
loop = false
default:
// 接收 dst
tag, addr, err := onConn(reader)
if err != nil {
return fmt.Errorf("接收连接命令失败: %w", err)
}
// 建立数据通道
case cmd := <-cmdCh:
slog.Debug("建立数据通道", "tag", cmd.Tag, "addr", cmd.Addr)
go func() {
err := data(dataAddr, addr, tag)
err := data(dataAddr, cmd.Addr, cmd.Tag)
if err != nil {
slog.Error("建立数据通道失败", "err", err)
}
@@ -150,7 +180,8 @@ func ctrl(ctx context.Context, id int32, host string) error {
}
// 发送关闭连接(不 return err否则会重新连接
err = sendClose(reader, conn)
slog.Debug("发送关闭连接")
err = sendClose(conn)
if err != nil {
slog.Error("发送关闭连接失败", "err", err)
}
@@ -207,7 +238,7 @@ func data(proxy string, dest string, tag [16]byte) error {
return nil
}
func sendOpen(reader io.Reader, writer io.Writer, id int32) error {
func sendOpen(writer io.Writer, id int32) error {
// 发送打开连接
var buf = make([]byte, 5)
@@ -219,72 +250,38 @@ func sendOpen(reader io.Reader, writer io.Writer, id int32) error {
return fmt.Errorf("发送打开连接失败: %w", err)
}
// 等待服务端响应
respBuf := make([]byte, 1)
_, err = io.ReadFull(reader, respBuf)
if err != nil {
return fmt.Errorf("接收服务端响应失败: %w", err)
}
if respBuf[0] != 1 {
return errors.New("服务端响应失败")
}
return nil
}
func sendClose(reader io.Reader, writer io.Writer) error {
func sendClose(writer io.Writer) error {
// 发送关闭连接
_, err := writer.Write([]byte{4})
if err != nil {
return err
}
// 等待服务端响应
respBuf := make([]byte, 1)
_, err = io.ReadFull(reader, respBuf)
if err != nil {
return fmt.Errorf("接收服务端响应失败: %w", err)
}
if respBuf[0] != 1 {
return errors.New("服务端响应失败")
}
return nil
}
func sendPing(reader io.Reader, writer io.Writer) error {
func sendPing(writer io.Writer) error {
_, err := writer.Write([]byte{2})
if err != nil {
return err
}
// 等待服务端响应
respBuf := make([]byte, 1)
_, err = io.ReadFull(reader, respBuf)
if err != nil {
return fmt.Errorf("接收服务端响应失败: %w", err)
}
if respBuf[0] != 1 {
return errors.New("服务端响应失败")
}
return nil
}
func onConn(reader io.Reader) (tag [16]byte, addr string, err error) {
var buf = make([]byte, 1+16+2)
var buf = make([]byte, 16+2)
_, err = io.ReadFull(reader, buf)
if err != nil {
return [16]byte{}, "", err
}
if buf[0] != 5 {
return [16]byte{}, "", errors.New("命令错误")
}
tag = [16]byte(buf[0:16])
tag = [16]byte(buf[1:17])
var addrLen = binary.BigEndian.Uint16(buf[17:19])
var addrLen = binary.BigEndian.Uint16(buf[16:18])
var addrBuf = make([]byte, addrLen)
_, err = io.ReadFull(reader, addrBuf)
if err != nil {
@@ -294,3 +291,8 @@ func onConn(reader io.Reader) (tag [16]byte, addr string, err error) {
addr = string(addrBuf)
return tag, addr, nil
}
type ConnCmd struct {
Tag [16]byte
Addr string
}

4
edge/env/env.go vendored
View File

@@ -15,7 +15,7 @@ var EndpointOffline = "https://api.lanhuip.com/api/edge/offline"
func Init() error {
var env = flag.String("e", "dev", "环境变量,可选值 dev 或 prod")
var name = flag.String("n", "", "客户端唯一标识")
var name = flag.String("n", "", "节点唯一标识")
var online = flag.String("online", "", "服务注册地址")
var offline = flag.String("offline", "", "服务注销地址")
@@ -32,7 +32,7 @@ func Init() error {
if name != nil && *name != "" {
Name = *name
} else {
return errors.New("客户端唯一标识不能为空")
return errors.New("节点唯一标识不能为空")
}
if online != nil && *online != "" {