# Utilisation de game-realtime-webtransport-lib Ce guide décrit le chemin natif fiable actuellement exposé par `game-realtime-webtransport-lib`. Il ne décrit ni gameplay, ni protocole wire métier, ni datagrams. ## Serveur natif Créer d'abord l'identité TLS et le listener : ```rust let identity = match game_realtime_webtransport_lib::WebTransportServerIdentity::generate_loopback() { Ok(value) => value, Err(error) => return Err(error), }; let config = game_realtime_webtransport_lib::WebTransportServerConfig::new( std::net::SocketAddr::from(([127, 0, 0, 1], 4433)), identity, ); let mut listener = match game_realtime_webtransport_lib::WebTransportListener::bind(config) { Ok(value) => value, Err(error) => return Err(error), }; let session = match listener.accept().await { Ok(value) => value, Err(error) => return Err(error), }; let connection = match session.accept_primary_connection().await { Ok(value) => value, Err(error) => return Err(error), }; ``` `open_primary_connection()` écrit l'en-tête WebTransport requis pour identifier le stream avant de retourner. Le serveur peut donc attendre `accept_primary_connection()` puis commencer les échanges applicatifs ; aucune frame artificielle n'est nécessaire pour rendre le stream visible. ## Client natif Le client doit connaître le SHA-256 exact du certificat serveur : ```rust let config = match game_realtime_webtransport_lib::WebTransportClientConfig::new( "https://127.0.0.1:4433/game", certificate_hash, ) { Ok(value) => value, Err(error) => return Err(error), }; let session = match game_realtime_webtransport_lib::connect(&config).await { Ok(value) => value, Err(error) => return Err(error), }; let connection = match session.open_primary_connection().await { Ok(value) => value, Err(error) => return Err(error), }; ``` Le pinning est obligatoire dans cette API native ; il n'existe pas de variante qui désactive globalement la vérification TLS. ## Contrat realtime Une fois le stream primaire sélectionné, utiliser uniquement les traits de `game-realtime-transport-lib` : ```rust let (mut sender, mut receiver) = game_realtime_transport_lib::RealtimeConnection::split(connection); let message = game_realtime_transport_lib::TransportMessage::new(vec![1, 2, 3, 4]); if let Err(error) = game_realtime_transport_lib::RealtimeSender::send(&mut sender, message).await { return Err(error); } let received = match game_realtime_transport_lib::RealtimeReceiver::receive(&mut receiver).await { Ok(value) => value, Err(error) => return Err(error), }; if let Err(error) = game_realtime_transport_lib::RealtimeSender::close(&mut sender).await { return Err(error); } ``` Le backend encode chaque `TransportMessage` sous la forme `u32` big-endian + payload. Le consommateur ne doit pas reproduire ce framing lui-même. ## Fermeture actuelle `RealtimeSender::close()` termine proprement la direction d'émission du stream primaire. Le pair observe ensuite `TransportReceive::Closed` lorsqu'il atteint le FIN après les messages déjà écrits. La fermeture de session complète, les resets, les aborts, les timeouts et les cas d'annulation appartiennent à la tranche de robustesse suivante et ne doivent pas être simulés par le consommateur.