重命名客户端相关术语为节点;移动 utils 包到根路径;优化网关对节点各种连接状态的处理,并在节点断联后统一清理资源
This commit is contained in:
112
edge/edge.go
112
edge/edge.go
@@ -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
4
edge/env/env.go
vendored
@@ -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 != "" {
|
||||
|
||||
Reference in New Issue
Block a user