Skip to content

fix(gui): one answer for a peer's ident state, and never a blank field - #728

Merged
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/ident-state-predicates
Jul 30, 2026
Merged

fix(gui): one answer for a peer's ident state, and never a blank field#728
got3nks merged 1 commit into
amule-org:masterfrom
got3nks:fix/ident-state-predicates

Conversation

@got3nks

@got3nks got3nks commented Jul 30, 2026

Copy link
Copy Markdown

Summary

Fixes #727.

CUpDownClient had two accessors disagreeing about what a missing credits object means. GetCurrentIdentState() treats it as IS_NOTAVAILABLE; the five boolean predicates tested credits && instead, so with credits still NULL every one of them returned false — including SUINotSupported(), which is exactly the state the accessor was reporting. credits is NULL from construction until the peer's user hash resolves, so this is reachable rather than theoretical.

The visible effect was in the Client Details dialog. CClientRef::GetSecureIdentTextStatus() is an if / else if chain over those five predicates with no final else, and its result is assigned straight into the label. All five false left the string empty, blanking the Secure ident: field and overwriting the _("N/A") placeholder it was built with. The same dialog reads "Not supported" in amulegui, whose predicates compare m_identState directly and whose credits object is always allocated — so the monolithic GUI was the odd one out, disagreeing with both amulegui and the EC / Web API view, all of which go through GetCurrentIdentState().

The fix defines the predicates in terms of that accessor. The contradiction then cannot recur: they are the accessor's answer rather than a second opinion about it.

The chain also gets a final else. It is unreachable while the five predicates cover every EIdentState, but a sixth state would otherwise silently blank the field again instead of failing visibly.

Blast radius is smaller than it looks

Only SUINotSupported() changes behaviour, and it has exactly one caller in the tree — the chain being fixed. For the other four the guard was redundant: a NULL credits yields IS_NOTAVAILABLE, which already compares unequal to the state each of them asks about, so their 6 / 4 / 1 / 1 call sites are unaffected.

On the catalogs

No new translatable string — the fallback reuses the _("N/A") the field is already built with. The catalogs still move, because since #673 they record locations by file and that msgid's reference list gains src/ClientRef.cpp. Existing translations are preserved.

Test plan

Built on macOS 15 ARM64 with MONOLITHIC + DAEMON + REMOTEGUI + AMULECMD + AMULEAPI + TESTING: 0 errors, ctest 29/29. Both divergent implementations compile — the monolithic aMule.app and aMuleGUI.app now report the same thing for the same peer.

git clang-format origin/master reports nothing to format. Diff-scoped clang-tidy is clean against both .clang-tidy-new-code and .clang-tidy, each analysing 5 TUs with 0 truncated ASTs.

Not unit-tested, deliberately. Nothing currently links BaseClient / ClientRef; CUpDownClient's construction pulls a 49-include closure with five app-singleton headers, and the chain needs theApp for CryptoAvailable(). A harness for that would dwarf the fix. Routing the predicates through the accessor makes the disagreement unrepresentable instead, which is a stronger guarantee than a test could give — a test could only sample states, whereas the definition covers all of them.

The reproduction in the issue (a source added from a server response, opened before it completes the eD2k handshake) has a short window and depends on live peers, so it has not been reproduced end to end here; the fix is derived from the code paths rather than from a captured repro.

Left out

The issue's "Related, same area" note — that GenericClientListCtrl draws an overlay for IsIdentified() and IsBadGuy() but nothing for SUIFailed(), so a peer whose signature actually failed looks identical to one that never supported SecIdent. That is a real gap, but it needs a decision on which icon to use, so it belongs in its own change.

CUpDownClient had two accessors disagreeing about what a missing credits
object means. GetCurrentIdentState() treats it as IS_NOTAVAILABLE; the
five boolean predicates tested `credits &&` instead, so with credits
still NULL every one of them returned false -- including
SUINotSupported(), which is exactly the state the accessor was
reporting. credits is NULL from construction until the peer's user hash
resolves, so this is reachable, not theoretical.

The visible effect was in the Client Details dialog.
CClientRef::GetSecureIdentTextStatus() is an if/else-if chain over those
five predicates with no final else, and its result is assigned straight
into the label. All five false left the string empty, blanking the
field and overwriting the _("N/A") placeholder it was built with. The
same dialog reads "Not supported" in amulegui, whose predicates compare
m_identState directly and whose credits object is always allocated --
so the monolithic GUI was the odd one out, disagreeing with both
amulegui and the EC/Web API view, all of which go through
GetCurrentIdentState().

