Geek++ · Dossier 01 / 25

Découverte et gestion des sources

Étude technique publique · 1,933 mots · ≈ 9 min de lecture attentive

Étude intégraleSans réflexion CODEXSources & constantes conservées
Réseau de découverte
Fichier X
ServeurKadSXPassifLien

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_LINK

L’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 minutes

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

Dé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 = 50

C’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 GETSOURCES2 permettant 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 = 5

eMule 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 heure

La 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 = 9

eMule 0.72a :

KADEMLIA_VERSION = 10

Cette é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   0x84

Version SX2 :

Opcodes.h:37

SOURCEEXCHANGE2_VERSION = 4

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

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

dans :

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-1499
  • PartFile.cpp:2488-2514
  • ED2KLink.cpp

Une source URL reçoit :

SF_LINK

9. 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 = 50

Valeur 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 = 750

c’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.



Dossier 01 terminé

Découverte et gestion des sources

← Portail Geek++Dossier 02 →