From 2c2f99e1a37c410649b02a2c063cbde64886dd40 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Sat, 5 Jul 2025 11:13:51 +0200 Subject: [PATCH] client: open firewall before sending PLAY request (#821) this prevents losing some initial packets. --- client.go | 31 +++++++++++++++---------------- server_session_media.go | 4 +--- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/client.go b/client.go index 7e797db6..4e2ebae4 100644 --- a/client.go +++ b/client.go @@ -1765,6 +1765,21 @@ func (c *Client) doPlay(ra *headers.Range) (*base.Response, error) { header["Require"] = base.HeaderValue{"www.onvif.org/ver20/backchannel"} } + // when protocol is UDP, + // open the firewall by sending empty packets to the remote part. + // do this before sending the PLAY request. + if *c.effectiveTransport == TransportUDP { + for _, cm := range c.setuppedMedias { + if !cm.media.IsBackChannel { + byts, _ := (&rtp.Packet{Header: rtp.Header{Version: 2}}).Marshal() + cm.udpRTPListener.write(byts) //nolint:errcheck + + byts, _ = (&rtcp.ReceiverReport{}).Marshal() + cm.udpRTCPListener.write(byts) //nolint:errcheck + } + } + } + res, err := c.do(&base.Request{ Method: base.Play, URL: c.baseURL, @@ -1786,22 +1801,6 @@ func (c *Client) doPlay(ra *headers.Range) (*base.Response, error) { } } - // open the firewall by sending empty packets to the counterpart. - // do this before sending the request. - // don't do this with multicast, otherwise the RTP packet is going to be broadcasted - // to all listeners, including us, messing up the stream. - if *c.effectiveTransport == TransportUDP { - for _, cm := range c.setuppedMedias { - if !cm.media.IsBackChannel { - byts, _ := (&rtp.Packet{Header: rtp.Header{Version: 2}}).Marshal() - cm.udpRTPListener.write(byts) //nolint:errcheck - - byts, _ = (&rtcp.ReceiverReport{}).Marshal() - cm.udpRTCPListener.write(byts) //nolint:errcheck - } - } - } - c.startWriter() c.lastRange = ra diff --git a/server_session_media.go b/server_session_media.go index 8a7c5e36..a7e829bf 100644 --- a/server_session_media.go +++ b/server_session_media.go @@ -72,14 +72,12 @@ func (sm *serverSessionMedia) start() { if *sm.ss.setuppedTransport == TransportUDP { if sm.ss.state == ServerSessionStatePlay { - // firewall opening is performed with RTCP sender reports generated by ServerStream - if sm.media.IsBackChannel { sm.ss.s.udpRTPListener.addClient(sm.ss.author.ip(), sm.udpRTPReadPort, sm.readPacketRTPUDPPlay) } sm.ss.s.udpRTCPListener.addClient(sm.ss.author.ip(), sm.udpRTCPReadPort, sm.readPacketRTCPUDPPlay) } else { - // open the firewall by sending empty packets to the counterpart. + // open the firewall by sending empty packets to the remote part. byts, _ := (&rtp.Packet{Header: rtp.Header{Version: 2}}).Marshal() sm.ss.s.udpRTPListener.write(byts, sm.udpRTPWriteAddr) //nolint:errcheck