sessions: switch to settings struct.

This commit is contained in:
Miroslav Šedivý 2022-03-27 00:08:06 +01:00
parent d004ddd68f
commit 81867d811b
9 changed files with 113 additions and 80 deletions

View File

@ -31,13 +31,14 @@ func New(
} }
// generate fallback image for private mode when needed // generate fallback image for private mode when needed
sessions.OnPrivateModeChanged(func(isPrivateMode bool) { sessions.OnSettingsChanged(func(new types.Settings, old types.Settings) {
if !isPrivateMode { if old.PrivateMode && !new.PrivateMode {
log.Debug().Msg("clearing private mode fallback image") log.Debug().Msg("clearing private mode fallback image")
h.privateModeImage = nil h.privateModeImage = nil
return return
} }
if !old.PrivateMode && new.PrivateMode {
img := h.desktop.GetScreenshotImage() img := h.desktop.GetScreenshotImage()
bytes, err := utils.CreateJPGImage(img, 90) bytes, err := utils.CreateJPGImage(img, 90)
if err != nil { if err != nil {
@ -47,6 +48,7 @@ func New(
log.Debug().Msg("using private mode fallback image") log.Debug().Msg("using private mode fallback image")
h.privateModeImage = bytes h.privateModeImage = bytes
}
}) })
return h return h
@ -110,7 +112,7 @@ func (h *RoomHandler) Route(r types.Router) {
func (h *RoomHandler) uploadMiddleware(w http.ResponseWriter, r *http.Request) (context.Context, error) { func (h *RoomHandler) uploadMiddleware(w http.ResponseWriter, r *http.Request) (context.Context, error) {
session, ok := auth.GetSession(r) session, ok := auth.GetSession(r)
if !ok || (!session.IsHost() && (!session.Profile().CanHost || !h.sessions.ImplicitHosting())) { if !ok || (!session.IsHost() && (!session.Profile().CanHost || !h.sessions.Settings().ImplicitHosting)) {
return nil, utils.HttpForbidden("without implicit hosting, only host can upload files") return nil, utils.HttpForbidden("without implicit hosting, only host can upload files")
} }

View File

@ -17,6 +17,12 @@ func New(config *config.Session) *SessionManagerCtx {
manager := &SessionManagerCtx{ manager := &SessionManagerCtx{
logger: log.With().Str("module", "session").Logger(), logger: log.With().Str("module", "session").Logger(),
config: config, config: config,
settings: types.Settings{
PrivateMode: false, // By default disabled.
ImplicitHosting: config.ImplicitHosting,
InactiveCursors: config.InactiveCursors,
MercifulReconnect: config.MercifulReconnect,
},
tokens: make(map[string]string), tokens: make(map[string]string),
sessions: make(map[string]*SessionCtx), sessions: make(map[string]*SessionCtx),
cursors: make(map[types.Session][]types.Cursor), cursors: make(map[types.Session][]types.Cursor),
@ -49,6 +55,9 @@ type SessionManagerCtx struct {
logger zerolog.Logger logger zerolog.Logger
config *config.Session config *config.Session
settings types.Settings
settingsMu sync.Mutex
tokens map[string]string tokens map[string]string
sessions map[string]*SessionCtx sessions map[string]*SessionCtx
sessionsMu sync.Mutex sessionsMu sync.Mutex
@ -56,9 +65,6 @@ type SessionManagerCtx struct {
host types.Session host types.Session
hostMu sync.Mutex hostMu sync.Mutex
privateMode bool
privateModeMu sync.Mutex
cursors map[types.Session][]types.Cursor cursors map[types.Session][]types.Cursor
cursorsMu sync.Mutex cursorsMu sync.Mutex
@ -200,39 +206,6 @@ func (manager *SessionManagerCtx) ClearHost() {
manager.SetHost(nil) manager.SetHost(nil)
} }
// ---
// private mode
// ---
func (manager *SessionManagerCtx) SetPrivateMode(isPrivateMode bool) {
manager.privateModeMu.Lock()
// only if value changed
if manager.privateMode == isPrivateMode {
manager.privateModeMu.Unlock()
return
}
// update webrtc paused state for all sessions
for _, session := range manager.List() {
if webrtcPeer := session.GetWebRTCPeer(); webrtcPeer != nil {
webrtcPeer.SetPaused(isPrivateMode && !session.Profile().IsAdmin)
}
}
manager.privateMode = isPrivateMode
manager.privateModeMu.Unlock()
manager.emmiter.Emit("private_mode_changed", isPrivateMode)
}
func (manager *SessionManagerCtx) PrivateMode() bool {
manager.privateModeMu.Lock()
defer manager.privateModeMu.Unlock()
return manager.privateMode
}
// --- // ---
// cursors // cursors
// --- // ---
@ -362,28 +335,42 @@ func (manager *SessionManagerCtx) OnHostChanged(listener func(session types.Sess
}) })
} }
func (manager *SessionManagerCtx) OnPrivateModeChanged(listener func(isPrivateMode bool)) { func (manager *SessionManagerCtx) OnSettingsChanged(listener func(new types.Settings, old types.Settings)) {
manager.emmiter.On("private_mode_changed", func(payload ...interface{}) { manager.emmiter.On("settings_changed", func(payload ...interface{}) {
listener(payload[0].(bool)) listener(payload[0].(types.Settings), payload[1].(types.Settings))
}) })
} }
// --- // ---
// config // settings
// --- // ---
func (manager *SessionManagerCtx) ImplicitHosting() bool { func (manager *SessionManagerCtx) UpdateSettings(new types.Settings) {
return manager.config.ImplicitHosting manager.settingsMu.Lock()
old := manager.settings
manager.settings = new
manager.settingsMu.Unlock()
// if private mode changed
if old.PrivateMode != new.PrivateMode {
// update webrtc paused state for all sessions
for _, session := range manager.List() {
if webrtcPeer := session.GetWebRTCPeer(); webrtcPeer != nil {
webrtcPeer.SetPaused(session.PrivateModeEnabled())
}
}
}
manager.emmiter.Emit("settings_changed", new, old)
} }
func (manager *SessionManagerCtx) InactiveCursors() bool { func (manager *SessionManagerCtx) Settings() types.Settings {
return manager.config.InactiveCursors manager.settingsMu.Lock()
defer manager.settingsMu.Unlock()
return manager.settings
} }
func (manager *SessionManagerCtx) CookieEnabled() bool { func (manager *SessionManagerCtx) CookieEnabled() bool {
return manager.config.CookieEnabled return manager.config.CookieEnabled
} }
func (manager *SessionManagerCtx) MercifulReconnect() bool {
return manager.config.MercifulReconnect
}

View File

@ -60,11 +60,11 @@ func (session *SessionCtx) IsHost() bool {
} }
func (session *SessionCtx) PrivateModeEnabled() bool { func (session *SessionCtx) PrivateModeEnabled() bool {
return session.manager.PrivateMode() && !session.profile.IsAdmin return session.manager.Settings().PrivateMode && !session.profile.IsAdmin
} }
func (session *SessionCtx) SetCursor(cursor types.Cursor) { func (session *SessionCtx) SetCursor(cursor types.Cursor) {
if session.manager.InactiveCursors() && session.profile.SendsInactiveCursor { if session.manager.Settings().InactiveCursors && session.profile.SendsInactiveCursor {
session.manager.SetCursor(cursor, session) session.manager.SetCursor(cursor, session)
} }
} }

View File

@ -40,7 +40,7 @@ func (h *MessageHandlerCtx) controlRequest(session types.Session) error {
return ErrIsAlreadyTheHost return ErrIsAlreadyTheHost
} }
if !h.sessions.ImplicitHosting() { if !h.sessions.Settings().ImplicitHosting {
// tell session if there is a host // tell session if there is a host
if host := h.sessions.GetHost(); host != nil { if host := h.sessions.GetHost(); host != nil {
session.Send( session.Send(

View File

@ -44,12 +44,15 @@ func (h *MessageHandlerCtx) systemInit(session types.Session) error {
ControlHost: controlHost, ControlHost: controlHost,
ScreenSize: message.ScreenSize(*size), ScreenSize: message.ScreenSize(*size),
Sessions: sessions, Sessions: sessions,
ImplicitHosting: h.sessions.ImplicitHosting(), Settings: h.sessions.Settings(),
InactiveCursors: h.sessions.InactiveCursors(),
ScreencastEnabled: h.capture.Screencast().Enabled(), ScreencastEnabled: h.capture.Screencast().Enabled(),
WebRTC: message.SystemWebRTC{ WebRTC: message.SystemWebRTC{
Videos: h.capture.VideoIDs(), Videos: h.capture.VideoIDs(),
}, },
// TODO: Left for compatibility with old client, remove.
ImplicitHosting: h.sessions.Settings().ImplicitHosting,
InactiveCursors: h.sessions.Settings().InactiveCursors,
}) })
return nil return nil

View File

@ -49,6 +49,8 @@ type WebSocketManagerCtx struct {
desktop types.DesktopManager desktop types.DesktopManager
handler *handler.MessageHandlerCtx handler *handler.MessageHandlerCtx
handlers []types.WebSocketHandler handlers []types.WebSocketHandler
shutdownInactiveCursors chan struct{}
} }
func (manager *WebSocketManagerCtx) Start() { func (manager *WebSocketManagerCtx) Start() {
@ -111,6 +113,24 @@ func (manager *WebSocketManagerCtx) Start() {
Msg("session host changed") Msg("session host changed")
}) })
manager.sessions.OnSettingsChanged(func(new types.Settings, old types.Settings) {
// start inactive cursors
if new.InactiveCursors && !old.InactiveCursors {
manager.startInactiveCursors()
}
// stop inactive cursors
if !new.InactiveCursors && old.InactiveCursors {
manager.stopInactiveCursors()
}
manager.sessions.Broadcast(event.SYSTEM_SETTINGS, new, nil)
manager.logger.Info().
Interface("new", new).
Interface("old", old).
Msg("settings changed")
})
manager.desktop.OnClipboardUpdated(func() { manager.desktop.OnClipboardUpdated(func() {
session := manager.sessions.GetHost() session := manager.sessions.GetHost()
if session == nil || !session.Profile().CanAccessClipboard { if session == nil || !session.Profile().CanAccessClipboard {
@ -135,8 +155,8 @@ func (manager *WebSocketManagerCtx) Start() {
manager.fileChooserDialogEvents() manager.fileChooserDialogEvents()
if manager.sessions.InactiveCursors() { if manager.sessions.Settings().InactiveCursors {
manager.inactiveCursors() manager.startInactiveCursors()
} }
manager.logger.Info().Msg("websocket starting") manager.logger.Info().Msg("websocket starting")
@ -145,6 +165,7 @@ func (manager *WebSocketManagerCtx) Start() {
func (manager *WebSocketManagerCtx) Shutdown() error { func (manager *WebSocketManagerCtx) Shutdown() error {
manager.logger.Info().Msg("shutdown") manager.logger.Info().Msg("shutdown")
close(manager.shutdown) close(manager.shutdown)
manager.stopInactiveCursors()
manager.wg.Wait() manager.wg.Wait()
return nil return nil
} }
@ -196,7 +217,7 @@ func (manager *WebSocketManagerCtx) connect(connection *websocket.Conn, r *http.
if session.State().IsConnected { if session.State().IsConnected {
logger.Warn().Msg("already connected") logger.Warn().Msg("already connected")
if !manager.sessions.MercifulReconnect() { if !manager.sessions.Settings().MercifulReconnect {
peer.Destroy("already connected") peer.Destroy("already connected")
return return
} }
@ -299,8 +320,14 @@ func (manager *WebSocketManagerCtx) handle(connection *websocket.Conn, peer type
} }
} }
func (manager *WebSocketManagerCtx) inactiveCursors() { func (manager *WebSocketManagerCtx) startInactiveCursors() {
if manager.shutdownInactiveCursors != nil {
manager.logger.Warn().Msg("inactive cursors handler already running")
return
}
manager.logger.Info().Msg("starting inactive cursors handler") manager.logger.Info().Msg("starting inactive cursors handler")
manager.shutdownInactiveCursors = make(chan struct{})
manager.wg.Add(1) manager.wg.Add(1)
go func() { go func() {
@ -314,8 +341,9 @@ func (manager *WebSocketManagerCtx) inactiveCursors() {
for { for {
select { select {
case <-manager.shutdown: case <-manager.shutdownInactiveCursors:
manager.logger.Info().Msg("stopping inactive cursors handler") manager.logger.Info().Msg("stopping inactive cursors handler")
manager.shutdownInactiveCursors = nil
return return
case <-ticker.C: case <-ticker.C:
cursorsMap := manager.sessions.PopCursors() cursorsMap := manager.sessions.PopCursors()
@ -342,3 +370,9 @@ func (manager *WebSocketManagerCtx) inactiveCursors() {
} }
}() }()
} }
func (manager *WebSocketManagerCtx) stopInactiveCursors() {
if manager.shutdownInactiveCursors != nil {
close(manager.shutdownInactiveCursors)
}
}

View File

@ -3,6 +3,7 @@ package event
const ( const (
SYSTEM_INIT = "system/init" SYSTEM_INIT = "system/init"
SYSTEM_ADMIN = "system/admin" SYSTEM_ADMIN = "system/admin"
SYSTEM_SETTINGS = "system/settings"
SYSTEM_LOGS = "system/logs" SYSTEM_LOGS = "system/logs"
SYSTEM_DISCONNECT = "system/disconnect" SYSTEM_DISCONNECT = "system/disconnect"
) )

View File

@ -19,10 +19,13 @@ type SystemInit struct {
ControlHost ControlHost `json:"control_host"` ControlHost ControlHost `json:"control_host"`
ScreenSize ScreenSize `json:"screen_size"` ScreenSize ScreenSize `json:"screen_size"`
Sessions map[string]SessionData `json:"sessions"` Sessions map[string]SessionData `json:"sessions"`
ImplicitHosting bool `json:"implicit_hosting"` Settings types.Settings `json:"settings"`
InactiveCursors bool `json:"inactive_cursors"`
ScreencastEnabled bool `json:"screencast_enabled"` ScreencastEnabled bool `json:"screencast_enabled"`
WebRTC SystemWebRTC `json:"webrtc"` WebRTC SystemWebRTC `json:"webrtc"`
// TODO: Left for compatibility with old client, remove.
ImplicitHosting bool `json:"implicit_hosting"`
InactiveCursors bool `json:"inactive_cursors"`
} }
type SystemAdmin struct { type SystemAdmin struct {

View File

@ -22,6 +22,13 @@ type SessionState struct {
IsWatching bool `json:"is_watching"` IsWatching bool `json:"is_watching"`
} }
type Settings struct {
PrivateMode bool `json:"private_mode"`
ImplicitHosting bool `json:"implicit_hosting"`
InactiveCursors bool `json:"inactive_cursors"`
MercifulReconnect bool `json:"merciful_reconnect"`
}
type Session interface { type Session interface {
ID() string ID() string
Profile() MemberProfile Profile() MemberProfile
@ -56,9 +63,6 @@ type SessionManager interface {
GetHost() Session GetHost() Session
ClearHost() ClearHost()
SetPrivateMode(isPrivateMode bool)
PrivateMode() bool
SetCursor(cursor Cursor, session Session) SetCursor(cursor Cursor, session Session)
PopCursors() map[Session][]Cursor PopCursors() map[Session][]Cursor
@ -73,12 +77,11 @@ type SessionManager interface {
OnProfileChanged(listener func(session Session)) OnProfileChanged(listener func(session Session))
OnStateChanged(listener func(session Session)) OnStateChanged(listener func(session Session))
OnHostChanged(listener func(session Session)) OnHostChanged(listener func(session Session))
OnPrivateModeChanged(listener func(isPrivateMode bool)) OnSettingsChanged(listener func(new Settings, old Settings))
ImplicitHosting() bool UpdateSettings(Settings)
InactiveCursors() bool Settings() Settings
CookieEnabled() bool CookieEnabled() bool
MercifulReconnect() bool
CookieSetToken(w http.ResponseWriter, token string) CookieSetToken(w http.ResponseWriter, token string)
CookieClearToken(w http.ResponseWriter, r *http.Request) CookieClearToken(w http.ResponseWriter, r *http.Request)