You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
4.6 KiB
Go

package routes
import (
"log"
"github.com/aziis98/lupus-lite/events"
"github.com/aziis98/lupus-lite/util"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/websocket/v2"
)
// func (s *Server) websocketHandler(handler func(c *fiber.Ctx) (interface{}, error)) fiber.Handler {
// return websocket.New(func(c *websocket.Conn) {
// clientId := util.GenerateRandomString(10)
// partitaUid := c.Params("partita")
// log.Printf("[%v] Connection started", clientId)
// done := make(chan error)
// clientListener := s.eventBus.Subscribe(
// database.OnPartitaPlayerJoin(partitaUid),
// func(e interface{}) {
// partita, err := s.db.GetPartita(partitaUid)
// if err != nil {
// done <- err
// return
// }
// log.Printf(`[%v] Sent message`, clientId)
// if err := c.WriteJSON(partita.Players); err != nil {
// done <- err
// return
// }
// },
// )
// defer func() {
// s.eventBus.Unsubscribe(clientListener)
// log.Printf("[%v] Connection closed", clientId)
// }()
// for {
// _, _, err := c.ReadMessage()
// if err != nil {
// if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
// log.Printf("[%v] Error: %v", clientId, err)
// }
// return
// }
// select {
// case err := <-done:
// if err != nil {
// log.Printf(`[%v] Error: %v`, clientId, err)
// }
// return
// case <-time.After(1 * time.Second):
// }
// }
// })
// }
// func (s *Server) registerEventBinding(event string, process func(c *fiber.Ctx, e any) (any, error)) fiber.Handler {
// return websocket.New(func(c *websocket.Conn) {
// clientId := util.GenerateRandomString(10)
// log.Printf("[%v] Connection started", clientId)
// done := make(chan error)
// clientListener := s.eventBus.Subscribe(
// event,
// func(e interface{}) {
// partita, err := s.db.GetPartita(partitaUid)
// if err != nil {
// done <- err
// return
// }
// log.Printf(`[%v] Sent message`, clientId)
// if err := c.WriteJSON(partita.Players); err != nil {
// done <- err
// return
// }
// },
// )
// defer func() {
// s.eventBus.Unsubscribe(clientListener)
// log.Printf("[%v] Connection closed", clientId)
// }()
// for {
// _, _, err := c.ReadMessage()
// if err != nil {
// if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
// log.Printf("[%v] Error: %v", clientId, err)
// }
// return
// }
// select {
// case err := <-done:
// if err != nil {
// log.Printf(`[%v] Error: %v`, clientId, err)
// }
// return
// case <-time.After(1 * time.Second):
// }
// }
// })
// }
type clientMessage struct {
Type string `json:"type"`
Event string `json:"event"`
}
type serverMessage struct {
Event string `json:"event"`
Data any `json:"data"`
}
// registerEventBinder creates a WebSocket handler that can subscribe the socket to some events generated on the server, for example a message from the client like { type: "subscribe", event: "foo" } binds the connection to the event "foo" and forwards events and the associated data to client as JSON.
func registerEventBinder(eb *events.EventBus) fiber.Handler {
return websocket.New(func(c *websocket.Conn) {
clientId := util.GenerateRandomString(10)
log.Printf("[%v] Connection started", clientId)
defer log.Printf("[%v] Connection closed", clientId)
listeners := []*events.Listener{}
defer func() {
for _, l := range listeners {
eb.Unsubscribe(l)
}
}()
done := make(chan error)
for {
var msg clientMessage
if err := c.ReadJSON(&msg); err != nil {
log.Printf(`[%v] Read error: %v`, clientId, err)
return
}
log.Printf("[%v] Received: %v", clientId, msg)
switch msg.Type {
case "subscribe":
newListener := eb.Subscribe(
msg.Event,
func(e interface{}) {
log.Printf(`[%v] Sent message`, clientId)
if err := c.WriteJSON(serverMessage{
Event: msg.Event,
Data: e,
}); err != nil {
log.Printf(`[%v] Write error: %v`, clientId, err)
done <- err
}
},
)
listeners = append(listeners, newListener)
default:
log.Printf("[%v] Unknown message type %q", clientId, msg.Type)
return
}
select {
case err := <-done:
if err != nil {
return
}
default:
}
}
})
}
func (s *Server) EventRoute(r fiber.Router) {
r.Use("/ws", func(c *fiber.Ctx) error {
if websocket.IsWebSocketUpgrade(c) {
c.Locals("allowed", true)
return c.Next()
}
return fiber.ErrUpgradeRequired
})
r.Get("/ws", registerEventBinder(s.eventBus))
}