Files
engine/config/tcp.go
langhuihui f4fb7881f7 增加Stream NeverTimeout属性,用于纯数据轨道的流保持不关闭
消除一处魔法数字
将TCP监听增加TLS支持
2023-06-04 11:02:45 +08:00

119 lines
2.7 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 config
import (
"context"
"crypto/tls"
_ "embed"
"net"
"runtime"
"time"
"m7s.live/engine/v4/log"
)
//go:embed local.monibuca.com_bundle.pem
var LocalCert []byte
//go:embed local.monibuca.com.key
var LocalKey []byte
var _ TCPConfig = (*TCP)(nil)
type TCPConfig interface {
ListenTCP(context.Context, TCPPlugin) error
}
type TCP struct {
ListenAddr string
ListenAddrTLS string
CertFile string
KeyFile string
ListenNum int //同时并行监听数量0为CPU核心数量
NoDelay bool //是否禁用Nagle算法
}
func (tcp *TCP) listen(l net.Listener, handler func(net.Conn)) {
var tempDelay time.Duration
for {
conn, err := l.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
log.Warnf("%s: Accept error: %v; retrying in %v", tcp.ListenAddr, err, tempDelay)
time.Sleep(tempDelay)
continue
}
return
}
var tcpConn *net.TCPConn
switch v := conn.(type) {
case *net.TCPConn:
tcpConn = v
case *tls.Conn:
tcpConn = v.NetConn().(*net.TCPConn)
}
if !tcp.NoDelay {
tcpConn.SetNoDelay(false)
}
tempDelay = 0
go handler(conn)
}
}
func (tcp *TCP) ListenTCP(ctx context.Context, plugin TCPPlugin) error {
l, err := net.Listen("tcp", tcp.ListenAddr)
if err != nil {
if Global.LogLang == "zh" {
log.Fatalf("%s: 监听失败: %v", tcp.ListenAddr, err)
} else {
log.Fatalf("%s: Listen error: %v", tcp.ListenAddr, err)
}
return err
}
count := tcp.ListenNum
if count == 0 {
count = runtime.NumCPU()
}
log.Infof("tcp listen %d at %s", count, tcp.ListenAddr)
for i := 0; i < count; i++ {
go tcp.listen(l, plugin.ServeTCP)
}
if tcp.ListenAddrTLS != "" {
keyPair, _ := tls.X509KeyPair(LocalCert, LocalKey)
if tcp.CertFile != "" || tcp.KeyFile != "" {
keyPair, err = tls.LoadX509KeyPair(tcp.CertFile, tcp.KeyFile)
}
if err != nil {
if Global.LogLang == "zh" {
log.Fatalf("加载证书失败: %v", err)
} else {
log.Fatalf("LoadX509KeyPair error: %v", err)
}
return err
}
l, err = tls.Listen("tcp", tcp.ListenAddrTLS, &tls.Config{
Certificates: []tls.Certificate{keyPair},
})
if err != nil {
if Global.LogLang == "zh" {
log.Fatalf("%s: 监听失败: %v", tcp.ListenAddrTLS, err)
} else {
log.Fatalf("%s: Listen error: %v", tcp.ListenAddrTLS, err)
}
return err
}
log.Infof("tls tcp listen %d at %s", count, tcp.ListenAddrTLS)
for i := 0; i < count; i++ {
go tcp.listen(l, plugin.ServeTCP)
}
}
<-ctx.Done()
return l.Close()
}