// 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) } return nil }