Files
Meshray-Manager/core/connect/direct.go
T
2026-06-30 15:14:37 +08:00

94 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package connect
import (
"context"
"fmt"
"net"
"time"
"go.uber.org/zap"
)
// DirectFactory Direct-UDP 直连工厂(Layer 1
type DirectFactory struct {
stunServers []string
logger *zap.Logger
}
// NewDirectFactory 创建 Direct-UDP 工厂
func NewDirectFactory(stunServers []string, logger *zap.Logger) *DirectFactory {
return &DirectFactory{
stunServers: stunServers,
logger: logger,
}
}
// Layer 返回传输层类型
func (f *DirectFactory) Layer() Layer {
return LayerDirectUDP
}
// Name 返回传输方式名称
func (f *DirectFactory) Name() string {
return "Direct-UDP"
}
// Dial 建立 Direct-UDP 直连
func (f *DirectFactory) Dial(ctx context.Context, config *DialConfig) (net.Conn, error) {
f.logger.Info("开始建立 Direct-UDP 直连",
zap.String("peer_id", config.PeerID))
servers := f.stunServers
if len(servers) == 0 {
servers = config.STUNServers
}
if len(servers) == 0 {
f.logger.Warn("未配置 STUN 服务器列表,仅尝试内部 P2P 打洞")
}
var candidates []string
if len(servers) > 0 {
// 1. 创建 STUN 客户端收集候选地址
stun := NewSTUNClient(servers, f.logger)
candidates = stun.CollectCandidates()
}
if len(candidates) == 0 {
f.logger.Warn("未能收集到任何 STUN 候选地址,回退至 PeerID")
// As a fallback, maybe PeerID contains IP:PORT
candidates = append(candidates, config.PeerID)
}
f.logger.Info("STUN 候选地址收集完成",
zap.Strings("candidates", candidates))
// 2. 实际 P2P 连接尝试
f.logger.Warn("当前尝试所有候选地址...")
dialer := &net.Dialer{
Timeout: 5 * time.Second,
}
// 建立 UDP 连接并返回最近可用的
var lastErr error
for _, candidate := range candidates {
if candidate == "" { continue }
conn, err := dialer.DialContext(ctx, "udp", candidate)
if err == nil {
f.logger.Info("Direct-UDP 直连建立成功",
zap.String("peer_id", config.PeerID),
zap.String("remote_addr", conn.RemoteAddr().String()))
return conn, nil
}
f.logger.Warn("候选地址连接失败",
zap.String("candidate", candidate),
zap.Error(err))
lastErr = err
}
return nil, fmt.Errorf("所有候选地址 UDP 连接均失败,最后错误:%w", lastErr)
}