Skip to main content

aMule 3.0.0

· 24 min read

Release name: The 'alive again' version

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.

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=0 capped at "current rate + 5 KB/s", MaxDownload was 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.app alongside aMule.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. CHTTPDownloadThread rewritten on top of wxWebRequest; 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 platform2.3.3 (sustained)3.0.0 (sustained)Speedup
macOS (Apple Silicon, Mac Studio)0.35 MB/s135 MB/s381×
Linux ARM (UTM VM, Ubuntu 25.10)0.34 MB/s117 MB/s345×
Windows ARM (UTM VM, Windows 11)0.36 MB/s39 MB/s107×

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:

Platform2.3.3+ seeder fix+ leecher fix (3.0.0)
macOS0.35 MB/s30 MB/s135 MB/s
Linux0.34 MB/s20 MB/s117 MB/s
Windows0.36 MB/s6.8 MB/s39 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)

DirectioneMule 0.70baMule 3.0.0Speedup
Upload (Windows seeds → Mac leecher)22 MB/s106 MB/s~4.8×
Download (Linux seeds → Windows leeches)20 MB/s39 MB/s~1.9×

Upload

  • #451 — eMule CUploadDiskIOThread port. Disk reads + ed2k packet construction off the main thread, RC4 stream-desync race fixed in the ASIO layer, EPOLLET spurious-wakeup fix in HandleRead, adaptive per-slot packet sizing (10 KiB → EMBLOCKSIZE). Dominant contributor to the upload gain.
  • #461 — MaxUpload=0 is now literal unlimited. The legacy code set allowedDataRate = current_rate + 5 KB/s per 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 uint16 to uint32. 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.

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-native async_read_some on Windows, wxMutexstd::mutex, and decoupling m_MaxBlockRequests from per-packet block count. The biggest win on Windows specifically.
  • #491 — MaxDownload is 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, so MaxDownload=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_timersteady_timer, null_buffersasync_wait(wait_read). Fixes the long-standing boost::bind placeholder 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 on CKnownFile / CPartFile so EC enumeration stops rebuilding them on every tick (#725). Per-file byte cache covers the FULL GET_SHARED_FILES / GET_DLOAD_QUEUE paths 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_UPDATE only re-sends what actually moved, with a backward-compatible partial-update protocol opt-in for amuleweb (#727 — landed as a 6-commit series). MarkECChanged gaps 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-zlib flag (#840 — handles the WireGuard-as-LAN case).
  • O(N²) → O(N log N) / O(1) algorithmic fixes.
    • SharedFilesCtrl bulk-update API skips per-row repaints during ClearED2KPublishInfo (#561, #2bf9b8f34).
    • SharedFileList keyword indexing in Reload (#566).
    • known2.met AICH SaveHashSet dedup made O(1) (#581).
    • known.met hash-collision dedup on Init dropped to O(N log N) (#584).
    • wxListCtrl::FindItem(data) O(N) → O(1) via user-data hash map (#614).
    • ExternalConn file-list enumeration snapshotted to avoid O(N²) GetFileByIndex loops (#687).
    • amuleweb array_push_back made O(N) via cached scan hint (#689).
    • KnownFileList indexes its size-map by (size, mtime) instead of size alone to cut false-positive collision-dedup walks (#593).
  • Disk I/O. CFile gains 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). SavePartFile switched 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_filenames capped so the list can't grow unbounded (#652). known.met growth bounded by per-hash cap + 30-day TTL (#598, #f33c56b44). KnownFileList::Append only stamps lastSeen=now on actual sightings (#fafbb8a66). Wake-from-sleep SIGSEGV in asio socket impls fixed via shared_from_this (#596).
  • Backpressure & yielding. ECSocket::OnOutput yields when asio backpressures Write to zero bytes (#672). CECServerSocket notification-dispatch recursion capped so EC bursts no longer stall the event loop (#667). HTTPDownload bounds libcurl connect-phase via GetNativeHandle() (#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 OnCoreTimer to 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 — CHTTPDownloadThread rewritten on top of wxWebRequest (#462), with a hard-fail when wxUSE_WEBREQUEST is off (#481).
  • Wire-parser hardening: OP_SERVERMESSAGE size validation (#447), buffer overflow fix in ECSocket (#421), uninitialized memory fix in UInt128 (#424).
  • 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 full Reload per filesystem event (#751); SharedFileList AICH-hash scan dropped from O(N·M) to O(N+M) (#746); optional "Follow symbolic links in shared folders" preference (#809). macOS amuled now pumps CFRunLoop so FSEvents deliver (#975f60fb0).
  • Kad index hygiene. CEntry::SetFileName rejects empty filenames in the merge path (#675); CKeyEntry::m_filenames bounded (#652); known2_64.met orphan-pruned at sync startup (#605). m_filenames rotation 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 the GetCommonFileName all-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_UNICODE gate (#835); explicit disconnect when the server assigns no client ID (#788). OP_IDCHANGE sanity checks demoted to debug log (#613). ServerUDPSocket "additional packet" notice demoted to non-critical debug (#548). HTTP/HTTPS auto-update for addresses.dat accepts 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_REMOVE made idempotent (#632); friend-slot flag persisted on CFriend so it survives disconnects (#633). amuleweb honours amule_set_options() nickname (#634); fixes POST body parsing when URL has a query string (#729); fixes split() 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 surfaces EC_OP_FAILED from ADD_LINK (#557), implements category-tab Stop/Pause/Resume/Cancel + Prio (#701), renders statistics graphs via EC_OP_GET_STATSGRAPHS (#639), and overrides OnFatalException with libbfd backtrace (#695). Aggregated single-popup AddLink error reporting (#577).
  • 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 empty OP_OFFERFILES when 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=YES cannot be honored: UPnP (#511), NLS (#512), Boost (#513), IP2Country (#509). No more silent disable.
  • CMake mins / detection: minimum 3.10 and version.rc path fix (#490), MIN_WX_VERSION 3.2 with legacy wx.cmake retired (#459), default build type Release (#469), broken UPNP.cmake workaround (#439), BFD link fixes for modern binutils (#487, #489), find_package(Intl) outside YYENABLE_NLS gate (#495).
  • SVNDATE banner: stops freezing at first configure (#483); refreshes on git reset / commit (#493). SVN macros / files renamed to GIT throughout the source tree (#726)SVNDATEGITDATE, __SVN____GIT__, config.h.cm and Windows version.rc.in follow suit. No user-facing impact; reflects 5+ years of Git as the canonical SCM.
  • compile_commands.json generated (#441); compile.sh and find_uncompiled.py build/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_BOOST and DOWNLOAD_AND_BUILD_DEPS escape hatches retired (#603).
  • CMake polish (post-#518). wx_NEED_NET kept on for BUILD_WEBSERVER-only (#620) and BUILD_AMULECMD-only (#630) configurations. libatomic linked directly on 32-bit targets where std::atomic<int64_t> needs it (#648, #662) — the heuristic atomic-probe is gone. glib-2.0 hard-fail when missing for amule / amuled / amulegui (#571), but the dependency itself is dropped on macOS even under wxGTK (#647). PACKAGE / PACKAGE_VERSION pre-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/checkout bumped (#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 .app trees are CI intermediates for the lipo merge 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 deprecated GtkStatusIcon), macOS dock-restore on quit, tray opt-in (#508; fallback workaround in #474).
  • macOS Carbon FSRef API 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 .rc icon, macOS amulegui.app (#464).
  • Initial AppStream metainfo (#367).
  • Localization on macOS and Windows fixed — wxLocale lookup paths repaired (#492).
  • macOS spurious wxGetCwd() errors silenced (#480).
  • Flatpak libupnp install-libdir pinned for pkg-config (#515).
  • macOS .dmg now bundles aMuleGUI.app alongside aMule.app so installing the .dmg gives both the daemon-style and GUI binaries in /Applications (#529). Locale catalogs are bundled inside the aMuleGUI.app Contents/Resources tree 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).
  • 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 ships amuleweb (#785); macOS .dmg now contains amuleweb after 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 same PerMonitorV2 declaration 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).
  • OnAssertFailure ternary fixed for strict GCC / Alpine builds (#476).
  • Documentation transitioned to Markdown; staleness audit; broken README icon URL fixed (#514).
  • po4a config restored + optional CMake po4a-update target (#485).
  • Wiki content migrated into the repository (#496).
  • Crash diagnostics. MuleDebug PIE-translates runtime PCs back to link-time addresses for bfd (#677, #678), uses popen() instead of wxExecute() for the addr2line fallback (#682), and the Do_not_auto_remove marker is replaced with the modern IWYU pragma: keep (#679). amulegui's OnFatalException overridden with libbfd backtrace (#695). wxcas / alc disable 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); HideOnClose decoupled from confirm-exit (#f1d0e85f0); iconize-aware menu + single-left toggle + robust ShowGUI (#0640373c8); ServerWnd sash 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_id via g_set_prgname() (#572).
  • GUI dispatch polish. MuleNotebook dispatches the right-click forward synchronously so PopupMenu's grab is fresh (#683). ClientDetailDialog binds 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-fatal also 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 CLoggerAccess so EC log polls see new lines (#567). Control characters escaped in 'Invalid Kad tag type' log lines (#550). ExternalConnector console binaries respect VerboseDebug from amule.conf (#654) and setlocale at 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_REALTIMECLOCK_MONOTONIC for steady-state intervals (#56a369e95).
  • EC ADD_LINK aggregates per-link result into a single response (#551).
  • Misc. asio sets FD_CLOEXEC on listen + UDP sockets (#552). FileFunctions bails out when wxZipInputStream stalls on a bad entry (#553). GuiEvents NULL-guards ECNotifier before dereferencing on download notifies (#554). StatTree stops double-counting session bytes (#555) and guards total ratio div-by-zero on fresh installs (#585). KnownFileList takes list_mut before opening known.met.new (#546) and closes a TOCTOU UAF window in Save() / PruneDuplicates (#690). SharedFileList takes list_mut around m_keywords ops in Reload and Publish so concurrent Kad publishes don't iterate a mid-mutation map (#686). PrefsUnifiedDlg flags user-home parents as sensitive (#599). amuleweb URL migration to amule-org and dead amule.org refs removed (#526).
  • Tooling / type cleanup. fileview CLogger stub extended with IsEnabled() for Debug builds (#657). muleunit adds missing override keywords (#664). Sockets override keyword sweep on CEMSocket-derived classes (#625). WebServer uses vector::data() in CProgressImage::CreateSpan (#684). Constant rename: PR_VERYLOWPR_VERY_LOW (#97fcd3ae8); PS_WAITINGFORHASHPS_WAITING_FOR_HASH (#2ae100b56). Webserver internal renames: gaptag / parttag / reqtaggap_tag / part_tag / req_tag (#412f5aa27); autoprioauto_priority (#f0bca611b). Backtrace internal rename: s_abfds_a_bfd (#5a576c3c1). Webserver enum typo fixes (#5a0d13718). Spelling sweeps across webserver (#fd823eff8, #0cda3b03c) and backtrace (#bb76d0ad8).
  • PartFile. m_lastDateChanged stamped on data arrival, not flush (#638). FlushBuffer size-correction guarded against closed fd (#609). m_hpartfile locked in ReadData + AICHRecoveryDataAvailable (#709). HashSinglePart bound-checked against partfile length (#130b0f495). Async hash enqueue gated on IsComplete (#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). ExternalConnector deletes m_ECClient in dtor to stop one-shot leak (#706).
  • Listctrl polish. RefreshLines skipped when range is outside visible (#624). Unfocused selection visible on themes where BTNSHADOW == 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. amuleDlg re-Realizes toolbar after Show() to fix wxMSW long-locale clipping (#532). Hardcoded 20px height on the FastEd2kLinks bar dropped (#534, #c710c08fe). Icons migrated from XPM #include to wxArtProvider + embedded PNG (#537, #59d718818). Gtk-CRITICAL warnings on Preferences + Networks tabs silenced (#739).
  • PartFileConvertDlg collects ids before removing rows so GetNextItem stays valid (#649).
  • SafeFile oversized-string assertion demoted to debug log (#617).
  • KnownFile. Skip notify when SetPublishedED2K value didn't change (#dde5294fc). m_duplicateFileList growth bounded with a per-hash cap (#f33c56b44).
  • Code-quality baseline. Baseline .clang-tidy configuration introduced (#770); first sweeps produced 6 safety fixes (#773) and 4 cosmetic fixes (#774); wxASSERTwxCHECK_MSG on array-access guards in Logger / UserEvents (#772).
  • Dead-code removal. 2011-era /Statistics legacy 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.sh introduced.
  • 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/amuleamule-org/amule, #cf84ec2c6); TODO comment syntax fix (shellXML, #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 .po completed (#775); pt-BR translations on 4 .desktop files (#812); French manual-page update (#811).
  • Man-page tooling: .TH headers templatized for date + version so they no longer drift per release (#802).

Bug Fixes & Stability

  • CFile::doSeek no longer asserts when IsOpened() is false (#294).
  • RLE_Data memory 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 apply options restored (#419).
  • PartFileWriteThread catches CIOFailureException so 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_this lifetime gap (#596). NULL m_socket also 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_ECClient leak on dtor (#706).
  • EC notification path raw-pointer CECPacket leak plugged (#797).
  • Detect dead amuled cleanly across all clients (#758); EC --upnp-port fixed from switch to numeric option in amuleweb (#820); amuleweb remote.conf round-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_UPDATE tag 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); DirectoryTreeCtrl wxNullFont crash on the Windows revert-recursive-share path (#830); modal popups deferred out of OnPacketReceived call stack (#760).
  • 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_KnownFileBeingDestroyed broadcast on every CKnownFile destruction (#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).

CI

  • macOS and Windows MinGW64 build jobs added (#458); ccpp.yml adjustments (#460).
  • Ubuntu CI installs binutils-dev so the BFD path is exercised (#488).
  • Assert tests gated on wxDEBUG_LEVEL; ctest runs in Release in CI (#506).
  • CodeQL adjustments and code-scanning fixes (#477, #478, #482).
  • actions/checkout bumped from v4 to v6 (#446).

Known Limitations

Known caveats users should be aware of for this release:

  • macOS .dmg is not yet code-signed or notarized — users will see Gatekeeper warnings on first launch.
  • Flathub submission pending — for now, install the .flatpak directly with flatpak install <file>.
  • AppImage doesn't yet ship through AppImageLauncher's catalogue.
  • Tray-icon library (libayatana-appindicator) is deprecated upstream; migration to libayatana-appindicator-glib deferred 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 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.

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.