Browse Source

Merge pull request #2672 from meshcore-dev/non-contact-requests

Non contact requests
pull/2642/merge
Liam Cottle 17 hours ago
committed by GitHub
parent
commit
da21d42a2e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      examples/companion_radio/DataStore.cpp
  2. 2
      examples/companion_radio/DataStore.h
  3. 29
      examples/companion_radio/MyMesh.cpp
  4. 4
      examples/companion_radio/MyMesh.h
  5. 40
      src/helpers/BaseChatMesh.cpp
  6. 8
      src/helpers/BaseChatMesh.h

6
examples/companion_radio/DataStore.cpp

@ -309,7 +309,7 @@ File file = openRead(_getContactsChannelsFS(), "/contacts3");
}
}
void DataStore::saveContacts(DataStoreHost* host) {
void DataStore::saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c)) {
File file = openWrite(_getContactsChannelsFS(), "/contacts3");
if (file) {
uint32_t idx = 0;
@ -317,6 +317,10 @@ void DataStore::saveContacts(DataStoreHost* host) {
uint8_t unused = 0;
while (host->getContactForSave(idx, c)) {
if (filter && !filter(c)) {
idx++; // advance to next contact
continue;
}
bool success = (file.write(c.id.pub_key, 32) == 32);
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
success = success && (file.write(&c.type, 1) == 1);

2
examples/companion_radio/DataStore.h

@ -36,7 +36,7 @@ public:
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
void loadContacts(DataStoreHost* host);
void saveContacts(DataStoreHost* host);
void saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL);
void loadChannels(DataStoreHost* host);
void saveChannels(DataStoreHost* host);
void migrateToSecondaryFS();

29
examples/companion_radio/MyMesh.cpp

@ -1536,6 +1536,15 @@ void MyMesh::handleCmdFrame(size_t len) {
} else if (cmd_frame[0] == CMD_SEND_ANON_REQ && len > 1 + PUB_KEY_SIZE) {
uint8_t *pub_key = &cmd_frame[1];
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
ContactInfo anon;
if (recipient == NULL) { // FIRMWARE_VER_CODE 13+, allow non-contact requests
memset(&anon, 0, sizeof(anon));
memcpy(anon.id.pub_key, pub_key, PUB_KEY_SIZE);
anon.out_path_len = 0; // default to zero-hop direct
anon.type = ADV_TYPE_NONE; // unknown
if (addContact(anon)) recipient = &anon;
}
uint8_t *data = &cmd_frame[1 + PUB_KEY_SIZE];
if (recipient) {
uint32_t tag, est_timeout;
@ -1552,7 +1561,7 @@ void MyMesh::handleCmdFrame(size_t len) {
_serial->writeFrame(out_frame, 10);
}
} else {
writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found
writeErrFrame(ERR_CODE_TABLE_FULL); // contacts full
}
} else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1 + PUB_KEY_SIZE) {
uint8_t *pub_key = &cmd_frame[1];
@ -1983,6 +1992,14 @@ void MyMesh::handleCmdFrame(size_t len) {
}
}
static bool save_filter(const ContactInfo& c) {
return c.type != ADV_TYPE_NONE; // don't save the transient/anon entries
}
void MyMesh::saveContacts() {
_store->saveContacts(this, save_filter);
}
void MyMesh::enterCLIRescue() {
_cli_rescue = true;
cli_command[0] = 0;
@ -2169,7 +2186,15 @@ void MyMesh::checkSerialInterface() {
&& !_serial->isWriteBusy() // don't spam the Serial Interface too quickly!
) {
ContactInfo contact;
if (_iter.hasNext(this, contact)) {
bool found = false;
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
writeContactRespFrame(RESP_CODE_CONTACT, contact);
if (contact.lastmod > _most_recent_lastmod) {

4
examples/companion_radio/MyMesh.h

@ -5,7 +5,7 @@
#include "AbstractUITask.h"
/*------------ Frame Protocol --------------*/
#define FIRMWARE_VER_CODE 12
#define FIRMWARE_VER_CODE 13
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "19 Apr 2026"
@ -201,7 +201,7 @@ private:
// helpers, short-cuts
void saveChannels() { _store->saveChannels(this); }
void saveContacts() { _store->saveContacts(this); }
void saveContacts();
DataStore* _store;
NodePrefs _prefs;

40
src/helpers/BaseChatMesh.cpp

@ -67,18 +67,25 @@ void BaseChatMesh::bootstrapRTCfromContacts() {
}
}
ContactInfo* BaseChatMesh::allocateContactSlot() {
ContactInfo* BaseChatMesh::allocateContactSlot(bool transient_only) {
if (num_contacts < MAX_CONTACTS) {
return &contacts[num_contacts++];
} else if (shouldOverwriteWhenFull()) {
} else if (transient_only || shouldOverwriteWhenFull()) {
// Find oldest non-favourite contact by oldest lastmod timestamp
int oldest_idx = -1;
uint32_t oldest_lastmod = 0xFFFFFFFF;
for (int i = 0; i < num_contacts; i++) {
bool is_favourite = (contacts[i].flags & 0x01) != 0;
if (!is_favourite && contacts[i].lastmod < oldest_lastmod) {
oldest_lastmod = contacts[i].lastmod;
oldest_idx = i;
if (transient_only) {
if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) {
oldest_lastmod = contacts[i].lastmod;
oldest_idx = i;
}
} else {
bool is_favourite = (contacts[i].flags & 0x01) != 0;
if (!is_favourite && contacts[i].lastmod < oldest_lastmod && contacts[i].type != ADV_TYPE_NONE) {
oldest_lastmod = contacts[i].lastmod;
oldest_idx = i;
}
}
}
if (oldest_idx >= 0) {
@ -164,16 +171,17 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
from->sync_since = 0;
from->shared_secret_valid = false;
}
// update
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name));
from->type = parser.getType();
if (parser.hasLatLon()) {
from->gps_lat = parser.getIntLat();
from->gps_lon = parser.getIntLon();
}
from->last_advert_timestamp = timestamp;
from->lastmod = getRTCClock()->getCurrentTime();
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name));
from->type = parser.getType();
if (parser.hasLatLon()) {
from->gps_lat = parser.getIntLat();
from->gps_lon = parser.getIntLon();
}
from->last_advert_timestamp = timestamp;
from->lastmod = getRTCClock()->getCurrentTime();
onDiscoveredContact(*from, is_new, packet->path_len, packet->path); // let UI know
}
@ -829,7 +837,7 @@ ContactInfo* BaseChatMesh::lookupContactByPubKey(const uint8_t* pub_key, int pre
}
bool BaseChatMesh::addContact(const ContactInfo& contact) {
ContactInfo* dest = allocateContactSlot();
ContactInfo* dest = allocateContactSlot(contact.type == ADV_TYPE_NONE);
if (dest) {
*dest = contact;
dest->shared_secret_valid = false; // mark shared_secret as needing calculation

8
src/helpers/BaseChatMesh.h

@ -37,6 +37,8 @@ public:
#define MAX_CONTACTS 32
#endif
#define MAX_ANON_CONTACTS 8
#ifndef MAX_CONNECTIONS
#define MAX_CONNECTIONS 16
#endif
@ -58,9 +60,9 @@ class BaseChatMesh : public mesh::Mesh {
friend class ContactsIterator;
ContactInfo contacts[MAX_CONTACTS];
ContactInfo contacts[MAX_CONTACTS+MAX_ANON_CONTACTS];
int num_contacts;
int sort_array[MAX_CONTACTS];
int sort_array[MAX_CONTACTS+MAX_ANON_CONTACTS];
int matching_peer_indexes[MAX_SEARCH_RESULTS];
unsigned long txt_send_timeout;
#ifdef MAX_GROUP_CHANNELS
@ -91,7 +93,7 @@ protected:
void bootstrapRTCfromContacts();
void resetContacts() { num_contacts = 0; }
void populateContactFromAdvert(ContactInfo& ci, const mesh::Identity& id, const AdvertDataParser& parser, uint32_t timestamp);
ContactInfo* allocateContactSlot(); // helper to find slot for new contact
ContactInfo* allocateContactSlot(bool transient_only=false); // helper to find slot for new contact
// 'UI' concepts, for sub-classes to implement
virtual bool isAutoAddEnabled() const { return true; }

Loading…
Cancel
Save