Replace old websocket library with gorilla's one #12
72
api/websocket/connection.go
Normal file
72
api/websocket/connection.go
Normal file
@ -0,0 +1,72 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"mchess_server/api"
|
||||
"net/http"
|
||||
|
||||
lobbies "mchess_server/lobby_registry"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
gorillaws "github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
var upgrader = gorillaws.Upgrader{
|
||||
CheckOrigin: func(r *http.Request) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
|
||||
func RegisterWebSocketConnection(c *gin.Context) {
|
||||
log.Println(c.Request)
|
||||
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
go waitForAndHandlePlayerID(c, conn)
|
||||
}
|
||||
|
||||
func waitForAndHandlePlayerID(ctx context.Context, conn *gorillaws.Conn) {
|
||||
msgType, msg, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
errorMessage := fmt.Sprintf("Reading from websocket connection did not work: %s", err)
|
||||
log.Println(errorMessage)
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("read from websocket endpoint: ", msgType, string(msg), err)
|
||||
|
||||
var info api.PlayerInfo
|
||||
err = json.Unmarshal(msg, &info)
|
||||
if err != nil {
|
||||
errorMessage := fmt.Sprintf("Unmarshaling message did not work: %s", err)
|
||||
log.Println(errorMessage)
|
||||
conn.WriteMessage(msgType, []byte(errorMessage))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(*info.LobbyID)
|
||||
if lobby == nil {
|
||||
conn.WriteMessage(msgType, []byte("lobby not found"))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
player, found := lobby.GetPlayerByUUID(*info.PlayerID)
|
||||
if !found {
|
||||
conn.WriteMessage(msgType, []byte("player not found"))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
if player.Conn.HasWebsocketConnection() {
|
||||
player.Conn.Close("closing existing connection")
|
||||
}
|
||||
lobby.Game.SetWebsocketConnectionFor(ctx, player, conn)
|
||||
log.Println("player after setting connection: ", player)
|
||||
}
|
@ -8,7 +8,7 @@ import (
|
||||
"mchess_server/types"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"nhooyr.io/websocket"
|
||||
gorillaws "github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
@ -211,6 +211,6 @@ func (game Game) broadcastGameEnd(reason GameEndedReason) error {
|
||||
func (game *Game) playerDisconnected(p *Player) {
|
||||
}
|
||||
|
||||
func (game *Game) SetWebsocketConnectionFor(ctx context.Context, p *Player, ws *websocket.Conn) {
|
||||
func (game *Game) SetWebsocketConnectionFor(ctx context.Context, p *Player, ws *gorillaws.Conn) {
|
||||
p.SetWebsocketConnectionAndSendBoardState(ctx, ws, game.board.PGN(), game.board.colorToMove)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"mchess_server/types"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"nhooyr.io/websocket"
|
||||
gorillaws "github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Player struct {
|
||||
@ -34,13 +34,13 @@ func (p Player) hasWebsocketConnection() bool {
|
||||
return p.Conn.HasWebsocketConnection()
|
||||
}
|
||||
|
||||
func (p *Player) SetWebsocketConnection(ctx context.Context, ws *websocket.Conn) {
|
||||
func (p *Player) SetWebsocketConnection(ctx context.Context, ws *gorillaws.Conn) {
|
||||
p.Conn.SetWebsocketConnection(ws)
|
||||
}
|
||||
|
||||
func (p *Player) SetWebsocketConnectionAndSendBoardState(
|
||||
ctx context.Context,
|
||||
ws *websocket.Conn,
|
||||
ws *gorillaws.Conn,
|
||||
boardPosition string,
|
||||
turnColor types.ChessColor,
|
||||
) {
|
||||
|
@ -3,13 +3,15 @@ package connection
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"nhooyr.io/websocket"
|
||||
gorillaws "github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Connection struct {
|
||||
ws *websocket.Conn
|
||||
ws *gorillaws.Conn
|
||||
wsConnectionEstablished chan bool
|
||||
wsWriteLock sync.Mutex
|
||||
ctx context.Context
|
||||
buffer MessageBuffer
|
||||
disconnectCallback func()
|
||||
@ -28,7 +30,7 @@ func NewConnection(options ...func(*Connection)) *Connection {
|
||||
return &connection
|
||||
}
|
||||
|
||||
func WithWebsocket(ws *websocket.Conn) func(*Connection) {
|
||||
func WithWebsocket(ws *gorillaws.Conn) func(*Connection) {
|
||||
return func(c *Connection) {
|
||||
c.ws = ws
|
||||
}
|
||||
@ -56,7 +58,7 @@ func (conn *Connection) HasWebsocketConnection() bool {
|
||||
return conn.ws != nil
|
||||
}
|
||||
|
||||
func (conn *Connection) SetWebsocketConnection(ws *websocket.Conn) {
|
||||
func (conn *Connection) SetWebsocketConnection(ws *gorillaws.Conn) {
|
||||
if ws == nil {
|
||||
return
|
||||
}
|
||||
@ -70,7 +72,7 @@ func (conn *Connection) SetWebsocketConnection(ws *websocket.Conn) {
|
||||
|
||||
go func() {
|
||||
for {
|
||||
_, msg, err := conn.ws.Read(conn.ctx)
|
||||
_, msg, err := conn.ws.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("while reading from websocket: %w", err)
|
||||
if conn.disconnectCallback != nil {
|
||||
@ -84,12 +86,15 @@ func (conn *Connection) SetWebsocketConnection(ws *websocket.Conn) {
|
||||
}
|
||||
|
||||
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.Write(conn.ctx, websocket.MessageText, msg)
|
||||
return conn.ws.WriteMessage(gorillaws.TextMessage, msg)
|
||||
}
|
||||
|
||||
func (conn *Connection) Read() ([]byte, error) {
|
||||
@ -103,6 +108,7 @@ func (conn *Connection) Read() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (conn *Connection) Close(msg string) {
|
||||
conn.ws.Close(websocket.StatusCode(400), msg)
|
||||
conn.ws.WriteMessage(gorillaws.TextMessage, []byte(msg))
|
||||
conn.ws.Close()
|
||||
conn.ws = nil
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -7,7 +7,6 @@ require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/samber/lo v1.39.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
nhooyr.io/websocket v1.8.11
|
||||
)
|
||||
|
||||
require (
|
||||
@ -22,6 +21,7 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -46,6 +46,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
|
58
main.go
58
main.go
@ -1,17 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"mchess_server/api"
|
||||
"mchess_server/handler"
|
||||
lobbies "mchess_server/lobby_registry"
|
||||
"mchess_server/api/handler"
|
||||
"mchess_server/api/websocket"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
var cert_path = "/etc/letsencrypt/live/chess.sw-gross.de/"
|
||||
@ -32,7 +27,7 @@ func main() {
|
||||
router.GET("/api/random", handler.RegisterForRandomGame)
|
||||
router.GET("/api/hostPrivate", handler.HostPrivateGameHandler)
|
||||
router.POST("/api/joinPrivate", handler.JoinPrivateGame)
|
||||
router.GET("/api/ws", registerWebSocketConnection)
|
||||
router.GET("/api/ws", websocket.RegisterWebSocketConnection)
|
||||
router.GET("/api/getLobbyForPassphrase/:phrase", handler.GetLobbyForPassphraseHandler)
|
||||
|
||||
if debugMode {
|
||||
@ -45,50 +40,3 @@ func main() {
|
||||
log.Fatal(router.RunTLS("chess.sw-gross.de:9999", cert_file, key_file))
|
||||
}
|
||||
}
|
||||
|
||||
func registerWebSocketConnection(c *gin.Context) {
|
||||
webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"chess.sw-gross.de", "localhost:*"}})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
go waitForAndHandlePlayerID(c, webSocketConn)
|
||||
}
|
||||
|
||||
func waitForAndHandlePlayerID(ctx context.Context, conn *websocket.Conn) {
|
||||
msgType, msg, err := conn.Read(ctx)
|
||||
if err != nil {
|
||||
errorMessage := fmt.Sprintf("Reading from websocket connection did not work: %s", err)
|
||||
log.Println(errorMessage)
|
||||
conn.Close(websocket.StatusCode(400), errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("read from websocket endpoint: ", msgType, string(msg), err)
|
||||
|
||||
var info api.PlayerInfo
|
||||
err = json.Unmarshal(msg, &info)
|
||||
if err != nil {
|
||||
errorMessage := fmt.Sprintf("Unmarshaling message did not work: %s", err)
|
||||
log.Println(errorMessage)
|
||||
conn.Close(websocket.StatusCode(400), errorMessage)
|
||||
return
|
||||
}
|
||||
|
||||
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(*info.LobbyID)
|
||||
if lobby == nil {
|
||||
conn.Close(websocket.StatusCode(400), "lobby not found")
|
||||
return
|
||||
}
|
||||
|
||||
player, found := lobby.GetPlayerByUUID(*info.PlayerID)
|
||||
if !found {
|
||||
conn.Close(websocket.StatusCode(400), "player not found")
|
||||
return
|
||||
}
|
||||
if player.Conn.HasWebsocketConnection() {
|
||||
player.Conn.Close("closing existing connection")
|
||||
}
|
||||
lobby.Game.SetWebsocketConnectionFor(ctx, player, conn)
|
||||
log.Println("player after setting connection: ", player)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user