// Package services ports the message handlers and lifecycle hooks that lived in // Source/Services/* of the Node.js engine: YourID, Session, Auth, Room, // IPPressure and DataTransfer. Each is registered onto a *ws.Hub, which owns the // router and the connect/disconnect event bus. // // Where the original handlers contained outright bugs (a Set used as if it were an // Array, comparing a Client object to a string id, validating against an // undefined schema variable, ...) this port implements the *intended* behaviour // and records the deviation in decisions.md. The on-the-wire message shapes the // SDK depends on are preserved. package services import ( "crypto/sha256" "encoding/hex" "git.saqut.com/saqut/mwse/internal/protocol" "git.saqut.com/saqut/mwse/internal/ws" ) // Register wires every service onto the hub. Call once during startup, before the // server begins accepting connections. The order mirrors the Node require() order // so connect-time side effects (id message, private room, session defaults) // happen in the same sequence. func Register(hub *ws.Hub) { registerYourID(hub) registerAuth(hub) registerRoom(hub) registerDataTransfer(hub) registerIPPressure(hub, nil) registerSession(hub) } // ---- small response helpers --------------------------------------------- // success is the ubiquitous {status:"success"} reply. func success() map[string]any { return map[string]any{"status": "success"} } // fail is the ubiquitous {status:"fail", message:...} reply. func fail(message string) map[string]any { return map[string]any{"status": "fail", "message": message} } // toMap coerces an arbitrary decoded JSON value to an object, returning an empty // map when it is not one (e.g. a missing "filter" field). func toMap(v any) map[string]any { if m, ok := v.(map[string]any); ok { return m } return map[string]any{} } // sha256hex hashes credentials the same way the original Room service did. func sha256hex(s string) string { sum := sha256.Sum256([]byte(s)) return hex.EncodeToString(sum[:]) } // ids extracts the client ids from a slice of clients. func ids(clients []*ws.Client) []string { out := make([]string, 0, len(clients)) for _, c := range clients { out = append(out, c.ID) } return out } // handler is a convenience alias matching ws.Handler's shape, used to keep the // per-service files concise. type handler = func(c *ws.Client, m protocol.Message) any