From ae3e73f7110adb6824876205de876c551cfadeed Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 20 Nov 2023 01:25:27 +0100 Subject: [PATCH] Another step towards allowing reconnections 1. Implement thread-safe ringbuffer for websocket messages This implements a ringbuffer that is used to decouple the raw websocket connection from the messages that the game handler handles. 2. Change websocket handling With this commit, we stop waiting for the websocket connection to be established before the game starts. Now, the Connection type is responsible for waiting for the websocket connection before writing. Some bugs are still happening: 1. The rejoining client is not told the state of the board 2. Invalid moves are not handled by the client (not sure why though) 3. The still-connected client should be told, that the opponent disconnected. Then the client should show the passphrase again 3. Introduce method to send status of board and player 4. Reconnect works (kind of) With the right changes in the client, the reconnect works (but only for the first time). WARNING: At the moment, we will create a new player whenever connection wants to join a private game. This will also clear all the disconnect callbacks that we set in the player. --- api/move.go | 14 ++- chess/free_squares.go | 1 - chess/game.go | 80 +++++++----- chess/player.go | 104 +++++++++++----- chess/rook_test.go | 2 +- connection/message_buffer.go | 82 ++++++++++++ connection/message_buffer_test.go | 199 ++++++++++++++++++++++++++++++ connection/type.go | 108 ++++++++++++++++ go.mod | 2 - go.sum | 97 --------------- lobby_registry/lobby.go | 2 +- main.go | 15 ++- utils/passphrase.go | 2 +- 13 files changed, 533 insertions(+), 175 deletions(-) create mode 100644 connection/message_buffer.go create mode 100644 connection/message_buffer_test.go create mode 100644 connection/type.go diff --git a/api/move.go b/api/move.go index 8d18031..e42a743 100644 --- a/api/move.go +++ b/api/move.go @@ -6,16 +6,18 @@ import ( ) type WebsocketMessage struct { - Type MessageType `json:"messageType"` - Move *types.Move `json:"move,omitempty"` - Color *types.ChessColor `json:"color,omitempty"` - Reason *string `json:"reason,omitempty"` - Position *string `json:"position,omitempty"` + Type MessageType `json:"messageType"` + Move *types.Move `json:"move,omitempty"` + TurnColor *types.ChessColor `json:"turnColor,omitempty"` + PlayerColor *types.ChessColor `json:"playerColor,omitempty"` + Reason *string `json:"reason,omitempty"` + Position *string `json:"position,omitempty"` } type MessageType string const ( + BoardStateMessage MessageType = "boardState" MoveMessage MessageType = "move" InvalidMoveMessage MessageType = "invalidMove" ColorDetermined MessageType = "colorDetermined" @@ -36,7 +38,7 @@ func (m WebsocketMessage) IsValidMoveMessage() bool { } func GetColorDeterminedMessage(color types.ChessColor) ([]byte, error) { - return json.Marshal(WebsocketMessage{Type: ColorDetermined, Color: &color}) + return json.Marshal(WebsocketMessage{Type: ColorDetermined, PlayerColor: &color}) } func GetInvalidMoveMessage(move types.Move, reason string) ([]byte, error) { diff --git a/chess/free_squares.go b/chess/free_squares.go index 9d2b4b8..c654ce2 100644 --- a/chess/free_squares.go +++ b/chess/free_squares.go @@ -12,7 +12,6 @@ func (b *Board) GetNonBlockedRowAndColumn(fromSquare types.Coordinate) []types.C nonBlocked = append(nonBlocked, b.getNonBlockedConsecutive(squaresRight, fromSquare)...) nonBlocked = append(nonBlocked, b.getNonBlockedConsecutive(squaresAbove, fromSquare)...) nonBlocked = append(nonBlocked, b.getNonBlockedConsecutive(squaresBelow, fromSquare)...) - return nonBlocked } diff --git a/chess/game.go b/chess/game.go index 481c724..ae6f0c5 100644 --- a/chess/game.go +++ b/chess/game.go @@ -1,12 +1,15 @@ package chess import ( + "context" "log" + "math/rand" "mchess_server/api" "mchess_server/types" - "time" "github.com/google/uuid" + "github.com/samber/lo" + "nhooyr.io/websocket" ) type Game struct { @@ -15,10 +18,13 @@ type Game struct { players []*Player currentTurnPlayer *Player gameState int + isBeingHandled bool } const ( - PlayerToMove = iota + Init = iota + Prepare + PlayerToMove CheckMove CheckPlayerChange ) @@ -27,7 +33,7 @@ func NewGame() *Game { var game = Game{ id: uuid.New(), board: newBoard(), - gameState: PlayerToMove, + gameState: Init, } game.board.Init() @@ -42,17 +48,21 @@ func (game Game) GetPlayer1() *Player { return game.players[0] } +func (game Game) GetRandomPlayer() *Player { + index := rand.Int() % 2 + return game.players[index] +} + func (game Game) GetPlayer2() *Player { return game.players[1] } func (game *Game) prepare() { - game.currentTurnPlayer = game.GetPlayer1() + game.players[0].color = types.White + game.players[1].color = types.Black - ok := game.waitForWebsocketConnections() - if !ok { - return - } + game.players[0].SetDisconnectCallback(game.playerDisconnected) + game.players[1].SetDisconnectCallback(game.playerDisconnected) err := game.notifyPlayersAboutGameStart() if err != nil { @@ -60,18 +70,35 @@ func (game *Game) prepare() { } } +func (game *Game) StartHandling() { + if game.isBeingHandled { + return + } + + game.isBeingHandled = true + go game.Handle() +} + func (game *Game) Handle() { defer game.killGame() - game.prepare() + game.prepare() var receivedMove types.Move - var err error + var err error for { switch game.gameState { + case Init: + game.currentTurnPlayer = game.GetPlayer1() + game.gameState = Prepare + + case Prepare: + game.prepare() + game.gameState = PlayerToMove + case PlayerToMove: - log.Println("with player ", game.currentTurnPlayer, " to move") + log.Println("with ", game.currentTurnPlayer.GetPlayerColor(), " to move") receivedMove, err = game.currentTurnPlayer.ReadMove() if err != nil { log.Println("Error while reading message:", err) @@ -121,25 +148,6 @@ func (game *Game) killGame() { log.Println("Game should be killed") } -func (game *Game) waitForWebsocketConnections() bool { - timer := time.NewTimer(5 * time.Second) - numberOfConnections := 0 - waitingForPlayers := make(chan bool) - - go game.GetPlayer1().WaitForWebsocketConnection(waitingForPlayers) - go game.GetPlayer2().WaitForWebsocketConnection(waitingForPlayers) - - for numberOfConnections < 2 { - select { - case <-waitingForPlayers: - numberOfConnections++ - case <-timer.C: - return false - } - } - return true -} - func (game Game) notifyPlayersAboutGameStart() error { colorDeterminedPlayer1, err := api.GetColorDeterminedMessage(types.White) if err != nil { @@ -169,3 +177,15 @@ func (game Game) broadcastMove(move types.Move) error { } return nil } + +func (game *Game) playerDisconnected(p *Player) { + log.Println(string(p.color), " disconnected") + playerStillInGame := lo.Filter(game.players, func(player *Player, _ int) bool { + return player.color != p.color + }) + game.players = playerStillInGame +} + +func (game *Game) SetWebsocketConnectionFor(ctx context.Context, p *Player, ws *websocket.Conn) { + p.SetWebsocketConnectionAndSendBoardState(ctx, ws, game.board.PGN(), game.board.colorToMove) +} diff --git a/chess/player.go b/chess/player.go index 907f96a..13d5348 100644 --- a/chess/player.go +++ b/chess/player.go @@ -6,34 +6,85 @@ import ( "errors" "log" "mchess_server/api" + "mchess_server/connection" "mchess_server/types" - "time" "github.com/google/uuid" "nhooyr.io/websocket" ) type Player struct { - Uuid uuid.UUID - Conn *websocket.Conn - InGame bool - wsConnEstablished chan bool - context context.Context + Uuid uuid.UUID + Conn *connection.Connection + color types.ChessColor + disconnectCallback func(p *Player) } func NewPlayer(uuid uuid.UUID) *Player { - return &Player{ - Uuid: uuid, - Conn: nil, - InGame: false, - wsConnEstablished: make(chan bool), + player := &Player{ + Uuid: uuid, + Conn: connection.NewConnection( + connection.WithContext(context.Background())), } + + return player } -func (p *Player) SetConnection(ctx context.Context, conn *websocket.Conn) { - p.Conn = conn - p.context = ctx - p.wsConnEstablished <- true +func (p Player) hasWebsocketConnection() bool { + return p.Conn.HasWebsocketConnection() +} + +func (p *Player) SetWebsocketConnection(ctx context.Context, ws *websocket.Conn) { + p.Conn.SetWebsocketConnection(ws) +} + +func (p *Player) SetWebsocketConnectionAndSendBoardState( + ctx context.Context, + ws *websocket.Conn, + boardPosition string, + turnColor types.ChessColor, +) { + p.SetWebsocketConnection(ctx, ws) + p.SendBoardState(boardPosition, turnColor) +} + +func (p *Player) SetDisconnectCallback(cb func(*Player)) { + // Todo: Fucking complicated + p.Conn.SetDisconnectCallback(p.PlayerDisconnectedCallback) + p.disconnectCallback = cb +} + +func (p *Player) PlayerDisconnectedCallback() { + p.disconnectCallback(p) +} + +func (p *Player) IsInGame() bool { + return p.hasWebsocketConnection() +} + +func (p *Player) SendBoardState(boardPosition string, turnColor types.ChessColor) error { + var pColor = p.color + if p.color == "" { // we default to white if we do not know the color yet + pColor = types.White + } + + messageToSend, err := json.Marshal(api.WebsocketMessage{ + Type: api.BoardStateMessage, + TurnColor: &turnColor, + PlayerColor: &pColor, + Position: &boardPosition, + }) + if err != nil { + log.Println("Error while marshalling: ", err) + return err + } + + err = p.writeMessage(messageToSend) + if err != nil { + log.Println("Error during message writing:", err) + return err + } + return nil } func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) error { @@ -56,13 +107,11 @@ func (p *Player) SendMoveAndPosition(move types.Move, boardPosition string) erro } func (p *Player) writeMessage(msg []byte) error { - log.Printf("Writing message: %s to player %s", string(msg), p.Uuid.String()) - - return p.Conn.Write(p.context, websocket.MessageText, msg) + return p.Conn.Write(msg) } func (p *Player) ReadMove() (types.Move, error) { - _, receivedMessage, err := p.readMessage() + receivedMessage, err := p.readMessage() if err != nil { return types.Move{}, err } @@ -80,20 +129,13 @@ func (p *Player) ReadMove() (types.Move, error) { return *msg.Move, nil } -func (p *Player) readMessage() (websocket.MessageType, []byte, error) { - msgType, msg, err := p.Conn.Read(p.context) +func (p *Player) readMessage() ([]byte, error) { + msg, err := p.Conn.Read() log.Printf("Reading message: %s from player %s", string(msg), p.Uuid.String()) - return msgType, msg, err + return msg, err } -func (p *Player) WaitForWebsocketConnection(c chan bool) { - timer := time.NewTimer(5 * time.Second) - - select { - case <-p.wsConnEstablished: - c <- true - case <-timer.C: - return - } +func (p Player) GetPlayerColor() string { + return string(p.color) } diff --git a/chess/rook_test.go b/chess/rook_test.go index 0cf6766..7189a91 100644 --- a/chess/rook_test.go +++ b/chess/rook_test.go @@ -18,7 +18,7 @@ func Test_Rook_GetNonBlockedSquares(t *testing.T) { assert.Len(t, squares, 14) }) - t.Run("free row and column", func(t *testing.T) { + t.Run("blocked row and column", func(t *testing.T) { board := newBoard() rook := Rook{Color: types.Black} rookCoordinate := types.Coordinate{Col: 5, Row: 5} diff --git a/connection/message_buffer.go b/connection/message_buffer.go new file mode 100644 index 0000000..a2613ce --- /dev/null +++ b/connection/message_buffer.go @@ -0,0 +1,82 @@ +package connection + +import "sync" + +type MessageBuffer struct { + messages []message + getIndex int + insertIndex int + size int + newDataInserted chan bool + firstWriteHappened bool + cond *sync.Cond +} + +type message struct { + content string + new bool +} + +func newMessageBuffer(size int) *MessageBuffer { + cond := sync.NewCond(&sync.Mutex{}) + + return &MessageBuffer{ + messages: make([]message, size), + size: size, + getIndex: 0, + insertIndex: 0, + newDataInserted: make(chan bool), + firstWriteHappened: false, + cond: cond, + } +} + +func (b *MessageBuffer) Insert(msg string) { + b.cond.L.Lock() + defer b.cond.L.Unlock() + + oldMessage := b.messages[b.insertIndex] + b.messages[b.insertIndex] = message{content: msg, new: true} + + if b.firstWriteHappened && + b.insertIndex == b.getIndex && + oldMessage.new { // insertIndex caught up with getIndex + b.getIndex = b.incrementAndWrapIndex(b.getIndex) + } + + b.insertIndex = b.incrementAndWrapIndex(b.insertIndex) + + b.firstWriteHappened = true + b.cond.Broadcast() +} + +func (b *MessageBuffer) Get() (string, error) { + b.cond.L.Lock() + defer b.cond.L.Unlock() + + if !b.firstWriteHappened { + b.cond.Wait() + } + + var msg *message + for { + msg = &b.messages[b.getIndex] + if msg.new { + msg.new = false + break + } + b.cond.Wait() + } + b.getIndex = b.incrementAndWrapIndex(b.getIndex) + + return msg.content, nil +} + +func (b MessageBuffer) incrementAndWrapIndex(index int) int { + newIndex := index + 1 + if newIndex == b.size { + newIndex = 0 + } + + return newIndex +} diff --git a/connection/message_buffer_test.go b/connection/message_buffer_test.go new file mode 100644 index 0000000..0b97e64 --- /dev/null +++ b/connection/message_buffer_test.go @@ -0,0 +1,199 @@ +package connection + +import ( + "fmt" + "strconv" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +var ( + message1 = "message-1" + message2 = "message-2" + message3 = "message-3" + message4 = "message-4" + message5 = "message-5" + message6 = "message-6" + message7 = "message-7" +) + +func Test_MessageBuffer_Add(t *testing.T) { + buf := newMessageBuffer(3) + + t.Run("insert without wrapping", func(t *testing.T) { + buf.Insert("message-1") + assert.Equal(t, 1, buf.insertIndex) + + buf.Insert("message-2") + assert.Equal(t, 2, buf.insertIndex) + + buf.Insert("message-3") + assert.Equal( + t, + []message{ + {content: message1, new: true}, + {content: message2, new: true}, + {content: message3, new: true}, + }, + buf.messages, + ) + }) + + t.Run("insert that causes wrapping", func(t *testing.T) { + buf.Insert("message-4") + assert.Equal( + t, + []message{ + {content: message4, new: true}, + {content: message2, new: true}, + {content: message3, new: true}, + }, + buf.messages) + }) +} + +func Test_MessageBuffer_GetWaitsForFirstData(t *testing.T) { + waitTime := 50 * time.Millisecond + buf := newMessageBuffer(1) + timer := time.NewTimer(waitTime) + startTime := time.Now() + + go func() { + <-timer.C + buf.Insert("delayed-message") + }() + + msg, err := buf.Get() + assert.NoError(t, err) + + endTime := time.Now() + + assert.Equal(t, "delayed-message", msg) + assert.GreaterOrEqual(t, endTime.Sub(startTime), waitTime) +} + +func Test_MessageBuffer_GetWaitsForNewData(t *testing.T) { + buf := newMessageBuffer(2) + + buf.Insert("message-1") + msg, err := buf.Get() + assert.NoError(t, err) + assert.Equal(t, "message-1", msg) + + go func() { + timer := time.NewTimer(100 * time.Millisecond) + <-timer.C + buf.Insert("delayed-message") + }() + + msg, err = buf.Get() + assert.NoError(t, err) + assert.Equal(t, "delayed-message", msg) +} + +func Test_MessageBuffer_IndexesAreCorrectAfterOverwritingOldData(t *testing.T) { + buf := newMessageBuffer(2) + + buf.Insert("message-1") + buf.Insert("message-2") + + assert.Equal( + t, + []message{ + {content: message1, new: true}, + {content: message2, new: true}, + }, + buf.messages) + + buf.Insert("message-3") + assert.Equal( + t, + []message{ + {content: message3, new: true}, + {content: message2, new: true}, + }, + buf.messages) + + msg, err := buf.Get() + assert.NoError(t, err) + assert.Equal(t, "message-2", msg) +} + +func Test_MessageBuffer_GetWaitsForNewDataIfOldOneWasAlreadyGotten(t *testing.T) { + buf := newMessageBuffer(2) + + buf.Insert(message1) + msg, err := buf.Get() + assert.NoError(t, err) + assert.Equal(t, message1, msg) + + buf.Insert(message2) + msg, err = buf.Get() + assert.NoError(t, err) + assert.Equal(t, message2, msg) + + go func() { + <-time.NewTimer(100 * time.Millisecond).C + buf.Insert(message3) + }() + + msg, err = buf.Get() + assert.NoError(t, err) + assert.Equal(t, message3, msg) + +} + +func Test_MessageBuffer_InsertCatchesUpWithRead(t *testing.T) { + buf := newMessageBuffer(5) + + buf.Insert(message1) + buf.Insert(message2) + buf.Insert(message3) + buf.Insert(message4) + buf.Insert(message5) + buf.Insert(message6) + buf.Insert(message7) + + msg, err := buf.Get() + + assert.NoError(t, err) + assert.Equal(t, message3, msg) +} + +func Test_MessageBuffer_FuckShitUp(t *testing.T) { + size := 10 + buf := newMessageBuffer(size) + wg := sync.WaitGroup{} + + wg.Add(2) + var readMsg = make([]string, 0) + go func() { + for i := 0; i < size*10; i++ { + msg, _ := buf.Get() + if msg == "99" { + break + } + fmt.Println("i = ", i, ": msg = ", msg) + readMsg = append(readMsg, msg) + } + wg.Done() + }() + + go func() { + for i := 0; i < size*10; i++ { + if i%10 == 0 { + timer := time.NewTimer(1 * time.Millisecond) + <-timer.C + } + buf.Insert(strconv.Itoa(i)) + } + wg.Done() + }() + + wg.Wait() + fmt.Println(buf.messages) + fmt.Println(readMsg) +} diff --git a/connection/type.go b/connection/type.go new file mode 100644 index 0000000..b4c6ebd --- /dev/null +++ b/connection/type.go @@ -0,0 +1,108 @@ +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 + return nil, err // Tell game-handler that connection was lost + } + + return []byte(msg), err +} + +func (conn *Connection) Close(msg string) { + conn.ws.Close(websocket.StatusCode(400), msg) + conn.ws = nil +} diff --git a/go.mod b/go.mod index f99aae5..e89c0e9 100644 --- a/go.mod +++ b/go.mod @@ -22,10 +22,8 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.16.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.3 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index fa4447d..81741d8 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,11 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc= -github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo= github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= @@ -21,45 +15,24 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-playground/validator/v10 v10.15.4 h1:zMXza4EpOdooxPel5xDqXEdXG5r+WggpvnAKMsalBjs= -github.com/go-playground/validator/v10 v10.15.4/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= -github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= -github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= -github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= -github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -67,8 +40,6 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -76,42 +47,22 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= -github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8= -github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= -github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -125,8 +76,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -137,49 +86,29 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tjarratt/babble v0.0.0-20210505082055-cbca2a4833c1 h1:j8whCiEmvLCXI3scVn+YnklCU8mwJ9ZJ4/DGAKqQbRE= github.com/tjarratt/babble v0.0.0-20210505082055-cbca2a4833c1/go.mod h1:O5hBrCGqzfb+8WyY8ico2AyQau7XQwAfEQeEQ5/5V9E= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y= -golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= -golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -188,12 +117,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -205,31 +128,17 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -244,9 +153,6 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= @@ -256,13 +162,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= -nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= diff --git a/lobby_registry/lobby.go b/lobby_registry/lobby.go index d47cb3b..d900002 100644 --- a/lobby_registry/lobby.go +++ b/lobby_registry/lobby.go @@ -32,7 +32,7 @@ func newEmptyLobbyWithPassphrase() *Lobby { func (l *Lobby) AddPlayerAndStartGameIfFull(player *chess.Player) { l.Game.AddPlayersToGame(player) if l.IsFull() { - go l.Game.Handle() + l.Game.StartHandling() } } diff --git a/main.go b/main.go index 03c4f2a..bd19b4f 100644 --- a/main.go +++ b/main.go @@ -75,7 +75,7 @@ func hostPrivateGame(c *gin.Context) { u := usher.GetUsher() mut.Lock() - defer mut.Unlock() + defer mut.Unlock() lobby := u.CreateNewPrivateLobby(player) u.AddPlayerToLobbyAndStartGameIfFull(player, lobby) @@ -137,7 +137,7 @@ func waitForAndHandlePlayerID(ctx context.Context, conn *websocket.Conn) { return } - log.Println("read from websocket: ", msgType, string(msg), err) + log.Println("read from websocket endpoint: ", msgType, string(msg), err) var info api.PlayerInfo err = json.Unmarshal(msg, &info) @@ -149,14 +149,19 @@ func waitForAndHandlePlayerID(ctx context.Context, conn *websocket.Conn) { } 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 != nil { - player.Conn.Close(websocket.StatusCode(400), "closing existing connection") + if player.Conn.HasWebsocketConnection() { + player.Conn.Close("closing existing connection") } - player.SetConnection(ctx, conn) + lobby.Game.SetWebsocketConnectionFor(ctx, player, conn) log.Println("player after setting connection: ", player) } diff --git a/utils/passphrase.go b/utils/passphrase.go index afb788b..4f54306 100644 --- a/utils/passphrase.go +++ b/utils/passphrase.go @@ -12,7 +12,7 @@ func NewPassphrase() Passphrase { var phrase string var retries int var word string - var words int = 2 + var words = 2 //TODO make sure passphrases are unique for words > 0 { retries = 20