Gateway working, beta
This commit is contained in:
119
ws/util.go
119
ws/util.go
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"homestead/homestead_gateway/util/cache"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
@@ -36,6 +36,11 @@ func (wsg *WebsocketGateway) deafen(srv *http.Server) {
|
||||
|
||||
// responses
|
||||
|
||||
func (wsg *WebsocketGateway) flush(c *websocket.Conn, m GatewayMessageOut) error {
|
||||
_ = c.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
||||
return c.WriteJSON(m)
|
||||
}
|
||||
|
||||
func (wsg *WebsocketGateway) sendHttpError(w http.ResponseWriter, message string, code int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(code)
|
||||
@@ -94,15 +99,6 @@ func (wsg *WebsocketGateway) validateApiKey(r *http.Request) bool {
|
||||
return !(apiKey == "" || apiKey != wsg.apiKey)
|
||||
}
|
||||
|
||||
func writeJSONSafe(c *websocket.Conn, v interface{}) error {
|
||||
_ = c.SetWriteDeadline(time.Now().Add(5 * time.Second))
|
||||
if err := c.WriteJSON(v); err != nil {
|
||||
// caller handles logging
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func loggingMiddleware(logger *slog.Logger, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
@@ -113,43 +109,112 @@ func loggingMiddleware(logger *slog.Logger, next http.Handler) http.Handler {
|
||||
|
||||
// connections
|
||||
|
||||
func (wsg *WebsocketGateway) registerConn(conn *websocket.Conn, meta cache.ConnectionMetaData, typ string) bool {
|
||||
func (wsg *WebsocketGateway) registerConn(conn *websocket.Conn, typ, channelId, serverId string) bool {
|
||||
if typ == "bot" {
|
||||
if wsg.bot != nil {
|
||||
wsg.registry.botMu.Lock()
|
||||
if wsg.registry.bot != nil && wsg.registry.bot.Conn != nil {
|
||||
wsg.registry.botMu.Unlock()
|
||||
return false
|
||||
}
|
||||
wsg.registry.botMu.Unlock()
|
||||
|
||||
wsg.bot = conn
|
||||
wsg.registry.RegisterBot(conn)
|
||||
return true
|
||||
}
|
||||
|
||||
wsg.conns.Set(meta.ID, conn, &meta)
|
||||
wsg.registry.RegisterMod(channelId, serverId, conn)
|
||||
return true
|
||||
}
|
||||
|
||||
func (wsg *WebsocketGateway) unregisterConn(conn *websocket.Conn, meta cache.ConnectionMetaData, typ string) {
|
||||
func (wsg *WebsocketGateway) unregisterConn(conn *websocket.Conn, typ, channelId string) {
|
||||
if typ == "bot" {
|
||||
_ = wsg.bot.Close()
|
||||
wsg.bot = nil
|
||||
wsg.registry.UnregisterBot()
|
||||
if conn != nil {
|
||||
_ = conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Disconnecting."), time.Now().Add(time.Second))
|
||||
_ = conn.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
wsg.conns.RemoveById(meta.ID)
|
||||
_ = conn.Close()
|
||||
wsg.registry.UnregisterMod(channelId)
|
||||
|
||||
if conn != nil {
|
||||
_ = conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Disconnecting."), time.Now().Add(time.Second))
|
||||
_ = conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (wsg *WebsocketGateway) closeAll() {
|
||||
wsg.logger.Info("Closing all websocket connections.")
|
||||
|
||||
if wsg.bot != nil {
|
||||
_ = wsg.bot.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Shutting down."), time.Now().Add(time.Second))
|
||||
_ = wsg.bot.Close()
|
||||
wsg.registry.UnregisterBot()
|
||||
|
||||
wsg.registry.mu.RLock()
|
||||
entries := make([]*ChannelEntry, 0, len(wsg.registry.entries))
|
||||
for _, e := range wsg.registry.entries {
|
||||
entries = append(entries, e)
|
||||
}
|
||||
wsg.registry.mu.RUnlock()
|
||||
|
||||
for _, e := range entries {
|
||||
e.mu.Lock()
|
||||
modConn := e.Mod
|
||||
if modConn != nil {
|
||||
e.Mod = nil
|
||||
}
|
||||
e.mu.Unlock()
|
||||
|
||||
if modConn != nil && modConn.Conn != nil {
|
||||
_ = modConn.Conn.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Shutting down."), time.Now().Add(time.Second))
|
||||
_ = modConn.Conn.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func NewRegistry(queueCap int) *Registry {
|
||||
return &Registry{
|
||||
entries: make(map[string]*ChannelEntry),
|
||||
queueCap: queueCap,
|
||||
}
|
||||
}
|
||||
|
||||
func NewBoundedQueue(cap int) *BoundedQueue {
|
||||
if cap <= 0 {
|
||||
cap = 128
|
||||
}
|
||||
return &BoundedQueue{buf: make([]GatewayMessageOut, cap), capacity: cap}
|
||||
}
|
||||
|
||||
func newChannelEntry(channel string, cap int) *ChannelEntry {
|
||||
return &ChannelEntry{
|
||||
Channel: channel,
|
||||
Queue: NewBoundedQueue(cap),
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func (m *GatewayMessageIn) Validate() error {
|
||||
if strings.TrimSpace(m.ID) == "" {
|
||||
return errors.New("id missing")
|
||||
}
|
||||
if strings.TrimSpace(m.MsgID) == "" {
|
||||
return errors.New("msg_id missing")
|
||||
}
|
||||
if strings.TrimSpace(m.Author.ID) == "" {
|
||||
return errors.New("author.id missing")
|
||||
}
|
||||
if strings.TrimSpace(m.Content) == "" {
|
||||
return errors.New("content missing")
|
||||
}
|
||||
|
||||
wsg.conns.Range(func(id string, c *websocket.Conn, meta *cache.ConnectionMetaData) {
|
||||
_ = c.WriteControl(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "Shutting down."), time.Now().Add(time.Second))
|
||||
_ = c.Close()
|
||||
})
|
||||
if m.Type == "mod" && strings.TrimSpace(m.Destination.ID) == "" {
|
||||
return errors.New("destination.channel_id missing")
|
||||
}
|
||||
|
||||
wsg.conns.Clear()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConnWrapper) Alive() bool { return c != nil && c.Conn != nil }
|
||||
|
||||
Reference in New Issue
Block a user