Skip to content

Commit 5f011c5

Browse files
committed
server: make websocket writes thread-safe
1 parent ec3d477 commit 5f011c5

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

server/internal/net/session.go

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package net
22

33
import (
44
"fmt"
5+
"sync"
56

67
"github.com/Tch1b0/quick-poll/internal/logging"
78
"github.com/Tch1b0/quick-poll/internal/quiz"
@@ -13,6 +14,8 @@ type Session struct {
1314
Hosts []*Host
1415
Clients []*Client
1516
CurrentQuiz *quiz.Data
17+
18+
writeMutex sync.Mutex
1619
}
1720

1821
func (s *Session) AddClient(c *Client) {
@@ -23,7 +26,7 @@ func (s *Session) AddClient(c *Client) {
2326

2427
// if quiz already started, send it to the new client
2528
if s.CurrentQuiz != nil {
26-
c.Ws.WriteJSON(Action{
29+
s.Write(c.Ws, Action{
2730
Type: "quiz",
2831
Data: s.CurrentQuiz,
2932
})
@@ -60,7 +63,7 @@ func (s *Session) ClientListenLoop(c *Client) {
6063
func (s *Session) AddHost(h *Host) {
6164
s.Hosts = append(s.Hosts, h)
6265

63-
h.Ws.WriteJSON(Action{
66+
s.Write(h.Ws, Action{
6467
Type: "quiz",
6568
Data: s.CurrentQuiz,
6669
})
@@ -70,7 +73,7 @@ func (s *Session) AddHost(h *Host) {
7073
allClientInfos = append(allClientInfos, c.Info())
7174
}
7275

73-
h.Ws.WriteJSON(Action{
76+
s.Write(h.Ws, Action{
7477
Type: "info",
7578
Data: allClientInfos,
7679
})
@@ -97,20 +100,27 @@ func (s *Session) HostListenLoop(h *Host) {
97100
}
98101

99102
func (s *Session) processAction(a Action) error {
100-
if a.Type == "idle" {
101-
s.StartIdle()
102-
return nil
103-
} else if a.Type == "quiz" {
104-
quiz, err := quiz.DataFromPartialParsedData(a.Data)
105-
106-
if err != nil {
107-
return err
103+
switch a.Type {
104+
case "idle":
105+
{
106+
s.StartIdle()
107+
return nil
108108
}
109+
case "quiz":
110+
{
111+
quiz, err := quiz.DataFromPartialParsedData(a.Data)
109112

110-
s.StartQuiz(quiz)
111-
return nil
112-
} else if a.Type == "close" {
113-
s.Active = false
113+
if err != nil {
114+
return err
115+
}
116+
117+
s.StartQuiz(quiz)
118+
return nil
119+
}
120+
case "close":
121+
{
122+
s.Active = false
123+
}
114124
}
115125

116126
return fmt.Errorf("invalid action type \"%s\"", a.Type)
@@ -134,9 +144,9 @@ func (s *Session) StartQuiz(quiz quiz.Data) {
134144
s.sessionLog("quiz was started")
135145
}
136146

137-
func (s Session) SendClients(v any) {
147+
func (s *Session) SendClients(v any) {
138148
for _, c := range s.Clients {
139-
err := c.Ws.WriteJSON(v)
149+
err := s.Write(c.Ws, v)
140150

141151
// kick the client if the message fails, as the client is most likely not in the session anymore
142152
if err != nil {
@@ -148,9 +158,9 @@ func (s Session) SendClients(v any) {
148158
s.sessionLog("a message was sent to clients")
149159
}
150160

151-
func (s Session) SendHosts(v any) {
161+
func (s *Session) SendHosts(v any) {
152162
for _, h := range s.Hosts {
153-
err := h.Ws.WriteJSON(v)
163+
err := s.Write(h.Ws, v)
154164

155165
// kick the host if the message fails, as the host is most likely not in the session anymore
156166
if err != nil {
@@ -162,7 +172,7 @@ func (s Session) SendHosts(v any) {
162172
s.sessionLog("a message was sent to host")
163173
}
164174

165-
func (s Session) SendAll(v any) {
175+
func (s *Session) SendAll(v any) {
166176
s.SendClients(v)
167177
s.SendHosts(v)
168178

@@ -174,7 +184,7 @@ func (s Session) SendAll(v any) {
174184
}
175185
}
176186

177-
func (s Session) SendHostCurrentState() {
187+
func (s *Session) SendHostCurrentState() {
178188
s.SendHosts(Action{
179189
Type: "state",
180190
Data: map[string]any{
@@ -229,10 +239,17 @@ func (s *Session) EndSession() {
229239
s.sessionLog("session ended")
230240
}
231241

232-
func (s Session) sessionLog(msg string) {
242+
func (s *Session) sessionLog(msg string) {
233243
logging.GetLogger().Info(fmt.Sprintf("Session#%s", s.Id), msg)
234244
}
235245

246+
func (s *Session) Write(ws WebSocket, v any) error {
247+
s.writeMutex.Lock()
248+
err := ws.WriteJSON(v)
249+
s.writeMutex.Unlock()
250+
return err
251+
}
252+
236253
func NewSession(id string) *Session {
237254
return &Session{
238255
Id: id,

0 commit comments

Comments
 (0)