1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
package connection
import (
"sync"
"github.com/fasthttp/websocket"
"github.com/spiral/errors"
"github.com/spiral/roadrunner/v2/plugins/logger"
)
// Connection represents wrapped and safe to use from the different threads websocket connection
type Connection struct {
sync.RWMutex
log logger.Logger
conn *websocket.Conn
}
func NewConnection(wsConn *websocket.Conn, log logger.Logger) *Connection {
return &Connection{
conn: wsConn,
log: log,
}
}
func (c *Connection) Write(data []byte) error {
c.Lock()
defer c.Unlock()
const op = errors.Op("websocket_write")
// handle a case when a goroutine tried to write into the closed connection
defer func() {
if r := recover(); r != nil {
c.log.Warn("panic handled, tried to write into the closed connection")
}
}()
err := c.conn.WriteMessage(websocket.TextMessage, data)
if err != nil {
return errors.E(op, err)
}
return nil
}
func (c *Connection) Read() (int, []byte, error) {
const op = errors.Op("websocket_read")
mt, data, err := c.conn.ReadMessage()
if err != nil {
return -1, nil, errors.E(op, err)
}
return mt, data, nil
}
func (c *Connection) Close() error {
c.Lock()
defer c.Unlock()
const op = errors.Op("websocket_close")
err := c.conn.Close()
if err != nil {
return errors.E(op, err)
}
return nil
}
|