Skip to content

Commit 3af2549

Browse files
author
Scott Powell
committed
* Repeater: new anon request sub-type: ANON_REQ_TYPE_REGIONS (rate limited to max 4 every 3 mins)
* Companion: new CMD_SEND_ANON_REQ command (reply with existing RESP_CODE_SENT frame)
1 parent e31c46f commit 3af2549

File tree

7 files changed

+104
-12
lines changed

7 files changed

+104
-12
lines changed

examples/companion_radio/MyMesh.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#define CMD_SET_FLOOD_SCOPE 54 // v8+
5454
#define CMD_SEND_CONTROL_DATA 55 // v8+
5555
#define CMD_GET_STATS 56 // v8+, second byte is stats type
56+
#define CMD_SEND_ANON_REQ 57
5657

5758
// Stats sub-types for CMD_GET_STATS
5859
#define STATS_TYPE_CORE 0
@@ -1286,6 +1287,27 @@ void MyMesh::handleCmdFrame(size_t len) {
12861287
} else {
12871288
writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found
12881289
}
1290+
} else if (cmd_frame[0] == CMD_SEND_ANON_REQ && len > 1 + PUB_KEY_SIZE) {
1291+
uint8_t *pub_key = &cmd_frame[1];
1292+
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);
1293+
uint8_t *data = &cmd_frame[1 + PUB_KEY_SIZE];
1294+
if (recipient) {
1295+
uint32_t tag, est_timeout;
1296+
int result = sendAnonReq(*recipient, data, len - (1 + PUB_KEY_SIZE), tag, est_timeout);
1297+
if (result == MSG_SEND_FAILED) {
1298+
writeErrFrame(ERR_CODE_TABLE_FULL);
1299+
} else {
1300+
clearPendingReqs();
1301+
pending_req = tag; // match this to onContactResponse()
1302+
out_frame[0] = RESP_CODE_SENT;
1303+
out_frame[1] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0;
1304+
memcpy(&out_frame[2], &tag, 4);
1305+
memcpy(&out_frame[6], &est_timeout, 4);
1306+
_serial->writeFrame(out_frame, 10);
1307+
}
1308+
} else {
1309+
writeErrFrame(ERR_CODE_NOT_FOUND); // contact not found
1310+
}
12891311
} else if (cmd_frame[0] == CMD_SEND_STATUS_REQ && len >= 1 + PUB_KEY_SIZE) {
12901312
uint8_t *pub_key = &cmd_frame[1];
12911313
ContactInfo *recipient = lookupContactByPubKey(pub_key, PUB_KEY_SIZE);

examples/simple_repeater/MyMesh.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151

5252
#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
5353

54+
#define ANON_REQ_TYPE_REGIONS 0x01
55+
5456
#define CLI_REPLY_DELAY_MILLIS 600
5557

5658
#define LAZY_CONTACTS_WRITE_DELAY 5000
@@ -139,6 +141,19 @@ uint8_t MyMesh::handleLoginReq(const mesh::Identity& sender, const uint8_t* secr
139141
return 13; // reply length
140142
}
141143

144+
uint8_t MyMesh::handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data) {
145+
// REVISIT: should there be params like 'since' in request data[] ?
146+
if (regions_limiter.allow(rtc_clock.getCurrentTime())) {
147+
memcpy(reply_data, &sender_timestamp, 4); // prefix with sender_timestamp, like a tag
148+
149+
uint32_t now = getRTCClock()->getCurrentTime();
150+
memcpy(&reply_data[4], &now, 4); // include our clock (for easy clock sync, if this is a trusted node)
151+
152+
return 8 + region_map.exportNamesTo((char *) &reply_data[8], sizeof(reply_data) - 12, REGION_DENY_FLOOD); // reply length
153+
}
154+
return 0;
155+
}
156+
142157
int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t *payload, size_t payload_len) {
143158
// uint32_t now = getRTCClock()->getCurrentTimeUnique();
144159
// memcpy(reply_data, &now, 4); // response packets always prefixed with timestamp
@@ -450,8 +465,8 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
450465
uint8_t reply_len;
451466
if (data[4] == 0 || data[4] >= ' ') { // is password, ie. a login request
452467
reply_len = handleLoginReq(sender, secret, timestamp, &data[4], packet->isRouteFlood());
453-
//} else if (data[4] == ANON_REQ_TYPE_*) { // future type codes
454-
// TODO
468+
} else if (data[4] == ANON_REQ_TYPE_REGIONS) {
469+
reply_len = handleAnonRegionsReq(sender, timestamp, &data[5]);
455470
} else {
456471
reply_len = 0; // unknown request type
457472
}
@@ -668,7 +683,8 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
668683
mesh::RTCClock &rtc, mesh::MeshTables &tables)
669684
: mesh::Mesh(radio, ms, rng, rtc, *new StaticPoolPacketManager(32), tables),
670685
_cli(board, rtc, sensors, &_prefs, this), telemetry(MAX_PACKET_PAYLOAD - 4), region_map(key_store), temp_map(key_store),
671-
discover_limiter(4, 120) // max 4 every 2 minutes
686+
discover_limiter(4, 120), // max 4 every 2 minutes
687+
regions_limiter(4, 180) // max 4 every 3 minutes
672688
#if defined(WITH_RS232_BRIDGE)
673689
, bridge(&_prefs, WITH_RS232_BRIDGE, _mgr, &rtc)
674690
#endif

