Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing features from m1k1o/neko #63

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"go.formatTool": "goformat",
"go.inferGopath": false,
"go.autocompleteUnimportedPackages": true,
"go.delveConfig": {
Expand Down
12 changes: 7 additions & 5 deletions internal/api/room/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) err
return utils.HttpForbidden("controls are locked")
}

h.sessions.SetHost(session)
session.SetAsHost()

return utils.HttpSuccess(w)
}
Expand All @@ -55,19 +55,20 @@ func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) err
}

h.desktop.ResetKeys()
h.sessions.ClearHost()
session.ClearHost()

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlTake(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
h.sessions.SetHost(session)
session.SetAsHost()

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
sessionId := chi.URLParam(r, "sessionId")

target, ok := h.sessions.Get(sessionId)
Expand All @@ -79,17 +80,18 @@ func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error
return utils.HttpBadRequest("target session is not allowed to host")
}

h.sessions.SetHost(target)
target.SetAsHostBy(session)

return utils.HttpSuccess(w)
}

func (h *RoomHandler) controlReset(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
_, hasHost := h.sessions.GetHost()

if hasHost {
h.desktop.ResetKeys()
h.sessions.ClearHost()
session.ClearHost()
}

return utils.HttpSuccess(w)
Expand Down
2 changes: 1 addition & 1 deletion internal/api/room/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func New(
}

// generate fallback image for private mode when needed
sessions.OnSettingsChanged(func(new types.Settings, old types.Settings) {
sessions.OnSettingsChanged(func(session types.Session, new types.Settings, old types.Settings) {
if old.PrivateMode && !new.PrivateMode {
log.Debug().Msg("clearing private mode fallback image")
h.privateModeImage = nil
Expand Down
32 changes: 11 additions & 21 deletions internal/api/room/keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,13 @@ import (
"github.com/demodesk/neko/pkg/utils"
)

type KeyboardMapData struct {
types.KeyboardMap
}

type KeyboardModifiersData struct {
types.KeyboardModifiers
}

func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) error {
data := &KeyboardMapData{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
keyboardMap := types.KeyboardMap{}
if err := utils.HttpJsonRequest(w, r, &keyboardMap); err != nil {
return err
}

err := h.desktop.SetKeyboardMap(data.KeyboardMap)
err := h.desktop.SetKeyboardMap(keyboardMap)
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}
Expand All @@ -30,28 +22,26 @@ func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Request) err
}

func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Request) error {
data, err := h.desktop.GetKeyboardMap()
keyboardMap, err := h.desktop.GetKeyboardMap()
if err != nil {
return utils.HttpInternalServerError().WithInternalErr(err)
}

return utils.HttpSuccess(w, KeyboardMapData{
KeyboardMap: *data,
})
return utils.HttpSuccess(w, keyboardMap)
}

func (h *RoomHandler) keyboardModifiersSet(w http.ResponseWriter, r *http.Request) error {
data := &KeyboardModifiersData{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
keyboardModifiers := types.KeyboardModifiers{}
if err := utils.HttpJsonRequest(w, r, &keyboardModifiers); err != nil {
return err
}

h.desktop.SetKeyboardModifiers(data.KeyboardModifiers)
h.desktop.SetKeyboardModifiers(keyboardModifiers)
return utils.HttpSuccess(w)
}

func (h *RoomHandler) keyboardModifiersGet(w http.ResponseWriter, r *http.Request) error {
return utils.HttpSuccess(w, KeyboardModifiersData{
KeyboardModifiers: h.desktop.GetKeyboardModifiers(),
})
keyboardModifiers := h.desktop.GetKeyboardModifiers()

return utils.HttpSuccess(w, keyboardModifiers)
}
36 changes: 9 additions & 27 deletions internal/api/room/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,16 @@ import (
"github.com/demodesk/neko/pkg/utils"
)

type ScreenConfigurationPayload struct {
Width int `json:"width"`
Height int `json:"height"`
Rate int16 `json:"rate"`
}

func (h *RoomHandler) screenConfiguration(w http.ResponseWriter, r *http.Request) error {
size := h.desktop.GetScreenSize()
screenSize := h.desktop.GetScreenSize()

return utils.HttpSuccess(w, ScreenConfigurationPayload{
Width: size.Width,
Height: size.Height,
Rate: size.Rate,
})
return utils.HttpSuccess(w, screenSize)
}

func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.Request) error {
data := &ScreenConfigurationPayload{}
auth, _ := auth.GetSession(r)

data := &types.ScreenSize{}
if err := utils.HttpJsonRequest(w, r, data); err != nil {
return err
}
Expand All @@ -43,10 +35,9 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
return utils.HttpUnprocessableEntity("cannot set screen size").WithInternalErr(err)
}

h.sessions.Broadcast(event.SCREEN_UPDATED, message.ScreenSize{
Width: size.Width,
Height: size.Height,
Rate: size.Rate,
h.sessions.Broadcast(event.SCREEN_UPDATED, message.ScreenSizeUpdate{
ID: auth.ID(),
ScreenSize: size,
})

return utils.HttpSuccess(w, data)
Expand All @@ -56,16 +47,7 @@ func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r *http.R
func (h *RoomHandler) screenConfigurationsList(w http.ResponseWriter, r *http.Request) error {
configurations := h.desktop.ScreenConfigurations()

list := make([]ScreenConfigurationPayload, 0, len(configurations))
for _, conf := range configurations {
list = append(list, ScreenConfigurationPayload{
Width: conf.Width,
Height: conf.Height,
Rate: conf.Rate,
})
}

return utils.HttpSuccess(w, list)
return utils.HttpSuccess(w, configurations)
}

func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Request) error {
Expand Down
22 changes: 18 additions & 4 deletions internal/api/room/settings.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package room

import (
"encoding/json"
"io"
"net/http"

"github.com/demodesk/neko/pkg/auth"
"github.com/demodesk/neko/pkg/types"
"github.com/demodesk/neko/pkg/utils"
)

Expand All @@ -12,13 +16,23 @@ func (h *RoomHandler) settingsGet(w http.ResponseWriter, r *http.Request) error
}

func (h *RoomHandler) settingsSet(w http.ResponseWriter, r *http.Request) error {
settings := h.sessions.Settings()
session, _ := auth.GetSession(r)

if err := utils.HttpJsonRequest(w, r, &settings); err != nil {
return err
// We read the request body first and unmashal it inside the UpdateSettingsFunc
// to ensure atomicity of the operation.
body, err := io.ReadAll(r.Body)
if err != nil {
return utils.HttpBadRequest("unable to read request body").WithInternalErr(err)
}

h.sessions.UpdateSettings(settings)
h.sessions.UpdateSettingsFunc(session, func(settings *types.Settings) bool {
err = json.Unmarshal(body, settings)
return err == nil
})

if err != nil {
return utils.HttpBadRequest("unable to parse provided data").WithInternalErr(err)
}

return utils.HttpSuccess(w)
}
49 changes: 18 additions & 31 deletions internal/session/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,14 @@ func (manager *SessionManagerCtx) Range(f func(session types.Session) bool) {
// host
// ---

func (manager *SessionManagerCtx) SetHost(host types.Session) {
func (manager *SessionManagerCtx) setHost(session, host types.Session) {
var hostId string
if host != nil {
hostId = host.ID()
}

manager.hostId.Store(hostId)
manager.emmiter.Emit("host_changed", host)
manager.emmiter.Emit("host_changed", session, host)
}

func (manager *SessionManagerCtx) GetHost() (types.Session, bool) {
Expand All @@ -229,10 +229,6 @@ func (manager *SessionManagerCtx) GetHost() (types.Session, bool) {
return manager.Get(hostId)
}

func (manager *SessionManagerCtx) ClearHost() {
manager.SetHost(nil)
}

func (manager *SessionManagerCtx) isHost(host types.Session) bool {
hostId, ok := manager.hostId.Load().(string)
return ok && hostId == host.ID()
Expand Down Expand Up @@ -357,62 +353,53 @@ func (manager *SessionManagerCtx) OnStateChanged(listener func(session types.Ses
})
}

func (manager *SessionManagerCtx) OnHostChanged(listener func(session types.Session)) {
func (manager *SessionManagerCtx) OnHostChanged(listener func(session, host types.Session)) {
manager.emmiter.On("host_changed", func(payload ...any) {
if payload[0] == nil {
listener(nil)
if payload[1] == nil {
listener(payload[0].(*SessionCtx), nil)
} else {
listener(payload[0].(*SessionCtx))
listener(payload[0].(*SessionCtx), payload[1].(*SessionCtx))
}
})
}

func (manager *SessionManagerCtx) OnSettingsChanged(listener func(new types.Settings, old types.Settings)) {
func (manager *SessionManagerCtx) OnSettingsChanged(listener func(session types.Session, new types.Settings, old types.Settings)) {
manager.emmiter.On("settings_changed", func(payload ...any) {
listener(payload[0].(types.Settings), payload[1].(types.Settings))
listener(payload[0].(types.Session), payload[1].(types.Settings), payload[2].(types.Settings))
})
}

// ---
// settings
// ---

func (manager *SessionManagerCtx) UpdateSettings(new types.Settings) {
manager.settingsMu.Lock()
old := manager.settings
manager.settings = new
manager.settingsMu.Unlock()

manager.updateSettings(new, old)
}

func (manager *SessionManagerCtx) UpdateSettingsFunc(f func(settings *types.Settings) bool) {
func (manager *SessionManagerCtx) UpdateSettingsFunc(session types.Session, f func(settings *types.Settings) bool) {
manager.settingsMu.Lock()
new := manager.settings
if f(&new) {
old := manager.settings
manager.settings = new
manager.settingsMu.Unlock()
manager.updateSettings(new, old)
manager.updateSettings(session, new, old)
return
}
manager.settingsMu.Unlock()
}

func (manager *SessionManagerCtx) updateSettings(new, old types.Settings) {
func (manager *SessionManagerCtx) updateSettings(session types.Session, new, old types.Settings) {
// if private mode changed
if old.PrivateMode != new.PrivateMode {
// update webrtc paused state for all sessions
for _, session := range manager.List() {
enabled := session.PrivateModeEnabled()
for _, s := range manager.List() {
enabled := s.PrivateModeEnabled()

// if session had control, it must release it
if enabled && session.IsHost() {
manager.ClearHost()
if enabled && s.IsHost() {
session.ClearHost()
}

// its webrtc connection will be paused or unpaused
if webrtcPeer := session.GetWebRTCPeer(); webrtcPeer != nil {
if webrtcPeer := s.GetWebRTCPeer(); webrtcPeer != nil {
webrtcPeer.SetPaused(enabled)
}
}
Expand Down Expand Up @@ -443,11 +430,11 @@ func (manager *SessionManagerCtx) updateSettings(new, old types.Settings) {
// if the host is not admin, it must release controls
host, hasHost := manager.GetHost()
if hasHost && !host.Profile().IsAdmin {
manager.ClearHost()
session.ClearHost()
}
}

manager.emmiter.Emit("settings_changed", new, old)
manager.emmiter.Emit("settings_changed", session, new, old)
}

func (manager *SessionManagerCtx) Settings() types.Settings {
Expand Down