udp: fix reading two streams with same port and different multicast IP (#2133) (#2332)

Fixes #2133
This commit is contained in:
Alessandro Ros 2023-09-12 00:27:08 +02:00 committed by GitHub
parent 2a26962167
commit a005de1aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 46 deletions

4
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/abema/go-mp4 v0.13.0
github.com/alecthomas/kong v0.8.0
github.com/bluenviron/gohlslib v1.0.2
github.com/bluenviron/gortsplib/v4 v4.0.1
github.com/bluenviron/gortsplib/v4 v4.0.2-0.20230911215322-4ede58cda208
github.com/bluenviron/mediacommon v1.1.1
github.com/datarhei/gosrt v0.5.4
github.com/fsnotify/fsnotify v1.6.0
@ -25,7 +25,6 @@ require (
github.com/pion/webrtc/v3 v3.2.19
github.com/stretchr/testify v1.8.4
golang.org/x/crypto v0.13.0
golang.org/x/net v0.15.0
golang.org/x/term v0.12.0
gopkg.in/yaml.v2 v2.4.0
)
@ -66,6 +65,7 @@ require (
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/net v0.15.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect

4
go.sum
View File

@ -14,8 +14,8 @@ github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c h1:8XZeJrs4+ZYh
github.com/benburkert/openpgp v0.0.0-20160410205803-c2471f86866c/go.mod h1:x1vxHcL/9AVzuk5HOloOEPrtJY0MaalYr78afXZ+pWI=
github.com/bluenviron/gohlslib v1.0.2 h1:LDA/CubL525e9rLWw+G/9GbFS6iXwozmOg8KJBT4qF4=
github.com/bluenviron/gohlslib v1.0.2/go.mod h1:oam0wsI2XqcHLTG6NM8HRvxAQsa3hIA0MLRiTOE7CB8=
github.com/bluenviron/gortsplib/v4 v4.0.1 h1:6Ng9fRW40tHnOx/kDqO6gIrSZocdvfHTp6mjdnkWlEU=
github.com/bluenviron/gortsplib/v4 v4.0.1/go.mod h1:bfw1TZzHt6NsuKgQxrfrb8w0NnYMvNvqZ1jgjQk5qaU=
github.com/bluenviron/gortsplib/v4 v4.0.2-0.20230911215322-4ede58cda208 h1:w1aishvJ4U2TuM1SsFmWoKuFNogqhla3eh2Qn6AyRtE=
github.com/bluenviron/gortsplib/v4 v4.0.2-0.20230911215322-4ede58cda208/go.mod h1:l6LO4TlHC3YdLIbEn89GeeSgzHaJlpAFF7NLZ7h4A+A=
github.com/bluenviron/mediacommon v1.1.1 h1:cGFy5hnLBeiTrpPyEOf23En+E86r3s99tudlQHY9eEA=
github.com/bluenviron/mediacommon v1.1.1/go.mod h1:/vlOVSebDwzdRtQONOKLua0fOSJg1tUDHpP+h9a0uqM=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=

View File

@ -8,8 +8,8 @@ import (
"github.com/bluenviron/gortsplib/v4/pkg/description"
"github.com/bluenviron/gortsplib/v4/pkg/format"
"github.com/bluenviron/gortsplib/v4/pkg/multicast"
"github.com/bluenviron/mediacommon/pkg/formats/mpegts"
"golang.org/x/net/ipv4"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/logger"
@ -18,34 +18,10 @@ import (
)
const (
multicastTTL = 16
udpMTU = 1472
// same size as GStreamer's rtspsrc
udpKernelReadBufferSize = 0x80000
)
func joinMulticastGroupOnAtLeastOneInterface(p *ipv4.PacketConn, listenIP net.IP) error {
intfs, err := net.Interfaces()
if err != nil {
return err
}
success := false
for _, intf := range intfs {
if (intf.Flags & net.FlagMulticast) != 0 {
err := p.JoinGroup(&intf, &net.UDPAddr{IP: listenIP})
if err == nil {
success = true
}
}
}
if !success {
return fmt.Errorf("unable to activate multicast on any network interface")
}
return nil
}
type packetConnReader struct {
net.PacketConn
}
@ -61,6 +37,11 @@ func (r *packetConnReader) Read(p []byte) (int, error) {
return n, err
}
type packetConn interface {
net.PacketConn
SetReadBuffer(int) error
}
type udpSourceParent interface {
logger.Writer
setReady(req pathSourceStaticSetReadyReq) pathSourceStaticSetReadyRes
@ -97,24 +78,26 @@ func (s *udpSource) run(ctx context.Context, cnf *conf.PathConf, _ chan *conf.Pa
return err
}
pc, err := net.ListenPacket(restrictNetwork("udp", addr.String()))
if err != nil {
return err
var pc packetConn
if ip4 := addr.IP.To4(); ip4 != nil && addr.IP.IsMulticast() {
pc, err = multicast.NewMultiConn(hostPort, net.ListenPacket)
if err != nil {
return err
}
} else {
tmp, err := net.ListenPacket(restrictNetwork("udp", addr.String()))
if err != nil {
return err
}
pc = tmp.(*net.UDPConn)
}
defer pc.Close()
if addr.IP.IsMulticast() {
p := ipv4.NewPacketConn(pc)
err = p.SetMulticastTTL(multicastTTL)
if err != nil {
return err
}
err = joinMulticastGroupOnAtLeastOneInterface(p, addr.IP)
if err != nil {
return err
}
err = pc.SetReadBuffer(udpKernelReadBufferSize)
if err != nil {
return err
}
readerErr := make(chan error)