Initial commit
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
package connect
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// QUICListener QUIC 监听器
|
||||
type QUICListener struct {
|
||||
listener *quic.Listener
|
||||
}
|
||||
|
||||
// NewQUICListener 创建 QUIC 监听器
|
||||
func NewQUICListener(addr string, logger *zap.Logger) (*QUICListener, error) {
|
||||
// 生成自签名证书(用于测试)
|
||||
cert, err := generateSelfSignedCert()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("生成证书失败:%w", err)
|
||||
}
|
||||
|
||||
tlsConf := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
NextProtos: []string{"meshray-quic"},
|
||||
}
|
||||
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
udpConn, err := net.ListenUDP("udp", udpAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener, err := quic.Listen(udpConn, tlsConf, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建 QUIC 监听器失败:%w", err)
|
||||
}
|
||||
|
||||
logger.Info("QUIC 监听器已启动", zap.String("addr", addr))
|
||||
|
||||
return &QUICListener{
|
||||
listener: listener,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Accept 接受 QUIC 连接
|
||||
func (l *QUICListener) Accept(ctx context.Context) (*quic.Conn, error) {
|
||||
return l.listener.Accept(ctx)
|
||||
}
|
||||
|
||||
// Close 关闭监听器
|
||||
func (l *QUICListener) Close() error {
|
||||
return l.listener.Close()
|
||||
}
|
||||
|
||||
// QUICClient QUIC 客户端
|
||||
type QUICClient struct {
|
||||
servers []string
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewQUICClient 创建 QUIC 客户端
|
||||
func NewQUICClient(servers []string, logger *zap.Logger) *QUICClient {
|
||||
return &QUICClient{
|
||||
servers: servers,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// Connect 建立 QUIC 连接
|
||||
func (c *QUICClient) Connect(ctx context.Context) (net.Conn, error) {
|
||||
if len(c.servers) == 0 {
|
||||
return nil, fmt.Errorf("未配置 QUIC 服务器")
|
||||
}
|
||||
|
||||
// 使用不安全的 TLS 配置(跳过证书验证,用于测试)
|
||||
tlsConf := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
NextProtos: []string{"meshray-quic"},
|
||||
}
|
||||
|
||||
// 尝试连接第一个服务器
|
||||
for _, server := range c.servers {
|
||||
_, err := net.ResolveUDPAddr("udp", server)
|
||||
if err != nil {
|
||||
c.logger.Warn("解析 QUIC 服务器地址失败",
|
||||
zap.String("server", server),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
|
||||
var conn *quic.Conn
|
||||
conn, err = quic.DialAddr(ctx, server, tlsConf, nil)
|
||||
if err == nil {
|
||||
c.logger.Info("QUIC 连接已建立",
|
||||
zap.String("server", server),
|
||||
zap.String("local_addr", conn.LocalAddr().String()))
|
||||
return newQUICConn(conn), nil
|
||||
}
|
||||
|
||||
c.logger.Warn("QUIC 连接失败",
|
||||
zap.String("server", server),
|
||||
zap.Error(err))
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("所有 QUIC 服务器连接失败")
|
||||
}
|
||||
|
||||
// quicConn QUIC 连接包装器(实现 net.Conn)
|
||||
type quicConn struct {
|
||||
conn *quic.Conn // quic-go v0.59.0 使用 *quic.Conn
|
||||
stream *quic.Stream // 使用 *quic.Stream
|
||||
}
|
||||
|
||||
// newQUICConn 创建 QUIC 连接包装器
|
||||
func newQUICConn(conn *quic.Conn) *quicConn {
|
||||
return &quicConn{
|
||||
conn: conn,
|
||||
}
|
||||
}
|
||||
|
||||
// OpenStream 打开流
|
||||
func (c *quicConn) OpenStream() error {
|
||||
stream, err := c.conn.OpenStreamSync(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.stream = stream
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read 实现 net.Conn
|
||||
func (c *quicConn) Read(b []byte) (n int, err error) {
|
||||
if c.stream == nil {
|
||||
stream, err := c.conn.OpenStreamSync(context.Background())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c.stream = stream
|
||||
}
|
||||
return c.stream.Read(b)
|
||||
}
|
||||
|
||||
// Write 实现 net.Conn
|
||||
func (c *quicConn) Write(b []byte) (n int, err error) {
|
||||
if c.stream == nil {
|
||||
stream, err := c.conn.OpenStreamSync(context.Background())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c.stream = stream
|
||||
}
|
||||
return c.stream.Write(b)
|
||||
}
|
||||
|
||||
// Close 实现 net.Conn
|
||||
func (c *quicConn) Close() error {
|
||||
if c.stream != nil {
|
||||
c.stream.Close()
|
||||
}
|
||||
return c.conn.CloseWithError(0, "closed")
|
||||
}
|
||||
|
||||
// LocalAddr 实现 net.Conn
|
||||
func (c *quicConn) LocalAddr() net.Addr {
|
||||
return c.conn.LocalAddr()
|
||||
}
|
||||
|
||||
// RemoteAddr 实现 net.Conn
|
||||
func (c *quicConn) RemoteAddr() net.Addr {
|
||||
return c.conn.RemoteAddr()
|
||||
}
|
||||
|
||||
// SetDeadline 实现 net.Conn
|
||||
func (c *quicConn) SetDeadline(t time.Time) error {
|
||||
if c.stream != nil {
|
||||
return (*c.stream).SetDeadline(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetReadDeadline 实现 net.Conn
|
||||
func (c *quicConn) SetReadDeadline(t time.Time) error {
|
||||
if c.stream != nil {
|
||||
return (*c.stream).SetReadDeadline(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetWriteDeadline 实现 net.Conn
|
||||
func (c *quicConn) SetWriteDeadline(t time.Time) error {
|
||||
if c.stream != nil {
|
||||
return (*c.stream).SetWriteDeadline(t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateSelfSignedCert 生成自签名证书(仅用于测试)
|
||||
func generateSelfSignedCert() (tls.Certificate, error) {
|
||||
// 生成私钥
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
|
||||
// 生成证书模板
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(365 * 24 * time.Hour),
|
||||
DNSNames: []string{"localhost"},
|
||||
}
|
||||
|
||||
// 自签名
|
||||
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
|
||||
// 编码证书和私钥
|
||||
certPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: certDER,
|
||||
})
|
||||
|
||||
keyPEM := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(priv),
|
||||
})
|
||||
|
||||
// 加载证书
|
||||
return tls.X509KeyPair(certPEM, keyPEM)
|
||||
}
|
||||
|
||||
// NewTURNFactoryQUIC 创建 QUIC TURN 工厂(用于 9 层降级策略)
|
||||
// 注意:当前版本暂不启用 QUIC 支持,返回 nil
|
||||
func NewTURNFactoryQUIC(servers []string, username, password string, logger *zap.Logger) *TURNFactory {
|
||||
logger.Warn("QUIC 传输模式暂不支持,已跳过")
|
||||
return nil // 暂时返回 nil,未来实现 QUIC 支持时再完善
|
||||
}
|
||||
Reference in New Issue
Block a user