diff options
Diffstat (limited to 'ws.go')
| -rw-r--r-- | ws.go | 106 |
1 files changed, 106 insertions, 0 deletions
@@ -0,0 +1,106 @@ +// ws.go +package main + +import ( + "encoding/json" + "log" + "net/http" + "time" + "unicode/utf8" + + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + // okay while you're behind nginx/caddy + CheckOrigin: func(r *http.Request) bool { return true }, +} + +func wsHandler(hub *Hub) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Printf("upgrade error: %v", err) + return + } + + // Expect first message to be auth + _, firstMsg, err := conn.ReadMessage() + if err != nil { + log.Printf("failed to read auth message: %v", err) + conn.Close() + return + } + + var auth IncomingMessage + if err := json.Unmarshal(firstMsg, &auth); err != nil { + log.Printf("invalid auth json: %v", err) + _ = conn.WriteJSON(AuthError{Type: "auth_error", Error: "bad_json"}) + conn.Close() + return + } + + if auth.Type != "auth" || auth.Token == "" { + _ = conn.WriteJSON(AuthError{Type: "auth_error", Error: "missing_token"}) + conn.Close() + return + } + + // Lookup token + hub.mu.RLock() + tc, ok := hub.tokens[auth.Token] + hub.mu.RUnlock() + + if !ok || tc.Revoked { + _ = conn.WriteJSON(AuthError{Type: "auth_error", Error: "invalid_token"}) + conn.Close() + return + } + + if auth.ServerID == "" { + auth.ServerID = "default" + } + if auth.Nick == "" { + auth.Nick = tc.Name + } + + // Enforce nickname length limit on initial/auth nick. + if utf8.RuneCountInString(auth.Nick) > maxNickLen { + log.Printf("auth nick %q too long, falling back to internal name %q", auth.Nick, tc.Name) + auth.Nick = tc.Name + } + if utf8.RuneCountInString(auth.Nick) > maxNickLen { + // still too long, truncate internal name + log.Printf("internal name %q too long, truncating to %d runes", auth.Nick, maxNickLen) + auth.Nick = truncateRunes(auth.Nick, maxNickLen) + } + + client := &Client{ + hub: hub, + conn: conn, + send: make(chan []byte, 32), + token: tc, + nick: auth.Nick, + serverID: auth.ServerID, + playerUUID: auth.PlayerUUID, + lastSeen: time.Now(), + } + + hub.register(client) + + if err := conn.WriteJSON(AuthOK{ + Type: "auth_ok", + InternalName: tc.Name, + }); err != nil { + log.Printf("failed to send auth_ok: %v", err) + hub.unregister(client) + conn.Close() + return + } + + go client.writePump() + client.readPump() + } +}
\ No newline at end of file |
