Skip to content

Commit 02c178d

Browse files
committed
implement new binary request/response for paginated neighbours
1 parent a5af1b5 commit 02c178d

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

examples/simple_repeater/MyMesh.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "MyMesh.h"
2+
#include <algorithm>
23

34
/* ------------------------------ Config -------------------------------- */
45

@@ -46,6 +47,7 @@
4647
#define REQ_TYPE_KEEP_ALIVE 0x02
4748
#define REQ_TYPE_GET_TELEMETRY_DATA 0x03
4849
#define REQ_TYPE_GET_ACCESS_LIST 0x05
50+
#define REQ_TYPE_GET_NEIGHBOURS 0x06
4951

5052
#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
5153

@@ -187,6 +189,98 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
187189
return ofs;
188190
}
189191
}
192+
if (payload[0] == REQ_TYPE_GET_NEIGHBOURS) {
193+
uint8_t request_version = payload[1];
194+
if (request_version == 0) {
195+
196+
// reply data offset (after response sender_timestamp/tag)
197+
int reply_offset = 4;
198+
199+
// get request params
200+
uint8_t count = payload[2]; // how many neighbours to fetch
201+
uint8_t offset = payload[3]; // offset from start of neighbours list
202+
uint8_t order_by = payload[4]; // how to order neighbours. 0=newest_to_oldest, 1=oldest_to_newest, 2=strongest_to_weakest, 3=weakest_to_strongest
203+
uint8_t pubkey_prefix_length = payload[5]; // how many bytes of neighbour pub key we want
204+
// we also send a 4 byte random blob in payload[6...9] to help packet uniqueness
205+
206+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS count=%d, offset=%d, order_by=%d, pubkey_prefix_length=%d", count, offset, order_by, pubkey_prefix_length);
207+
208+
// clamp pub key prefix length to max pub key length
209+
if(pubkey_prefix_length > PUB_KEY_SIZE){
210+
pubkey_prefix_length = PUB_KEY_SIZE;
211+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS invalid pubkey_prefix_length=%d clamping to %d", pubkey_prefix_length, PUB_KEY_SIZE);
212+
}
213+
214+
// create copy of neighbours list, skipping empty entries so we can sort it separately from main list
215+
int16_t neighbours_count = 0;
216+
NeighbourInfo sorted_neighbours[MAX_NEIGHBOURS];
217+
for (int i = 0; i < MAX_NEIGHBOURS; i++) {
218+
auto neighbour = &neighbours[i];
219+
if (neighbour->heard_timestamp > 0) {
220+
sorted_neighbours[neighbours_count] = *neighbour;
221+
neighbours_count++;
222+
}
223+
}
224+
225+
// sort neighbours based on order
226+
if (order_by == 0) {
227+
// sort by newest to oldest
228+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting newest to oldest");
229+
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
230+
return a.heard_timestamp > b.heard_timestamp; // desc
231+
});
232+
} else if (order_by == 1) {
233+
// sort by oldest to newest
234+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting oldest to newest");
235+
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
236+
return a.heard_timestamp < b.heard_timestamp; // asc
237+
});
238+
} else if (order_by == 2) {
239+
// sort by strongest to weakest
240+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting strongest to weakest");
241+
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
242+
return a.snr > b.snr; // desc
243+
});
244+
} else if (order_by == 3) {
245+
// sort by weakest to strongest
246+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting weakest to strongest");
247+
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
248+
return a.snr < b.snr; // asc
249+
});
250+
}
251+
252+
// build results buffer
253+
int results_count = 0;
254+
int results_offset = 0;
255+
uint8_t results_buffer[130];
256+
for(int index = 0; index < count && index + offset < neighbours_count; index++){
257+
258+
// stop if we can't fit another entry in results
259+
int entry_size = pubkey_prefix_length + 4 + 1;
260+
if(results_offset + entry_size > sizeof(results_buffer)){
261+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS no more entries can fit in results buffer");
262+
break;
263+
}
264+
265+
// add next neighbour to results
266+
auto neighbour = &sorted_neighbours[index + offset];
267+
uint32_t heard_seconds_ago = getRTCClock()->getCurrentTime() - neighbour->heard_timestamp;
268+
memcpy(&results_buffer[results_offset], neighbour->id.pub_key, pubkey_prefix_length); results_offset += pubkey_prefix_length;
269+
memcpy(&results_buffer[results_offset], &heard_seconds_ago, 4); results_offset += 4;
270+
memcpy(&results_buffer[results_offset], &neighbour->snr, 1); results_offset += 1;
271+
results_count++;
272+
273+
}
274+
275+
// build reply
276+
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS neighbours_count=%d results_count=%d", neighbours_count, results_count);
277+
memcpy(&reply_data[reply_offset], &neighbours_count, 2); reply_offset += 2;
278+
memcpy(&reply_data[reply_offset], &results_count, 2); reply_offset += 2;
279+
memcpy(&reply_data[reply_offset], &results_buffer, results_offset); reply_offset += results_offset;
280+
281+
return reply_offset;
282+
}
283+
}
190284
return 0; // unknown command
191285
}
192286

0 commit comments

Comments
 (0)