Trabajo de @alyeri, revisado y verificado. Sustituye al PR #5, que se mergeo y
se revirtio (c32d7ca) porque la primera version tenia dos fallos bloqueantes.
Los cinco hallazgos de aquella revision estan atendidos.
CAUSA. El codigo del torneo se escribia en un offset fijo, localizado buscando
el ultimo patron de cadena vacia. Esa heuristica es ambigua: un entero posterior
puede contener 01 00 00, asi que el codigo acababa en el campo equivocado y
desplazaba el resto de la estructura. MK8D interpretaba entonces bytes de cadena
como campos de fecha y el cliente Pia crasheaba al procesar la lista.
ARREGLO. tournamentCodeOffset ya no asume nada fijo: lee la longitud del nombre
UTF-16 y despues RECORRE la lista de propiedades de reglas hasta su terminador
0xFF, avanzando segun el ancho de cada tipo (0x01 -> 4, 0x02 -> 5, 0x04 -> 7).
La version anterior daba por hecho un bloque fijo de 0x40 bytes entre el nombre
y el codigo, y ese bloque es de longitud VARIABLE: decodificando la captura hay
entradas de 4, 5 y 7 bytes, y el id 02 ni siquiera aparece.
Que cambia respecto a la primera version, punto por punto:
- El 0x40 fijo desaparece, sustituido por el recorrido real.
- CreateTournament ya no rechaza en duro cuando el offset falla: devuelve nil en
vez de ResultCoreInvalidArgument. Antes, un jugador con un reglamento distinto
no podia crear torneos en absoluto.
- Los torneos invalidados se CONSERVAN en un slice `quarantined`. Antes se
perdian: el flusher reescribe el fichero solo desde byID, asi que el primer
torneo creado tras arrancar borraba del disco todas las entradas rechazadas.
- nextID avanza con TODAS las entradas leidas, incluidas las rechazadas. Antes se
reasignaban IDs que las consolas tenian cacheados de searchTournaments, y un
cliente podia entrar en un torneo distinto del que creia.
- joinTournament y deleteTournament validan con validStoredTournament, igual que
tournamentByID y allTournaments. Antes una entrada invalida era invisible en
los listados pero seguia siendo joinable, y al entrar se re-persistia.
Dos cambios propios sobre lo que envio:
- El caso `default` (tipo de propiedad desconocido) volvia a caer en el scan
ambiguo "01 00 00" — justo la heuristica que este parche elimina. Ahora falla
explicitamente y registra el tipo desconocido: mejor enterarse que adivinar y
corromper la estructura.
- server.go venia con finales de linea CRLF, lo que inflaba el diff a 216 lineas
cuando el cambio real son 15. Normalizado a LF.
server.go anade un CustomHTTPHandler opcional para responder HTTP plano en rutas
distintas de "/" sin intentar el upgrade a WebSocket. Por defecto es nil, asi que
el transporte se comporta EXACTAMENTE igual que antes para todos los titulos
existentes.
Tests: ocho, todos pasando. Incluyen TestTournamentVariableLengthName (nombres de
cualquier longitud, el hueco que dejaba pasar el bug) y
TestStampTournamentIgnoresLaterEmptyPattern (la colision con un 01 00 00
posterior). La captura real existente sigue reproduciendose.
NO DESPLEGADO. MK8 no compila contra este repo sino contra una copia local, el
binario mk8cs es codigo cerrado y se construye fuera del servidor. Ademas la
contrasena Kerberos esta parcheada en el binario desplegado mientras el codigo
lleva el valor publico: un rebuild ingenuo la devolveria a produccion. El
despliegue tiene que pasar por Kazu.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
A from-scratch implementation of Nintendo's NEX / PRUDP online protocol, written in Go.
What is this?
nextendo-nex is the server core that powers the Nextendo Network
game servers — Mario Kart 8 Deluxe, Splatoon 2, Super Smash Bros. Ultimate, and others.
NEX is the client-server middleware many Nintendo games use for matchmaking, rankings, and other
online services, layered on top of the PRUDP transport. This package reimplements the server side
of that stack from scratch:
PRUDP transport (reliable UDP: connection handshake, fragmentation, acknowledgements)
RMC message layer (the request/response format NEX methods speak)
Kerberos-style ticket authentication (auth server ↔ secure server)
The common service protocols games build on (matchmaking, ranking, data store, utility, …)
It has no third-party NEX dependencies — only permissive Go libraries (gorilla/websocket,
lxzan/gws). The module is github.com/NextendoNetwork/nextendo-nex.
Usage
This is a library, not a runnable server on its own. A game server imports it, registers the
protocols and methods that game needs, and starts an endpoint. See the per-game repositories for
concrete servers built on top of this core.
This project ships no Nintendo code, keys, or copyrighted assets. It is an independent,
clean-room reimplementation of a publicly-documented protocol, for use with a community-run
replacement service. It is not affiliated with, endorsed by, or associated with Nintendo.
Credits
The NEX / PRUDP protocol is publicly documented by
Kinnay's NintendoClients (MIT); this implementation
follows that documentation.
License
Released under the PolyForm Shield License 1.0.0 — a source-available license: you
may read, use, modify, and self-host the code, but not use it to provide a product that competes with
Nextendo Network.