Define the predicates in terms of that accessor. The contradiction then
cannot recur: they are the accessor's answer rather than a second
opinion about it.

Only SUINotSupported() changes behaviour, and it has exactly one caller
in the tree -- the chain being fixed. For the other four the guard was
redundant: a NULL credits yields IS_NOTAVAILABLE, which already compares
unequal to the state each of them asks about, so their 6/4/1/1 call
sites are unaffected.

Give the chain a final else as well. It is unreachable while the five
predicates cover every EIdentState, but a sixth state would otherwise
silently blank the field again rather than fail visibly.

No new catalog string: the fallback reuses the _("N/A") the field is
already built with. The catalogs still move, because that msgid's
reference list gains src/ClientRef.cpp.

Not unit-tested: nothing currently links BaseClient/ClientRef, and
CUpDownClient's construction pulls a 49-include closure while the chain
needs theApp for CryptoAvailable(), so a harness would dwarf the fix.
Routing the predicates through the accessor makes the disagreement
unrepresentable instead, which a test could only sample for.
@got3nks
got3nks merged commit 8f3150d into amule-org:master Jul 30, 2026
15 checks passed
@got3nks
got3nks deleted the fix/ident-state-predicates branch July 30, 2026 23:10
LSalami added a commit to LSalami/amule that referenced this pull request Jul 31, 2026
muleToolbar() duplicated several msgid source-location references
(Networks, Searches, Downloads Window, etc.) already present via
amuleDlg.cpp's own toolbar setup. Deleting it drops those now-stale
#: comments; no msgid added, removed, or retranslated -- verified via
unchanged msgid count (1903 before/after) and a diff limited to
source-location comments and POT-Creation-Date.

Regenerated after rebasing onto upstream/master to pick up po/
changes from amule-org#723/amule-org#724/amule-org#726/amule-org#728/amule-org#730/amule-org#731, which had drifted our
prior regeneration out of sync.
got3nks pushed a commit that referenced this pull request Jul 31, 2026
…r.cpp (#675) (#725)

* chore(gui): delete unreachable bitmap functions/entries from muuli_wdr.cpp

First slice of the icon-system cleanup scoped in #675: remove code with
zero call sites anywhere in the tree, before any wxArtProvider migration
work starts.

- muleToolbar(): whole function unused -- superseded by the main
  wxToolBar setup in amuleDlg.cpp; nothing calls it.
- moreImages(): whole function unused, both of its two icon entries.
- amuleDlgImages(): 21 of 35 index blocks have no caller anywhere
  (0-13, 16, 17, 19, 27, 28, 31, 34). The 14 live ones are untouched --
  10 of those (20-26, 29, 32, 33) are already the fallback path inside
  amuleDlg.cpp's Add_Skin_Icon, which prefers a wxArtProvider/SVG lookup
  first; the other 4 (14, 15, 18, 30) are still called directly.
- amuleSpecial(): 6 of 26 index blocks have no caller (6, 7, 8, 9, 18,
  20) -- checked both direct call sites and the PrefsUnifiedDlg.cpp
  fallback table (pages[].m_imageidx), which uses neither.

convert_xpm in PartFileConvertDlg.cpp was on the same "no literal
grep hits" list initially but is not actually dead -- SetIcon(wxICON
(convert)) reaches it via the wxICON macro's token-pasting
(X##_xpm), invisible to a plain identifier search. Caught by a full
build failing on the undeclared identifier, not by inspection; left
untouched.

Deletes 1373 lines (~16% of the file). No behavior change: every
touched entry was unreachable code. clang-format v18 clean; full
amule build verified (macOS, CLIENT_GUI unaffected since neither
touched symbol is CLIENT_GUI-only).

* chore(po): regenerate catalogs after muuli_wdr.cpp dead-code removal

muleToolbar() duplicated several msgid source-location references
(Networks, Searches, Downloads Window, etc.) already present via
amuleDlg.cpp's own toolbar setup. Deleting it drops those now-stale
#: comments; no msgid added, removed, or retranslated -- verified via
unchanged msgid count (1903 before/after) and a diff limited to
source-location comments and POT-Creation-Date.

Regenerated after rebasing onto upstream/master to pick up po/
changes from #723/#724/#726/#728/#730/#731, which had drifted our
prior regeneration out of sync.
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.

The SUI* predicates contradict GetCurrentIdentState() when a client has no credits

1 participant