0. Résumé exécutif
- des éléments strictement protocolaires et donc intouchables sans rupture de compatibilité ;
- des conventions communes entre clients ;
- une grande quantité de politique locale : temporisations, seuils, ordonnancement, dédoublonnage et choix du canal de découverte.
La piste prioritaire n’est pas de créer de nouveaux paquets réseau.
La piste prioritaire est de rendre la stratégie locale plus intelligente et plus observable tout en conservant les protocoles existants.
1. Périmètre analysé
Corpus utilisé :
- eDonkey Protocol v0.6 (2002)
- Overnet Protocol (2003)
- The eMule Protocol Specification (2005)
- eMule 0.50a
- eMule Community 0.72a
- aMule 3.x
- MLDonkey et son ancien wiki
- Wireshark
packet-edonkey - documentation officielle eMule
- documentation aMule
- papier Kademlia
Les références de lignes ci-dessous concernent les copies fournies dans le corpus.
2. Les cinq origines de sources d’eMule 0.72a
Dans :
srchybrid/ClientStateDefs.h:103-110
eMule définit :
SF_SERVER
SF_KADEMLIA
SF_SOURCE_EXCHANGE
SF_PASSIVE
SF_LINKL’interface reprend cette information dans :
DownloadListCtrl.cpp:468-486
Il s’agit donc bien d’une classification fonctionnelle utilisée par le programme.
3. Canal 1 — serveur eD2K connecté, en TCP
3.1 Racine historique
La spécification eDonkey 0.6 définit :
0x19 Get sources -> serveur
0x42 Found sources <- serveur
La demande contient le hash du fichier.
Le mécanisme existe donc dans le socle eDonkey, avant les extensions propres à eMule.
3.2 eMule 0.72a
Le test de programmation est dans :
PartFile.cpp:2339-2346
Conditions principales :
- aucune demande locale déjà en attente ;
- première recherche OU dernier appel vieux d’au moins
SERVERREASKTIME; - serveur eD2K connecté ;
- nombre de sources inférieur au seuil « soft » ;
- fichier non stoppé ;
- serveur capable de traiter les grandes tailles si le fichier est > 4 Gio.
Valeur :
Opcodes.h:66
SERVERREASKTIME = 15 minutesLe commentaire historique dit explicitement de ne pas réduire agressivement cette valeur.
3.3 Mise en file des requêtes
DownloadQueue.cpp:1318-1401
Les demandes ne sont pas envoyées immédiatement une par une.
eMule :
- place les fichiers dans une file locale ;
- choisit le fichier ayant attendu le plus longtemps, pondéré par la priorité ;
- regroupe jusqu’à 15 demandes dans une même trame TCP ;
- espace ensuite le prochain groupe.
Après un lot de 15, le code fixe :
m_dwNextTCPSrcReq = curTick + SEC2MS(15 * (16 + 4));soit 300 secondes / 5 minutes avant le prochain lot TCP.
Cela distingue deux notions :
- intervalle de re-demande d’un fichier : ~15 min ;
- débit de vidage de la file globale de requêtes : lots espacés.
3.4 Obfuscation
Si le serveur le supporte et que l’obfuscation est activée :
OP_GETSOURCES_OBFU
est utilisé à la place du OP_GETSOURCES historique.
Référence :
DownloadQueue.cpp:1372-1378
3.5 Réception
ServerSocket.cpp:366-379
Les réponses OP_FOUNDSOURCES et OP_FOUNDSOURCES_OBFU sont dirigées vers :
CPartFile::AddSources(...)
4. Canal 2 — autres serveurs eD2K, en UDP
4.1 Racine historique
eDonkey v0.6 documente :
0x9A UDP Get sources
0x9B UDP Found sources
Ce mécanisme permet de demander des sources à des serveurs autres que celui auquel le client est connecté.
4.2 eMule 0.72a
Cadence globale :
Opcodes.h:67
UDPSERVERREASKTIME = 30 minutesDéclenchement :
DownloadQueue.cpp:414-427
4.3 Seuil de sources
eMule ne fait une recherche UDP que si le fichier reste sous :
GetMaxSourcePerFileUDP()
Calcul :
PartFile.cpp:5316-5319
min(75 % de la limite du fichier, 50)Le 50 vient de :
Opcodes.h:98
MAX_SOURCES_FILE_UDP = 50C’est important : ce n’est pas la limite totale de sources du fichier. C’est un seuil à partir duquel eMule estime que les requêtes UDP serveur sont moins nécessaires.
4.4 Protection des serveurs
DownloadQueue.cpp:713-734
Quelques limites :
- taille de données utile visée : ~510 octets ;
- maximum 35 requêtes par serveur dans l’intervalle ;
- support d’un paquet
GETSOURCES2permettant d’inclure la taille du fichier et les grands fichiers.
Une fois 35 demandes atteintes, eMule fait tourner les fichiers et passe au serveur suivant.
5. Canal 3 — Kad
5.1 Déclenchement
PartFile.cpp:2320-2337
Kad est utilisé lorsque :
- le fichier est sous le seuil UDP de sources ;
- Kad est connecté ;
- eMule est connecté ;
- le fichier n’est pas stoppé ;
- la recherche précédente est suffisamment ancienne.
5.2 Nombre simultané
Opcodes.h:72
KADEMLIATOTALFILE = 5eMule limite à cinq le nombre de fichiers dont les sources sont recherchées simultanément via Kad.
5.3 Temporisation adaptative déjà présente
Le code contient déjà une forme rudimentaire de backoff.
PartFile.cpp:2327-2331
À chaque nouvelle recherche Kad, m_TotalSearchesKad augmente jusqu’à 7, puis :
m_LastSearchTimeKad =
maintenant + KADEMLIAREASKTIME * m_TotalSearchesKad;avec :
KADEMLIAREASKTIME = 1 heureLa re-recherche passe donc progressivement à environ :
1 h → 2 h → 3 h → … → 7 h
5.4 Types de sources Kad reçues
DownloadQueue.cpp:1521-1618
Le code différencie plusieurs types :
- sources non firewalled ;
- sources firewalled utilisant un Buddy ;
- sources firewalled supportant un callback UDP direct.
Si notre propre client est firewalled, certaines sources firewalled sont rejetées car elles ne seraient pas joignables.
5.5 Évolution Kad
eMule 0.50a :
KADEMLIA_VERSION = 9eMule 0.72a :
KADEMLIA_VERSION = 10Cette évolution devra faire l’objet d’un dossier Kad séparé.
6. Canal 4 — Source Exchange
6.1 SX1 historique
La spécification eDonkey de 2002 documente déjà les extensions eMule :
0x81 eMule Sources request
0x82 eMule Sources answer
Le format initial de réponse contient :
- IP/ID du client ;
- port client ;
- IP serveur ;
- port serveur.
6.2 État dans eMule 0.72a
Opcodes.h:254-257
OP_REQUESTSOURCES 0x81 // DEPRECATED
OP_ANSWERSOURCES 0x82 // DEPRECATED
OP_REQUESTSOURCES2 0x83
OP_ANSWERSOURCES2 0x84Version SX2 :
Opcodes.h:37
SOURCEEXCHANGE2_VERSION = 4SX1 reste compris pour la compatibilité.
6.3 Quand eMule demande des sources ?
DownloadClient.cpp:212-255
Conditions principales :
- protocole étendu disponible ;
- SX2 ou SX1 > 1 ;
- fichier sous son seuil « soft » ;
- politique différente selon le nombre de sources.
Constantes :
SOURCECLIENTREASKS = 40 min
SOURCECLIENTREASKF = 5 min
RARE_FILE = 50
MINCOMMONPENALTY = 4Le comportement est approximativement :
Très rare
Jusqu’à RARE_FILE / 5, soit 10 sources :
- demande permise plus facilement ;
- temporisation centrée sur le client.
Rare
Jusqu’à environ 50 sources :
- re-demande client ~40 min ;
- fichier ~5 min.
Fichier courant
Les délais sont multipliés par MINCOMMONPENALTY = 4.
On obtient donc des ordres de grandeur pouvant atteindre :
- 160 min côté client ;
- 20 min côté fichier.
La stratégie n’est donc pas « toutes les 10 minutes pour tout ». Le code moderne adapte déjà la sollicitation à la rareté.
6.4 Anti-spam côté réception
ListenSocket.cpp:1204-1223
Un client distant ne peut pas nous demander notre liste en boucle.
eMule ne répond de nouveau que si :
- le fichier est rare et la dernière demande suffisamment ancienne ;
- ou le délai long commun a expiré ;
- ou c’est la première demande.
6.5 Ce qu’eMule transmet
PartFile.cpp:3652-3695
eMule :
- ignore les sources LowID ;
- ignore les sources invalides ;
- essaie de ne transmettre que des sources possédant des parties utiles au demandeur ;
- limite la réponse à environ 501 entrées ;
- compresse le paquet s’il dépasse 354 octets.
6.6 Évolution du format
Décodage :
PartFile.cpp:3728-3840
Version 1
12 octets/source :
ID/IP + port + IP serveur + port serveur
Version 2
Ajout d’un UserHash de 16 octets.
Version 3
Taille identique à v2, mais évolution de la représentation de l’ID.
Version 4
Ajout d’un octet de capacités de connexion / cryptage.
C’est un bel exemple de compatibilité ascendante construite progressivement.
7. Canal 5 — source passive
ListenSocket.cpp:326-334 et 909-913
C’est un mécanisme particulièrement élégant.
Lorsqu’un client distant nous demande un fichier que nous partageons et que ce fichier est également en cours de téléchargement chez nous, son simple contact révèle qu’il possède le fichier ou au moins une partie.
eMule peut donc l’ajouter comme source sans effectuer une recherche.
La source est marquée :
SF_PASSIVEdans :
DownloadQueue.cpp:621-625
Restriction intéressante : le code évite l’ajout passif pour un fichier d’une seule partie.
8. Canal 6 au sens pratique — lien / source URL
Même si l’enum en compte cinq, SF_LINK couvre une autre voie logique :
- source incluse dans un lien ;
- hostname à résoudre ;
- source URL.
Références :
DownloadQueue.cpp:1451-1499PartFile.cpp:2488-2514ED2KLink.cpp
Une source URL reçoit :
SF_LINK9. Après la découverte : la grande étape de validation
DownloadQueue.cpp:472-555
Une source nouvelle est rejetée notamment si :
- elle correspond à notre propre UserHash ;
- elle se trouve dans une Dead Source List ;
- ses exigences d’obfuscation sont incompatibles ;
- elle existe déjà pour le fichier ou pour un autre fichier.
Quand elle existe déjà pour un autre fichier, eMule ne crée pas un deuxième objet client : il peut l’associer à la nouvelle demande et utiliser la logique A4AF.
D’autres filtres sont appliqués plus tôt :
- IP invalide ;
- IPFilter ;
- client banni ;
- LowID inutilisable dans notre situation ;
- limite maximale de sources.
10. Point important : LowID et utilité réelle d’une source
PartFile.cpp:2368-2404
Le code rejette une source LowID lorsque notre propre client est firewalled.
C’est cohérent avec le modèle historique :
LowID ↔︎ LowID ne peut pas ouvrir une connexion TCP directe classique.
Pour Kad, eMule applique une logique similaire mais sait exploiter :
- Buddy ;
- callbacks ;
- callback UDP direct selon la version/capacité.
La modernisation de la connectivité (NAT moderne, CGNAT, IPv6) doit devenir un chantier séparé. Elle ne doit pas être mélangée à l’optimisation de la découverte des sources.
11. Comparaison eMule 0.50a → 0.72a
La découverte des sources a remarquablement peu changé dans ses constantes fondamentales.
Les valeurs suivantes sont identiques dans 0.50a et 0.72a :
| Élément | 0.50a | 0.72a |
|---|---|---|
| Serveur TCP reask | 15 min | 15 min |
| Serveurs UDP | 30 min | 30 min |
| SX client | 40 min | 40 min |
| SX fichier | 5 min | 5 min |
| recherches Kad simultanées | 5 | 5 |
| base du reask Kad | 1 h | 1 h |
| seuil rare | 50 | 50 |
| SX2 | v4 | v4 |
Cela ne prouve pas qu’elles sont mauvaises.
Cela prouve qu’elles méritent un audit car une part importante de cette politique a traversé plus de quinze ans pratiquement inchangée.
12. Comparaison avec aMule
aMule confirme une partie de la logique mais apporte une information très importante :
les mêmes protocoles peuvent fonctionner avec des politiques locales différentes.
Dans le corpus aMule :
SERVERREASKTIME = 800000 ms ≈ 13 min 20 s
UDPSERVERREASKTIME = 1300000 ms ≈ 21 min 40 s
SOURCECLIENTREASKS = 40 min
SOURCECLIENTREASKF = 5 min
SOURCEEXCHANGE2_VERSION = 4
RARE_FILE = 50Valeur par défaut de sources/fichier :
- eMule 0.50a / 0.72a : 400
- aMule 3.x : 300
Correction importante par rapport à notre toute première ébauche
Le 750 trouvé dans eMule n’est pas la valeur par défaut des sources par fichier.
C’est :
MAX_SOURCES_FILE_SOFT = 750c’est-à-dire un plafond du seuil soft, calculé à 90 % de la limite configurée.
La valeur par défaut réelle dans Preferences.cpp est 400.
Pour aMule, la valeur par défaut est 300 et son seuil soft est 90 %, plafonné à 1000.
Cette correction illustre exactement pourquoi notre méthode doit toujours distinguer « constante trouvée » et « signification réelle ».
13. Ce qui appartient au protocole et ce qui appartient à la politique locale
Protocole — à préserver
- opcodes serveur et client ;
- structure de
OP_GETSOURCES/OP_FOUNDSOURCES; - formats SX1/SX2 ;
- interprétation des versions SX ;
- hash ED2K ;
- représentation des clients HighID/LowID ;
- messages Kad ;
- compatibilité des grandes tailles.
17. Conclusion du dossier 01
Le système de découverte des sources d’eMule est déjà multi-canal et plus sophistiqué qu’une simple interrogation périodique d’un serveur.
Sa faiblesse potentielle en 2026 n’est pas l’absence de mécanismes.
Au contraire : il possède beaucoup de mécanismes, mais ils sont largement pilotés par des seuils et des temporisations historiques indépendants.
conserver tous les protocoles existants, instrumenter leur rendement réel, puis coordonner intelligemment leur utilisation.
C’est une modernisation compatible, mesurable et techniquement réaliste.