2023-11-20 00:25:27 +00:00
|
|
|
package connection
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"log"
|
|
|
|
|
|
|
|
"nhooyr.io/websocket"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Connection struct {
|
|
|
|
ws *websocket.Conn
|
|
|
|
wsConnectionEstablished chan bool
|
|
|
|
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 *websocket.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 *websocket.Conn) {
|
|
|
|
if ws == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
conn.ws = ws
|
|
|
|
|
|
|
|
select {
|
|
|
|
case conn.wsConnectionEstablished <- true:
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
_, msg, err := conn.ws.Read(conn.ctx)
|
|
|
|
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 {
|
|
|
|
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.Write(conn.ctx, websocket.MessageText, msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (conn *Connection) Read() ([]byte, error) {
|
|
|
|
msg, err := conn.buffer.Get()
|
|
|
|
if err != nil {
|
|
|
|
conn.ws = nil
|
2024-01-17 16:38:06 +00:00
|
|
|
return nil, err // TODO: Tell game-handler that connection was lost
|
2023-11-20 00:25:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return []byte(msg), err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (conn *Connection) Close(msg string) {
|
|
|
|
conn.ws.Close(websocket.StatusCode(400), msg)
|
|
|
|
conn.ws = nil
|
|
|
|
}
|