* repeater: default-scope support
This commit is contained in:
@@ -413,6 +413,19 @@ bool MyMesh::isLooped(const mesh::Packet* packet, const uint8_t max_counters[])
|
|||||||
return n >= max_counters[hash_size];
|
return n >= max_counters[hash_size];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyMesh::sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size) {
|
||||||
|
if (recv_pkt_region) { // if _request_ packet scope is known, send reply with same scope
|
||||||
|
TransportKey scope;
|
||||||
|
if (region_map.getTransportKeysFor(*recv_pkt_region, &scope, 1) == 0) {
|
||||||
|
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||||
|
} else {
|
||||||
|
sendFloodScoped(scope, packet, delay_millis, path_hash_size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendFloodScoped(default_scope, packet, delay_millis, path_hash_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
bool MyMesh::allowPacketForward(const mesh::Packet *packet) {
|
||||||
if (_prefs.disable_fwd) return false;
|
if (_prefs.disable_fwd) return false;
|
||||||
if (packet->isRouteFlood() && packet->getPathHashCount() >= _prefs.flood_max) return false;
|
if (packet->isRouteFlood() && packet->getPathHashCount() >= _prefs.flood_max) return false;
|
||||||
@@ -578,10 +591,10 @@ void MyMesh::onAnonDataRecv(mesh::Packet *packet, const uint8_t *secret, const m
|
|||||||
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
||||||
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
|
mesh::Packet* path = createPathReturn(sender, secret, packet->path, packet->path_len,
|
||||||
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
||||||
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||||
} else if (reply_path_len < 0) {
|
} else if (reply_path_len < 0) {
|
||||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||||
if (reply) sendFlood(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
if (reply) sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||||
} else {
|
} else {
|
||||||
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
mesh::Packet* reply = createDatagram(PAYLOAD_TYPE_RESPONSE, sender, secret, reply_data, reply_len);
|
||||||
uint8_t path_len = ((reply_path_hash_size - 1) << 6) | (reply_path_len & 63);
|
uint8_t path_len = ((reply_path_hash_size - 1) << 6) | (reply_path_len & 63);
|
||||||
@@ -654,7 +667,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
|
|||||||
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
// let this sender know path TO here, so they can use sendDirect(), and ALSO encode the response
|
||||||
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
|
mesh::Packet *path = createPathReturn(client->id, secret, packet->path, packet->path_len,
|
||||||
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
PAYLOAD_TYPE_RESPONSE, reply_data, reply_len);
|
||||||
if (path) sendFlood(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
if (path) sendFloodReply(path, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||||
} else {
|
} else {
|
||||||
mesh::Packet *reply =
|
mesh::Packet *reply =
|
||||||
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
|
createDatagram(PAYLOAD_TYPE_RESPONSE, client->id, secret, reply_data, reply_len);
|
||||||
@@ -662,7 +675,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
|
|||||||
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
|
if (client->out_path_len != OUT_PATH_UNKNOWN) { // we have an out_path, so send DIRECT
|
||||||
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
|
sendDirect(reply, client->out_path, client->out_path_len, SERVER_RESPONSE_DELAY);
|
||||||
} else {
|
} else {
|
||||||
sendFlood(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
sendFloodReply(reply, SERVER_RESPONSE_DELAY, packet->getPathHashSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -693,7 +706,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
|
|||||||
mesh::Packet *ack = createAck(ack_hash);
|
mesh::Packet *ack = createAck(ack_hash);
|
||||||
if (ack) {
|
if (ack) {
|
||||||
if (client->out_path_len == OUT_PATH_UNKNOWN) {
|
if (client->out_path_len == OUT_PATH_UNKNOWN) {
|
||||||
sendFlood(ack, TXT_ACK_DELAY, packet->getPathHashSize());
|
sendFloodReply(ack, TXT_ACK_DELAY, packet->getPathHashSize());
|
||||||
} else {
|
} else {
|
||||||
sendDirect(ack, client->out_path, client->out_path_len, TXT_ACK_DELAY);
|
sendDirect(ack, client->out_path, client->out_path_len, TXT_ACK_DELAY);
|
||||||
}
|
}
|
||||||
@@ -721,7 +734,7 @@ void MyMesh::onPeerDataRecv(mesh::Packet *packet, uint8_t type, int sender_idx,
|
|||||||
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
|
auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, client->id, secret, temp, 5 + text_len);
|
||||||
if (reply) {
|
if (reply) {
|
||||||
if (client->out_path_len == OUT_PATH_UNKNOWN) {
|
if (client->out_path_len == OUT_PATH_UNKNOWN) {
|
||||||
sendFlood(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());
|
sendFloodReply(reply, CLI_REPLY_DELAY_MILLIS, packet->getPathHashSize());
|
||||||
} else {
|
} else {
|
||||||
sendDirect(reply, client->out_path, client->out_path_len, CLI_REPLY_DELAY_MILLIS);
|
sendDirect(reply, client->out_path, client->out_path_len, CLI_REPLY_DELAY_MILLIS);
|
||||||
}
|
}
|
||||||
@@ -899,6 +912,8 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc
|
|||||||
|
|
||||||
pending_discover_tag = 0;
|
pending_discover_tag = 0;
|
||||||
pending_discover_until = 0;
|
pending_discover_until = 0;
|
||||||
|
|
||||||
|
memset(default_scope.key, 0, sizeof(default_scope.key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyMesh::begin(FILESYSTEM *fs) {
|
void MyMesh::begin(FILESYSTEM *fs) {
|
||||||
@@ -910,6 +925,26 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
|||||||
// TODO: key_store.begin();
|
// TODO: key_store.begin();
|
||||||
region_map.load(_fs);
|
region_map.load(_fs);
|
||||||
|
|
||||||
|
// establish default-scope
|
||||||
|
{
|
||||||
|
RegionEntry* r = region_map.getDefaultRegion();
|
||||||
|
if (r) {
|
||||||
|
region_map.getTransportKeysFor(*r, &default_scope, 1);
|
||||||
|
} else {
|
||||||
|
#ifdef DEFAULT_FLOOD_SCOPE_NAME
|
||||||
|
r = region_map.findByName(DEFAULT_FLOOD_SCOPE_NAME);
|
||||||
|
if (r == NULL) {
|
||||||
|
r = region_map.putRegion(DEFAULT_FLOOD_SCOPE_NAME, 0); // auto-create the default scope region
|
||||||
|
if (r) { r->flags = 0; } // Allow-flood
|
||||||
|
}
|
||||||
|
if (r) {
|
||||||
|
region_map.setDefaultRegion(r);
|
||||||
|
region_map.getTransportKeysFor(*r, &default_scope, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(WITH_BRIDGE)
|
#if defined(WITH_BRIDGE)
|
||||||
if (_prefs.bridge_enabled) {
|
if (_prefs.bridge_enabled) {
|
||||||
bridge.begin();
|
bridge.begin();
|
||||||
@@ -933,6 +968,17 @@ void MyMesh::begin(FILESYSTEM *fs) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis, uint8_t path_hash_size) {
|
||||||
|
if (scope.isNull()) {
|
||||||
|
sendFlood(pkt, delay_millis, path_hash_size);
|
||||||
|
} else {
|
||||||
|
uint16_t codes[2];
|
||||||
|
codes[0] = scope.calcTransportCode(pkt);
|
||||||
|
codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region?
|
||||||
|
sendFlood(pkt, codes, delay_millis, path_hash_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {
|
void MyMesh::applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) {
|
||||||
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
|
set_radio_at = futureMillis(2000); // give CLI reply some time to be sent back, before applying temp radio params
|
||||||
pending_freq = freq;
|
pending_freq = freq;
|
||||||
@@ -960,7 +1006,7 @@ void MyMesh::sendSelfAdvertisement(int delay_millis, bool flood) {
|
|||||||
mesh::Packet *pkt = createSelfAdvert();
|
mesh::Packet *pkt = createSelfAdvert();
|
||||||
if (pkt) {
|
if (pkt) {
|
||||||
if (flood) {
|
if (flood) {
|
||||||
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
|
sendFloodScoped(default_scope, pkt, delay_millis, _prefs.path_hash_mode + 1);
|
||||||
} else {
|
} else {
|
||||||
sendZeroHop(pkt, delay_millis);
|
sendZeroHop(pkt, delay_millis);
|
||||||
}
|
}
|
||||||
@@ -1231,6 +1277,24 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply
|
|||||||
} else if (n == 2 && strcmp(parts[1], "home") == 0) {
|
} else if (n == 2 && strcmp(parts[1], "home") == 0) {
|
||||||
auto home = region_map.getHomeRegion();
|
auto home = region_map.getHomeRegion();
|
||||||
sprintf(reply, " home is %s", home ? home->name : "*");
|
sprintf(reply, " home is %s", home ? home->name : "*");
|
||||||
|
} else if (n >= 3 && strcmp(parts[1], "default") == 0) {
|
||||||
|
if (strcmp(parts[2], "<null>") == 0) {
|
||||||
|
region_map.setDefaultRegion(NULL);
|
||||||
|
memset(default_scope.key, 0, sizeof(default_scope.key));
|
||||||
|
sprintf(reply, " default scope is now <null>");
|
||||||
|
} else {
|
||||||
|
auto def = region_map.findByNamePrefix(parts[2]);
|
||||||
|
if (def) {
|
||||||
|
region_map.setDefaultRegion(def);
|
||||||
|
region_map.getTransportKeysFor(*def, &default_scope, 1);
|
||||||
|
sprintf(reply, " default scope is now %s", def->name);
|
||||||
|
} else {
|
||||||
|
strcpy(reply, "Err - unknown region");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (n == 2 && strcmp(parts[1], "default") == 0) {
|
||||||
|
auto def = region_map.getDefaultRegion();
|
||||||
|
sprintf(reply, " default scope is %s", def ? def->name : "<null>");
|
||||||
} else if (n >= 3 && strcmp(parts[1], "put") == 0) {
|
} else if (n >= 3 && strcmp(parts[1], "put") == 0) {
|
||||||
auto parent = n >= 4 ? region_map.findByNamePrefix(parts[3]) : ®ion_map.getWildcard();
|
auto parent = n >= 4 ? region_map.findByNamePrefix(parts[3]) : ®ion_map.getWildcard();
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
@@ -1300,7 +1364,7 @@ void MyMesh::loop() {
|
|||||||
if (next_flood_advert && millisHasNowPassed(next_flood_advert)) {
|
if (next_flood_advert && millisHasNowPassed(next_flood_advert)) {
|
||||||
mesh::Packet *pkt = createSelfAdvert();
|
mesh::Packet *pkt = createSelfAdvert();
|
||||||
uint32_t delay_millis = 0;
|
uint32_t delay_millis = 0;
|
||||||
if (pkt) sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
|
if (pkt) sendFloodScoped(default_scope, pkt, delay_millis, _prefs.path_hash_mode + 1);
|
||||||
|
|
||||||
updateFloodAdvertTimer(); // schedule next flood advert
|
updateFloodAdvertTimer(); // schedule next flood advert
|
||||||
updateAdvertTimer(); // also schedule local advert (so they don't overlap)
|
updateAdvertTimer(); // also schedule local advert (so they don't overlap)
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks {
|
|||||||
RegionMap region_map, temp_map;
|
RegionMap region_map, temp_map;
|
||||||
RegionEntry* load_stack[8];
|
RegionEntry* load_stack[8];
|
||||||
RegionEntry* recv_pkt_region;
|
RegionEntry* recv_pkt_region;
|
||||||
|
TransportKey default_scope;
|
||||||
RateLimiter discover_limiter, anon_limiter;
|
RateLimiter discover_limiter, anon_limiter;
|
||||||
uint32_t pending_discover_tag;
|
uint32_t pending_discover_tag;
|
||||||
unsigned long pending_discover_until;
|
unsigned long pending_discover_until;
|
||||||
@@ -172,6 +173,8 @@ protected:
|
|||||||
bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
|
bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override;
|
||||||
void onControlDataRecv(mesh::Packet* packet) override;
|
void onControlDataRecv(mesh::Packet* packet) override;
|
||||||
|
|
||||||
|
void sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables);
|
MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables);
|
||||||
|
|
||||||
@@ -189,6 +192,7 @@ public:
|
|||||||
_cli.savePrefs(_fs);
|
_cli.savePrefs(_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis, uint8_t path_hash_size);
|
||||||
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) override;
|
||||||
bool formatFileSystem() override;
|
bool formatFileSystem() override;
|
||||||
void sendSelfAdvertisement(int delay_millis, bool flood) override;
|
void sendSelfAdvertisement(int delay_millis, bool flood) override;
|
||||||
|
|||||||
Reference in New Issue
Block a user