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-27 22:31:32 +00:00
|
|
|
// We only consider multihop routing packets (i.e. those with dest set)
|
|
|
|
if (p->decoded.dest) {
|
|
|
|
// add an entry for this pending message
|
|
|
|
auto pending = startRetransmission(p);
|
|
|
|
// FIXME - when acks come in for this packet, we should _not_ delete the record unless the ack was from
|
|
|
|
// the final dest. We need to keep that record around until FIXME
|
|
|
|
// Also we should not retransmit multihop entries in that table at all
|
2020-05-21 19:47:08 +00:00
|
|
|
|
2020-05-27 22:31:32 +00:00
|
|
|
// If we have an entry in our routing tables, just send it, otherwise start a route discovery
|
|
|
|
NodeNum nextHop = getNextHop(p->decoded.dest);
|
|
|
|
if (nextHop) {
|
|
|
|
sendNextHop(nextHop, p); // start a reliable single hop send
|
|
|
|
} else {
|
|
|
|
pending->wantRoute = true;
|
|
|
|
|
|
|
|
// start discovery, but only if we don't already a discovery in progress for that node number
|
|
|
|
startDiscovery(p->decoded.dest);
|
|
|
|
}
|
2020-06-03 19:49:36 +00:00
|
|
|
|
|
|
|
return ERRNO_OK;
|
2020-05-27 22:31:32 +00:00
|
|
|
} else
|
|
|
|
return ReliableRouter::send(p);
|
2020-05-24 00:39:08 +00:00
|
|
|
}
|
2020-05-21 19:47:08 +00:00
|
|
|
|
2021-02-21 04:59:47 +00:00
|
|
|
void DSRRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
2020-05-24 00:39:08 +00:00
|
|
|
{
|
|
|
|
// 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) {
|
2021-03-05 02:19:27 +00:00
|
|
|
addRoute(getFrom(p), getFrom(p), 0); // We are adjacent with zero hops
|
2020-05-24 00:39:08 +00:00
|
|
|
}
|
2020-05-21 19:47:08 +00:00
|
|
|
|
2021-02-21 04:59:47 +00:00
|
|
|
if (c)
|
|
|
|
switch (c->which_variant) {
|
|
|
|
case Routing_route_request_tag:
|
|
|
|
// Handle route discovery packets (will be a broadcast message)
|
|
|
|
// FIXME - always start request with the senders nodenum
|
|
|
|
if (weAreInRoute(c->route_request)) {
|
|
|
|
DEBUG_MSG("Ignoring a route request that contains us\n");
|
2020-05-21 19:47:08 +00:00
|
|
|
} else {
|
2021-02-21 04:59:47 +00:00
|
|
|
updateRoutes(c->route_request,
|
|
|
|
true); // Update our routing tables based on the route that came in so far on this request
|
|
|
|
|
|
|
|
if (p->decoded.dest == getNodeNum()) {
|
|
|
|
// They were looking for us, send back a route reply (the sender address will be first in the list)
|
|
|
|
sendRouteReply(c->route_request);
|
2020-05-21 19:47:08 +00:00
|
|
|
} else {
|
2021-02-21 04:59:47 +00:00
|
|
|
// 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)
|
|
|
|
sendRouteReply(c->route_request, nextHop);
|
|
|
|
} else {
|
|
|
|
// Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
|
|
|
|
resendRouteRequest(p);
|
|
|
|
}
|
2020-05-21 19:47:08 +00:00
|
|
|
}
|
|
|
|
}
|
2021-02-21 04:59:47 +00:00
|
|
|
break;
|
|
|
|
case Routing_route_reply_tag:
|
|
|
|
updateRoutes(c->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 Routing_error_reason_tag:
|
|
|
|
removeRoute(p->decoded.dest);
|
|
|
|
|
|
|
|
// FIXME: if any pending packets were waiting on this route, delete them
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2020-05-21 19:47:08 +00:00
|
|
|
}
|
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)
|
|
|
|
|
2020-05-23 16:24:22 +00:00
|
|
|
// 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?
|
2021-02-17 05:06:23 +00:00
|
|
|
sendRouteError(p, Routing_Error_NO_ROUTE);
|
2020-05-23 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME, stop local processing of this packet
|
2020-05-21 19:47:08 +00:00
|
|
|
}
|
2020-05-23 19:50:33 +00:00
|
|
|
|
2021-02-21 04:59:47 +00:00
|
|
|
if (c) {
|
|
|
|
// handle naks - convert them to route error packets
|
|
|
|
// All naks are generated locally, because we failed resending the packet too many times
|
2021-02-26 12:36:22 +00:00
|
|
|
PacketId nakId = c->error_reason ? p->decoded.request_id : 0;
|
2021-02-21 04:59:47 +00:00
|
|
|
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
|
|
|
|
removeRoute(pending->packet->decoded.dest); // We no longer have a route to the specified node
|
|
|
|
|
|
|
|
sendRouteError(p, Routing_Error_GOT_NAK);
|
|
|
|
}
|
2020-05-23 22:48:23 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-21 19:47:08 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 05:06:23 +00:00
|
|
|
ReliableRouter::sniffReceived(p, c);
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Does our node appear in the specified route
|
|
|
|
*/
|
|
|
|
bool DSRRouter::weAreInRoute(const RouteDiscovery &route)
|
|
|
|
{
|
|
|
|
return true; // FIXME
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a DSR route, use that route to update our DB of possible routes
|
|
|
|
*
|
|
|
|
* Note: routes are always listed in the same order - from sender to receipient (i.e. route_replies also use this some order)
|
|
|
|
*
|
|
|
|
* @param isRequest is true if we are looking at a route request, else we are looking at a reply
|
|
|
|
**/
|
|
|
|
void DSRRouter::updateRoutes(const RouteDiscovery &route, bool isRequest)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented updateRoutes\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* send back a route reply (the sender address will be first in the list)
|
|
|
|
*/
|
|
|
|
void DSRRouter::sendRouteReply(const RouteDiscovery &route, NodeNum toAppend)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented sendRoute\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Given a nodenum return the next node we should forward to if we want to reach that node.
|
|
|
|
*
|
|
|
|
* @return 0 if no route found
|
|
|
|
*/
|
|
|
|
NodeNum DSRRouter::getNextHop(NodeNum dest)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented getNextHop\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route)
|
|
|
|
*
|
|
|
|
* We will bump down hop_limit in this call.
|
|
|
|
*/
|
|
|
|
void DSRRouter::resendRouteRequest(const MeshPacket *p)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented resendRoute\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Record that forwarder can reach dest for us, but they will need numHops to get there.
|
|
|
|
* If our routing tables already have something that can reach that node in fewer hops we will keep the existing route
|
|
|
|
* instead.
|
|
|
|
*/
|
|
|
|
void DSRRouter::addRoute(NodeNum dest, NodeNum forwarder, uint8_t numHops)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented addRoute\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Record that we no longer have a route to the dest
|
|
|
|
*/
|
|
|
|
void DSRRouter::removeRoute(NodeNum dest)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented removeRoute\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Forward the specified packet to the specified node
|
|
|
|
*/
|
|
|
|
void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented sendNextHop\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a route error packet towards whoever originally sent this message
|
|
|
|
*/
|
2021-02-17 05:06:23 +00:00
|
|
|
void DSRRouter::sendRouteError(const MeshPacket *p, Routing_Error err)
|
2020-06-03 19:49:36 +00:00
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented sendRouteError\n");
|
2020-06-03 19:49:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** make a copy of p, start discovery, but only if we don't
|
|
|
|
* already a discovery in progress for that node number. Caller has already scheduled this message for retransmission
|
|
|
|
* when the discovery is complete.
|
|
|
|
*/
|
|
|
|
void DSRRouter::startDiscovery(NodeNum dest)
|
|
|
|
{
|
2020-12-13 07:59:26 +00:00
|
|
|
DEBUG_MSG("FIXME not implemented startDiscovery\n");
|
2020-05-21 19:47:08 +00:00
|
|
|
}
|