Périmètre : construction des requêtes, choix du canal, recherche globale UDP, recherche Kad, agrégation des résultats et filtre anti-spam. Le MultiServer n’est pas un objectif de recherche ici : ce dossier étudie le protocole et la qualité des résultats.
1. Sources auditées
SearchResultsWnd.cpp
SearchList.cpp
SearchList.h
SearchFile.cpp
SearchParams.h
SearchParamsWnd.cpp
SearchExpr.*
Scanner.*
ServerSocket.cpp
UDPSocket.cpp
ServerList.cpp
kademlia/kademlia/Search.cpp
SearchManager.cpp
Opcodes.h
Référence historique :
edonkey-protocol.txt
2. Types de recherche exposés
StartSearch() distingue :
SearchTypeAutomatic
SearchTypeEd2kServer
SearchTypeEd2kGlobal
SearchTypeKademlia
SearchTypeContentDB
ContentDB sort du protocole P2P et ouvre une requête web historique.
3. Sélection Automatic
Si un seul réseau est disponible :
server only → ED2K Server
Kad only → Kad
Si les deux sont connectés, la branche applique une heuristique historique.
4. Heuristique Automatic actuelle
Le serveur est choisi si le serveur courant est statique ou s’il vérifie notamment :
users > 40 000
users < 2 000 000
files > 5 000 000
server list < 40
Sinon Kad.
Le commentaire dit explicitement que cette logique pourrait être optimisée.
5. Interprétation
Ces seuils ne sont pas des propriétés du protocole.
Ils représentent une heuristique codée dans une certaine époque du réseau.
Avant toute modification :
mesurer le réseau actuel
6. Construction d’une recherche eD2K
DoNewEd2kSearch() :
vérifie connexion serveur
détermine support 64-bit/LargeFiles
GetSearchPacket()
annule ancienne recherche ED2K
crée SearchID
enregistre nouvelle SearchList
envoie OP_SEARCHREQUEST
7. SearchID
La fenêtre attribue un identifiant local de recherche afin de rattacher résultats, onglet et état.
Important pour :
réponses tardives
plusieurs recherches successives
annulation
UDP global
8. Search packet
GetSearchPacket() transforme l’expression et les filtres en une représentation binaire de recherche.
Le protocole possède un arbre d’expressions, pas une simple chaîne libre.
9. Nœuds booléens
Types historiques :
AND
OR
AND NOT
Le parser/serializer construit un arbre récursif.
Cas de fuzzing naturel :
profondeur excessive
arbre tronqué
nombre énorme de nœuds
10. Termes texte
Une recherche peut écrire un paramètre texte simple.
Pour Kad, un mot-clé principal est extrait séparément afin de construire la cible de routage.
11. Métadonnées chaîne
Le builder prend notamment en charge :
FT_FILETYPE
FT_FILEFORMAT
FT_MEDIA_CODEC
FT_MEDIA_TITLE
FT_MEDIA_ALBUM
FT_MEDIA_ARTIST
FT_FILENAME
Le détail exact de compatibilité varie entre vieux/nouveaux tags.
12. Comparaisons numériques
La syntaxe supporte des opérateurs de comparaison pour les attributs numériques.
Exemples :
FileSize
Sources
Bitrate
Length
CompleteSources
à confirmer attribut par attribut dans SearchExpr/builder.
13. 32-bit / 64-bit
Le builder peut produire une requête nécessitant 64 bits.
La branche mémorise :
m_b64BitSearchPacket
pour éviter d’envoyer cette requête à un serveur UDP incapable de LargeFiles.
14. Envoi local TCP
Paquet :
OP_SEARCHREQUEST
vers le serveur connecté.
En mode Global, une copie du payload est conservée pour le parcours UDP.
15. Timeout serveur local
En Global :
TimerServerTimeout = 50 s
Si le serveur courant tarde trop, la recherche globale UDP peut démarrer.
Il ne s’agit pas d’un timeout de téléchargement.
16. Timer global
Une fois le global actif :
intervalle ≈ 750 ms
La liste des serveurs est parcourue progressivement.
17. Serveurs morts
Le parcours saute les serveurs dont le failed-count a atteint le seuil DeadServerRetries.
Donc la qualité de server.met influence directement le coût d’une recherche globale.
18. Recherche UDP v1
Serveur ancien :
OP_GLOBSEARCHREQ
si la requête est compatible.
19. Recherche UDP v2
Si :
SRV_UDPFLG_EXT_GETFILES
le client utilise :
OP_GLOBSEARCHREQ2
20. Recherche UDP v3
Si le serveur supporte les extensions adéquates et LargeFiles :
OP_GLOBSEARCHREQ3
avec un tag de flags :
CT_SERVER_UDPSEARCH_FLAGS
SRVCAP_UDP_NEWTAGS_LARGEFILES
21. Skip LargeFiles
Une recherche nécessitant 64 bits est ignorée pour un serveur UDP qui ne supporte pas cette capacité.
Cela évite d’envoyer une requête qu’il interpréterait incorrectement.
22. Notification d’origine
Après un envoi UDP :
SentUDPRequestNotification(searchID, serverIP)
La SearchList peut ainsi associer certaines réponses à leur serveur d’origine.
Cette provenance est importante pour l’anti-spam.
23. Réception UDP
UDPSocket.cpp transmet les résultats à :
ProcessUDPSearchAnswer()
avec :
server IP
server port
Les résultats de plusieurs serveurs sont donc agrégeables avec provenance.
24. More Results
SearchMore() envoie :
OP_QUERY_MORE_RESULT
au serveur TCP courant.
Constante historique :
MAX_MORE_SEARCH_REQ = 5
Le commentaire indique une limite totale dépendant du nombre de réponses par page serveur.
25. Kad Search
DoNewKadSearch() :
extrait premier mot-clé
gère quotes
Trim
construit les contraintes
vérifie chars interdits
PrepareFindKeywords()
Le SearchID vient alors de l’objet CSearch Kad.
26. Keyword principal
Le premier token n’est pas nécessairement toute l’expression booléenne.
Il sert à choisir la clé distribuée.
Les autres conditions accompagnent la recherche pour filtrer les entrées.
27. Requête Kad et recherche serveur
Une partie de la logique de construction des contraintes est partagée.
Mais le transport et le mécanisme de découverte sont complètement différents.
28. Agrégation
SearchList reçoit des résultats de :
server TCP
server UDP
Kad
client shared-files selon contexte
Elle doit regrouper les variantes et conserver les origines.
29. Identité de regroupement
Le FileHash est la base naturelle de regroupement.
Les variantes de nom doivent être conservées comme observations, pas transformées en fichiers distincts lorsque le hash est identique.
30. Métadonnées contradictoires
Cas :
même hash
taille différente
devrait être considéré comme incohérent car taille+hash font partie de l’identité opérationnelle.
Cas :
même hash
noms différents
est possible.
Tester les décisions actuelles de SearchList.
31. Anti-spam : architecture
CSearchList::DoSpamRating() combine :
heuristiques générales
et
apprentissage à partir des choix utilisateur
Le commentaire du code reconnaît la fiabilité limitée des seules heuristiques.
32. Hash connu spam
Un FileHash déjà marqué spam peut produire un score décisif.
Un hash marqué explicitement non-spam peut au contraire devenir une forte preuve négative.
33. Noms
Le filtre compare :
nom exact
nom similaire
nom après suppression des mots de recherche et séparateurs
Il prend aussi en compte les variantes parent/enfant d’un même résultat groupé.
34. Tailles similaires
Une taille connue spam peut influencer un résultat si elle est proche :
< 5 Mio d'écart
ET
< 5 %
Ce signal a un poids relativement faible seul.
35. Serveur UDP d’origine
Le filtre conserve des IP de serveurs associés à du spam.
Le score dépend du contexte :
seul serveur à avoir donné le résultat
plusieurs serveurs
nombre de serveurs déjà marqués
36. Ratio spam d’un serveur
m_mUDPServerRecords conserve pour chaque serveur :
results
spam results
Un ratio est calculé.
Seuil historique visible :
UDP_SPAMRATIO_THRESHOLD = 50
37. Sources initiales
Le filtre peut également apprendre des sources clientes associées à des résultats spam.
Cela montre que l’ancien système avait déjà une notion de corrélation multi-signal.
38. Heuristiques générales
Le commentaire source cite notamment :
forte disponibilité sur un serveur UDP mais pas les autres
archive/program entre ~0,1 et 10 MB
100 % complete sources + forte disponibilité
Ces règles visaient des campagnes historiques de faux résultats.
39. Poids visibles
Exemples de constantes :
similar name ~40–60
similar size 10
UDP server 10–21
only spam servers 30
source hit 39
heuristic base 39
heuristic max 60
Et :
SEARCH_SPAM_THRESHOLD = 60
Ces valeurs doivent être traitées comme heuristiques historiques, pas comme probabilités.
40. Problème du score additif
Additionner plusieurs signaux corrélés peut surpondérer un même phénomène.
Exemple :
même campagne de spam
→ nom similaire
→ taille similaire
→ même serveur
→ mêmes sources
Ces signaux ne sont pas statistiquement indépendants.
41. Risque de dérive temporelle
Les heuristiques « petit .exe/.zip très disponible » correspondaient à des campagnes anciennes.
En 2026, le profil du spam peut avoir changé.
Question centrale :
quelle précision ont encore ces règles ?
42. Dataset de validation
Créer un corpus offline avec résultats réels/synthétiques étiquetés :
spam
non-spam
incertain
Éviter de prétendre mesurer précision/recall sans labels humains.
49. Ce que « utile » doit signifier
Pas seulement :
beaucoup de lignes
Mais :
hashs uniques
résultat choisi par utilisateur
sources ensuite trouvées
fichier finalement transférable
50. Pas de « meilleur réseau » global
Kad peut mieux fonctionner sur une requête rare.
Un gros serveur peut être meilleur sur une autre.
Le but n’est pas de déclarer :
Kad > serveur
mais de comprendre les conditions.
51. MultiServer
Le projet possède déjà sa propre réflexion/maîtrise du MultiServer.
D16 ne doit donc pas repartir sur une conception « Smart MultiServer ».
Ici nous étudions seulement :
la recherche UDP globale du protocole
la provenance des résultats
leur qualité
52. Query parser fuzzing
Cibles :
arbre profond
nœud incomplet
opérateur invalide
string énorme
tag inconnu
uint64 frontière
expressions imbriquées
53. Result parser fuzzing
Cibles :
count énorme
tag count énorme
troncature
FileHash absent
taille 0
taille > max
Unicode malformé
duplicate tags
54. UDP correlation
Une réponse UDP doit être associée à une recherche active et à une origine attendue.
Vérifier le comportement sur :
réponse tardive
serveur jamais interrogé
ancienne SearchID
onglet fermé
55. Kad late results
Même question pour Kad :
search stopping
15 s grace
late answer
deleted GUI search
Le moteur prévoit déjà une phase de stop avant destruction.
56. Privacy audit
Journaliser une recherche peut révéler les termes de l’utilisateur.
Toute télémétrie expérimentale doit privilégier :
SearchID local
hash du terme si nécessaire
compteurs
et éviter la conservation longue des requêtes textuelles.
57. Search evidence local-only
Structure conceptuelle :
SearchEvidence {
search_id
channel
origin
result_hash
first_seen
duplicate
metadata_conflict
spam_reasons
}
Sans upload externe par défaut.
58. UI et filtre
Un filtre anti-spam amélioré ne doit pas supprimer silencieusement des résultats légitimes sans possibilité de diagnostic.
Pour les tests :
score
reasons
hidden/visible
doivent être observables.
59. Noms alternatifs
Un même FileHash ayant plusieurs noms peut fournir une information utile contre certains fakes.
Mais le « nom majoritaire » n’est pas automatiquement vrai.
Mesurer seulement.
60. Sources complètes
Le nombre de complete sources est une métadonnée utile mais déclarative.
Ne pas confondre :
complete sources annoncées
avec :
sources réellement vérifiées
61. Recherche par hash
Lorsqu’on possède déjà un lien ED2K, la recherche textuelle devient secondaire.
Le téléchargement peut directement utiliser le FileHash et lancer la découverte de sources.
D14 et D16 doivent donc rester clairement séparés.
62. Robustesse sur 64-bit
Tests frontières :
OLD_MAX_EMULE_FILE_SIZE - 1
OLD_MAX_EMULE_FILE_SIZE
OLD_MAX_EMULE_FILE_SIZE + 1
MAX_EMULE_FILE_SIZE
MAX + 1
sur :
builder
server local
global UDP capability filtering
Kad
63. Performance locale
Les listes de résultats peuvent être nombreuses.
Profiling à faire sur :
grouping
spam recalculation
sorting
UI refresh
string normalization
Sur PC moderne, l’UI peut être plus coûteuse que le parsing réseau.
64. Pas d’optimisation par suppression de vérifications
Si un profil montre du coût dans le spam filter ou le regroupement, ne pas supprimer d’abord les contrôles de cohérence.
Séparer :
algorithme
allocations
rafraîchissement GUI
65. Recherche liée à Trust Model
Les résultats de recherche sont des :
remote claims
Leur confiance peut se renforcer par :
observations indépendantes
cohérence de métadonnées
succès du téléchargement
mais aucune de ces dimensions ne doit devenir une « vérité » avant validation.
66. Conclusion
Le moteur de recherche eMule est déjà une architecture multi-canal sophistiquée :
query tree
server TCP
global UDP
Kad
result grouping
spam heuristics
user feedback
Les zones qui méritent le plus d’étude sont :
pertinence actuelle du mode Automatic
rendement de chaque canal
qualité des métadonnées
validité du filtre anti-spam historique
robustesse des parsers
La prochaine étape n’est pas de changer ces règles immédiatement, mais de construire le corpus de test et les métriques permettant de savoir lesquelles fonctionnent encore réellement.
================================================================================================