mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-19 17:22:59 +00:00
dynamic nodenum assignment now works
This commit is contained in:
@@ -20,8 +20,22 @@ a node number and keeping the current nodedb.
|
||||
|
||||
*/
|
||||
|
||||
MeshService service;
|
||||
/* Broadcast when a newly powered mesh node wants to find a node num it can use
|
||||
|
||||
The algoritm is as follows:
|
||||
* when a node starts up, it broadcasts their user and the normal flow is for all other nodes to reply with their User as well (so the new node can build its node db)
|
||||
* If a node ever receives a User (not just the first broadcast) message where the sender node number equals our node number, that indicates a collision has occurred and the following steps should happen:
|
||||
|
||||
If the receiving node (that was already in the mesh)'s macaddr is LOWER than the new User who just tried to sign in: it gets to keep its nodenum. We send a broadcast message
|
||||
of OUR User (we use a broadcast so that the other node can receive our message, considering we have the same id - it also serves to let observers correct their nodedb) - this case is rare so it should be okay.
|
||||
|
||||
If any node receives a User where the macaddr is GTE than their local macaddr, they have been vetoed and should pick a new random nodenum (filtering against whatever it knows about the nodedb) and
|
||||
rebroadcast their User.
|
||||
|
||||
FIXME in the initial proof of concept we just skip the entire want/deny flow and just hand pick node numbers at first.
|
||||
*/
|
||||
|
||||
MeshService service;
|
||||
|
||||
// I think this is right, one packet for each of the three fifos + one packet being currently assembled for TX or RX
|
||||
#define MAX_PACKETS (MAX_RX_TOPHONE + MAX_RX_FROMRADIO + MAX_TX_QUEUE + 2) // max number of packets which can be in flight (either queued from reception or queued for sending)
|
||||
@@ -61,39 +75,77 @@ void MeshService::sendOurOwner(NodeNum dest)
|
||||
sendToMesh(p);
|
||||
}
|
||||
|
||||
|
||||
void MeshService::handleFromRadio()
|
||||
{
|
||||
MeshPacket *mp;
|
||||
uint32_t oldFromNum = fromNum;
|
||||
while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL)
|
||||
{
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
if(mp->has_payload && mp->payload.which_variant == SubPacket_user_tag && mp->to == NODENUM_BROADCAST) {
|
||||
// Someone just sent us a User, reply with our Owner
|
||||
DEBUG_MSG("Received broadcast Owner from 0x%x, replying with our owner\n", mp->from);
|
||||
sendOurOwner(mp->from);
|
||||
if (mp->has_payload && mp->payload.which_variant == SubPacket_user_tag)
|
||||
{
|
||||
bool wasBroadcast = mp->to == NODENUM_BROADCAST;
|
||||
bool isCollision = mp->from == myNodeInfo.my_node_num;
|
||||
|
||||
String lcd = String("Joined: ") + mp->payload.variant.user.long_name + "\n";
|
||||
screen_print(lcd.c_str());
|
||||
// we win if we have a lower macaddr
|
||||
bool weWin = memcmp(&owner.macaddr, &mp->payload.variant.user.macaddr, sizeof(owner.macaddr)) < 0;
|
||||
|
||||
if (isCollision)
|
||||
{
|
||||
if (weWin)
|
||||
{
|
||||
DEBUG_MSG("NOTE! Received a nodenum collision and we are vetoing\n");
|
||||
|
||||
packetPool.release(mp); // discard it
|
||||
mp = NULL;
|
||||
|
||||
sendOurOwner(); // send our owner as a _broadcast_ because that other guy is mistakenly using our nodenum
|
||||
}
|
||||
else
|
||||
{
|
||||
// we lost, we need to try for a new nodenum!
|
||||
DEBUG_MSG("NOTE! Received a nodenum collision we lost, so picking a new nodenum\n");
|
||||
nodeDB.updateFrom(*mp); // update the DB early - before trying to repick (so we don't select the same node number again)
|
||||
nodeDB.pickNewNodeNum();
|
||||
sendOurOwner(); // broadcast our new attempt at a node number
|
||||
}
|
||||
}
|
||||
else if (wasBroadcast)
|
||||
{
|
||||
// If we haven't yet abandoned the packet and it was a broadcast, reply (just to them) with our User record so they can build their DB
|
||||
|
||||
// Someone just sent us a User, reply with our Owner
|
||||
DEBUG_MSG("Received broadcast Owner from 0x%x, replying with our owner\n", mp->from);
|
||||
|
||||
sendOurOwner(mp->from);
|
||||
|
||||
String lcd = String("Joined: ") + mp->payload.variant.user.long_name + "\n";
|
||||
screen_print(lcd.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
fromNum++;
|
||||
// If we veto a received User packet, we don't put it into the DB or forward it to the phone (to prevent confusing it)
|
||||
if (mp)
|
||||
{
|
||||
nodeDB.updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio
|
||||
|
||||
if(toPhoneQueue.numFree() == 0) {
|
||||
DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n");
|
||||
MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if(d)
|
||||
releaseToPool(d);
|
||||
fromNum++;
|
||||
|
||||
if (toPhoneQueue.numFree() == 0)
|
||||
{
|
||||
DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n");
|
||||
MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
}
|
||||
assert(toPhoneQueue.enqueue(mp, 0) == pdTRUE); // FIXME, instead of failing for full queue, delete the oldest mssages
|
||||
}
|
||||
assert(toPhoneQueue.enqueue(mp, 0) == pdTRUE); // FIXME, instead of failing for full queue, delete the oldest mssages
|
||||
else
|
||||
DEBUG_MSG("Dropping vetoed User message\n");
|
||||
}
|
||||
if (oldFromNum != fromNum) // We don't want to generate extra notifies for multiple new packets
|
||||
bluetoothNotifyFromNum(fromNum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Do idle processing (mostly processing messages which have been queued from the radio)
|
||||
void MeshService::loop()
|
||||
{
|
||||
@@ -103,8 +155,9 @@ void MeshService::loop()
|
||||
|
||||
// FIXME, don't send user this often, but for now it is useful for testing
|
||||
static uint32_t lastsend;
|
||||
uint32_t now = millis();
|
||||
if(now - lastsend > 20 * 1000) {
|
||||
uint32_t now = millis();
|
||||
if (now - lastsend > 20 * 1000)
|
||||
{
|
||||
lastsend = now;
|
||||
sendOurOwner();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user