2020-04-17 16:48:54 +00:00
|
|
|
#include "Router.h"
|
2021-02-22 04:57:26 +00:00
|
|
|
#include "Channels.h"
|
2020-05-10 00:51:20 +00:00
|
|
|
#include "CryptoEngine.h"
|
2021-02-22 04:57:26 +00:00
|
|
|
#include "NodeDB.h"
|
2020-10-07 23:28:57 +00:00
|
|
|
#include "RTC.h"
|
2022-04-12 03:09:48 +00:00
|
|
|
#include "configuration.h"
|
2021-03-28 04:16:37 +00:00
|
|
|
#include "main.h"
|
2020-04-17 16:48:54 +00:00
|
|
|
#include "mesh-pb-constants.h"
|
2022-02-27 08:18:35 +00:00
|
|
|
#include "modules/RoutingModule.h"
|
2022-04-12 03:09:48 +00:00
|
|
|
extern "C" {
|
|
|
|
#include "mesh/compression/unishox2.h"
|
|
|
|
}
|
2020-04-17 16:48:54 +00:00
|
|
|
|
2021-04-05 05:00:56 +00:00
|
|
|
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
|
|
|
#include "mqtt/MQTT.h"
|
|
|
|
#endif
|
|
|
|
|
2020-04-17 16:48:54 +00:00
|
|
|
/**
|
|
|
|
* Router todo
|
|
|
|
*
|
2020-04-17 18:52:20 +00:00
|
|
|
* DONE: Implement basic interface and use it elsewhere in app
|
2020-04-17 16:48:54 +00:00
|
|
|
* 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
|
|
|
|
*
|
|
|
|
**/
|
|
|
|
|
|
|
|
#define MAX_RX_FROMRADIO \
|
|
|
|
4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big
|
|
|
|
|
|
|
|
// I think this is right, one packet for each of the three fifos + one packet being currently assembled for TX or RX
|
2020-06-13 15:27:44 +00:00
|
|
|
// And every TX packet might have a retransmission packet or an ack alive at any moment
|
2020-04-17 16:48:54 +00:00
|
|
|
#define MAX_PACKETS \
|
2020-06-13 15:27:44 +00:00
|
|
|
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + 2 * MAX_TX_QUEUE + \
|
2020-04-17 16:48:54 +00:00
|
|
|
2) // max number of packets which can be in flight (either queued from reception or queued for sending)
|
|
|
|
|
2020-07-10 20:52:26 +00:00
|
|
|
// static MemoryPool<MeshPacket> staticPool(MAX_PACKETS);
|
|
|
|
static MemoryDynamic<MeshPacket> staticPool;
|
2020-06-12 18:53:59 +00:00
|
|
|
|
|
|
|
Allocator<MeshPacket> &packetPool = staticPool;
|
2020-04-17 16:48:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*
|
|
|
|
* Currently we only allow one interface, that may change in the future
|
|
|
|
*/
|
2020-10-09 06:16:51 +00:00
|
|
|
Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRADIO)
|
2020-06-17 02:55:14 +00:00
|
|
|
{
|
2020-07-10 20:52:26 +00:00
|
|
|
// This is called pre main(), don't touch anything here, the following code is not safe
|
2020-06-17 23:04:37 +00:00
|
|
|
|
|
|
|
/* DEBUG_MSG("Size of NodeInfo %d\n", sizeof(NodeInfo));
|
2020-06-17 02:55:14 +00:00
|
|
|
DEBUG_MSG("Size of SubPacket %d\n", sizeof(SubPacket));
|
2020-06-17 23:04:37 +00:00
|
|
|
DEBUG_MSG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */
|
2020-10-10 01:57:57 +00:00
|
|
|
|
|
|
|
fromRadioQueue.setReader(this);
|
2020-06-17 02:55:14 +00:00
|
|
|
}
|
2020-04-17 16:48:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* do idle processing
|
|
|
|
* Mostly looking in our incoming rxPacket queue and calling handleReceived.
|
|
|
|
*/
|
2020-10-10 01:57:57 +00:00
|
|
|
int32_t Router::runOnce()
|
2020-04-17 16:48:54 +00:00
|
|
|
{
|
|
|
|
MeshPacket *mp;
|
|
|
|
while ((mp = fromRadioQueue.dequeuePtr(0)) != NULL) {
|
2021-03-28 04:16:37 +00:00
|
|
|
// printPacket("handle fromRadioQ", mp);
|
2020-05-23 16:24:22 +00:00
|
|
|
perhapsHandleReceived(mp);
|
2020-04-17 16:48:54 +00:00
|
|
|
}
|
2020-10-09 06:16:51 +00:00
|
|
|
|
2021-03-28 04:16:37 +00:00
|
|
|
// DEBUG_MSG("sleeping forever!\n");
|
2020-10-10 01:57:57 +00:00
|
|
|
return INT32_MAX; // Wait a long time - until we get woken for the message queue
|
2020-04-17 16:48:54 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 01:24:00 +00:00
|
|
|
/**
|
|
|
|
* RadioInterface calls this to queue up packets that have been received from the radio. The router is now responsible for
|
|
|
|
* freeing the packet
|
|
|
|
*/
|
|
|
|
void Router::enqueueReceivedMessage(MeshPacket *p)
|
|
|
|
{
|
|
|
|
if (fromRadioQueue.enqueue(p, 0)) { // NOWAIT - fixme, if queue is full, delete older messages
|
|
|
|
|
|
|
|
// Nasty hack because our threading is primitive. interfaces shouldn't need to know about routers FIXME
|
|
|
|
setReceivedMessage();
|
|
|
|
} else {
|
|
|
|
printPacket("BUG! fromRadioQueue is full! Discarding!", p);
|
|
|
|
packetPool.release(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-19 18:56:17 +00:00
|
|
|
/// Generate a unique packet id
|
|
|
|
// FIXME, move this someplace better
|
|
|
|
PacketId generatePacketId()
|
|
|
|
{
|
|
|
|
static uint32_t i; // Note: trying to keep this in noinit didn't help for working across reboots
|
|
|
|
static bool didInit = false;
|
|
|
|
|
2020-06-03 20:46:31 +00:00
|
|
|
assert(sizeof(PacketId) == 4 || sizeof(PacketId) == 1); // only supported values
|
|
|
|
uint32_t numPacketId = sizeof(PacketId) == 1 ? UINT8_MAX : UINT32_MAX; // 0 is consider invalid
|
2020-06-03 20:15:45 +00:00
|
|
|
|
2020-05-19 18:56:17 +00:00
|
|
|
if (!didInit) {
|
|
|
|
didInit = true;
|
2020-06-06 20:16:36 +00:00
|
|
|
|
|
|
|
// pick a random initial sequence number at boot (to prevent repeated reboots always starting at 0)
|
|
|
|
// Note: we mask the high order bit to ensure that we never pass a 'negative' number to random
|
|
|
|
i = random(numPacketId & 0x7fffffff);
|
|
|
|
DEBUG_MSG("Initial packet id %u, numPacketId %u\n", i, numPacketId);
|
2020-05-19 18:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
2020-06-03 20:46:31 +00:00
|
|
|
PacketId id = (i % numPacketId) + 1; // return number between 1 and numPacketId (ie - never zero)
|
2020-06-03 20:15:45 +00:00
|
|
|
return id;
|
2020-05-19 18:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MeshPacket *Router::allocForSending()
|
|
|
|
{
|
|
|
|
MeshPacket *p = packetPool.allocZeroed();
|
|
|
|
|
2021-02-10 08:18:41 +00:00
|
|
|
p->which_payloadVariant = MeshPacket_decoded_tag; // Assume payload is decoded at start.
|
2020-05-19 18:56:17 +00:00
|
|
|
p->from = nodeDB.getNodeNum();
|
|
|
|
p->to = NODENUM_BROADCAST;
|
2021-12-18 21:21:12 +00:00
|
|
|
if (radioConfig.preferences.hop_limit && radioConfig.preferences.hop_limit <= HOP_MAX) {
|
|
|
|
p->hop_limit = (radioConfig.preferences.hop_limit >= HOP_MAX) ? HOP_MAX : radioConfig.preferences.hop_limit;
|
|
|
|
} else {
|
|
|
|
p->hop_limit = HOP_RELIABLE;
|
|
|
|
}
|
2020-05-19 18:56:17 +00:00
|
|
|
p->id = generatePacketId();
|
2020-12-13 08:11:38 +00:00
|
|
|
p->rx_time =
|
|
|
|
getValidTime(RTCQualityFromNet); // Just in case we process the packet locally - make sure it has a valid timestamp
|
2020-05-19 18:56:17 +00:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2021-02-07 02:26:11 +00:00
|
|
|
/**
|
|
|
|
* Send an ack or a nak packet back towards whoever sent idFrom
|
|
|
|
*/
|
2021-03-12 06:10:36 +00:00
|
|
|
void Router::sendAckNak(Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex)
|
2021-02-07 02:26:11 +00:00
|
|
|
{
|
2022-02-27 10:21:02 +00:00
|
|
|
routingModule->sendAckNak(err, to, idFrom, chIndex);
|
2021-02-07 02:26:11 +00:00
|
|
|
}
|
|
|
|
|
2021-02-22 04:57:26 +00:00
|
|
|
void Router::abortSendAndNak(Routing_Error err, MeshPacket *p)
|
|
|
|
{
|
|
|
|
DEBUG_MSG("Error=%d, returning NAK and dropping packet.\n", err);
|
2021-03-12 06:10:36 +00:00
|
|
|
sendAckNak(Routing_Error_NO_INTERFACE, getFrom(p), p->id, p->channel);
|
2021-02-22 04:57:26 +00:00
|
|
|
packetPool.release(p);
|
|
|
|
}
|
2021-02-11 09:39:53 +00:00
|
|
|
|
2021-03-24 05:25:10 +00:00
|
|
|
void Router::setReceivedMessage()
|
|
|
|
{
|
2021-03-28 04:16:37 +00:00
|
|
|
// DEBUG_MSG("set interval to ASAP\n");
|
2021-03-06 03:13:33 +00:00
|
|
|
setInterval(0); // Run ASAP, so we can figure out our correct sleep time
|
2021-03-28 04:16:37 +00:00
|
|
|
runASAP = true;
|
2021-03-06 03:13:33 +00:00
|
|
|
}
|
|
|
|
|
2021-10-27 13:16:51 +00:00
|
|
|
ErrorCode Router::sendLocal(MeshPacket *p, RxSource src)
|
2020-05-21 23:34:16 +00:00
|
|
|
{
|
2020-12-13 08:11:38 +00:00
|
|
|
// No need to deliver externally if the destination is the local node
|
2020-05-21 23:34:16 +00:00
|
|
|
if (p->to == nodeDB.getNodeNum()) {
|
2021-04-05 01:24:00 +00:00
|
|
|
printPacket("Enqueued local", p);
|
|
|
|
enqueueReceivedMessage(p);
|
2020-05-21 23:34:16 +00:00
|
|
|
return ERRNO_OK;
|
2021-02-07 02:26:11 +00:00
|
|
|
} else if (!iface) {
|
|
|
|
// We must be sending to remote nodes also, fail if no interface found
|
2021-02-22 04:57:26 +00:00
|
|
|
abortSendAndNak(Routing_Error_NO_INTERFACE, p);
|
2020-12-13 08:11:38 +00:00
|
|
|
|
2021-02-07 02:26:11 +00:00
|
|
|
return ERRNO_NO_INTERFACES;
|
|
|
|
} else {
|
|
|
|
// If we are sending a broadcast, we also treat it as if we just received it ourself
|
|
|
|
// this allows local apps (and PCs) to see broadcasts sourced locally
|
|
|
|
if (p->to == NODENUM_BROADCAST) {
|
2021-10-27 13:16:51 +00:00
|
|
|
handleReceived(p, src);
|
2021-02-07 02:26:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return send(p);
|
|
|
|
}
|
2020-05-21 23:34:16 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 05:25:10 +00:00
|
|
|
void printBytes(const char *label, const uint8_t *p, size_t numbytes)
|
|
|
|
{
|
2021-03-06 06:21:20 +00:00
|
|
|
DEBUG_MSG("%s: ", label);
|
2021-03-24 05:25:10 +00:00
|
|
|
for (size_t i = 0; i < numbytes; i++)
|
2021-03-06 06:21:20 +00:00
|
|
|
DEBUG_MSG("%02x ", p[i]);
|
|
|
|
DEBUG_MSG("\n");
|
|
|
|
}
|
|
|
|
|
2020-04-17 16:48:54 +00:00
|
|
|
/**
|
|
|
|
* Send a packet on a suitable interface. This routine will
|
|
|
|
* later free() the packet to pool. This routine is not allowed to stall.
|
2020-05-10 00:51:20 +00:00
|
|
|
* If the txmit queue is full it might return an error.
|
2020-04-17 16:48:54 +00:00
|
|
|
*/
|
|
|
|
ErrorCode Router::send(MeshPacket *p)
|
|
|
|
{
|
2020-05-21 23:34:16 +00:00
|
|
|
assert(p->to != nodeDB.getNodeNum()); // should have already been handled by sendLocal
|
|
|
|
|
2021-02-17 05:06:23 +00:00
|
|
|
// PacketId nakId = p->decoded.which_ackVariant == SubPacket_fail_id_tag ? p->decoded.ackVariant.fail_id : 0;
|
2021-02-22 04:57:26 +00:00
|
|
|
// assert(!nakId); // I don't think we ever send 0hop naks over the wire (other than to the phone), test that assumption with
|
|
|
|
// assert
|
2020-05-23 22:48:23 +00:00
|
|
|
|
2020-05-21 23:34:16 +00:00
|
|
|
// Never set the want_ack flag on broadcast packets sent over the air.
|
|
|
|
if (p->to == NODENUM_BROADCAST)
|
|
|
|
p->want_ack = false;
|
|
|
|
|
2021-03-05 02:19:27 +00:00
|
|
|
// Up until this point we might have been using 0 for the from address (if it started with the phone), but when we send over
|
|
|
|
// the lora we need to make sure we have replaced it with our local address
|
|
|
|
p->from = getFrom(p);
|
|
|
|
|
2020-05-21 23:34:16 +00:00
|
|
|
// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)
|
|
|
|
|
2021-02-10 08:18:41 +00:00
|
|
|
assert(p->which_payloadVariant == MeshPacket_encrypted_tag ||
|
|
|
|
p->which_payloadVariant == MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now
|
2020-05-21 23:34:16 +00:00
|
|
|
|
2021-04-04 01:20:37 +00:00
|
|
|
// If the packet is not yet encrypted, do so now
|
2021-02-10 08:18:41 +00:00
|
|
|
if (p->which_payloadVariant == MeshPacket_decoded_tag) {
|
2021-04-04 01:20:37 +00:00
|
|
|
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
2021-02-22 04:57:26 +00:00
|
|
|
|
2022-01-28 17:03:48 +00:00
|
|
|
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
2022-04-12 03:09:48 +00:00
|
|
|
// check if we should send decrypted packets to mqtt
|
2022-01-28 17:03:48 +00:00
|
|
|
|
2022-04-12 03:09:48 +00:00
|
|
|
// truth table:
|
2022-01-28 17:03:48 +00:00
|
|
|
/* mqtt_server mqtt_encryption_enabled should_encrypt
|
|
|
|
* not set 0 1
|
|
|
|
* not set 1 1
|
|
|
|
* set 0 0
|
|
|
|
* set 1 1
|
2022-04-12 03:09:48 +00:00
|
|
|
*
|
2022-01-28 17:40:17 +00:00
|
|
|
* => so we only decrypt mqtt if they have a custom mqtt server AND mqtt_encryption_enabled is FALSE
|
2022-04-12 03:09:48 +00:00
|
|
|
*/
|
2022-01-28 17:03:48 +00:00
|
|
|
|
|
|
|
bool shouldActuallyEncrypt = true;
|
|
|
|
if (*radioConfig.preferences.mqtt_server && !radioConfig.preferences.mqtt_encryption_enabled) {
|
|
|
|
shouldActuallyEncrypt = false;
|
|
|
|
}
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-01-28 17:03:48 +00:00
|
|
|
DEBUG_MSG("Should encrypt MQTT?: %d\n", shouldActuallyEncrypt);
|
|
|
|
|
2022-04-12 03:09:48 +00:00
|
|
|
// the packet is currently in a decrypted state. send it now if they want decrypted packets
|
2022-01-28 17:03:48 +00:00
|
|
|
if (mqtt && !shouldActuallyEncrypt)
|
|
|
|
mqtt->onSend(*p, chIndex);
|
|
|
|
#endif
|
|
|
|
|
2021-04-05 01:24:00 +00:00
|
|
|
auto encodeResult = perhapsEncode(p);
|
|
|
|
if (encodeResult != Routing_Error_NONE) {
|
|
|
|
abortSendAndNak(encodeResult, p);
|
|
|
|
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
|
|
|
}
|
2021-04-04 01:20:37 +00:00
|
|
|
|
2021-04-05 05:00:56 +00:00
|
|
|
#if defined(HAS_WIFI) || defined(PORTDUINO)
|
2022-04-12 03:09:48 +00:00
|
|
|
// the packet is now encrypted.
|
|
|
|
// check if we should send encrypted packets to mqtt
|
2022-01-28 17:03:48 +00:00
|
|
|
if (mqtt && shouldActuallyEncrypt)
|
2021-04-04 01:20:37 +00:00
|
|
|
mqtt->onSend(*p, chIndex);
|
2021-04-05 05:00:56 +00:00
|
|
|
#endif
|
2020-05-21 23:34:16 +00:00
|
|
|
}
|
|
|
|
|
2021-02-07 02:26:11 +00:00
|
|
|
assert(iface); // This should have been detected already in sendLocal (or we just received a packet from outside)
|
|
|
|
return iface->send(p);
|
2020-04-17 16:48:54 +00:00
|
|
|
}
|
|
|
|
|
2021-02-11 09:39:53 +00:00
|
|
|
/** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */
|
2021-02-22 04:57:26 +00:00
|
|
|
bool Router::cancelSending(NodeNum from, PacketId id)
|
|
|
|
{
|
2021-02-11 09:39:53 +00:00
|
|
|
return iface ? iface->cancelSending(from, id) : false;
|
|
|
|
}
|
|
|
|
|
2020-05-19 00:57:58 +00:00
|
|
|
/**
|
|
|
|
* 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)
|
|
|
|
*/
|
2021-02-21 04:59:47 +00:00
|
|
|
void Router::sniffReceived(const MeshPacket *p, const Routing *c)
|
2020-05-19 00:57:58 +00:00
|
|
|
{
|
2020-06-14 22:30:42 +00:00
|
|
|
DEBUG_MSG("FIXME-update-db Sniffing packet\n");
|
|
|
|
// FIXME, update nodedb here for any packet that passes through us
|
2020-05-19 00:57:58 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 01:24:00 +00:00
|
|
|
bool perhapsDecode(MeshPacket *p)
|
2020-04-17 16:48:54 +00:00
|
|
|
{
|
2021-02-10 08:18:41 +00:00
|
|
|
if (p->which_payloadVariant == MeshPacket_decoded_tag)
|
2020-05-19 18:56:17 +00:00
|
|
|
return true; // If packet was already decoded just return
|
2020-04-17 16:48:54 +00:00
|
|
|
|
2022-04-12 03:09:48 +00:00
|
|
|
// assert(p->which_payloadVariant == MeshPacket_encrypted_tag);
|
2020-05-10 00:51:20 +00:00
|
|
|
|
2021-02-23 02:45:03 +00:00
|
|
|
// Try to find a channel that works with this hash
|
|
|
|
for (ChannelIndex chIndex = 0; chIndex < channels.getNumChannels(); chIndex++) {
|
|
|
|
// Try to use this hash/channel pair
|
|
|
|
if (channels.decryptForHash(chIndex, p->channel)) {
|
|
|
|
// Try to decrypt the packet if we can
|
|
|
|
static uint8_t bytes[MAX_RHPACKETLEN];
|
2021-03-06 06:21:20 +00:00
|
|
|
size_t rawSize = p->encrypted.size;
|
|
|
|
assert(rawSize <= sizeof(bytes));
|
2021-02-23 02:45:03 +00:00
|
|
|
memcpy(bytes, p->encrypted.bytes,
|
2021-03-06 06:21:20 +00:00
|
|
|
rawSize); // we have to copy into a scratch buffer, because these bytes are a union with the decoded protobuf
|
|
|
|
crypto->decrypt(p->from, p->id, rawSize, bytes);
|
|
|
|
|
2021-03-24 05:25:10 +00:00
|
|
|
// printBytes("plaintext", bytes, p->encrypted.size);
|
2021-02-23 02:45:03 +00:00
|
|
|
|
|
|
|
// Take those raw bytes and convert them back into a well structured protobuf we can understand
|
2021-03-24 05:25:10 +00:00
|
|
|
memset(&p->decoded, 0, sizeof(p->decoded));
|
2021-03-06 06:21:20 +00:00
|
|
|
if (!pb_decode_from_bytes(bytes, rawSize, Data_fields, &p->decoded)) {
|
|
|
|
DEBUG_MSG("Invalid protobufs in received mesh packet (bad psk?)!\n");
|
2021-03-24 05:25:10 +00:00
|
|
|
} else if (p->decoded.portnum == PortNum_UNKNOWN_APP) {
|
2021-03-06 06:21:20 +00:00
|
|
|
DEBUG_MSG("Invalid portnum (bad psk?)!\n");
|
2021-03-24 05:25:10 +00:00
|
|
|
} else {
|
2021-02-23 02:45:03 +00:00
|
|
|
// parsing was successful
|
2021-03-06 06:21:20 +00:00
|
|
|
p->which_payloadVariant = MeshPacket_decoded_tag; // change type to decoded
|
2021-03-24 05:25:10 +00:00
|
|
|
p->channel = chIndex; // change to store the index instead of the hash
|
2022-04-14 02:23:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Decompress if needed. jm
|
|
|
|
if (p->decoded.which_payloadVariant == Data_payload_compressed_tag) {
|
|
|
|
// Decompress the file
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-06 06:21:20 +00:00
|
|
|
printPacket("decoded message", p);
|
2021-02-23 02:45:03 +00:00
|
|
|
return true;
|
|
|
|
}
|
2021-02-22 04:57:26 +00:00
|
|
|
}
|
2020-05-19 18:56:17 +00:00
|
|
|
}
|
2021-02-23 02:45:03 +00:00
|
|
|
|
|
|
|
DEBUG_MSG("No suitable channel found for decoding, hash was 0x%x!\n", p->channel);
|
|
|
|
return false;
|
2020-05-19 18:56:17 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 01:24:00 +00:00
|
|
|
/** Return 0 for success or a Routing_Errror code for failure
|
|
|
|
*/
|
|
|
|
Routing_Error perhapsEncode(MeshPacket *p)
|
|
|
|
{
|
|
|
|
// If the packet is not yet encrypted, do so now
|
|
|
|
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), Data_fields, &p->decoded);
|
|
|
|
|
2022-04-14 02:23:35 +00:00
|
|
|
// Only allow encryption on the text message app.
|
|
|
|
// TODO: Allow modules to opt into compression.
|
2022-04-12 05:12:04 +00:00
|
|
|
if (p->decoded.portnum == PortNum_TEXT_MESSAGE_APP) {
|
|
|
|
|
|
|
|
char original_payload[Constants_DATA_PAYLOAD_LEN];
|
|
|
|
memcpy(original_payload, p->decoded.payload.bytes, p->decoded.payload.size);
|
|
|
|
|
2022-04-14 02:23:35 +00:00
|
|
|
char compressed_out[Constants_DATA_PAYLOAD_LEN] = {0};
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-04-19 00:00:36 +00:00
|
|
|
int compressed_len;
|
|
|
|
// compressed_len = unishox2_compress_simple(original_payload, p->decoded.payload.size, compressed_out);
|
2022-04-12 05:12:04 +00:00
|
|
|
|
|
|
|
Serial.print("Original length - ");
|
|
|
|
Serial.println(p->decoded.payload.size);
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-04-12 05:12:04 +00:00
|
|
|
Serial.print("Compressed length - ");
|
2022-04-12 03:09:48 +00:00
|
|
|
Serial.println(compressed_len);
|
2022-04-14 02:23:35 +00:00
|
|
|
// Serial.println(compressed_out);
|
|
|
|
|
|
|
|
// If the compressed length is greater than or equal to the original size, don't use the compressed form
|
|
|
|
if (compressed_len >= p->decoded.payload.size) {
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-04-14 02:23:35 +00:00
|
|
|
DEBUG_MSG("Not compressing message. Not enough benefit from doing so.\n");
|
|
|
|
// Set the uncompressed payload varient anyway. Shouldn't hurt?
|
|
|
|
p->decoded.which_payloadVariant = Data_payload_tag;
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-04-14 02:23:35 +00:00
|
|
|
// Otherwise we use the compressor
|
|
|
|
} else {
|
|
|
|
DEBUG_MSG("Compressing message.\n");
|
|
|
|
// Copy the compressed data into the meshpacket
|
2022-04-14 04:59:25 +00:00
|
|
|
//p->decoded.payload_compressed.size = compressed_len;
|
|
|
|
//memcpy(p->decoded.payload_compressed.bytes, compressed_out, compressed_len);
|
2022-04-14 02:23:35 +00:00
|
|
|
|
2022-04-14 04:59:25 +00:00
|
|
|
//p->decoded.which_payloadVariant = Data_payload_compressed_tag;
|
2022-04-14 02:23:35 +00:00
|
|
|
}
|
2022-04-12 03:09:48 +00:00
|
|
|
|
2022-04-19 00:00:36 +00:00
|
|
|
if (0) {
|
2022-04-14 02:23:35 +00:00
|
|
|
char decompressed_out[Constants_DATA_PAYLOAD_LEN] = {};
|
|
|
|
int decompressed_len;
|
|
|
|
|
2022-04-19 00:00:36 +00:00
|
|
|
// decompressed_len = unishox2_decompress_simple(compressed_out, compressed_len, decompressed_out);
|
2022-04-14 02:23:35 +00:00
|
|
|
|
|
|
|
Serial.print("Decompressed length - ");
|
|
|
|
Serial.println(decompressed_len);
|
|
|
|
Serial.println(decompressed_out);
|
|
|
|
}
|
2022-04-12 03:09:48 +00:00
|
|
|
}
|
|
|
|
|
2021-04-05 01:24:00 +00:00
|
|
|
if (numbytes > MAX_RHPACKETLEN)
|
|
|
|
return Routing_Error_TOO_LARGE;
|
|
|
|
|
|
|
|
// printBytes("plaintext", bytes, numbytes);
|
|
|
|
|
|
|
|
ChannelIndex chIndex = p->channel; // keep as a local because we are about to change it
|
|
|
|
auto hash = channels.setActiveByIndex(chIndex);
|
|
|
|
if (hash < 0)
|
|
|
|
// No suitable channel could be found for sending
|
|
|
|
return Routing_Error_NO_CHANNEL;
|
|
|
|
|
|
|
|
// Now that we are encrypting the packet channel should be the hash (no longer the index)
|
|
|
|
p->channel = hash;
|
|
|
|
crypto->encrypt(getFrom(p), p->id, numbytes, bytes);
|
|
|
|
|
|
|
|
// Copy back into the packet and set the variant type
|
|
|
|
memcpy(p->encrypted.bytes, bytes, numbytes);
|
|
|
|
p->encrypted.size = numbytes;
|
|
|
|
p->which_payloadVariant = MeshPacket_encrypted_tag;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Routing_Error_NONE;
|
|
|
|
}
|
|
|
|
|
2020-05-19 18:56:17 +00:00
|
|
|
NodeNum Router::getNodeNum()
|
|
|
|
{
|
|
|
|
return nodeDB.getNodeNum();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-10-09 13:54:42 +00:00
|
|
|
void Router::handleReceived(MeshPacket *p, RxSource src)
|
2020-05-19 18:56:17 +00:00
|
|
|
{
|
|
|
|
// Also, we should set the time from the ISR and it should have msec level resolution
|
2020-10-09 02:01:13 +00:00
|
|
|
p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
|
2020-05-19 18:56:17 +00:00
|
|
|
|
|
|
|
// Take those raw bytes and convert them back into a well structured protobuf we can understand
|
2021-03-24 05:25:10 +00:00
|
|
|
bool decoded = perhapsDecode(p);
|
2021-02-23 06:35:34 +00:00
|
|
|
if (decoded) {
|
2020-05-19 18:56:17 +00:00
|
|
|
// parsing was successful, queue for our recipient
|
2021-10-09 13:54:42 +00:00
|
|
|
if (src == RX_SRC_LOCAL)
|
2021-10-28 11:33:32 +00:00
|
|
|
printPacket("handleReceived(LOCAL)", p);
|
|
|
|
else if (src == RX_SRC_USER)
|
|
|
|
printPacket("handleReceived(USER)", p);
|
2021-10-09 13:54:42 +00:00
|
|
|
else
|
2021-10-28 11:33:32 +00:00
|
|
|
printPacket("handleReceived(REMOTE)", p);
|
2021-03-24 05:25:10 +00:00
|
|
|
} else {
|
2021-04-05 00:44:47 +00:00
|
|
|
printPacket("packet decoding failed (no PSK?)", p);
|
2020-05-10 00:51:20 +00:00
|
|
|
}
|
2021-04-05 00:44:47 +00:00
|
|
|
|
2022-02-27 08:29:05 +00:00
|
|
|
// call modules here
|
2022-03-09 08:01:43 +00:00
|
|
|
MeshModule::callPlugins(*p, src);
|
2020-05-23 16:24:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Router::perhapsHandleReceived(MeshPacket *p)
|
|
|
|
{
|
2020-05-23 17:01:36 +00:00
|
|
|
assert(radioConfig.has_preferences);
|
2021-03-24 05:25:10 +00:00
|
|
|
bool ignore = is_in_repeated(radioConfig.preferences.ignore_incoming, p->from);
|
2020-05-23 17:01:36 +00:00
|
|
|
|
2020-05-24 19:58:36 +00:00
|
|
|
if (ignore)
|
2020-05-23 17:01:36 +00:00
|
|
|
DEBUG_MSG("Ignoring incoming message, 0x%x is in our ignore list\n", p->from);
|
2020-05-25 02:23:50 +00:00
|
|
|
else if (ignore |= shouldFilterReceived(p)) {
|
2021-03-24 05:25:10 +00:00
|
|
|
DEBUG_MSG("Incoming message was filtered 0x%x\n", p->from);
|
2020-05-25 02:23:50 +00:00
|
|
|
}
|
2020-05-23 17:01:36 +00:00
|
|
|
|
|
|
|
// Note: we avoid calling shouldFilterReceived if we are supposed to ignore certain nodes - because some overrides might
|
|
|
|
// cache/learn of the existence of nodes (i.e. FloodRouter) that they should not
|
2020-05-24 19:58:36 +00:00
|
|
|
if (!ignore)
|
2020-05-23 16:24:22 +00:00
|
|
|
handleReceived(p);
|
2020-05-10 00:51:20 +00:00
|
|
|
|
2020-04-17 16:48:54 +00:00
|
|
|
packetPool.release(p);
|
2022-01-28 17:40:17 +00:00
|
|
|
}
|