mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
Merge pull request #2672 from meshcore-dev/non-contact-requests
Non contact requests
This commit is contained in:
@@ -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");
|
File file = openWrite(_getContactsChannelsFS(), "/contacts3");
|
||||||
if (file) {
|
if (file) {
|
||||||
uint32_t idx = 0;
|
uint32_t idx = 0;
|
||||||
@@ -317,6 +317,10 @@ void DataStore::saveContacts(DataStoreHost* host) {
|
|||||||
uint8_t unused = 0;
|
uint8_t unused = 0;
|
||||||
|
|
||||||
while (host->getContactForSave(idx, c)) {
|
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);
|
bool success = (file.write(c.id.pub_key, 32) == 32);
|
||||||
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
|
success = success && (file.write((uint8_t *)&c.name, 32) == 32);
|
||||||
success = success && (file.write(&c.type, 1) == 1);
|
success = success && (file.write(&c.type, 1) == 1);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
|
void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon);
|
||||||
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon);
|
||||||
void loadContacts(DataStoreHost* host);
|
void loadContacts(DataStoreHost* host);
|
||||||
void saveContacts(DataStoreHost* host);
|
void saveContacts(DataStoreHost* host, bool (*filter)(const ContactInfo& c) = NULL);
|
||||||
void loadChannels(DataStoreHost* host);
|
void loadChannels(DataStoreHost* host);
|
||||||
void saveChannels(DataStoreHost* host);
|
void saveChannels(DataStoreHost* host);
|
||||||
void migrateToSecondaryFS();
|
void migrateToSecondaryFS();
|
||||||
|
|||||||
@@ -1536,6 +1536,15 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
} else if (cmd_frame[0] == CMD_SEND_ANON_REQ && len > 1 + PUB_KEY_SIZE) {
|
} else if (cmd_frame[0] == CMD_SEND_ANON_REQ && len > 1 + PUB_KEY_SIZE) {
|
||||||
uint8_t *pub_key = &cmd_frame[1];
|
uint8_t *pub_key = &cmd_frame[1];
|
||||||
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
|
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];
|
uint8_t *data = &cmd_frame[1 + PUB_KEY_SIZE];
|
||||||
if (recipient) {
|
if (recipient) {
|
||||||
uint32_t tag, est_timeout;
|
uint32_t tag, est_timeout;
|
||||||
@@ -1552,7 +1561,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
|||||||
_serial->writeFrame(out_frame, 10);
|
_serial->writeFrame(out_frame, 10);
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
} else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1 + PUB_KEY_SIZE) {
|
||||||
uint8_t *pub_key = &cmd_frame[1];
|
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() {
|
void MyMesh::enterCLIRescue() {
|
||||||
_cli_rescue = true;
|
_cli_rescue = true;
|
||||||
cli_command[0] = 0;
|
cli_command[0] = 0;
|
||||||
@@ -2169,7 +2186,15 @@ 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;
|
||||||
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
|
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) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "AbstractUITask.h"
|
#include "AbstractUITask.h"
|
||||||
|
|
||||||
/*------------ Frame Protocol --------------*/
|
/*------------ Frame Protocol --------------*/
|
||||||
#define FIRMWARE_VER_CODE 12
|
#define FIRMWARE_VER_CODE 13
|
||||||
|
|
||||||
#ifndef FIRMWARE_BUILD_DATE
|
#ifndef FIRMWARE_BUILD_DATE
|
||||||
#define FIRMWARE_BUILD_DATE "19 Apr 2026"
|
#define FIRMWARE_BUILD_DATE "19 Apr 2026"
|
||||||
@@ -201,7 +201,7 @@ private:
|
|||||||
|
|
||||||
// helpers, short-cuts
|
// helpers, short-cuts
|
||||||
void saveChannels() { _store->saveChannels(this); }
|
void saveChannels() { _store->saveChannels(this); }
|
||||||
void saveContacts() { _store->saveContacts(this); }
|
void saveContacts();
|
||||||
|
|
||||||
DataStore* _store;
|
DataStore* _store;
|
||||||
NodePrefs _prefs;
|
NodePrefs _prefs;
|
||||||
|
|||||||
@@ -67,18 +67,25 @@ void BaseChatMesh::bootstrapRTCfromContacts() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ContactInfo* BaseChatMesh::allocateContactSlot() {
|
ContactInfo* BaseChatMesh::allocateContactSlot(bool transient_only) {
|
||||||
if (num_contacts < MAX_CONTACTS) {
|
if (num_contacts < MAX_CONTACTS) {
|
||||||
return &contacts[num_contacts++];
|
return &contacts[num_contacts++];
|
||||||
} else if (shouldOverwriteWhenFull()) {
|
} else if (transient_only || shouldOverwriteWhenFull()) {
|
||||||
// Find oldest non-favourite contact by oldest lastmod timestamp
|
// Find oldest non-favourite contact by oldest lastmod timestamp
|
||||||
int oldest_idx = -1;
|
int oldest_idx = -1;
|
||||||
uint32_t oldest_lastmod = 0xFFFFFFFF;
|
uint32_t oldest_lastmod = 0xFFFFFFFF;
|
||||||
for (int i = 0; i < num_contacts; i++) {
|
for (int i = 0; i < num_contacts; i++) {
|
||||||
bool is_favourite = (contacts[i].flags & 0x01) != 0;
|
if (transient_only) {
|
||||||
if (!is_favourite && contacts[i].lastmod < oldest_lastmod) {
|
if (contacts[i].type == ADV_TYPE_NONE && contacts[i].lastmod < oldest_lastmod) {
|
||||||
oldest_lastmod = contacts[i].lastmod;
|
oldest_lastmod = contacts[i].lastmod;
|
||||||
oldest_idx = i;
|
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) {
|
if (oldest_idx >= 0) {
|
||||||
@@ -164,16 +171,17 @@ void BaseChatMesh::onAdvertRecv(mesh::Packet* packet, const mesh::Identity& id,
|
|||||||
from->sync_since = 0;
|
from->sync_since = 0;
|
||||||
from->shared_secret_valid = false;
|
from->shared_secret_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
|
putBlobByKey(id.pub_key, PUB_KEY_SIZE, temp_buf, plen);
|
||||||
StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name));
|
StrHelper::strncpy(from->name, parser.getName(), sizeof(from->name));
|
||||||
from->type = parser.getType();
|
from->type = parser.getType();
|
||||||
if (parser.hasLatLon()) {
|
if (parser.hasLatLon()) {
|
||||||
from->gps_lat = parser.getIntLat();
|
from->gps_lat = parser.getIntLat();
|
||||||
from->gps_lon = parser.getIntLon();
|
from->gps_lon = parser.getIntLon();
|
||||||
}
|
}
|
||||||
from->last_advert_timestamp = timestamp;
|
from->last_advert_timestamp = timestamp;
|
||||||
from->lastmod = getRTCClock()->getCurrentTime();
|
from->lastmod = getRTCClock()->getCurrentTime();
|
||||||
|
|
||||||
onDiscoveredContact(*from, is_new, packet->path_len, packet->path); // let UI know
|
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) {
|
bool BaseChatMesh::addContact(const ContactInfo& contact) {
|
||||||
ContactInfo* dest = allocateContactSlot();
|
ContactInfo* dest = allocateContactSlot(contact.type == ADV_TYPE_NONE);
|
||||||
if (dest) {
|
if (dest) {
|
||||||
*dest = contact;
|
*dest = contact;
|
||||||
dest->shared_secret_valid = false; // mark shared_secret as needing calculation
|
dest->shared_secret_valid = false; // mark shared_secret as needing calculation
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
#define MAX_CONTACTS 32
|
#define MAX_CONTACTS 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MAX_ANON_CONTACTS 8
|
||||||
|
|
||||||
#ifndef MAX_CONNECTIONS
|
#ifndef MAX_CONNECTIONS
|
||||||
#define MAX_CONNECTIONS 16
|
#define MAX_CONNECTIONS 16
|
||||||
#endif
|
#endif
|
||||||
@@ -58,9 +60,9 @@ class BaseChatMesh : public mesh::Mesh {
|
|||||||
|
|
||||||
friend class ContactsIterator;
|
friend class ContactsIterator;
|
||||||
|
|
||||||
ContactInfo contacts[MAX_CONTACTS];
|
ContactInfo contacts[MAX_CONTACTS+MAX_ANON_CONTACTS];
|
||||||
int num_contacts;
|
int num_contacts;
|
||||||
int sort_array[MAX_CONTACTS];
|
int sort_array[MAX_CONTACTS+MAX_ANON_CONTACTS];
|
||||||
int matching_peer_indexes[MAX_SEARCH_RESULTS];
|
int matching_peer_indexes[MAX_SEARCH_RESULTS];
|
||||||
unsigned long txt_send_timeout;
|
unsigned long txt_send_timeout;
|
||||||
#ifdef MAX_GROUP_CHANNELS
|
#ifdef MAX_GROUP_CHANNELS
|
||||||
@@ -91,7 +93,7 @@ protected:
|
|||||||
void bootstrapRTCfromContacts();
|
void bootstrapRTCfromContacts();
|
||||||
void resetContacts() { num_contacts = 0; }
|
void resetContacts() { num_contacts = 0; }
|
||||||
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(); // 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
|
// 'UI' concepts, for sub-classes to implement
|
||||||
virtual bool isAutoAddEnabled() const { return true; }
|
virtual bool isAutoAddEnabled() const { return true; }
|
||||||
|
|||||||
Reference in New Issue
Block a user