mchess-server/connection/type.go

115 lines
2.2 KiB
Go

package connection
import (
"context"
"log"
"sync"
gorillaws "github.com/gorilla/websocket"
)
type Connection struct {
ws *gorillaws.Conn
wsConnectionEstablished chan bool
wsWriteLock sync.Mutex
ctx context.Context
buffer MessageBuffer
disconnectCallback func()
}
func NewConnection(options ...func(*Connection)) *Connection {
connection := Connection{
buffer: *newMessageBuffer(100),
wsConnectionEstablished: make(chan bool),
}
for _, option := range options {
option(&connection)
}
return &connection
}
func WithWebsocket(ws *gorillaws.Conn) func(*Connection) {
return func(c *Connection) {
c.ws = ws
}
}
func WithContext(ctx context.Context) func(*Connection) {
return func(c *Connection) {
c.ctx = ctx
}
}
func WithDisconnectCallback(cb func()) func(*Connection) {
return func(c *Connection) {
if cb != nil {
c.disconnectCallback = cb
}
}
}
func (conn *Connection) SetDisconnectCallback(cb func()) {
conn.disconnectCallback = cb
}
func (conn *Connection) HasWebsocketConnection() bool {
return conn.ws != nil
}
func (conn *Connection) SetWebsocketConnection(ws *gorillaws.Conn) {
if ws == nil {
return
}
conn.ws = ws
select {
case conn.wsConnectionEstablished <- true:
default:
}
go func() {
for {
_, msg, err := conn.ws.ReadMessage()
if err != nil {
log.Println("while reading from websocket: %w", err)
if conn.disconnectCallback != nil {
conn.disconnectCallback()
}
return
}
conn.buffer.Insert(string(msg))
}
}()
}
func (conn *Connection) Write(msg []byte) error {
conn.wsWriteLock.Lock()
defer conn.wsWriteLock.Unlock()
if conn.ws == nil { //if ws is not yet set, we wait for it
<-conn.wsConnectionEstablished
}
log.Printf("Writing message: %s", string(msg))
return conn.ws.WriteMessage(gorillaws.TextMessage, msg)
}
func (conn *Connection) Read() ([]byte, error) {
msg, err := conn.buffer.Get()
if err != nil {
conn.ws = nil
return nil, err // TODO: Tell game-handler that connection was lost
}
return []byte(msg), err
}
func (conn *Connection) Close(msg string) {
conn.ws.WriteMessage(gorillaws.TextMessage, []byte(msg))
conn.ws.Close()
conn.ws = nil
}