From-scratch Go implementation of Nintendo's NEX/PRUDP protocol — the Nextendo Network server core.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Budsin e614118cbc tournament: localizar el codigo del torneo recorriendo la lista de propiedades
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]>
2026-08-16 17:26:36 -05:00
.gitignore Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
authbinding.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
authbinding_test.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
dashboard_data.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
diag.go lm3: friend presence WIP on v0.1.3 rebase 2026-08-11 04:29:17 +01:00
endpoint.go Deduplicate retransmitted reliable PRUDP packets before RMC dispatch 2026-08-15 21:23:34 -04:00
endpoint_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
go.mod nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
go.sum nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
kerberos.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
kerberos_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
LICENSE.md nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
matchmaking.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
matchmaking_acnh.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
matchmaking_acnh_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
matchmaking_handlers.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
matchmaking_handlers_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
matchmaking_notifdata.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
matchmaking_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
nat_matchmaking_test.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
natbridge.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
natbridge_race_test.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
natbridge_test.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
nattraversal.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
nattraversal_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
notification.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
proxyproto.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
prudp_lite.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
prudp_lite_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
ranking.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
ranking_board.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
ranking_board_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
ranking_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
README.md nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
reaper.go Core: matchmaking/NAT refresh, auth token binding, solo isolation, dashboard geo/NAT/ping 2026-08-10 20:45:45 +02:00
resultcodes.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
rmc.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
rmc_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
secureconnection.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
secureconnection_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
server.go tournament: localizar el codigo del torneo recorriendo la lista de propiedades 2026-08-16 17:26:36 -05:00
server_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
settings.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
solo_isolate.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
stream.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
stream_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
stubs_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
ticketgranting.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
ticketgranting_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00
tournament.go tournament: localizar el codigo del torneo recorriendo la lista de propiedades 2026-08-16 17:26:36 -05:00
tournament_capture_test.go tournament: localizar el codigo del torneo recorriendo la lista de propiedades 2026-08-16 17:26:36 -05:00
tournament_test.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
types.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
utility.go Sync: player profiles, tournaments and tournament rankings 2026-08-13 14:57:35 +02:00
utility_test.go nextendo-nex: initial source release 2026-07-21 23:38:07 +02:00

nextendo-nex

A from-scratch implementation of Nintendo's NEX / PRUDP online protocol, written in Go.

License: PolyForm Shield 1.0.0 Go 1.23+


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.

import nex "github.com/NextendoNetwork/nextendo-nex"

What this is not

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.