fix(xmpp): corriger le timeout XMPP — TLS mode + timeouts de connexion/cleanup (#25) #26
Reference in New Issue
Block a user
Delete Branch "fix/xmpp-tls-timeout-25"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
Résolution du bug de production #25 — le canal XMPP ne parvenait pas à établir sa session : timeout 30 s puis erreur, nécessitant un Ctrl-C pour terminer le processus. Le serveur XMPP ne voyait aucune connexion depuis l'identité configurée.
Cause racine
use_tls=True(défaut) était interprété comme direct TLS (enable_direct_tls=True,enable_starttls=False), mais le port par défaut 5222 est conventionnellement le port STARTTLS. Le client envoyait un ClientHello TLS sur un port attendant un stream XMPP en clair → le serveur ne reconnaissait jamais l'identité → timeout.Causes secondaires : événement
connection_failedde Slixmpp non géré, pas de timeout surconnect_future, pas de timeout surdisconnect_futuredans lefinally.Corrections
Configuration (
settings.py)tls_mode: Literal["direct", "starttls", "disabled"](défaut"starttls") remplace le booléenuse_tls. Compatible avec le port 5222 par défaut.use_tlsconservé comme alias déprécié avecDeprecationWarning(True → direct,False → starttls).connect_timeout(15 s),cleanup_timeout(10 s) — distincts dutimeoutde session (30 s).tls_mode="disabled"uniquement.Canal XMPP (
channels/xmpp.py)match self.settings.tls_modepour configurerenable_direct_tls/enable_starttls.connection_failedde Slixmpp géré → échec rapide au lieu d'attendre le timeout de session.asyncio.wait_forsurconnect_future(anti-blocage DNS/TCP/TLS).asyncio.wait_forsurdisconnect_futuredans lefinally(anti-blocage cleanup).connect_future+session_futureviaasyncio.wait(FIRST_COMPLETED)pour détecterconnection_failedavant l'expiration duconnect_timeout._cancel_pending()idempotent).asyncio.CancelledErrorattrapé → retourFalse(contrat « never raises »).ClientXMPPconstruit dans letryavec guardclient is not Nonedans lefinally.redact_exception()passentextra_secrets=_secret_values(self.settings).Tests
FakeClientXMPPenrichi avec modesconnect(ok/pending/connection_failed) etdisconnect(ok/pending).connection_failed, cleanup bloqué,CancelledError, mappingtls_mode, fuite de secrets, backward compatuse_tls, validationconnect_timeout/cleanup_timeout.pronote_sync/channels/xmpp.py: 96 %.Documentation
.env.example:XMPP_TLS_MODE=starttls,XMPP_CONNECT_TIMEOUT=15,XMPP_CLEANUP_TIMEOUT=10.GUIDE_DEV_PYTHON.mdetREADME.LLM.mdmis à jour.Validation
ruff checkruff format --checkmypy(strict)banditpytestxmpp.pydetect-secretsMigration
La variable
XMPP_USE_TLSreste supportée mais dépréciée. Pour migrer :XMPP_USE_TLS=true→XMPP_TLS_MODE=direct(ou simplement supprimer la ligne pour utiliser le défautstarttls)XMPP_USE_TLS=false→XMPP_TLS_MODE=starttls(défaut, peut être supprimé)Closes #25