examples/simple_repeater/MyMesh.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
9393
RegionMap region_map, temp_map;
9494
RegionEntry* load_stack[8];
9595
RegionEntry* recv_pkt_region;
96-
RateLimiter discover_limiter;
96+
RateLimiter discover_limiter, regions_limiter;
9797
bool region_load_active;
9898
unsigned long dirty_contacts_expiry;
9999
#if MAX_NEIGHBOURS
@@ -114,6 +114,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
114114

115115
void putNeighbour(const mesh::Identity& id, uint32_t timestamp, float snr);
116116
uint8_t handleLoginReq(const mesh::Identity& sender, const uint8_t* secret, uint32_t sender_timestamp, const uint8_t* data, bool is_flood);
117+
uint8_t handleAnonRegionsReq(const mesh::Identity& sender, uint32_t sender_timestamp, const uint8_t* data);
117118
int handleRequest(ClientInfo* sender, uint32_t sender_timestamp, uint8_t* payload, size_t payload_len);
118119
mesh::Packet* createSelfAdvert();
119120

src/helpers/BaseChatMesh.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,31 @@ int BaseChatMesh::sendLogin(const ContactInfo& recipient, const char* password,
477477
return MSG_SEND_FAILED;
478478
}
479479

480+
int BaseChatMesh::sendAnonReq(const ContactInfo& recipient, const uint8_t* data, uint8_t len, uint32_t& tag, uint32_t& est_timeout) {
481+
mesh::Packet* pkt;
482+
{
483+
uint8_t temp[MAX_PACKET_PAYLOAD];
484+
tag = getRTCClock()->getCurrentTimeUnique();
485+
memcpy(temp, &tag, 4); // tag to match later (also extra blob to help make packet_hash unique)
486+
memcpy(&temp[4], data, len);
487+
488+
pkt = createAnonDatagram(PAYLOAD_TYPE_ANON_REQ, self_id, recipient.id, recipient.getSharedSecret(self_id), temp, 4 + len);
489+
}
490+
if (pkt) {
491+
uint32_t t = _radio->getEstAirtimeFor(pkt->getRawLength());
492+
if (recipient.out_path_len < 0) {
493+
sendFloodScoped(recipient, pkt);
494+
est_timeout = calcFloodTimeoutMillisFor(t);
495+
return MSG_SEND_SENT_FLOOD;
496+
} else {
497+
sendDirect(pkt, recipient.out_path, recipient.out_path_len);
498+
est_timeout = calcDirectTimeoutMillisFor(t, recipient.out_path_len);
499+
return MSG_SEND_SENT_DIRECT;
500+
}
501+
}
502+
return MSG_SEND_FAILED;
503+
}
504+
480505
int BaseChatMesh::sendRequest(const ContactInfo& recipient, const uint8_t* req_data, uint8_t data_len, uint32_t& tag, uint32_t& est_timeout) {
481506
if (data_len > MAX_PACKET_PAYLOAD - 16) return MSG_SEND_FAILED;
482507

src/helpers/BaseChatMesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class BaseChatMesh : public mesh::Mesh {
141141
int sendCommandData(const ContactInfo& recipient, uint32_t timestamp, uint8_t attempt, const char* text, uint32_t& est_timeout);
142142
bool sendGroupMessage(uint32_t timestamp, mesh::GroupChannel& channel, const char* sender_name, const char* text, int text_len);
143143
int sendLogin(const ContactInfo& recipient, const char* password, uint32_t& est_timeout);
144+
int sendAnonReq(const ContactInfo& recipient, const uint8_t* data, uint8_t len, uint32_t& tag, uint32_t& est_timeout);
144145
int sendRequest(const ContactInfo& recipient, uint8_t req_type, uint32_t& tag, uint32_t& est_timeout);
145146
int sendRequest(const ContactInfo& recipient, const uint8_t* req_data, uint8_t data_len, uint32_t& tag, uint32_t& est_timeout);
146147
bool shareContactZeroHop(const ContactInfo& contact);

src/helpers/RegionMap.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ static File openWrite(FILESYSTEM* _fs, const char* filename) {
2424
#endif
2525
}
2626

27-
bool RegionMap::load(FILESYSTEM* _fs) {
28-
if (_fs->exists("/regions2")) {
27+
bool RegionMap::load(FILESYSTEM* _fs, const char* path) {
28+
if (_fs->exists(path ? path : "/regions2")) {
2929
#if defined(RP2040_PLATFORM)
30-
File file = _fs->open("/regions2", "r");
30+
File file = _fs->open(path ? path : "/regions2", "r");
3131
#else
32-
File file = _fs->open("/regions2");
32+
File file = _fs->open(path ? path : "/regions2");
3333
#endif
3434

3535
if (file) {
@@ -67,8 +67,8 @@ bool RegionMap::load(FILESYSTEM* _fs) {
6767
return false; // failed
6868
}
6969

70-
bool RegionMap::save(FILESYSTEM* _fs) {
71-
File file = openWrite(_fs, "/regions2");
70+
bool RegionMap::save(FILESYSTEM* _fs, const char* path) {
71+
File file = openWrite(_fs, path ? path : "/regions2");
7272
if (file) {
7373
uint8_t pad[128];
7474
memset(pad, 0, sizeof(pad));
@@ -235,3 +235,27 @@ void RegionMap::printChildRegions(int indent, const RegionEntry* parent, Stream&
235235
void RegionMap::exportTo(Stream& out) const {
236236
printChildRegions(0, &wildcard, out); // recursive
237237
}
238+
239+
int RegionMap::exportNamesTo(char *dest, int max_len, uint8_t mask) {
240+
char *dp = dest;
241+
if ((wildcard.flags & mask) == 0) {
242+
*dp++ = '*';
243+
*dp++ = ',';
244+
}
245+
246+
for (int i = 0; i < num_regions; i++) {
247+
auto region = &regions[i];
248+
if ((region->flags & mask) == 0) { // region allowed? (per 'mask' param)
249+
int len = strlen(region->name);
250+
if ((dp - dest) + len + 2 < max_len) { // only append if name will fit
251+
memcpy(dp, region->name, len);
252+
dp += len;
253+
*dp++ = ',';
254+
}
255+
}
256+
}
257+
if (dp > dest) { dp--; } // don't include trailing comma
258+
259+
*dp = 0; // set null terminator
260+
return dp - dest; // return length
261+
}

src/helpers/RegionMap.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ class RegionMap {
3232

3333
static bool is_name_char(char c);
3434

35-
bool load(FILESYSTEM* _fs);
36-
bool save(FILESYSTEM* _fs);
35+
bool load(FILESYSTEM* _fs, const char* path=NULL);
36+
bool save(FILESYSTEM* _fs, const char* path=NULL);
3737

3838
RegionEntry* putRegion(const char* name, uint16_t parent_id, uint16_t id = 0);
3939
RegionEntry* findMatch(mesh::Packet* packet, uint8_t mask);
@@ -47,6 +47,9 @@ class RegionMap {
4747
bool clear();
4848
void resetFrom(const RegionMap& src) { num_regions = 0; next_id = src.next_id; }
4949
int getCount() const { return num_regions; }
50+
const RegionEntry* getByIdx(int i) const { return &regions[i]; }
51+
const RegionEntry* getRoot() const { return &wildcard; }
52+
int exportNamesTo(char *dest, int max_len, uint8_t mask);
5053

5154
void exportTo(Stream& out) const;
5255
};

0 commit comments

Comments
 (0)