LSX gate: FIFA reaches "connecting to EA Servers" via bridge
Implement the LSX (EA App bootstrap, TCP :3216→:3217) server in the bridge
and clear the loading-screen crash gate. FIFA 23 now completes the full LSX
handshake + session against OpenFUT and advances to the online/Blaze phase
("<persona> is connecting to the EA Servers…") — verified live, not a cached
session (the displayed persona "fun" comes from our GetProfile).
Root cause of the invariant loading-screen crash: get_config() omitted the
PROGRESSIVE_INSTALLATION and PROGRESSIVE_INSTALLATION_EVENT services (Name="PI").
FIFA builds its service registry from GetConfig and resolves that handle during
online-init; the missing service left a null handle it dereferenced at
FIFA23.exe+0x133dfc5 (mov rax,[r13+0x18], r13=NULL) ~2s after LSX — identical
across every prior run. Found via FIFA's own CrashReport_*.json (stable RIP) +
diffing anadius64.dll's service-registration table against ours.
Also in this change:
- process_frame(): handle FIFA's pipelined (batched) LSX messages per read,
eliminating the ~15s handshake hang.
- Real anadius values (RE'd from anadius64.dll + anadius.cfg): PersonaId/UserId/
persona, locale list, GetGameInfo fixed `GameInfo="<value>"` attribute,
GetAllGameInfo 14-attr schema, GetSetting `Setting=` attribute.
- IsProgressiveInstallationAvailable served from sender="PI".
- docs/connection-gate-findings.md: full RE trail; relocate stale openfut-hook
copy under docs/ (canonical hook lives in openfut-launcher).
Next gate: Blaze/online (M2), ridden over ProtoSSL in-process.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+47
-10
@@ -1,19 +1,56 @@
|
||||
use std::sync::Arc;
|
||||
use std::{path::Path, sync::Arc};
|
||||
use tokio_rustls::TlsAcceptor;
|
||||
|
||||
/// Generate a self-signed certificate covering localhost and EA FUT hostnames.
|
||||
/// Returns (cert_pem, key_pem) as byte vectors.
|
||||
/// Load a previously persisted cert/key pair, or generate and save a new one.
|
||||
///
|
||||
/// For FIFA 23 to connect, the cert must be installed as a trusted CA in the OS
|
||||
/// trust store, OR certificate validation must be disabled in the game binary.
|
||||
/// Reusing the same cert across restarts means clients only need to trust it once.
|
||||
pub fn load_or_generate_cert(cert_path: &Path, key_path: &Path) -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||
if cert_path.exists() && key_path.exists() {
|
||||
let cert_pem = std::fs::read(cert_path)?;
|
||||
let key_pem = std::fs::read(key_path)?;
|
||||
tracing::info!("Loaded existing TLS cert from {:?}", cert_path);
|
||||
return Ok((cert_pem, key_pem));
|
||||
}
|
||||
|
||||
let (cert_pem, key_pem) = generate_self_signed_cert()?;
|
||||
if let Some(parent) = cert_path.parent() {
|
||||
std::fs::create_dir_all(parent)?;
|
||||
}
|
||||
std::fs::write(cert_path, &cert_pem)?;
|
||||
std::fs::write(key_path, &key_pem)?;
|
||||
tracing::info!("Generated new TLS cert, saved to {:?}", cert_path);
|
||||
Ok((cert_pem, key_pem))
|
||||
}
|
||||
|
||||
/// Generate a self-signed certificate covering EA FUT hostnames.
|
||||
/// CN is set to `fut.ea.com` so ProtoSSL's CN hostname check passes.
|
||||
/// SANs include wildcard entries for all `*.ea.com` and `*.easports.com` subdomains
|
||||
/// so connections to any EA subdomain are covered.
|
||||
pub fn generate_self_signed_cert() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||
let subject_alt_names = vec![
|
||||
"localhost".to_string(),
|
||||
"127.0.0.1".to_string(),
|
||||
use rcgen::{Certificate, CertificateParams, DistinguishedName, DnType, SanType};
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
let mut params = CertificateParams::new(vec![
|
||||
"fut.ea.com".to_string(),
|
||||
"utas.mob.v4.fut.ea.com".to_string(),
|
||||
];
|
||||
let cert = rcgen::generate_simple_self_signed(subject_alt_names)?;
|
||||
"accounts.ea.com".to_string(),
|
||||
"pin.data.ea.com".to_string(),
|
||||
"gateway.ea.com".to_string(),
|
||||
"localhost".to_string(),
|
||||
]);
|
||||
|
||||
// Wildcard SANs cover every EA subdomain the game might contact
|
||||
params.subject_alt_names.push(SanType::DnsName("*.ea.com".to_string()));
|
||||
params.subject_alt_names.push(SanType::DnsName("*.easports.com".to_string()));
|
||||
params.subject_alt_names.push(SanType::DnsName("*.ugc.footapi.com".to_string()));
|
||||
params.subject_alt_names.push(SanType::IpAddress(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))));
|
||||
|
||||
// CN must match the primary hostname so ProtoSSL's CN check passes
|
||||
let mut dn = DistinguishedName::new();
|
||||
dn.push(DnType::CommonName, "fut.ea.com");
|
||||
params.distinguished_name = dn;
|
||||
|
||||
let cert = Certificate::from_params(params)?;
|
||||
let cert_pem = cert.serialize_pem()?.into_bytes();
|
||||
let key_pem = cert.serialize_private_key_pem().into_bytes();
|
||||
Ok((cert_pem, key_pem))
|
||||
|
||||
Reference in New Issue
Block a user