neko/server/internal/http/legacy/wstoclient.go

642 lines
14 KiB
Go
Raw Normal View History

2024-07-20 05:10:27 +12:00
package legacy
import (
"encoding/json"
2024-07-21 01:45:01 +12:00
"errors"
2024-07-20 05:10:27 +12:00
"fmt"
2024-07-21 02:12:36 +12:00
"github.com/pion/webrtc/v3"
2024-07-21 01:45:01 +12:00
oldEvent "github.com/demodesk/neko/internal/http/legacy/event"
oldMessage "github.com/demodesk/neko/internal/http/legacy/message"
oldTypes "github.com/demodesk/neko/internal/http/legacy/types"
2024-07-21 02:12:36 +12:00
"github.com/demodesk/neko/internal/plugins/chat"
"github.com/demodesk/neko/internal/plugins/filetransfer"
2024-07-21 01:45:01 +12:00
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/types/event"
"github.com/demodesk/neko/pkg/types/message"
2024-07-20 05:10:27 +12:00
)
2024-07-21 01:45:01 +12:00
func sessionDataToMember(id string, session message.SessionData) (*oldTypes.Member, error) {
settings := chat.Settings{
CanSend: true, // defaults to true
CanReceive: true, // defaults to true
}
err := session.Profile.Plugins.Unmarshal(chat.PluginName, &settings)
if err != nil && !errors.Is(err, types.ErrPluginSettingsNotFound) {
return nil, fmt.Errorf("unable to unmarshal %s plugin settings from global settings: %w", chat.PluginName, err)
}
return &oldTypes.Member{
ID: id,
Name: session.Profile.Name,
Admin: session.Profile.IsAdmin,
Muted: !settings.CanSend,
}, nil
}
2024-07-23 09:30:45 +12:00
func (s *session) sendControlHost(request message.ControlHost) error {
2024-07-21 10:33:04 +12:00
lastHostID := s.lastHostID
2024-07-21 01:45:01 +12:00
if request.HasHost {
2024-07-21 10:19:04 +12:00
s.lastHostID = request.ID
2024-07-21 01:45:01 +12:00
if request.ID == request.HostID {
2024-07-21 10:33:04 +12:00
if request.ID == lastHostID || lastHostID == "" {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Control{
2024-07-21 10:33:04 +12:00
Event: oldEvent.CONTROL_LOCKED,
ID: request.HostID,
})
} else {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.AdminTarget{
2024-07-21 10:33:04 +12:00
Event: oldEvent.ADMIN_CONTROL,
ID: request.ID,
Target: lastHostID,
})
}
2024-07-21 10:19:04 +12:00
} else {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.ControlTarget{
2024-07-21 10:19:04 +12:00
Event: oldEvent.CONTROL_GIVE,
ID: request.HostID,
Target: request.ID,
})
2024-07-21 01:45:01 +12:00
}
}
if request.ID != "" {
2024-07-21 10:33:04 +12:00
s.lastHostID = ""
if request.ID == lastHostID {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Control{
2024-07-21 10:19:04 +12:00
Event: oldEvent.CONTROL_RELEASE,
ID: request.ID,
})
} else {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Control{
2024-07-21 10:19:04 +12:00
Event: oldEvent.ADMIN_RELEASE,
ID: request.ID,
})
}
2024-07-21 01:45:01 +12:00
}
return nil
}
2024-07-23 09:30:45 +12:00
func (s *session) wsToClient(msg []byte) error {
2024-07-21 01:45:01 +12:00
data := types.WebSocketMessage{}
err := json.Unmarshal(msg, &data)
2024-07-20 05:10:27 +12:00
if err != nil {
2024-07-21 01:45:01 +12:00
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
switch data.Event {
2024-07-20 05:10:27 +12:00
// System Events
2024-07-21 01:45:01 +12:00
case event.SYSTEM_DISCONNECT:
request := &message.SystemDisconnect{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SystemMessage{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SYSTEM_DISCONNECT,
Message: request.Message,
})
case event.SYSTEM_INIT:
request := &message.SystemInit{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
//
// MembersList
//
membersList := []*oldTypes.Member{}
s.sessions = map[string]*oldTypes.Member{}
2024-07-21 01:45:01 +12:00
for id, session := range request.Sessions {
if !session.State.IsConnected {
continue
}
2024-07-21 01:45:01 +12:00
member, err := sessionDataToMember(id, session)
if err != nil {
return err
}
membersList = append(membersList, member)
s.sessions[id] = member
2024-07-21 01:45:01 +12:00
}
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.MembersList{
2024-07-21 01:45:01 +12:00
Event: oldEvent.MEMBER_LIST,
Members: membersList,
})
if err != nil {
return err
}
//
// ScreenSize
//
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.ScreenResolution{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SCREEN_RESOLUTION,
Width: request.ScreenSize.Width,
Height: request.ScreenSize.Height,
Rate: request.ScreenSize.Rate,
})
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
// actually its already set when we create the session
s.id = request.SessionId
//
// ControlHost
//
2024-07-23 09:30:45 +12:00
err = s.sendControlHost(request.ControlHost)
2024-07-21 01:45:01 +12:00
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
//
// FileTransfer
//
filetransferSettings := filetransfer.Settings{
Enabled: true, // defaults to true
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
err = request.Settings.Plugins.Unmarshal(filetransfer.PluginName, &filetransferSettings)
if err != nil && !errors.Is(err, types.ErrPluginSettingsNotFound) {
return fmt.Errorf("unable to unmarshal %s plugin settings from global settings: %w", filetransfer.PluginName, err)
}
//
// Locks
//
locks := map[string]string{}
if request.Settings.LockedLogins {
locks["login"] = "" // TODO: We don't know who locked the login.
2024-07-22 01:29:37 +12:00
s.lockedLogins = true
2024-07-21 01:45:01 +12:00
}
if request.Settings.LockedControls {
locks["control"] = "" // TODO: We don't know who locked the control.
2024-07-22 01:29:37 +12:00
s.lockedControls = true
2024-07-21 01:45:01 +12:00
}
if !filetransferSettings.Enabled {
2024-07-22 01:29:37 +12:00
locks["file_transfer"] = "" // TODO: We don't know who locked the file transfer.
s.lockedFileTransfer = true
2024-07-21 01:45:01 +12:00
}
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SystemInit{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SYSTEM_INIT,
ImplicitHosting: request.Settings.ImplicitHosting,
Locks: locks,
FileTransfer: true, // TODO: We don't know if file transfer is enabled, we would need to check the global config somehow.
})
case event.SYSTEM_ADMIN:
request := &message.SystemAdmin{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
//
// ScreenSizesList
//
rates := map[string][]int16{}
for _, size := range request.ScreenSizesList {
key := fmt.Sprintf("%dx%d", size.Width, size.Height)
rates[key] = append(rates[key], size.Rate)
}
usedScreenSizes := map[string]struct{}{}
screenSizesList := map[int]oldTypes.ScreenConfiguration{}
for i, size := range request.ScreenSizesList {
key := fmt.Sprintf("%dx%d", size.Width, size.Height)
if _, ok := usedScreenSizes[key]; ok {
continue
}
ratesMap := map[int]int16{}
for i, rate := range rates[key] {
ratesMap[i] = rate
}
screenSizesList[i] = oldTypes.ScreenConfiguration{
Width: size.Width,
Height: size.Height,
Rates: ratesMap,
}
}
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.ScreenConfigurations{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SCREEN_CONFIGURATIONS,
Configurations: screenSizesList,
})
if err != nil {
return err
}
//
// BroadcastStatus
//
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.BroadcastStatus{
2024-07-21 01:45:01 +12:00
Event: oldEvent.BROADCAST_STATUS,
URL: request.BroadcastStatus.URL,
IsActive: request.BroadcastStatus.IsActive,
})
2024-07-20 05:10:27 +12:00
// Member Events
2024-07-21 01:45:01 +12:00
case event.SESSION_CREATED:
request := &message.SessionData{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
member, err := sessionDataToMember(request.ID, *request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
// only save session - will be notified on connect
s.sessions[request.ID] = member
return nil
2024-07-21 01:45:01 +12:00
case event.SESSION_DELETED:
request := &message.SessionID{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
// only continue if session is in the list - should have been already removed
if _, ok := s.sessions[request.ID]; !ok {
return nil
}
delete(s.sessions, request.ID)
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.MemberDisconnected{
2024-07-21 01:45:01 +12:00
Event: oldEvent.MEMBER_DISCONNECTED,
ID: request.ID,
})
case event.SESSION_STATE:
request := &message.SessionState{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
member, ok := s.sessions[request.ID]
if !ok {
return nil
}
if request.IsConnected && member != nil {
s.sessions[request.ID] = nil
// oldEvent.MEMBER_CONNECTED if not sent already
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Member{
Event: oldEvent.MEMBER_CONNECTED,
Member: member,
})
}
if !request.IsConnected {
delete(s.sessions, request.ID)
// oldEvent.MEMBER_DISCONNECTED if nor sent already
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.MemberDisconnected{
Event: oldEvent.MEMBER_DISCONNECTED,
ID: request.ID,
})
}
return nil
2024-07-21 01:45:01 +12:00
2024-07-20 05:10:27 +12:00
// Signal Events
2024-07-21 01:45:01 +12:00
case event.SIGNAL_OFFER:
request := &message.SignalDescription{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SignalOffer{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SIGNAL_OFFER,
SDP: request.SDP,
})
case event.SIGNAL_ANSWER:
request := &message.SignalDescription{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SignalAnswer{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SIGNAL_ANSWER,
DisplayName: s.profile.Name, // DisplayName
SDP: request.SDP,
})
case event.SIGNAL_CANDIDATE:
request := &message.SignalCandidate{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
json, err := json.Marshal(request.ICECandidateInit)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SignalCandidate{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SIGNAL_CANDIDATE,
Data: string(json),
})
case event.SIGNAL_PROVIDE:
request := &message.SignalProvide{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
iceServers := []webrtc.ICEServer{}
for _, ice := range request.ICEServers {
iceServers = append(iceServers, webrtc.ICEServer{
URLs: ice.URLs,
Username: ice.Username,
Credential: ice.Credential,
CredentialType: webrtc.ICECredentialTypePassword,
})
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.SignalProvide{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SIGNAL_PROVIDE,
ID: s.id, // SessionId
SDP: request.SDP,
Lite: len(iceServers) == 0, // if no ICE servers are provided, it's a lite offer
ICE: iceServers,
})
// Control Events
case event.CLIPBOARD_UPDATED:
request := &message.ClipboardData{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Clipboard{
2024-07-21 01:45:01 +12:00
Event: oldEvent.CONTROL_CLIPBOARD,
Text: request.Text,
})
case event.CONTROL_HOST:
request := &message.ControlHost{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.sendControlHost(*request)
2024-07-21 01:45:01 +12:00
case event.CONTROL_REQUEST:
request := &message.SessionID{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
if s.id == request.ID {
// if i am the one that is requesting, send CONTROL_REQUEST to me
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Control{
2024-07-21 01:45:01 +12:00
Event: oldEvent.CONTROL_REQUEST,
ID: request.ID,
})
} else {
// if not, let me know someone else is requesting
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.Control{
2024-07-21 01:45:01 +12:00
Event: oldEvent.CONTROL_REQUESTING,
ID: request.ID,
})
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
// Chat Events
case chat.CHAT_MESSAGE:
request := &chat.Message{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.ChatSend{
2024-07-21 01:45:01 +12:00
Event: oldEvent.CHAT_MESSAGE,
ID: request.ID,
Content: request.Content.Text,
})
2024-07-21 10:19:04 +12:00
case event.SEND_BROADCAST:
request := &message.SendBroadcast{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
if request.Subject == "emote" {
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.EmoteSend{
2024-07-21 10:19:04 +12:00
Event: oldEvent.CHAT_EMOTE,
ID: request.Sender,
Emote: request.Body.(string),
})
}
return nil
2024-07-21 01:45:01 +12:00
2024-07-20 05:10:27 +12:00
// File Transfer Events
2024-07-21 01:45:01 +12:00
case filetransfer.FILETRANSFER_UPDATE:
request := &filetransfer.Message{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
files := []oldTypes.FileListItem{}
for _, file := range request.Files {
var itemType string
switch file.Type {
case filetransfer.ItemTypeFile:
itemType = "file"
case filetransfer.ItemTypeDir:
itemType = "dir"
}
files = append(files, oldTypes.FileListItem{
Filename: file.Name,
Type: itemType,
Size: file.Size,
})
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.FileTransferList{
2024-07-21 01:45:01 +12:00
Event: oldEvent.FILETRANSFER_LIST,
Cwd: request.RootDir,
Files: files,
})
// Screen Events
case event.SCREEN_UPDATED:
request := &message.ScreenSizeUpdate{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.ScreenResolution{
2024-07-21 01:45:01 +12:00
Event: oldEvent.SCREEN_RESOLUTION,
ID: request.ID,
Width: request.ScreenSize.Width,
Height: request.ScreenSize.Height,
Rate: request.ScreenSize.Rate,
})
2024-07-20 05:10:27 +12:00
// Broadcast Events
2024-07-21 01:45:01 +12:00
case event.BROADCAST_STATUS:
request := &message.BroadcastStatus{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
2024-07-20 05:10:27 +12:00
}
2024-07-21 01:45:01 +12:00
2024-07-23 09:30:45 +12:00
return s.toClient(&oldMessage.BroadcastStatus{
2024-07-21 01:45:01 +12:00
Event: oldEvent.BROADCAST_STATUS,
URL: request.URL,
IsActive: request.IsActive,
})
2024-07-22 01:29:37 +12:00
// Admin Events
case event.SYSTEM_SETTINGS:
request := &message.SystemSettingsUpdate{}
err := json.Unmarshal(data.Payload, request)
if err != nil {
return err
}
if s.lockedControls != request.LockedControls {
s.lockedControls = request.LockedControls
if request.LockedControls {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_LOCK,
Resource: "control",
2024-07-21 01:45:01 +12:00
})
2024-07-22 01:29:37 +12:00
} else {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_UNLOCK,
Resource: "control",
})
}
if err != nil {
return err
}
}
if s.lockedLogins != request.LockedLogins {
s.lockedLogins = request.LockedLogins
if request.LockedLogins {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_LOCK,
Resource: "login",
})
} else {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_UNLOCK,
Resource: "login",
2024-07-21 01:45:01 +12:00
})
2024-07-22 01:29:37 +12:00
}
if err != nil {
return err
}
}
//
// FileTransfer
//
filetransferSettings := filetransfer.Settings{
Enabled: true, // defaults to true
}
err = request.Settings.Plugins.Unmarshal(filetransfer.PluginName, &filetransferSettings)
if err != nil && !errors.Is(err, types.ErrPluginSettingsNotFound) {
return fmt.Errorf("unable to unmarshal %s plugin settings from global settings: %w", filetransfer.PluginName, err)
}
if s.lockedFileTransfer != !filetransferSettings.Enabled {
s.lockedFileTransfer = !filetransferSettings.Enabled
if !filetransferSettings.Enabled {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_LOCK,
Resource: "file_transfer",
})
} else {
2024-07-23 09:30:45 +12:00
err = s.toClient(&oldMessage.AdminLock{
2024-07-22 01:29:37 +12:00
Event: oldEvent.ADMIN_UNLOCK,
Resource: "file_transfer",
})
}
if err != nil {
return err
}
}
return nil
/*
2024-07-21 01:45:01 +12:00
case:
2024-07-23 09:30:45 +12:00
s.toClient(&oldMessage.AdminTarget{
2024-07-21 10:33:04 +12:00
Event: oldEvent.ADMIN_BAN,
2024-07-21 01:45:01 +12:00
})
case:
2024-07-23 09:30:45 +12:00
s.toClient(&oldMessage.AdminTarget{
2024-07-21 10:33:04 +12:00
Event: oldEvent.ADMIN_KICK,
2024-07-21 01:45:01 +12:00
})
case:
2024-07-23 09:30:45 +12:00
s.toClient(&oldMessage.AdminTarget{
2024-07-21 10:33:04 +12:00
Event: oldEvent.ADMIN_MUTE,
2024-07-21 01:45:01 +12:00
})
case:
2024-07-23 09:30:45 +12:00
s.toClient(&oldMessage.AdminTarget{
2024-07-21 10:33:04 +12:00
Event: oldEvent.ADMIN_UNMUTE,
2024-07-21 01:45:01 +12:00
})
*/
case event.SYSTEM_HEARTBEAT:
return nil
2024-07-20 05:10:27 +12:00
default:
2024-07-21 01:45:01 +12:00
return fmt.Errorf("unknown event type: %s", data.Event)
2024-07-20 05:10:27 +12:00
}
}