mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-03-30 17:05:52 +00:00
implement new binary request/response for paginated neighbours
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "MyMesh.h"
|
||||
#include <algorithm>
|
||||
|
||||
/* ------------------------------ Config -------------------------------- */
|
||||
|
||||
@@ -46,6 +47,7 @@
|
||||
#define REQ_TYPE_KEEP_ALIVE 0x02
|
||||
#define REQ_TYPE_GET_TELEMETRY_DATA 0x03
|
||||
#define REQ_TYPE_GET_ACCESS_LIST 0x05
|
||||
#define REQ_TYPE_GET_NEIGHBOURS 0x06
|
||||
|
||||
#define RESP_SERVER_LOGIN_OK 0 // response to ANON_REQ
|
||||
|
||||
@@ -187,6 +189,98 @@ int MyMesh::handleRequest(ClientInfo *sender, uint32_t sender_timestamp, uint8_t
|
||||
return ofs;
|
||||
}
|
||||
}
|
||||
if (payload[0] == REQ_TYPE_GET_NEIGHBOURS) {
|
||||
uint8_t request_version = payload[1];
|
||||
if (request_version == 0) {
|
||||
|
||||
// reply data offset (after response sender_timestamp/tag)
|
||||
int reply_offset = 4;
|
||||
|
||||
// get request params
|
||||
uint8_t count = payload[2]; // how many neighbours to fetch
|
||||
uint8_t offset = payload[3]; // offset from start of neighbours list
|
||||
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
|
||||
uint8_t pubkey_prefix_length = payload[5]; // how many bytes of neighbour pub key we want
|
||||
// we also send a 4 byte random blob in payload[6...9] to help packet uniqueness
|
||||
|
||||
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);
|
||||
|
||||
// clamp pub key prefix length to max pub key length
|
||||
if(pubkey_prefix_length > PUB_KEY_SIZE){
|
||||
pubkey_prefix_length = PUB_KEY_SIZE;
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS invalid pubkey_prefix_length=%d clamping to %d", pubkey_prefix_length, PUB_KEY_SIZE);
|
||||
}
|
||||
|
||||
// create copy of neighbours list, skipping empty entries so we can sort it separately from main list
|
||||
int16_t neighbours_count = 0;
|
||||
NeighbourInfo sorted_neighbours[MAX_NEIGHBOURS];
|
||||
for (int i = 0; i < MAX_NEIGHBOURS; i++) {
|
||||
auto neighbour = &neighbours[i];
|
||||
if (neighbour->heard_timestamp > 0) {
|
||||
sorted_neighbours[neighbours_count] = *neighbour;
|
||||
neighbours_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// sort neighbours based on order
|
||||
if (order_by == 0) {
|
||||
// sort by newest to oldest
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting newest to oldest");
|
||||
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
|
||||
return a.heard_timestamp > b.heard_timestamp; // desc
|
||||
});
|
||||
} else if (order_by == 1) {
|
||||
// sort by oldest to newest
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting oldest to newest");
|
||||
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
|
||||
return a.heard_timestamp < b.heard_timestamp; // asc
|
||||
});
|
||||
} else if (order_by == 2) {
|
||||
// sort by strongest to weakest
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting strongest to weakest");
|
||||
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
|
||||
return a.snr > b.snr; // desc
|
||||
});
|
||||
} else if (order_by == 3) {
|
||||
// sort by weakest to strongest
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS sorting weakest to strongest");
|
||||
std::sort(sorted_neighbours, sorted_neighbours + neighbours_count, [](const NeighbourInfo &a, const NeighbourInfo &b) {
|
||||
return a.snr < b.snr; // asc
|
||||
});
|
||||
}
|
||||
|
||||
// build results buffer
|
||||
int results_count = 0;
|
||||
int results_offset = 0;
|
||||
uint8_t results_buffer[130];
|
||||
for(int index = 0; index < count && index + offset < neighbours_count; index++){
|
||||
|
||||
// stop if we can't fit another entry in results
|
||||
int entry_size = pubkey_prefix_length + 4 + 1;
|
||||
if(results_offset + entry_size > sizeof(results_buffer)){
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS no more entries can fit in results buffer");
|
||||
break;
|
||||
}
|
||||
|
||||
// add next neighbour to results
|
||||
auto neighbour = &sorted_neighbours[index + offset];
|
||||
uint32_t heard_seconds_ago = getRTCClock()->getCurrentTime() - neighbour->heard_timestamp;
|
||||
memcpy(&results_buffer[results_offset], neighbour->id.pub_key, pubkey_prefix_length); results_offset += pubkey_prefix_length;
|
||||
memcpy(&results_buffer[results_offset], &heard_seconds_ago, 4); results_offset += 4;
|
||||
memcpy(&results_buffer[results_offset], &neighbour->snr, 1); results_offset += 1;
|
||||
results_count++;
|
||||
|
||||
}
|
||||
|
||||
// build reply
|
||||
MESH_DEBUG_PRINTLN("REQ_TYPE_GET_NEIGHBOURS neighbours_count=%d results_count=%d", neighbours_count, results_count);
|
||||
memcpy(&reply_data[reply_offset], &neighbours_count, 2); reply_offset += 2;
|
||||
memcpy(&reply_data[reply_offset], &results_count, 2); reply_offset += 2;
|
||||
memcpy(&reply_data[reply_offset], &results_buffer, results_offset); reply_offset += results_offset;
|
||||
|
||||
return reply_offset;
|
||||
}
|
||||
}
|
||||
return 0; // unknown command
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user