udp: support using domain names instead of IPs (#2150)

This commit is contained in:
Alessandro Ros
2023-08-05 16:40:51 +02:00
committed by GitHub
parent 8bb71ac8d8
commit ce0924ac72
3 changed files with 95 additions and 12 deletions

View File

@@ -200,16 +200,11 @@ func (pconf *PathConf) check(conf *Conf, name string) error {
return fmt.Errorf("a path with a regular expression (or path 'all') cannot have a HLS source. use another path")
}
host, _, err := net.SplitHostPort(pconf.Source[len("udp://"):])
_, _, err := net.SplitHostPort(pconf.Source[len("udp://"):])
if err != nil {
return fmt.Errorf("'%s' is not a valid UDP URL", pconf.Source)
}
ip := net.ParseIP(host)
if ip == nil {
return fmt.Errorf("'%s' is not a valid IP", host)
}
case strings.HasPrefix(pconf.Source, "srt://"):
if pconf.Regexp != nil {
return fmt.Errorf("a path with a regular expression (or path 'all') cannot have a SRT source. use another path")

View File

@@ -92,16 +92,18 @@ func (s *udpSource) run(ctx context.Context, cnf *conf.PathConf, _ chan *conf.Pa
hostPort := cnf.Source[len("udp://"):]
pc, err := net.ListenPacket(restrictNetwork("udp", hostPort))
addr, err := net.ResolveUDPAddr("udp", hostPort)
if err != nil {
return err
}
pc, err := net.ListenPacket(restrictNetwork("udp", addr.String()))
if err != nil {
return err
}
defer pc.Close()
host, _, _ := net.SplitHostPort(hostPort)
ip := net.ParseIP(host)
if ip.IsMulticast() {
if addr.IP.IsMulticast() {
p := ipv4.NewPacketConn(pc)
err = p.SetMulticastTTL(multicastTTL)
@@ -109,7 +111,7 @@ func (s *udpSource) run(ctx context.Context, cnf *conf.PathConf, _ chan *conf.Pa
return err
}
err = joinMulticastGroupOnAtLeastOneInterface(p, ip)
err = joinMulticastGroupOnAtLeastOneInterface(p, addr.IP)
if err != nil {
return err
}

View File

@@ -0,0 +1,86 @@
package core
import (
"bufio"
"net"
"testing"
"time"
"github.com/bluenviron/gortsplib/v3"
"github.com/bluenviron/gortsplib/v3/pkg/formats"
"github.com/bluenviron/gortsplib/v3/pkg/url"
"github.com/bluenviron/mediacommon/pkg/formats/mpegts"
"github.com/pion/rtp"
"github.com/stretchr/testify/require"
)
func TestUDPSource(t *testing.T) {
p, ok := newInstance("paths:\n" +
" proxied:\n" +
" source: udp://localhost:9999\n" +
" sourceOnDemand: yes\n")
require.Equal(t, true, ok)
defer p.Close()
c := gortsplib.Client{}
u, err := url.Parse("rtsp://127.0.0.1:8554/proxied")
require.NoError(t, err)
err = c.Start(u.Scheme, u.Host)
require.NoError(t, err)
defer c.Close()
connected := make(chan struct{})
received := make(chan struct{})
go func() {
time.Sleep(200 * time.Millisecond)
conn, err := net.Dial("udp", "localhost:9999")
require.NoError(t, err)
defer conn.Close()
track := &mpegts.Track{
Codec: &mpegts.CodecH264{},
}
bw := bufio.NewWriter(conn)
w := mpegts.NewWriter(bw, []*mpegts.Track{track})
require.NoError(t, err)
err = w.WriteH26x(track, 0, 0, true, [][]byte{
{ // IDR
0x05, 1,
},
})
require.NoError(t, err)
bw.Flush()
<-connected
err = w.WriteH26x(track, 0, 0, true, [][]byte{{5, 2}})
require.NoError(t, err)
bw.Flush()
}()
medias, baseURL, _, err := c.Describe(u)
require.NoError(t, err)
var forma *formats.H264
medi := medias.FindFormat(&forma)
_, err = c.Setup(medi, baseURL, 0, 0)
require.NoError(t, err)
c.OnPacketRTP(medi, forma, func(pkt *rtp.Packet) {
require.Equal(t, []byte{5, 1}, pkt.Payload)
close(received)
})
_, err = c.Play(nil)
require.NoError(t, err)
close(connected)
<-received
}