Skip to content

Commit 29f0a7f

Browse files
authored
Merge pull request meshcore-dev#2763 from meshcore-dev/anon-contacts-fix
* fix for anon contacts when full
2 parents a5cb0c2 + 2e73fe9 commit 29f0a7f

4 files changed

Lines changed: 48 additions & 36 deletions

File tree

examples/companion_radio/MyMesh.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,7 @@ void MyMesh::onSendTimeout() {}
854854

855855
MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui)
856856
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables),
857-
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui) {
857+
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui), _iter(0) {
858858
_iter_started = false;
859859
_cli_rescue = false;
860860
offline_queue_len = 0;
@@ -1542,6 +1542,7 @@ void MyMesh::handleCmdFrame(size_t len) {
15421542
memcpy(anon.id.pub_key, pub_key, PUB_KEY_SIZE);
15431543
anon.out_path_len = 0; // default to zero-hop direct
15441544
anon.type = ADV_TYPE_NONE; // unknown
1545+
anon.lastmod = getRTCClock()->getCurrentTime();
15451546

15461547
if (addContact(anon)) recipient = &anon;
15471548
}
@@ -2187,15 +2188,7 @@ void MyMesh::checkSerialInterface() {
21872188
&& !_serial->isWriteBusy() // don't spam the Serial Interface too quickly!
21882189
) {
21892190
ContactInfo contact;
2190-
bool found = false;
2191-
while (_iter.hasNext(this, contact)) {
2192-
if (contact.type != ADV_TYPE_NONE) {
2193-
found = true;
2194-
break;
2195-
}
2196-
}
2197-
2198-
if (found) {
2191+
if (_iter.hasNext(this, contact)) {
21992192
if (contact.lastmod > _iter_filter_since) { // apply the 'since' filter
22002193
writeContactRespFrame(RESP_CODE_CONTACT, contact);
22012194
if (contact.lastmod > _most_recent_lastmod) {

examples/simple_secure_chat/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ class MyMesh : public BaseChatMesh, ContactVisitor {
135135
File file = _fs->open("/contacts", "w", true);
136136
#endif
137137
if (file) {
138-
ContactsIterator iter;
138+
ContactsIterator iter = startContactsIterator();
139139
ContactInfo c;
140140
uint8_t unused = 0;
141141
uint32_t reserved = 0;

src/helpers/BaseChatMesh.cpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,36 @@ void BaseChatMesh::bootstrapRTCfromContacts() {
6868
}
6969

7070
ContactInfo* BaseChatMesh::allocateContactSlot(bool transient_only) {
71-
if (num_contacts < MAX_CONTACTS) {
72-
return &contacts[num_contacts++];
73-
} else if (transient_only || shouldOverwriteWhenFull()) {
74-
// Find oldest non-favourite contact by oldest lastmod timestamp
75-
int oldest_idx = -1;
76-
uint32_t oldest_lastmod = 0xFFFFFFFF;
77-
for (int i = 0; i < num_contacts; i++) {
78-
if (transient_only) {
79-
if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) {
80-
oldest_lastmod = contacts[i].lastmod;
81-
oldest_idx = i;
82-
}
83-
} else {
71+
int oldest_idx = -1;
72+
uint32_t oldest_lastmod = 0xFFFFFFFF;
73+
if (transient_only) {
74+
// only allocate from first N
75+
for (int i = 0; i < MAX_ANON_CONTACTS; i++) {
76+
if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) {
77+
oldest_lastmod = contacts[i].lastmod;
78+
oldest_idx = i;
79+
}
80+
}
81+
if (oldest_idx >= 0) {
82+
// NOTE: do NOT call onContactOverwrite()
83+
return &contacts[oldest_idx];
84+
}
85+
} else {
86+
if (num_contacts < MAX_ANON_CONTACTS+MAX_CONTACTS) {
87+
return &contacts[num_contacts++];
88+
} else if (shouldOverwriteWhenFull()) {
89+
// Find oldest non-favourite contact by oldest lastmod timestamp
90+
for (int i = MAX_ANON_CONTACTS; i < num_contacts; i++) {
8491
bool is_favourite = (contacts[i].flags & 0x01) != 0;
85-
if (!is_favourite && contacts[i].lastmod < oldest_lastmod && contacts[i].type != ADV_TYPE_NONE) {
92+
if (!is_favourite && contacts[i].lastmod < oldest_lastmod) {
8693
oldest_lastmod = contacts[i].lastmod;
8794
oldest_idx = i;
8895
}
8996
}
90-
}
91-
if (oldest_idx >= 0) {
92-
onContactOverwrite(contacts[oldest_idx].id.pub_key);
93-
return &contacts[oldest_idx];
97+
if (oldest_idx >= 0) {
98+
onContactOverwrite(contacts[oldest_idx].id.pub_key);
99+
return &contacts[oldest_idx];
100+
}
94101
}
95102
}
96103
return NULL; // no space, no overwrite or all contacts are all favourites
@@ -139,6 +146,11 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
139146
packet->header = save;
140147
}
141148

149+
if (from && from->type == ADV_TYPE_NONE) { // already in contacts, but from a temporary ANON_REQ ?
150+
memset(from, 0, sizeof(*from)); // clear the anon/temp slot
151+
from = NULL; // do normal 'add' flow
152+
}
153+
142154
bool is_new = false; // true = not in contacts[], false = exists in contacts[]
143155
if (from == NULL) {
144156
if (!shouldAutoAddContactType(parser.getType())) {
@@ -930,11 +942,11 @@ bool BaseChatMesh::getContactByIdx(uint32_t idx, ContactInfo& contact) {
930942
}
931943

932944
ContactsIterator BaseChatMesh::startContactsIterator() {
933-
return ContactsIterator();
945+
return ContactsIterator(MAX_ANON_CONTACTS); // start at offset, skip the anon entries
934946
}
935947

936948
bool ContactsIterator::hasNext(const BaseChatMesh* mesh, ContactInfo& dest) {
937-
if (next_idx >= mesh->getNumContacts()) return false;
949+
if (next_idx >= mesh->getTotalContactSlots()) return false;
938950

939951
dest = mesh->contacts[next_idx++];
940952
return true;

src/helpers/BaseChatMesh.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ class ContactVisitor {
2828
class BaseChatMesh;
2929

3030
class ContactsIterator {
31-
int next_idx = 0;
31+
int next_idx;
3232
public:
33+
ContactsIterator(int start) { next_idx = start; }
3334
bool hasNext(const BaseChatMesh* mesh, ContactInfo& dest);
3435
};
3536

@@ -79,8 +80,9 @@ class BaseChatMesh : public mesh::Mesh {
7980
protected:
8081
BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)
8182
: mesh::Mesh(radio, ms, rng, rtc, mgr, tables)
82-
{
83-
num_contacts = 0;
83+
{
84+
resetContacts();
85+
8486
#ifdef MAX_GROUP_CHANNELS
8587
memset(channels, 0, sizeof(channels));
8688
num_channels = 0;
@@ -91,7 +93,11 @@ class BaseChatMesh : public mesh::Mesh {
9193
}
9294

9395
void bootstrapRTCfromContacts();
94-
void resetContacts() { num_contacts = 0; }
96+
97+
void resetContacts() {
98+
memset(contacts, 0, sizeof(contacts[0])*MAX_ANON_CONTACTS); // set all to have type = ADV_TYPE_NONE(0)
99+
num_contacts = MAX_ANON_CONTACTS; // seed the first contacts for anon requests
100+
}
95101
void populateContactFromAdvert(ContactInfo& ci, const mesh::Identity& id, const AdvertDataParser& parser, uint32_t timestamp);
96102
ContactInfo* allocateContactSlot(bool transient_only=false); // helper to find slot for new contact
97103

@@ -166,7 +172,8 @@ class BaseChatMesh : public mesh::Mesh {
166172
ContactInfo* lookupContactByPubKey(const uint8_t* pub_key, int prefix_len);
167173
bool removeContact(ContactInfo& contact);
168174
bool addContact(const ContactInfo& contact);
169-
int getNumContacts() const { return num_contacts; }
175+
int getTotalContactSlots() const { return num_contacts; }
176+
int getNumContacts() const { return num_contacts - MAX_ANON_CONTACTS; } // don't include the reserved slots at start
170177
bool getContactByIdx(uint32_t idx, ContactInfo& contact);
171178
ContactsIterator startContactsIterator();
172179
ChannelDetails* addChannel(const char* name, const char* psk_base64);

0 commit comments

Comments
 (0)