diff --git a/docs/software/TODO.md b/docs/software/TODO.md index ded8796de..c4569cbda 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -4,16 +4,26 @@ You probably don't care about this section - skip to the next one. 1.2 cleanup & multichannel: -* remove deprecated +* DONE remove deprecated * allow chaning packets in single transmission -* fix setchannel in phoneapi.cpp -* set mynodeinfo.max_channels -* set mynodeinfo.num_bands (formerly num_channels) +* DONE fix setchannel in phoneapi.cpp +* DONE set mynodeinfo.max_channels +* DONE set mynodeinfo.num_bands (formerly num_channels) +* fix sniffing of non Routing packets +* move portnum up? +* scrub protobufs to make sure they are absoloute minimum wiresize (in particular packets, ChannelSets and positions) * send a hint that can be used to select which channel to try and hash against with each message * change syncword -* move acks into routing -* make all subpackets different versions of data -* move routing control into a data packet +* DONE move acks into routing +* DONE make all subpackets different versions of data +* DONE move routing control into a data packet +* have phoneapi done via plugin +* figure out how to add micro_delta to position, make it so that phone apps don't need to understand it? +* only send battery updates a max of once a minute +* add multichannel support in python +* add channel selection for sending +* record recevied channel in meshpacket +* add channel restrictions for plugins (and restrict routing plugin to the "control" channel) * make a primaryChannel global and properly maintain it when the phone sends setChannel * move setCrypto call into packet send and packet decode code * implement'small locations' change? diff --git a/proto b/proto index 481beb41b..65914b84f 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 481beb41ba8c8f39bfc6b3f397d6107af04dfb93 +Subproject commit 65914b84f1ee8f25807187d60b43ad29dfbaedc3 diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index f7193260f..a2c74ba7e 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -216,8 +216,7 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state // the max length of this buffer is much longer than we can possibly print static char tempBuf[96]; - assert(mp.decoded.which_payloadVariant == SubPacket_data_tag); - snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.data.payload.bytes); + snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.payload.bytes); display->drawStringMaxWidth(4 + x, 10 + y, SCREEN_WIDTH - (6 + x), tempBuf); } diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index 584a83bc8..510510ca3 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -118,7 +118,7 @@ void setCrypto(size_t chIndex) void Channels::initDefaults() { - devicestate.channels_count = MAX_CHANNELS; + devicestate.channels_count = MAX_NUM_CHANNELS; for (int i = 0; i < devicestate.channels_count; i++) fixupChannel(i); initDefaultChannel(0); diff --git a/src/mesh/DSRRouter.cpp b/src/mesh/DSRRouter.cpp index 8b1e6f67e..04d4a2bef 100644 --- a/src/mesh/DSRRouter.cpp +++ b/src/mesh/DSRRouter.cpp @@ -62,7 +62,7 @@ ErrorCode DSRRouter::send(MeshPacket *p) return ReliableRouter::send(p); } -void DSRRouter::sniffReceived(const MeshPacket *p) +void DSRRouter::sniffReceived(const MeshPacket *p, const Routing &c) { // 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 @@ -72,25 +72,25 @@ void DSRRouter::sniffReceived(const MeshPacket *p) addRoute(p->from, p->from, 0); // We are adjacent with zero hops } - switch (p->decoded.which_payloadVariant) { - case SubPacket_route_request_tag: + 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(p->decoded.route_request)) { + if (weAreInRoute(c.route_request)) { DEBUG_MSG("Ignoring a route request that contains us\n"); } else { - updateRoutes(p->decoded.route_request, + 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(p->decoded.route_request); + sendRouteReply(c.route_request); } 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) - sendRouteReply(p->decoded.route_request, nextHop); + sendRouteReply(c.route_request, nextHop); } else { // Not in our route cache, rebroadcast on their behalf (after adding ourselves to the request route) resendRouteRequest(p); @@ -98,14 +98,14 @@ void DSRRouter::sniffReceived(const MeshPacket *p) } } break; - case SubPacket_route_reply_tag: - updateRoutes(p->decoded.route_reply, false); + 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 SubPacket_error_reason_tag: + case Routing_error_reason_tag: removeRoute(p->decoded.dest); // FIXME: if any pending packets were waiting on this route, delete them @@ -131,7 +131,7 @@ void DSRRouter::sniffReceived(const MeshPacket *p) assert(p->decoded.source); // I think this is guaranteed by now // FIXME - what if the current packet _is_ a route error packet? - sendRouteError(p, ErrorReason_NO_ROUTE); + sendRouteError(p, Routing_Error_NO_ROUTE); } // FIXME, stop local processing of this packet @@ -139,18 +139,18 @@ void DSRRouter::sniffReceived(const MeshPacket *p) // 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_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + PacketId nakId = c.fail_id; 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, ErrorReason_GOT_NAK); + sendRouteError(p, Routing_Error_GOT_NAK); } } } - return ReliableRouter::sniffReceived(p); + ReliableRouter::sniffReceived(p, c); } /** @@ -230,7 +230,7 @@ void DSRRouter::sendNextHop(NodeNum n, const MeshPacket *p) /** * Send a route error packet towards whoever originally sent this message */ -void DSRRouter::sendRouteError(const MeshPacket *p, ErrorReason err) +void DSRRouter::sendRouteError(const MeshPacket *p, Routing_Error err) { DEBUG_MSG("FIXME not implemented sendRouteError\n"); } diff --git a/src/mesh/DSRRouter.h b/src/mesh/DSRRouter.h index 02c0f2775..eef1a991c 100644 --- a/src/mesh/DSRRouter.h +++ b/src/mesh/DSRRouter.h @@ -8,7 +8,7 @@ class DSRRouter : public ReliableRouter * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Send a packet on a suitable interface. This routine will @@ -70,7 +70,7 @@ class DSRRouter : public ReliableRouter /** * Send a route error packet towards whoever originally sent this message */ - void sendRouteError(const MeshPacket *p, ErrorReason err); + void sendRouteError(const MeshPacket *p, Routing_Error err); /** 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 diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index f2b718835..777178c41 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -27,7 +27,7 @@ bool FloodingRouter::shouldFilterReceived(const MeshPacket *p) return Router::shouldFilterReceived(p); } -void FloodingRouter::sniffReceived(const MeshPacket *p) +void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing &c) { // If a broadcast, possibly _also_ send copies out into the mesh. // (FIXME, do something smarter than naive flooding here) @@ -48,5 +48,5 @@ void FloodingRouter::sniffReceived(const MeshPacket *p) } // handle the packet as normal - Router::sniffReceived(p); + Router::sniffReceived(p, c); } diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index ca7ee489f..3e4f5de6e 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -55,5 +55,5 @@ class FloodingRouter : public Router, protected PacketHistory /** * Look for broadcasts we need to rebroadcast */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); }; diff --git a/src/mesh/MeshPacketQueue.cpp b/src/mesh/MeshPacketQueue.cpp index 363e83ba7..56db3feb3 100644 --- a/src/mesh/MeshPacketQueue.cpp +++ b/src/mesh/MeshPacketQueue.cpp @@ -33,7 +33,7 @@ void fixPriority(MeshPacket *p) if (p->priority == MeshPacket_Priority_UNSET) { // if acks give high priority // if a reliable message give a bit higher default priority - p->priority = p->decoded.which_ackVariant ? MeshPacket_Priority_ACK : + p->priority = (p->decoded.portnum == PortNum_ROUTING_APP) ? MeshPacket_Priority_ACK : (p->want_ack ? MeshPacket_Priority_RELIABLE : MeshPacket_Priority_DEFAULT); } } diff --git a/src/mesh/MeshPlugin.cpp b/src/mesh/MeshPlugin.cpp index ebaee49a6..7befb6623 100644 --- a/src/mesh/MeshPlugin.cpp +++ b/src/mesh/MeshPlugin.cpp @@ -32,7 +32,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) auto &pi = **i; pi.currentRequest = ∓ - if (pi.wantPortnum(mp.decoded.data.portnum)) { + if (pi.wantPortnum(mp.decoded.portnum)) { pluginFound = true; bool handled = pi.handleReceived(mp); @@ -50,7 +50,7 @@ void MeshPlugin::callPlugins(const MeshPacket &mp) } if(!pluginFound) - DEBUG_MSG("No plugins interested in portnum=%d\n", mp.decoded.data.portnum); + DEBUG_MSG("No plugins interested in portnum=%d\n", mp.decoded.portnum); } /** Messages can be received that have the want_response bit set. If set, this callback will be invoked diff --git a/src/mesh/MeshPlugin.h b/src/mesh/MeshPlugin.h index 01af58114..1c90f8829 100644 --- a/src/mesh/MeshPlugin.h +++ b/src/mesh/MeshPlugin.h @@ -31,6 +31,12 @@ class MeshPlugin protected: const char *name; + /* Most plugins only care about packets that are destined for their node (i.e. broadcasts or has their node as the specific recipient) + But some plugs might want to 'sniff' packets that are merely being routed (passing through the current node). Those plugins can set this to + true and their handleReceived() will be called for every packet. + */ + bool isPromiscuous = false; + /** * If this plugin is currently handling a request currentRequest will be preset * to the packet with the request. This is mostly useful for reply handlers. diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 9347ef0fd..3cc6b000b 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -4,6 +4,7 @@ #include "FS.h" +#include "Channels.h" #include "CryptoEngine.h" #include "FSCommon.h" #include "GPS.h" @@ -16,7 +17,6 @@ #include "configuration.h" #include "error.h" #include "main.h" -#include "Channels.h" #include "mesh-pb-constants.h" #include #include @@ -160,7 +160,7 @@ void NodeDB::init() loadFromDisk(); // saveToDisk(); - myNodeInfo.max_channels = MAX_CHANNELS; // tell others the max # of channels we can understand + myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand myNodeInfo.error_code = CriticalErrorCode_None; // For the error code, only show values from this boot (discard value from flash) @@ -394,7 +394,7 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p) void NodeDB::updateFrom(const MeshPacket &mp) { if (mp.which_payloadVariant == MeshPacket_decoded_tag) { - const SubPacket &p = mp.decoded; + const Data &p = mp.decoded; DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time); NodeInfo *info = getOrCreateNode(mp.from); @@ -406,18 +406,8 @@ void NodeDB::updateFrom(const MeshPacket &mp) info->snr = mp.rx_snr; // keep the most recent SNR we received for this node. - switch (p.which_payloadVariant) { - - case SubPacket_data_tag: { - if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) - MeshPlugin::callPlugins(mp); - break; - } - - default: { - notifyObservers(); // If the node counts have changed, notify observers - } - } + if (mp.to == NODENUM_BROADCAST || mp.to == nodeDB.getNodeNum()) + MeshPlugin::callPlugins(mp); } } diff --git a/src/mesh/ProtobufPlugin.h b/src/mesh/ProtobufPlugin.h index a5c0aea15..d931185e0 100644 --- a/src/mesh/ProtobufPlugin.h +++ b/src/mesh/ProtobufPlugin.h @@ -8,7 +8,7 @@ * If you are using protobufs to encode your packets (recommended) you can use this as a baseclass for your plugin * and avoid a bunch of boilerplate code. */ -template class ProtobufPlugin : private SinglePortPlugin +template class ProtobufPlugin : protected SinglePortPlugin { const pb_msgdesc_t *fields; @@ -38,8 +38,8 @@ template class ProtobufPlugin : private SinglePortPlugin // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = allocDataPacket(); - p->decoded.data.payload.size = - pb_encode_to_bytes(p->decoded.data.payload.bytes, sizeof(p->decoded.data.payload.bytes), fields, &payload); + p->decoded.payload.size = + pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), fields, &payload); // DEBUG_MSG("did encode\n"); return p; } @@ -54,7 +54,7 @@ template class ProtobufPlugin : private SinglePortPlugin // FIXME - we currently update position data in the DB only if the message was a broadcast or destined to us // it would be better to update even if the message was destined to others. - auto &p = mp.decoded.data; + auto &p = mp.decoded; DEBUG_MSG("Received %s from=0x%0x, id=0x%x, payloadlen=%d\n", name, mp.from, mp.id, p.payload.size); T scratch; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 0d99ca2ff..08ac40d5d 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -1,12 +1,12 @@ #include "RadioInterface.h" +#include "Channels.h" #include "MeshRadio.h" #include "MeshService.h" #include "NodeDB.h" #include "assert.h" #include "configuration.h" #include "sleep.h" -#include "Channels.h" #include #include #include @@ -122,17 +122,9 @@ void printPacket(const char *prefix, const MeshPacket *p) p->hop_limit); if (p->which_payloadVariant == MeshPacket_decoded_tag) { auto &s = p->decoded; - switch (s.which_payloadVariant) { - case SubPacket_data_tag: - DEBUG_MSG(" Portnum=%d", s.data.portnum); - break; - case 0: - DEBUG_MSG(" Payload:None"); - break; - default: - DEBUG_MSG(" Payload:%d", s.which_payloadVariant); - break; - } + + DEBUG_MSG(" Portnum=%d", s.portnum); + if (s.want_response) DEBUG_MSG(" WANTRESP"); @@ -142,10 +134,11 @@ void printPacket(const char *prefix, const MeshPacket *p) if (s.dest != 0) DEBUG_MSG(" dest=%08x", s.dest); + /* now inside Data and therefore kinda opaque if (s.which_ackVariant == SubPacket_success_id_tag) DEBUG_MSG(" successId=%08x", s.ackVariant.success_id); else if (s.which_ackVariant == SubPacket_fail_id_tag) - DEBUG_MSG(" failId=%08x", s.ackVariant.fail_id); + DEBUG_MSG(" failId=%08x", s.ackVariant.fail_id); */ } else { DEBUG_MSG(" encrypted"); } @@ -156,9 +149,9 @@ void printPacket(const char *prefix, const MeshPacket *p) if (p->rx_snr != 0.0) { DEBUG_MSG(" rxSNR=%g", p->rx_snr); } - if(p->priority != 0) + if (p->priority != 0) DEBUG_MSG(" priority=%d", p->priority); - + DEBUG_MSG(")\n"); } diff --git a/src/mesh/ReliableRouter.cpp b/src/mesh/ReliableRouter.cpp index 3bc8bfde5..3dc07c9c9 100644 --- a/src/mesh/ReliableRouter.cpp +++ b/src/mesh/ReliableRouter.cpp @@ -34,7 +34,7 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) // the original sending process. if (stopRetransmission(p->from, p->id)) { DEBUG_MSG("Someone is retransmitting for us, generate implicit ack\n"); - sendAckNak(ErrorReason_NONE, p->from, p->id); + sendAckNak(Routing_Error_NONE, p->from, p->id); } } @@ -53,20 +53,20 @@ bool ReliableRouter::shouldFilterReceived(const MeshPacket *p) * * Otherwise, let superclass handle it. */ -void ReliableRouter::sniffReceived(const MeshPacket *p) +void ReliableRouter::sniffReceived(const MeshPacket *p, const Routing &c) { NodeNum ourNode = getNodeNum(); if (p->to == ourNode) { // ignore ack/nak/want_ack packets that are not address to us (we only handle 0 hop reliability // - not DSR routing) if (p->want_ack) { - sendAckNak(ErrorReason_NONE, p->from, p->id); + sendAckNak(Routing_Error_NONE, p->from, p->id); } // If the payload is valid, look for ack/nak - PacketId ackId = p->decoded.which_ackVariant == SubPacket_success_id_tag ? p->decoded.ackVariant.success_id : 0; - PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + PacketId ackId = c.success_id; + PacketId nakId = c.fail_id; // We intentionally don't check wasSeenRecently, because it is harmless to delete non existent retransmission records if (ackId || nakId) { @@ -81,7 +81,7 @@ void ReliableRouter::sniffReceived(const MeshPacket *p) } // handle the packet as normal - FloodingRouter::sniffReceived(p); + FloodingRouter::sniffReceived(p, c); } #define NUM_RETRANSMISSIONS 3 @@ -155,7 +155,7 @@ int32_t ReliableRouter::doRetransmissions() if (p.numRetransmissions == 0) { DEBUG_MSG("Reliable send failed, returning a nak fr=0x%x,to=0x%x,id=%d\n", p.packet->from, p.packet->to, p.packet->id); - sendAckNak(ErrorReason_MAX_RETRANSMIT, p.packet->from, p.packet->id); + sendAckNak(Routing_Error_MAX_RETRANSMIT, p.packet->from, p.packet->id); // Note: we don't stop retransmission here, instead the Nak packet gets processed in sniffReceived - which // allows the DSR version to still be able to look at the PendingPacket stopRetransmission(it->first); diff --git a/src/mesh/ReliableRouter.h b/src/mesh/ReliableRouter.h index 62d555389..bf0338f9b 100644 --- a/src/mesh/ReliableRouter.h +++ b/src/mesh/ReliableRouter.h @@ -90,7 +90,7 @@ class ReliableRouter : public FloodingRouter /** * Look for acks/naks or someone retransmitting us */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Try to find the pending packet record for this ID (or NULL if not found) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 5178e229b..f20cf02bf 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -4,6 +4,7 @@ #include "configuration.h" #include "mesh-pb-constants.h" #include +#include "plugins/RoutingPlugin.h" /** * Router todo @@ -101,27 +102,9 @@ MeshPacket *Router::allocForSending() /** * Send an ack or a nak packet back towards whoever sent idFrom */ -void Router::sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom) +void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) { - auto p = allocForSending(); - p->hop_limit = 0; // Assume just immediate neighbors for now - p->to = to; - DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); - - if (!err) { - p->decoded.ackVariant.success_id = idFrom; - p->decoded.which_ackVariant = SubPacket_success_id_tag; - } else { - p->decoded.ackVariant.fail_id = idFrom; - p->decoded.which_ackVariant = SubPacket_fail_id_tag; - - // Also send back the error reason - p->decoded.which_payloadVariant = SubPacket_error_reason_tag; - p->decoded.error_reason = err; - } - p->priority = MeshPacket_Priority_ACK; - - sendLocal(p); // we sometimes send directly to the local node + routingPlugin->sendAckNak(err, to, idFrom); } @@ -138,7 +121,7 @@ ErrorCode Router::sendLocal(MeshPacket *p) // ERROR! no radio found, report failure back to the client and drop the packet DEBUG_MSG("Error: No interface, returning NAK and dropping packet.\n"); - sendAckNak(ErrorReason_NO_INTERFACE, p->from, p->id); + sendAckNak(Routing_Error_NO_INTERFACE, p->from, p->id); packetPool.release(p); return ERRNO_NO_INTERFACES; @@ -162,9 +145,8 @@ ErrorCode Router::send(MeshPacket *p) { assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal - PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; - assert( - !nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with assert + // PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0; + // assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with assert // Never set the want_ack flag on broadcast packets sent over the air. if (p->to == NODENUM_BROADCAST) @@ -179,7 +161,7 @@ ErrorCode Router::send(MeshPacket *p) if (p->which_payloadVariant == MeshPacket_decoded_tag) { static uint8_t bytes[MAX_RHPACKETLEN]; // we have to use a scratch buffer because a union - size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), SubPacket_fields, &p->decoded); + size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded); assert(numbytes <= MAX_RHPACKETLEN); crypto->encrypt(p->from, p->id, numbytes, bytes); @@ -212,7 +194,7 @@ bool Router::cancelSending(NodeNum from, PacketId id) { * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ -void Router::sniffReceived(const MeshPacket *p) +void Router::sniffReceived(const MeshPacket *p, const Routing &c) { DEBUG_MSG("FIXME-update-db Sniffing packet\n"); // FIXME, update nodedb here for any packet that passes through us @@ -234,7 +216,7 @@ bool Router::perhapsDecode(MeshPacket *p) crypto->decrypt(p->from, p->id, p->encrypted.size, bytes); // Take those raw bytes and convert them back into a well structured protobuf we can understand - if (!pb_decode_from_bytes(bytes, p->encrypted.size, SubPacket_fields, &p->decoded)) { + if (!pb_decode_from_bytes(bytes, p->encrypted.size, Data_fields, &p->decoded)) { DEBUG_MSG("Invalid protobufs in received mesh packet!\n"); return false; } else { @@ -262,7 +244,8 @@ void Router::handleReceived(MeshPacket *p) if (perhapsDecode(p)) { // parsing was successful, queue for our recipient - sniffReceived(p); + assert(0); // FIXME, call any promiscious plugins here, make a (non promisiocous) plugin for forwarding messages to phone api + // sniffReceived(p); if (p->to == NODENUM_BROADCAST || p->to == getNodeNum()) { printPacket("Delivering rx packet", p); diff --git a/src/mesh/Router.h b/src/mesh/Router.h index 3951f3062..e9a10dae1 100644 --- a/src/mesh/Router.h +++ b/src/mesh/Router.h @@ -68,6 +68,8 @@ class Router : protected concurrency::OSThread NodeNum getNodeNum(); protected: + friend class RoutingPlugin; + /** * Send a packet on a suitable interface. This routine will * later free() the packet to pool. This routine is not allowed to stall. @@ -79,6 +81,8 @@ class Router : protected concurrency::OSThread /** * Should this incoming filter be dropped? + * + * FIXME, move this into the new RoutingPlugin and do the filtering there using the regular plugin logic * * Called immedately on receiption, before any further processing. * @return true to abandon the packet @@ -89,7 +93,7 @@ class Router : protected concurrency::OSThread * Every (non duplicate) packet this node receives will be passed through this method. This allows subclasses to * update routing tables etc... based on what we overhear (even for messages not destined to our node) */ - virtual void sniffReceived(const MeshPacket *p); + virtual void sniffReceived(const MeshPacket *p, const Routing &c); /** * Remove any encryption and decode the protobufs inside this packet (if necessary). @@ -101,7 +105,7 @@ class Router : protected concurrency::OSThread /** * Send an ack or a nak packet back towards whoever sent idFrom */ - void sendAckNak(ErrorReason err, NodeNum to, PacketId idFrom); + void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom); private: /** diff --git a/src/mesh/SinglePortPlugin.h b/src/mesh/SinglePortPlugin.h index d182579b7..5fa609dd4 100644 --- a/src/mesh/SinglePortPlugin.h +++ b/src/mesh/SinglePortPlugin.h @@ -32,8 +32,7 @@ class SinglePortPlugin : public MeshPlugin { // Update our local node info with our position (even if we don't decide to update anyone else) MeshPacket *p = router->allocForSending(); - p->decoded.which_payloadVariant = SubPacket_data_tag; - p->decoded.data.portnum = ourPortNum; + p->decoded.portnum = ourPortNum; return p; } diff --git a/src/mesh/generated/apponly.pb.c b/src/mesh/generated/apponly.pb.c index c93d63292..d6f17d7f7 100644 --- a/src/mesh/generated/apponly.pb.c +++ b/src/mesh/generated/apponly.pb.c @@ -9,4 +9,7 @@ PB_BIND(ServiceEnvelope, ServiceEnvelope, 2) +PB_BIND(ChannelSet, ChannelSet, AUTO) + + diff --git a/src/mesh/generated/apponly.pb.h b/src/mesh/generated/apponly.pb.h index fbf80324b..af527f0c8 100644 --- a/src/mesh/generated/apponly.pb.h +++ b/src/mesh/generated/apponly.pb.h @@ -11,6 +11,10 @@ #endif /* Struct definitions */ +typedef struct _ChannelSet { + pb_callback_t settings; +} ChannelSet; + typedef struct _ServiceEnvelope { bool has_packet; MeshPacket packet; @@ -25,9 +29,12 @@ extern "C" { /* Initializer values for message structs */ #define ServiceEnvelope_init_default {false, MeshPacket_init_default, {{NULL}, NULL}, {{NULL}, NULL}} +#define ChannelSet_init_default {{{NULL}, NULL}} #define ServiceEnvelope_init_zero {false, MeshPacket_init_zero, {{NULL}, NULL}, {{NULL}, NULL}} +#define ChannelSet_init_zero {{{NULL}, NULL}} /* Field tags (for use in manual encoding/decoding) */ +#define ChannelSet_settings_tag 1 #define ServiceEnvelope_packet_tag 1 #define ServiceEnvelope_channel_id_tag 2 #define ServiceEnvelope_gateway_id_tag 3 @@ -41,13 +48,22 @@ X(a, CALLBACK, SINGULAR, STRING, gateway_id, 3) #define ServiceEnvelope_DEFAULT NULL #define ServiceEnvelope_packet_MSGTYPE MeshPacket +#define ChannelSet_FIELDLIST(X, a) \ +X(a, CALLBACK, REPEATED, MESSAGE, settings, 1) +#define ChannelSet_CALLBACK pb_default_field_callback +#define ChannelSet_DEFAULT NULL +#define ChannelSet_settings_MSGTYPE ChannelSettings + extern const pb_msgdesc_t ServiceEnvelope_msg; +extern const pb_msgdesc_t ChannelSet_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define ServiceEnvelope_fields &ServiceEnvelope_msg +#define ChannelSet_fields &ChannelSet_msg /* Maximum encoded size of messages (where known) */ /* ServiceEnvelope_size depends on runtime parameters */ +/* ChannelSet_size depends on runtime parameters */ #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/deviceonly.pb.h b/src/mesh/generated/deviceonly.pb.h index e1f4c4010..47ffe2ae3 100644 --- a/src/mesh/generated/deviceonly.pb.h +++ b/src/mesh/generated/deviceonly.pb.h @@ -80,7 +80,7 @@ extern const pb_msgdesc_t DeviceState_msg; #define DeviceState_fields &DeviceState_msg /* Maximum encoded size of messages (where known) */ -#define DeviceState_size 6265 +#define DeviceState_size 6225 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index 872447623..c4fd0d8e5 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -9,16 +9,16 @@ PB_BIND(Position, Position, AUTO) -PB_BIND(Data, Data, AUTO) - - PB_BIND(User, User, AUTO) PB_BIND(RouteDiscovery, RouteDiscovery, AUTO) -PB_BIND(SubPacket, SubPacket, 2) +PB_BIND(Routing, Routing, AUTO) + + +PB_BIND(Data, Data, 2) PB_BIND(MeshPacket, MeshPacket, 2) diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 691b4cd78..ca47ffa89 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -11,15 +11,6 @@ #endif /* Enum definitions */ -typedef enum _ErrorReason { - ErrorReason_NONE = 0, - ErrorReason_NO_ROUTE = 1, - ErrorReason_GOT_NAK = 2, - ErrorReason_TIMEOUT = 3, - ErrorReason_NO_INTERFACE = 4, - ErrorReason_MAX_RETRANSMIT = 5 -} ErrorReason; - typedef enum _Constants { Constants_Unused = 0, Constants_DATA_PAYLOAD_LEN = 240 @@ -83,6 +74,15 @@ typedef enum _CriticalErrorCode { CriticalErrorCode_TransmitFailed = 8 } CriticalErrorCode; +typedef enum _Routing_Error { + Routing_Error_NONE = 0, + Routing_Error_NO_ROUTE = 1, + Routing_Error_GOT_NAK = 2, + Routing_Error_TIMEOUT = 3, + Routing_Error_NO_INTERFACE = 4, + Routing_Error_MAX_RETRANSMIT = 5 +} Routing_Error; + typedef enum _MeshPacket_Priority { MeshPacket_Priority_UNSET = 0, MeshPacket_Priority_MIN = 1, @@ -136,6 +136,9 @@ typedef PB_BYTES_ARRAY_T(240) Data_payload_t; typedef struct _Data { PortNum portnum; Data_payload_t payload; + bool want_response; + uint32_t dest; + uint32_t source; } Data; typedef struct _LogRecord { @@ -216,7 +219,7 @@ typedef struct _RadioConfig_UserPreferences { typedef struct _RouteDiscovery { pb_size_t route_count; - int32_t route[8]; + uint32_t route[8]; } RouteDiscovery; typedef struct _User { @@ -233,6 +236,24 @@ typedef struct _Channel { Channel_Role role; } Channel; +typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; +typedef struct _MeshPacket { + uint32_t from; + uint32_t to; + pb_size_t which_payloadVariant; + union { + Data decoded; + MeshPacket_encrypted_t encrypted; + }; + uint32_t channel_index; + uint32_t id; + float rx_snr; + uint32_t rx_time; + uint32_t hop_limit; + bool want_ack; + MeshPacket_Priority priority; +} MeshPacket; + typedef struct _NodeInfo { uint32_t num; bool has_user; @@ -248,48 +269,22 @@ typedef struct _RadioConfig { RadioConfig_UserPreferences preferences; } RadioConfig; -typedef struct _SubPacket { - uint32_t original_id; - pb_size_t which_payloadVariant; +typedef struct _Routing { + pb_size_t which_variant; union { - Data data; RouteDiscovery route_request; RouteDiscovery route_reply; - ErrorReason error_reason; - }; - bool want_response; - uint32_t dest; - pb_size_t which_ackVariant; - union { + Routing_Error error_reason; uint32_t success_id; uint32_t fail_id; - } ackVariant; - uint32_t source; -} SubPacket; - -typedef PB_BYTES_ARRAY_T(256) MeshPacket_encrypted_t; -typedef struct _MeshPacket { - uint32_t from; - uint32_t to; - pb_size_t which_payloadVariant; - union { - SubPacket decoded; - MeshPacket_encrypted_t encrypted; }; - uint32_t channel_index; - uint32_t id; - float rx_snr; - uint32_t rx_time; - uint32_t hop_limit; - bool want_ack; - MeshPacket_Priority priority; -} MeshPacket; + uint32_t original_id; +} Routing; typedef struct _FromRadio { uint32_t num; pb_size_t which_payloadVariant; union { - MeshPacket packet; MyNodeInfo my_info; NodeInfo node_info; RadioConfig radio; @@ -297,6 +292,7 @@ typedef struct _FromRadio { uint32_t config_complete_id; bool rebooted; Channel channel; + MeshPacket packet; }; } FromRadio; @@ -313,10 +309,6 @@ typedef struct _ToRadio { /* Helper constants for enums */ -#define _ErrorReason_MIN ErrorReason_NONE -#define _ErrorReason_MAX ErrorReason_MAX_RETRANSMIT -#define _ErrorReason_ARRAYSIZE ((ErrorReason)(ErrorReason_MAX_RETRANSMIT+1)) - #define _Constants_MIN Constants_Unused #define _Constants_MAX Constants_DATA_PAYLOAD_LEN #define _Constants_ARRAYSIZE ((Constants)(Constants_DATA_PAYLOAD_LEN+1)) @@ -341,6 +333,10 @@ typedef struct _ToRadio { #define _CriticalErrorCode_MAX CriticalErrorCode_TransmitFailed #define _CriticalErrorCode_ARRAYSIZE ((CriticalErrorCode)(CriticalErrorCode_TransmitFailed+1)) +#define _Routing_Error_MIN Routing_Error_NONE +#define _Routing_Error_MAX Routing_Error_MAX_RETRANSMIT +#define _Routing_Error_ARRAYSIZE ((Routing_Error)(Routing_Error_MAX_RETRANSMIT+1)) + #define _MeshPacket_Priority_MIN MeshPacket_Priority_UNSET #define _MeshPacket_Priority_MAX MeshPacket_Priority_MAX #define _MeshPacket_Priority_ARRAYSIZE ((MeshPacket_Priority)(MeshPacket_Priority_MAX+1)) @@ -364,11 +360,11 @@ extern "C" { /* Initializer values for message structs */ #define Position_init_default {0, 0, 0, 0, 0} -#define Data_init_default {_PortNum_MIN, {0, {0}}} #define User_init_default {"", "", "", {0}} #define RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_default {0, 0, {Data_init_default}, 0, 0, 0, {0}, 0} -#define MeshPacket_init_default {0, 0, 0, {SubPacket_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define Routing_init_default {0, {RouteDiscovery_init_default}, 0} +#define Data_init_default {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define MeshPacket_init_default {0, 0, 0, {Data_init_default}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_default {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_default {0, false, ChannelSettings_init_default, _Channel_Role_MIN} #define RadioConfig_init_default {false, RadioConfig_UserPreferences_init_default} @@ -376,14 +372,14 @@ extern "C" { #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} -#define FromRadio_init_default {0, 0, {MeshPacket_init_default}} +#define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} #define Position_init_zero {0, 0, 0, 0, 0} -#define Data_init_zero {_PortNum_MIN, {0, {0}}} #define User_init_zero {"", "", "", {0}} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} -#define SubPacket_init_zero {0, 0, {Data_init_zero}, 0, 0, 0, {0}, 0} -#define MeshPacket_init_zero {0, 0, 0, {SubPacket_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} +#define Routing_init_zero {0, {RouteDiscovery_init_zero}, 0} +#define Data_init_zero {_PortNum_MIN, {0, {0}}, 0, 0, 0} +#define MeshPacket_init_zero {0, 0, 0, {Data_init_zero}, 0, 0, 0, 0, 0, 0, _MeshPacket_Priority_MIN} #define ChannelSettings_init_zero {0, _ChannelSettings_ModemConfig_MIN, {0, {0}}, "", 0, 0, 0, 0, 0, 0, 0} #define Channel_init_zero {0, false, ChannelSettings_init_zero, _Channel_Role_MIN} #define RadioConfig_init_zero {false, RadioConfig_UserPreferences_init_zero} @@ -391,7 +387,7 @@ extern "C" { #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", _CriticalErrorCode_MIN, 0, 0, 0, 0, 0} #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} -#define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} +#define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} /* Field tags (for use in manual encoding/decoding) */ @@ -408,6 +404,9 @@ extern "C" { #define ChannelSettings_downlink_enabled_tag 17 #define Data_portnum_tag 1 #define Data_payload_tag 2 +#define Data_want_response_tag 5 +#define Data_dest_tag 9 +#define Data_source_tag 12 #define LogRecord_message_tag 1 #define LogRecord_time_tag 2 #define LogRecord_source_tag 3 @@ -479,22 +478,6 @@ extern "C" { #define Channel_index_tag 1 #define Channel_settings_tag 2 #define Channel_role_tag 3 -#define NodeInfo_num_tag 1 -#define NodeInfo_user_tag 2 -#define NodeInfo_position_tag 3 -#define NodeInfo_next_hop_tag 5 -#define NodeInfo_snr_tag 7 -#define RadioConfig_preferences_tag 1 -#define SubPacket_original_id_tag 2 -#define SubPacket_data_tag 3 -#define SubPacket_route_request_tag 6 -#define SubPacket_route_reply_tag 7 -#define SubPacket_error_reason_tag 13 -#define SubPacket_want_response_tag 5 -#define SubPacket_dest_tag 9 -#define SubPacket_success_id_tag 10 -#define SubPacket_fail_id_tag 11 -#define SubPacket_source_tag 12 #define MeshPacket_from_tag 1 #define MeshPacket_to_tag 2 #define MeshPacket_decoded_tag 3 @@ -506,8 +489,19 @@ extern "C" { #define MeshPacket_hop_limit_tag 10 #define MeshPacket_want_ack_tag 11 #define MeshPacket_priority_tag 12 +#define NodeInfo_num_tag 1 +#define NodeInfo_user_tag 2 +#define NodeInfo_position_tag 3 +#define NodeInfo_next_hop_tag 5 +#define NodeInfo_snr_tag 7 +#define RadioConfig_preferences_tag 1 +#define Routing_route_request_tag 1 +#define Routing_route_reply_tag 2 +#define Routing_error_reason_tag 3 +#define Routing_success_id_tag 4 +#define Routing_fail_id_tag 5 +#define Routing_original_id_tag 6 #define FromRadio_num_tag 1 -#define FromRadio_packet_tag 2 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 #define FromRadio_radio_tag 6 @@ -515,7 +509,8 @@ extern "C" { #define FromRadio_config_complete_id_tag 8 #define FromRadio_rebooted_tag 9 #define FromRadio_channel_tag 10 -#define ToRadio_packet_tag 1 +#define FromRadio_packet_tag 11 +#define ToRadio_packet_tag 2 #define ToRadio_want_config_id_tag 100 #define ToRadio_set_radio_tag 101 #define ToRadio_set_owner_tag 102 @@ -531,12 +526,6 @@ X(a, STATIC, SINGULAR, FIXED32, time, 9) #define Position_CALLBACK NULL #define Position_DEFAULT NULL -#define Data_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ -X(a, STATIC, SINGULAR, BYTES, payload, 2) -#define Data_CALLBACK NULL -#define Data_DEFAULT NULL - #define User_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, id, 1) \ X(a, STATIC, SINGULAR, STRING, long_name, 2) \ @@ -546,34 +535,38 @@ X(a, STATIC, SINGULAR, FIXED_LENGTH_BYTES, macaddr, 4) #define User_DEFAULT NULL #define RouteDiscovery_FIELDLIST(X, a) \ -X(a, STATIC, REPEATED, INT32, route, 2) +X(a, STATIC, REPEATED, FIXED32, route, 2) #define RouteDiscovery_CALLBACK NULL #define RouteDiscovery_DEFAULT NULL -#define SubPacket_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, original_id, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,data,data), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_request,route_request), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,route_reply,route_reply), 7) \ -X(a, STATIC, ONEOF, UENUM, (payloadVariant,error_reason,error_reason), 13) \ +#define Routing_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,route_request,route_request), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (variant,route_reply,route_reply), 2) \ +X(a, STATIC, ONEOF, UENUM, (variant,error_reason,error_reason), 3) \ +X(a, STATIC, ONEOF, FIXED32, (variant,success_id,success_id), 4) \ +X(a, STATIC, ONEOF, FIXED32, (variant,fail_id,fail_id), 5) \ +X(a, STATIC, SINGULAR, FIXED32, original_id, 6) +#define Routing_CALLBACK NULL +#define Routing_DEFAULT NULL +#define Routing_variant_route_request_MSGTYPE RouteDiscovery +#define Routing_variant_route_reply_MSGTYPE RouteDiscovery + +#define Data_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, portnum, 1) \ +X(a, STATIC, SINGULAR, BYTES, payload, 2) \ X(a, STATIC, SINGULAR, BOOL, want_response, 5) \ -X(a, STATIC, SINGULAR, UINT32, dest, 9) \ -X(a, STATIC, ONEOF, UINT32, (ackVariant,success_id,ackVariant.success_id), 10) \ -X(a, STATIC, ONEOF, UINT32, (ackVariant,fail_id,ackVariant.fail_id), 11) \ -X(a, STATIC, SINGULAR, UINT32, source, 12) -#define SubPacket_CALLBACK NULL -#define SubPacket_DEFAULT NULL -#define SubPacket_payloadVariant_data_MSGTYPE Data -#define SubPacket_payloadVariant_route_request_MSGTYPE RouteDiscovery -#define SubPacket_payloadVariant_route_reply_MSGTYPE RouteDiscovery +X(a, STATIC, SINGULAR, FIXED32, dest, 9) \ +X(a, STATIC, SINGULAR, FIXED32, source, 12) +#define Data_CALLBACK NULL +#define Data_DEFAULT NULL #define MeshPacket_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, from, 1) \ -X(a, STATIC, SINGULAR, UINT32, to, 2) \ +X(a, STATIC, SINGULAR, FIXED32, from, 1) \ +X(a, STATIC, SINGULAR, FIXED32, to, 2) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,decoded,decoded), 3) \ X(a, STATIC, ONEOF, BYTES, (payloadVariant,encrypted,encrypted), 8) \ X(a, STATIC, SINGULAR, UINT32, channel_index, 4) \ -X(a, STATIC, SINGULAR, UINT32, id, 6) \ +X(a, STATIC, SINGULAR, FIXED32, id, 6) \ X(a, STATIC, SINGULAR, FLOAT, rx_snr, 7) \ X(a, STATIC, SINGULAR, FIXED32, rx_time, 9) \ X(a, STATIC, SINGULAR, UINT32, hop_limit, 10) \ @@ -581,7 +574,7 @@ X(a, STATIC, SINGULAR, BOOL, want_ack, 11) \ X(a, STATIC, SINGULAR, UENUM, priority, 12) #define MeshPacket_CALLBACK NULL #define MeshPacket_DEFAULT NULL -#define MeshPacket_payloadVariant_decoded_MSGTYPE SubPacket +#define MeshPacket_payloadVariant_decoded_MSGTYPE Data #define ChannelSettings_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, tx_power, 1) \ @@ -695,25 +688,25 @@ X(a, STATIC, SINGULAR, UENUM, level, 4) #define FromRadio_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, num, 1) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,radio,radio), 6) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,channel,channel), 10) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11) #define FromRadio_CALLBACK NULL #define FromRadio_DEFAULT NULL -#define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket #define FromRadio_payloadVariant_my_info_MSGTYPE MyNodeInfo #define FromRadio_payloadVariant_node_info_MSGTYPE NodeInfo #define FromRadio_payloadVariant_radio_MSGTYPE RadioConfig #define FromRadio_payloadVariant_log_record_MSGTYPE LogRecord #define FromRadio_payloadVariant_channel_MSGTYPE Channel +#define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket #define ToRadio_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_radio,set_radio), 101) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_owner,set_owner), 102) \ @@ -726,10 +719,10 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,set_channel,set_channel), 104 #define ToRadio_payloadVariant_set_channel_MSGTYPE Channel extern const pb_msgdesc_t Position_msg; -extern const pb_msgdesc_t Data_msg; extern const pb_msgdesc_t User_msg; extern const pb_msgdesc_t RouteDiscovery_msg; -extern const pb_msgdesc_t SubPacket_msg; +extern const pb_msgdesc_t Routing_msg; +extern const pb_msgdesc_t Data_msg; extern const pb_msgdesc_t MeshPacket_msg; extern const pb_msgdesc_t ChannelSettings_msg; extern const pb_msgdesc_t Channel_msg; @@ -743,10 +736,10 @@ extern const pb_msgdesc_t ToRadio_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Position_fields &Position_msg -#define Data_fields &Data_msg #define User_fields &User_msg #define RouteDiscovery_fields &RouteDiscovery_msg -#define SubPacket_fields &SubPacket_msg +#define Routing_fields &Routing_msg +#define Data_fields &Data_msg #define MeshPacket_fields &MeshPacket_msg #define ChannelSettings_fields &ChannelSettings_msg #define Channel_fields &Channel_msg @@ -760,11 +753,11 @@ extern const pb_msgdesc_t ToRadio_msg; /* Maximum encoded size of messages (where known) */ #define Position_size 37 -#define Data_size 246 #define User_size 72 -#define RouteDiscovery_size 88 -#define SubPacket_size 275 -#define MeshPacket_size 322 +#define RouteDiscovery_size 40 +#define Routing_size 47 +#define Data_size 258 +#define MeshPacket_size 302 #define ChannelSettings_size 95 #define Channel_size 105 #define RadioConfig_size 308 @@ -772,8 +765,8 @@ extern const pb_msgdesc_t ToRadio_msg; #define NodeInfo_size 130 #define MyNodeInfo_size 89 #define LogRecord_size 81 -#define FromRadio_size 331 -#define ToRadio_size 325 +#define FromRadio_size 317 +#define ToRadio_size 312 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/portnums.pb.h b/src/mesh/generated/portnums.pb.h index 2133ecaa7..72360f295 100644 --- a/src/mesh/generated/portnums.pb.h +++ b/src/mesh/generated/portnums.pb.h @@ -16,6 +16,7 @@ typedef enum _PortNum { PortNum_REMOTE_HARDWARE_APP = 2, PortNum_POSITION_APP = 3, PortNum_NODEINFO_APP = 4, + PortNum_ROUTING_APP = 5, PortNum_REPLY_APP = 32, PortNum_IP_TUNNEL_APP = 33, PortNum_SERIAL_APP = 64, diff --git a/src/mesh/mesh-pb-constants.h b/src/mesh/mesh-pb-constants.h index ed1c4f7e8..21163c496 100644 --- a/src/mesh/mesh-pb-constants.h +++ b/src/mesh/mesh-pb-constants.h @@ -17,7 +17,7 @@ #define MAX_NUM_NODES (member_size(DeviceState, node_db) / member_size(DeviceState, node_db[0])) /// Max number of channels allowed -#define MAX_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0])) +#define MAX_NUM_CHANNELS (member_size(DeviceState, channels) / member_size(DeviceState, channels[0])) /// helper function for encoding a record as a protobuf, any failures to encode are fatal and we will panic /// returns the encoded packet size diff --git a/src/plugins/Plugins.cpp b/src/plugins/Plugins.cpp index ac8dd7336..65cfdcee4 100644 --- a/src/plugins/Plugins.cpp +++ b/src/plugins/Plugins.cpp @@ -7,12 +7,14 @@ #include "plugins/SerialPlugin.h" #include "plugins/StoreForwardPlugin.h" #include "plugins/TextMessagePlugin.h" +#include "plugins/RoutingPlugin.h" /** * Create plugin instances here. If you are adding a new plugin, you must 'new' it here (or somewhere else) */ void setupPlugins() { + routingPlugin = new RoutingPlugin(); nodeInfoPlugin = new NodeInfoPlugin(); positionPlugin = new PositionPlugin(); textMessagePlugin = new TextMessagePlugin(); diff --git a/src/plugins/RangeTestPlugin.cpp b/src/plugins/RangeTestPlugin.cpp index 58150f5bb..dc5f30048 100644 --- a/src/plugins/RangeTestPlugin.cpp +++ b/src/plugins/RangeTestPlugin.cpp @@ -108,8 +108,8 @@ void RangeTestPluginRadio::sendPayload(NodeNum dest, bool wantReplies) static char heartbeatString[20]; snprintf(heartbeatString, sizeof(heartbeatString), "seq %d", packetSequence); - p->decoded.data.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply - memcpy(p->decoded.data.payload.bytes, heartbeatString, p->decoded.data.payload.size); + p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply + memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size); service.sendToMesh(p); } diff --git a/src/plugins/ReplyPlugin.cpp b/src/plugins/ReplyPlugin.cpp index a8c607436..69903aa36 100644 --- a/src/plugins/ReplyPlugin.cpp +++ b/src/plugins/ReplyPlugin.cpp @@ -9,7 +9,7 @@ MeshPacket *ReplyPlugin::allocReply() { assert(currentRequest); // should always be !NULL auto req = *currentRequest; - auto &p = req.decoded.data; + auto &p = req.decoded; // The incoming message is in p.payload DEBUG_MSG("Received message from=0x%0x, id=%d, msg=%.*s\n", req.from, req.id, p.payload.size, p.payload.bytes); @@ -17,8 +17,8 @@ MeshPacket *ReplyPlugin::allocReply() const char *replyStr = "Message Received"; auto reply = allocDataPacket(); // Allocate a packet for sending - reply->decoded.data.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply - memcpy(reply->decoded.data.payload.bytes, replyStr, reply->decoded.data.payload.size); + reply->decoded.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply + memcpy(reply->decoded.payload.bytes, replyStr, reply->decoded.payload.size); return reply; } diff --git a/src/plugins/RoutingPlugin.cpp b/src/plugins/RoutingPlugin.cpp new file mode 100644 index 000000000..6f4c2123b --- /dev/null +++ b/src/plugins/RoutingPlugin.cpp @@ -0,0 +1,54 @@ +#include "RoutingPlugin.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" +#include "Router.h" +#include "configuration.h" +#include "main.h" + +RoutingPlugin *routingPlugin; + +bool RoutingPlugin::handleReceivedProtobuf(const MeshPacket &mp, const Routing &p) +{ + + return false; // Let others look at this message also if they want +} + + +MeshPacket *RoutingPlugin::allocReply() +{ + assert(0); // 1.2 refactoring fixme, Not sure if anything needs this yet? + // return allocDataProtobuf(u); + return NULL; +} + +void RoutingPlugin::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom) +{ + Routing c = Routing_init_default; + + if (!err) { + c.success_id = idFrom; + } else { + c.fail_id = idFrom; + + // Also send back the error reason + c.error_reason = err; + } + + auto p = allocDataProtobuf(c); + p->priority = MeshPacket_Priority_ACK; + + p->hop_limit = 0; // Assume just immediate neighbors for now + p->to = to; + DEBUG_MSG("Sending an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id); + + router->sendLocal(p); // we sometimes send directly to the local node +} + +RoutingPlugin::RoutingPlugin() + : ProtobufPlugin("routing", PortNum_ROUTING_APP, User_fields) +{ + isPromiscuous = true; +} + + diff --git a/src/plugins/RoutingPlugin.h b/src/plugins/RoutingPlugin.h new file mode 100644 index 000000000..080b8fe12 --- /dev/null +++ b/src/plugins/RoutingPlugin.h @@ -0,0 +1,31 @@ +#pragma once +#include "ProtobufPlugin.h" + +/** + * Routing plugin for router control messages + */ +class RoutingPlugin : public ProtobufPlugin +{ + public: + /** Constructor + * name is for debugging output + */ + RoutingPlugin(); + + protected: + friend class Router; + + /** Called to handle a particular incoming message + + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceivedProtobuf(const MeshPacket &mp, const Routing &p); + + /** Messages can be received that have the want_response bit set. If set, this callback will be invoked + * so that subclasses can (optionally) send a response back to the original sender. */ + virtual MeshPacket *allocReply(); + + void sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom); +}; + +extern RoutingPlugin *routingPlugin; \ No newline at end of file diff --git a/src/plugins/SerialPlugin.cpp b/src/plugins/SerialPlugin.cpp index 47f279089..a3493c880 100644 --- a/src/plugins/SerialPlugin.cpp +++ b/src/plugins/SerialPlugin.cpp @@ -144,8 +144,8 @@ void SerialPluginRadio::sendPayload(NodeNum dest, bool wantReplies) p->want_ack = SERIALPLUGIN_ACK; - p->decoded.data.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply - memcpy(p->decoded.data.payload.bytes, serialStringChar, p->decoded.data.payload.size); + p->decoded.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply + memcpy(p->decoded.payload.bytes, serialStringChar, p->decoded.payload.size); service.sendToMesh(p); } diff --git a/src/plugins/TextMessagePlugin.cpp b/src/plugins/TextMessagePlugin.cpp index 4ad080702..8da2a10f9 100644 --- a/src/plugins/TextMessagePlugin.cpp +++ b/src/plugins/TextMessagePlugin.cpp @@ -7,7 +7,7 @@ TextMessagePlugin *textMessagePlugin; bool TextMessagePlugin::handleReceived(const MeshPacket &mp) { - auto &p = mp.decoded.data; + auto &p = mp.decoded; DEBUG_MSG("Received text msg from=0x%0x, id=%d, msg=%.*s\n", mp.from, mp.id, p.payload.size, p.payload.bytes); // We only store/display messages destined for us.