Support participant identity in permissions (#663)

* Support participant identity in permissions

It is harder for clients to update permissions by SID as remote
reconnecting means a new SID for that participant. Using participant
identity is a better option.

For now, participant SID is also supported. Internally, it will
get mapped to identity. Server code uses identity throughout after
doing any necessary conversion from SID -> Identity.

* Address comments
This commit is contained in:
Raja Subramanian
2022-05-02 12:35:20 +05:30
committed by GitHub
parent d863b45dc1
commit fe8c355a32
13 changed files with 348 additions and 142 deletions
+13 -12
View File
@@ -142,12 +142,13 @@ func (t *MediaTrackSubscriptions) AddSubscriber(sub types.LocalParticipant, code
}
subTrack := NewSubscribedTrack(SubscribedTrackParams{
PublisherID: t.params.MediaTrack.PublisherID(),
PublisherIdentity: t.params.MediaTrack.PublisherIdentity(),
SubscriberID: subscriberID,
MediaTrack: t.params.MediaTrack,
DownTrack: downTrack,
AdaptiveStream: sub.GetAdaptiveStream(),
PublisherID: t.params.MediaTrack.PublisherID(),
PublisherIdentity: t.params.MediaTrack.PublisherIdentity(),
SubscriberID: subscriberID,
SubscriberIdentity: sub.Identity(),
MediaTrack: t.params.MediaTrack,
DownTrack: downTrack,
AdaptiveStream: sub.GetAdaptiveStream(),
})
var transceiver *webrtc.RTPTransceiver
@@ -276,14 +277,14 @@ func (t *MediaTrackSubscriptions) ResyncAllSubscribers() {
}
}
func (t *MediaTrackSubscriptions) RevokeDisallowedSubscribers(allowedSubscriberIDs []livekit.ParticipantID) []livekit.ParticipantID {
var revokedSubscriberIDs []livekit.ParticipantID
func (t *MediaTrackSubscriptions) RevokeDisallowedSubscribers(allowedSubscriberIdentities []livekit.ParticipantIdentity) []livekit.ParticipantIdentity {
var revokedSubscriberIdentities []livekit.ParticipantIdentity
// LK-TODO: large number of subscribers needs to be solved for this loop
for _, subTrack := range t.getAllSubscribedTracks() {
found := false
for _, allowedID := range allowedSubscriberIDs {
if subTrack.SubscriberID() == allowedID {
for _, allowedIdentity := range allowedSubscriberIdentities {
if subTrack.SubscriberIdentity() == allowedIdentity {
found = true
break
}
@@ -291,11 +292,11 @@ func (t *MediaTrackSubscriptions) RevokeDisallowedSubscribers(allowedSubscriberI
if !found {
go subTrack.DownTrack().Close()
revokedSubscriberIDs = append(revokedSubscriberIDs, subTrack.SubscriberID())
revokedSubscriberIdentities = append(revokedSubscriberIdentities, subTrack.SubscriberIdentity())
}
}
return revokedSubscriberIDs
return revokedSubscriberIdentities
}
func (t *MediaTrackSubscriptions) GetAllSubscribers() []livekit.ParticipantID {
+1 -1
View File
@@ -397,7 +397,7 @@ func (r *Room) SyncState(participant types.LocalParticipant, state *livekit.Sync
}
func (r *Room) UpdateSubscriptionPermission(participant types.LocalParticipant, subscriptionPermission *livekit.SubscriptionPermission) error {
return participant.UpdateSubscriptionPermission(subscriptionPermission, r.GetParticipantBySid)
return participant.UpdateSubscriptionPermission(subscriptionPermission, r.GetParticipant, r.GetParticipantBySid)
}
func (r *Room) RemoveDisallowedSubscriptions(sub types.LocalParticipant, disallowedSubscriptions map[livekit.TrackID]livekit.ParticipantID) {
+11 -6
View File
@@ -18,12 +18,13 @@ const (
)
type SubscribedTrackParams struct {
PublisherID livekit.ParticipantID
PublisherIdentity livekit.ParticipantIdentity
SubscriberID livekit.ParticipantID
MediaTrack types.MediaTrack
DownTrack *sfu.DownTrack
AdaptiveStream bool
PublisherID livekit.ParticipantID
PublisherIdentity livekit.ParticipantIdentity
SubscriberID livekit.ParticipantID
SubscriberIdentity livekit.ParticipantIdentity
MediaTrack types.MediaTrack
DownTrack *sfu.DownTrack
AdaptiveStream bool
}
type SubscribedTrack struct {
@@ -75,6 +76,10 @@ func (t *SubscribedTrack) SubscriberID() livekit.ParticipantID {
return t.params.SubscriberID
}
func (t *SubscribedTrack) SubscriberIdentity() livekit.ParticipantIdentity {
return t.params.SubscriberIdentity
}
func (t *SubscribedTrack) DownTrack() *sfu.DownTrack {
return t.params.DownTrack
}
+7 -2
View File
@@ -74,7 +74,11 @@ type Participant interface {
SubscriptionPermission() *livekit.SubscriptionPermission
// updates from remotes
UpdateSubscriptionPermission(subscriptionPermission *livekit.SubscriptionPermission, resolver func(participantID livekit.ParticipantID) LocalParticipant) error
UpdateSubscriptionPermission(
subscriptionPermission *livekit.SubscriptionPermission,
resolverByIdentity func(participantIdentity livekit.ParticipantIdentity) LocalParticipant,
resolverBySid func(participantID livekit.ParticipantID) LocalParticipant,
) error
UpdateVideoLayers(updateVideoLayers *livekit.UpdateVideoLayers) error
UpdateSubscribedQuality(nodeID livekit.NodeID, trackID livekit.TrackID, maxQuality livekit.VideoQuality) error
UpdateMediaLoss(nodeID livekit.NodeID, trackID livekit.TrackID, fractionalLoss uint32) error
@@ -203,7 +207,7 @@ type MediaTrack interface {
RemoveSubscriber(participantID livekit.ParticipantID, resume bool)
IsSubscriber(subID livekit.ParticipantID) bool
RemoveAllSubscribers()
RevokeDisallowedSubscribers(allowedSubscriberIDs []livekit.ParticipantID) []livekit.ParticipantID
RevokeDisallowedSubscribers(allowedSubscriberIdentities []livekit.ParticipantIdentity) []livekit.ParticipantIdentity
GetAllSubscribers() []livekit.ParticipantID
// returns quality information that's appropriate for width & height
@@ -234,6 +238,7 @@ type SubscribedTrack interface {
PublisherID() livekit.ParticipantID
PublisherIdentity() livekit.ParticipantIdentity
SubscriberID() livekit.ParticipantID
SubscriberIdentity() livekit.ParticipantIdentity
DownTrack() *sfu.DownTrack
MediaTrack() MediaTrack
IsMuted() bool
@@ -187,16 +187,16 @@ type FakeLocalMediaTrack struct {
restartMutex sync.RWMutex
restartArgsForCall []struct {
}
RevokeDisallowedSubscribersStub func([]livekit.ParticipantID) []livekit.ParticipantID
RevokeDisallowedSubscribersStub func([]livekit.ParticipantIdentity) []livekit.ParticipantIdentity
revokeDisallowedSubscribersMutex sync.RWMutex
revokeDisallowedSubscribersArgsForCall []struct {
arg1 []livekit.ParticipantID
arg1 []livekit.ParticipantIdentity
}
revokeDisallowedSubscribersReturns struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}
revokeDisallowedSubscribersReturnsOnCall map[int]struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}
SdpCidStub func() string
sdpCidMutex sync.RWMutex
@@ -1206,16 +1206,16 @@ func (fake *FakeLocalMediaTrack) RestartCalls(stub func()) {
fake.RestartStub = stub
}
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribers(arg1 []livekit.ParticipantID) []livekit.ParticipantID {
var arg1Copy []livekit.ParticipantID
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribers(arg1 []livekit.ParticipantIdentity) []livekit.ParticipantIdentity {
var arg1Copy []livekit.ParticipantIdentity
if arg1 != nil {
arg1Copy = make([]livekit.ParticipantID, len(arg1))
arg1Copy = make([]livekit.ParticipantIdentity, len(arg1))
copy(arg1Copy, arg1)
}
fake.revokeDisallowedSubscribersMutex.Lock()
ret, specificReturn := fake.revokeDisallowedSubscribersReturnsOnCall[len(fake.revokeDisallowedSubscribersArgsForCall)]
fake.revokeDisallowedSubscribersArgsForCall = append(fake.revokeDisallowedSubscribersArgsForCall, struct {
arg1 []livekit.ParticipantID
arg1 []livekit.ParticipantIdentity
}{arg1Copy})
stub := fake.RevokeDisallowedSubscribersStub
fakeReturns := fake.revokeDisallowedSubscribersReturns
@@ -1236,39 +1236,39 @@ func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersCallCount() int {
return len(fake.revokeDisallowedSubscribersArgsForCall)
}
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersCalls(stub func([]livekit.ParticipantID) []livekit.ParticipantID) {
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersCalls(stub func([]livekit.ParticipantIdentity) []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = stub
}
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersArgsForCall(i int) []livekit.ParticipantID {
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersArgsForCall(i int) []livekit.ParticipantIdentity {
fake.revokeDisallowedSubscribersMutex.RLock()
defer fake.revokeDisallowedSubscribersMutex.RUnlock()
argsForCall := fake.revokeDisallowedSubscribersArgsForCall[i]
return argsForCall.arg1
}
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersReturns(result1 []livekit.ParticipantID) {
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersReturns(result1 []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = nil
fake.revokeDisallowedSubscribersReturns = struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}{result1}
}
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersReturnsOnCall(i int, result1 []livekit.ParticipantID) {
func (fake *FakeLocalMediaTrack) RevokeDisallowedSubscribersReturnsOnCall(i int, result1 []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = nil
if fake.revokeDisallowedSubscribersReturnsOnCall == nil {
fake.revokeDisallowedSubscribersReturnsOnCall = make(map[int]struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
})
}
fake.revokeDisallowedSubscribersReturnsOnCall[i] = struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}{result1}
}
@@ -603,11 +603,12 @@ type FakeLocalParticipant struct {
updateSubscribedTrackSettingsReturnsOnCall map[int]struct {
result1 error
}
UpdateSubscriptionPermissionStub func(*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) error
UpdateSubscriptionPermissionStub func(*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) error
updateSubscriptionPermissionMutex sync.RWMutex
updateSubscriptionPermissionArgsForCall []struct {
arg1 *livekit.SubscriptionPermission
arg2 func(participantID livekit.ParticipantID) types.LocalParticipant
arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant
arg3 func(participantID livekit.ParticipantID) types.LocalParticipant
}
updateSubscriptionPermissionReturns struct {
result1 error
@@ -3832,19 +3833,20 @@ func (fake *FakeLocalParticipant) UpdateSubscribedTrackSettingsReturnsOnCall(i i
}{result1}
}
func (fake *FakeLocalParticipant) UpdateSubscriptionPermission(arg1 *livekit.SubscriptionPermission, arg2 func(participantID livekit.ParticipantID) types.LocalParticipant) error {
func (fake *FakeLocalParticipant) UpdateSubscriptionPermission(arg1 *livekit.SubscriptionPermission, arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, arg3 func(participantID livekit.ParticipantID) types.LocalParticipant) error {
fake.updateSubscriptionPermissionMutex.Lock()
ret, specificReturn := fake.updateSubscriptionPermissionReturnsOnCall[len(fake.updateSubscriptionPermissionArgsForCall)]
fake.updateSubscriptionPermissionArgsForCall = append(fake.updateSubscriptionPermissionArgsForCall, struct {
arg1 *livekit.SubscriptionPermission
arg2 func(participantID livekit.ParticipantID) types.LocalParticipant
}{arg1, arg2})
arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant
arg3 func(participantID livekit.ParticipantID) types.LocalParticipant
}{arg1, arg2, arg3})
stub := fake.UpdateSubscriptionPermissionStub
fakeReturns := fake.updateSubscriptionPermissionReturns
fake.recordInvocation("UpdateSubscriptionPermission", []interface{}{arg1, arg2})
fake.recordInvocation("UpdateSubscriptionPermission", []interface{}{arg1, arg2, arg3})
fake.updateSubscriptionPermissionMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
return stub(arg1, arg2, arg3)
}
if specificReturn {
return ret.result1
@@ -3858,17 +3860,17 @@ func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionCallCount() int {
return len(fake.updateSubscriptionPermissionArgsForCall)
}
func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionCalls(stub func(*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) error) {
func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionCalls(stub func(*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) error) {
fake.updateSubscriptionPermissionMutex.Lock()
defer fake.updateSubscriptionPermissionMutex.Unlock()
fake.UpdateSubscriptionPermissionStub = stub
}
func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionArgsForCall(i int) (*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) {
func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionArgsForCall(i int) (*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) {
fake.updateSubscriptionPermissionMutex.RLock()
defer fake.updateSubscriptionPermissionMutex.RUnlock()
argsForCall := fake.updateSubscriptionPermissionArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
}
func (fake *FakeLocalParticipant) UpdateSubscriptionPermissionReturns(result1 error) {
+15 -15
View File
@@ -165,16 +165,16 @@ type FakeMediaTrack struct {
restartMutex sync.RWMutex
restartArgsForCall []struct {
}
RevokeDisallowedSubscribersStub func([]livekit.ParticipantID) []livekit.ParticipantID
RevokeDisallowedSubscribersStub func([]livekit.ParticipantIdentity) []livekit.ParticipantIdentity
revokeDisallowedSubscribersMutex sync.RWMutex
revokeDisallowedSubscribersArgsForCall []struct {
arg1 []livekit.ParticipantID
arg1 []livekit.ParticipantIdentity
}
revokeDisallowedSubscribersReturns struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}
revokeDisallowedSubscribersReturnsOnCall map[int]struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}
SetMutedStub func(bool)
setMutedMutex sync.RWMutex
@@ -1050,16 +1050,16 @@ func (fake *FakeMediaTrack) RestartCalls(stub func()) {
fake.RestartStub = stub
}
func (fake *FakeMediaTrack) RevokeDisallowedSubscribers(arg1 []livekit.ParticipantID) []livekit.ParticipantID {
var arg1Copy []livekit.ParticipantID
func (fake *FakeMediaTrack) RevokeDisallowedSubscribers(arg1 []livekit.ParticipantIdentity) []livekit.ParticipantIdentity {
var arg1Copy []livekit.ParticipantIdentity
if arg1 != nil {
arg1Copy = make([]livekit.ParticipantID, len(arg1))
arg1Copy = make([]livekit.ParticipantIdentity, len(arg1))
copy(arg1Copy, arg1)
}
fake.revokeDisallowedSubscribersMutex.Lock()
ret, specificReturn := fake.revokeDisallowedSubscribersReturnsOnCall[len(fake.revokeDisallowedSubscribersArgsForCall)]
fake.revokeDisallowedSubscribersArgsForCall = append(fake.revokeDisallowedSubscribersArgsForCall, struct {
arg1 []livekit.ParticipantID
arg1 []livekit.ParticipantIdentity
}{arg1Copy})
stub := fake.RevokeDisallowedSubscribersStub
fakeReturns := fake.revokeDisallowedSubscribersReturns
@@ -1080,39 +1080,39 @@ func (fake *FakeMediaTrack) RevokeDisallowedSubscribersCallCount() int {
return len(fake.revokeDisallowedSubscribersArgsForCall)
}
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersCalls(stub func([]livekit.ParticipantID) []livekit.ParticipantID) {
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersCalls(stub func([]livekit.ParticipantIdentity) []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = stub
}
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersArgsForCall(i int) []livekit.ParticipantID {
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersArgsForCall(i int) []livekit.ParticipantIdentity {
fake.revokeDisallowedSubscribersMutex.RLock()
defer fake.revokeDisallowedSubscribersMutex.RUnlock()
argsForCall := fake.revokeDisallowedSubscribersArgsForCall[i]
return argsForCall.arg1
}
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersReturns(result1 []livekit.ParticipantID) {
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersReturns(result1 []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = nil
fake.revokeDisallowedSubscribersReturns = struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}{result1}
}
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersReturnsOnCall(i int, result1 []livekit.ParticipantID) {
func (fake *FakeMediaTrack) RevokeDisallowedSubscribersReturnsOnCall(i int, result1 []livekit.ParticipantIdentity) {
fake.revokeDisallowedSubscribersMutex.Lock()
defer fake.revokeDisallowedSubscribersMutex.Unlock()
fake.RevokeDisallowedSubscribersStub = nil
if fake.revokeDisallowedSubscribersReturnsOnCall == nil {
fake.revokeDisallowedSubscribersReturnsOnCall = make(map[int]struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
})
}
fake.revokeDisallowedSubscribersReturnsOnCall[i] = struct {
result1 []livekit.ParticipantID
result1 []livekit.ParticipantIdentity
}{result1}
}
+12 -10
View File
@@ -167,11 +167,12 @@ type FakeParticipant struct {
updateSubscribedQualityReturnsOnCall map[int]struct {
result1 error
}
UpdateSubscriptionPermissionStub func(*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) error
UpdateSubscriptionPermissionStub func(*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) error
updateSubscriptionPermissionMutex sync.RWMutex
updateSubscriptionPermissionArgsForCall []struct {
arg1 *livekit.SubscriptionPermission
arg2 func(participantID livekit.ParticipantID) types.LocalParticipant
arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant
arg3 func(participantID livekit.ParticipantID) types.LocalParticipant
}
updateSubscriptionPermissionReturns struct {
result1 error
@@ -1021,19 +1022,20 @@ func (fake *FakeParticipant) UpdateSubscribedQualityReturnsOnCall(i int, result1
}{result1}
}
func (fake *FakeParticipant) UpdateSubscriptionPermission(arg1 *livekit.SubscriptionPermission, arg2 func(participantID livekit.ParticipantID) types.LocalParticipant) error {
func (fake *FakeParticipant) UpdateSubscriptionPermission(arg1 *livekit.SubscriptionPermission, arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, arg3 func(participantID livekit.ParticipantID) types.LocalParticipant) error {
fake.updateSubscriptionPermissionMutex.Lock()
ret, specificReturn := fake.updateSubscriptionPermissionReturnsOnCall[len(fake.updateSubscriptionPermissionArgsForCall)]
fake.updateSubscriptionPermissionArgsForCall = append(fake.updateSubscriptionPermissionArgsForCall, struct {
arg1 *livekit.SubscriptionPermission
arg2 func(participantID livekit.ParticipantID) types.LocalParticipant
}{arg1, arg2})
arg2 func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant
arg3 func(participantID livekit.ParticipantID) types.LocalParticipant
}{arg1, arg2, arg3})
stub := fake.UpdateSubscriptionPermissionStub
fakeReturns := fake.updateSubscriptionPermissionReturns
fake.recordInvocation("UpdateSubscriptionPermission", []interface{}{arg1, arg2})
fake.recordInvocation("UpdateSubscriptionPermission", []interface{}{arg1, arg2, arg3})
fake.updateSubscriptionPermissionMutex.Unlock()
if stub != nil {
return stub(arg1, arg2)
return stub(arg1, arg2, arg3)
}
if specificReturn {
return ret.result1
@@ -1047,17 +1049,17 @@ func (fake *FakeParticipant) UpdateSubscriptionPermissionCallCount() int {
return len(fake.updateSubscriptionPermissionArgsForCall)
}
func (fake *FakeParticipant) UpdateSubscriptionPermissionCalls(stub func(*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) error) {
func (fake *FakeParticipant) UpdateSubscriptionPermissionCalls(stub func(*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) error) {
fake.updateSubscriptionPermissionMutex.Lock()
defer fake.updateSubscriptionPermissionMutex.Unlock()
fake.UpdateSubscriptionPermissionStub = stub
}
func (fake *FakeParticipant) UpdateSubscriptionPermissionArgsForCall(i int) (*livekit.SubscriptionPermission, func(participantID livekit.ParticipantID) types.LocalParticipant) {
func (fake *FakeParticipant) UpdateSubscriptionPermissionArgsForCall(i int) (*livekit.SubscriptionPermission, func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant, func(participantID livekit.ParticipantID) types.LocalParticipant) {
fake.updateSubscriptionPermissionMutex.RLock()
defer fake.updateSubscriptionPermissionMutex.RUnlock()
argsForCall := fake.updateSubscriptionPermissionArgsForCall[i]
return argsForCall.arg1, argsForCall.arg2
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3
}
func (fake *FakeParticipant) UpdateSubscriptionPermissionReturns(result1 error) {
@@ -90,6 +90,16 @@ type FakeSubscribedTrack struct {
subscriberIDReturnsOnCall map[int]struct {
result1 livekit.ParticipantID
}
SubscriberIdentityStub func() livekit.ParticipantIdentity
subscriberIdentityMutex sync.RWMutex
subscriberIdentityArgsForCall []struct {
}
subscriberIdentityReturns struct {
result1 livekit.ParticipantIdentity
}
subscriberIdentityReturnsOnCall map[int]struct {
result1 livekit.ParticipantIdentity
}
UpdateSubscriberSettingsStub func(*livekit.UpdateTrackSettings)
updateSubscriberSettingsMutex sync.RWMutex
updateSubscriberSettingsArgsForCall []struct {
@@ -538,6 +548,59 @@ func (fake *FakeSubscribedTrack) SubscriberIDReturnsOnCall(i int, result1 liveki
}{result1}
}
func (fake *FakeSubscribedTrack) SubscriberIdentity() livekit.ParticipantIdentity {
fake.subscriberIdentityMutex.Lock()
ret, specificReturn := fake.subscriberIdentityReturnsOnCall[len(fake.subscriberIdentityArgsForCall)]
fake.subscriberIdentityArgsForCall = append(fake.subscriberIdentityArgsForCall, struct {
}{})
stub := fake.SubscriberIdentityStub
fakeReturns := fake.subscriberIdentityReturns
fake.recordInvocation("SubscriberIdentity", []interface{}{})
fake.subscriberIdentityMutex.Unlock()
if stub != nil {
return stub()
}
if specificReturn {
return ret.result1
}
return fakeReturns.result1
}
func (fake *FakeSubscribedTrack) SubscriberIdentityCallCount() int {
fake.subscriberIdentityMutex.RLock()
defer fake.subscriberIdentityMutex.RUnlock()
return len(fake.subscriberIdentityArgsForCall)
}
func (fake *FakeSubscribedTrack) SubscriberIdentityCalls(stub func() livekit.ParticipantIdentity) {
fake.subscriberIdentityMutex.Lock()
defer fake.subscriberIdentityMutex.Unlock()
fake.SubscriberIdentityStub = stub
}
func (fake *FakeSubscribedTrack) SubscriberIdentityReturns(result1 livekit.ParticipantIdentity) {
fake.subscriberIdentityMutex.Lock()
defer fake.subscriberIdentityMutex.Unlock()
fake.SubscriberIdentityStub = nil
fake.subscriberIdentityReturns = struct {
result1 livekit.ParticipantIdentity
}{result1}
}
func (fake *FakeSubscribedTrack) SubscriberIdentityReturnsOnCall(i int, result1 livekit.ParticipantIdentity) {
fake.subscriberIdentityMutex.Lock()
defer fake.subscriberIdentityMutex.Unlock()
fake.SubscriberIdentityStub = nil
if fake.subscriberIdentityReturnsOnCall == nil {
fake.subscriberIdentityReturnsOnCall = make(map[int]struct {
result1 livekit.ParticipantIdentity
})
}
fake.subscriberIdentityReturnsOnCall[i] = struct {
result1 livekit.ParticipantIdentity
}{result1}
}
func (fake *FakeSubscribedTrack) UpdateSubscriberSettings(arg1 *livekit.UpdateTrackSettings) {
fake.updateSubscriberSettingsMutex.Lock()
fake.updateSubscriberSettingsArgsForCall = append(fake.updateSubscriberSettingsArgsForCall, struct {
@@ -615,6 +678,8 @@ func (fake *FakeSubscribedTrack) Invocations() map[string][][]interface{} {
defer fake.setPublisherMutedMutex.RUnlock()
fake.subscriberIDMutex.RLock()
defer fake.subscriberIDMutex.RUnlock()
fake.subscriberIdentityMutex.RLock()
defer fake.subscriberIdentityMutex.RUnlock()
fake.updateSubscriberSettingsMutex.RLock()
defer fake.updateSubscriberSettingsMutex.RUnlock()
fake.updateVideoLayerMutex.RLock()
+81 -38
View File
@@ -10,6 +10,10 @@ import (
"github.com/livekit/livekit-server/pkg/rtc/types"
)
var (
ErrSubscriptionPermissionNeedsId = errors.New("either participant identity or SID needed")
)
type UpTrackManagerParams struct {
SID livekit.ParticipantID
Logger logger.Logger
@@ -24,9 +28,9 @@ type UpTrackManager struct {
publishedTracks map[livekit.TrackID]types.MediaTrack
subscriptionPermission *livekit.SubscriptionPermission
// subscriber permission for published tracks
subscriberPermissions map[livekit.ParticipantID]*livekit.TrackPermission // subscriberID => *livekit.TrackPermission
subscriberPermissions map[livekit.ParticipantIdentity]*livekit.TrackPermission // subscriberIdentity => *livekit.TrackPermission
// keeps tracks of track specific subscribers who are awaiting permission
pendingSubscriptions map[livekit.TrackID][]livekit.ParticipantID // trackID => []subscriberID
pendingSubscriptions map[livekit.TrackID][]livekit.ParticipantIdentity // trackID => []subscriberIdentity
lock sync.RWMutex
@@ -39,7 +43,7 @@ func NewUpTrackManager(params UpTrackManagerParams) *UpTrackManager {
return &UpTrackManager{
params: params,
publishedTracks: make(map[livekit.TrackID]types.MediaTrack),
pendingSubscriptions: make(map[livekit.TrackID][]livekit.ParticipantID),
pendingSubscriptions: make(map[livekit.TrackID][]livekit.ParticipantIdentity),
}
}
@@ -121,8 +125,8 @@ func (u *UpTrackManager) AddSubscriber(sub types.LocalParticipant, params types.
n := 0
for _, track := range tracks {
trackID := track.ID()
subscriberID := sub.ID()
if !u.hasPermission(trackID, subscriberID) {
subscriberIdentity := sub.Identity()
if !u.hasPermission(trackID, subscriberIdentity) {
u.lock.Lock()
u.maybeAddPendingSubscription(trackID, sub)
u.lock.Unlock()
@@ -188,7 +192,8 @@ func (u *UpTrackManager) GetPublishedTracks() []types.MediaTrack {
func (u *UpTrackManager) UpdateSubscriptionPermission(
subscriptionPermission *livekit.SubscriptionPermission,
resolver func(participantID livekit.ParticipantID) types.LocalParticipant,
resolverByIdentity func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant,
resolverBySid func(participantID livekit.ParticipantID) types.LocalParticipant,
) error {
u.lock.Lock()
defer u.lock.Unlock()
@@ -200,11 +205,15 @@ func (u *UpTrackManager) UpdateSubscriptionPermission(
return nil
}
u.parseSubscriptionPermissions(subscriptionPermission)
if err := u.parseSubscriptionPermissions(subscriptionPermission, resolverBySid); err != nil {
// do not accept permissions if parse fails
u.subscriptionPermission = nil
return err
}
u.processPendingSubscriptions(resolver)
u.processPendingSubscriptions(resolverByIdentity)
u.maybeRevokeSubscriptions(resolver)
u.maybeRevokeSubscriptions(resolverByIdentity)
return nil
}
@@ -298,29 +307,63 @@ func (u *UpTrackManager) getPublishedTrack(trackID livekit.TrackID) types.MediaT
return u.publishedTracks[trackID]
}
func (u *UpTrackManager) parseSubscriptionPermissions(subscriptionPermission *livekit.SubscriptionPermission) {
func (u *UpTrackManager) parseSubscriptionPermissions(
subscriptionPermission *livekit.SubscriptionPermission,
resolver func(participantID livekit.ParticipantID) types.LocalParticipant,
) error {
// every update overrides the existing
// all_participants takes precedence
if subscriptionPermission.AllParticipants {
// everything is allowed, nothing else to do
u.subscriberPermissions = nil
return
return nil
}
// per participant permissions
u.subscriberPermissions = make(map[livekit.ParticipantID]*livekit.TrackPermission)
u.subscriberPermissions = make(map[livekit.ParticipantIdentity]*livekit.TrackPermission)
for _, trackPerms := range subscriptionPermission.TrackPermissions {
u.subscriberPermissions[livekit.ParticipantID(trackPerms.ParticipantSid)] = trackPerms
subscriberIdentity := livekit.ParticipantIdentity(trackPerms.ParticipantIdentity)
if subscriberIdentity == "" {
if trackPerms.ParticipantSid == "" {
u.subscriberPermissions = nil
return ErrSubscriptionPermissionNeedsId
}
var sub types.LocalParticipant
if resolver != nil {
sub = resolver(livekit.ParticipantID(trackPerms.ParticipantSid))
}
if sub == nil {
u.params.Logger.Warnw("could not find subscriber for permissions update", nil, "subscriberID", trackPerms.ParticipantSid)
continue
}
subscriberIdentity = sub.Identity()
} else {
if trackPerms.ParticipantSid != "" {
sub := resolver(livekit.ParticipantID(trackPerms.ParticipantSid))
if sub != nil && sub.Identity() != subscriberIdentity {
u.params.Logger.Errorw("participant identity mismatch", nil, "expected", subscriberIdentity, "got", sub.Identity())
}
if sub == nil {
u.params.Logger.Warnw("could not find subscriber for permissions update", nil, "subscriberID", trackPerms.ParticipantSid)
}
}
}
u.subscriberPermissions[subscriberIdentity] = trackPerms
}
return nil
}
func (u *UpTrackManager) hasPermission(trackID livekit.TrackID, subscriberID livekit.ParticipantID) bool {
func (u *UpTrackManager) hasPermission(trackID livekit.TrackID, subscriberIdentity livekit.ParticipantIdentity) bool {
if u.subscriberPermissions == nil {
return true
}
perms, ok := u.subscriberPermissions[subscriberID]
perms, ok := u.subscriberPermissions[subscriberIdentity]
if !ok {
return false
}
@@ -338,21 +381,21 @@ func (u *UpTrackManager) hasPermission(trackID livekit.TrackID, subscriberID liv
return false
}
func (u *UpTrackManager) getAllowedSubscribers(trackID livekit.TrackID) []livekit.ParticipantID {
func (u *UpTrackManager) getAllowedSubscribers(trackID livekit.TrackID) []livekit.ParticipantIdentity {
if u.subscriberPermissions == nil {
return nil
}
allowed := make([]livekit.ParticipantID, 0)
for subscriberID, perms := range u.subscriberPermissions {
allowed := make([]livekit.ParticipantIdentity, 0)
for subscriberIdentity, perms := range u.subscriberPermissions {
if perms.AllTracks {
allowed = append(allowed, subscriberID)
allowed = append(allowed, subscriberIdentity)
continue
}
for _, sid := range perms.TrackSids {
if livekit.TrackID(sid) == trackID {
allowed = append(allowed, subscriberID)
allowed = append(allowed, subscriberIdentity)
break
}
}
@@ -362,27 +405,27 @@ func (u *UpTrackManager) getAllowedSubscribers(trackID livekit.TrackID) []liveki
}
func (u *UpTrackManager) maybeAddPendingSubscription(trackID livekit.TrackID, sub types.LocalParticipant) {
subscriberID := sub.ID()
subscriberIdentity := sub.Identity()
pending := u.pendingSubscriptions[trackID]
for _, sid := range pending {
if sid == subscriberID {
for _, identity := range pending {
if identity == subscriberIdentity {
// already pending
return
}
}
u.pendingSubscriptions[trackID] = append(u.pendingSubscriptions[trackID], subscriberID)
u.pendingSubscriptions[trackID] = append(u.pendingSubscriptions[trackID], subscriberIdentity)
go sub.SubscriptionPermissionUpdate(u.params.SID, trackID, false)
}
func (u *UpTrackManager) maybeRemovePendingSubscription(trackID livekit.TrackID, sub types.LocalParticipant) {
subscriberID := sub.ID()
subscriberIdentity := sub.Identity()
pending := u.pendingSubscriptions[trackID]
n := len(pending)
for idx, sid := range pending {
if sid == subscriberID {
for idx, identity := range pending {
if identity == subscriberIdentity {
u.pendingSubscriptions[trackID][idx] = u.pendingSubscriptions[trackID][n-1]
u.pendingSubscriptions[trackID] = u.pendingSubscriptions[trackID][:n-1]
break
@@ -393,34 +436,34 @@ func (u *UpTrackManager) maybeRemovePendingSubscription(trackID livekit.TrackID,
}
}
func (u *UpTrackManager) processPendingSubscriptions(resolver func(participantID livekit.ParticipantID) types.LocalParticipant) {
updatedPendingSubscriptions := make(map[livekit.TrackID][]livekit.ParticipantID)
func (u *UpTrackManager) processPendingSubscriptions(resolver func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant) {
updatedPendingSubscriptions := make(map[livekit.TrackID][]livekit.ParticipantIdentity)
for trackID, pending := range u.pendingSubscriptions {
track := u.getPublishedTrack(trackID)
if track == nil {
continue
}
var updatedPending []livekit.ParticipantID
for _, sid := range pending {
var updatedPending []livekit.ParticipantIdentity
for _, identity := range pending {
var sub types.LocalParticipant
if resolver != nil {
sub = resolver(sid)
sub = resolver(identity)
}
if sub == nil || sub.State() == livekit.ParticipantInfo_DISCONNECTED {
// do not keep this pending subscription as subscriber may be gone
continue
}
if !u.hasPermission(trackID, sid) {
updatedPending = append(updatedPending, sid)
if !u.hasPermission(trackID, identity) {
updatedPending = append(updatedPending, identity)
continue
}
if err := track.AddSubscriber(sub); err != nil {
u.params.Logger.Errorw("error reinstating pending subscription", err)
// keep it in pending on error in case the error is transient
updatedPending = append(updatedPending, sid)
updatedPending = append(updatedPending, identity)
continue
}
@@ -433,7 +476,7 @@ func (u *UpTrackManager) processPendingSubscriptions(resolver func(participantID
u.pendingSubscriptions = updatedPendingSubscriptions
}
func (u *UpTrackManager) maybeRevokeSubscriptions(resolver func(participantID livekit.ParticipantID) types.LocalParticipant) {
func (u *UpTrackManager) maybeRevokeSubscriptions(resolver func(participantIdentity livekit.ParticipantIdentity) types.LocalParticipant) {
for _, track := range u.publishedTracks {
trackID := track.ID()
allowed := u.getAllowedSubscribers(trackID)
@@ -443,10 +486,10 @@ func (u *UpTrackManager) maybeRevokeSubscriptions(resolver func(participantID li
}
revokedSubscribers := track.RevokeDisallowedSubscribers(allowed)
for _, subID := range revokedSubscribers {
for _, subIdentity := range revokedSubscribers {
var sub types.LocalParticipant
if resolver != nil {
sub = resolver(subID)
sub = resolver(subIdentity)
}
if sub == nil {
continue
+113 -24
View File
@@ -7,6 +7,7 @@ import (
"github.com/livekit/protocol/livekit"
"github.com/livekit/livekit-server/pkg/rtc/types"
"github.com/livekit/livekit-server/pkg/rtc/types/typesfakes"
)
@@ -26,17 +27,34 @@ func TestUpdateSubscriptionPermission(t *testing.T) {
subscriptionPermission := &livekit.SubscriptionPermission{
AllParticipants: true,
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.Nil(t, um.subscriberPermissions)
// nobody is allowed to subscribe
subscriptionPermission = &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.NotNil(t, um.subscriberPermissions)
require.Equal(t, 0, len(um.subscriberPermissions))
lp1 := &typesfakes.FakeLocalParticipant{}
lp1.IdentityReturns("p1")
lp2 := &typesfakes.FakeLocalParticipant{}
lp2.IdentityReturns("p2")
sidResolver := func(sid livekit.ParticipantID) types.LocalParticipant {
if sid == "p1" {
return lp1
}
if sid == "p2" {
return lp2
}
return nil
}
// allow all tracks for participants
perms1 := &livekit.TrackPermission{
ParticipantSid: "p1",
@@ -52,23 +70,23 @@ func TestUpdateSubscriptionPermission(t *testing.T) {
perms2,
},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, sidResolver)
require.Equal(t, 2, len(um.subscriberPermissions))
require.EqualValues(t, perms1, um.subscriberPermissions["p1"])
require.EqualValues(t, perms2, um.subscriberPermissions["p2"])
// allow all tracks for some and restrictive for others
perms1 = &livekit.TrackPermission{
ParticipantSid: "p1",
AllTracks: true,
ParticipantIdentity: "p1",
AllTracks: true,
}
perms2 = &livekit.TrackPermission{
ParticipantSid: "p2",
TrackSids: []string{"audio"},
ParticipantIdentity: "p2",
TrackSids: []string{"audio"},
}
perms3 := &livekit.TrackPermission{
ParticipantSid: "p3",
TrackSids: []string{"video"},
ParticipantIdentity: "p3",
TrackSids: []string{"video"},
}
subscriptionPermission = &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{
@@ -77,12 +95,83 @@ func TestUpdateSubscriptionPermission(t *testing.T) {
perms3,
},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.Equal(t, 3, len(um.subscriberPermissions))
require.EqualValues(t, perms1, um.subscriberPermissions["p1"])
require.EqualValues(t, perms2, um.subscriberPermissions["p2"])
require.EqualValues(t, perms3, um.subscriberPermissions["p3"])
})
t.Run("updates subscription permission using both", func(t *testing.T) {
um := NewUpTrackManager(UpTrackManagerParams{})
tra := &typesfakes.FakeMediaTrack{}
tra.IDReturns("audio")
um.publishedTracks["audio"] = tra
trv := &typesfakes.FakeMediaTrack{}
trv.IDReturns("video")
um.publishedTracks["video"] = trv
lp1 := &typesfakes.FakeLocalParticipant{}
lp1.IdentityReturns("p1")
lp2 := &typesfakes.FakeLocalParticipant{}
lp2.IdentityReturns("p2")
sidResolver := func(sid livekit.ParticipantID) types.LocalParticipant {
if sid == "p1" {
return lp1
}
if sid == "p2" {
return lp2
}
return nil
}
// allow all tracks for participants
perms1 := &livekit.TrackPermission{
ParticipantSid: "p1",
ParticipantIdentity: "p1",
AllTracks: true,
}
perms2 := &livekit.TrackPermission{
ParticipantSid: "p2",
ParticipantIdentity: "p2",
AllTracks: true,
}
subscriptionPermission := &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{
perms1,
perms2,
},
}
err := um.UpdateSubscriptionPermission(subscriptionPermission, nil, sidResolver)
require.NoError(t, err)
require.Equal(t, 2, len(um.subscriberPermissions))
require.EqualValues(t, perms1, um.subscriberPermissions["p1"])
require.EqualValues(t, perms2, um.subscriberPermissions["p2"])
// mismatched identities should fail a permission update
badSidResolver := func(sid livekit.ParticipantID) types.LocalParticipant {
if sid == "p1" {
return lp2
}
if sid == "p2" {
return lp1
}
return nil
}
err = um.UpdateSubscriptionPermission(subscriptionPermission, nil, badSidResolver)
require.NoError(t, err)
require.Equal(t, 2, len(um.subscriberPermissions))
require.EqualValues(t, perms1, um.subscriberPermissions["p1"])
require.EqualValues(t, perms2, um.subscriberPermissions["p2"])
})
}
func TestSubscriptionPermission(t *testing.T) {
@@ -101,7 +190,7 @@ func TestSubscriptionPermission(t *testing.T) {
subscriptionPermission := &livekit.SubscriptionPermission{
AllParticipants: true,
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.True(t, um.hasPermission("audio", "p1"))
require.True(t, um.hasPermission("audio", "p2"))
@@ -109,7 +198,7 @@ func TestSubscriptionPermission(t *testing.T) {
subscriptionPermission = &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.False(t, um.hasPermission("audio", "p1"))
require.False(t, um.hasPermission("audio", "p2"))
@@ -117,16 +206,16 @@ func TestSubscriptionPermission(t *testing.T) {
subscriptionPermission = &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{
{
ParticipantSid: "p1",
AllTracks: true,
ParticipantIdentity: "p1",
AllTracks: true,
},
{
ParticipantSid: "p2",
AllTracks: true,
ParticipantIdentity: "p2",
AllTracks: true,
},
},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.True(t, um.hasPermission("audio", "p1"))
require.True(t, um.hasPermission("video", "p1"))
require.True(t, um.hasPermission("audio", "p2"))
@@ -148,20 +237,20 @@ func TestSubscriptionPermission(t *testing.T) {
subscriptionPermission = &livekit.SubscriptionPermission{
TrackPermissions: []*livekit.TrackPermission{
{
ParticipantSid: "p1",
AllTracks: true,
ParticipantIdentity: "p1",
AllTracks: true,
},
{
ParticipantSid: "p2",
TrackSids: []string{"audio"},
ParticipantIdentity: "p2",
TrackSids: []string{"audio"},
},
{
ParticipantSid: "p3",
TrackSids: []string{"video"},
ParticipantIdentity: "p3",
TrackSids: []string{"video"},
},
},
}
um.UpdateSubscriptionPermission(subscriptionPermission, nil)
um.UpdateSubscriptionPermission(subscriptionPermission, nil, nil)
require.True(t, um.hasPermission("audio", "p1"))
require.True(t, um.hasPermission("video", "p1"))
require.True(t, um.hasPermission("screen", "p1"))