diff --git a/config-sample.yaml b/config-sample.yaml index aa2b01889..c800abd16 100644 --- a/config-sample.yaml +++ b/config-sample.yaml @@ -152,7 +152,7 @@ keys: # enable_remote_unmute: true # # limit size of room and participant's metadata, 0 for no limit # max_metadata_size: 0 -# # control playout delay in ms of video track (and associated audio track) +# # control playout delay in ms of video track (and associated audio track) # playout_delay: # enabled: true # min: 100 @@ -171,7 +171,7 @@ keys: # since v1.4.0, a more reliable, psrpc based signal relay is available # this gives us the ability to reliably proxy messages between a signal server and RTC node # signal_relay: -# # disabled by default. will be enabled by default in future versions +# # enabled by default as of v1.5.0, legacy signal proxy will be removed in v1.6 # enabled: true # # amount of time a message delivery is tried before giving up # retry_timeout: 30s diff --git a/go.mod b/go.mod index 021fba3cc..6150a1681 100644 --- a/go.mod +++ b/go.mod @@ -26,12 +26,13 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/pion/dtls/v2 v2.2.7 - github.com/pion/ice/v2 v2.3.10 + github.com/pion/ice/v2 v2.3.11 github.com/pion/interceptor v0.1.17 github.com/pion/rtcp v1.2.10 github.com/pion/rtp v1.8.1 + github.com/pion/sctp v1.8.7 github.com/pion/sdp/v3 v3.0.6 - github.com/pion/transport/v2 v2.2.1 + github.com/pion/transport/v2 v2.2.3 github.com/pion/turn/v2 v2.1.3 github.com/pion/webrtc/v3 v3.2.16 github.com/pkg/errors v0.9.1 @@ -64,7 +65,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/subcommands v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + github.com/google/uuid v1.3.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/josharian/native v1.1.0 // indirect @@ -80,9 +81,8 @@ require ( github.com/nats-io/nuid v1.0.1 // indirect github.com/pion/datachannel v1.5.5 // indirect github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.7 // indirect + github.com/pion/mdns v0.0.8 // indirect github.com/pion/randutil v0.1.0 // indirect - github.com/pion/sctp v1.8.7 // indirect github.com/pion/srtp/v2 v2.0.16 // indirect github.com/pion/stun v0.6.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index 602f95ac6..071770a9f 100644 --- a/go.sum +++ b/go.sum @@ -73,8 +73,9 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -184,14 +185,16 @@ github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/ice/v2 v2.3.10 h1:T3bUJKqh7pGEdMyTngUcTeQd6io9X8JjgsVWZDannnY= github.com/pion/ice/v2 v2.3.10/go.mod h1:hHGCibDfmXGqukayQw979xEctASp2Pe5Oe0iDU8pRus= +github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw= +github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E= github.com/pion/interceptor v0.1.17 h1:prJtgwFh/gB8zMqGZoOgJPHivOwVAp61i2aG61Du/1w= github.com/pion/interceptor v0.1.17/go.mod h1:SY8kpmfVBvrbUzvj2bsXz7OJt5JvmVNZ+4Kjq7FcwrI= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.7 h1:P0UB4Sr6xDWEox0kTVxF0LmQihtCbSAdW0H2nEgkA3U= github.com/pion/mdns v0.0.7/go.mod h1:4iP2UbeFhLI/vWju/bw6ZfwjJzk0z8DNValjGxR/dD8= +github.com/pion/mdns v0.0.8 h1:HhicWIg7OX5PVilyBO6plhMetInbzkVJAhbdJiAeVaI= +github.com/pion/mdns v0.0.8/go.mod h1:hYE72WX8WDveIhg7fmXgMKivD3Puklk0Ymzog0lSyaI= github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= github.com/pion/rtcp v1.2.10 h1:nkr3uj+8Sp97zyItdN60tE/S6vk4al5CPRR6Gejsdjc= @@ -214,8 +217,10 @@ github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99 github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= github.com/pion/transport/v2 v2.1.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= github.com/pion/transport/v2 v2.2.0/go.mod h1:AdSw4YBZVDkZm8fpoz+fclXyQwANWmZAlDuQdctTThQ= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= +github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= +github.com/pion/transport/v2 v2.2.3 h1:XcOE3/x41HOSKbl1BfyY1TF1dERx7lVvlMCbXU7kfvA= +github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= github.com/pion/turn/v2 v2.1.3 h1:pYxTVWG2gpC97opdRc5IGsQ1lJ9O/IlNhkzj7MMrGAA= github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= github.com/pion/webrtc/v3 v3.2.16 h1:2tfQ8qdyUAjeG5Zn44yE98umMtdxuHembJ3WYhj4Zd4= @@ -286,6 +291,7 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= @@ -322,6 +328,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= @@ -385,7 +392,9 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -395,6 +404,7 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= diff --git a/pkg/config/config.go b/pkg/config/config.go index 368282294..b8dc6044e 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -102,6 +102,9 @@ type RTCConfig struct { // force a reconnect on a subscription error ReconnectOnSubscriptionError *bool `yaml:"reconnect_on_subscription_error,omitempty"` + + // force a reconnect on a data channel error + ReconnectOnDataChannelError *bool `yaml:"reconnect_on_data_channel_error,omitempty"` } type TURNServer struct { @@ -473,7 +476,7 @@ var DefaultConfig = Config{ CPULoadLimit: 0.9, }, SignalRelay: SignalRelayConfig{ - Enabled: false, + Enabled: true, RetryTimeout: 7500 * time.Millisecond, MinRetryInterval: 500 * time.Millisecond, MaxRetryInterval: 4 * time.Second, diff --git a/pkg/routing/node.go b/pkg/routing/node.go index 16dc769a2..022d740ae 100644 --- a/pkg/routing/node.go +++ b/pkg/routing/node.go @@ -27,10 +27,7 @@ import ( type LocalNode *livekit.Node func NewLocalNode(conf *config.Config) (LocalNode, error) { - nodeID, err := utils.LocalNodeID() - if err != nil { - return nil, err - } + nodeID := utils.NewGuid(utils.NodePrefix) if conf.RTC.NodeIP == "" { return nil, ErrIPNotSet } diff --git a/pkg/routing/redisrouter.go b/pkg/routing/redisrouter.go index ef679261f..a3e7e8365 100644 --- a/pkg/routing/redisrouter.go +++ b/pkg/routing/redisrouter.go @@ -212,7 +212,7 @@ func (r *RedisRouter) WriteParticipantRTC(_ context.Context, roomName livekit.Ro return err } - rtcSink := NewRTCNodeSink(r.rc, livekit.NodeID(rtcNode), livekit.ConnectionID("ephemeral"), pkey, pkeyB62) + rtcSink := NewRTCNodeSink(r.rc, livekit.NodeID(rtcNode), "ephemeral", pkey, pkeyB62) msg.ParticipantKey = string(ParticipantKeyLegacy(roomName, identity)) msg.ParticipantKeyB62 = string(ParticipantKey(roomName, identity)) return r.writeRTCMessage(rtcSink, msg) @@ -229,7 +229,7 @@ func (r *RedisRouter) WriteRoomRTC(ctx context.Context, roomName livekit.RoomNam } func (r *RedisRouter) WriteNodeRTC(_ context.Context, rtcNodeID string, msg *livekit.RTCNodeMessage) error { - rtcSink := NewRTCNodeSink(r.rc, livekit.NodeID(rtcNodeID), livekit.ConnectionID("ephemeral"), livekit.ParticipantKey(msg.ParticipantKey), livekit.ParticipantKey(msg.ParticipantKeyB62)) + rtcSink := NewRTCNodeSink(r.rc, livekit.NodeID(rtcNodeID), "ephemeral", livekit.ParticipantKey(msg.ParticipantKey), livekit.ParticipantKey(msg.ParticipantKeyB62)) return r.writeRTCMessage(rtcSink, msg) } diff --git a/pkg/rtc/errors.go b/pkg/rtc/errors.go index 383afde0d..656995632 100644 --- a/pkg/rtc/errors.go +++ b/pkg/rtc/errors.go @@ -23,6 +23,7 @@ var ( ErrLimitExceeded = errors.New("node has exceeded its configured limit") ErrAlreadyJoined = errors.New("a participant with the same identity is already in the room") ErrDataChannelUnavailable = errors.New("data channel is not available") + ErrTransportFailure = errors.New("transport failure") ErrEmptyIdentity = errors.New("participant identity cannot be empty") ErrEmptyParticipantID = errors.New("participant ID cannot be empty") ErrMissingGrants = errors.New("VideoGrant is missing") diff --git a/pkg/rtc/participant.go b/pkg/rtc/participant.go index 3b4518c51..005ff5141 100644 --- a/pkg/rtc/participant.go +++ b/pkg/rtc/participant.go @@ -16,6 +16,7 @@ package rtc import ( "context" + "io" "os" "strconv" "strings" @@ -24,6 +25,7 @@ import ( lru "github.com/hashicorp/golang-lru/v2" "github.com/pion/rtcp" + "github.com/pion/sctp" "github.com/pion/sdp/v3" "github.com/pion/webrtc/v3" "github.com/pkg/errors" @@ -103,6 +105,7 @@ type ParticipantParams struct { GetParticipantInfo func(pID livekit.ParticipantID) *livekit.ParticipantInfo ReconnectOnPublicationError bool ReconnectOnSubscriptionError bool + ReconnectOnDataChannelError bool VersionGenerator utils.TimedVersionGenerator TrackResolver types.MediaTrackResolver DisableDynacast bool @@ -2143,6 +2146,8 @@ func (p *ParticipantImpl) IssueFullReconnect(reason types.ParticipantCloseReason scr = types.SignallingCloseReasonFullReconnectPublicationError case types.ParticipantCloseReasonSubscriptionError: scr = types.SignallingCloseReasonFullReconnectSubscriptionError + case types.ParticipantCloseReasonDataChannelError: + scr = types.SignallingCloseReasonFullReconnectDataChannelError case types.ParticipantCloseReasonNegotiateFailed: scr = types.SignallingCloseReasonFullReconnectNegotiateFailed } @@ -2251,7 +2256,12 @@ func (p *ParticipantImpl) SendDataPacket(dp *livekit.DataPacket, data []byte) er } err := p.TransportManager.SendDataPacket(dp, data) - if err == nil { + if err != nil { + if (err == sctp.ErrStreamClosed || err == io.ErrClosedPipe) && p.params.ReconnectOnDataChannelError { + p.params.Logger.Infow("issuing full reconnect on data channel error") + p.IssueFullReconnect(types.ParticipantCloseReasonDataChannelError) + } + } else { p.dataChannelStats.AddBytes(uint64(len(data)), true) } return err diff --git a/pkg/rtc/transport.go b/pkg/rtc/transport.go index fc13fe314..47464e6b9 100644 --- a/pkg/rtc/transport.go +++ b/pkg/rtc/transport.go @@ -662,9 +662,9 @@ func (t *PCTransport) onPeerConnectionStateChange(state webrtc.PeerConnectionSta } func (t *PCTransport) onDataChannel(dc *webrtc.DataChannel) { + t.params.Logger.Debugw(dc.Label() + " data channel open") switch dc.Label() { case ReliableDataChannel: - t.params.Logger.Debugw("reliable data channel open") t.lock.Lock() t.reliableDC = dc t.reliableDCOpened = true @@ -677,7 +677,6 @@ func (t *PCTransport) onDataChannel(dc *webrtc.DataChannel) { t.maybeNotifyFullyEstablished() case LossyDataChannel: - t.params.Logger.Debugw("lossy data channel open") t.lock.Lock() t.lossyDC = dc t.lossyDCOpened = true @@ -762,7 +761,6 @@ func (t *PCTransport) AddTrack(trackLocal webrtc.TrackLocal, params types.AddTra } configureAudioTransceiver(transceiver, params.Stereo, !params.Red || !t.params.ClientInfo.SupportsAudioRED()) - return } @@ -833,7 +831,7 @@ func (t *PCTransport) CreateDataChannel(label string, dci *webrtc.DataChannelIni } dcErrorHandler := func(err error) { - t.params.Logger.Errorw(dc.Label()+" data channel close", err) + t.params.Logger.Errorw(dc.Label()+" data channel error", err) } t.lock.Lock() @@ -924,6 +922,10 @@ func (t *PCTransport) SendDataPacket(dp *livekit.DataPacket, data []byte) error return ErrDataChannelUnavailable } + if t.pc.ConnectionState() == webrtc.PeerConnectionStateFailed { + return ErrTransportFailure + } + return dc.Send(data) } diff --git a/pkg/rtc/types/interfaces.go b/pkg/rtc/types/interfaces.go index 5275b5ad3..e5e44d992 100644 --- a/pkg/rtc/types/interfaces.go +++ b/pkg/rtc/types/interfaces.go @@ -102,6 +102,7 @@ const ( ParticipantCloseReasonOvercommitted ParticipantCloseReasonPublicationError ParticipantCloseReasonSubscriptionError + ParticipantCloseReasonDataChannelError ) func (p ParticipantCloseReason) String() string { @@ -148,6 +149,8 @@ func (p ParticipantCloseReason) String() string { return "PUBLICATION_ERROR" case ParticipantCloseReasonSubscriptionError: return "SUBSCRIPTION_ERROR" + case ParticipantCloseReasonDataChannelError: + return "DATA_CHANNEL_ERROR" default: return fmt.Sprintf("%d", int(p)) } @@ -178,7 +181,7 @@ func (p ParticipantCloseReason) ToDisconnectReason() livekit.DisconnectReason { return livekit.DisconnectReason_SERVER_SHUTDOWN case ParticipantCloseReasonOvercommitted: return livekit.DisconnectReason_SERVER_SHUTDOWN - case ParticipantCloseReasonNegotiateFailed, ParticipantCloseReasonPublicationError, ParticipantCloseReasonSubscriptionError: + case ParticipantCloseReasonNegotiateFailed, ParticipantCloseReasonPublicationError, ParticipantCloseReasonSubscriptionError, ParticipantCloseReasonDataChannelError: return livekit.DisconnectReason_STATE_MISMATCH default: // the other types will map to unknown reason @@ -197,6 +200,7 @@ const ( SignallingCloseReasonTransportFailure SignallingCloseReasonFullReconnectPublicationError SignallingCloseReasonFullReconnectSubscriptionError + SignallingCloseReasonFullReconnectDataChannelError SignallingCloseReasonFullReconnectNegotiateFailed SignallingCloseReasonParticipantClose ) @@ -215,6 +219,8 @@ func (s SignallingCloseReason) String() string { return "FULL_RECONNECT_PUBLICATION_ERROR" case SignallingCloseReasonFullReconnectSubscriptionError: return "FULL_RECONNECT_SUBSCRIPTION_ERROR" + case SignallingCloseReasonFullReconnectDataChannelError: + return "FULL_RECONNECT_DATA_CHANNEL_ERROR" case SignallingCloseReasonFullReconnectNegotiateFailed: return "FULL_RECONNECT_NEGOTIATE_FAILED" case SignallingCloseReasonParticipantClose: diff --git a/pkg/service/roommanager.go b/pkg/service/roommanager.go index 2dec20064..6393e55be 100644 --- a/pkg/service/roommanager.go +++ b/pkg/service/roommanager.go @@ -355,6 +355,11 @@ func (r *RoomManager) StartSession( if r.config.RTC.ReconnectOnSubscriptionError != nil { reconnectOnSubscriptionError = *r.config.RTC.ReconnectOnSubscriptionError } + // default do not force full reconnect on a data channel error + reconnectOnDataChannelError := false + if r.config.RTC.ReconnectOnDataChannelError != nil { + reconnectOnDataChannelError = *r.config.RTC.ReconnectOnDataChannelError + } subscriberAllowPause := r.config.RTC.CongestionControl.AllowPause if pi.SubscriberAllowPause != nil { subscriberAllowPause = *pi.SubscriberAllowPause @@ -389,6 +394,7 @@ func (r *RoomManager) StartSession( }, ReconnectOnPublicationError: reconnectOnPublicationError, ReconnectOnSubscriptionError: reconnectOnSubscriptionError, + ReconnectOnDataChannelError: reconnectOnDataChannelError, VersionGenerator: r.versionGenerator, TrackResolver: room.ResolveMediaTrackForSubscriber, SubscriberAllowPause: subscriberAllowPause,