From b9dfe1b310eaa7f0e2d02bb928447d05ccfd6c94 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Wed, 20 Jan 2021 23:23:35 +0100 Subject: [PATCH] client: support servers which don't provide UDP ports (#21) --- clientconf.go | 13 +++++++++---- clientconf_test.go | 37 +++++++++++++++++++++++++++++++++++-- clientconn.go | 8 +++++--- clientconnudpl.go | 2 +- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/clientconf.go b/clientconf.go index 1a35f3b8..751a06e2 100644 --- a/clientconf.go +++ b/clientconf.go @@ -39,6 +39,15 @@ type ClientConf struct { // It defaults to &tls.Config{InsecureSkipVerify:true} TLSConfig *tls.Config + // disable being redirected to other servers, that can happen during Describe(). + // It defaults to false. + RedirectDisable bool + + // enable communication with servers which don't provide server ports. + // this can be a security issue. + // It defaults to false. + AnyPortEnable bool + // timeout of read operations. // It defaults to 10 seconds. ReadTimeout time.Duration @@ -47,10 +56,6 @@ type ClientConf struct { // It defaults to 10 seconds. WriteTimeout time.Duration - // disable being redirected to other servers, that can happen during Describe(). - // It defaults to false. - RedirectDisable bool - // read buffer count. // If greater than 1, allows to pass buffers to routines different than the one // that is reading frames. diff --git a/clientconf_test.go b/clientconf_test.go index 02d58919..1c36197b 100644 --- a/clientconf_test.go +++ b/clientconf_test.go @@ -220,10 +220,43 @@ func TestClientDialReadZeroServerPorts(t *testing.T) { }, }.Write(bconn.Writer) require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Play, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + }.Write(bconn.Writer) + require.NoError(t, err) + + time.Sleep(1 * time.Second) + + l1, err := net.ListenPacket("udp", "localhost:0") + require.NoError(t, err) + defer l1.Close() + + l1.WriteTo([]byte("\x00\x00\x00\x00"), &net.UDPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: th.ClientPorts[0], + }) }() - _, err = DialRead("rtsp://localhost:8554/teststream") - require.Equal(t, "server ports are zero", err.Error()) + conf := ClientConf{ + AnyPortEnable: true, + } + + conn, err := conf.DialRead("rtsp://localhost:8554/teststream") + require.NoError(t, err) + + frameRecv := make(chan struct{}) + done := conn.ReadFrames(func(id int, typ StreamType, payload []byte) { + close(frameRecv) + }) + + <-frameRecv + conn.Close() + <-done } func TestClientDialReadAutomaticProtocol(t *testing.T) { diff --git a/clientconn.go b/clientconn.go index 5c1868f3..745bac7f 100644 --- a/clientconn.go +++ b/clientconn.go @@ -578,7 +578,7 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track, if thRes.ServerPorts == nil { rtpListener.close() rtcpListener.close() - return nil, fmt.Errorf("server ports not provided") + return nil, fmt.Errorf("server ports have not been provided. Use AnyPortEnable to communicate with this server") } if (thRes.ServerPorts[0] == 0 && thRes.ServerPorts[1] != 0) || @@ -588,8 +588,10 @@ func (c *ClientConn) Setup(mode headers.TransportMode, track *Track, return nil, fmt.Errorf("server ports must be both zero or both not zero") } - if thRes.ServerPorts[0] == 0 && thRes.ServerPorts[1] == 0 { - return nil, fmt.Errorf("server ports are zero") + if !c.conf.AnyPortEnable { + if thRes.ServerPorts[0] == 0 && thRes.ServerPorts[1] == 0 { + return nil, fmt.Errorf("server ports have not been provided. Use AnyPortEnable to communicate with this server") + } } } else { diff --git a/clientconnudpl.go b/clientconnudpl.go index 559a4118..84e63fd4 100644 --- a/clientconnudpl.go +++ b/clientconnudpl.go @@ -79,7 +79,7 @@ func (l *clientConnUDPListener) run() { uaddr := addr.(*net.UDPAddr) - if !l.remoteIP.Equal(uaddr.IP) || l.remotePort != uaddr.Port { + if !l.remoteIP.Equal(uaddr.IP) || (l.remotePort != 0 && l.remotePort != uaddr.Port) { continue }