mirror of
https://github.com/livekit/livekit.git
synced 2026-05-14 16:15:25 +00:00
Add support for WHIP ICE Trickle/Restart. (#3596)
* Add support for WHIP ICE Trickle/Restart. Tested a bit using the WHIP client at https://github.com/Eyevinn/whip, but needs a lot more testing. ICERestart is not tested yet. * comment * clean up
This commit is contained in:
@@ -23,7 +23,7 @@ require (
|
||||
github.com/jxskiss/base62 v1.1.0
|
||||
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1
|
||||
github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6
|
||||
github.com/livekit/protocol v1.36.2-0.20250408143132-c193b8d080da
|
||||
github.com/livekit/protocol v1.36.2-0.20250408183714-0975d348643e
|
||||
github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126
|
||||
github.com/mackerelio/go-osstat v0.2.5
|
||||
github.com/magefile/mage v1.15.0
|
||||
@@ -55,7 +55,7 @@ require (
|
||||
go.uber.org/atomic v1.11.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0
|
||||
golang.org/x/mod v0.24.0
|
||||
golang.org/x/sync v0.13.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
@@ -133,10 +133,10 @@ require (
|
||||
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.37.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250407143221-ac9807e6c755 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250407143221-ac9807e6c755 // indirect
|
||||
google.golang.org/grpc v1.71.1 // indirect
|
||||
|
||||
@@ -171,8 +171,8 @@ github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1 h1:jm09419p0lqTkD
|
||||
github.com/livekit/mageutil v0.0.0-20230125210925-54e8a70427c1/go.mod h1:Rs3MhFwutWhGwmY1VQsygw28z5bWcnEYmS1OG9OxjOQ=
|
||||
github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6 h1:6ZhtnY9I9knfm3ieIPpznQSEU2rDECO8yliW/ANLQ7U=
|
||||
github.com/livekit/mediatransportutil v0.0.0-20250310153736-45596af895b6/go.mod h1:36s+wwmU3O40IAhE+MjBWP3W71QRiEE9SfooSBvtBqY=
|
||||
github.com/livekit/protocol v1.36.2-0.20250408143132-c193b8d080da h1:KZ2almsG7lNk0/4FhpLEuX5JOq5QVh8eCVhfsf4821M=
|
||||
github.com/livekit/protocol v1.36.2-0.20250408143132-c193b8d080da/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4=
|
||||
github.com/livekit/protocol v1.36.2-0.20250408183714-0975d348643e h1:uCdTqLPDVdJeJdXkSx7hlfUlY1MBmfBo8fOk2TF28cU=
|
||||
github.com/livekit/protocol v1.36.2-0.20250408183714-0975d348643e/go.mod h1:WrT/CYRxtMNOVUjnIPm5OjWtEkmreffTeE1PRZwlRg4=
|
||||
github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126 h1:fzuYpAQbCid7ySPpQWWePfQOWUrs8x6dJ0T3Wl07n+Y=
|
||||
github.com/livekit/psrpc v0.6.1-0.20250205181828-a0beed2e4126/go.mod h1:X5WtEZ7OnEs72Fi5/J+i0on3964F1aynQpCalcgMqRo=
|
||||
github.com/mackerelio/go-osstat v0.2.5 h1:+MqTbZUhoIt4m8qzkVoXUJg1EuifwlAJSk4Yl2GXh+o=
|
||||
@@ -367,8 +367,8 @@ golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1m
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
|
||||
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM=
|
||||
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@@ -399,8 +399,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -471,8 +471,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
|
||||
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -903,11 +903,7 @@ func (p *ParticipantImpl) HandleOffer(offer webrtc.SessionDescription) error {
|
||||
}
|
||||
|
||||
offer = p.setCodecPreferencesForPublisher(offer)
|
||||
err := p.TransportManager.HandleOffer(offer, shouldPend)
|
||||
if p.params.UseOneShotSignallingMode {
|
||||
p.updateState(livekit.ParticipantInfo_ACTIVE)
|
||||
}
|
||||
return err
|
||||
return p.TransportManager.HandleOffer(offer, shouldPend)
|
||||
}
|
||||
|
||||
func (p *ParticipantImpl) onPublisherAnswer(answer webrtc.SessionDescription) error {
|
||||
|
||||
+189
-2
@@ -93,6 +93,11 @@ var (
|
||||
ErrMidNotFound = errors.New("mid not found")
|
||||
ErrNotSynchronousPeerConnectionMode = errors.New("not using synchronous peer connection mode")
|
||||
ErrNoRemoteDescription = errors.New("no remote description")
|
||||
ErrNoLocalDescription = errors.New("no local description")
|
||||
ErrInvalidSDPFragment = errors.New("invalid sdp fragment")
|
||||
ErrNoBundleMid = errors.New("could not get bundle mid")
|
||||
ErrMidMismatch = errors.New("media mid does not match bundle mid")
|
||||
ErrICECredentialMismatch = errors.New("ice credential mismatch")
|
||||
)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@@ -871,7 +876,7 @@ func (t *PCTransport) isFullyEstablished() bool {
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
|
||||
dataChannelReady := t.firstOfferNoDataChannel || (t.reliableDCOpened && t.lossyDCOpened)
|
||||
dataChannelReady := t.params.UseOneShotSignallingMode || t.firstOfferNoDataChannel || (t.reliableDCOpened && t.lossyDCOpened)
|
||||
|
||||
return dataChannelReady && !t.connectedAt.IsZero()
|
||||
}
|
||||
@@ -1317,6 +1322,188 @@ func (t *PCTransport) GetAnswer() (webrtc.SessionDescription, error) {
|
||||
return *cld, nil
|
||||
}
|
||||
|
||||
func (t *PCTransport) GetICESessionUfrag() (string, error) {
|
||||
cld := t.pc.CurrentLocalDescription()
|
||||
if cld == nil {
|
||||
return "", ErrNoLocalDescription
|
||||
}
|
||||
|
||||
parsed, err := cld.Unmarshal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ufrag, _, err := lksdp.ExtractICECredential(parsed)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ufrag, nil
|
||||
}
|
||||
|
||||
// Handles SDP Fragment for ICE Trickle in WHIP
|
||||
func (t *PCTransport) HandleICETrickleSDPFragment(sdpFragment string) error {
|
||||
if !t.params.UseOneShotSignallingMode {
|
||||
return ErrNotSynchronousPeerConnectionMode
|
||||
}
|
||||
|
||||
parsedFragment := &lksdp.SDPFragment{}
|
||||
if err := parsedFragment.Unmarshal(sdpFragment); err != nil {
|
||||
t.params.Logger.Warnw("could not parse SDP fragment", err, "sdpFragment", sdpFragment)
|
||||
return ErrInvalidSDPFragment
|
||||
}
|
||||
|
||||
crd := t.pc.CurrentRemoteDescription()
|
||||
if crd == nil {
|
||||
t.params.Logger.Warnw("no remote description", nil)
|
||||
return ErrNoRemoteDescription
|
||||
}
|
||||
|
||||
parsedRemote, err := crd.Unmarshal()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not parse remote description", err, "offer", crd)
|
||||
return err
|
||||
}
|
||||
|
||||
// check if BUNDLE mid matches the "mid" in the SDP fragment
|
||||
bundleMid, found := lksdp.GetBundleMid(parsedRemote)
|
||||
if !found {
|
||||
return ErrNoBundleMid
|
||||
}
|
||||
|
||||
if parsedFragment.Mid() != bundleMid {
|
||||
t.params.Logger.Warnw("incorrect mid", nil, "sdpFragment", sdpFragment)
|
||||
return ErrMidMismatch
|
||||
}
|
||||
|
||||
fragmentICEUfrag, fragmentICEPwd, err := parsedFragment.ExtractICECredential()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw(
|
||||
"could not get ICE crendential from fragment", err,
|
||||
"sdpFragment", sdpFragment,
|
||||
)
|
||||
return ErrInvalidSDPFragment
|
||||
}
|
||||
remoteICEUfrag, remoteICEPwd, err := lksdp.ExtractICECredential(parsedRemote)
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not get ICE crendential from remote description", err, "sdpFragment", sdpFragment, "remoteDescription", crd)
|
||||
return err
|
||||
}
|
||||
if fragmentICEUfrag != "" && fragmentICEUfrag != remoteICEUfrag {
|
||||
t.params.Logger.Warnw(
|
||||
"ice ufrag mismatch", nil,
|
||||
"remoteICEUfrag", remoteICEUfrag,
|
||||
"fragmentICEUfrag", fragmentICEUfrag,
|
||||
"sdpFragment", sdpFragment,
|
||||
"remoteDescription", crd,
|
||||
)
|
||||
return ErrICECredentialMismatch
|
||||
}
|
||||
if fragmentICEPwd != "" && fragmentICEPwd != remoteICEPwd {
|
||||
t.params.Logger.Warnw(
|
||||
"ice pwd mismatch", nil,
|
||||
"remoteICEPwd", remoteICEPwd,
|
||||
"fragmentICEPwd", fragmentICEPwd,
|
||||
"sdpFragment", sdpFragment,
|
||||
"remoteDescription", crd,
|
||||
)
|
||||
return ErrICECredentialMismatch
|
||||
}
|
||||
|
||||
// add candidates from media description
|
||||
for _, ic := range parsedFragment.Candidates() {
|
||||
c, err := ice.UnmarshalCandidate(ic)
|
||||
if err == nil {
|
||||
t.connectionDetails.AddRemoteICECandidate(c, false, false, false)
|
||||
}
|
||||
|
||||
candidate := webrtc.ICECandidateInit{
|
||||
Candidate: ic,
|
||||
}
|
||||
if err := t.pc.AddICECandidate(candidate); err != nil {
|
||||
t.params.Logger.Warnw("failed to add ICE candidate", err, "candidate", candidate)
|
||||
} else {
|
||||
t.params.Logger.Debugw("added ICE candidate", "candidate", candidate)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handles SDP Fragment for ICE Restart in WHIP
|
||||
func (t *PCTransport) HandleICERestartSDPFragment(sdpFragment string) (string, error) {
|
||||
if !t.params.UseOneShotSignallingMode {
|
||||
return "", ErrNotSynchronousPeerConnectionMode
|
||||
}
|
||||
|
||||
parsedFragment := &lksdp.SDPFragment{}
|
||||
if err := parsedFragment.Unmarshal(sdpFragment); err != nil {
|
||||
t.params.Logger.Warnw("could not parse SDP fragment", err, "sdpFragment", sdpFragment)
|
||||
return "", ErrInvalidSDPFragment
|
||||
}
|
||||
|
||||
crd := t.pc.CurrentRemoteDescription()
|
||||
if crd == nil {
|
||||
t.params.Logger.Warnw("no remote description", nil)
|
||||
return "", ErrNoRemoteDescription
|
||||
}
|
||||
|
||||
parsedRemote, err := crd.Unmarshal()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not parse remote description", err, "offer", crd)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := parsedFragment.PatchICECredentialIntoSDP(parsedRemote); err != nil {
|
||||
t.params.Logger.Warnw("could not patch SDP fragment into remote description", err, "offer", crd, "sdpFragment", sdpFragment)
|
||||
return "", err
|
||||
}
|
||||
|
||||
bytes, err := parsedRemote.Marshal()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not marshal SDP with patched remote", err)
|
||||
return "", err
|
||||
}
|
||||
sd := webrtc.SessionDescription{
|
||||
SDP: string(bytes),
|
||||
Type: webrtc.SDPTypeOffer,
|
||||
}
|
||||
if err := t.pc.SetRemoteDescription(sd); err != nil {
|
||||
t.params.Logger.Warnw("could not set remote description", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
ans, err := t.pc.CreateAnswer(nil)
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not create answer", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = t.pc.SetLocalDescription(ans); err != nil {
|
||||
t.params.Logger.Warnw("could not set local description", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
parsedAnswer, err := ans.Unmarshal()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not parse local description", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
parsedFragmentAnswer, err := lksdp.ExtractSDPFragment(parsedAnswer)
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not extract SDP fragment", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
answerFragment, err := parsedFragmentAnswer.Marshal()
|
||||
if err != nil {
|
||||
t.params.Logger.Warnw("could not marshal answer SDP fragment", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return answerFragment, nil
|
||||
}
|
||||
|
||||
func (t *PCTransport) OnNegotiationStateChanged(f func(state transport.NegotiationState)) {
|
||||
t.lock.Lock()
|
||||
t.onNegotiationStateChanged = f
|
||||
@@ -1752,7 +1939,7 @@ func (t *PCTransport) handleRemoteICECandidate(e event) error {
|
||||
}
|
||||
|
||||
if err := t.pc.AddICECandidate(*c); err != nil {
|
||||
t.params.Logger.Warnw("failed to add cached ICE candidate", err, "candidate", c)
|
||||
t.params.Logger.Warnw("failed to add ICE candidate", err, "candidate", c)
|
||||
return errors.Wrap(err, "add ice candidate failed")
|
||||
} else {
|
||||
t.params.Logger.Debugw("added ICE candidate", "candidate", c)
|
||||
|
||||
@@ -462,6 +462,18 @@ func (t *TransportManager) GetAnswer() (webrtc.SessionDescription, error) {
|
||||
return answer, err
|
||||
}
|
||||
|
||||
func (t *TransportManager) GetPublisherICESessionUfrag() (string, error) {
|
||||
return t.publisher.GetICESessionUfrag()
|
||||
}
|
||||
|
||||
func (t *TransportManager) HandleICETrickleSDPFragment(sdpFragment string) error {
|
||||
return t.publisher.HandleICETrickleSDPFragment(sdpFragment)
|
||||
}
|
||||
|
||||
func (t *TransportManager) HandleICERestartSDPFragment(sdpFragment string) (string, error) {
|
||||
return t.publisher.HandleICERestartSDPFragment(sdpFragment)
|
||||
}
|
||||
|
||||
func (t *TransportManager) ProcessPendingPublisherOffer() {
|
||||
t.lock.Lock()
|
||||
pendingOffer := t.pendingOfferPublisher
|
||||
|
||||
@@ -340,6 +340,7 @@ type LocalParticipant interface {
|
||||
GetICEConnectionInfo() []*ICEConnectionInfo
|
||||
HasConnected() bool
|
||||
GetEnabledPublishCodecs() []*livekit.Codec
|
||||
GetPublisherICESessionUfrag() (string, error)
|
||||
|
||||
SetResponseSink(sink routing.MessageSink)
|
||||
CloseSignalConnection(reason SignallingCloseReason)
|
||||
@@ -367,6 +368,8 @@ type LocalParticipant interface {
|
||||
AddICECandidate(candidate webrtc.ICECandidateInit, target livekit.SignalTarget)
|
||||
HandleOffer(sdp webrtc.SessionDescription) error
|
||||
GetAnswer() (webrtc.SessionDescription, error)
|
||||
HandleICETrickleSDPFragment(sdpFragment string) error
|
||||
HandleICERestartSDPFragment(sdpFragment string) (string, error)
|
||||
AddTrack(req *livekit.AddTrackRequest)
|
||||
SetTrackMuted(trackID livekit.TrackID, muted bool, fromAdmin bool) *livekit.TrackInfo
|
||||
|
||||
|
||||
@@ -390,6 +390,18 @@ type FakeLocalParticipant struct {
|
||||
getPublishedTracksReturnsOnCall map[int]struct {
|
||||
result1 []types.MediaTrack
|
||||
}
|
||||
GetPublisherICESessionUfragStub func() (string, error)
|
||||
getPublisherICESessionUfragMutex sync.RWMutex
|
||||
getPublisherICESessionUfragArgsForCall []struct {
|
||||
}
|
||||
getPublisherICESessionUfragReturns struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
getPublisherICESessionUfragReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
GetSubscribedParticipantsStub func() []livekit.ParticipantID
|
||||
getSubscribedParticipantsMutex sync.RWMutex
|
||||
getSubscribedParticipantsArgsForCall []struct {
|
||||
@@ -425,6 +437,30 @@ type FakeLocalParticipant struct {
|
||||
handleAnswerArgsForCall []struct {
|
||||
arg1 webrtc.SessionDescription
|
||||
}
|
||||
HandleICERestartSDPFragmentStub func(string) (string, error)
|
||||
handleICERestartSDPFragmentMutex sync.RWMutex
|
||||
handleICERestartSDPFragmentArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
handleICERestartSDPFragmentReturns struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
handleICERestartSDPFragmentReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
HandleICETrickleSDPFragmentStub func(string) error
|
||||
handleICETrickleSDPFragmentMutex sync.RWMutex
|
||||
handleICETrickleSDPFragmentArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
handleICETrickleSDPFragmentReturns struct {
|
||||
result1 error
|
||||
}
|
||||
handleICETrickleSDPFragmentReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
HandleMetricsStub func(livekit.ParticipantID, *livekit.MetricsBatch) error
|
||||
handleMetricsMutex sync.RWMutex
|
||||
handleMetricsArgsForCall []struct {
|
||||
@@ -3124,6 +3160,62 @@ func (fake *FakeLocalParticipant) GetPublishedTracksReturnsOnCall(i int, result1
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetPublisherICESessionUfrag() (string, error) {
|
||||
fake.getPublisherICESessionUfragMutex.Lock()
|
||||
ret, specificReturn := fake.getPublisherICESessionUfragReturnsOnCall[len(fake.getPublisherICESessionUfragArgsForCall)]
|
||||
fake.getPublisherICESessionUfragArgsForCall = append(fake.getPublisherICESessionUfragArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.GetPublisherICESessionUfragStub
|
||||
fakeReturns := fake.getPublisherICESessionUfragReturns
|
||||
fake.recordInvocation("GetPublisherICESessionUfrag", []interface{}{})
|
||||
fake.getPublisherICESessionUfragMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetPublisherICESessionUfragCallCount() int {
|
||||
fake.getPublisherICESessionUfragMutex.RLock()
|
||||
defer fake.getPublisherICESessionUfragMutex.RUnlock()
|
||||
return len(fake.getPublisherICESessionUfragArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetPublisherICESessionUfragCalls(stub func() (string, error)) {
|
||||
fake.getPublisherICESessionUfragMutex.Lock()
|
||||
defer fake.getPublisherICESessionUfragMutex.Unlock()
|
||||
fake.GetPublisherICESessionUfragStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetPublisherICESessionUfragReturns(result1 string, result2 error) {
|
||||
fake.getPublisherICESessionUfragMutex.Lock()
|
||||
defer fake.getPublisherICESessionUfragMutex.Unlock()
|
||||
fake.GetPublisherICESessionUfragStub = nil
|
||||
fake.getPublisherICESessionUfragReturns = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetPublisherICESessionUfragReturnsOnCall(i int, result1 string, result2 error) {
|
||||
fake.getPublisherICESessionUfragMutex.Lock()
|
||||
defer fake.getPublisherICESessionUfragMutex.Unlock()
|
||||
fake.GetPublisherICESessionUfragStub = nil
|
||||
if fake.getPublisherICESessionUfragReturnsOnCall == nil {
|
||||
fake.getPublisherICESessionUfragReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.getPublisherICESessionUfragReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) GetSubscribedParticipants() []livekit.ParticipantID {
|
||||
fake.getSubscribedParticipantsMutex.Lock()
|
||||
ret, specificReturn := fake.getSubscribedParticipantsReturnsOnCall[len(fake.getSubscribedParticipantsArgsForCall)]
|
||||
@@ -3315,6 +3407,131 @@ func (fake *FakeLocalParticipant) HandleAnswerArgsForCall(i int) webrtc.SessionD
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragment(arg1 string) (string, error) {
|
||||
fake.handleICERestartSDPFragmentMutex.Lock()
|
||||
ret, specificReturn := fake.handleICERestartSDPFragmentReturnsOnCall[len(fake.handleICERestartSDPFragmentArgsForCall)]
|
||||
fake.handleICERestartSDPFragmentArgsForCall = append(fake.handleICERestartSDPFragmentArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.HandleICERestartSDPFragmentStub
|
||||
fakeReturns := fake.handleICERestartSDPFragmentReturns
|
||||
fake.recordInvocation("HandleICERestartSDPFragment", []interface{}{arg1})
|
||||
fake.handleICERestartSDPFragmentMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragmentCallCount() int {
|
||||
fake.handleICERestartSDPFragmentMutex.RLock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.RUnlock()
|
||||
return len(fake.handleICERestartSDPFragmentArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragmentCalls(stub func(string) (string, error)) {
|
||||
fake.handleICERestartSDPFragmentMutex.Lock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.Unlock()
|
||||
fake.HandleICERestartSDPFragmentStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragmentArgsForCall(i int) string {
|
||||
fake.handleICERestartSDPFragmentMutex.RLock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.RUnlock()
|
||||
argsForCall := fake.handleICERestartSDPFragmentArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragmentReturns(result1 string, result2 error) {
|
||||
fake.handleICERestartSDPFragmentMutex.Lock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.Unlock()
|
||||
fake.HandleICERestartSDPFragmentStub = nil
|
||||
fake.handleICERestartSDPFragmentReturns = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICERestartSDPFragmentReturnsOnCall(i int, result1 string, result2 error) {
|
||||
fake.handleICERestartSDPFragmentMutex.Lock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.Unlock()
|
||||
fake.HandleICERestartSDPFragmentStub = nil
|
||||
if fake.handleICERestartSDPFragmentReturnsOnCall == nil {
|
||||
fake.handleICERestartSDPFragmentReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.handleICERestartSDPFragmentReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragment(arg1 string) error {
|
||||
fake.handleICETrickleSDPFragmentMutex.Lock()
|
||||
ret, specificReturn := fake.handleICETrickleSDPFragmentReturnsOnCall[len(fake.handleICETrickleSDPFragmentArgsForCall)]
|
||||
fake.handleICETrickleSDPFragmentArgsForCall = append(fake.handleICETrickleSDPFragmentArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.HandleICETrickleSDPFragmentStub
|
||||
fakeReturns := fake.handleICETrickleSDPFragmentReturns
|
||||
fake.recordInvocation("HandleICETrickleSDPFragment", []interface{}{arg1})
|
||||
fake.handleICETrickleSDPFragmentMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragmentCallCount() int {
|
||||
fake.handleICETrickleSDPFragmentMutex.RLock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.RUnlock()
|
||||
return len(fake.handleICETrickleSDPFragmentArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragmentCalls(stub func(string) error) {
|
||||
fake.handleICETrickleSDPFragmentMutex.Lock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.Unlock()
|
||||
fake.HandleICETrickleSDPFragmentStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragmentArgsForCall(i int) string {
|
||||
fake.handleICETrickleSDPFragmentMutex.RLock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.RUnlock()
|
||||
argsForCall := fake.handleICETrickleSDPFragmentArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragmentReturns(result1 error) {
|
||||
fake.handleICETrickleSDPFragmentMutex.Lock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.Unlock()
|
||||
fake.HandleICETrickleSDPFragmentStub = nil
|
||||
fake.handleICETrickleSDPFragmentReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleICETrickleSDPFragmentReturnsOnCall(i int, result1 error) {
|
||||
fake.handleICETrickleSDPFragmentMutex.Lock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.Unlock()
|
||||
fake.HandleICETrickleSDPFragmentStub = nil
|
||||
if fake.handleICETrickleSDPFragmentReturnsOnCall == nil {
|
||||
fake.handleICETrickleSDPFragmentReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.handleICETrickleSDPFragmentReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeLocalParticipant) HandleMetrics(arg1 livekit.ParticipantID, arg2 *livekit.MetricsBatch) error {
|
||||
fake.handleMetricsMutex.Lock()
|
||||
ret, specificReturn := fake.handleMetricsReturnsOnCall[len(fake.handleMetricsArgsForCall)]
|
||||
@@ -7702,6 +7919,8 @@ func (fake *FakeLocalParticipant) Invocations() map[string][][]interface{} {
|
||||
defer fake.getPublishedTrackMutex.RUnlock()
|
||||
fake.getPublishedTracksMutex.RLock()
|
||||
defer fake.getPublishedTracksMutex.RUnlock()
|
||||
fake.getPublisherICESessionUfragMutex.RLock()
|
||||
defer fake.getPublisherICESessionUfragMutex.RUnlock()
|
||||
fake.getSubscribedParticipantsMutex.RLock()
|
||||
defer fake.getSubscribedParticipantsMutex.RUnlock()
|
||||
fake.getSubscribedTracksMutex.RLock()
|
||||
@@ -7710,6 +7929,10 @@ func (fake *FakeLocalParticipant) Invocations() map[string][][]interface{} {
|
||||
defer fake.getTrailerMutex.RUnlock()
|
||||
fake.handleAnswerMutex.RLock()
|
||||
defer fake.handleAnswerMutex.RUnlock()
|
||||
fake.handleICERestartSDPFragmentMutex.RLock()
|
||||
defer fake.handleICERestartSDPFragmentMutex.RUnlock()
|
||||
fake.handleICETrickleSDPFragmentMutex.RLock()
|
||||
defer fake.handleICETrickleSDPFragmentMutex.RUnlock()
|
||||
fake.handleMetricsMutex.RLock()
|
||||
defer fake.handleMetricsMutex.RUnlock()
|
||||
fake.handleOfferMutex.RLock()
|
||||
|
||||
Reference in New Issue
Block a user