Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/mesh/Channels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,4 +459,15 @@ bool Channels::setDefaultPresetCryptoForHash(ChannelHash channelHash)
int16_t Channels::setActiveByIndex(ChannelIndex channelIndex)
{
return setCrypto(channelIndex);
}

int8_t Channels::getIndexByHash(ChannelHash channelHash)
{
// Iterate through all channels to find the one with matching hash
for (ChannelIndex i = 0; i < getNumChannels(); i++) {
if (getHash(i) == channelHash) {
return i;
}
}
return -1; // Hash not found
}
6 changes: 3 additions & 3 deletions src/mesh/Channels.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,16 @@ class Channels

bool setDefaultPresetCryptoForHash(ChannelHash channelHash);

/** Return the channel index for the specified channel hash, or -1 for not found */
int8_t getIndexByHash(ChannelHash channelHash);

private:
/** Given a channel index, change to use the crypto key specified by that index
*
* @eturn the (0 to 255) hash for that channel - if no suitable channel could be found, return -1
*/
int16_t setCrypto(ChannelIndex chIndex);

/** Return the channel index for the specified channel hash, or -1 for not found */
int8_t getIndexByHash(ChannelHash channelHash);

/** Given a channel number, return the (0 to 255) hash for that channel
* If no suitable channel could be found, return -1
*
Expand Down
77 changes: 74 additions & 3 deletions src/mesh/Router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,55 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
mqtt->onSend(*p, *p_decoded, chIndex);
}
#endif
#if HAS_UDP_MULTICAST
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
// We must have at least one channel setup for with uplink_enabled
bool uplinkEnabled = false;
for (int i = 0; i <= 7; i++) {
if (channels.getByIndex(i).settings.uplink_enabled)
uplinkEnabled = true;
}
if (uplinkEnabled) {
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p), chIndex);
}
}
#endif
packetPool.release(p_decoded);
}

#if HAS_UDP_MULTICAST
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p));
// For packets that are already encrypted, we need to determine the channel from packet info
else if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST &&
isFromUs(p)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isFromUs(p) is here still.

// Check if any channel has uplink enabled (for PKI support)
bool uplinkEnabled = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of this bool we can use an int8_t to store the channel index where uplink is enabled, and -1 if none was found such that we can eliminate the same loop hereafter.

for (int i = 0; i <= 7; i++) {
if (channels.getByIndex(i).settings.uplink_enabled) {
uplinkEnabled = true;
break;
}
}
if (uplinkEnabled) {
ChannelIndex chIndex = 0; // Default to primary channel

// For PKI encrypted packets, use default channel if at least one channel has uplink
if (p->pki_encrypted) {
for (int i = 0; i <= 7; i++) {
if (channels.getByIndex(i).settings.uplink_enabled) {
chIndex = i;
break;
}
}
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p), chIndex);
} else {
// For regular channel PSK encrypted packets, try to find the channel by hash
int8_t foundIndex = channels.getIndexByHash(p->channel);
if (foundIndex >= 0) {
chIndex = foundIndex;
udpHandler->onSend(const_cast<meshtastic_MeshPacket *>(p), chIndex);
}
}
}
}
#endif

Expand Down Expand Up @@ -480,6 +522,35 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
}
}

#if HAS_UDP_MULTICAST
// Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed
if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) {
if (channels.setDefaultPresetCryptoForHash(p->channel)) {
memcpy(bytes, p->encrypted.bytes, rawSize);
crypto->decrypt(p->from, p->id, rawSize, bytes);

meshtastic_Data decodedtmp;
memset(&decodedtmp, 0, sizeof(decodedtmp));
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) &&
decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) {
p->decoded = decodedtmp;
p->which_payload_variant = meshtastic_MeshPacket_decoded_tag;
// Map to our local default channel index (name+PSK default), not necessarily primary
ChannelIndex defaultIndex = channels.getPrimaryIndex();
for (ChannelIndex i = 0; i < channels.getNumChannels(); ++i) {
if (channels.isDefaultChannel(i)) {
defaultIndex = i;
break;
}
}
chIndex = defaultIndex;
decrypted = true;
} else {
LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel);
}
}
}
#endif
if (decrypted) {
// parsing was successful
p->channel = chIndex; // change to store the index instead of the hash
Expand Down
23 changes: 22 additions & 1 deletion src/mesh/udp/UdpMulticastHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#if HAS_UDP_MULTICAST
#include "configuration.h"
#include "main.h"
#include "mesh/Channels.h"
#include "mesh/Router.h"

#if HAS_ETHERNET && defined(ARCH_NRF52)
Expand Down Expand Up @@ -53,6 +54,20 @@ class UdpMulticastHandler final
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetLength);
bool isPacketDecoded = pb_decode_from_bytes(packet.data(), packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router && mp.which_payload_variant == meshtastic_MeshPacket_encrypted_tag) {
// Convert channel hash to index for downlink check
int8_t chIndex = channels.getIndexByHash(mp.channel);
if (chIndex < 0) {
LOG_DEBUG("UDP received packet with unknown channel hash 0x%x", mp.channel);
return;
}

// Check if downlink is enabled for this channel
auto &ch = channels.getByIndex(chIndex);
if (!ch.settings.downlink_enabled) {
LOG_DEBUG("UDP downlink disabled for channel %d", chIndex);
return;
}

mp.transport_mechanism = meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP;
mp.pki_encrypted = false;
mp.public_key.size = 0;
Expand All @@ -65,11 +80,17 @@ class UdpMulticastHandler final
}
}

bool onSend(const meshtastic_MeshPacket *mp)
bool onSend(const meshtastic_MeshPacket *mp, ChannelIndex chIndex)
{
if (!mp || !udp) {
return false;
}
// Check if uplink is enabled for this specific channel
auto &ch = channels.getByIndex(chIndex);
if (!ch.settings.uplink_enabled) {
LOG_DEBUG("UDP uplink disabled for channel %d", chIndex);
return false;
}
#if defined(ARCH_NRF52)
if (!isEthernetAvailable()) {
return false;
Expand Down