Appearance
Status: DRAFT Last Reviewed: 2026-03-03
Download Subsystem Design (iMule-Compatible, Rust-Native)
Goal
Implement chunked file downloads compatible with iMule/eMule behavior, including:
- active temp state in
data/download/(.part,.part.met, backup, optional seeds), - completed files in
data/incoming/, - persisted known-file metadata (
known.met) and AICH hashsets (known2_64.met), - wire-compatible block request/receive flow for client-to-client transfers.
This document extracts architecture and behavior from iMule source without line-by-line translation.
iMule Findings (Deep Dive Summary)
Core files and responsibilities
source_ref/iMule-2.3.1.5-src/src/PartFile.cpp:- creates numbered temp files (
%03d.part.met+.part), - persists gap map + file tags to
.part.met, - tracks requested blocks and chooses next blocks by chunk-selection policy,
- buffers incoming block data, flushes to disk, hashes completed parts, finalizes file.
- creates numbered temp files (
source_ref/iMule-2.3.1.5-src/src/DownloadClient.cpp:- sends
OP_REQUESTPARTS, - receives
OP_SENDINGPART/OP_COMPRESSEDPART, - maps packets to pending requested blocks and writes to partfile buffer.
- sends
source_ref/iMule-2.3.1.5-src/src/UploadClient.cpp:- validates and serves requested block ranges from complete/part files.
source_ref/iMule-2.3.1.5-src/src/DownloadQueue.cpp:- orchestrates active downloads, source selection, source requests, and queue lifecycle.
source_ref/iMule-2.3.1.5-src/src/KnownFileList.cpp:- persists
known.metfor known/shared/completed files.
- persists
source_ref/iMule-2.3.1.5-src/src/SHAHashSet.handsource_ref/iMule-2.3.1.5-src/src/SHAHashSet.cpp:- manages AICH hashsets in
known2_64.met.
- manages AICH hashsets in
On-disk formats and filenames
- Part metadata versions:
PARTFILE_VERSION=0xE0,PARTFILE_VERSION_LARGEFILE=0xE2- from
source_ref/iMule-2.3.1.5-src/src/include/common/DataFileVersion.h.
- Known list headers:
MET_HEADER=0x0E,MET_HEADER_WITH_LARGEFILES=0x0F- from
source_ref/iMule-2.3.1.5-src/src/include/common/DataFileVersion.h.
- AICH hashset file:
known2_64.met(KNOWN2_MET_FILENAME)- from
source_ref/iMule-2.3.1.5-src/src/SHAHashSet.h.
- Block/part sizing:
PARTSIZE=9728000,BLOCKSIZE=184320,EMBLOCKSIZE=184320- from
source_ref/iMule-2.3.1.5-src/src/include/protocol/ed2k/Constants.h.
Transfer behavior to preserve
- Requests are grouped as up to N pending blocks; each block is a byte range.
- Block boundaries are aligned to ed2k block semantics (~180 KiB), but requests may be smaller to fill gaps.
- Chunk selection is rarity-aware and completion-aware (Maella enhanced chunk selection in
PartFile.cpp). - Received data is matched against pending requested ranges, buffered, persisted, then verified by part hash.
- Completed download is moved from temp (
.part) into incoming dir and state is persisted.
Rust Module Boundaries (Proposed)
New subsystem under src/download/:
src/download/mod.rs- public facade, commands/events, subsystem wiring.
src/download/types.rs- immutable identifiers and DTOs:
DownloadId,FileHashMd4,PartIndex,BlockRange,DownloadStatus.
src/download/errors.rs- typed
DownloadErrorand sub-errors (StoreError,WireError,HashError,IoError).
- typed
src/download/store.rs- partfile metadata persistence:
- read/write
.part.met,.part.met.bak, allocate numbered slots.
src/download/gap.rs- gap/range tracking and merge/split logic.
src/download/scheduler.rs- chunk selection + block request scheduling (rarity + completion + request spread).
src/download/transfer.rs- per-peer pending blocks, request building, receive-path matching, timeout/retry bookkeeping.
src/download/hash.rs- MD4 part/full-file verification; optional AICH integration hooks.
src/download/known.rs- known-file persistence interface (
known.met,known2_64.metphase-gated).
- known-file persistence interface (
src/download/service.rs- async event loop actor for download queue, source updates, and state transitions.
Integration points:
src/app.rs: start/stopDownloadServiceand route commands.src/api/*: add endpoints for create/list/detail/pause/resume/cancel and per-download metrics.- UI controllers can then consume these endpoints for active downloads.
Data Layout (rust-mule)
Under general.data_dir:
download/001.part001.part.met001.part.met.bak- optional:
001.part.met.seeds
incoming/- finalized files (safe rename/move target).
known.metknown2_64.met(when AICH support is enabled).
Notes:
- Keep temp and incoming split explicit.
- Startup scan should rebuild in-memory queue from
download/*.part.met. - Write operations should be atomic where possible (temp + rename).
Delivery Phases
- Phase 0: scaffolding + typed errors
- Create
src/download/*modules and typed errors. - Add config defaults for
download/andincoming/subdirs underdata_dir. - No wire traffic yet.
- Phase 1: local partfile lifecycle
- Create/load/save
.part.metand.part. - Persist gap map and requested ranges.
- Add queue operations: add/pause/resume/cancel/delete.
- Add unit tests for persistence and gap math.
- Phase 2: block transfer receive path
- Implement incoming block packet validation and write pipeline.
- Buffer + flush behavior, part completion detection, MD4 verification.
- Add deterministic tests for range matching, duplicate packets, and boundary checks.
- Phase 3: block request scheduler
- Implement rarity/completion-aware part selection compatible with iMule intent.
- Add per-peer pending block windows and timeout/retry handling.
- Add tests for selection fairness and starvation avoidance.
- Phase 4: finalize + known files
- Move completed files to
data/incoming/. - Persist known entries to
known.met. - Phase-gated AICH/
known2_64.metintegration.
- Phase 5: API + UI integration
- Add REST endpoints for download lifecycle and progress.
- Surface queue details in UI (active, paused, completed, errored).
Compatibility Rules
- Maintain ed2k file/block constants and range semantics.
- Keep
.part.metmetadata stable and recoverable (.bakfallback). - Preserve source compatibility at protocol level; internal scheduling may be Rust-native as long as behavior is equivalent.
- No global mutable state; use actor-style command/event loop for subsystem core.
Test Plan
- Unit tests:
- gap/range operations,
.part.metroundtrip,- requested/pending block lifecycle,
- hash verification rules.
- Integration tests:
- startup recovery from existing temp files,
- download completion and move to
incoming, - cancellation cleanup semantics.
- Compatibility tests:
- fixture-based comparison for key
.part.metfields and part/gap interpretation.
- fixture-based comparison for key
Open Decisions
data/incomingspelling is recommended (legacy typoincommingshould not become canonical).- AICH can be introduced in phase 4 after MD4-first baseline is stable.
known2_64.metcan be feature-gated initially if full AICH recovery path is deferred.