0d84b07f68
CI / docker (push) Successful in 1m58s
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。 Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。 Co-authored-by: Cursor <cursoragent@cursor.com>
68 lines
1.3 KiB
Go
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)
|
|
}
|