firmware/src/mesh/DSRRouter.cpp

135 lines
5.9 KiB
C++
Raw Normal View History

2020-05-21 19:47:08 +00:00
#include "DSRRouter.h"
#include "configuration.h"
/* when we receive any packet
- sniff and update tables (especially useful to find adjacent nodes). Update user, network and position info.
- if we need to route() that packet, resend it to the next_hop based on our nodedb.
- if it is broadcast or destined for our node, deliver locally
- handle routereply/routeerror/routediscovery messages as described below
- then free it
routeDiscovery
- if we've already passed through us (or is from us), then it ignore it
- use the nodes already mentioned in the request to update our routing table
- if they were looking for us, send back a routereply
- if max_hops is zero and they weren't looking for us, drop (FIXME, send back error - I think not though?)
- if we receive a discovery packet, we use it to populate next_hop (if needed) towards the requester (after decrementing max_hops)
- if we receive a discovery packet, and we have a next_hop in our nodedb for that destination we send a (reliable) we send a route
reply towards the requester
when sending any reliable packet
- if timeout doing retries, send a routeError (nak) message back towards the original requester. all nodes eavesdrop on that
packet and update their route caches.
when we receive a routereply packet
- update next_hop on the node, if the new reply needs fewer hops than the existing one (we prefer shorter paths). fixme, someday
use a better heuristic
when we receive a routeError packet
- delete the route for that failed recipient, restartRouteDiscovery()
- if we receive routeerror in response to a discovery,
- fixme, eventually keep caches of possible other routes.
*/
2020-05-24 00:39:08 +00:00
ErrorCode DSRRouter::send(MeshPacket *p)
2020-05-21 19:47:08 +00:00
{
2020-05-24 00:39:08 +00:00
// If we have an entry in our routing tables, just send it, otherwise start a route discovery
2020-05-21 19:47:08 +00:00
2020-05-24 00:39:08 +00:00
return ReliableRouter::send(p);
}
2020-05-21 19:47:08 +00:00
2020-05-24 00:39:08 +00:00
void DSRRouter::sniffReceived(const MeshPacket *p)
{
// Learn 0 hop routes by just hearing any adjacent nodes
// But treat broadcasts carefully, because when flood broadcasts go out they keep the same original "from". So we want to
// ignore rebroadcasts.
// this will also add records for any ACKs we receive for our messages
if (p->to != NODENUM_BROADCAST || p->hop_limit != HOP_RELIABLE) {
addRoute(p->from, p->from, 0); // We are adjacent with zero hops
}
2020-05-21 19:47:08 +00:00
2020-05-24 00:39:08 +00:00
switch (p->decoded.which_payload) {
case SubPacket_route_request_tag:
// Handle route discovery packets (will be a broadcast message)
// FIXME - always start request with the senders nodenum
2020-05-23 22:48:23 +00:00
if (weAreInRoute(p->decoded.route_request)) {
2020-05-21 19:47:08 +00:00
DEBUG_MSG("Ignoring a route request that contains us\n");
} else {
2020-05-23 22:48:23 +00:00
updateRoutes(p->decoded.route_request,
2020-05-24 00:39:08 +00:00
true); // Update our routing tables based on the route that came in so far on this request
2020-05-21 19:47:08 +00:00
if (p->decoded.dest == getNodeNum()) {
// They were looking for us, send back a route reply (the sender address will be first in the list)
2020-05-23 22:48:23 +00:00
sendRouteReply(p->decoded.route_request);
2020-05-21 19:47:08 +00:00
} else {
// They were looking for someone else, forward it along (as a zero hop broadcast)
NodeNum nextHop = getNextHop(p->decoded.dest);
if (nextHop) {
// in our route cache, reply to the requester (the sender address will be first in the list)
2020-05-23 22:48:23 +00:00
sendRouteReply(p->decoded.route_request, nextHop);
2020-05-21 19:47:08 +00:00
} else {
// Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
resendRouteRequest(p);
}
}
}
2020-05-24 00:39:08 +00:00
break;
case SubPacket_route_reply_tag:
updateRoutes(p->decoded.route_reply, false);
// FIXME, if any of our current pending packets were waiting for this route, send them (and leave them as regular pending
// packets until ack arrives)
// FIXME, if we don't get a route reply at all (or a route error), timeout and generate a routeerror TIMEOUT on our own...
break;
case SubPacket_route_error_tag:
removeRoute(p->decoded.dest);
// FIXME: if any pending packets were waiting on this route, delete them
break;
default:
break;
2020-05-23 19:50:33 +00:00
}
2020-05-23 22:48:23 +00:00
// We simply ignore ACKs - because ReliableRouter will delete the pending packet for us
2020-05-23 19:50:33 +00:00
2020-05-21 19:47:08 +00:00
// Handle regular packets
if (p->to == getNodeNum()) { // Destined for us (at least for this hop)
// We need to route this packet to some other node
if (p->decoded.dest && p->decoded.dest != p->to) {
2020-05-24 00:39:08 +00:00
// if we have a route out, resend the packet to the next hop, otherwise return RouteError no-route available
2020-05-23 22:48:23 +00:00
NodeNum nextHop = getNextHop(p->decoded.dest);
if (nextHop) {
sendNextHop(nextHop, p); // start a reliable single hop send
} else {
// We don't have a route out
assert(p->decoded.source); // I think this is guaranteed by now
2020-05-24 00:39:08 +00:00
// FIXME - what if the current packet _is_ a route error packet?
2020-05-23 22:48:23 +00:00
sendRouteError(p, RouteError_NO_ROUTE);
}
// FIXME, stop local processing of this packet
2020-05-21 19:47:08 +00:00
}
2020-05-23 19:50:33 +00:00
2020-05-23 22:48:23 +00:00
// handle naks - convert them to route error packets
// All naks are generated locally, because we failed resending the packet too many times
PacketId nakId = p->decoded.which_ack == SubPacket_fail_id_tag ? p->decoded.ack.fail_id : 0;
if (nakId) {
auto pending = findPendingPacket(p->to, nakId);
if (pending && pending->packet->decoded.source) { // if source not set, this was not a multihop packet, just ignore
2020-05-24 00:39:08 +00:00
removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node
2020-05-23 22:48:23 +00:00
sendRouteError(p, RouteError_GOT_NAK);
}
}
2020-05-21 19:47:08 +00:00
}
return ReliableRouter::sniffReceived(p);
}