Browse Source

Merge pull request #2763 from meshcore-dev/anon-contacts-fix

* fix for anon contacts when full
dev
Huw Duddy 1 day ago
committed by GitHub
parent
commit
29f0a7fc4f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 13
      examples/companion_radio/MyMesh.cpp
  2. 2
      examples/simple_secure_chat/main.cpp
  3. 52
      src/helpers/BaseChatMesh.cpp
  4. 17
      src/helpers/BaseChatMesh.h

13
examples/companion_radio/MyMesh.cpp

@ -854,7 +854,7 @@ void MyMesh::onSendTimeout() {}
MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui) MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMeshTables &tables, DataStore& store, AbstractUITask* ui)
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables), : BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables),
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui) { _serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui), _iter(0) {
_iter_started = false; _iter_started = false;
_cli_rescue = false; _cli_rescue = false;
offline_queue_len = 0; offline_queue_len = 0;
@ -1542,6 +1542,7 @@ void MyMesh::handleCmdFrame(size_t len) {
memcpy(anon.id.pub_key, pub_key, PUB_KEY_SIZE); memcpy(anon.id.pub_key, pub_key, PUB_KEY_SIZE);
anon.out_path_len = 0; // default to zero-hop direct anon.out_path_len = 0; // default to zero-hop direct
anon.type = ADV_TYPE_NONE; // unknown anon.type = ADV_TYPE_NONE; // unknown
anon.lastmod = getRTCClock()->getCurrentTime();
if (addContact(anon)) recipient = &anon; if (addContact(anon)) recipient = &anon;
} }
@ -2187,15 +2188,7 @@ void MyMesh::checkSerialInterface() {
&& !_serial->isWriteBusy() // don't spam the Serial Interface too quickly! && !_serial->isWriteBusy() // don't spam the Serial Interface too quickly!
) { ) {
ContactInfo contact; ContactInfo contact;
bool found = false; if (_iter.hasNext(this, contact)) {
while (_iter.hasNext(this, contact)) {
if (contact.type != ADV_TYPE_NONE) {
found = true;
break;
}
}
if (found) {
if (contact.lastmod > _iter_filter_since) { // apply the 'since' filter if (contact.lastmod > _iter_filter_since) { // apply the 'since' filter
writeContactRespFrame(RESP_CODE_CONTACT, contact); writeContactRespFrame(RESP_CODE_CONTACT, contact);
if (contact.lastmod > _most_recent_lastmod) { if (contact.lastmod > _most_recent_lastmod) {

2
examples/simple_secure_chat/main.cpp

@ -135,7 +135,7 @@ class MyMesh : public BaseChatMesh, ContactVisitor {
File file = _fs->open("/contacts", "w", true); File file = _fs->open("/contacts", "w", true);
#endif #endif
if (file) { if (file) {
ContactsIterator iter; ContactsIterator iter = startContactsIterator();
ContactInfo c; ContactInfo c;
uint8_t unused = 0; uint8_t unused = 0;
uint32_t reserved = 0; uint32_t reserved = 0;

52
src/helpers/BaseChatMesh.cpp

@ -68,29 +68,36 @@ void BaseChatMesh::bootstrapRTCfromContacts() {
} }
ContactInfo* BaseChatMesh::allocateContactSlot(bool transient_only) { ContactInfo* BaseChatMesh::allocateContactSlot(bool transient_only) {
if (num_contacts < MAX_CONTACTS) { int oldest_idx = -1;
return &contacts[num_contacts++]; uint32_t oldest_lastmod = 0xFFFFFFFF;
} else if (transient_only || shouldOverwriteWhenFull()) { if (transient_only) {
// Find oldest non-favourite contact by oldest lastmod timestamp // only allocate from first N
int oldest_idx = -1; for (int i = 0; i < MAX_ANON_CONTACTS; i++) {
uint32_t oldest_lastmod = 0xFFFFFFFF; if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) {
for (int i = 0; i < num_contacts; i++) { oldest_lastmod = contacts[i].lastmod;
if (transient_only) { oldest_idx = i;
if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) { }
oldest_lastmod = contacts[i].lastmod; }
oldest_idx = i; if (oldest_idx >= 0) {
} // NOTE: do NOT call onContactOverwrite()
} else { return &contacts[oldest_idx];
}
} else {
if (num_contacts < MAX_ANON_CONTACTS+MAX_CONTACTS) {
return &contacts[num_contacts++];
} else if (shouldOverwriteWhenFull()) {
// Find oldest non-favourite contact by oldest lastmod timestamp
for (int i = MAX_ANON_CONTACTS; i < num_contacts; i++) {
bool is_favourite = (contacts[i].flags & 0x01) != 0; bool is_favourite = (contacts[i].flags & 0x01) != 0;
if (!is_favourite && contacts[i].lastmod < oldest_lastmod && contacts[i].type != ADV_TYPE_NONE) { if (!is_favourite && contacts[i].lastmod < oldest_lastmod) {
oldest_lastmod = contacts[i].lastmod; oldest_lastmod = contacts[i].lastmod;
oldest_idx = i; oldest_idx = i;
} }
} }
} if (oldest_idx >= 0) {
if (oldest_idx >= 0) { onContactOverwrite(contacts[oldest_idx].id.pub_key);
onContactOverwrite(contacts[oldest_idx].id.pub_key); return &contacts[oldest_idx];
return &contacts[oldest_idx]; }
} }
} }
return NULL; // no space, no overwrite or all contacts are all favourites 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,
packet->header = save; packet->header = save;
} }
if (from && from->type == ADV_TYPE_NONE) { // already in contacts, but from a temporary ANON_REQ ?
memset(from, 0, sizeof(*from)); // clear the anon/temp slot
from = NULL; // do normal 'add' flow
}
bool is_new = false; // true = not in contacts[], false = exists in contacts[] bool is_new = false; // true = not in contacts[], false = exists in contacts[]
if (from == NULL) { if (from == NULL) {
if (!shouldAutoAddContactType(parser.getType())) { if (!shouldAutoAddContactType(parser.getType())) {
@ -930,11 +942,11 @@ bool BaseChatMesh::getContactByIdx(uint32_t idx, ContactInfo& contact) {
} }
ContactsIterator BaseChatMesh::startContactsIterator() { ContactsIterator BaseChatMesh::startContactsIterator() {
return ContactsIterator(); return ContactsIterator(MAX_ANON_CONTACTS); // start at offset, skip the anon entries
} }
bool ContactsIterator::hasNext(const BaseChatMesh* mesh, ContactInfo& dest) { bool ContactsIterator::hasNext(const BaseChatMesh* mesh, ContactInfo& dest) {
if (next_idx >= mesh->getNumContacts()) return false; if (next_idx >= mesh->getTotalContactSlots()) return false;
dest = mesh->contacts[next_idx++]; dest = mesh->contacts[next_idx++];
return true; return true;

17
src/helpers/BaseChatMesh.h

@ -28,8 +28,9 @@ public:
class BaseChatMesh; class BaseChatMesh;
class ContactsIterator { class ContactsIterator {
int next_idx = 0; int next_idx;
public: public:
ContactsIterator(int start) { next_idx = start; }
bool hasNext(const BaseChatMesh* mesh, ContactInfo& dest); bool hasNext(const BaseChatMesh* mesh, ContactInfo& dest);
}; };
@ -79,8 +80,9 @@ class BaseChatMesh : public mesh::Mesh {
protected: protected:
BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables) BaseChatMesh(mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::PacketManager& mgr, mesh::MeshTables& tables)
: mesh::Mesh(radio, ms, rng, rtc, mgr, tables) : mesh::Mesh(radio, ms, rng, rtc, mgr, tables)
{ {
num_contacts = 0; resetContacts();
#ifdef MAX_GROUP_CHANNELS #ifdef MAX_GROUP_CHANNELS
memset(channels, 0, sizeof(channels)); memset(channels, 0, sizeof(channels));
num_channels = 0; num_channels = 0;
@ -91,7 +93,11 @@ protected:
} }
void bootstrapRTCfromContacts(); void bootstrapRTCfromContacts();
void resetContacts() { num_contacts = 0; }
void resetContacts() {
memset(contacts, 0, sizeof(contacts[0])*MAX_ANON_CONTACTS); // set all to have type = ADV_TYPE_NONE(0)
num_contacts = MAX_ANON_CONTACTS; // seed the first contacts for anon requests
}
void populateContactFromAdvert(ContactInfo& ci, const mesh::Identity& id, const AdvertDataParser& parser, uint32_t timestamp); void populateContactFromAdvert(ContactInfo& ci, const mesh::Identity& id, const AdvertDataParser& parser, uint32_t timestamp);
ContactInfo* allocateContactSlot(bool transient_only=false); // helper to find slot for new contact ContactInfo* allocateContactSlot(bool transient_only=false); // helper to find slot for new contact
@ -166,7 +172,8 @@ public:
ContactInfo* lookupContactByPubKey(const uint8_t* pub_key, int prefix_len); ContactInfo* lookupContactByPubKey(const uint8_t* pub_key, int prefix_len);
bool removeContact(ContactInfo& contact); bool removeContact(ContactInfo& contact);
bool addContact(const ContactInfo& contact); bool addContact(const ContactInfo& contact);
int getNumContacts() const { return num_contacts; } int getTotalContactSlots() const { return num_contacts; }
int getNumContacts() const { return num_contacts - MAX_ANON_CONTACTS; } // don't include the reserved slots at start
bool getContactByIdx(uint32_t idx, ContactInfo& contact); bool getContactByIdx(uint32_t idx, ContactInfo& contact);
ContactsIterator startContactsIterator(); ContactsIterator startContactsIterator();
ChannelDetails* addChannel(const char* name, const char* psk_base64); ChannelDetails* addChannel(const char* name, const char* psk_base64);

Loading…
Cancel
Save