init: 自 zomaintain/backend/zonat 平移独立成库; module path 改为 git.zeroonesoft.cn/golib/zonat; 内部 import 同步重写

This commit is contained in:
w11
2026-09-19 18:55:43 +08:00
commit 984041f1a0
20 changed files with 2427 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
package node
import (
"io"
"log/slog"
"net"
"sync/atomic"
"time"
"git.zeroonesoft.cn/golib/zonat/agent"
)
// TunnelServer 一条已注册隧道的公网侧监听。
// 纯 TCP 字节管道:无协议嗅探、无 HTTP 代理、无证书,任何 TCP 协议原样通过。
type TunnelServer struct {
tunnel agent.Tunnel
session *Session
listener net.Listener
connCount atomic.Int64
lastActive atomic.Int64 // unix nano
closed atomic.Bool
}
// Port 公网监听端口
func (t *TunnelServer) Port() int { return t.tunnel.ListenPort }
func (t *TunnelServer) touch() { t.lastActive.Store(time.Now().UnixNano()) }
func (t *TunnelServer) lastActiveTime() time.Time {
return time.Unix(0, t.lastActive.Load())
}
func (t *TunnelServer) acceptLoop() {
for {
conn, err := t.listener.Accept()
if err != nil {
return
}
if t.closed.Load() {
conn.Close()
return
}
go t.handleConn(conn)
}
}
// handleConn 公网连接 → smux 新流 → 首帧告知目标 → agent 回执后双向管道。
// 与 zonat 多路复用路径一致,仅去掉协议嗅探与限流。
func (t *TunnelServer) handleConn(conn net.Conn) {
defer conn.Close()
if t.session.isDead() {
return
}
stream, err := t.session.OpenStream()
if err != nil {
return
}
defer stream.Close()
tf := agent.NewFrame(agent.FrameVersion, agent.CmdTarget, 0)
if err := tf.Marshal(t.tunnel); err != nil {
return
}
if err := agent.WriteFrame(stream, tf); err != nil {
return
}
rf, err := agent.ReadFrame(stream)
if err != nil {
return
}
ret := agent.Ret{}
if err := rf.Unmarshal(&ret); err != nil || ret.Code != 0 {
slog.Warn("节点 agent拨号失败", "id", t.tunnel.Id, "msg", ret.Msg)
return
}
// 公网侧 TCP 保活(smux 流自身由会话级 keepalive 保护)
if tc, ok := conn.(*net.TCPConn); ok {
tc.SetKeepAlive(true)
tc.SetKeepAlivePeriod(5 * time.Second)
}
t.connCount.Add(1)
t.touch()
defer func() {
t.connCount.Add(-1)
t.touch()
}()
pipe(conn, stream)
}
func (t *TunnelServer) close() {
if t.closed.CompareAndSwap(false, true) && t.listener != nil {
t.listener.Close()
}
}
// pipe 双向拷贝,任一方向结束即关闭两端
func pipe(a, b net.Conn) {
go func() {
io.Copy(b, a)
b.Close()
}()
io.Copy(a, b)
a.Close()
}