mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45:58 +01:00
Fix locking in group.go.
Also export some fields as thread-safe methods.
This commit is contained in:
parent
938d231b30
commit
7126394e65
3 changed files with 61 additions and 29 deletions
62
group.go
62
group.go
|
@ -13,7 +13,6 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/pion/webrtc/v3"
|
||||
|
@ -32,15 +31,46 @@ const (
|
|||
|
||||
type group struct {
|
||||
name string
|
||||
dead bool
|
||||
description *groupDescription
|
||||
locked uint32
|
||||
|
||||
mu sync.Mutex
|
||||
description *groupDescription
|
||||
// indicates that the group no longer exists, but it still has clients
|
||||
dead bool
|
||||
locked bool
|
||||
clients map[string]client
|
||||
history []chatHistoryEntry
|
||||
}
|
||||
|
||||
func (g *group) Locked() bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.locked
|
||||
}
|
||||
|
||||
func (g *group) SetLocked(locked bool) {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
g.locked = locked
|
||||
}
|
||||
|
||||
func (g *group) Public() bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.description.Public
|
||||
}
|
||||
|
||||
func (g *group) Redirect() string {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.description.Redirect
|
||||
}
|
||||
|
||||
func (g *group) AllowRecording() bool {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
return g.description.AllowRecording
|
||||
}
|
||||
|
||||
var groups struct {
|
||||
mu sync.Mutex
|
||||
groups map[string]*group
|
||||
|
@ -94,9 +124,19 @@ func addGroup(name string, desc *groupDescription) (*group, error) {
|
|||
clients: make(map[string]client),
|
||||
}
|
||||
groups.groups[name] = g
|
||||
} else if desc != nil {
|
||||
return g, nil
|
||||
}
|
||||
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
if desc != nil {
|
||||
g.description = desc
|
||||
} else if g.dead || time.Since(g.description.loadTime) > 5*time.Second {
|
||||
g.dead = false
|
||||
return g, nil
|
||||
}
|
||||
|
||||
if g.dead || time.Since(g.description.loadTime) > 5*time.Second {
|
||||
changed, err := descriptionChanged(name, g.description)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
|
@ -176,6 +216,9 @@ func addClient(name string, c client) (*group, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
perms, err := getPermission(g.description, c.Credentials())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -183,13 +226,10 @@ func addClient(name string, c client) (*group, error) {
|
|||
|
||||
c.SetPermissions(perms)
|
||||
|
||||
if !perms.Op && atomic.LoadUint32(&g.locked) != 0 {
|
||||
if !perms.Op && g.locked {
|
||||
return nil, userError("group is locked")
|
||||
}
|
||||
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
if !perms.Op && g.description.MaxClients > 0 {
|
||||
if len(g.clients) >= g.description.MaxClients {
|
||||
return nil, userError("too many users")
|
||||
|
@ -424,7 +464,7 @@ type publicGroup struct {
|
|||
func getPublicGroups() []publicGroup {
|
||||
gs := make([]publicGroup, 0)
|
||||
rangeGroups(func(g *group) bool {
|
||||
if g.description.Public {
|
||||
if g.Public() {
|
||||
gs = append(gs, publicGroup{
|
||||
Name: g.name,
|
||||
ClientCount: len(g.clients),
|
||||
|
|
18
webclient.go
18
webclient.go
|
@ -12,7 +12,6 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"sfu/estimator"
|
||||
|
@ -713,10 +712,10 @@ func startClient(conn *websocket.Conn) (err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
if g.description.Redirect != "" {
|
||||
if redirect := g.Redirect(); redirect != "" {
|
||||
// We normally redirect at the HTTP level, but the group
|
||||
// description could have been edited in the meantime.
|
||||
err = userError("group is now at " + g.description.Redirect)
|
||||
err = userError("group is now at " + redirect)
|
||||
return
|
||||
}
|
||||
c.group = g
|
||||
|
@ -940,10 +939,7 @@ func failConnection(c *webClient, id string, message string) error {
|
|||
}
|
||||
|
||||
func setPermissions(g *group, id string, perm string) error {
|
||||
g.mu.Lock()
|
||||
defer g.mu.Unlock()
|
||||
|
||||
client := g.getClientUnlocked(id)
|
||||
client := g.getClient(id)
|
||||
if client == nil {
|
||||
return userError("no such user")
|
||||
}
|
||||
|
@ -956,7 +952,7 @@ func setPermissions(g *group, id string, perm string) error {
|
|||
switch perm {
|
||||
case "op":
|
||||
c.permissions.Op = true
|
||||
if g.description.AllowRecording {
|
||||
if g.AllowRecording() {
|
||||
c.permissions.Record = true
|
||||
}
|
||||
case "unop":
|
||||
|
@ -1071,11 +1067,7 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
|||
if !c.permissions.Op {
|
||||
return c.error(userError("not authorised"))
|
||||
}
|
||||
var locked uint32
|
||||
if m.Kind == "lock" {
|
||||
locked = 1
|
||||
}
|
||||
atomic.StoreUint32(&c.group.locked, locked)
|
||||
c.group.SetLocked(m.Kind == "lock")
|
||||
case "record":
|
||||
if !c.permissions.Record {
|
||||
return c.error(userError("not authorised"))
|
||||
|
|
|
@ -151,8 +151,8 @@ func groupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if g.description.Redirect != "" {
|
||||
http.Redirect(w, r, g.description.Redirect,
|
||||
if redirect := g.Redirect(); redirect != "" {
|
||||
http.Redirect(w, r, redirect,
|
||||
http.StatusPermanentRedirect)
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue