Files
monibuca/pkg/config/udp.go
T
2024-11-12 10:19:55 +08:00

78 lines
1.7 KiB
Go

package config
import (
"crypto/tls"
"log/slog"
"net"
"time"
"m7s.live/v5/pkg/task"
)
type UDP struct {
ListenAddr string `desc:"监听地址,格式为ip:port,ip 可省略默认监听所有网卡"`
CertFile string `desc:"证书文件"`
KeyFile string `desc:"私钥文件"`
AutoListen bool `default:"true" desc:"是否自动监听"`
}
func (config *UDP) CreateUDPWork(logger *slog.Logger, handler func(conn *net.UDPConn) task.ITask) *ListenUDPWork {
ret := &ListenUDPWork{UDP: config, handler: handler}
ret.Logger = logger.With("addr", config.ListenAddr)
return ret
}
type ListenUDPWork struct {
task.Work
*UDP
net.Listener
handler func(conn *net.UDPConn) task.ITask
}
func (task *ListenUDPWork) Dispose() {
task.Close()
}
func (task *ListenUDPWork) Start() (err error) {
task.Listener, err = net.Listen("udp", task.ListenAddr)
if err == nil {
task.Info("listen udp")
} else {
task.Error("failed to listen udp", "error", err)
}
return
}
func (task *ListenUDPWork) Go() error {
var tempDelay time.Duration
for {
conn, err := task.Accept()
if err != nil {
if ne, ok := err.(net.Error); ok && !ne.Timeout() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
// slog.Warnf("%s: Accept error: %v; retrying in %v", tcp.ListenAddr, err, tempDelay)
time.Sleep(tempDelay)
continue
}
return err
}
var udpConn *net.UDPConn
switch v := conn.(type) {
case *net.UDPConn:
udpConn = v
case *tls.Conn:
udpConn = v.NetConn().(*net.UDPConn)
}
tempDelay = 0
subTask := task.handler(udpConn)
task.AddTask(subTask)
}
}