add first cut of mesh naive flooding

1.2-legacy
geeksville 2020-04-17 11:52:20 -07:00
rodzic 6afeb3e456
commit ea24394110
8 zmienionych plików z 117 dodań i 18 usunięć

2
proto

@ -1 +1 @@
Subproject commit 793d3e65ca66c3a0914e74a285a729429952a042
Subproject commit e06645d8db16b9e4f23e74a931b8d5cd07bcbe3c

Wyświetl plik

@ -214,20 +214,24 @@ void MeshService::handleToRadio(std::string s)
switch (r.which_variant) {
case ToRadio_packet_tag: {
// If our phone is sending a position, see if we can use it to set our RTC
handleIncomingPosition(&r.variant.packet); // If it is a position packet, perhaps set our clock
MeshPacket &p = r.variant.packet;
handleIncomingPosition(&p); // If it is a position packet, perhaps set our clock
r.variant.packet.rx_time = gps.getValidTime(); // Record the time the packet arrived from the phone (so we update our
// nodedb for the local node)
if (p.from == 0) // If the phone didn't set a sending node ID, use ours
p.from = nodeDB.getNodeNum();
p.rx_time = gps.getValidTime(); // Record the time the packet arrived from the phone
// (so we update our nodedb for the local node)
// Send the packet into the mesh
sendToMesh(packetPool.allocCopy(r.variant.packet));
sendToMesh(packetPool.allocCopy(p));
bool loopback = false; // if true send any packet the phone sends back itself (for testing)
if (loopback) {
const MeshPacket *mp = &r.variant.packet;
// no need to copy anymore because handle from radio assumes it should _not_ delete
// packetPool.allocCopy(r.variant.packet);
handleFromRadio(mp);
handleFromRadio(&p);
// handleFromRadio will tell the phone a new packet arrived
}
break;

Wyświetl plik

@ -7,6 +7,7 @@
#include <Arduino.h>
typedef uint8_t NodeNum;
typedef uint8_t PacketId; // A packet sequence number
#define NODENUM_BROADCAST 255
#define ERRNO_OK 0

Wyświetl plik

@ -31,6 +31,7 @@
#include "error.h"
#include "power.h"
// #include "rom/rtc.h"
#include "FloodingRouter.h"
#include "screen.h"
#include "sleep.h"
#include <Wire.h>
@ -60,6 +61,9 @@ static meshtastic::PowerStatus powerStatus;
bool ssd1306_found;
bool axp192_found;
FloodingRouter realRouter;
Router &router = realRouter; // Users of router don't care what sort of subclass implements that API
// -----------------------------------------------------------------------------
// Application
// -----------------------------------------------------------------------------

Wyświetl plik

@ -1,5 +1,5 @@
#include "CustomRF95.h"
#include "NodeDB.h"
#include "NodeDB.h" // FIXME, this class should not need to touch nodedb
#include "assert.h"
#include "configuration.h"
#include <pb_decode.h>
@ -97,6 +97,8 @@ void CustomRF95::handleInterrupt()
mp->from = _rxHeaderFrom;
mp->to = _rxHeaderTo;
mp->id = _rxHeaderId;
//_rxHeaderId = _buf[2];
//_rxHeaderFlags = _buf[3];
@ -162,9 +164,11 @@ void CustomRF95::startSend(MeshPacket *txp)
sendingPacket = txp;
setHeaderTo(txp->to);
setHeaderFrom(nodeDB.getNodeNum()); // We must do this before each send, because we might have just changed our nodenum
setHeaderId(txp->id);
// setHeaderId(0);
// if the sender nodenum is zero, that means uninitialized
assert(txp->from);
setHeaderFrom(txp->from); // We must do this before each send, because we might have just changed our nodenum
assert(numbytes <= 251); // Make sure we don't overflow the tiny max packet size

Wyświetl plik

@ -0,0 +1,90 @@
#include "FloodingRouter.h"
#include "configuration.h"
#include "mesh-pb-constants.h"
/// We clear our old flood record five minute after we see the last of it
#define FLOOD_EXPIRE_TIME (5 * 60 * 1000L)
FloodingRouter::FloodingRouter()
{
recentBroadcasts.reserve(MAX_NUM_NODES); // Prealloc the worst case # of records - to prevent heap fragmentation
}
/**
* Send a packet on a suitable interface. This routine will
* later free() the packet to pool. This routine is not allowed to stall.
* If the txmit queue is full it might return an error
*/
ErrorCode FloodingRouter::send(MeshPacket *p)
{
// We update our table of recent broadcasts, even for messages we send
wasSeenRecently(p);
return Router::send(p);
}
/**
* Called from loop()
* Handle any packet that is received by an interface on this node.
* Note: some packets may merely being passed through this node and will be forwarded elsewhere.
*
* Note: this method will free the provided packet
*/
void FloodingRouter::handleReceived(MeshPacket *p)
{
if (wasSeenRecently(p)) {
DEBUG_MSG("Ignoring incoming floodmsg, because we've already seen it\n");
packetPool.release(p);
} else {
if (p->to == NODENUM_BROADCAST && p->id != 0) {
DEBUG_MSG("Rebroadcasting received floodmsg to neighbors\n");
// FIXME, wait a random delay
MeshPacket *tosend = packetPool.allocCopy(*p);
// Note: we are careful to resend using the original senders node id
Router::send(tosend); // We are careful not to call our hooked version of send()
}
// handle the packet as normal
Router::handleReceived(p);
}
}
/**
* Update recentBroadcasts and return true if we have already seen this packet
*/
bool FloodingRouter::wasSeenRecently(const MeshPacket *p)
{
if (p->to != NODENUM_BROADCAST)
return false; // Not a broadcast, so we don't care
if (p->id == 0)
return false; // Not a floodable message ID, so we don't care
uint32_t now = millis();
for (int i = 0; i < recentBroadcasts.size();) {
BroadcastRecord &r = recentBroadcasts[i];
if ((now - r.rxTimeMsec) >= FLOOD_EXPIRE_TIME) {
DEBUG_MSG("Deleting old recentBroadcast %d\n", i);
recentBroadcasts.erase(recentBroadcasts.begin() + i); // delete old record
} else {
if (r.id == p->id && r.sender == p->from) {
// Update the time on this record to now
r.rxTimeMsec = now;
return true;
}
i++;
}
}
// Didn't find an existing record, make one
BroadcastRecord r;
r.id = p->id;
r.sender = p->from;
r.rxTimeMsec = now;
recentBroadcasts.push_back(r);
return false;
}

Wyświetl plik

@ -5,7 +5,7 @@
/**
* Router todo
*
* Implement basic interface and use it elsewhere in app
* DONE: Implement basic interface and use it elsewhere in app
* Add naive flooding mixin (& drop duplicate rx broadcasts), add tools for sending broadcasts with incrementing sequence #s
* Add an optional adjacent node only 'send with ack' mixin. If we timeout waiting for the ack, call handleAckTimeout(packet)
* Add DSR mixin
@ -22,8 +22,6 @@
MemoryPool<MeshPacket> packetPool(MAX_PACKETS);
Router router;
/**
* Constructor
*

Wyświetl plik

@ -8,8 +8,6 @@
#include "mesh.pb.h"
#include <RH_RF95.h>
/**
* A mesh aware router that supports multiple interfaces.
*/
@ -56,7 +54,7 @@ class Router
*/
virtual ErrorCode send(MeshPacket *p);
private:
protected:
/**
* Called from loop()
* Handle any packet that is received by an interface on this node.
@ -64,7 +62,7 @@ class Router
*
* Note: this method will free the provided packet
*/
void handleReceived(MeshPacket *p);
virtual void handleReceived(MeshPacket *p);
};
extern Router router;
extern Router &router;