From dc7a2827a3dbc529498e47cc7f4ecd9b176cb2dc Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:53:33 +0200 Subject: [PATCH] sync with vanilla dev --- zephcore/app/CompanionMesh.cpp | 11 +++++++++-- zephcore/helpers/BaseChatMesh.cpp | 11 ++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/zephcore/app/CompanionMesh.cpp b/zephcore/app/CompanionMesh.cpp index 5441a11..504d08d 100644 --- a/zephcore/app/CompanionMesh.cpp +++ b/zephcore/app/CompanionMesh.cpp @@ -1677,10 +1677,16 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len) _contact_iter_since = 0; } - // Send PACKET_CONTACT_START with total count (unfiltered) + // Send PACKET_CONTACT_START with total count (unfiltered, but excluding + // transient anon slots -- continueContactIteration() never streams those) + uint32_t total = 0; + for (int i = 0; i < getNumContacts(); i++) { + ContactInfo c; + if (getContactByIdx(i, c) && c.type != ADV_TYPE_NONE) total++; + } uint8_t rsp[5]; rsp[0] = PACKET_CONTACT_START; - put_le32(&rsp[1], (uint32_t)getNumContacts()); + put_le32(&rsp[1], total); writeFrame(rsp, sizeof(rsp)); _contact_iter_idx = 0; _contact_iter_lastmod = 0; @@ -2975,6 +2981,7 @@ bool CompanionMesh::handleProtocolFrame(const uint8_t *data, size_t len) memcpy(anon.id.pub_key, &data[1], PUB_KEY_SIZE); anon.out_path_len = 0; // zero-hop direct by default anon.type = ADV_TYPE_NONE; // transient/unknown + anon.lastmod = getRTCClock()->getCurrentTime(); // so slot recycling is LRU, not always slot 0 if (addContact(anon)) { contact = lookupContactByPubKey(&data[1], PUB_KEY_SIZE); } diff --git a/zephcore/helpers/BaseChatMesh.cpp b/zephcore/helpers/BaseChatMesh.cpp index 1cb5594..e8f283c 100644 --- a/zephcore/helpers/BaseChatMesh.cpp +++ b/zephcore/helpers/BaseChatMesh.cpp @@ -107,7 +107,11 @@ ContactInfo *BaseChatMesh::allocateContactSlot(bool transient_only) } } if (oldest_idx >= 0) { - onContactOverwrite(contacts[oldest_idx].id.pub_key); + if (!transient_only) { + // recycling an anon slot isn't a "contact deleted" event -- the + // app was never told this transient pubkey existed + onContactOverwrite(contacts[oldest_idx].id.pub_key); + } return &contacts[oldest_idx]; } } @@ -165,6 +169,11 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet *packet, const mesh::Identity &id, packet->header = save; } + if (from && from->type == ADV_TYPE_NONE) { // matched a transient anon/ANON_REQ slot -- promote to a real contact + *from = ContactInfo{}; + from = nullptr; + } + bool is_new = false; if (from == nullptr) { LOG_DBG("onAdvertRecv: new contact, checking auto-add for type %d", parser.getType());