mchess-server/main.go

189 lines
4.7 KiB
Go
Raw Normal View History

2022-10-22 18:01:55 +00:00
package main
import (
"context"
"encoding/json"
2023-09-01 13:29:26 +00:00
"flag"
"fmt"
"log"
2023-06-25 14:11:29 +00:00
"mchess_server/api"
"mchess_server/chess"
lobbies "mchess_server/lobby_registry"
"mchess_server/usher"
"mchess_server/utils"
2022-11-19 10:41:10 +00:00
"net/http"
"sync"
2023-04-18 20:12:05 +00:00
"github.com/gin-gonic/gin"
2023-04-18 20:19:28 +00:00
"github.com/google/uuid"
"nhooyr.io/websocket"
2022-10-22 18:01:55 +00:00
)
var cert_path = "/etc/letsencrypt/live/chess.sw-gross.de/"
var cert_file = cert_path + "fullchain.pem"
var key_file = cert_path + "privkey.pem"
var mut sync.Mutex
2023-04-18 20:12:05 +00:00
func main() {
2023-09-01 13:29:26 +00:00
var debugMode bool
debugModeLong := flag.Bool("debug", false, "activates debug mode")
debugModeShort := flag.Bool("d", false, "activates debug mode")
flag.Parse()
if *debugModeShort || *debugModeLong {
debugMode = true
2022-12-18 14:43:27 +00:00
}
2023-04-18 20:12:05 +00:00
router := gin.Default()
router.GET("/api/random", registerForRandomGame)
2023-06-28 17:51:36 +00:00
router.GET("/api/hostPrivate", hostPrivateGame)
2023-06-29 23:50:04 +00:00
router.POST("/api/joinPrivate", joinPrivateGame)
router.GET("/api/ws", registerWebSocketConnection)
2022-11-19 10:41:10 +00:00
2023-09-01 13:29:26 +00:00
if debugMode {
2023-04-18 20:12:05 +00:00
log.Println("Starting service WITHOUT TLS")
log.Fatal(router.Run(":8080"))
} else {
2023-06-06 20:58:33 +00:00
gin.SetMode(gin.ReleaseMode)
log.Println("Starting in release mode")
log.Println("Starting service with TLS")
2023-06-06 21:23:28 +00:00
log.Fatal(router.RunTLS("chess.sw-gross.de:9999", cert_file, key_file))
2022-11-19 10:41:10 +00:00
}
2023-04-18 20:12:05 +00:00
}
2022-11-19 10:41:10 +00:00
func registerForRandomGame(c *gin.Context) {
player := chess.NewPlayer(uuid.New())
usher := usher.GetUsher()
mut.Lock()
defer mut.Unlock()
lobby := usher.WelcomeNewPlayer(player)
usher.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
info := api.PlayerInfo{
2023-06-29 23:50:04 +00:00
PlayerID: &player.Uuid,
LobbyID: &lobby.Uuid,
}
log.Println("responding with info ", info)
c.Header("Access-Control-Allow-Origin", "*")
c.IndentedJSON(http.StatusOK, info)
2023-04-18 20:12:05 +00:00
}
2023-06-28 17:51:36 +00:00
func hostPrivateGame(c *gin.Context) {
player := chess.NewPlayer(uuid.New())
u := usher.GetUsher()
mut.Lock()
defer mut.Unlock()
2023-06-29 23:50:04 +00:00
lobby := u.CreateNewPrivateLobby(player)
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
2023-06-28 17:51:36 +00:00
passphrase := lobby.Passphrase.String()
info := api.PlayerInfo{
2023-06-29 23:50:04 +00:00
PlayerID: &player.Uuid,
LobbyID: &lobby.Uuid,
Passphrase: &passphrase,
}
c.Header("Access-Control-Allow-Origin", "*")
c.IndentedJSON(http.StatusOK, info)
2023-06-28 17:51:36 +00:00
}
func joinPrivateGame(c *gin.Context) {
2023-06-29 23:50:04 +00:00
req := api.PlayerInfo{}
log.Println(c.Request.Body)
err := c.ShouldBindJSON(&req)
if err != nil || req.Passphrase == nil || *req.Passphrase == "" {
c.IndentedJSON(http.StatusNotFound, req)
}
u := usher.GetUsher()
2023-12-25 15:30:03 +00:00
if req.Passphrase != nil &&
*req.Passphrase != "" &&
req.PlayerID != nil &&
req.LobbyID != nil { //is reconnect
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
_, found := lobby.GetPlayerByUUID(*req.PlayerID)
if found {
c.IndentedJSON(
http.StatusOK,
api.PlayerInfo{
PlayerID: req.PlayerID,
LobbyID: req.LobbyID,
Passphrase: req.Passphrase,
})
return
} else {
c.IndentedJSON(http.StatusNotFound, req)
}
}
player := chess.NewPlayer(uuid.New())
mut.Lock()
2023-06-29 23:50:04 +00:00
defer mut.Unlock()
lobby := u.FindExistingPrivateLobby(utils.Passphrase(*req.Passphrase))
2023-06-29 23:50:04 +00:00
if lobby != nil {
u.AddPlayerToLobbyAndStartGameIfFull(player, lobby)
} else {
c.IndentedJSON(http.StatusNotFound, req)
return
}
info := api.PlayerInfo{
PlayerID: &player.Uuid,
LobbyID: &lobby.Uuid,
Passphrase: req.Passphrase,
}
c.Header("Access-Control-Allow-Origin", "*")
c.IndentedJSON(http.StatusOK, info)
2023-06-28 17:51:36 +00:00
}
func registerWebSocketConnection(c *gin.Context) {
2023-06-08 18:20:37 +00:00
webSocketConn, err := websocket.Accept(c.Writer, c.Request, &websocket.AcceptOptions{OriginPatterns: []string{"chess.sw-gross.de", "localhost:*"}})
if err != nil {
log.Println(err)
return
}
2023-06-06 20:58:33 +00:00
go waitForAndHandlePlayerID(c, webSocketConn)
}
2023-04-18 20:12:05 +00:00
2023-06-06 20:58:33 +00:00
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
}
2023-04-18 20:12:05 +00:00
2023-06-29 23:50:04 +00:00
lobby := lobbies.GetLobbyRegistry().GetLobbyByUUID(*info.LobbyID)
if lobby == nil {
conn.Close(websocket.StatusCode(400), "lobby not found")
return
}
2023-06-29 23:50:04 +00:00
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")
2023-04-18 20:12:05 +00:00
}
lobby.Game.SetWebsocketConnectionFor(ctx, player, conn)
log.Println("player after setting connection: ", player)
}