Skip to content

fix(ec): emit full detail for ECIDs the client hasn't received yet - #857

Merged
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/ec-emit-detail-for-unseen-ecids
Jun 5, 2026
Merged

fix(ec): emit full detail for ECIDs the client hasn't received yet#857
mrjimenez merged 1 commit into
amule-project:masterfrom
got3nks:fix/ec-emit-detail-for-unseen-ecids

Conversation

@got3nks

@got3nks got3nks commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Server-side fix for the #808 ghost-entry bug class. Where the partial-update opt-in's m_ecGen <= ec_threshold shortcut produces either a childless alive-marker (legacy clients) or a silent skip (partial-update clients), gate the shortcut on whether the client has previously received the ECID with full detail. If not, fall through to full-detail emission.

Why

PR #810 and #819 fixed two surfaces of the same bug in amulegui — childless alive-markers and CValueMap-suppressed identity tags both produced 0-byte unnamed ghost entries when amulegui hadn't yet received the file's metadata. Both fixes are amulegui-side guards.

Other EC consumers — amuleweb and amulecmd, both of which advertise EC_TAG_CAN_PARTIAL_UPDATE via CRemoteConnect and so sit on the partial-update silent-skip path, plus genuinely-legacy third-party clients that don't advertise the tag and hit the childless alive-marker path — have no analogous guard. Both variants of the shortcut produce a file the client never gets metadata for: silent absence in partial-update mode, empty cache entry in legacy mode. They lose newly-shared files until restart, with intermittent symptoms depending on when their poll cycle aligns with the daemon's m_ecGen accounting and which CValueMap cache state the server happens to be in.

Fixing at the daemon ends the per-client patch treadmill and restores the invariant that any tag the server emits carries enough metadata for the client to construct the entry.

What

Three handlers in src/ExternalConn.cpp:

  • Get_EC_Response_GetUpdate — covers both legacy alive-marker and partial-update silent-skip paths
  • Get_EC_Response_GetSharedFiles — partial-update silent-skip path
  • Get_EC_Response_GetDownloadQueue — partial-update silent-skip path

Each takes an additional std::set<uint32> &io_sentWithDetailIds and only takes the shortcut if io_sentWithDetailIds.count(ecid) is true. When the shortcut is skipped (first-sight ECID) the handler falls through to full-detail emission and inserts the ECID into the set.

Three corresponding std::set<uint32> fields on CECServerSocket — one per request path because each handler has its own m_lastEcGenSeen* cadence.

Cost

Bounded by alive-file ECID count per connection. ~360 KB at 91k shared files; immaterial vs. existing per-connection encoder + CObjTagMap state. The set is never pruned — re-share bumps m_ecGen via SetFilePath / Init so any resurrected ECID naturally takes the full-detail branch on its first post-resurrection cycle.

Refs #808 #810 #819

…_FILES / GET_DLOAD_QUEUE

