Implicit control gain (#108)
* add client side implicit hosting. * add server side implicit hosting. * update changelog. * allow clipboard & keybaord access.
This commit is contained in:
parent
f08ed0fc28
commit
7d1fa28d88
@ -18,20 +18,20 @@
|
|||||||
<span @click="mute(child.data.member)" v-if="!child.data.member.muted">{{ $t('context.mute') }}</span>
|
<span @click="mute(child.data.member)" v-if="!child.data.member.muted">{{ $t('context.mute') }}</span>
|
||||||
<span @click="unmute(child.data.member)" v-else>{{ $t('context.unmute') }}</span>
|
<span @click="unmute(child.data.member)" v-else>{{ $t('context.unmute') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="child.data.member.id === host">
|
<li v-if="child.data.member.id === host && !implicitHosting">
|
||||||
<span @click="adminRelease(child.data.member)">{{ $t('context.release') }}</span>
|
<span @click="adminRelease(child.data.member)">{{ $t('context.release') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="child.data.member.id === host">
|
<li v-if="child.data.member.id === host && !implicitHosting">
|
||||||
<span @click="adminControl(child.data.member)">{{ $t('context.take') }}</span>
|
<span @click="adminControl(child.data.member)">{{ $t('context.take') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span v-if="child.data.member.id !== host" @click="adminGive(child.data.member)">{{
|
<span v-if="child.data.member.id !== host && !implicitHosting" @click="adminGive(child.data.member)">{{
|
||||||
$t('context.give')
|
$t('context.give')
|
||||||
}}</span>
|
}}</span>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<li v-if="hosting">
|
<li v-if="hosting && !implicitHosting">
|
||||||
<span @click="give(child.data.member)">{{ $t('context.give') }}</span>
|
<span @click="give(child.data.member)">{{ $t('context.give') }}</span>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
@ -161,6 +161,10 @@
|
|||||||
return this.$accessor.remote.id
|
return this.$accessor.remote.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get implicitHosting() {
|
||||||
|
return this.$accessor.remote.implicitHosting
|
||||||
|
}
|
||||||
|
|
||||||
open(event: MouseEvent, data: any) {
|
open(event: MouseEvent, data: any) {
|
||||||
this.context.open(event, data)
|
this.context.open(event, data)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-if="seesControl">
|
<li v-if="!implicitHosting && (!controlLocked || hosting)">
|
||||||
<i
|
<i
|
||||||
:class="[
|
:class="[
|
||||||
!disabeld && shakeKbd ? 'shake' : '',
|
!disabeld && shakeKbd ? 'shake' : '',
|
||||||
@ -20,7 +20,19 @@
|
|||||||
@click.stop.prevent="toggleControl"
|
@click.stop.prevent="toggleControl"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="seesControl">
|
<li class="no-pointer" v-if="implicitHosting">
|
||||||
|
<i
|
||||||
|
:class="[controlLocked ? 'disabled' : '', 'fas', 'fa-mouse-pointer']"
|
||||||
|
v-tooltip="{
|
||||||
|
content: controlLocked ? $t('controls.hasnot') : $t('controls.has'),
|
||||||
|
placement: 'top',
|
||||||
|
offset: 5,
|
||||||
|
boundariesElement: 'body',
|
||||||
|
delay: { show: 300, hide: 100 },
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li v-if="implicitHosting || (!implicitHosting && (!controlLocked || hosting))">
|
||||||
<label
|
<label
|
||||||
class="switch"
|
class="switch"
|
||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
@ -31,7 +43,7 @@
|
|||||||
delay: { show: 300, hide: 100 },
|
delay: { show: 300, hide: 100 },
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<input type="checkbox" v-model="locked" :disabled="!hosting" />
|
<input type="checkbox" v-model="locked" :disabled="!hosting || (implicitHosting && controlLocked)" />
|
||||||
<span />
|
<span />
|
||||||
</label>
|
</label>
|
||||||
</li>
|
</li>
|
||||||
@ -105,6 +117,10 @@
|
|||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&.no-pointer {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
|
|
||||||
@ -242,12 +258,8 @@
|
|||||||
export default class extends Vue {
|
export default class extends Vue {
|
||||||
@Prop(Boolean) readonly shakeKbd!: boolean
|
@Prop(Boolean) readonly shakeKbd!: boolean
|
||||||
|
|
||||||
get severLocked(): boolean {
|
get controlLocked() {
|
||||||
return 'control' in this.$accessor.locked && this.$accessor.locked['control']
|
return 'control' in this.$accessor.locked && this.$accessor.locked['control'] && !this.$accessor.user.admin
|
||||||
}
|
|
||||||
|
|
||||||
get seesControl(): boolean {
|
|
||||||
return !this.severLocked || this.$accessor.user.admin || this.hosting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get disabeld() {
|
get disabeld() {
|
||||||
@ -258,6 +270,10 @@
|
|||||||
return this.$accessor.remote.hosting
|
return this.$accessor.remote.hosting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get implicitHosting() {
|
||||||
|
return this.$accessor.remote.implicitHosting
|
||||||
|
}
|
||||||
|
|
||||||
get volume() {
|
get volume() {
|
||||||
return this.$accessor.video.volume
|
return this.$accessor.video.volume
|
||||||
}
|
}
|
||||||
|
@ -240,6 +240,10 @@
|
|||||||
return this.$accessor.remote.hosting
|
return this.$accessor.remote.hosting
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get implicitHosting() {
|
||||||
|
return this.$accessor.remote.implicitHosting
|
||||||
|
}
|
||||||
|
|
||||||
get hosted() {
|
get hosted() {
|
||||||
return this.$accessor.remote.hosted
|
return this.$accessor.remote.hosted
|
||||||
}
|
}
|
||||||
@ -272,8 +276,13 @@
|
|||||||
return this.$accessor.settings.autoplay
|
return this.$accessor.settings.autoplay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// server-side lock
|
||||||
|
get controlLocked() {
|
||||||
|
return 'control' in this.$accessor.locked && this.$accessor.locked['control'] && !this.$accessor.user.admin
|
||||||
|
}
|
||||||
|
|
||||||
get locked() {
|
get locked() {
|
||||||
return this.$accessor.remote.locked
|
return this.$accessor.remote.locked || (this.controlLocked && (!this.hosting || this.implicitHosting))
|
||||||
}
|
}
|
||||||
|
|
||||||
get scroll() {
|
get scroll() {
|
||||||
|
@ -49,6 +49,8 @@ export const controls = {
|
|||||||
request: 'Request Controls',
|
request: 'Request Controls',
|
||||||
lock: 'Lock Controls',
|
lock: 'Lock Controls',
|
||||||
unlock: 'Unlock Controls',
|
unlock: 'Unlock Controls',
|
||||||
|
has: 'You have control',
|
||||||
|
hasnot: 'You do not have control',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
|
@ -51,6 +51,9 @@ export const controls = {
|
|||||||
request: 'Controles solicitados',
|
request: 'Controles solicitados',
|
||||||
lock: 'Controles bloqueados',
|
lock: 'Controles bloqueados',
|
||||||
unlock: 'Controles desbloqueados',
|
unlock: 'Controles desbloqueados',
|
||||||
|
// TODO
|
||||||
|
//has: 'You have control',
|
||||||
|
//hasnot: 'You do not have control',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
|
@ -46,6 +46,16 @@ export const context = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const controls = {
|
||||||
|
release: 'Relacher le contrôle',
|
||||||
|
request: 'Demander le contrôle',
|
||||||
|
lock: 'Vérouiller le contrôle',
|
||||||
|
unlock: 'Débloquer le contrôle',
|
||||||
|
// TODO
|
||||||
|
// has: 'You have control',
|
||||||
|
// hasnot: 'You do not have control',
|
||||||
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
// TODO
|
// TODO
|
||||||
//control: {
|
//control: {
|
||||||
@ -57,20 +67,13 @@ export const locks = {
|
|||||||
// notif_unlocked: 'unlocked controls for users',
|
// notif_unlocked: 'unlocked controls for users',
|
||||||
//},
|
//},
|
||||||
login: {
|
login: {
|
||||||
release: 'Relacher le contrôle',
|
|
||||||
request: 'Demander le contrôle',
|
|
||||||
lock: 'Vérouiller le contrôle',
|
|
||||||
unlock: 'Débloquer le contrôle',
|
|
||||||
notif_locked: 'a vérouillé la salle',
|
|
||||||
notif_unlocked: 'a dévérouillé la salle',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const room = {
|
|
||||||
lock: 'Vérouiller la salle (pour les utilisateurs)',
|
lock: 'Vérouiller la salle (pour les utilisateurs)',
|
||||||
unlock: 'Dévérouiller la salle (pour les utilisateurs)',
|
unlock: 'Dévérouiller la salle (pour les utilisateurs)',
|
||||||
locked: 'Salle vérouillée (pour les utilisateurs)',
|
locked: 'Salle vérouillée (pour les utilisateurs)',
|
||||||
unlocked: 'Salle dévérouillée (pour les utilisateurs)',
|
unlocked: 'Salle dévérouillée (pour les utilisateurs)',
|
||||||
|
notif_locked: 'a vérouillé la salle',
|
||||||
|
notif_unlocked: 'a dévérouillé la salle',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const setting = {
|
export const setting = {
|
||||||
|
@ -51,6 +51,9 @@ export const controls = {
|
|||||||
request: 'Forespør kontroll',
|
request: 'Forespør kontroll',
|
||||||
lock: 'Lås kontrollen',
|
lock: 'Lås kontrollen',
|
||||||
unlock: 'Lås opp kontrollen',
|
unlock: 'Lås opp kontrollen',
|
||||||
|
// TODO
|
||||||
|
//has: 'You have control',
|
||||||
|
//hasnot: 'You do not have control',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
|
@ -51,6 +51,9 @@ export const controls = {
|
|||||||
request: 'Požiadať o ovládanie',
|
request: 'Požiadať o ovládanie',
|
||||||
lock: 'Zamknúť ovládanie',
|
lock: 'Zamknúť ovládanie',
|
||||||
unlock: 'Odomknúť ovládanie',
|
unlock: 'Odomknúť ovládanie',
|
||||||
|
// TODO
|
||||||
|
//has: 'You have control',
|
||||||
|
//hasnot: 'You do not have control',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
|
@ -51,6 +51,9 @@ export const controls = {
|
|||||||
request: 'Fråga om kontroll',
|
request: 'Fråga om kontroll',
|
||||||
lock: 'Lås kontrollen',
|
lock: 'Lås kontrollen',
|
||||||
unlock: 'Lås upp kontrollen',
|
unlock: 'Lås upp kontrollen',
|
||||||
|
// TODO
|
||||||
|
//has: 'You have control',
|
||||||
|
//hasnot: 'You do not have control',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const locks = {
|
export const locks = {
|
||||||
|
@ -18,13 +18,13 @@ export const state = () => ({
|
|||||||
|
|
||||||
export const getters = getterTree(state, {
|
export const getters = getterTree(state, {
|
||||||
hosting: (state, getters, root) => {
|
hosting: (state, getters, root) => {
|
||||||
return root.user.id === state.id
|
return root.user.id === state.id || state.implicitHosting
|
||||||
},
|
},
|
||||||
hosted: (state, getters, root) => {
|
hosted: (state, getters, root) => {
|
||||||
return state.id !== ''
|
return state.id !== '' || state.implicitHosting
|
||||||
},
|
},
|
||||||
host: (state, getters, root) => {
|
host: (state, getters, root) => {
|
||||||
return root.user.members[state.id] || null
|
return root.user.members[state.id] || (state.implicitHosting && root.user.id) || null
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -57,8 +57,6 @@ export const mutations = mutationTree(state, {
|
|||||||
state.id = ''
|
state.id = ''
|
||||||
state.clipboard = ''
|
state.clipboard = ''
|
||||||
state.locked = false
|
state.locked = false
|
||||||
state.implicitHosting = false
|
|
||||||
state.keyboardModifierState = -1
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
### New Features
|
### New Features
|
||||||
- Added `m1k1o/neko:microsoft-edge` tag.
|
- Added `m1k1o/neko:microsoft-edge` tag.
|
||||||
- Fixed clipboard sync in chromium based browsers.
|
- Fixed clipboard sync in chromium based browsers.
|
||||||
|
- Added support for implicit control (using `NEKO_IMPLICITCONTROL=1`). That means, users do not need to request control prior usage.
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Automatic WebRTC SDP negotiation using onnegotiationneeded handlers. This allows adding/removing track on demand in a session.
|
- Automatic WebRTC SDP negotiation using onnegotiationneeded handlers. This allows adding/removing track on demand in a session.
|
||||||
|
@ -29,6 +29,8 @@ type SessionManager struct {
|
|||||||
remote types.RemoteManager
|
remote types.RemoteManager
|
||||||
members map[string]*Session
|
members map[string]*Session
|
||||||
emmiter events.EventEmmiter
|
emmiter events.EventEmmiter
|
||||||
|
// TODO: Handle locks in sessions as flags.
|
||||||
|
controlLocked bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *SessionManager) New(id string, admin bool, socket types.WebSocket) types.Session {
|
func (manager *SessionManager) New(id string, admin bool, socket types.WebSocket) types.Session {
|
||||||
@ -104,6 +106,16 @@ func (manager *SessionManager) Get(id string) (types.Session, bool) {
|
|||||||
return session, ok
|
return session, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Handle locks in sessions as flags.
|
||||||
|
func (manager *SessionManager) SetControlLocked(locked bool) {
|
||||||
|
manager.controlLocked = locked
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *SessionManager) CanControl(id string) bool {
|
||||||
|
session, ok := manager.Get(id)
|
||||||
|
return ok && (!manager.controlLocked || session.Admin())
|
||||||
|
}
|
||||||
|
|
||||||
func (manager *SessionManager) Admins() []*types.Member {
|
func (manager *SessionManager) Admins() []*types.Member {
|
||||||
manager.mu.Lock()
|
manager.mu.Lock()
|
||||||
defer manager.mu.Unlock()
|
defer manager.mu.Unlock()
|
||||||
|
@ -22,6 +22,8 @@ type WebRTC struct {
|
|||||||
NAT1To1IPs []string
|
NAT1To1IPs []string
|
||||||
TCPMUX int
|
TCPMUX int
|
||||||
UDPMUX int
|
UDPMUX int
|
||||||
|
|
||||||
|
ImplicitControl bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (WebRTC) Init(cmd *cobra.Command) error {
|
func (WebRTC) Init(cmd *cobra.Command) error {
|
||||||
@ -65,6 +67,12 @@ func (WebRTC) Init(cmd *cobra.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should be moved to session config.
|
||||||
|
cmd.PersistentFlags().Bool("implicitcontrol", false, "if enabled members can gain control implicitly")
|
||||||
|
if err := viper.BindPFlag("implicitcontrol", cmd.PersistentFlags().Lookup("implicitcontrol")); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,4 +128,7 @@ func (s *WebRTC) Set() {
|
|||||||
s.EphemeralMin = min
|
s.EphemeralMin = min
|
||||||
s.EphemeralMax = max
|
s.EphemeralMax = max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Should be moved to session config.
|
||||||
|
s.ImplicitControl = viper.GetBool("implicitcontrol")
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ type SessionManager interface {
|
|||||||
ClearHost()
|
ClearHost()
|
||||||
Has(id string) bool
|
Has(id string) bool
|
||||||
Get(id string) (Session, bool)
|
Get(id string) (Session, bool)
|
||||||
|
SetControlLocked(locked bool)
|
||||||
|
CanControl(id string) bool
|
||||||
Members() []*Member
|
Members() []*Member
|
||||||
Admins() []*Member
|
Admins() []*Member
|
||||||
Destroy(id string)
|
Destroy(id string)
|
||||||
|
@ -13,6 +13,7 @@ type WebRTCManager interface {
|
|||||||
CreatePeer(id string, session Session) (Peer, error)
|
CreatePeer(id string, session Session) (Peer, error)
|
||||||
ICELite() bool
|
ICELite() bool
|
||||||
ICEServers() []webrtc.ICEServer
|
ICEServers() []webrtc.ICEServer
|
||||||
|
ImplicitControl() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Peer interface {
|
type Peer interface {
|
||||||
|
@ -39,7 +39,7 @@ type PayloadKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) error {
|
func (manager *WebRTCManager) handle(id string, msg webrtc.DataChannelMessage) error {
|
||||||
if !manager.sessions.IsHost(id) {
|
if (!manager.config.ImplicitControl && !manager.sessions.IsHost(id)) || (manager.config.ImplicitControl && !manager.sessions.CanControl(id)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +301,10 @@ func (manager *WebRTCManager) ICEServers() []webrtc.ICEServer {
|
|||||||
return manager.config.ICEServers
|
return manager.config.ICEServers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (manager *WebRTCManager) ImplicitControl() bool {
|
||||||
|
return manager.config.ImplicitControl
|
||||||
|
}
|
||||||
|
|
||||||
func (manager *WebRTCManager) createTrack(codecName string) (*webrtc.TrackLocalStaticSample, webrtc.RTPCodecParameters, error) {
|
func (manager *WebRTCManager) createTrack(codecName string) (*webrtc.TrackLocalStaticSample, webrtc.RTPCodecParameters, error) {
|
||||||
var codec webrtc.RTPCodecParameters
|
var codec webrtc.RTPCodecParameters
|
||||||
|
|
||||||
|
@ -25,6 +25,11 @@ func (h *MessageHandler) adminLock(id string, session types.Session, payload *me
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Handle locks in sessions as flags.
|
||||||
|
if payload.Resource == "control" {
|
||||||
|
h.sessions.SetControlLocked(true)
|
||||||
|
}
|
||||||
|
|
||||||
h.locked[payload.Resource] = id
|
h.locked[payload.Resource] = id
|
||||||
|
|
||||||
if err := h.sessions.Broadcast(
|
if err := h.sessions.Broadcast(
|
||||||
@ -52,6 +57,11 @@ func (h *MessageHandler) adminUnlock(id string, session types.Session, payload *
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Handle locks in sessions as flags.
|
||||||
|
if payload.Resource == "control" {
|
||||||
|
h.sessions.SetControlLocked(false)
|
||||||
|
}
|
||||||
|
|
||||||
delete(h.locked, payload.Resource)
|
delete(h.locked, payload.Resource)
|
||||||
|
|
||||||
if err := h.sessions.Broadcast(
|
if err := h.sessions.Broadcast(
|
||||||
|
@ -125,9 +125,9 @@ func (h *MessageHandler) controlGive(id string, session types.Session, payload *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) controlClipboard(id string, session types.Session, payload *message.Clipboard) error {
|
func (h *MessageHandler) controlClipboard(id string, session types.Session, payload *message.Clipboard) error {
|
||||||
// check if session is host
|
// check if session can access clipboard
|
||||||
if !h.sessions.IsHost(id) {
|
if (!h.webrtc.ImplicitControl() && !h.sessions.IsHost(id)) || (h.webrtc.ImplicitControl() && !h.sessions.CanControl(id)) {
|
||||||
h.logger.Debug().Str("id", id).Msg("is not the host")
|
h.logger.Debug().Str("id", id).Msg("cannot access clipboard")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,9 +136,9 @@ func (h *MessageHandler) controlClipboard(id string, session types.Session, payl
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *MessageHandler) controlKeyboard(id string, session types.Session, payload *message.Keyboard) error {
|
func (h *MessageHandler) controlKeyboard(id string, session types.Session, payload *message.Keyboard) error {
|
||||||
// check if session is host
|
// check if session can control keyboard
|
||||||
if !h.sessions.IsHost(id) {
|
if (!h.webrtc.ImplicitControl() && !h.sessions.IsHost(id)) || (h.webrtc.ImplicitControl() && !h.sessions.CanControl(id)) {
|
||||||
h.logger.Debug().Str("id", id).Msg("is not the host")
|
h.logger.Debug().Str("id", id).Msg("cannot control keyboard")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ func (h *MessageHandler) SessionCreated(id string, session types.Session) error
|
|||||||
// send initialization information
|
// send initialization information
|
||||||
if err := session.Send(message.SystemInit{
|
if err := session.Send(message.SystemInit{
|
||||||
Event: event.SYSTEM_INIT,
|
Event: event.SYSTEM_INIT,
|
||||||
ImplicitHosting: true,
|
ImplicitHosting: h.webrtc.ImplicitControl(),
|
||||||
Locks: h.locked,
|
Locks: h.locked,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.SYSTEM_INIT)
|
h.logger.Warn().Str("id", id).Err(err).Msgf("sending event %s has failed", event.SYSTEM_INIT)
|
||||||
|
@ -105,6 +105,7 @@ func (ws *WebSocketHandler) Start() {
|
|||||||
sess, ok := ws.handler.locked["control"]
|
sess, ok := ws.handler.locked["control"]
|
||||||
if ok && ws.conf.ControlProtection && sess == CONTROL_PROTECTION_SESSION && len(ws.sessions.Admins()) > 0 {
|
if ok && ws.conf.ControlProtection && sess == CONTROL_PROTECTION_SESSION && len(ws.sessions.Admins()) > 0 {
|
||||||
delete(ws.handler.locked, "control")
|
delete(ws.handler.locked, "control")
|
||||||
|
ws.sessions.SetControlLocked(false) // TODO: Handle locks in sessions as flags.
|
||||||
ws.logger.Info().Msgf("control unlocked on behalf of control protection")
|
ws.logger.Info().Msgf("control unlocked on behalf of control protection")
|
||||||
|
|
||||||
if err := ws.sessions.Broadcast(
|
if err := ws.sessions.Broadcast(
|
||||||
@ -140,6 +141,7 @@ func (ws *WebSocketHandler) Start() {
|
|||||||
_, ok := ws.handler.locked["control"]
|
_, ok := ws.handler.locked["control"]
|
||||||
if !ok && ws.conf.ControlProtection && adminCount == 0 {
|
if !ok && ws.conf.ControlProtection && adminCount == 0 {
|
||||||
ws.handler.locked["control"] = CONTROL_PROTECTION_SESSION
|
ws.handler.locked["control"] = CONTROL_PROTECTION_SESSION
|
||||||
|
ws.sessions.SetControlLocked(true) // TODO: Handle locks in sessions as flags.
|
||||||
ws.logger.Info().Msgf("control locked and released on behalf of control protection")
|
ws.logger.Info().Msgf("control locked and released on behalf of control protection")
|
||||||
ws.handler.adminRelease(id, session)
|
ws.handler.adminRelease(id, session)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user