blasphem/pkg/wsapi/api.go

137 lines
2.1 KiB
Go
Raw Normal View History

2022-12-19 19:24:01 -05:00
package wsapi
import (
2022-12-20 19:05:45 -05:00
"encoding/json"
"errors"
2022-12-20 11:34:25 -05:00
"io"
2022-12-19 19:24:01 -05:00
"dynatron.me/x/blasphem/pkg/auth"
2022-12-20 19:05:45 -05:00
"dynatron.me/x/blasphem/pkg/blas/core"
2022-12-19 19:24:01 -05:00
"github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"github.com/rs/zerolog/log"
)
2022-12-20 19:05:45 -05:00
var (
NoSuchHandlerErr = errors.New("bad websocket command")
)
2022-12-19 19:24:01 -05:00
type Type string
type MsgBase struct {
Type Type `json:"type"`
}
type (
wsSession struct {
*websocket.Conn
2022-12-20 19:05:45 -05:00
b core.Blas
2022-12-19 19:24:01 -05:00
ec echo.Context
2022-12-20 13:16:30 -05:00
h phaseHandler
2022-12-19 19:24:01 -05:00
2022-12-20 13:16:30 -05:00
user *auth.User
2022-12-19 19:24:01 -05:00
refreshToken *auth.RefreshToken
}
phaseHandler interface {
2022-12-20 11:34:25 -05:00
handleMsg(io.Reader) error
2022-12-19 19:24:01 -05:00
}
cmdHandler struct {
*wsSession
}
2022-12-20 19:05:45 -05:00
wsEntry struct {
dataNew core.NewData
hnd core.Handler
}
wsRegistry map[string]wsEntry
wsManager struct {
r wsRegistry
}
2022-12-19 19:24:01 -05:00
)
2022-12-20 19:05:45 -05:00
func (wsm *wsManager) RegisterWSCommand(cmd string, hnd core.Handler, dataNew core.NewData) {
wsm.r[cmd] = wsEntry{
dataNew: dataNew,
hnd: hnd,
}
}
func (wsm *wsManager) WSCommandHandler(cmd string) (core.NewData, core.Handler, error) {
wse, ok := wsm.r[cmd]
if !ok {
return nil, nil, NoSuchHandlerErr
}
return wse.dataNew, wse.hnd, nil
}
func NewManager() core.WebSocketManager {
return &wsManager{
r: make(wsRegistry),
}
}
func NewSession(s core.Blas, c echo.Context, conn *websocket.Conn) core.WebSocketSession {
2022-12-19 19:24:01 -05:00
ws := &wsSession{
Conn: conn,
2022-12-20 13:16:30 -05:00
b: s,
ec: c,
2022-12-19 19:24:01 -05:00
}
2022-12-20 19:05:45 -05:00
ws.h = &authPhase{ws}
2022-12-19 19:24:01 -05:00
return ws
}
2022-12-20 19:05:45 -05:00
func (ws *wsSession) Blas() core.Blas { return ws.b }
func (ws *wsSession) Go() error {
2022-12-19 19:24:01 -05:00
err := ws.sendAuthRequired()
if err != nil {
return err
}
for {
2022-12-20 11:34:25 -05:00
_, rdr, err := ws.NextReader()
2022-12-19 19:24:01 -05:00
if err != nil {
log.Error().Err(err).Str("remote", ws.ec.Request().RemoteAddr).Msg("websocket read fail")
2022-12-20 11:34:25 -05:00
return err
2022-12-19 19:24:01 -05:00
}
2022-12-20 11:34:25 -05:00
err = ws.h.handleMsg(rdr)
2022-12-19 19:24:01 -05:00
if err != nil {
return err
}
}
}
type cmdMsg struct {
}
type MsgType string
2022-12-20 11:34:25 -05:00
func (ws *cmdHandler) handleMsg(r io.Reader) error {
2022-12-20 19:05:45 -05:00
var msgMap map[string]interface{}
err := json.NewDecoder(r).Decode(&msgMap)
if err != nil {
return err
}
msgType, ok := msgMap["type"].(string)
if !ok {
return NoSuchHandlerErr
}
newData, hand, err := ws.b.WSCommandHandler(msgType)
if !ok {
return err
}
nd := newData()
return hand(ws, nd)
2022-12-19 19:24:01 -05:00
}