summaryrefslogtreecommitdiff
path: root/plugins/websockets/connection/connection.go
blob: 04c29d83212a2710c5acd13b4051612c261d92d2 (plain)
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
}