The EC skip-unchanged opt-in (93a0676 "EC skip-unchanged (4/5)")
gates the per-file emit on `m_ecGen <= ec_threshold` in three
handlers. For unchanged files the server either emits a childless
alive-marker tag (legacy clients) or skips silently (partial-update
clients). Both shortcuts assume the client has previously received
the ECID with full detail. If it hasn't, the alive marker
constructs a ghost CKnownFile from an empty tag (amule-project#810 surface) and
the silent skip leaves the file invisible. The CValueMap-driven
identity suppression on subsequent emissions extends the surface to
INC_UPDATE tags that have children but no identifying fields (amule-project#819
surface).

The amulegui-side guards in amule-project#810 and amule-project#819 cover that client
specifically. Other legacy EC consumers — amuleweb, amulecmd, and
third-party clients — have no analogous guard and silently lose
newly-shared files until restart.

Fix at the source: track per-connection, per-handler ECIDs that
have been sent with full detail. Gate the alive-marker / silent-
skip shortcut on membership in that set. Files the client hasn't
seen fall through to full-detail emission unconditionally, and the
emission populates the per-connection CObjTagMap (so subsequent
INC_UPDATE diffs work) and inserts into the new sent-with-detail
set.

Three handlers, three sets — one per request path because each
handler has its own `m_lastEcGenSeen*` cadence.

Memory cost: bounded by alive-file ECID count per connection
(~360 KB at 91k files; insignificant). Never pruned — re-share
bumps m_ecGen via SetFilePath / Init so any resurrected ECID
naturally takes the full-detail branch again.

The amulegui guards from amule-project#810 and amule-project#819 stay as defensive belt-and-
suspenders for amulegui talking to unpatched / older daemons.
@mrjimenez
mrjimenez merged commit 32f6ea1 into amule-project:master Jun 5, 2026
7 checks passed
@got3nks
got3nks deleted the fix/ec-emit-detail-for-unseen-ecids branch June 5, 2026 22:35
got3nks added a commit to got3nks/amule that referenced this pull request Jun 7, 2026
…ule-project#912)

Extends existing categories (preferring extensions over new lines):
- Performance/Upload: amule-project#898 SlotAllocation default raised.
- Networking & Discovery: wire-parser hardening list extended with
  amule-project#879/amule-project#882/amule-project#890/amule-project#886; new amuleweb security hardening bullet
  consolidating ngosang's amule-project#869-amule-project#874 triage (all landed in amule-project#875);
  amulegui list extended with amule-project#857; shared-folder watcher extended
  with amule-project#858.
- Packaging: Windows installer i18n line extended with amule-project#899.
- Internals & Refactoring: new docs-polish + code-quality bullets
  covering amule-project#851/amule-project#855/amule-project#862/amule-project#888/amule-project#900/amule-project#866/amule-project#867/amule-project#895 and amule-project#909/amule-project#910/amule-project#912.
- Translations: new pre-release final-wave bullet covering amule-project#847/amule-project#856/
  amule-project#891/amule-project#908/amule-project#860/amule-project#904/amule-project#859/amule-project#863/amule-project#861/amule-project#880/amule-project#911/amule-project#901/amule-project#902/amule-project#889/amule-project#868/amule-project#853.
- Bug Fixes & Stability: amule-project#850/amule-project#854/amule-project#878/amule-project#906.
- CI: ccache wiring (amule-project#892, amule-project#903) + CodeQL binutils-dev (amule-project#907).

Contributors footer gains mifritscher and nguyenhoangminhhieu2004-gif
(both first-time contributors).

PR index extended through amule-project#912.
mrjimenez pushed a commit that referenced this pull request Jun 8, 2026
Extends existing categories (preferring extensions over new lines):
- Performance/Upload: #898 SlotAllocation default raised.
- Networking & Discovery: wire-parser hardening list extended with
  #879/#882/#890/#886; new amuleweb security hardening bullet
  consolidating ngosang's #869-#874 triage (all landed in #875);
  amulegui list extended with #857; shared-folder watcher extended
  with #858.
- Packaging: Windows installer i18n line extended with #899.
- Internals & Refactoring: new docs-polish + code-quality bullets
  covering #851/#855/#862/#888/#900/#866/#867/#895 and #909/#910/#912.
- Translations: new pre-release final-wave bullet covering #847/#856/
  #891/#908/#860/#904/#859/#863/#861/#880/#911/#901/#902/#889/#868/#853.
- Bug Fixes & Stability: #850/#854/#878/#906.
- CI: ccache wiring (#892, #903) + CodeQL binutils-dev (#907).

Contributors footer gains mifritscher and nguyenhoangminhhieu2004-gif
(both first-time contributors).

PR index extended through #912.
mrjimenez pushed a commit to mrjimenez/amule that referenced this pull request Aug 8, 2026
…st (amule-project#857)

Two gaps in the comments/ratings dialog, plus one piece of dead code found alongside them.

The sort caret went with amule-project#855's downgrade from CMuleListCtrl to a plain wxListCtrl, which tracks no sort state of its own; ShowSortIndicator() drives the glyph explicitly, and all three ports draw it -- macOS and GTK through the generic implementation, Windows through wxMSW's override.

The rating smiley was never there, on master either: the column has always been GetRateString() text alone while every other list showing a rating draws the icon beside it. The images are already in the app's shared list, so it needs SetImageList() plus a per-row SetItemColumnImage(). Borrowed rather than assigned, so this modal does not delete the app's list on close. Unrated rows stay blank rather than drawing a "not rated" glyph on each one.

The cell also fell back to an untranslated "on" for a rating of -1, which cannot occur: the wire value is a uint8 and CUpDownClient clamps anything above 5 to 0, so the range is 0..5 with 0 meaning a comment carrying no rating.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants