cf961603fe
The second migration step: the layer above the codec, deciding WHAT to say
rather than how to encode it. Sits on openfut-protocol-blaze and supplies
what that crate deliberately refuses to know.
blaze/ids.rs component/command/notification tables
blaze/config.rs injectable identity + endpoints, nothing hardcoded
blaze/session.rs per-connection state
blaze/client_config.rs the fetchClientConfig tables
blaze/responses.rs 16 Blaze::* response bodies
blaze/dispatch.rs (component, command) -> Vec<Frame>
Parity is tested, not asserted. fixtures/generate.py drives the real
blaze_responder_v3b.dispatch() and records 49 request->response(s)
transactions, replayed in order against a shared session per connection so
ordering-dependent behaviour is exercised: preAuth captures the locale later
ALOC fields echo, login sets the auth code getAuthToken returns. Comparison
is byte-for-byte including frame count and order.
98 tests green across both crates; clippy clean.
MUTATION TESTED, and it found a real defect in this commit's own design.
Swapping two post-login notifications and flipping one enum inside
AccountInfo both turned the suite red as intended. Hardcoding an address in
utas_base() did NOT -- the config templating substituted raw hosts directly,
making those helpers dead code that merely looked load-bearing. The table now
templates on URL-level tokens ({utas_base}, {nucleus_base},
{pow_content_url}) so they are the single place a URL shape is defined, and
the mutation is caught.
The client config table (227-243 rows per CFID) is generated from the oracle
rather than transcribed: it is reverse-engineered data, not logic, and 400
hand-copied string literals would add a typo class no reviewer can catch. The
generator substitutes real addresses back in and diffs against the oracle for
every section before writing, so the templating is verified rather than
assumed.
Reproduces one known defect deliberately: nucleusConnect is built from BIND,
not advertise, so the live split deployment tells a client on another machine
to reach Nucleus at http://0.0.0.0:42131. Confirmed against the running
container. Reproduced because it is what the only proven-working config does;
fixing it needs live validation and is a separate change. It also implies the
Nucleus stub is not reached in the current remote flow.
Blaze carries no FUT domain state -- no coins, packs, clubs or squads on this
wire -- so Session stays a session key, locale, service name, auth code and a
flag. That boundary will need defending when UTAS is migrated.
Not wired into anything. The crate answers frames; it opens no socket and
owns no runtime. The Python backend remains the live service and the oracle,
and is unmodified (contract suite still green).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
63 lines
2.4 KiB
Rust
63 lines
2.4 KiB
Rust
//! # openfut-adapter-fifa17
|
|
//!
|
|
//! The FIFA 17 game adapter: everything that is true of *FIFA 17 specifically*
|
|
//! and must therefore stay out of OpenFUT Core and out of the generic protocol
|
|
//! crates.
|
|
//!
|
|
//! ## Layering
|
|
//!
|
|
//! ```text
|
|
//! openfut-protocol-blaze generic Blaze: Fire2 framing, Heat2/TDF codec
|
|
//! ▲
|
|
//! openfut-adapter-fifa17 THIS: FIFA 17 command tables, response bodies,
|
|
//! ▲ dispatch ordering, session identity
|
|
//! OpenFUT Core game-independent FUT domain (not yet wired)
|
|
//! ```
|
|
//!
|
|
//! A second title gets its own adapter crate and reuses the protocol layer
|
|
//! underneath. Nothing here is written to be shared with one; if something in
|
|
//! this crate turns out to be title-independent, it belongs one layer down.
|
|
//!
|
|
//! ## Modules
|
|
//!
|
|
//! * [`blaze`] — the Blaze/Fire2 RPC surface. Implemented.
|
|
//!
|
|
//! Still served only by the Python backend, each a separate future module:
|
|
//! the redirector (HTTPS + XML `getServerInstance`), the Nucleus OAuth stub,
|
|
//! LSX/Origin (`:4216`), roster XML (`:8081`), UTAS/RS4 (`:8099`) and POW/EASFC
|
|
//! (`:8094`).
|
|
//!
|
|
//! ## Provenance
|
|
//!
|
|
//! Ported from `fifa17-recon/tools/blaze_responder_v3b.py`, the implementation
|
|
//! that drove a retail FIFA 17 client from Origin login to an opened FUT pack.
|
|
//! Parity is tested, not asserted: `fixtures/blaze_transactions.jsonl` records
|
|
//! real request→response(s) transactions produced by the Python dispatcher, and
|
|
//! `tests/oracle_parity.rs` replays them byte-for-byte.
|
|
//!
|
|
//! ## Not a server
|
|
//!
|
|
//! This crate answers frames. It opens no socket, terminates no TLS and owns no
|
|
//! runtime. Hosting it is a separate, later decision — the Python backend
|
|
//! remains the live runtime and nothing here is wired into it.
|
|
//!
|
|
//! ```
|
|
//! use openfut_adapter_fifa17::blaze::{Adapter, AdapterConfig, Session};
|
|
//! use openfut_protocol_blaze::fire2::{Header, MsgType};
|
|
//! use openfut_protocol_blaze::heat2::Struct;
|
|
//!
|
|
//! let adapter = Adapter::new(AdapterConfig::default());
|
|
//! let mut session = Session::new("session-key", 0x656E5553);
|
|
//!
|
|
//! // Util::ping
|
|
//! let request = Header::new(0x0009, 0x0002, 1, MsgType::Message);
|
|
//! let out = adapter.dispatch(&request, &Struct::new(), &mut session, 1_754_870_400);
|
|
//!
|
|
//! assert_eq!(out.len(), 1);
|
|
//! assert_eq!(out[0].header.msg_type, MsgType::Reply);
|
|
//! ```
|
|
|
|
pub mod blaze;
|
|
|
|
pub use blaze::{Adapter, AdapterConfig, Session};
|