Files
Wormhole/internal/bridge/watchdog.go
T
rose_cat707 0d84b07f68
CI / docker (push) Successful in 1m58s
feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。
Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 17:52:43 +08:00

68 lines
1.3 KiB
Go

package bridge
import (
"log"
"time"
"github.com/wormhole/wormhole/internal/protocol"
)
func (b *Bridge) startWatchdog() {
go func() {
ticker := time.NewTicker(WatchdogInterval)
defer ticker.Stop()
for range ticker.C {
b.runWatchdog()
}
}()
}
func (b *Bridge) runWatchdog() {
now := time.Now()
b.mu.RLock()
sessions := make([]*AgentSession, 0, len(b.agents))
for _, agent := range b.agents {
sessions = append(sessions, agent)
}
b.mu.RUnlock()
for _, agent := range sessions {
if agent.closed.Load() {
continue
}
lastPing, ok := b.cache.AgentLastPing(agent.ClientID)
if !ok {
continue
}
since := now.Sub(lastPing)
if since > HeartbeatTimeout {
log.Printf("[bridge] client %d heartbeat timeout (%v), closing", agent.ClientID, since.Round(time.Second))
agent.Close()
continue
}
if since > ServerProbeAfter {
go b.probeAgent(agent)
}
}
}
func (b *Bridge) probeAgent(agent *AgentSession) {
if agent.closed.Load() {
return
}
stream, err := agent.smux.OpenStream()
if err != nil {
return
}
defer stream.Close()
if err := protocol.WriteMessage(stream, protocol.MsgPing, nil); err != nil {
return
}
msgType, _, err := protocol.ReadMessage(stream)
if err != nil || msgType != protocol.MsgPong {
return
}
b.cache.TouchAgent(agent.ClientID)
}