From 8e2c8682de1d68b32baad9999d762fd93eee6e9b Mon Sep 17 00:00:00 2001 From: cnderrauber Date: Fri, 29 Nov 2024 16:31:55 +0800 Subject: [PATCH] Add option to disable close by dtls Close peerconnection on DTLS.CloseNotify could break ice restart with dtls restart, when the dtls finger-print changed, the browser could teardown the old dtlstransport and establish new one then pion could close the peerconnection and restart failed. So browser don't do this and spec also don't say peerconnection should close when dtls is closed. --- peerconnection.go | 2 +- settingengine.go | 8 ++++++++ settingengine_test.go | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/peerconnection.go b/peerconnection.go index 4b2a16e39ca..5ac160c9afd 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -2417,7 +2417,7 @@ func (pc *PeerConnection) startTransports(iceRole ICERole, dtlsRole DTLSRole, re } pc.dtlsTransport.internalOnCloseHandler = func() { - if pc.isClosed.get() { + if pc.isClosed.get() || pc.api.settingEngine.disableCloseByDTLS { return } diff --git a/settingengine.go b/settingengine.go index 5fcafeb7615..fb2c40bc5fc 100644 --- a/settingengine.go +++ b/settingengine.go @@ -102,6 +102,7 @@ type SettingEngine struct { receiveMTU uint iceMaxBindingRequests *uint16 fireOnTrackBeforeFirstRTP bool + disableCloseByDTLS bool } // getReceiveMTU returns the configured MTU. If SettingEngine's MTU is configured to 0 it returns the default @@ -501,3 +502,10 @@ func (e *SettingEngine) SetICEBindingRequestHandler(bindingRequestHandler func(m func (e *SettingEngine) SetFireOnTrackBeforeFirstRTP(fireOnTrackBeforeFirstRTP bool) { e.fireOnTrackBeforeFirstRTP = fireOnTrackBeforeFirstRTP } + +// DisableCloseByDTLS sets if the connection should be closed when dtls transport is closed. +// Setting this to true will keep the connection open when dtls transport is closed +// and relies on the ice failed state to detect the connection is interrupted. +func (e *SettingEngine) DisableCloseByDTLS(isEnabled bool) { + e.disableCloseByDTLS = isEnabled +} diff --git a/settingengine_test.go b/settingengine_test.go index 6912694f497..8b786859fc7 100644 --- a/settingengine_test.go +++ b/settingengine_test.go @@ -394,3 +394,26 @@ func TestSetFireOnTrackBeforeFirstRTP(t *testing.T) { closePairNow(t, offerer, answerer) } + +func TestDisableCloseByDTLS(t *testing.T) { + lim := test.TimeOut(time.Second * 30) + defer lim.Stop() + + report := test.CheckRoutines(t) + defer report() + + s := SettingEngine{} + s.DisableCloseByDTLS(true) + + offer, answer, err := NewAPI(WithSettingEngine(s)).newPair(Configuration{}) + assert.NoError(t, err) + + assert.NoError(t, signalPair(offer, answer)) + + untilConnectionState(PeerConnectionStateConnected, offer, answer).Wait() + assert.NoError(t, answer.Close()) + + time.Sleep(time.Second) + assert.True(t, offer.ConnectionState() == PeerConnectionStateConnected) + assert.NoError(t, offer.Close()) +}