snapshot of https://github.com/livekit/livekit.git @ 08c5433449c106943231037d0b892895f6e92d3b (2026-09-15)
This commit is contained in:
27
pkg/rtc/signalling/errors.go
Normal file
27
pkg/rtc/signalling/errors.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidMessageType = errors.New("invalid message type")
|
||||
ErrNameExceedsLimits = errors.New("name length exceeds limits")
|
||||
ErrMetadataExceedsLimits = errors.New("metadata size exceeds limits")
|
||||
ErrAttributesExceedsLimits = errors.New("attributes size exceeds limits")
|
||||
ErrUpdateOwnMetadataNotAllowed = errors.New("update own metadata not allowed")
|
||||
)
|
||||
74
pkg/rtc/signalling/interfaces.go
Normal file
74
pkg/rtc/signalling/interfaces.go
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"github.com/livekit/protocol/livekit"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type ParticipantSignalHandler interface {
|
||||
HandleMessage(msg proto.Message) error
|
||||
}
|
||||
|
||||
type ParticipantSignaller interface {
|
||||
SwapResponseSink(sink routing.MessageSink, reason types.SignallingCloseReason)
|
||||
GetResponseSink() routing.MessageSink
|
||||
CloseSignalConnection(reason types.SignallingCloseReason)
|
||||
|
||||
// HandshakePending reports whether a resumed connection is still waiting for the
|
||||
// ReconnectResponse it has to open with
|
||||
HandshakePending() bool
|
||||
// OpenHandshake lets messages flow on a resumed connection that does not open with
|
||||
// a ReconnectResponse
|
||||
OpenHandshake()
|
||||
|
||||
WriteMessage(msg proto.Message) error
|
||||
}
|
||||
|
||||
type ParticipantSignalling interface {
|
||||
SignalJoinResponse(join *livekit.JoinResponse) proto.Message
|
||||
SignalParticipantUpdate(participants []*livekit.ParticipantInfo) proto.Message
|
||||
SignalSpeakerUpdate(speakers []*livekit.SpeakerInfo) proto.Message
|
||||
SignalRoomUpdate(room *livekit.Room) proto.Message
|
||||
SignalConnectionQualityUpdate(connectionQuality *livekit.ConnectionQualityUpdate) proto.Message
|
||||
SignalRefreshToken(token string) proto.Message
|
||||
SignalRequestResponse(requestResponse *livekit.RequestResponse) proto.Message
|
||||
SignalRoomMovedResponse(roomMoved *livekit.RoomMovedResponse) proto.Message
|
||||
SignalReconnectResponse(reconnect *livekit.ReconnectResponse) proto.Message
|
||||
SignalICECandidate(trickle *livekit.TrickleRequest) proto.Message
|
||||
SignalTrackMuted(mute *livekit.MuteTrackRequest) proto.Message
|
||||
SignalTrackPublished(trackPublished *livekit.TrackPublishedResponse) proto.Message
|
||||
SignalTrackUnpublished(trackUnpublished *livekit.TrackUnpublishedResponse) proto.Message
|
||||
SignalTrackSubscribed(trackSubscribed *livekit.TrackSubscribed) proto.Message
|
||||
SignalLeaveRequest(leave *livekit.LeaveRequest) proto.Message
|
||||
SignalSdpAnswer(answer *livekit.SessionDescription) proto.Message
|
||||
SignalSdpOffer(offer *livekit.SessionDescription) proto.Message
|
||||
SignalStreamStateUpdate(streamStateUpdate *livekit.StreamStateUpdate) proto.Message
|
||||
SignalSubscribedQualityUpdate(subscribedQualityUpdate *livekit.SubscribedQualityUpdate) proto.Message
|
||||
SignalSubscriptionResponse(subscriptionResponse *livekit.SubscriptionResponse) proto.Message
|
||||
SignalSubscriptionPermissionUpdate(subscriptionPermissionUpdate *livekit.SubscriptionPermissionUpdate) proto.Message
|
||||
SignalMediaSectionsRequirement(mediaSectionsRequirement *livekit.MediaSectionsRequirement) proto.Message
|
||||
SignalSubscribedAudioCodecUpdate(subscribedAudioCodecUpdate *livekit.SubscribedAudioCodecUpdate) proto.Message
|
||||
SignalPublishDataTrackResponse(publishDataTrackResponse *livekit.PublishDataTrackResponse) proto.Message
|
||||
SignalUnpublishDataTrackResponse(unpublishDataTrackResponse *livekit.UnpublishDataTrackResponse) proto.Message
|
||||
SignalDataTrackSubscriberHandles(dataTrackSubscriberHandles *livekit.DataTrackSubscriberHandles) proto.Message
|
||||
SignalStoreDataBlobResponse(storeDataBlobResponse *livekit.StoreDataBlobResponse) proto.Message
|
||||
SignalGetDataBlobResponse(getDataBlobResponse *livekit.GetDataBlobResponse) proto.Message
|
||||
}
|
||||
163
pkg/rtc/signalling/signalhandler.go
Normal file
163
pkg/rtc/signalling/signalhandler.go
Normal file
@@ -0,0 +1,163 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/livekit/protocol/livekit"
|
||||
"github.com/livekit/protocol/logger"
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
)
|
||||
|
||||
var _ ParticipantSignalHandler = (*signalhandler)(nil)
|
||||
|
||||
type SignalHandlerParams struct {
|
||||
Logger logger.Logger
|
||||
Participant types.LocalParticipant
|
||||
}
|
||||
|
||||
type signalhandler struct {
|
||||
params SignalHandlerParams
|
||||
}
|
||||
|
||||
func NewSignalHandler(params SignalHandlerParams) ParticipantSignalHandler {
|
||||
return &signalhandler{
|
||||
params: params,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalhandler) HandleMessage(msg proto.Message) error {
|
||||
req, ok := msg.(*livekit.SignalRequest)
|
||||
if !ok {
|
||||
s.params.Logger.Warnw(
|
||||
"unknown message type", nil,
|
||||
"messageType", fmt.Sprintf("%T", msg),
|
||||
)
|
||||
return ErrInvalidMessageType
|
||||
}
|
||||
s.params.Participant.UpdateLastSeenSignal()
|
||||
|
||||
s.params.Logger.Debugw("handling signal request", "request", logger.Proto(req))
|
||||
switch msg := req.GetMessage().(type) {
|
||||
case *livekit.SignalRequest_Offer:
|
||||
s.params.Participant.HandleOffer(msg.Offer)
|
||||
|
||||
case *livekit.SignalRequest_Answer:
|
||||
s.params.Participant.HandleAnswer(msg.Answer)
|
||||
|
||||
case *livekit.SignalRequest_Trickle:
|
||||
s.params.Participant.HandleICETrickle(msg.Trickle)
|
||||
|
||||
case *livekit.SignalRequest_AddTrack:
|
||||
s.params.Participant.AddTrack(msg.AddTrack)
|
||||
|
||||
case *livekit.SignalRequest_Mute:
|
||||
s.params.Participant.SetTrackMuted(msg.Mute, false)
|
||||
|
||||
case *livekit.SignalRequest_Subscription:
|
||||
// allow participant to indicate their interest in the subscription
|
||||
// permission check happens later in SubscriptionManager
|
||||
s.params.Participant.HandleUpdateSubscriptions(
|
||||
livekit.StringsAsIDs[livekit.TrackID](msg.Subscription.TrackSids),
|
||||
msg.Subscription.ParticipantTracks,
|
||||
msg.Subscription.Subscribe,
|
||||
)
|
||||
|
||||
case *livekit.SignalRequest_TrackSetting:
|
||||
for _, sid := range livekit.StringsAsIDs[livekit.TrackID](msg.TrackSetting.TrackSids) {
|
||||
s.params.Participant.UpdateSubscribedTrackSettings(sid, msg.TrackSetting)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_Leave:
|
||||
reason := types.ParticipantCloseReasonClientRequestLeave
|
||||
switch msg.Leave.Reason {
|
||||
case livekit.DisconnectReason_CLIENT_INITIATED:
|
||||
reason = types.ParticipantCloseReasonClientRequestLeave
|
||||
case livekit.DisconnectReason_USER_UNAVAILABLE:
|
||||
reason = types.ParticipantCloseReasonUserUnavailable
|
||||
case livekit.DisconnectReason_USER_REJECTED:
|
||||
reason = types.ParticipantCloseReasonUserRejected
|
||||
case livekit.DisconnectReason_AGENT_ERROR:
|
||||
reason = types.ParticipantCloseReasonAgentError
|
||||
}
|
||||
s.params.Logger.Debugw("client leaving room", "reason", reason)
|
||||
s.params.Participant.HandleLeaveRequest(reason)
|
||||
|
||||
case *livekit.SignalRequest_SubscriptionPermission:
|
||||
err := s.params.Participant.HandleUpdateSubscriptionPermission(msg.SubscriptionPermission)
|
||||
if err != nil {
|
||||
s.params.Logger.Warnw(
|
||||
"could not update subscription permission", err,
|
||||
"permissions", msg.SubscriptionPermission,
|
||||
)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_SyncState:
|
||||
err := s.params.Participant.HandleSyncState(msg.SyncState)
|
||||
if err != nil {
|
||||
s.params.Logger.Warnw(
|
||||
"could not sync state", err,
|
||||
"state", msg.SyncState,
|
||||
)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_Simulate:
|
||||
err := s.params.Participant.HandleSimulateScenario(msg.Simulate)
|
||||
if err != nil {
|
||||
s.params.Logger.Warnw(
|
||||
"could not simulate scenario", err,
|
||||
"simulate", msg.Simulate,
|
||||
)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_PingReq:
|
||||
if msg.PingReq.Rtt > 0 {
|
||||
s.params.Participant.UpdateSignalingRTT(uint32(msg.PingReq.Rtt))
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_UpdateMetadata:
|
||||
s.params.Participant.UpdateMetadata(msg.UpdateMetadata, false)
|
||||
|
||||
case *livekit.SignalRequest_UpdateAudioTrack:
|
||||
if err := s.params.Participant.UpdateAudioTrack(msg.UpdateAudioTrack); err != nil {
|
||||
s.params.Logger.Warnw("could not update audio track", err, "update", msg.UpdateAudioTrack)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_UpdateVideoTrack:
|
||||
if err := s.params.Participant.UpdateVideoTrack(msg.UpdateVideoTrack); err != nil {
|
||||
s.params.Logger.Warnw("could not update video track", err, "update", msg.UpdateVideoTrack)
|
||||
}
|
||||
|
||||
case *livekit.SignalRequest_PublishDataTrackRequest:
|
||||
s.params.Participant.HandlePublishDataTrackRequest(msg.PublishDataTrackRequest)
|
||||
|
||||
case *livekit.SignalRequest_UnpublishDataTrackRequest:
|
||||
s.params.Participant.HandleUnpublishDataTrackRequest(msg.UnpublishDataTrackRequest)
|
||||
|
||||
case *livekit.SignalRequest_UpdateDataSubscription:
|
||||
s.params.Participant.HandleUpdateDataSubscription(msg.UpdateDataSubscription)
|
||||
|
||||
case *livekit.SignalRequest_StoreDataBlobRequest:
|
||||
s.params.Participant.HandleStoreDataBlobRequest(msg.StoreDataBlobRequest)
|
||||
|
||||
case *livekit.SignalRequest_GetDataBlobRequest:
|
||||
s.params.Participant.HandleGetDataBlobRequest(msg.GetDataBlobRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
27
pkg/rtc/signalling/signalhandlerunimplemented.go
Normal file
27
pkg/rtc/signalling/signalhandlerunimplemented.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ ParticipantSignalHandler = (*signalhandlerUnimplemented)(nil)
|
||||
|
||||
type signalhandlerUnimplemented struct{}
|
||||
|
||||
func (u *signalhandlerUnimplemented) HandleMessage(msg proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
140
pkg/rtc/signalling/signallerasync.go
Normal file
140
pkg/rtc/signalling/signallerasync.go
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/livekit/protocol/livekit"
|
||||
"github.com/livekit/protocol/logger"
|
||||
"github.com/livekit/protocol/utils"
|
||||
"github.com/livekit/psrpc"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ ParticipantSignaller = (*signallerAsync)(nil)
|
||||
|
||||
type SignallerAsyncParams struct {
|
||||
Logger logger.Logger
|
||||
Participant types.LocalParticipant
|
||||
OnHandshakeOpened func()
|
||||
}
|
||||
|
||||
type signallerAsync struct {
|
||||
params SignallerAsyncParams
|
||||
|
||||
*signallerAsyncBase
|
||||
}
|
||||
|
||||
func NewSignallerAsync(params SignallerAsyncParams) ParticipantSignaller {
|
||||
return &signallerAsync{
|
||||
params: params,
|
||||
signallerAsyncBase: newSignallerAsyncBase(signallerAsyncBaseParams{
|
||||
Logger: params.Logger,
|
||||
OnHandshakeOpened: params.OnHandshakeOpened,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signallerAsync) WriteMessage(msg proto.Message) error {
|
||||
if msg == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
getMessageType := func(msg proto.Message) string {
|
||||
messageType := "unknown"
|
||||
if typed, ok := msg.(*livekit.SignalResponse); ok {
|
||||
messageType = fmt.Sprintf("%T", typed.Message)
|
||||
}
|
||||
return messageType
|
||||
}
|
||||
|
||||
if s.params.Participant.IsDisconnected() {
|
||||
s.params.Logger.Debugw(
|
||||
"could not send message to participant, participant disconnected",
|
||||
"messageType", getMessageType(msg),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
// a signal connection opens with a join response, or with a reconnect response when
|
||||
// it is resumed or migrated in. The client reads that first message as the handshake,
|
||||
// so nothing may go out ahead of it.
|
||||
isHandshake := false
|
||||
isSdp := false
|
||||
if typed, ok := msg.(*livekit.SignalResponse); !ok {
|
||||
s.params.Logger.Warnw(
|
||||
"unknown message type", nil,
|
||||
"messageType", fmt.Sprintf("%T", msg),
|
||||
)
|
||||
} else {
|
||||
isHandshake = typed.GetJoin() != nil || typed.GetReconnect() != nil
|
||||
isSdp = typed.GetOffer() != nil || typed.GetAnswer() != nil
|
||||
}
|
||||
|
||||
if !isHandshake && (!s.params.Participant.IsReady() || s.HandshakePending()) {
|
||||
logFunc := s.params.Logger.Debugw
|
||||
if isSdp {
|
||||
// a dropped SDP leaves the negotiation waiting for the peer until the
|
||||
// negotiation state machine recovers it, so make it visible
|
||||
logFunc = func(msg string, keysAndValues ...any) {
|
||||
s.params.Logger.Infow(msg, keysAndValues...)
|
||||
}
|
||||
}
|
||||
logFunc(
|
||||
"dropping message, connection has not opened yet",
|
||||
"messageType", getMessageType(msg),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
sink := s.GetResponseSink()
|
||||
if sink == nil {
|
||||
s.params.Logger.Debugw(
|
||||
"could not send message to participant, no sink",
|
||||
"messageType", getMessageType(msg),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := sink.WriteMessage(msg)
|
||||
if err != nil {
|
||||
if utils.ErrorIsOneOf(err, psrpc.Canceled, routing.ErrChannelClosed) {
|
||||
s.params.Logger.Debugw(
|
||||
"could not send message to participant",
|
||||
"error", err,
|
||||
"messageType", getMessageType(msg),
|
||||
)
|
||||
return nil
|
||||
} else {
|
||||
s.params.Logger.Warnw(
|
||||
"could not send message to participant", err,
|
||||
"messageType", getMessageType(msg),
|
||||
)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if isHandshake {
|
||||
// the connection is open, hold nothing back any more
|
||||
s.OpenHandshake()
|
||||
}
|
||||
s.params.Logger.Debugw("sent signal response", "response", logger.Proto(msg))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
185
pkg/rtc/signalling/signallerasyncbase.go
Normal file
185
pkg/rtc/signalling/signallerasyncbase.go
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/livekit/protocol/logger"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
)
|
||||
|
||||
type signallerAsyncBaseParams struct {
|
||||
Logger logger.Logger
|
||||
// called when the connection opens, i. e. when messages held back for the
|
||||
// handshake may be sent
|
||||
OnHandshakeOpened func()
|
||||
}
|
||||
|
||||
// how long a resumed connection holds messages back waiting for its ReconnectResponse.
|
||||
// A path that resumes without sending one lets messages flow after this instead of
|
||||
// holding them back for the rest of the session.
|
||||
const handshakeWindow = 5 * time.Second
|
||||
|
||||
type signallerAsyncBase struct {
|
||||
signallerUnimplemented
|
||||
|
||||
params signallerAsyncBaseParams
|
||||
|
||||
resSinkMu sync.Mutex
|
||||
resSink routing.MessageSink
|
||||
// set while a resumed connection holds messages back waiting for its
|
||||
// ReconnectResponse, the timer opens the connection if none is written.
|
||||
// handshakeGeneration tells a timeout whether it belongs to the current wait, a
|
||||
// Stop cannot cancel a callback that has already started running.
|
||||
handshakePending bool
|
||||
handshakeGeneration uint32
|
||||
handshakeTimer *time.Timer
|
||||
}
|
||||
|
||||
func newSignallerAsyncBase(params signallerAsyncBaseParams) *signallerAsyncBase {
|
||||
return &signallerAsyncBase{
|
||||
params: params,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) SwapResponseSink(sink routing.MessageSink, reason types.SignallingCloseReason) {
|
||||
s.resSinkMu.Lock()
|
||||
oldSink := s.resSink
|
||||
s.resSink = sink
|
||||
// a resumed connection has to open with the ReconnectResponse, the client takes it
|
||||
// only as the first message it reads
|
||||
opened := false
|
||||
switch {
|
||||
case sink == nil:
|
||||
// the connection is gone, keep anything queued for the next one
|
||||
s.disarmHandshakeLocked()
|
||||
case reason == types.SignallingCloseReasonResume:
|
||||
s.armHandshakeLocked()
|
||||
default:
|
||||
opened = s.disarmHandshakeLocked()
|
||||
}
|
||||
s.resSinkMu.Unlock()
|
||||
|
||||
if opened {
|
||||
s.notifyHandshakeOpened()
|
||||
}
|
||||
|
||||
if oldSink != nil {
|
||||
if sink != nil {
|
||||
s.params.Logger.Debugw(
|
||||
"swapping signal connection",
|
||||
"reason", reason,
|
||||
"connID", oldSink.ConnectionID(),
|
||||
"newConnID", sink.ConnectionID(),
|
||||
)
|
||||
} else {
|
||||
s.params.Logger.Debugw(
|
||||
"closing signal connection",
|
||||
"reason", reason,
|
||||
"connID", oldSink.ConnectionID(),
|
||||
)
|
||||
}
|
||||
oldSink.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// HandshakePending is a plain read, so a caller can decide to hold a message back
|
||||
// while holding its own lock
|
||||
func (s *signallerAsyncBase) HandshakePending() bool {
|
||||
s.resSinkMu.Lock()
|
||||
defer s.resSinkMu.Unlock()
|
||||
|
||||
return s.handshakePending
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) OpenHandshake() {
|
||||
s.resSinkMu.Lock()
|
||||
opened := s.disarmHandshakeLocked()
|
||||
s.resSinkMu.Unlock()
|
||||
|
||||
if opened {
|
||||
s.notifyHandshakeOpened()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) armHandshakeLocked() {
|
||||
s.stopHandshakeTimerLocked()
|
||||
|
||||
s.handshakePending = true
|
||||
s.handshakeGeneration++
|
||||
generation := s.handshakeGeneration
|
||||
// the connection opens on its own if nothing writes a ReconnectResponse, a path
|
||||
// that resumes without one should not hold messages back for the whole session
|
||||
s.handshakeTimer = time.AfterFunc(handshakeWindow, func() { s.onHandshakeTimeout(generation) })
|
||||
}
|
||||
|
||||
// disarmHandshakeLocked reports whether it opened a connection that was holding
|
||||
// messages back
|
||||
func (s *signallerAsyncBase) disarmHandshakeLocked() bool {
|
||||
s.stopHandshakeTimerLocked()
|
||||
|
||||
wasPending := s.handshakePending
|
||||
s.handshakePending = false
|
||||
// a timeout of the wait that just ended is stale
|
||||
s.handshakeGeneration++
|
||||
return wasPending
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) stopHandshakeTimerLocked() {
|
||||
if s.handshakeTimer != nil {
|
||||
s.handshakeTimer.Stop()
|
||||
s.handshakeTimer = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) onHandshakeTimeout(generation uint32) {
|
||||
s.resSinkMu.Lock()
|
||||
if generation != s.handshakeGeneration {
|
||||
// the wait this timeout was armed for has ended, a later one may be in progress
|
||||
s.resSinkMu.Unlock()
|
||||
return
|
||||
}
|
||||
opened := s.disarmHandshakeLocked()
|
||||
s.resSinkMu.Unlock()
|
||||
|
||||
if !opened {
|
||||
return
|
||||
}
|
||||
|
||||
s.params.Logger.Warnw("resumed connection did not open with a ReconnectResponse", nil)
|
||||
s.notifyHandshakeOpened()
|
||||
}
|
||||
|
||||
// notifyHandshakeOpened runs without resSinkMu held, the callback sends messages
|
||||
func (s *signallerAsyncBase) notifyHandshakeOpened() {
|
||||
if s.params.OnHandshakeOpened != nil {
|
||||
s.params.OnHandshakeOpened()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signallerAsyncBase) GetResponseSink() routing.MessageSink {
|
||||
s.resSinkMu.Lock()
|
||||
defer s.resSinkMu.Unlock()
|
||||
return s.resSink
|
||||
}
|
||||
|
||||
// closes signal connection to notify client to resume/reconnect
|
||||
func (s *signallerAsyncBase) CloseSignalConnection(reason types.SignallingCloseReason) {
|
||||
s.SwapResponseSink(nil, reason)
|
||||
}
|
||||
157
pkg/rtc/signalling/signallerasyncbase_test.go
Normal file
157
pkg/rtc/signalling/signallerasyncbase_test.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/atomic"
|
||||
|
||||
"github.com/livekit/protocol/logger"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing/routingfakes"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
)
|
||||
|
||||
func newTestSignallerBase(onHandshakeOpened func()) *signallerAsyncBase {
|
||||
return newSignallerAsyncBase(signallerAsyncBaseParams{
|
||||
Logger: logger.GetLogger(),
|
||||
OnHandshakeOpened: onHandshakeOpened,
|
||||
})
|
||||
}
|
||||
|
||||
// currentHandshakeGeneration is what a timeout armed right now would be tagged with
|
||||
func currentHandshakeGeneration(s *signallerAsyncBase) uint32 {
|
||||
s.resSinkMu.Lock()
|
||||
defer s.resSinkMu.Unlock()
|
||||
|
||||
return s.handshakeGeneration
|
||||
}
|
||||
|
||||
func TestHandshakeGate(t *testing.T) {
|
||||
t.Run("a resumed connection holds messages back", func(t *testing.T) {
|
||||
s := newTestSignallerBase(nil)
|
||||
require.False(t, s.HandshakePending())
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.True(t, s.HandshakePending())
|
||||
|
||||
s.OpenHandshake()
|
||||
require.False(t, s.HandshakePending())
|
||||
})
|
||||
|
||||
t.Run("other sink swaps do not hold messages back", func(t *testing.T) {
|
||||
s := newTestSignallerBase(nil)
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonUnknown)
|
||||
require.False(t, s.HandshakePending())
|
||||
})
|
||||
|
||||
t.Run("closing the connection clears the gate", func(t *testing.T) {
|
||||
s := newTestSignallerBase(nil)
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.True(t, s.HandshakePending())
|
||||
|
||||
s.CloseSignalConnection(types.SignallingCloseReasonParticipantClose)
|
||||
require.False(t, s.HandshakePending())
|
||||
})
|
||||
|
||||
t.Run("the handshake window opens the gate", func(t *testing.T) {
|
||||
s := newTestSignallerBase(nil)
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.True(t, s.HandshakePending())
|
||||
|
||||
s.onHandshakeTimeout(currentHandshakeGeneration(s))
|
||||
require.False(t, s.HandshakePending())
|
||||
})
|
||||
|
||||
t.Run("a swap to a fresh connection opens the gate", func(t *testing.T) {
|
||||
s := newTestSignallerBase(nil)
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.True(t, s.HandshakePending())
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonUnknown)
|
||||
require.False(t, s.HandshakePending())
|
||||
})
|
||||
|
||||
t.Run("a timeout of a wait that has ended does nothing", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
stale := currentHandshakeGeneration(s)
|
||||
|
||||
// the client resumes again while the first timeout is running, Stop cannot
|
||||
// cancel a callback that has already started
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
s.onHandshakeTimeout(stale)
|
||||
|
||||
require.True(t, s.HandshakePending())
|
||||
require.Zero(t, opened.Load())
|
||||
|
||||
// and the wait in progress still opens on its own timeout
|
||||
s.onHandshakeTimeout(currentHandshakeGeneration(s))
|
||||
require.False(t, s.HandshakePending())
|
||||
require.EqualValues(t, 1, opened.Load())
|
||||
})
|
||||
}
|
||||
|
||||
func TestHandshakeGateNotifiesOnOpen(t *testing.T) {
|
||||
t.Run("on an explicit open", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.Zero(t, opened.Load())
|
||||
|
||||
s.OpenHandshake()
|
||||
require.EqualValues(t, 1, opened.Load())
|
||||
|
||||
// only the transition notifies
|
||||
s.OpenHandshake()
|
||||
require.EqualValues(t, 1, opened.Load())
|
||||
})
|
||||
|
||||
t.Run("on the handshake window expiring", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
s.onHandshakeTimeout(currentHandshakeGeneration(s))
|
||||
|
||||
require.False(t, s.HandshakePending())
|
||||
require.EqualValues(t, 1, opened.Load())
|
||||
})
|
||||
|
||||
t.Run("the window fires without anything else touching the gate", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
require.Eventually(t, func() bool {
|
||||
return !s.HandshakePending() && opened.Load() == 1
|
||||
}, 2*handshakeWindow, 100*time.Millisecond)
|
||||
})
|
||||
|
||||
t.Run("not on a connection close", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.SwapResponseSink(&routingfakes.FakeMessageSink{}, types.SignallingCloseReasonResume)
|
||||
s.CloseSignalConnection(types.SignallingCloseReasonParticipantClose)
|
||||
|
||||
require.False(t, s.HandshakePending())
|
||||
require.Zero(t, opened.Load())
|
||||
})
|
||||
|
||||
t.Run("not when the gate was never armed", func(t *testing.T) {
|
||||
var opened atomic.Int32
|
||||
s := newTestSignallerBase(func() { opened.Inc() })
|
||||
|
||||
s.OpenHandshake()
|
||||
require.Zero(t, opened.Load())
|
||||
})
|
||||
}
|
||||
45
pkg/rtc/signalling/signallerunimplemented.go
Normal file
45
pkg/rtc/signalling/signallerunimplemented.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ ParticipantSignaller = (*signallerUnimplemented)(nil)
|
||||
|
||||
type signallerUnimplemented struct{}
|
||||
|
||||
func (u *signallerUnimplemented) SwapResponseSink(sink routing.MessageSink, reason types.SignallingCloseReason) {
|
||||
}
|
||||
|
||||
func (u *signallerUnimplemented) GetResponseSink() routing.MessageSink {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallerUnimplemented) CloseSignalConnection(reason types.SignallingCloseReason) {}
|
||||
|
||||
func (u *signallerUnimplemented) HandshakePending() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *signallerUnimplemented) OpenHandshake() {}
|
||||
|
||||
func (u *signallerUnimplemented) WriteMessage(msg proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
276
pkg/rtc/signalling/signalling.go
Normal file
276
pkg/rtc/signalling/signalling.go
Normal file
@@ -0,0 +1,276 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"github.com/livekit/protocol/livekit"
|
||||
"github.com/livekit/protocol/logger"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ ParticipantSignalling = (*signalling)(nil)
|
||||
|
||||
type SignallingParams struct {
|
||||
Logger logger.Logger
|
||||
}
|
||||
|
||||
type signalling struct {
|
||||
params SignallingParams
|
||||
}
|
||||
|
||||
func NewSignalling(params SignallingParams) ParticipantSignalling {
|
||||
return &signalling{
|
||||
params: params,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalJoinResponse(join *livekit.JoinResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Join{
|
||||
Join: join,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalParticipantUpdate(participants []*livekit.ParticipantInfo) proto.Message {
|
||||
if len(participants) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Update{
|
||||
Update: &livekit.ParticipantUpdate{
|
||||
Participants: participants,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSpeakerUpdate(speakers []*livekit.SpeakerInfo) proto.Message {
|
||||
if len(speakers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_SpeakersChanged{
|
||||
SpeakersChanged: &livekit.SpeakersChanged{
|
||||
Speakers: speakers,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalRoomUpdate(room *livekit.Room) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_RoomUpdate{
|
||||
RoomUpdate: &livekit.RoomUpdate{
|
||||
Room: room,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalConnectionQualityUpdate(connectionQuality *livekit.ConnectionQualityUpdate) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_ConnectionQuality{
|
||||
ConnectionQuality: connectionQuality,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalRefreshToken(token string) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_RefreshToken{
|
||||
RefreshToken: token,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalRequestResponse(requestResponse *livekit.RequestResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_RequestResponse{
|
||||
RequestResponse: requestResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalRoomMovedResponse(roomMoved *livekit.RoomMovedResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_RoomMoved{
|
||||
RoomMoved: roomMoved,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalReconnectResponse(reconnect *livekit.ReconnectResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Reconnect{
|
||||
Reconnect: reconnect,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalICECandidate(trickle *livekit.TrickleRequest) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Trickle{
|
||||
Trickle: trickle,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalTrackMuted(mute *livekit.MuteTrackRequest) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Mute{
|
||||
Mute: mute,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalTrackPublished(trackPublished *livekit.TrackPublishedResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_TrackPublished{
|
||||
TrackPublished: trackPublished,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalTrackUnpublished(trackUnpublished *livekit.TrackUnpublishedResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_TrackUnpublished{
|
||||
TrackUnpublished: trackUnpublished,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalTrackSubscribed(trackSubscribed *livekit.TrackSubscribed) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_TrackSubscribed{
|
||||
TrackSubscribed: trackSubscribed,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalLeaveRequest(leave *livekit.LeaveRequest) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Leave{
|
||||
Leave: leave,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSdpAnswer(answer *livekit.SessionDescription) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Answer{
|
||||
Answer: answer,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSdpOffer(offer *livekit.SessionDescription) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Offer{
|
||||
Offer: offer,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalStreamStateUpdate(streamStateUpdate *livekit.StreamStateUpdate) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_StreamStateUpdate{
|
||||
StreamStateUpdate: streamStateUpdate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSubscribedQualityUpdate(subscribedQualityUpdate *livekit.SubscribedQualityUpdate) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_SubscribedQualityUpdate{
|
||||
SubscribedQualityUpdate: subscribedQualityUpdate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSubscriptionResponse(subscriptionResponse *livekit.SubscriptionResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_SubscriptionResponse{
|
||||
SubscriptionResponse: subscriptionResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSubscriptionPermissionUpdate(subscriptionPermissionUpdate *livekit.SubscriptionPermissionUpdate) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_SubscriptionPermissionUpdate{
|
||||
SubscriptionPermissionUpdate: subscriptionPermissionUpdate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalMediaSectionsRequirement(mediaSectionsRequirement *livekit.MediaSectionsRequirement) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_MediaSectionsRequirement{
|
||||
MediaSectionsRequirement: mediaSectionsRequirement,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalSubscribedAudioCodecUpdate(subscribedAudioCodecUpdate *livekit.SubscribedAudioCodecUpdate) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_SubscribedAudioCodecUpdate{
|
||||
SubscribedAudioCodecUpdate: subscribedAudioCodecUpdate,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalPublishDataTrackResponse(publishDataTrackResponse *livekit.PublishDataTrackResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_PublishDataTrackResponse{
|
||||
PublishDataTrackResponse: publishDataTrackResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalUnpublishDataTrackResponse(unpublishDataTrackResponse *livekit.UnpublishDataTrackResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_UnpublishDataTrackResponse{
|
||||
UnpublishDataTrackResponse: unpublishDataTrackResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalDataTrackSubscriberHandles(dataTrackSubscriberHandles *livekit.DataTrackSubscriberHandles) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_DataTrackSubscriberHandles{
|
||||
DataTrackSubscriberHandles: dataTrackSubscriberHandles,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalStoreDataBlobResponse(storeDataBlobResponse *livekit.StoreDataBlobResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_StoreDataBlobResponse{
|
||||
StoreDataBlobResponse: storeDataBlobResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *signalling) SignalGetDataBlobResponse(getDataBlobResponse *livekit.GetDataBlobResponse) proto.Message {
|
||||
return &livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_GetDataBlobResponse{
|
||||
GetDataBlobResponse: getDataBlobResponse,
|
||||
},
|
||||
}
|
||||
}
|
||||
137
pkg/rtc/signalling/signallingunimplemented.go
Normal file
137
pkg/rtc/signalling/signallingunimplemented.go
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2023 LiveKit, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package signalling
|
||||
|
||||
import (
|
||||
"github.com/livekit/protocol/livekit"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var _ ParticipantSignalling = (*signallingUnimplemented)(nil)
|
||||
|
||||
type signallingUnimplemented struct{}
|
||||
|
||||
func (u *signallingUnimplemented) SignalJoinResponse(join *livekit.JoinResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalParticipantUpdate(participants []*livekit.ParticipantInfo) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSpeakerUpdate(speakers []*livekit.SpeakerInfo) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalRoomUpdate(room *livekit.Room) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalConnectionQualityUpdate(connectionQuality *livekit.ConnectionQualityUpdate) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalRefreshToken(token string) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalRequestResponse(requestResponse *livekit.RequestResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalRoomMovedResponse(roomMoved *livekit.RoomMovedResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalReconnectResponse(reconnect *livekit.ReconnectResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalICECandidate(trickle *livekit.TrickleRequest) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalTrackMuted(mute *livekit.MuteTrackRequest) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalTrackPublished(trackPublished *livekit.TrackPublishedResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalTrackUnpublished(trackUnpublished *livekit.TrackUnpublishedResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalTrackSubscribed(trackSubscribed *livekit.TrackSubscribed) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalLeaveRequest(leave *livekit.LeaveRequest) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSdpAnswer(answer *livekit.SessionDescription) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSdpOffer(offer *livekit.SessionDescription) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalStreamStateUpdate(streamStateUpdate *livekit.StreamStateUpdate) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSubscribedQualityUpdate(subscribedQualityUpdate *livekit.SubscribedQualityUpdate) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSubscriptionResponse(subscriptionResponse *livekit.SubscriptionResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSubscriptionPermissionUpdate(subscriptionPermissionUpdate *livekit.SubscriptionPermissionUpdate) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalMediaSectionsRequirement(mediaSectionsRequirement *livekit.MediaSectionsRequirement) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalSubscribedAudioCodecUpdate(subscribedAudioCodecUpdate *livekit.SubscribedAudioCodecUpdate) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalPublishDataTrackResponse(publishDataTrackResponse *livekit.PublishDataTrackResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalUnpublishDataTrackResponse(unpublishDataTrackResponse *livekit.UnpublishDataTrackResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalDataTrackSubscriberHandles(dataTrackSubscriberHandles *livekit.DataTrackSubscriberHandles) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalStoreDataBlobResponse(storeDataBlobResponse *livekit.StoreDataBlobResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *signallingUnimplemented) SignalGetDataBlobResponse(getDataBlobResponse *livekit.GetDataBlobResponse) proto.Message {
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user