136 lines
2.1 KiB
Go
136 lines
2.1 KiB
Go
package wsapi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io"
|
|
|
|
"dynatron.me/x/blasphem/pkg/auth"
|
|
"dynatron.me/x/blasphem/pkg/blas/core"
|
|
|
|
"github.com/gorilla/websocket"
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var (
|
|
NoSuchHandlerErr = errors.New("bad websocket command")
|
|
)
|
|
|
|
type Type string
|
|
type MsgBase struct {
|
|
Type Type `json:"type"`
|
|
}
|
|
|
|
type (
|
|
wsSession struct {
|
|
*websocket.Conn
|
|
b core.Blas
|
|
ec echo.Context
|
|
h phaseHandler
|
|
|
|
user *auth.User
|
|
refreshToken *auth.RefreshToken
|
|
}
|
|
|
|
phaseHandler interface {
|
|
handleMsg(io.Reader) error
|
|
}
|
|
|
|
cmdHandler struct {
|
|
*wsSession
|
|
}
|
|
|
|
wsEntry struct {
|
|
dataNew core.NewData
|
|
hnd core.Handler
|
|
}
|
|
|
|
wsRegistry map[string]wsEntry
|
|
|
|
wsManager struct {
|
|
r wsRegistry
|
|
}
|
|
)
|
|
|
|
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 {
|
|
ws := &wsSession{
|
|
Conn: conn,
|
|
b: s,
|
|
ec: c,
|
|
}
|
|
|
|
ws.h = &authPhase{ws}
|
|
|
|
return ws
|
|
}
|
|
|
|
func (ws *wsSession) Blas() core.Blas { return ws.b }
|
|
|
|
func (ws *wsSession) Go() error {
|
|
err := ws.sendAuthRequired()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for {
|
|
_, rdr, err := ws.NextReader()
|
|
if err != nil {
|
|
log.Error().Err(err).Str("remote", ws.ec.Request().RemoteAddr).Msg("websocket read fail")
|
|
return err
|
|
}
|
|
|
|
err = ws.h.handleMsg(rdr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
type cmdMsg struct {
|
|
}
|
|
|
|
type MsgType string
|
|
|
|
func (ws *cmdHandler) handleMsg(r io.Reader) error {
|
|
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)
|
|
}
|