0. Résumé exécutif
Le Source Exchange est un mécanisme historique de découverte pair-à-pair qui complète :
serveurs eD2K
Kad
sources passives
liens / sources explicites
Le principe est ancien : le document communautaire edonkey-protocol.txt de 2002 décrit déjà :
0x81 eMule Sources request
0x82 eMule Sources answer
avec, par source :
client IP/ID
client port
server IP
server port
La branche moderne conserve cette compatibilité sous le nom SX1 tout en ajoutant SX2 :
OP_REQUESTSOURCES2
OP_ANSWERSOURCES2
SOURCEEXCHANGE2_VERSION = 4
SX2 n’est pas « le format v2 ».
Il s’agit d’un mécanisme de négociation pouvant transporter aujourd’hui le format de source v1 à v4.
La branche étudiée possède déjà plusieurs défenses solides :
temporisation par client et par fichier
politique dépendant de la rareté
soft source limit
version connue
taille exacte du paquet
IsGoodIP
IPFilter
ban list
CanAddSource
DeadSourceList
compatibilité crypt layer
dédoublonnage
A4AF
Mais le Dossier 08 met au jour deux limites architecturales intéressantes.
Découverte D08-A — la provenance SX précise est perdue
Au moment de parser une réponse, eMule connaît :
provider = le client qui a envoyé le paquet
mais les nouvelles sources sont ensuite seulement marquées :
SF_SOURCE_EXCHANGELe pClient fournisseur n’est pas conservé comme provenance durable de la source.
Conséquence :
on sait QU'UNE source vient de SX
mais plus QUI nous l'a donnée
Il devient donc impossible, avec le modèle actuel seul, de calculer a posteriori :
provider X
→ 100 sources annoncées
→ 73 nouvelles
→ 41 jointes
→ 25 ayant confirmé le fichier
→ 12 ayant transféré
Le Dossier 05 avait déjà proposé Source Exchange Quality Metrics.
Le Dossier 08 montre maintenant où brancher cette idée.
Découverte D08-B — pas de corrélation forte request/answer
Le vieux protocole SX n’a pas de Request ID.
Dans le chemin OP_ANSWERSOURCES / OP_ANSWERSOURCES2 inspecté, la réponse est acceptée si notamment :
handshake terminé
hash correspondant à un fichier téléchargé
format SX valide
Il n’apparaît pas de contrôle strict :
« cette réponse correspond exactement
à une demande SX encore pending »
EXPECTED
LATE
UNSOLICITED
Aucun blocage immédiat n’est recommandé.
Décision de ce dossier
Ne pas réécrire SX.
Ne pas accélérer globalement les reasks.
Ne pas porter aveuglément les vieux Source Cache / Save Load Sources.
Première expérimentation :
SX Provider Provenance + Quality Metrics, en shadow telemetry uniquement.
Puis, si les mesures sont concluantes :
provider quality
→ tie-break pour choisir quel pair interroger
→ surtout en Tail Source Wakeup / SOURCE_LIMITED
sans toucher au wire protocol.
1. Racine historique : SX1
Le protocole communautaire eDonkey/eMule de 2002 décrit dans ses extensions eMule :
<eMule Sources request> ::= 0x81 <File hash>
<eMule Sources answer> ::= 0x82
<File hash>
<2 Byte len>
[len](
<client.ip>
<2 client.port>
<4 server.ip>
<2 server.port>
)
Ce document est historique et reverse-engineered/communautaire, pas une norme officielle.
Mais il fournit une preuve directe que Source Exchange existe très tôt dans l’histoire d’eMule.
2. Pourquoi SX est différent des serveurs et de Kad
Serveur :
index centralisé sur le serveur connecté
Kad :
index distribué selon le DHT
Source Exchange :
connaissance locale d'un pair déjà lié au fichier
Chaque mécanisme a donc une surface d’échec différente.
SX est particulièrement contextuel :
je demande à quelqu'un déjà impliqué dans le fichier
mais aussi particulièrement subjectif :
je ne reçois que ce que ce pair veut / peut me raconter
3. Évolution des opcodes
Branche étudiée :
OP_REQUESTSOURCES 0x81 // deprecated
OP_ANSWERSOURCES 0x82 // deprecated
OP_REQUESTSOURCES2 0x83
OP_ANSWERSOURCES2 0x84Important :
deprecated
≠
supprimé
SX1 reste traité pour compatibilité.
4. Capability negotiation
Deux notions coexistent historiquement.
SX1 version
Une version SX1 est annoncée dans les options eMule historiques.
Elle décrit le format de source que le client sait manipuler.
Support SX2
Une capacité séparée annonce :
SupportsSourceExchange2
SX2 permet alors au demandeur d’expliciter :
version maximale désirée
options
Le répondant choisit :
min(requested_version, SOURCEEXCHANGE2_VERSION)5. VERSION actuelle du contenu
Dans la branche inspectée :
SOURCEEXCHANGE2_VERSION = 4Le même numéro 4 apparaît dans l’implémentation aMule inspectée.
Cela fournit une corroboration indépendante du format historique moderne.
6. SX2 request : options réservées
Le client envoie actuellement :
RequestedVersion = 4
Options = 0
Le répondant possède un paramètre nRequestedOptions, mais la branche ne définit aucun comportement utile pour des bits non nuls.
Elle journalise les options inconnues.
7. Nuance de documentation : ordre du paquet SX2
Le code d’émission séparée inspecté écrit :
Version
Options
FileHash
Le code aMule d’émission fait de même.
Dans les multipackets, le contexte fichier est déjà porté par l’enveloppe et le sous-opcode SX2 ajoute :
Version
Options
Certaines anciennes annotations d’opcodes sont moins explicites et peuvent suggérer un autre ordre.
Règle documentaire
ne pas prendre le commentaire court d'opcodes.h
comme spécification wire normative
Toujours vérifier :
writer
+
reader
+
implémentation indépendante / capture
avant de publier un layout octet par octet.
8. Réponse SX2
CreateSrcInfoPacket() écrit :
Version réellement utilisée
FileHash
Count
Sources...
Le récepteur lit explicitement la version de la réponse avant le FileHash.
SX1 n’a pas ce préfixe de version explicite dans la réponse.
9. Format v1
Par source :
ID/IP 4
ClientPort 2
ServerIP 4
ServerPort 2
----------------
12 octets
C’est le format décrit par le document historique.
10. Format v2
Ajout :
UserHash 16 octets
Taille :
28 octets/source
Le UserHash reçu reste une assertion faite par le fournisseur SX au sujet d’un tiers.
Il ne faut pas lui donner le statut d’un SecureIdent validé.
11. Format v3
Le nombre d’octets reste comparable à v2.
Le changement important est l’interprétation de l’ID :
Hybrid ID
au lieu de l’ancienne représentation IP directe.
Le parseur traite donc l’endianness / conversion différemment suivant la version.
12. Format v4
Ajout d’un octet d’options de connexion :
bit 0 crypt layer supported
bit 1 crypt layer requested
bit 2 crypt layer required
autres bits réservés
Dans le code d’envoi inspecté, le Direct UDP Callback n’est pas publié dans cet octet.
Conséquence
Ne pas documenter v4 comme contenant toute la connectivité moderne possible.
Il contient ce que le writer met réellement.
13. SX2 ≠ v2
SX generation :
SX1 / SX2
source record version :
v1 / v2 / v3 / v4
Toujours séparer les deux dans nos docs et logs.
Proposition de champs :
sx_transport = 1 | 2
sx_record_version = 1..4
14. Quand une demande SX peut partir
IsSourceRequestAllowed() vérifie d’abord :
Extended Protocol disponible
ET
SX2 ou SX1 > 1
ET
source count sous le soft limit
Puis la rareté et les timers décident.
15. Constantes historiques
Branche étudiée :
SOURCECLIENTREASKS = 40 min
SOURCECLIENTREASKF = 5 min
RARE_FILE = 50
MINCOMMONPENALTY = 4
Ces constantes appartiennent à la politique locale.
Elles ne sont pas intrinsèques au format wire SX.
16. Très rare
Cas approximatif :
uSources <= RARE_FILE / 5
<= 10
La demande est facilitée.
Pour le fichier directement demandé au pair, la contrainte principale est le timer client.
Sens
Sur un fichier presque sans sources :
la découverte vaut plus
que l'économie de quelques paquets
17. Rare
Jusqu’à environ :
50 sources
la branche combine :
~40 min par client
~5 min par fichier
avec plusieurs nuances A4AF et « valid source count ».
18. Commun
Pour un fichier déjà riche en sources :
client timer × MINCOMMONPENALTY
file timer × MINCOMMONPENALTY
Ordres de grandeur :
160 min
20 min
Le mécanisme évite donc naturellement le broadcast social permanent.
19. Réponse à une demande distante
Le serveur TCP client-à-client applique lui aussi un délai.
Pour un partfile rare :
première demande
ou
> SOURCECLIENTREASKS
Pour un fichier non rare ou complet :
première demande
ou
> SOURCECLIENTREASKS * MINCOMMONPENALTY
Défense
Cela limite l’utilisation de notre client comme « oracle de sources » sollicité en boucle.
20. Séquence protocolaire préférée
Le code rappelle qu’un client devrait normalement suivre :
OP_REQUESTFILENAME
→ OP_SETREQFILEID
→ OP_REQUESTSOURCES
Pourquoi ?
Parce que cette séquence permet au répondant de connaître le Part Status du demandeur.
Sans cette information, le choix des sources est moins précis.
Le code indique alors qu’il pourra fournir un ensemble plus aléatoire.
21. Source selection côté réponse
CreateSrcInfoPacket() ne renvoie pas la totalité brute des clients connus.
La liste candidate provient de la liste d’upload associée au fichier.
Sont notamment exclus :
LowID
requester lui-même
client hors états d'upload utiles
22. Part-aware Source Exchange
Si la carte des parties du demandeur est disponible :
source candidate
↓
possède-t-elle au moins une partie
que le demandeur n'a pas ?
Si oui :
candidate utile
Si la source candidate ne fournit pas de Part Status exploitable :
elle peut tout de même être transmise
avec la philosophie historique :
send it and hope for the best
23. Lorsque le demandeur n’a pas de Part Status
La branche essaie alors de transmettre des sources ayant au moins une partie complète.
Si le statut du candidat est lui-même inconnu :
il peut encore être envoyé
Cela conserve la découvrabilité au prix d’une précision moindre.
24. Pourquoi cette tolérance est importante
Règle trop stricte :
absence de Part Status
→ ne jamais transmettre
risquerait de pénaliser :
anciens clients
clients partiellement compatibles
fichiers rares
Le protocole historique privilégie donc souvent :
interopérabilité
avant certitude
25. Sources LowID
Le writer SX classique exclut les sources LowID.
Cela évite de diffuser des contacts qui ne sont pas directement joignables comme un HighID classique et dont la joignabilité dépend d’un serveur, Buddy ou mécanisme de callback.
26. Limite de réponse
Le compteur est incrémenté puis testé avec :
if (nCount > 500)
break;
Donc la borne réelle peut atteindre :
501
C’est probablement un petit artefact historique.
Statut
PAS IMPORTANT
Ne pas modifier pour « faire propre » sans nécessité : cela pourrait seulement créer des différences inutiles.
27. Compression
Si le paquet de réponse dépasse environ :
354 octets
il peut être compressé.
Le Source Exchange a donc déjà une optimisation d’overhead.
28. Réception SX1 : inférer le format par la taille
SX1 ne porte pas dans le paquet de réponse une version de record explicite équivalente à SX2.
AddClientSources() utilise donc :
nCount
+
taille restante exacte
+
version SX annoncée par le client
pour décider si le contenu correspond à v1, v2/v3 ou v4.
29. Défense structurelle importante
Le commentaire historique du parseur explique explicitement que ce contrôle évite une probabilité plus élevée de :
wrong source data
wrong userhashes
duplicate sources
Si :
count × record_size
!=
bytes restants
le paquet est rejeté.
30. Réception SX2
Pour SX2 :
version explicite
Le parser refuse :
version 0
version > SOURCEEXCHANGE2_VERSION
puis applique lui aussi une vérification de taille cohérente avec le format.
31. Filtrage d’entrée
Pour chaque source HighID reçue :
IsGoodIP()
IPFilter
ban list
Puis :
CanAddSource()
vérifie notamment certains cas « nous-mêmes » et les impossibilités LowID↔︎LowID.
32. Limite maximale du fichier
Même un paquet entièrement valide ne peut pas forcer l’ajout indéfini de sources.
Le parseur s’arrête lorsque :
GetMaxSources() <= GetSourceCount()
Cette borne protège :
mémoire
connexions
overhead
33. Après le parseur : CheckAndAddSource()
Le candidat traverse encore CDownloadQueue::CheckAndAddSource().
Le code rejette notamment :
notre propre UserHash
DeadSourceList globale
DeadSourceList du fichier
incompatibilité CryptLayer
doublon
et fusionne avec les clients déjà connus.
34. Dédoublonnage inter-fichiers
Si le même pair existe déjà pour un autre fichier :
AddRequestForAnotherFile()
peut l’associer au nouveau téléchargement.
C’est l’une des portes d’entrée d’A4AF.
Conséquence
Un paquet SX peut modifier :
non seulement srclist
mais aussi la topologie A4AF
du Download Manager.
35. Debug historique : « potential wrong source »
CheckAndAddSource() contient un commentaire/debug particulièrement intéressant.
Il reconnaît le cas où :
un pair nous envoie une source
pour le mauvais fichier
MAIS
nous téléchargeons aussi
le fichier auquel cette source appartient réellement
Le merge d’un client déjà connu peut alors devenir délicat.
Leçon
Le code lui-même reconnaît implicitement :
association SX source ↔ fichier
= information distante potentiellement erronée
37. Découverte centrale : pClient est disponible puis perdu
AddClientSources(..., const CUpDownClient* pClient) reçoit bien le client ayant fourni la réponse.
Dans la branche eMule inspectée, cette information sert surtout au contexte/log.
Dans aMule, le paramètre correspondant apparaît même explicitement ignoré dans la signature inspectée.
La nouvelle source reçoit ensuite :
SetSourceFrom(SF_SOURCE_EXCHANGE)mais pas :
SetSourceProvider(provider)
Conclusion
Le moteur n’est pas structuré pour répondre à :
« qui nous a appris cette source ? »
après l’ajout.
38. Ce que cela empêche
Impossible sans instrumentation supplémentaire de construire proprement :
Provider A
announced
accepted
duplicates
unreachable
file-confirmed
useful
bytes transferred
verified bytes
Provider B
...
Une future « réputation SX » ne peut donc pas être ajoutée correctement en regardant seulement les CUpDownClient existants.
Il faut conserver la provenance dès le parsing.
39. Trust Model
Dossier 05 :
SX entry = REMOTE_CLAIM
La progression proposée est :
ANNOUNCED
↓
STRUCTURAL_VALID
↓
ADMITTED
↓
CONTACTABLE
↓
FILE_CONFIRMED
↓
USEFUL_PARTS
↓
TRANSFERRED
↓
HASH_VERIFIED
Ne pas réduire cette chaîne à :
GOOD / BAD
40. UserHash reçu via SX
Version 2+ fournit :
UserHash
Mais le fournisseur dit :
« cette IP a ce UserHash »
Ce n’est pas l’équivalent :
« cette IP a prouvé cryptographiquement
la possession de sa clé SecureIdent »
41. Crypt options reçues via SX v4
Même logique :
SupportsCryptLayer
RequestsCryptLayer
RequiresCryptLayer
sont annoncés par un tiers.
Ils sont nécessaires pour décider si la connexion est plausible.
Mais ils doivent pouvoir être corrigés par les informations reçues directement du client.
Trust
initial = SX_CLAIM
direct hello = DIRECT_CLAIM
successful encrypted connection = LOCAL_OBSERVED
42. Pollution SX : catégories
Ne pas tout appeler « fake source ».
Séparer :
STALE
source autrefois vraie, maintenant morte
DUPLICATE
source déjà connue
UNREACHABLE
adresse techniquement inaccessible
WRONG_FILE
pair joignable mais ne confirme pas ce fichier
MALFORMED
paquet ou record structurellement invalide
FILTERED
IPFilter / ban / règles locales
USELESS_PARTS
source valide mais aucune partie utile
USEFUL
source réellement exploitable
Cette taxonomie est cruciale pour éviter les faux positifs.
43. Une source morte n’est pas une fraude
Le vieillissement du réseau rend certaines annonces obsolètes sans faute du fournisseur.
Facteurs :
DHCP / IP dynamique
déconnexion
redémarrage
changement de port
VPN
changement de serveur
suppression du fichier
Règle
STALE_RATE
ne doit pas être assimilé directement
à MALICIOUS_RATE
44. Métrique fournisseur minimale
Proposition :
SXProviderStats
packets_received
records_announced
records_valid_structure
records_invalid_structure
records_admitted
records_duplicate
records_filtered
records_deadsource
connect_attempted
connect_success
file_confirmed
useful_parts_confirmed
payload_received
payload_hash_valid
Pas besoin d’un score composite dans la V1.
45. Échantillon et confiance statistique
Un fournisseur ayant :
1 source annoncée
1 source morte
ne doit pas être classé comme catastrophique.
Conserver :
sample_count
first_observed
last_observed
et n’utiliser la métrique pour une décision qu’après un minimum d’observations.
Le seuil exact doit venir des mesures, pas être inventé maintenant.
46. Comparaison au contexte global
La qualité brute dépend de l’état du réseau.
Exemple :
pendant 1 h
taux connectable global = 15 %
provider A = 18 %
provider B = 14 %
B est proche de la normale.
Autre cas :
global = 20 %
provider B = 0,5 %
sur 400 annonces
L’écart devient intéressant.
47. Multi-source corroboration
Une source annoncée par plusieurs fournisseurs indépendants est plus intéressante qu’une source annoncée une seule fois.
Sans considérer cela comme une preuve absolue :
Provider A → source X
Provider B → source X
Provider C → source X
peut augmenter :
discovery confidence
Attention
Une information fausse peut elle aussi être recopiée.
Donc :
corroborated
≠
verified
48. Source attribution graph
Structure locale possible :
FileHash
|
+-- Candidate Source X
| |
| +-- provider A
| +-- provider B
|
+-- Candidate Source Y
|
+-- provider C
Après contact :
X → file confirmed
Y → wrong file
Les fournisseurs A/B et C obtiennent alors une observation de qualité différente.
49. Confidentialité
Ne pas transformer ce mécanisme en base durable de pairs.
Par défaut :
provider_session_id pseudonymisé
pas d'IP persistante longue durée
pas de UserHash complet dans le log standard
TTL des métriques
agrégation
Debug détaillé seulement sur activation explicite.
Cohérent avec Dossier 05.
50. Réponses SX non corrélées : observation de code
Le handler OP_ANSWERSOURCES / OP_ANSWERSOURCES2 vérifie :
handshake
FileHash présent dans DownloadQueue
format
puis appelle AddClientSources().
Dans le chemin inspecté, il n’y a pas de :
request nonce
request id
strict pending SX answer flag
Le protocole ancien n’en définit pas.
Hypothèse à mesurer
Un pair connecté pourrait donc fournir une réponse SX pour un fichier que nous téléchargeons sans qu’une demande immédiatement associée soit visible.
Ne pas transformer cette observation en accusation.
51. Pourquoi ne pas simplement rejeter toute réponse « unsolicited »
Plusieurs risques de compatibilité :
réponse retardée
état local nettoyé entre-temps
multipacket
client ancien
différences d'implémentation
Palier D08-SX1
Telemetry seulement :
answer_expected
answer_late
answer_no_recent_request
Aucune modification du comportement.
52. Si les réponses unsolicited existent réellement
Étapes possibles, dans cet ordre :
1. mesurer volume
2. mesurer utilité
3. distinguer legacy / client moderne
4. limiter le budget de traitement si nécessaire
5. seulement ensuite envisager drop
La protection la moins agressive pourrait être :
rate limit par pair
avant un rejet absolu.
53. Capability Trust SX
Dossier 05 proposait :
CLAIMED_SX4
OBSERVED_VALID_SX4
OBSERVED_BROKEN_SX4
D08 précise l’implémentation.
Événements :
SX_CAPABILITY_CLAIM
SX_PACKET_VALID
SX_PACKET_BAD_VERSION
SX_PACKET_BAD_SIZE
SX_PACKET_UNKNOWN_OPTIONS
Réaction future :
fonctionnalité SX dégradée pour ce pair
plutôt que :
ban global du pair
si le problème ne concerne que SX.
54. Parser robustness
Tests défensifs prioritaires :
count = 0
count max
count × size overflow
troncature 1 octet
octets en trop
version 0
version 5+
v2 sans UserHash complet
v4 sans options byte
invalid IP
lowID edge cases
Objectif :
pas de crash
pas d'allocation abusive
pas de source partiellement initialisée
55. Fuzzing local
Dossier 05 proposait déjà SX1/SX2 comme cible.
D08 permet d’être précis :
AddClientSources SX1
AddClientSources SX2
OP_REQUESTSOURCES parser
OP_ANSWERSOURCES parser
OP_REQUESTSOURCES2 parser
OP_ANSWERSOURCES2 parser
Sans émettre un seul paquet vers Internet.
56. A4AF : relation structurelle
Lorsqu’une source SX est déjà connue sur un autre fichier :
CheckAndAddSource
→ AddRequestForAnotherFile
→ A4AF list
Le Source Exchange nourrit donc naturellement A4AF.
57. SX et choix du fichier
IsSourceRequestAllowed(partfile, sourceExchangeCheck) est aussi utilisé lors des décisions de swap.
Le moteur peut préférer un fichier offrant une meilleure opportunité de Source Exchange.
Le Dossier 05 a déjà identifié un autre facteur dans cette zone :
Remote Queue Rank
qui est une donnée non vérifiable fournie par le pair.
D08
Ne pas fusionner :
Remote QR trust
SX provider quality
Ce sont deux dimensions différentes.
58. Refactor futur : raison de swap explicite
L’instrumentation proposée en D05 :
[A4AF_SWAP_DECISION]
doit ajouter :
sx_need_from
sx_need_to
sx_provider_quality_if_known
source_deficit_from
source_deficit_to
Ainsi nous verrons si SX influence encore fortement les swaps en pratique.
59. AllowSwapForSourceExchange()
La branche contient une protection simple :
30 secondes
entre certains swaps motivés par Source Exchange.
Cette hystérésis évite un basculement trop rapide d’un fichier à l’autre.
60. Endgame E6bis : SOURCE_LIMITED
Dossier 06 a introduit un état où :
il reste peu de sources réellement capables
et où multiplier les races ne peut plus créer de capacité réseau.
C’est exactement le point de jonction avec D08.
61. Tail Source Wakeup × SX
Principe actuel documenté :
si trop peu de sources finales sont actives
→ réveiller A4AF / Source Exchange
D08 propose de rendre ce réveil plus sélectif.
Pas :
reask plus vite partout
mais :
parmi les pairs déjà éligibles
→ choisir les meilleurs fournisseurs SX observés
62. Tie-break uniquement en première version
Exemple :
A éligible
B éligible
mêmes contraintes protocole
même rareté
même timers
Si :
A provider-quality suffisamment documentée > B
alors :
demander A avant B
Aucune nouvelle demande n’est créée.
On change uniquement l’ordre.
63. Exception rare-file
Si :
sources <= 10
la diversité doit prendre le dessus.
Même un provider peu performant peut détenir :
la seule nouvelle source utile
Politique possible
quality tie-break fort sur fichier courant
quality tie-break faible sur fichier rare
quality jamais exclusion dure sur fichier très rare
À valider par simulation/telemetry.
64. Source completeness et demande SX
IsSourceRequestAllowed() traite différemment les sources complètes et incomplètes dans les branches rare/très rare.
Une source incomplète participe elle-même au graphe actif de téléchargement et a souvent davantage intérêt à connaître des sources.
Une source complète peut toujours être utile, mais la politique la sollicite moins agressivement.
À mesurer
Ne pas supposer qu’en 2026 :
incomplete peer
=
meilleur provider
La telemetry pourra le confirmer ou non.
65. Quality metrics par type de pair
Axes d’analyse :
complete vs incomplete
HighID
client software
SX1 vs SX2
record version
SecureIdent verified vs unavailable
Important
Ces dimensions servent à comprendre le réseau.
Elles ne doivent pas devenir :
« tel logiciel est mauvais »
sans preuve comportementale.
66. Source Cache historique
Corpus Mods :
Off+
Source cache
Save Load Source
Optimization Source Exchange
StulleMule / MorphXT heritage
Save/Load Sources
Load saved Sources
Timer for ReAsk File Sources
Reask after IP change
Source Cache
Cela montre une préoccupation historique réelle :
ne pas perdre trop vite
la connaissance de sources coûteuses à découvrir
67. Mais le nom de fonction ne suffit pas
Nous n’avons pas encore, pour toutes ces variantes :
algorithme exact
TTL exact
format disque
critères de validation
interaction DeadSource
interaction IP change
Statut
ARCHIVE / PISTE
PAS PORTAGE IMMÉDIAT
68. Risque d’un cache persistant
Un cache disque peut réinjecter :
IP réattribuées
ports anciens
LowID devenus invalides
UserHash associé à une ancienne adresse
client n'ayant plus le fichier
Le Source Exchange lui-même possède déjà un problème de vieillissement.
Un cache persistant peut amplifier ce vieillissement.
69. Mesure avant Source Cache
A. redémarrage sans cache
B. temps jusqu'à N sources utiles
C. sources serveur
D. sources Kad
E. sources SX
F. premier transfert utile
Puis seulement comparer à une branche expérimentale de cache.
Métriques :
time_to_first_source
time_to_first_transfer
time_to_10_valid_sources
stale_ratio
wrong_file_ratio
connection_attempts_wasted
70. Cache court possible
Si l’intérêt est démontré :
file hash
endpoint
last confirmed time
discovery channel
optional provider evidence
TTL
avec invalidation agressive.
Pas :
source éternelle
71. Reask after IP change
Les vieux Mods mentionnent explicitement :
Reask after IP change
L’idée est logique :
notre identité réseau a changé
→ certaines relations de joignabilité
peuvent changer
nouveau HighID
reconnexion serveur
nouvelle IP publique
Kad reconnect
avant de porter du code ancien.
72. Source provider identity
Pour conserver une provenance, quelles données utiliser ?
Pas uniquement :
IP
Dossier 07 a déjà montré les limites :
NAT
CGNAT
VPN
IP dynamique
73. Provider session identity
Première version recommandée :
provider_session_id
identifiant local éphémère associé à l’instance CUpDownClient.
Optionnellement :
secure_ident_verified = yes/no
Ne pas persister la clé ou le UserHash complet dans les logs standards.
74. Plusieurs providers pour une même source
Ne pas stocker un seul :
source.provider
car une source peut être annoncée par plusieurs pairs.
Préférer :
CandidateSource
providers[]
ou une table séparée d’événements de découverte.
75. Donnée de provenance utile même après déduplication
Aujourd’hui :
source déjà connue
→ pas de nouvelle source
Mais pour la qualité fournisseur :
le provider l'a quand même annoncée
Il faut donc enregistrer l’événement avant que CheckAndAddSource() ne détruise le candidat duplicate.
Sinon on perd l’information statistique.
76. Admission reason
Le bool historique de CheckAndAddSource() est trop pauvre pour la telemetry.
Il confond plusieurs raisons de false.
ADDED_NEW
ADDED_A4AF
DUPLICATE
SELF
DEAD_SOURCE
CRYPT_INCOMPATIBLE
BAD_IP
IP_FILTERED
BANNED
UNREACHABLE_LOWID
MAX_SOURCE_LIMIT
OTHER_REJECT
Attention
Faire cela sans changer les décisions existantes dans le premier palier.
77. Wrong-file confirmation
Une source SX pour Fichier A est vraiment confirmée lorsque l’échange direct montre qu’elle sert Fichier A.
Événements possibles :
FILE_INFO_OK
FILE_STATUS_OK
FILENAME_ANSWER
hash / FileIdentifier coherent
Le détail exact dépend de la génération du protocole.
Qualité
provider said A
direct peer confirms A
→ provider claim corroborated
78. NNP ne signifie pas « mauvaise source »
DS_NONEEDEDPARTS peut vouloir dire :
le pair possède bien le fichier
mais aucune partie qu'il a
ne nous manque actuellement
Il ne faut donc pas compter :
NNP
comme :
wrong-file
Métrique distincte :
file_confirmed=yes
useful_now=no
79. Queue Full ne signifie pas « source inutile »
Même chose :
remote queue full
ou rang lointain :
source réellement liée au fichier
mais pas immédiatement productive
Un provider SX peut donc être correct même si le transfert n’arrive jamais pendant notre fenêtre d’observation.
80. Hiérarchie de succès SX
Proposition :
L0 announced
L1 accepted
L2 endpoint contacted
L3 file confirmed
L4 useful parts
L5 payload
L6 hash-validated payload
Le niveau L3 est déjà un succès de découverte important.
Ne pas juger uniquement L5/L6.
81. Time decay
La qualité d’un provider doit vieillir.
Un client peut changer d’environnement.
Proposition conceptuelle :
observations récentes > observations anciennes
sans fixer encore de demi-vie.
Pourquoi
Éviter qu’un mauvais épisode datant de plusieurs mois définisse éternellement un pair.
82. Pas de sanction globale
Si un pair fournit régulièrement de mauvaises listes SX :
action domaine SX
exemples futurs :
moins souvent choisi comme provider
SX désactivé temporairement avec lui
budget d'annonces réduit
Pas automatiquement :
upload ban
IP ban
credit penalty
83. Quand une sanction plus forte devient légitime
Uniquement si d’autres mécanismes disposent de leurs propres preuves :
flood observable
paquets invalides répétés
SecureIdent conflict
corruption hash-attributed
Chaque domaine décide selon ses preuves.
Cohérent avec Trust Model.
84. SX flooding
Deux directions :
request flood
answer flood
Le serveur d’entrée possède déjà un throttling des requests reçues.
Le traitement des answers reçues doit être mesuré séparément.
Ne pas supposer que les protections sont symétriques.
85. Inbound budget possible
Si la telemetry montre des réponses SX excessives :
max records processed / peer / fenêtre
pourrait être une défense locale peu intrusive.
Mais elle doit préserver :
fichiers très rares
réponses normales volumineuses
legacy clients
Pas de seuil avant mesure.
87. Privacy and abuse resistance
Le graphe de provenance doit rester interne.
Ne jamais envoyer :
« provider X est mauvais »
aux autres clients.
Règle
local observations only
88. Pas de réputation globale partagée
Une réputation distribuée exigerait :
identités fortes
Sybil resistance
signatures
gestion des faux rapports
vieillissement
consensus
Ce serait un nouveau protocole complexe.
Aucun besoin n’est démontré.
89. Cross-check aMule
L’implémentation aMule inspectée confirme plusieurs éléments :
OP_REQUESTSOURCES / 2
version SX2
request version/options
formats v1-v4
sélection par Part Status
limite ~500
compression
contrôles taille/version
Cela renforce l’idée que ces comportements ne sont pas seulement un accident d’une branche eMule récente.
90. Divergences d’implémentation
Les lecteurs/parsers anciens ne sont pas toujours parfaitement symétriques ni parfaitement documentés.
Il faut donc conserver la règle :
eMule writer
eMule reader
aMule writer
aMule reader
Wireshark
captures
avant d’écrire une spécification wire définitive.
Le Dossier 08 est d’abord un audit de comportement, pas encore une RFC eMule.
101. Patch expérimental V1 proposé
Nom de travail :
SX Evidence by Akshaan — V1 Shadow
Aucun changement de comportement.
Hooks :
ListenSocket.cpp
answer receive
PartFile.cpp
AddClientSources parse/admission
DownloadQueue.cpp
CheckAndAdd outcome
DownloadClient.cpp
connect/file confirmation/transfer milestones
102. Structures V1
Minimal :
enum class ESXDiscoveryOutcome
{
Announced,
InvalidRecord,
Filtered,
Duplicate,
AddedNew,
AddedA4AF,
DeadSource,
ConnectFailed,
Connected,
FileConfirmed,
UsefulParts,
PayloadReceived
};103. Provider key
V1 :
runtime pointer/session id
+
optional SecureIdent state
Pas de persistance forte.
Le diagnostic peut calculer un ID pseudonymisé pour les logs.
104. Event example
[SX_EVIDENCE]
file=anon:8C12
provider=session:37
transport=SX2
record_version=4
announced=42
valid=40
filtered=3
duplicate=21
new=16
later:
connected=7
file_confirmed=6
useful=4
payload=3
106. Packet Quality
Mesures :
valid_version
valid_size
valid_count
unknown_options
parse_error
Cela évalue surtout :
compatibilité / comportement protocolaire
du provider.
107. Source Outcome
Mesures :
admitted
duplicate
deadsource
connected
file_confirmed
useful
Cela évalue :
qualité pratique de l'information
Le provider peut être protocolairement impeccable mais disposer d’informations anciennes.
108. Capability contradiction
Cas :
Hello : supports SX2
puis
SX2 systématiquement mal formé
Après répétition :
OBSERVED_BROKEN_SX2
Réaction future :
fallback SX1 si compatible
ou ne plus demander SX à ce pair
plutôt qu’un ban.
109. Unknown options
SX2 possède 16 bits réservés.
Si un client demande des options inconnues :
log
La branche répond tout de même selon son comportement connu.
110. Version future
Le parseur actuel rejette les formats qu’il ne sait pas dimensionner.
C’est raisonnable.
capability negotiation
documentation publique
aMule / autres clients
compatibilité de parsing
Pas d’extension privée cachée.
111. Source quality vs source priority
Ne pas confondre :
provider quality
avec :
priority de téléchargement
Une source découverte par un provider médiocre peut être excellente.
Chaque source doit être évaluée par ses propres interactions.
112. Provider quality vs credits
Ne pas utiliser la qualité SX pour :
crédits
upload queue score
friend slot
Ce serait une récompense non liée au service d’upload réel et facilement manipulable.
113. Provider quality vs admission
Première politique recommandée :
ne pas rejeter une source valide
uniquement parce que son provider a un faible rendement
Utiliser la qualité pour :
choisir le prochain provider à interroger
est beaucoup moins risqué.
114. Pourquoi le tie-break est élégant
Il ne change pas :
nombre maximal de requêtes
timers
packet format
source validation
Il améliore uniquement :
l'ordre de sélection
Donc faible risque d’interopérabilité.
115. Information gain
Une autre métrique possible :
new_unique_sources / announced_sources
Mais elle doit être contextualisée.
Sur un fichier mature :
faible information gain
est normal.
Sur un fichier rare :
une seule source nouvelle
peut être extrêmement précieuse.
116. Useful discovery value
Métrique plus intéressante :
confirmed_unique_source
×
rarity_weight
sans la transformer immédiatement en score de production.
Exemple :
1 source confirmée pour fichier à 2 sources
>
10 doublons confirmés sur fichier à 600 sources
Cette logique rejoint le scheduler historique basé sur la rareté.
117. Pas de machine learning nécessaire
Le problème est suffisamment structuré pour commencer avec :
compteurs
EWMA éventuelle
seuil minimum d’échantillon
tie-break
Un modèle opaque rendrait les décisions plus difficiles à expliquer.
mesure explicable
118. Source diversity
Quand plusieurs providers ont des qualités proches, favoriser parfois la diversité peut empêcher :
toujours interroger le même sous-groupe
et améliorer la découverte d’une composante différente du graphe.
Une petite randomisation contrôlée peut donc rester utile.
119. Ne pas centraliser le réseau autour de « bons providers »
Si tous les clients choisissaient toujours les mêmes pairs :
overhead concentré
moins de diversité
points chauds
Le but n’est pas de créer des « super nœuds SX ».
121. Statistiques utilisateur possibles
Vue avancée :
DÉCOUVERTE DES SOURCES
Serveurs 124
Kad 83
Source Exchange 217
Passives 18
SX
Annoncées 1 842
Nouvelles 311
Confirmées 126
Utiles 79
Pas besoin d’afficher :
« client X est mauvais »
122. Statistiques par fichier
Dans détails du fichier :
Sources actuelles 47
Découvertes par SX 18
Confirmées par SX 11
A4AF 7
Dernière réponse SX 4 min
Cela aiderait aussi à comprendre les fichiers rares.
123. Journal utilisateur
Éviter le bruit.
Seulement événements significatifs :
[Sources] Fichier X : 8 nouvelles sources découvertes via SX.
Les détails de provider restent dans un mode diagnostic.
124. Source freshness
Une future source evidence peut conserver :
first_seen
last_seen
last_connected
last_file_confirmed
sans nécessairement persister l’identité du provider.
Cela aiderait également le sujet Source Cache.
125. DeadSourceList comme signal
Une source reçue qui est déjà dans :
global DeadSourceList
file DeadSourceList
est un événement utile pour la qualité provider.
Mais avec nuance :
provider peut l'avoir apprise avant qu'elle meure
Donc poids faible et temporel.
126. IPFilter hit
Source annoncée sur une IP filtrée :
rejected-IPFilter
Cela dit quelque chose sur l’adéquation à notre politique locale, pas nécessairement sur la malveillance du provider.
Ne pas mélanger :
policy filtered
avec :
invalid source
127. Ban-list hit
Même prudence.
Provider peut annoncer un client déjà banni localement parce que :
il ne connaît pas notre ban
Ce n’est pas un mensonge en soi.
Métrique séparée.
128. SecureIdent provider
Si le provider a un SecureIdent validé :
nous savons mieux que la même identité
nous a fourni plusieurs listes
Cela améliore la continuité statistique dans la session.
Mais SecureIdent ne prouve pas :
que ses listes sont vraies
Il prouve l’identité, pas la qualité.
129. UserHash source
Lorsque le record SX contient un UserHash :
ne pas utiliser le seul fait qu'il correspond
à un client connu
comme preuve du fichier
La source peut être la bonne identité mais ne plus posséder le fichier.
130. Multi-channel corroboration
Source X reçue par :
SX
+
Kad
+
serveur
peut être marquée :
multi-channel discovered
C’est un bon signal de pertinence opérationnelle.
Mais la validation finale reste directe.
131. Exploiter le canal sans lui faire confiance
C’est probablement le meilleur résumé du Source Exchange :
utiliser l'information
rapidement
mais
ne pas la transformer
en privilège
avant observation
132. Roadmap proposée
D08-V1 — Provider provenance shadow
Ajouter l’événement de provenance.
Aucun changement de décision.
D08-V2 — Outcome correlation
Relier :
announced source
→ connect
→ file confirmation
→ useful state
D08-V3 — Provider selection tie-break
Seulement si les distributions montrent une différence exploitable.
D08-V4 — Tail Source Wakeup integration
Tester en SOURCE_LIMITED.
D08-V5 — Inbound answer budget
Seulement si unsolicited/flood réellement observé.
133. Critères de succès V1
V1 réussie si :
aucune différence de nombre de sources
aucune différence de paquet réseau
aucune différence de timing
aucun changement A4AF
faible overhead CPU/RAM
corrélation provider→source exploitable
134. Critères de succès V2
V2 doit pouvoir répondre :
Parmi 100 sources annoncées par SX :
combien étaient nouvelles ?
combien ont été jointes ?
combien ont confirmé le fichier ?
combien avaient des parties utiles ?
sans stocker inutilement les identités réseau au long cours.
135. Critères de succès V3
Comparer A/B :
historical provider selection
vs
quality tie-break
Même :
nombre de demandes SX
timers
soft source limit
Mesurer :
new confirmed sources / request
useful sources / request
connections wasted
136. Critères de succès Tail Source Wakeup
Sur fichiers E6bis réellement SOURCE_LIMITED :
temps jusqu'à nouvelle source utile
temps 99.x → 100
nombre de SX requests
redondance
CPU
Le gain doit être comparé à :
E6bis baseline
pas seulement eMule officiel.
137. Ce que nous ne devons pas porter maintenant
Source Cache ancien sans audit
Save Load Sources sans TTL moderne
boost SX agressif générique
Community Source Exchange propriétaires
blacklists de Mods
ban pour mauvais rendement SX
138. Ce que nous ne devons pas modifier
SX1 compatibility
SX2 v4 wire format
FileHash association
rare-file timers
soft source limits
part-aware filtering
A4AF semantics
sans preuve expérimentale claire.
139. Documentation publique
Pages possibles sur le site :
Source Exchange : le bouche-à-oreille d'eMule
SX1 vs SX2
Pourquoi une source peut être morte
Comment eMule évite le spam SX
A4AF : une source, plusieurs fichiers
La fiche SITE de ce dossier peut servir de base à la première.
141. Conclusion
Source Exchange est beaucoup plus mûr qu’une simple liste d’IP échangée entre pairs.
Il possède déjà :
compatibilité SX1
négociation SX2
formats v1-v4
throttling
rareté
soft limits
Part Status awareness
IP filtering
dédoublonnage
A4AF
compression
C’est une absence de mémoire explicite de provenance.
Le moteur reçoit :
Provider P
→ Source X
puis conserve essentiellement :
X vient de SOURCE_EXCHANGE
sans conserver :
P nous a annoncé X
Cette information manquante empêche d’évaluer la qualité réelle du canal par fournisseur.
C’est donc une amélioration intéressante parce qu’elle respecte les quatre contraintes qui reviennent dans tout notre travail :
compatible avec les clients existants
pas de nouveau wire protocol
mesurable avant activation
utile à Endgame sans le remplacer
La première implémentation doit rester purement observationnelle.
Ensuite seulement, si les données montrent des écarts significatifs entre providers, la qualité SX pourra devenir un tie-break local pour choisir à qui demander des sources — particulièrement quand E6bis détecte un vrai état SOURCE_LIMITED.
================================================================================================