add session to host change.

This commit is contained in:
Miroslav Šedivý 2024-05-06 23:47:13 +02:00
parent b562c797b3
commit 416faa3df4
9 changed files with 46 additions and 46 deletions

View File

@ -43,7 +43,7 @@ func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Request) err
return utils.HttpForbidden("controls are locked") return utils.HttpForbidden("controls are locked")
} }
h.sessions.SetHost(session) session.SetAsHost()
return utils.HttpSuccess(w) return utils.HttpSuccess(w)
} }
@ -55,19 +55,20 @@ func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Request) err
} }
h.desktop.ResetKeys() h.desktop.ResetKeys()
h.sessions.ClearHost() session.ClearHost()
return utils.HttpSuccess(w) return utils.HttpSuccess(w)
} }
func (h *RoomHandler) controlTake(w http.ResponseWriter, r *http.Request) error { func (h *RoomHandler) controlTake(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r) session, _ := auth.GetSession(r)
h.sessions.SetHost(session) session.SetAsHost()
return utils.HttpSuccess(w) return utils.HttpSuccess(w)
} }
func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error { func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
sessionId := chi.URLParam(r, "sessionId") sessionId := chi.URLParam(r, "sessionId")
target, ok := h.sessions.Get(sessionId) target, ok := h.sessions.Get(sessionId)
@ -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") return utils.HttpBadRequest("target session is not allowed to host")
} }
h.sessions.SetHost(target) target.SetAsHostBy(session)
return utils.HttpSuccess(w) return utils.HttpSuccess(w)
} }
func (h *RoomHandler) controlReset(w http.ResponseWriter, r *http.Request) error { func (h *RoomHandler) controlReset(w http.ResponseWriter, r *http.Request) error {
session, _ := auth.GetSession(r)
_, hasHost := h.sessions.GetHost() _, hasHost := h.sessions.GetHost()
if hasHost { if hasHost {
h.desktop.ResetKeys() h.desktop.ResetKeys()
h.sessions.ClearHost() session.ClearHost()
} }
return utils.HttpSuccess(w) return utils.HttpSuccess(w)

View File

@ -210,14 +210,14 @@ func (manager *SessionManagerCtx) Range(f func(session types.Session) bool) {
// host // host
// --- // ---
func (manager *SessionManagerCtx) SetHost(host types.Session) { func (manager *SessionManagerCtx) setHost(session, host types.Session) {
var hostId string var hostId string
if host != nil { if host != nil {
hostId = host.ID() hostId = host.ID()
} }
manager.hostId.Store(hostId) manager.hostId.Store(hostId)
manager.emmiter.Emit("host_changed", host) manager.emmiter.Emit("host_changed", session, host)
} }
func (manager *SessionManagerCtx) GetHost() (types.Session, bool) { func (manager *SessionManagerCtx) GetHost() (types.Session, bool) {
@ -229,10 +229,6 @@ func (manager *SessionManagerCtx) GetHost() (types.Session, bool) {
return manager.Get(hostId) return manager.Get(hostId)
} }
func (manager *SessionManagerCtx) ClearHost() {
manager.SetHost(nil)
}
func (manager *SessionManagerCtx) isHost(host types.Session) bool { func (manager *SessionManagerCtx) isHost(host types.Session) bool {
hostId, ok := manager.hostId.Load().(string) hostId, ok := manager.hostId.Load().(string)
return ok && hostId == host.ID() return ok && hostId == host.ID()
@ -357,12 +353,12 @@ 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) { manager.emmiter.On("host_changed", func(payload ...any) {
if payload[0] == nil { if payload[1] == nil {
listener(nil) listener(payload[0].(*SessionCtx), nil)
} else { } else {
listener(payload[0].(*SessionCtx)) listener(payload[0].(*SessionCtx), payload[1].(*SessionCtx))
} }
}) })
} }
@ -394,16 +390,16 @@ func (manager *SessionManagerCtx) updateSettings(session types.Session, new, old
// if private mode changed // if private mode changed
if old.PrivateMode != new.PrivateMode { if old.PrivateMode != new.PrivateMode {
// update webrtc paused state for all sessions // update webrtc paused state for all sessions
for _, session := range manager.List() { for _, s := range manager.List() {
enabled := session.PrivateModeEnabled() enabled := s.PrivateModeEnabled()
// if session had control, it must release it // if session had control, it must release it
if enabled && session.IsHost() { if enabled && s.IsHost() {
manager.ClearHost() session.ClearHost()
} }
// its webrtc connection will be paused or unpaused // its webrtc connection will be paused or unpaused
if webrtcPeer := session.GetWebRTCPeer(); webrtcPeer != nil { if webrtcPeer := s.GetWebRTCPeer(); webrtcPeer != nil {
webrtcPeer.SetPaused(enabled) webrtcPeer.SetPaused(enabled)
} }
} }
@ -434,7 +430,7 @@ func (manager *SessionManagerCtx) updateSettings(session types.Session, new, old
// if the host is not admin, it must release controls // if the host is not admin, it must release controls
host, hasHost := manager.GetHost() host, hasHost := manager.GetHost()
if hasHost && !host.Profile().IsAdmin { if hasHost && !host.Profile().IsAdmin {
manager.ClearHost() session.ClearHost()
} }
} }

View File

@ -43,7 +43,7 @@ func (session *SessionCtx) Profile() types.MemberProfile {
func (session *SessionCtx) profileChanged() { func (session *SessionCtx) profileChanged() {
if !session.profile.CanHost && session.IsHost() { if !session.profile.CanHost && session.IsHost() {
session.manager.ClearHost() session.ClearHost()
} }
if (!session.profile.CanConnect || !session.profile.CanLogin || !session.profile.CanWatch) && session.state.IsWatching { if (!session.profile.CanConnect || !session.profile.CanLogin || !session.profile.CanWatch) && session.state.IsWatching {
@ -68,6 +68,18 @@ func (session *SessionCtx) IsHost() bool {
return session.manager.isHost(session) return session.manager.isHost(session)
} }
func (session *SessionCtx) SetAsHost() {
session.manager.setHost(session, session)
}
func (session *SessionCtx) SetAsHostBy(host types.Session) {
session.manager.setHost(session, host)
}
func (session *SessionCtx) ClearHost() {
session.manager.setHost(session, nil)
}
func (session *SessionCtx) PrivateModeEnabled() bool { func (session *SessionCtx) PrivateModeEnabled() bool {
return session.manager.Settings().PrivateMode && !session.profile.IsAdmin return session.manager.Settings().PrivateMode && !session.profile.IsAdmin
} }
@ -82,10 +94,8 @@ func (session *SessionCtx) SetCursor(cursor types.Cursor) {
// websocket // websocket
// --- // ---
//
// Connect WebSocket peer sets current peer and emits connected event. It also destroys the // Connect WebSocket peer sets current peer and emits connected event. It also destroys the
// previous peer, if there was one. If the peer is already set, it will be ignored. // previous peer, if there was one. If the peer is already set, it will be ignored.
//
func (session *SessionCtx) ConnectWebSocketPeer(websocketPeer types.WebSocketPeer) { func (session *SessionCtx) ConnectWebSocketPeer(websocketPeer types.WebSocketPeer) {
session.websocketMu.Lock() session.websocketMu.Lock()
isCurrentPeer := websocketPeer == session.websocketPeer isCurrentPeer := websocketPeer == session.websocketPeer
@ -113,14 +123,12 @@ func (session *SessionCtx) ConnectWebSocketPeer(websocketPeer types.WebSocketPee
} }
} }
//
// Disconnect WebSocket peer sets current peer to nil and emits disconnected event. It also // Disconnect WebSocket peer sets current peer to nil and emits disconnected event. It also
// allows for a delayed disconnect. That means, the peer will not be disconnected immediately, // allows for a delayed disconnect. That means, the peer will not be disconnected immediately,
// but after a delay. If the peer is connected again before the delay, the disconnect will be // but after a delay. If the peer is connected again before the delay, the disconnect will be
// cancelled. // cancelled.
// //
// If the peer is not the current peer or the peer is nil, it will be ignored. // If the peer is not the current peer or the peer is nil, it will be ignored.
//
func (session *SessionCtx) DisconnectWebSocketPeer(websocketPeer types.WebSocketPeer, delayed bool) { func (session *SessionCtx) DisconnectWebSocketPeer(websocketPeer types.WebSocketPeer, delayed bool) {
session.websocketMu.Lock() session.websocketMu.Lock()
isCurrentPeer := websocketPeer == session.websocketPeer && websocketPeer != nil isCurrentPeer := websocketPeer == session.websocketPeer && websocketPeer != nil
@ -175,10 +183,8 @@ func (session *SessionCtx) DisconnectWebSocketPeer(websocketPeer types.WebSocket
session.websocketMu.Unlock() session.websocketMu.Unlock()
} }
//
// Destroy WebSocket peer disconnects the peer and destroys it. It ensures that the peer is // Destroy WebSocket peer disconnects the peer and destroys it. It ensures that the peer is
// disconnected immediately even though normal flow would be to disconnect it delayed. // disconnected immediately even though normal flow would be to disconnect it delayed.
//
func (session *SessionCtx) DestroyWebSocketPeer(reason string) { func (session *SessionCtx) DestroyWebSocketPeer(reason string) {
session.websocketMu.Lock() session.websocketMu.Lock()
peer := session.websocketPeer peer := session.websocketPeer
@ -195,9 +201,7 @@ func (session *SessionCtx) DestroyWebSocketPeer(reason string) {
peer.Destroy(reason) peer.Destroy(reason)
} }
//
// Send event to websocket peer. // Send event to websocket peer.
//
func (session *SessionCtx) Send(event string, payload any) { func (session *SessionCtx) Send(event string, payload any) {
session.websocketMu.Lock() session.websocketMu.Lock()
peer := session.websocketPeer peer := session.websocketPeer
@ -212,9 +216,7 @@ func (session *SessionCtx) Send(event string, payload any) {
// webrtc // webrtc
// --- // ---
//
// Set webrtc peer and destroy the old one, if there is old one. // Set webrtc peer and destroy the old one, if there is old one.
//
func (session *SessionCtx) SetWebRTCPeer(webrtcPeer types.WebRTCPeer) { func (session *SessionCtx) SetWebRTCPeer(webrtcPeer types.WebRTCPeer) {
session.webrtcMu.Lock() session.webrtcMu.Lock()
session.webrtcPeer, webrtcPeer = webrtcPeer, session.webrtcPeer session.webrtcPeer, webrtcPeer = webrtcPeer, session.webrtcPeer
@ -225,14 +227,12 @@ func (session *SessionCtx) SetWebRTCPeer(webrtcPeer types.WebRTCPeer) {
} }
} }
//
// Set if current webrtc peer is connected or not. Since there might be lefover calls from // Set if current webrtc peer is connected or not. Since there might be lefover calls from
// webrtc peer, that are not used anymore, we need to check if the webrtc peer is still the // webrtc peer, that are not used anymore, we need to check if the webrtc peer is still the
// same as the one we are setting the connected state for. // same as the one we are setting the connected state for.
// //
// If webrtc peer is disconnected, we don't expect it to be reconnected, so we set it to nil // If webrtc peer is disconnected, we don't expect it to be reconnected, so we set it to nil
// and send a signal close to the client. New connection is expected to use a new webrtc peer. // and send a signal close to the client. New connection is expected to use a new webrtc peer.
//
func (session *SessionCtx) SetWebRTCConnected(webrtcPeer types.WebRTCPeer, connected bool) { func (session *SessionCtx) SetWebRTCConnected(webrtcPeer types.WebRTCPeer, connected bool) {
session.webrtcMu.Lock() session.webrtcMu.Lock()
isCurrentPeer := webrtcPeer == session.webrtcPeer isCurrentPeer := webrtcPeer == session.webrtcPeer
@ -274,9 +274,7 @@ func (session *SessionCtx) SetWebRTCConnected(webrtcPeer types.WebRTCPeer, conne
} }
} }
//
// Get current WebRTC peer. Nil if not connected. // Get current WebRTC peer. Nil if not connected.
//
func (session *SessionCtx) GetWebRTCPeer() types.WebRTCPeer { func (session *SessionCtx) GetWebRTCPeer() types.WebRTCPeer {
session.webrtcMu.Lock() session.webrtcMu.Lock()
defer session.webrtcMu.Unlock() defer session.webrtcMu.Unlock()

View File

@ -26,7 +26,7 @@ func (h *MessageHandlerCtx) controlRelease(session types.Session) error {
} }
h.desktop.ResetKeys() h.desktop.ResetKeys()
h.sessions.ClearHost() session.ClearHost()
return nil return nil
} }
@ -58,7 +58,7 @@ func (h *MessageHandlerCtx) controlRequest(session types.Session) error {
} }
} }
h.sessions.SetHost(session) session.SetAsHost()
return nil return nil
} }

View File

@ -56,7 +56,7 @@ func (h *MessageHandlerCtx) SessionDisconnected(session types.Session) error {
// clear host if exists // clear host if exists
if session.IsHost() { if session.IsHost() {
h.desktop.ResetKeys() h.desktop.ResetKeys()
h.sessions.ClearHost() session.ClearHost()
} }
if session.Profile().IsAdmin { if session.Profile().IsAdmin {

View File

@ -110,18 +110,20 @@ func (manager *WebSocketManagerCtx) Start() {
Msg("session state changed") Msg("session state changed")
}) })
manager.sessions.OnHostChanged(func(session types.Session) { manager.sessions.OnHostChanged(func(session, host types.Session) {
payload := message.ControlHost{ payload := message.ControlHost{
HasHost: session != nil, ID: session.ID(),
HasHost: host != nil,
} }
if payload.HasHost { if payload.HasHost {
payload.HostID = session.ID() payload.HostID = host.ID()
} }
manager.sessions.Broadcast(event.CONTROL_HOST, payload) manager.sessions.Broadcast(event.CONTROL_HOST, payload)
manager.logger.Info(). manager.logger.Info().
Str("session_id", session.ID()).
Bool("has_host", payload.HasHost). Bool("has_host", payload.HasHost).
Str("host_id", payload.HostID). Str("host_id", payload.HostID).
Msg("session host changed") Msg("session host changed")

View File

@ -97,7 +97,7 @@ func TestHostsOnly(t *testing.T) {
} }
// r2 is host // r2 is host
sessionManager.SetHost(session) session.SetAsHost()
r3, _, err := rWithSession(types.MemberProfile{CanHost: false}) r3, _, err := rWithSession(types.MemberProfile{CanHost: false})
if err != nil { if err != nil {

View File

@ -116,6 +116,7 @@ type SessionCursors struct {
///////////////////////////// /////////////////////////////
type ControlHost struct { type ControlHost struct {
ID string `json:"id"`
HasHost bool `json:"has_host"` HasHost bool `json:"has_host"`
HostID string `json:"host_id,omitempty"` HostID string `json:"host_id,omitempty"`
} }

View File

@ -57,6 +57,9 @@ type Session interface {
Profile() MemberProfile Profile() MemberProfile
State() SessionState State() SessionState
IsHost() bool IsHost() bool
SetAsHost()
SetAsHostBy(session Session)
ClearHost()
PrivateModeEnabled() bool PrivateModeEnabled() bool
// cursor // cursor
@ -83,9 +86,7 @@ type SessionManager interface {
List() []Session List() []Session
Range(func(Session) bool) Range(func(Session) bool)
SetHost(host Session)
GetHost() (Session, bool) GetHost() (Session, bool)
ClearHost()
SetCursor(cursor Cursor, session Session) SetCursor(cursor Cursor, session Session)
PopCursors() map[Session][]Cursor PopCursors() map[Session][]Cursor
@ -100,7 +101,7 @@ type SessionManager interface {
OnDisconnected(listener func(session Session)) OnDisconnected(listener func(session Session))
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, host Session))
OnSettingsChanged(listener func(session Session, new Settings, old Settings)) OnSettingsChanged(listener func(session Session, new Settings, old Settings))
UpdateSettingsFunc(session Session, f func(settings *Settings) bool) UpdateSettingsFunc(session Session, f func(settings *Settings) bool)