Fix RTPSender.SetReadDeadline crash

Add nil pointer check when calling SetReadDeadline. I don't believe this
can happen with WebRTC, but is possible with `ortc`.

A future improvement would be to cache the `SetReadDeadline` call. At
this time the complexity seems to outweight the reward.

Resolves #2889
This commit is contained in:
Sean DuBois
2025-09-12 10:57:27 -04:00
parent 634a904ba9
commit 6ef2888a26
3 changed files with 32 additions and 10 deletions

View File

@@ -244,6 +244,7 @@ var (
errRTPSenderTrackNil = errors.New("Track must not be nil")
errRTPSenderDTLSTransportNil = errors.New("DTLSTransport must not be nil")
errRTPSenderSendAlreadyCalled = errors.New("Send has already been called")
errRTPSenderSendNotCalled = errors.New("Send has not been called")
errRTPSenderStopped = errors.New("Sender has already been stopped")
errRTPSenderTrackRemoved = errors.New("Sender Track has been removed or replaced to nil")
errRTPSenderRidNil = errors.New("Sender cannot add encoding as rid is empty")

View File

@@ -470,6 +470,10 @@ func (r *RTPSender) ReadSimulcastRTCP(rid string) ([]rtcp.Packet, interceptor.At
// SetReadDeadline sets the deadline for the Read operation.
// Setting to zero means no deadline.
func (r *RTPSender) SetReadDeadline(t time.Time) error {
if r.trackEncodings[0].srtpStream == nil {
return errRTPSenderSendNotCalled
}
return r.trackEncodings[0].srtpStream.SetReadDeadline(t)
}

View File

@@ -504,6 +504,20 @@ func Test_RTPSender_RTX_Support(t *testing.T) {
})
}
type TrackLocalCheckRTCPReaderOnBind struct {
*TrackLocalStaticSample
t *testing.T
bindCalled chan struct{}
}
func (s *TrackLocalCheckRTCPReaderOnBind) Bind(ctx TrackLocalContext) (RTPCodecParameters, error) {
assert.NotNil(s.t, ctx.RTCPReader())
p, err := s.TrackLocalStaticSample.Bind(ctx)
close(s.bindCalled)
return p, err
}
func Test_RTPSender_RTCPReader_Bind_Not_Nil(t *testing.T) {
track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
assert.NoError(t, err)
@@ -528,16 +542,19 @@ func Test_RTPSender_RTCPReader_Bind_Not_Nil(t *testing.T) {
assert.NoError(t, peerConnection.Close())
}
type TrackLocalCheckRTCPReaderOnBind struct {
*TrackLocalStaticSample
t *testing.T
bindCalled chan struct{}
}
func Test_RTPSender_SetReadDeadline_Crash(t *testing.T) {
stackA, stackB, err := newORTCPair()
assert.NoError(t, err)
func (s *TrackLocalCheckRTCPReaderOnBind) Bind(ctx TrackLocalContext) (RTPCodecParameters, error) {
assert.NotNil(s.t, ctx.RTCPReader())
p, err := s.TrackLocalStaticSample.Bind(ctx)
close(s.bindCalled)
assert.NoError(t, signalORTCPair(stackA, stackB))
return p, err
track, err := NewTrackLocalStaticSample(RTPCodecCapability{MimeType: MimeTypeVP8}, "video", "pion")
assert.NoError(t, err)
rtpSender, err := stackA.api.NewRTPSender(track, stackA.dtls)
assert.NoError(t, err)
assert.Error(t, rtpSender.SetReadDeadline(time.Time{}), errRTPSenderSendNotCalled)
assert.NoError(t, stackA.close())
assert.NoError(t, stackB.close())
}