mirror of
https://github.com/m1k1o/neko.git
synced 2026-11-03 00:11:48 -06:00
a2cb38dd10
when NEKO_CAPTURE_VIDEO_PIPELINES is set without capture.video.ids the VideoIDs list stayed empty, so capture.Video().IDs() returned [] and the first websocket signal request crashed the whole server with "index out of range [0] with length 0" in signalRequest. now we fill VideoIDs from the configured pipeline keys (sorted by id) whenever no ids are set explicitly, and signalRequest returns a plain error instead of panicking when there is no video stream at all. added tests for the config loader, the capture manager and the signal handler so this path stays covered.
167 lines
3.5 KiB
Go
167 lines
3.5 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/m1k1o/neko/server/pkg/types"
|
|
"github.com/m1k1o/neko/server/pkg/types/event"
|
|
"github.com/m1k1o/neko/server/pkg/types/message"
|
|
|
|
"github.com/pion/webrtc/v4"
|
|
)
|
|
|
|
func (h *MessageHandlerCtx) signalRequest(session types.Session, payload *message.SignalRequest) error {
|
|
if !session.Profile().CanWatch {
|
|
return errors.New("not allowed to watch")
|
|
}
|
|
|
|
offer, peer, err := h.webrtc.CreatePeer(session)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// set webrtc as paused if session has private mode enabled
|
|
if session.PrivateModeEnabled() {
|
|
peer.SetPaused(true)
|
|
}
|
|
|
|
video := payload.Video
|
|
|
|
// use default first video, if not provided
|
|
if video.Selector == nil {
|
|
videos := h.capture.Video().IDs()
|
|
if len(videos) == 0 {
|
|
return errors.New("no video streams available")
|
|
}
|
|
video.Selector = &types.StreamSelector{
|
|
ID: videos[0],
|
|
Type: types.StreamSelectorTypeExact,
|
|
}
|
|
}
|
|
|
|
// TODO: Remove, used for compatibility with old clients.
|
|
if video.Auto == nil {
|
|
video.Auto = &payload.Auto
|
|
}
|
|
|
|
// set video stream
|
|
err = peer.SetVideo(video)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
audio := payload.Audio
|
|
|
|
// enable by default if not requested otherwise
|
|
if audio.Disabled == nil {
|
|
disabled := false
|
|
audio.Disabled = &disabled
|
|
}
|
|
|
|
// set audio stream
|
|
err = peer.SetAudio(audio)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
session.Send(
|
|
event.SIGNAL_PROVIDE,
|
|
message.SignalProvide{
|
|
SDP: offer.SDP,
|
|
ICEServers: h.webrtc.ICEServers(),
|
|
|
|
Video: peer.Video(),
|
|
Audio: peer.Audio(),
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalRestart(session types.Session) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
offer, err := peer.CreateOffer(true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// TODO: Use offer event instead.
|
|
session.Send(
|
|
event.SIGNAL_RESTART,
|
|
message.SignalDescription{
|
|
SDP: offer.SDP,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalOffer(session types.Session, payload *message.SignalDescription) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
err := peer.SetRemoteDescription(webrtc.SessionDescription{
|
|
SDP: payload.SDP,
|
|
Type: webrtc.SDPTypeOffer,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
answer, err := peer.CreateAnswer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
session.Send(
|
|
event.SIGNAL_ANSWER,
|
|
message.SignalDescription{
|
|
SDP: answer.SDP,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalAnswer(session types.Session, payload *message.SignalDescription) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
return peer.SetRemoteDescription(webrtc.SessionDescription{
|
|
SDP: payload.SDP,
|
|
Type: webrtc.SDPTypeAnswer,
|
|
})
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalCandidate(session types.Session, payload *message.SignalCandidate) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
return peer.SetCandidate(payload.ICECandidateInit)
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalVideo(session types.Session, payload *message.SignalVideo) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
return peer.SetVideo(payload.PeerVideoRequest)
|
|
}
|
|
|
|
func (h *MessageHandlerCtx) signalAudio(session types.Session, payload *message.SignalAudio) error {
|
|
peer := session.GetWebRTCPeer()
|
|
if peer == nil {
|
|
return errors.New("webRTC peer does not exist")
|
|
}
|
|
|
|
return peer.SetAudio(payload.PeerAudioRequest)
|
|
}
|