From a005de1aa0e2384009e4ff211cb511f07e63633a Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Tue, 12 Sep 2023 00:27:08 +0200 Subject: [PATCH] udp: fix reading two streams with same port and different multicast IP (#2133) (#2332) Fixes #2133 --- go.mod | 4 +-- go.sum | 4 +-- internal/core/udp_source.go | 67 ++++++++++++++----------------------- 3 files changed, 29 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index fb92b468..bb34aca4 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 557e6d49..1b21def2 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/core/udp_source.go b/internal/core/udp_source.go index 66628633..dfb0a2eb 100644 --- a/internal/core/udp_source.go +++ b/internal/core/udp_source.go @@ -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)