Archived
2
0

add fields to stats.

This commit is contained in:
Miroslav Šedivý 2021-11-17 22:10:55 +01:00
parent 6d7486ab57
commit f59128cf72
5 changed files with 70 additions and 18 deletions

View File

@ -7,6 +7,7 @@
- Ability to set locks from config `NEKO_LOCKS=control login`.
- Added control protection - users can gain control only if at least one admin is in the room `NEKO_CONTROL_PROTECTION=true`.
- Emotes sending on mouse down holding.
- Include `banned`, `locked`, `server_started_at`, `last_admin_left_at`, `last_user_left_at`, `control_protection` data in stats.
### Misc
- ARM-based images not bound to Raspberry Pi only.

View File

@ -1,11 +1,23 @@
package types
import "net/http"
import (
"net/http"
"time"
)
type Stats struct {
Connections uint32 `json:"connections"`
Host string `json:"host"`
Members []*Member `json:"members"`
Banned map[string]string `json:"banned"` // IP -> session ID (that banned it)
Locked map[string]string `json:"locked"` // resource name -> session ID (that locked it)
ServerStartedAt time.Time `json:"server_started_at"`
LastAdminLeftAt *time.Time `json:"last_admin_left_at"`
LastUserLeftAt *time.Time `json:"last_user_left_at"`
ControlProtection bool `json:"control_protection"`
}
type WebSocket interface {

View File

@ -292,8 +292,7 @@ func (h *MessageHandler) adminBan(id string, session types.Session, payload *mes
}
h.logger.Debug().Str("address", remote).Msg("adding address to banned")
h.banned[address[0]] = true
h.banned[address[0]] = id
if err := target.Kick("banned"); err != nil {
return err

View File

@ -18,8 +18,8 @@ type MessageHandler struct {
webrtc types.WebRTCManager
remote types.RemoteManager
broadcast types.BroadcastManager
banned map[string]bool
locked map[string]string
banned map[string]string // IP -> session ID (that banned it)
locked map[string]string // resource name -> session ID (that locked it)
}
func (h *MessageHandler) Connected(admin bool, socket *WebSocket) (bool, string) {
@ -27,8 +27,8 @@ func (h *MessageHandler) Connected(admin bool, socket *WebSocket) (bool, string)
if address == "" {
h.logger.Debug().Msg("no remote address")
} else {
ok, banned := h.banned[address]
if ok && banned {
_, ok := h.banned[address]
if ok {
h.logger.Debug().Str("address", address).Msg("banned")
return false, "banned"
}

View File

@ -18,12 +18,20 @@ import (
"m1k1o/neko/internal/utils"
)
const CONTROL_PROTECTION_SESSION = "control_protection"
const CONTROL_PROTECTION_SESSION = "by_control_protection"
func New(sessions types.SessionManager, remote types.RemoteManager, broadcast types.BroadcastManager, webrtc types.WebRTCManager, conf *config.WebSocket) *WebSocketHandler {
logger := log.With().Str("module", "websocket").Logger()
locks := make(map[string]string)
// if control protection is enabled
if conf.ControlProtection {
locks["control"] = CONTROL_PROTECTION_SESSION
logger.Info().Msgf("control locked on behalf of control protection")
}
// apply default locks
for _, lock := range conf.Locks {
locks[lock] = "" // empty session ID
}
@ -32,12 +40,6 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
logger.Info().Msgf("locked resources: %+v", conf.Locks)
}
// if control protection is enabled
if conf.ControlProtection {
locks["control"] = CONTROL_PROTECTION_SESSION
logger.Info().Msgf("control locked on behalf of control protection")
}
return &WebSocketHandler{
logger: logger,
shutdown: make(chan interface{}),
@ -55,10 +57,10 @@ func New(sessions types.SessionManager, remote types.RemoteManager, broadcast ty
broadcast: broadcast,
sessions: sessions,
webrtc: webrtc,
banned: make(map[string]bool),
banned: make(map[string]string),
locked: locks,
},
conns: 0,
serverStartedAt: time.Now(),
}
}
@ -74,7 +76,12 @@ type WebSocketHandler struct {
remote types.RemoteManager
conf *config.WebSocket
handler *MessageHandler
// stats
conns uint32
serverStartedAt time.Time
lastAdminLeftAt *time.Time
lastUserLeftAt *time.Time
}
func (ws *WebSocketHandler) Start() {
@ -109,6 +116,13 @@ func (ws *WebSocketHandler) Start() {
ws.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_UNLOCK)
}
}
// remove outdated stats
if session.Admin() {
ws.lastAdminLeftAt = nil
} else {
ws.lastUserLeftAt = nil
}
})
ws.sessions.OnDestroy(func(id string, session types.Session) {
@ -118,8 +132,13 @@ func (ws *WebSocketHandler) Start() {
ws.logger.Debug().Str("id", id).Msg("session destroyed")
}
membersCount := len(ws.sessions.Members())
adminCount := len(ws.sessions.Admins())
// if control protection is enabled and no admin
if ws.conf.ControlProtection && len(ws.sessions.Admins()) == 0 {
// and room is not locked, lock
_, ok := ws.handler.locked["control"]
if !ok && ws.conf.ControlProtection && adminCount == 0 {
ws.handler.locked["control"] = CONTROL_PROTECTION_SESSION
ws.logger.Info().Msgf("control locked and released on behalf of control protection")
ws.handler.adminRelease(id, session)
@ -133,6 +152,18 @@ func (ws *WebSocketHandler) Start() {
ws.logger.Warn().Err(err).Msgf("broadcasting event %s has failed", event.ADMIN_LOCK)
}
}
// if this was the last admin
if session.Admin() && adminCount == 0 {
now := time.Now()
ws.lastAdminLeftAt = &now
}
// if this was the last user
if !session.Admin() && membersCount-adminCount == 0 {
now := time.Now()
ws.lastUserLeftAt = &now
}
})
ws.wg.Add(1)
@ -274,6 +305,15 @@ func (ws *WebSocketHandler) Stats() types.Stats {
Connections: atomic.LoadUint32(&ws.conns),
Host: host,
Members: ws.sessions.Members(),
Banned: ws.handler.banned,
Locked: ws.handler.locked,
ServerStartedAt: ws.serverStartedAt,
LastAdminLeftAt: ws.lastAdminLeftAt,
LastUserLeftAt: ws.lastUserLeftAt,
ControlProtection: ws.conf.ControlProtection,
}
}