func tabHandle(gui *gocui.Gui, v *gocui.View) error {
sids := make([]int, 0, len(Streams)+1)
sids = append(sids, -1)
+ StreamsM.RLock()
for sid := range Streams {
sids = append(sids, int(sid))
}
+ StreamsM.RUnlock()
sort.Ints(sids)
if CurrentView+1 >= len(sids) {
CurrentView = 0
}
prevY += 3
sids := make([]int, 0, len(Streams))
+ StreamsM.RLock()
for sid := range Streams {
sids = append(sids, int(sid))
}
+ StreamsM.RUnlock()
sort.Ints(sids)
for _, sid := range sids {
stream := Streams[byte(sid)]
"os/exec"
"strconv"
"strings"
+ "sync"
"time"
"github.com/dchest/siphash"
var (
Streams = map[byte]*Stream{}
+ StreamsM sync.RWMutex
Finish = make(chan struct{})
OurStats = &Stats{dead: make(chan struct{})}
Name = flag.String("name", "test", "username")
log.Fatalln("cookie acceptance failed:", string(args[1]))
case vors.CmdSID:
sid = args[1][0]
+ StreamsM.Lock()
Streams[sid] = &Stream{name: *Name, stats: OurStats}
+ StreamsM.Unlock()
default:
log.Fatalln("unexpected post-cookie cmd:", cmd)
}
}
}()
go statsDrawer(stream)
+ StreamsM.Lock()
Streams[sid] = stream
+ StreamsM.Unlock()
case vors.CmdDel:
sid := args[1][0]
s := Streams[sid]
continue
}
log.Println("del", s.name, "sid:", sid)
+ StreamsM.Lock()
delete(Streams, sid)
+ StreamsM.Unlock()
close(s.in)
close(s.stats.dead)
case vors.CmdMuted:
alive: make(chan struct{}),
}
Rooms[roomName] = room
+ RoomsM.Unlock()
go func() {
if *NoGUI {
return
}
}
}()
+ } else {
+ RoomsM.Unlock()
}
- RoomsM.Unlock()
if room.key != key {
logger.Error("wrong password")
buf, _, _, err = hs.WriteMessage(nil, vors.ArgsEncode(
}
peer.room = room
+ room.peersM.RLock()
for _, p := range room.peers {
if p.name != peer.name {
continue
if err != nil {
log.Fatal(err)
}
+ room.peersM.RUnlock()
nsConn.Tx(buf)
return
}
+ room.peersM.RUnlock()
{
var i byte
}
}
logger = logger.With("sid", peer.sid)
+ room.peersM.Lock()
room.peers[peer.sid] = peer
+ room.peersM.Unlock()
logger.Info("logged in")
defer func() {
logger.Info("removing")
PeersM.Lock()
delete(Peers, peer.sid)
+ room.peersM.Lock()
delete(room.peers, peer.sid)
+ room.peersM.Unlock()
PeersM.Unlock()
s := vors.ArgsEncode([]byte(vors.CmdDel), []byte{peer.sid})
+ room.peersM.RLock()
for _, p := range room.peers {
- go func(tx chan []byte) { tx <- s }(p.tx)
+ p.tx <- s
}
+ room.peersM.RUnlock()
}()
{
go peer.Rx()
peer.tx <- vors.ArgsEncode([]byte(vors.CmdSID), []byte{peer.sid})
+ room.peersM.RLock()
for _, p := range room.peers {
if p.sid == peer.sid {
continue
peer.tx <- vors.ArgsEncode(
[]byte(vors.CmdAdd), []byte{p.sid}, []byte(p.name), p.key)
}
+ room.peersM.RUnlock()
{
xof, err := blake2s.NewXOF(chacha20.KeySize+16, nil)
{
s := vors.ArgsEncode(
[]byte(vors.CmdAdd), []byte{peer.sid}, []byte(peer.name), peer.key)
+ room.peersM.RLock()
for _, p := range room.peers {
if p.sid != peer.sid {
p.tx <- s
}
}
+ room.peersM.RUnlock()
}
seen := time.Now()
case vors.CmdMuted:
peer.muted = true
s := vors.ArgsEncode([]byte(vors.CmdMuted), []byte{peer.sid})
+ room.peersM.RLock()
for _, p := range room.peers {
- if p.sid == peer.sid {
- continue
+ if p.sid != peer.sid {
+ p.tx <- s
}
- go func(tx chan []byte) { tx <- s }(p.tx)
}
+ room.peersM.RUnlock()
case vors.CmdUnmuted:
peer.muted = false
s := vors.ArgsEncode([]byte(vors.CmdUnmuted), []byte{peer.sid})
+ room.peersM.RLock()
for _, p := range room.peers {
- if p.sid == peer.sid {
- continue
+ if p.sid != peer.sid {
+ p.tx <- s
}
- go func(tx chan []byte) { tx <- s }(p.tx)
}
+ room.peersM.RUnlock()
case vors.CmdChat:
if len(args) != 2 {
logger.Error("wrong len(args)")
continue
}
- msg := vors.ArgsEncode([]byte(vors.CmdChat), []byte{peer.sid}, args[1])
+ s := vors.ArgsEncode([]byte(vors.CmdChat), []byte{peer.sid}, args[1])
+ room.peersM.RLock()
for _, p := range room.peers {
- if p.sid == peer.sid {
- continue
+ if p.sid != peer.sid {
+ p.tx <- s
}
- go func(tx chan []byte) { tx <- msg }(p.tx)
}
+ room.peersM.RUnlock()
default:
logger.Error("unknown", "cmd", cmd)
}
}
peer.stats.last = time.Now()
+ peer.room.peersM.RLock()
for _, p := range peer.room.peers {
if p.sid == sid || p.addr == nil {
continue
slog.Warn("sendto", "peer", peer.name, "err", err)
}
}
+ peer.room.peersM.RUnlock()
}
}()
var (
Rooms = map[string]*Room{}
- RoomsM sync.Mutex
+ RoomsM sync.RWMutex
)
type Room struct {
- name string
- key string
- peers map[byte]*Peer
- alive chan struct{}
+ name string
+ key string
+ peers map[byte]*Peer
+ peersM sync.RWMutex
+ alive chan struct{}
}
func (room *Room) Stats(now time.Time) []string {
sids := make([]int, 0, len(room.peers))
+ room.peersM.RLock()
for sid := range room.peers {
sids = append(sids, int(sid))
}
+ room.peersM.RUnlock()
sort.Ints(sids)
lines := make([]string, 0, len(sids))
for _, sid := range sids {