Geek++ · Dossier 08 / 25

Source Exchange SX1/SX2, qualité des sources et pollution

Étude technique publique · 5,909 mots · ≈ 26 min de lecture attentive

Étude intégraleSans réflexion CODEXSources & constantes conservées
Source Exchange
Vous
AliceBobClaireDavidÉric

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_EXCHANGE

Le 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   0x84

Important :

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 = 4

Le 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.

================================================================================================


Dossier 08 terminé

Source Exchange SX1/SX2, qualité des sources et pollution

← Dossier 07Dossier 09 →