3.0.0 — The "alive again" version
Hi! We are back.
This is the first major release in 5+ years (since 2.3.3, 2021-02-07). Headline changes are dramatic throughput improvements, full build-system overhaul, modernized dependency stack, native binaries for Linux / macOS / Windows, and a broad legacy-API cleanup.
We went through hard times, we missed programmers and maintainers. There were doubts whether aMule could reemerge. People called aMule a dead project. But eD2k still has users, and those users need working software. So here we are — back to bring you the best eD2k client.
One unfortunate thing happened: Gonosztopi, one of aMule's most prolific devs, who has been the maintainer for many years, is missing. We have no news from him (we hope you are well, man!). And he was the only owner of the original GitHub repo. The other members left in amule-project do not have enough rights on the organization to properly manage the project. So we were forced to create a new one. New org, new repos, but the same folks.
You can find the new aMule site here.
You will find everything there: the home page, complete documentation, download links, news and links to the source code.
Highlights
- Throughput rewrite. Disk I/O moved off the main thread, ASIO/EPOLLET races fixed, throttlers replaced with proper token-bucket limiters. Peer-to-peer download on the same hardware sees ~100–380× speedups across macOS / Linux / Windows over 2.3.3, plus aMule 3.0.0 sustains ~4.8× the upload throughput of eMule 0.70b on Windows. See Performance for the full matrix and per-PR breakdown.
- Both throttlers (
MaxUpload,MaxDownload) were also broken pre-fix —MaxUpload=0capped at "current rate + 5 KB/s",MaxDownloadwas a ratio controller rather than a literal cap. Both rewritten (#461, #491). Important user-facing bug fixes, but secondary to the headline numbers. - Big-library / big-shareset scaling. Follow-up wave targeting nodes with 100 k+ shared files: per-file EC payload caches (#725, #736), skip-unchanged EC updates (#727), local-peer ZLIB bypass (#728), and a string of O(N²) → O(N log N) / O(1) algorithmic fixes across
SharedFileList,SharedFilesCtrl,KnownFileList,wxListCtrl,ExternalConn, and amuleweb — the WebUI / amulegui stay responsive even on libraries where the previous GUI took minutes to redraw. - CMake replaces autotools. Single build system, modern toolchain — minimum CMake 3.10, minimum wxWidgets 3.2.0.
- Native binaries for every major desktop. AppImage (x86_64 + aarch64), Flatpak (x86_64 + aarch64), macOS Universal2 .dmg (now bundling
aMuleGUI.appalongsideaMule.app, #529), Windows portable .zip and NSIS installer (x64 + ARM64, #740). First-run desktop integration prompt for AppImage; cross-platform autostart-on-login toggle (#744). - Auto-rescan of shared folders.
wxFileSystemWatcher-driven (#591), with recursive vs explicit-share intent split (#606) and coverage of Incoming + per-category Incoming dirs (#743). - HTTPS works again.
CHTTPDownloadThreadrewritten on top ofwxWebRequest; the hand-rolled stack had silently stopped working against modern TLS. - Kad parallel searches with alpha-frontier widening.
- MaxMindDB replaces deprecated GeoIP for IP→country.
Performance
Throughput work landed across April 2026. The bottom-line cross-platform
numbers first, then the per-PR contributions that produced them.
Cross-platform end-to-end (2.3.3 vs 3.0.0)
| Leecher platform | 2.3.3 (sustained) | 3.0.0 (sustained) | Speedup |
|---|---|---|---|
| macOS (Apple Silicon, Mac Studio) | 0.35 MB/s | 135 MB/s | 381× |
| Linux ARM (UTM VM, Ubuntu 25.10) | 0.34 MB/s | 117 MB/s | 345× |
| Windows ARM (UTM VM, Windows 11) | 0.36 MB/s | 39 MB/s | 107× |
Sustained over a 90 s window, single LAN peer downloading a 30 GB file
from an x86_64 Linux seeder running the same aMule version under test.
Per-platform breakdown of the seeder-side vs leecher-side contributions:
| Platform | 2.3.3 | + seeder fix | + leecher fix (3.0.0) |
|---|---|---|---|
| macOS | 0.35 MB/s | 30 MB/s | 135 MB/s |
| Linux | 0.34 MB/s | 20 MB/s | 117 MB/s |
| Windows | 0.36 MB/s | 6.8 MB/s | 39 MB/s |
The seeder-side contribution (PR #451 CUploadDiskIOThread + ASIO fixes)
dominates everywhere; the leecher-side contribution (#454 partfile-write
offload + #484 throttler-wake fix + #491 token-bucket cap) stacks another
~4–6× on top.
vs eMule 0.70b (Windows · same UTM hardware)
| Direction | eMule 0.70b | aMule 3.0.0 | Speedup |
|---|---|---|---|
| Upload (Windows seeds → Mac leecher) | 22 MB/s | 106 MB/s | ~4.8× |
| Download (Linux seeds → Windows leeches) | 20 MB/s | 39 MB/s | ~1.9× |
Upload
- #451 — eMule
CUploadDiskIOThreadport. Disk reads + ed2k packet construction off the main thread, RC4 stream-desync race fixed in the ASIO layer, EPOLLET spurious-wakeup fix inHandleRead, adaptive per-slot packet sizing (10 KiB → EMBLOCKSIZE). Dominant contributor to the upload gain. - #461 —
MaxUpload=0is now literal unlimited. The legacy code setallowedDataRate = current_rate + 5 KB/sper iteration — a tracking cap that pinned the uplink at a fraction of capacity on any link above a few hundred KB/s. - #436 — Speed-limit fields widened from
uint16touint32. Legacy 65,534 KB/s (~524 Mbps) configuration ceiling gone; gigabit-class links can now be configured. - #463 — Bandwidth-cap UI. Spin button ceiling 19,375 → 1,000,000 KB/s; field width 100 → 140 px so the
+button no longer clips off on modern themes. Slot Allocation cap 100 → 100,000 KB/s. - #898 — Default
SlotAllocationraised from 2 kB/s to 10 kB/s. The previous default (set in 2005) fragmented uploads into so many sub-slot slices that fast peers were rate-shaped down to a trickle.
Download
- #454 —
CPartFileWriteThread. Disk writes for downloads moved off the main thread. - #484 — Throttler-wake fix.
UploadBandwidthThrottler::Entry()adaptive backoff dozed for 5–25 ms between control-queue pumps, stalling the request→response loop. Empty→non-empty wake gate added on the control-queue path, plus IOCP-nativeasync_read_someon Windows,wxMutex→std::mutex, and decouplingm_MaxBlockRequestsfrom per-packet block count. The biggest win on Windows specifically. - #491 —
MaxDownloadis now a literal byte/sec cap. The legacy code was a closed-loop ratio controller that nudged each peer's rate ±5%/tick relative to its own current speed, soMaxDownload=20000(20 MB/s) shaped traffic toward whatever the aggregate converged on — generally well below configured. Replaced with a global token bucket (CDownloadBandwidthThrottler) enforcing the cap to within 2.5% across platforms. - #498 — Per-part hash verification deferred to a dedicated worker thread (only runs when the file isn't actively transferring). Follow-ups #499, #500.
Other
- #467 — ASIO handler binding modernised.
boost::bind→ C++11 lambda,strand.wrap()→bind_executor(),deadline_timer→steady_timer,null_buffers→async_wait(wait_read). Fixes the long-standingboost::bindplaceholder warning. Minimum Boost bumped 1.47 → 1.70. - #504 — Fast-path bare-filename comparison skips
wxGetCwd().
Big-library / big-shareset scaling
A follow-up wave targeting nodes with 100 k+ shared files, where the daemon ↔ GUI / WebUI / amuleweb traffic and several internal data structures were quadratic in the shareset size:
- EC payload caches. Per-file
ed2k://link and partmet basename cached onCKnownFile/CPartFileso EC enumeration stops rebuilding them on every tick (#725). Per-file byte cache covers the FULLGET_SHARED_FILES/GET_DLOAD_QUEUEpaths so wire-marshalling cost drops by orders of magnitude on huge sharesets (#736). - EC skip-unchanged. Per-file change tracking infrastructure threaded through every field-change site so
INC_UPDATEonly re-sends what actually moved, with a backward-compatible partial-update protocol opt-in for amuleweb (#727 — landed as a 6-commit series).MarkECChangedgaps closed for paused / user-action setters. - Local-peer EC bypass. ZLIB compression skipped on local peers (#728), receiver limit raised to 256 MB, and the locality decision later moved to the client side with a user override checkbox /
--force-zlibflag (#840 — handles the WireGuard-as-LAN case). - O(N²) → O(N log N) / O(1) algorithmic fixes.
SharedFilesCtrlbulk-update API skips per-row repaints duringClearED2KPublishInfo(#561, #2bf9b8f34).SharedFileListkeyword indexing inReload(#566).known2.metAICHSaveHashSetdedup made O(1) (#581).known.methash-collision dedup on Init dropped to O(N log N) (#584).wxListCtrl::FindItem(data)O(N) → O(1) via user-data hash map (#614).ExternalConnfile-list enumeration snapshotted to avoid O(N²)GetFileByIndexloops (#687).- amuleweb
array_push_backmade O(N) via cached scan hint (#689). KnownFileListindexes its size-map by(size, mtime)instead of size alone to cut false-positive collision-dedup walks (#593).
- Disk I/O.
CFilegains a 64 KB userspace write buffer to coalesce metadata-save syscalls (#573); the buffer was subsequently moved off the stack onto the heap so it survives musl's 128 KiB pthread stack, and an internal recursive_mutex was added to serialise buffer + fd access against the concurrent-corruption race surfaced on Alpine (#576).SavePartFileswitched to atomic-rename (#670) and gated on an in-memory dirty flag so periodic ticks only touch disk when something actually changed (#671). Upload-stats persistence on 10-min heartbeat when only stats moved (#e8363bf42). - Memory bounds.
amuleIPV4Address::operator=no longer leaks the endpoint copy on every assign (#716) — was 7 MB / 514 k objects per ~10 h of runtime on a busy node.CKeyEntry::m_filenamescapped so the list can't grow unbounded (#652).known.metgrowth bounded by per-hash cap + 30-day TTL (#598, #f33c56b44).KnownFileList::Appendonly stampslastSeen=nowon actual sightings (#fafbb8a66). Wake-from-sleep SIGSEGV in asio socket impls fixed viashared_from_this(#596). - Backpressure & yielding.
ECSocket::OnOutputyields when asio backpressuresWriteto zero bytes (#672).CECServerSocketnotification-dispatch recursion capped so EC bursts no longer stall the event loop (#667).HTTPDownloadbounds libcurl connect-phase viaGetNativeHandle()(#565). Startup HTTP downloads deferred until after partfile + shared-file scan (#719) so cold-start UI is responsive while ipfilter.dat and friends are fetched. - Recursive share walks deferred + cancellable, with confirmation prompts for sensitive home-parent paths (#594, #599).
- macOS daemon shutdown driven from
OnCoreTimerto fix the long-standing hang (#563).
Networking & Discovery
- Kad parallel searches with alpha-frontier widening; new "More" button to ask additional peers for results (#505).
- MaxMindDB replaces deprecated GeoIP for IP→country (.dat → .mmdb; free MaxMind account required for the database) (#502, #507, #509).
- HTTPS downloads work again —
CHTTPDownloadThreadrewritten on top ofwxWebRequest(#462), with a hard-fail whenwxUSE_WEBREQUESTis off (#481). - Wire-parser hardening:
OP_SERVERMESSAGEsize validation (#447), buffer overflow fix inECSocket(#421), uninitialized memory fix inUInt128(#424). EC tags whose declared length underflows the children size now rejected (#879).Proxy::SendToSOCKS5 UDP relay bounded against oversized payloads (#882). Webserver/PHPIDENTstrcpy intoYYSTYPE.str_valbounded (#890). Memory leaks on malformed-packet exception paths plugged (#886, fixes #884 / #885). - ed2k-link float tags endian-swapped correctly on big-endian hosts (#368).
- Friend's shared list and search-result rating exposed via EC (#430, #452).
- Shared-folder watcher.
wxFileSystemWatcher-driven auto-rescan (#591), with recursive vs explicit-share intent split + cold-discover of subdirs created while offline (#606). Watcher also covers the Incoming dir + per-category Incoming dirs so completed downloads register without a manual reload (#743). Incremental rescan replaces fullReloadper filesystem event (#751);SharedFileListAICH-hash scan dropped from O(N·M) to O(N+M) (#746); optional "Follow symbolic links in shared folders" preference (#809). macOS amuled now pumpsCFRunLoopso FSEvents deliver (#975f60fb0). File rename / move-out / delete during in-flight hash handled cleanly (#858). - Kad index hygiene.
CEntry::SetFileNamerejects empty filenames in the merge path (#675);CKeyEntry::m_filenamesbounded (#652);known2_64.metorphan-pruned at sync startup (#605).m_filenamesrotation now uses O(N) compare-and-skip insertion instead of sort+resize (#795); a popularity-decay experiment (#799) was introduced and then reverted (#805), keeping theGetCommonFileNameall-zero robustness fix. Kad late UDP firewall responses dropped; Recheck assert downgraded (#afb9da010). SearchID collisions between Kad and ed2k searches no longer mix tab results (#530, #3008ada0f). - Server protocol. Future ping timestamps discarded from server.met (#3f70856a0); several server-ping fixes (#715). Control-traffic bypasses the download throttler (#615); inbound server probes also bypass it (#787). Server-name updates parsed as Unicode without the obsolete
SRV_TCPFLG_UNICODEgate (#835); explicit disconnect when the server assigns no client ID (#788).OP_IDCHANGEsanity checks demoted to debug log (#613).ServerUDPSocket"additional packet" notice demoted to non-critical debug (#548). HTTP/HTTPS auto-update foraddresses.dataccepts https URLs (#721); default eMule-security + shortypower URLs upgraded to HTTPS (#718). - EC / WebUI / amuleweb. 65535-children-per-tag wire-format ceiling lifted (#570).
FRIEND_REMOVEmade idempotent (#632); friend-slot flag persisted onCFriendso it survives disconnects (#633). amuleweb honoursamule_set_options()nickname (#634); fixes POST body parsing when URL has a query string (#729); fixessplit()byte/wide-char confusion on UTF-8 input (#619); fixes SIGSEGV rendering y-axis labels above 9999 (#618); fixes crash with >65535 shared files (#700). WebUI adds Kad + ed2k connect/disconnect controls (#660), Kad nodes-URL control, "Disconnect from current ed2k server" (#a82cd2e1a, #b5d83829a), and persistent ED2K / Kad enable checkboxes (#661, #8ce30f910); sends max upload/download rate as uint32 (#645). amulegui surfacesEC_OP_FAILEDfromADD_LINK(#557), implements category-tab Stop/Pause/Resume/Cancel + Prio (#701), renders statistics graphs viaEC_OP_GET_STATSGRAPHS(#639), and overridesOnFatalExceptionwith libbfd backtrace (#695). Aggregated single-popup AddLink error reporting (#577). - amuleweb security hardening (ngosang triage, all in #875). XSS-safe whitelist on the
sortquery param +htmlspecialcharsdefence-in-depth (#869);rand()-derived session IDs replaced with a 64-bit CSPRNG token fromCryptoPP::AutoSeededRandomPool(#870);HttpOnly; SameSite=Stricton the session cookie (#871); login handler refuses to consumepasswhen reachable via the pre-POST-body-merge URL (#872); read-buffer NUL-terminator allocation fix (#873); deadSESSION_TIMEOUT_SECSmacro wired up (#874). - UPnP. Filter non-WAN device announcements before fetching description (#623). Cache failed XML fetches + demote routine discovery logs from critical to debug (#653, #627).
- ClientTCPSocket strict "no trailing bytes" asserts demoted to debug log (#710).
- SharedFileList emits the honest file count in
OP_OFFERFILES(#556) and skips emptyOP_OFFERFILESwhen nothing made the LF cut (#169910998).
Build System & Dependencies
aMule 3.0 requires CMake ≥ 3.10 and wxWidgets ≥ 3.2.0. Autotools is removed entirely.
- Full CMake build replaces autotools (#449).
- Autotools,
debian/packaging dir, and dead platform/subtool trees retired (#466). - wxWidgets 3.x build fixes (#438, #443, #453); macOS framework / app-bundle compat (#453).
- Boost 1.87 / 1.89 build fixes (#387, #429) — modern Boost ASIO no longer breaks the build.
- CMake hard-fails when
ENABLE_X=YEScannot be honored: UPnP (#511), NLS (#512), Boost (#513), IP2Country (#509). No more silent disable. - CMake mins / detection: minimum 3.10 and
version.rcpath fix (#490),MIN_WX_VERSION3.2 with legacywx.cmakeretired (#459), default build type Release (#469), brokenUPNP.cmakeworkaround (#439), BFD link fixes for modern binutils (#487, #489),find_package(Intl)outsideYYENABLE_NLSgate (#495). - SVNDATE banner: stops freezing at first configure (#483); refreshes on
git reset/ commit (#493).SVNmacros / files renamed toGITthroughout the source tree (#726) —SVNDATE→GITDATE,__SVN__→__GIT__,config.h.cmand Windowsversion.rc.infollow suit. No user-facing impact; reflects 5+ years of Git as the canonical SCM. compile_commands.jsongenerated (#441);compile.shandfind_uncompiled.pybuild/analysis scripts (#494, #501).- Loongarch64 architecture support (#286).
- OpenSUSE platform fixes (#440); libupnp 1.18 compatibility (#448).
- boost::asio mandatory. wxWidgets-sockets fallback path removed;
ENABLE_BOOSTandDOWNLOAD_AND_BUILD_DEPSescape hatches retired (#603). - CMake polish (post-#518).
wx_NEED_NETkept on for BUILD_WEBSERVER-only (#620) and BUILD_AMULECMD-only (#630) configurations.libatomiclinked directly on 32-bit targets wherestd::atomic<int64_t>needs it (#648, #662) — the heuristic atomic-probe is gone.glib-2.0hard-fail when missing foramule/amuled/amulegui(#571), but the dependency itself is dropped on macOS even under wxGTK (#647).PACKAGE/PACKAGE_VERSIONpre-defined for the bfd.h probe (#545). - license.txt moved to project root (#730).
- CodeQL alerts cleared (#732, #733); CI runs CodeQL on push to master only, not on PRs (#c02d5ec04).
actions/checkoutbumped (#446 in initial pass). - README + docs polish. Distro version and GitHub activity badges (#7a1b310b5); markdown / ortography sweep (#6e9a9fe5a); INSTALL.md MD012/MD060 markup warnings fixed (#31aff1499).
Packaging
aMule 3.0 ships native binaries covering most modern desktops:
- Linux AppImage (x86_64, aarch64) — works across all major distros.
- Linux Flatpak (x86_64, aarch64) — runs in the GNOME Platform sandbox.
- macOS Universal2
.dmg— single installer containing Apple Silicon and Intel binaries (the per-arch.apptrees are CI intermediates for thelipomerge job and are not published as separate downloads). - Windows portable
.zip(x64, ARM64). - Windows NSIS installer
.exe(x64, ARM64) — guided installation, alternative to the portable zip.
Recipes, manifests, and the GitHub Actions packaging matrix landed in #510. AppImage's first-run prompt installs a desktop launcher to the user's application menu (reversible, opt-in).
Other platform integration work:
- Wayland-friendly desktop integration: matching
app_id, SNI tray icon (replaces deprecatedGtkStatusIcon), macOS dock-restore on quit, tray opt-in (#508; fallback workaround in #474). - macOS Carbon
FSRefAPI retired in favor of$HOME-based paths (#468). - macOS Dock right-click Quit triggers proper shutdown cleanup (#456).
- Windows / MinGW build support: cmake fixes, LLP64 pointer safety, ASIO on Windows (#457).
- Icons across all platforms: Linux hicolor PNG, Windows
.rcicon, macOSamulegui.app(#464). - Initial AppStream metainfo (#367).
- Localization on macOS and Windows fixed — wxLocale lookup paths repaired (#492).
- macOS spurious
wxGetCwd()errors silenced (#480). - Flatpak
libupnpinstall-libdir pinned for pkg-config (#515). - macOS .dmg now bundles
aMuleGUI.appalongsideaMule.appso installing the .dmg gives both the daemon-style and GUI binaries in/Applications(#529). Locale catalogs are bundled inside theaMuleGUI.appContents/Resourcestree so translated strings render correctly when run from the .dmg (#543). - Windows NSIS installer shipped alongside the existing portable .zip (#740), with un.SecRemoveUserData no longer appearing on the install Components page (#65178406a). Installer UI now driven from
po/<lang>.povia apo-to-nsh.pybridge so every supported NSIS language gets translated strings with English fallback (#899). - Cross-platform autostart-on-login toggle in Preferences (#744): Linux .desktop, macOS LaunchAgent, Windows registry under one checkbox.
- All platforms ship
alc/alcc/cas/wxcas; Windows additionally shipsamuleweb(#785); macOS.dmgnow containsamulewebafter build-path correction (#794). - Release-asset filenames standardised on
<OS>-<arch>so every package is reachable by predictable URL (#789). - Windows non-DPI executables (
alc,wxcas) get a comctl32 v6 + PerMonitorV2 manifest so they aren't bitmap-scaled on hi-DPI displays (#796); the main GUI got the samePerMonitorV2declaration in #780. - Windows resource lookup paths corrected so skins and webserver templates resolve to
share/amule(#784).
Internals & Refactoring
- Legacy wx 2.x-era deprecated APIs removed (#470).
- 2.x-compat globals and event-table macros retired (#475).
- Dialog code migrated to
wxSizerFlags; wxDesigner-generated code retired; GCC 15 enum-enum conversion warnings eliminated (#473). - macOS 10.10-era deprecation cleanup (#470).
OnAssertFailureternary fixed for strict GCC / Alpine builds (#476).- Documentation transitioned to Markdown; staleness audit; broken README icon URL fixed (#514).
- Late-cycle docs polish. Petar Maymounkov's email + paper URL refreshed to current (#851); IRC channel pointed to
irc.libera.chat(#855); leftover references to the removed XAS module dropped (#862); README project-migration notice (#888); English man-page masters resynced to source (#900);--enable-webserverbuild hint refreshed in amuleweb-launch failure (#866, fixes #864); copyright headers refreshed across the source tree (#867); EC host default corrected in i18n docs (#895). - Code-quality follow-ups.
FileLockplatform#ifdefmoved out of class body (#909); redundant null guard after early return removed fromSharedFileList(#910); unused UPnP symbols dropped fromWebSocketandSafeFile.htypo fixed (#912). - po4a config restored + optional CMake
po4a-updatetarget (#485). - Wiki content migrated into the repository (#496).
- Crash diagnostics.
MuleDebugPIE-translates runtime PCs back to link-time addresses for bfd (#677, #678), usespopen()instead ofwxExecute()for the addr2line fallback (#682), and theDo_not_auto_removemarker is replaced with the modernIWYU pragma: keep(#679). amulegui'sOnFatalExceptionoverridden with libbfd backtrace (#695).wxcas/alcdisable wxSizerFlags consistency checks at startup (#694) — eliminates spurious assertion noise that broke the apps under wx 3.3. - Tray-icon overhaul. Unified Linux/macOS/Windows tray path (#574); dock icon dropped while hidden via tray on macOS (#a5a9a5866);
HideOnClosedecoupled from confirm-exit (#f1d0e85f0); iconize-aware menu + single-left toggle + robust ShowGUI (#0640373c8);ServerWndsash anchored to top, persist-on-drag only (#47c811191); 'Enable Tray Icon' master placed before its dependents (#64b83e48e). Linux-specific tray-icon limitations gated separately (#2a0b874d7). 'Hide on close' exposed cross-platform behind the tray-icon gate (#e82b4bac5). - Wayland. amule-remote-gui binds
wl_app_idviag_set_prgname()(#572). - GUI dispatch polish.
MuleNotebookdispatches the right-click forward synchronously so PopupMenu's grab is fresh (#683).ClientDetailDialogbinds Escape to Close (#681). Destructive YES_NO prompts no longer treat ESC as confirm (#612). - amulecmd. Search filters (type/extension/availability/size) now exposed via flags (#542) and documented (#544, #547). amulecmd.1 stops translating command names in section headers (#4296bbccf).
- amule
--disable-fatalalso skips the assertion dialog (#549). - First-run prompt for nodes.dat alongside server.met (#558), with translations regenerated (#71542203f).
- Logger. Sticky stdio EOF cleared on
CLoggerAccessso EC log polls see new lines (#567). Control characters escaped in 'Invalid Kad tag type' log lines (#550).ExternalConnectorconsole binaries respectVerboseDebugfrom amule.conf (#654) andsetlocaleat init so non-interactive output keeps accented chars (#629). - Y2038. Internal time-handling unified on
uint64 GetTickCount64()to properly manage milliseconds past 2038 (#702).CLOCK_REALTIME→CLOCK_MONOTONICfor steady-state intervals (#56a369e95). - EC ADD_LINK aggregates per-link result into a single response (#551).
- Misc.
asiosetsFD_CLOEXECon listen + UDP sockets (#552).FileFunctionsbails out whenwxZipInputStreamstalls on a bad entry (#553).GuiEventsNULL-guardsECNotifierbefore dereferencing on download notifies (#554).StatTreestops double-counting session bytes (#555) and guards total ratio div-by-zero on fresh installs (#585).KnownFileListtakes list_mut before openingknown.met.new(#546) and closes a TOCTOU UAF window inSave()/PruneDuplicates(#690).SharedFileListtakeslist_mutaroundm_keywordsops inReloadandPublishso concurrent Kad publishes don't iterate a mid-mutation map (#686).PrefsUnifiedDlgflags user-home parents as sensitive (#599). amuleweb URL migration toamule-organd deadamule.orgrefs removed (#526). - Tooling / type cleanup.
fileviewCLogger stub extended withIsEnabled()for Debug builds (#657).muleunitadds missing override keywords (#664). Socketsoverridekeyword sweep onCEMSocket-derived classes (#625).WebServerusesvector::data()inCProgressImage::CreateSpan(#684). Constant rename:PR_VERYLOW→PR_VERY_LOW(#97fcd3ae8);PS_WAITINGFORHASH→PS_WAITING_FOR_HASH(#2ae100b56). Webserver internal renames:gaptag/parttag/reqtag→gap_tag/part_tag/req_tag(#412f5aa27);autoprio→auto_priority(#f0bca611b). Backtrace internal rename:s_abfd→s_a_bfd(#5a576c3c1). Webserver enum typo fixes (#5a0d13718). Spelling sweeps across webserver (#fd823eff8, #0cda3b03c) and backtrace (#bb76d0ad8). - PartFile.
m_lastDateChangedstamped on data arrival, not flush (#638).FlushBuffersize-correction guarded against closed fd (#609).m_hpartfilelocked inReadData+AICHRecoveryDataAvailable(#709).HashSinglePartbound-checked against partfile length (#130b0f495). Async hash enqueue gated onIsComplete(#c660e1281). Per-part hashing hardened against gap/disk-state drift (#560). - Preferences. No longer drops inaccessible shared dirs on load (#707); preserves unknown WebServer Template across GUI Save (#621); prefs/directories surfaces that the Incoming folder is shared (#631).
ExternalConnectordeletesm_ECClientin dtor to stop one-shot leak (#706). - Listctrl polish.
RefreshLinesskipped when range is outside visible (#624). Unfocused selection visible on themes whereBTNSHADOW == LISTBOX(#646). LTR cell paint forced to fix RTL-locale glyph mirroring (#540). - Search dialog. Clipped Min/Max Size + Availability spin controls on Linux (#607, #82626f2f3). 10px-tall extension input field (#569 / #971310402).
- Misc UI.
amuleDlgre-Realizes toolbar after Show() to fix wxMSW long-locale clipping (#532). Hardcoded 20px height on the FastEd2kLinks bar dropped (#534, #c710c08fe). Icons migrated fromXPM #includetowxArtProvider+ embedded PNG (#537, #59d718818). Gtk-CRITICAL warnings on Preferences + Networks tabs silenced (#739). - PartFileConvertDlg collects ids before removing rows so
GetNextItemstays valid (#649). - SafeFile oversized-string assertion demoted to debug log (#617).
- KnownFile. Skip notify when
SetPublishedED2Kvalue didn't change (#dde5294fc).m_duplicateFileListgrowth bounded with a per-hash cap (#f33c56b44). - Code-quality baseline. Baseline
.clang-tidyconfiguration introduced (#770); first sweeps produced 6 safety fixes (#773) and 4 cosmetic fixes (#774);wxASSERT→wxCHECK_MSGon array-access guards inLogger/UserEvents(#772). - Dead-code removal. 2011-era
/Statisticslegacy config migration dropped (#825); long-broken "Automatic server connect without proxy" checkbox removed from preferences (#806).
Translations
- Italian: AppImage integration prompt translated (#518).
- Spanish updated and completed (#497).
- Dutch updated (#343).
- Catalan updated (#425).
- Simplified Chinese updated (#348).
- Translation pipeline:
scripts/update-po.shintroduced. - AI-assisted gap-fill for it / fr / de / es app strings (#582) and man pages (#580).
- Spanish further updates (cpp + docs, manpages rebuilt) (#655).
- French + Turkish updated (#691) and added to the AppStream info file (#698, #86a08ffc7).
- Brazilian Portuguese (pt-BR) added to metainfo (#86bafee35); metainfo screenshot URLs fixed (
amule/amule→amule-org/amule, #cf84ec2c6); TODO comment syntax fix (shell→XML, #fc205619f). - po regeneration from updated sources + msgmerge across all locales (#c2bbea0ed).
- Late-cycle wave: French + Turkish manual pages (#753, #754, #776); Galician update (#763); Slovenian recovered from forum.amule.org (#771); Brazilian Portuguese man page added (#768) and the
.pocompleted (#775); pt-BR translations on 4.desktopfiles (#812); French manual-page update (#811). - Man-page tooling:
.THheaders templatized for date + version so they no longer drift per release (#802). - Pre-release final wave (3.0.0 cut): French + Turkish updates (#847, #856, #891, #908); Brazilian Portuguese (#860, #904); Spanish app + man pages (#859, #863); Italian completed (it / it_CH fuzzy + untranslated) (#861); German (#880, #911); Vietnamese README added (#901); regenerated po/pot for app + man pages with Italian translations applied (#902); obsolete (#~) entries swept from app + man po (#889); stale Copyright year bumped + obsolete entries pruned (#868); Petar Maymounkov's email + paper URL updated in all catalogs (#853).
Bug Fixes & Stability
CFile::doSeekno longer asserts whenIsOpened()is false (#294).RLE_Datamemory delete issue fixed (Valgrind report) (#379).- Selected lines in Download/Shared lists no longer become illegible when losing focus (#385).
- amulegui: clean startup on Cancel + watchdog on wrong connection data (#465).
- amuleweb: missing
prefs applyoptions restored (#419). PartFileWriteThreadcatchesCIOFailureExceptionso disk-full doesn't kill the process (#499).- StatTree fix (#319); totalizers added to download/upload stats (#338, #339).
- Doc / source-comment typos cleanup (#297); missing include (#360).
- amuleweb crash with >65535 shared files fixed (#700) with regression test (#61276d70d).
- CFile musl SIGSEGV + concurrent corruption caught and fixed (#576) — musl's 128 KiB pthread stack interacted badly with the 64 KB userspace write buffer added in #573; a separate concurrent-corruption race on a shared write buffer was also fixed in the same PR.
- macOS link error caused by implicit AppKit framework dependency now resolved by naming it explicitly (#578).
- Wake-from-sleep SIGSEGV in asio socket impls — root cause
shared_from_thislifetime gap (#596). NULLm_socketalso guarded in UDP DispatchClose (#82b5400dc). - WebUI rate-limit fields no longer truncate at 16 bits (#645).
- PartFileConvertDlg iteration invalidation crash (#649).
- amulegui EC connect-timeout shutdown crash (#717).
- ExternalConnector one-shot
m_ECClientleak on dtor (#706). - EC notification path raw-pointer
CECPacketleak plugged (#797). - Detect dead amuled cleanly across all clients (#758); EC
--upnp-portfixed from switch to numeric option inamuleweb(#820);amulewebremote.confround-trip + Windows webserver template path fixed (#822). - amulegui improvements and fixes: ghost-entry sources — stale EC alive-marker for unknown ID no longer creates phantom rows (#810),
INC_UPDATEtag for unknown file ID with suppressed identifying metadata now skipped cleanly (#819); connection dialog reappears on failure instead of quitting (#841); ED2K Info pane readability + clipboard copy fixed (#824);DirectoryTreeCtrlwxNullFontcrash on the Windows revert-recursive-share path (#830); modal popups deferred out ofOnPacketReceivedcall stack (#760). ECIDs the client hasn't received yet now sent with full detail instead of an empty alive marker (#857). - PartFile: first-share early hash so a downloading file appears in "Shared files" before it completes (#762); drop LowID-0 sources in
CanAddSource(#790). - Crypto stream: don't UB if
EncryptedStreamSocket::Negotiate()is entered with no expected bytes (#779). - UAF prevention:
Notify_KnownFileBeingDestroyedbroadcast on everyCKnownFiledestruction (#756). - GUI / GTK warnings: silenced on the Advanced Preferences tab via sizer simplification (#833); slider min-height pin attempted (#826) then reverted (#836) after wxGTK 3.2.9 surfaced an invisibility regression.
- SearchListCtrl dropped bogus "File" title from right-click popup (#769).
- Three GUI fixes from #800: toolbar races and web-template placeholder loop closed (#803).
- amuled constructs
CPartFileWriteThread+ hash worker AFTER the InitGui fork so the daemon no longer crashes on first flush (#850, fixes #849). - Locale.
LC_CTYPE=Cscoped aroundwxFileConfigops and the country-flag lookup so non-C locales no longer break preference number parsing or flag matching (#854, fixes #852). - ServerUDPSocket
Delete()leaked the detachedCAsyncDNSon thread Create/Run failure (#878). - eD2k socket
CLibSocket::OnLost(int)now forwards toCEMSocket::OnCloseso server/peer disconnects actually fire (#906).
CI
- macOS and Windows MinGW64 build jobs added (#458); ccpp.yml adjustments (#460).
- Ubuntu CI installs
binutils-devso the BFD path is exercised (#488). - Assert tests gated on
wxDEBUG_LEVEL;ctestruns in Release in CI (#506). - CodeQL adjustments and code-scanning fixes (#477, #478, #482).
actions/checkoutbumped from v4 to v6 (#446).- ccache wired across all compile jobs in both
ccpp.yml(#892) and the packaging matrix (#903) —actions/cache-backed, gated off for tag builds. CodeQL workflow also getsbinutils-devso its BFD detection mirrors the main Ubuntu job (#907).
Known Limitations
Known caveats users should be aware of for this release:
- macOS
.dmgis not yet code-signed or notarized — users will see Gatekeeper warnings on first launch. - Flathub submission pending — for now, install the
.flatpakdirectly withflatpak install <file>. - AppImage doesn't yet ship through AppImageLauncher's catalogue.
- Tray-icon library (
libayatana-appindicator) is deprecated upstream; migration tolibayatana-appindicator-glibdeferred until LTS distros pick it up.
Contributors
This release reflects 5+ years of work across 234 merged PRs (98 initial + 136 follow-ups through to the tag). Particular thanks to:
- got3nks — 182 PRs.
- Marcelo Jimenez (mrjimenez) — 17 PRs.
- Werner Mahr (Vollstrecker) — 38 commits.
- Pablo Barciela (sc0w) — 3 PRs, 17 commits.
- Dévai Tamás (GonoszTopi) — 16 commits.
- danim7 — 5 PRs across the follow-up cycle (translations, server pings, y2038, cmake polish).
- cardpuncher — French + Turkish translations and AppStream entries (#691, #698).
- ngosang — UX feedback driving the late-3.0 cycle (issues #817, #818, #821, #828, #844) and ongoing work on the user-facing manual at https://amule-org.github.io.
Plus contributions from RealGreenDragon, frnjjq, Sergi Amoros, Stefano Picerno, Alexander Tsoy, sergiomb2, puleglot, mercu01, lggcs, comio, MPolleke, mike2718, joebonrichie, matoro, dependabot, tbo47, SevC10, topotech, minterior, luzpaz, loongson-zn, mifritscher, nguyenhoangminhhieu2004-gif.
Merged PRs in this release
Complete list of PRs that landed for 3.0.0, in numerical order. The narrative sections above call out the most impactful changes; this index gives the full traceback.
#286, #294, #297, #319, #338, #339, #343, #348, #360, #367, #368, #379, #385, #387, #419, #421, #424, #425, #429, #430, #436, #438, #439, #440, #441, #443, #446, #447, #448, #449, #451, #452, #453, #454, #456, #457, #458, #459, #460, #461, #462, #463, #464, #465, #466, #467, #468, #469, #470, #473, #474, #475, #476, #477, #478, #480, #481, #482, #483, #484, #485, #487, #488, #489, #490, #491, #492, #493, #494, #495, #496, #497, #498, #499, #500, #501, #502, #504, #505, #506, #507, #508, #509, #510, #511, #512, #513, #514, #515, #518, #526, #529, #530, #532, #534, #537, #540, #542, #543, #544, #545, #546, #547, #548, #549, #550, #551, #552, #553, #554, #555, #556, #557, #558, #560, #561, #563, #565, #566, #567, #569, #570, #571, #572, #573, #574, #576, #577, #578, #580, #581, #582, #584, #585, #591, #593, #594, #596, #598, #599, #603, #605, #606, #607, #609, #612, #613, #614, #615, #617, #618, #619, #620, #621, #623, #624, #625, #627, #629, #630, #631, #632, #633, #634, #638, #639, #645, #646, #647, #648, #649, #652, #653, #654, #655, #657, #660, #661, #662, #664, #667, #670, #671, #672, #675, #677, #678, #679, #681, #682, #683, #684, #686, #687, #689, #690, #691, #694, #695, #698, #700, #701, #702, #706, #707, #709, #710, #715, #716, #717, #718, #719, #721, #725, #726, #727, #728, #729, #730, #732, #733, #736, #739, #740, #743, #744, #746, #747, #750, #751, #753, #754, #756, #758, #760, #762, #763, #768, #769, #770, #771, #772, #773, #774, #775, #776, #779, #780, #784, #785, #787, #788, #789, #790, #794, #795, #796, #797, #799, #801, #802, #803, #805, #806, #809, #810, #811, #812, #819, #820, #822, #824, #825, #826, #830, #833, #834, #835, #836, #839, #840, #841, #845, #847, #850, #851, #853, #854, #855, #856, #857, #858, #859, #860, #861, #862, #863, #866, #867, #868, #875, #878, #879, #880, #882, #886, #888, #889, #890, #891, #892, #895, #898, #899, #900, #901, #902, #903, #904, #906, #907, #908, #909, #910, #911, #912.