First iteration that seems to work

This commit is contained in:
liquidraver committed 2026-02-20 12:43:13 +01:00
commit 8d1823d0b6
205 files changed
+41989

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore MainBoard interface - matches MeshCore.h
*/
#pragma once
#include <stdint.h>
#include <math.h>
namespace mesh {
#define BD_STARTUP_NORMAL 0
#define BD_STARTUP_RX_PACKET 1
class MainBoard {
public:
virtual uint16_t getBattMilliVolts() = 0;
virtual float getMCUTemperature() { return NAN; }
virtual bool setAdcMultiplier(float multiplier) { (void)multiplier; return false; }
virtual float getAdcMultiplier() const { return 0.0f; }
virtual const char *getManufacturerName() const = 0;
virtual void onBeforeTransmit() {}
virtual void onAfterTransmit() {}
virtual void reboot() = 0;
virtual void powerOff() {}
virtual void sleep(uint32_t secs) { (void)secs; }
virtual uint32_t getGpio() { return 0; }
virtual void setGpio(uint32_t values) { (void)values; }
virtual uint8_t getStartupReason() const = 0;
virtual bool startOTAUpdate(const char *id, char reply[]) { (void)id; (void)reply; return false; }
virtual bool isExternalPowered() { return false; }
virtual uint16_t getBootVoltage() { return 0; }
virtual uint32_t getResetReason() const { return 0; }
virtual const char *getResetReasonString(uint32_t reason) { (void)reason; return "Not available"; }
virtual uint8_t getShutdownReason() const { return 0; }
virtual const char *getShutdownReasonString(uint8_t reason) { (void)reason; return "Not available"; }
};
} /* namespace mesh */
+17
View File
@@ -0,0 +1,17 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore clock interfaces - matches Dispatcher.h / MeshCore.h
*/
#pragma once
#include <stdint.h>
namespace mesh {
class MillisecondClock {
public:
virtual unsigned long getMillis() = 0;
};
} /* namespace mesh */
+141
View File
@@ -0,0 +1,141 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Dispatcher - packet queue and radio scheduling
*/
#pragma once
#include <mesh/MeshCore.h>
#include <mesh/Identity.h>
#include <mesh/Packet.h>
#include <mesh/Utils.h>
#include <mesh/Radio.h>
#include <mesh/Clock.h>
#include <string.h>
namespace mesh {
/* EU ETSI EN 300 220 duty cycle tracker.
* Fixed 1-hour window, tracks cumulative TX airtime in ms.
* duty_pct=0 disables all tracking (zero overhead). */
struct DutyCycleTracker {
uint32_t window_start;
uint32_t window_airtime_ms;
uint8_t duty_pct; /* 0=disabled, 1-99=percentage */
void init(uint8_t pct) {
window_start = 0;
window_airtime_ms = 0;
duty_pct = pct;
}
void recordTx(uint32_t duration_ms, uint32_t now) {
if (duty_pct == 0) return;
if (now - window_start > 3600000UL) {
window_start = now;
window_airtime_ms = 0;
}
window_airtime_ms += duration_ms;
}
bool isExceeded(uint32_t now) const {
if (duty_pct == 0) return false;
if (now - window_start > 3600000UL) return false; /* window expired */
uint32_t budget_ms = (3600000UL / 100) * (uint32_t)duty_pct;
return window_airtime_ms >= budget_ms;
}
uint32_t budgetMs() const {
if (duty_pct == 0) return 0;
return (3600000UL / 100) * (uint32_t)duty_pct;
}
};
class PacketManager {
public:
virtual Packet *allocNew() = 0;
virtual void free(Packet *packet) = 0;
virtual void queueOutbound(Packet *packet, uint8_t priority, uint32_t scheduled_for) = 0;
virtual Packet *getNextOutbound(uint32_t now) = 0;
virtual int getOutboundCount(uint32_t now) const = 0;
virtual int getFreeCount() const = 0;
virtual Packet *getOutboundByIdx(int i) = 0;
virtual Packet *removeOutboundByIdx(int i) = 0;
virtual void queueInbound(Packet *packet, uint32_t scheduled_for) = 0;
virtual Packet *getNextInbound(uint32_t now) = 0;
};
typedef uint32_t DispatcherAction;
#define ACTION_RELEASE (0)
#define ACTION_MANUAL_HOLD (1)
#define ACTION_RETRANSMIT(pri) (((uint32_t)1 + (pri))<<24)
#define ACTION_RETRANSMIT_DELAYED(pri, _delay) ((((uint32_t)1 + (pri))<<24) | (_delay))
#define ERR_EVENT_FULL (1 << 0)
#define ERR_EVENT_CAD_TIMEOUT (1 << 1)
#define ERR_EVENT_STARTRX_TIMEOUT (1 << 2)
class Dispatcher {
Packet *outbound;
uint32_t outbound_expiry, outbound_start, total_air_time, rx_air_time;
uint32_t next_tx_time;
uint32_t cad_busy_start;
DutyCycleTracker _duty_cycle;
uint32_t radio_nonrx_start;
uint32_t next_floor_calib_time, next_agc_reset_time;
bool prev_isrecv_mode;
uint32_t n_sent_flood, n_sent_direct;
uint32_t n_recv_flood, n_recv_direct;
void processRecvPacket(Packet *pkt);
protected:
Radio *_radio;
MillisecondClock *_ms;
PacketManager *_mgr;
uint16_t _err_flags;
Dispatcher(Radio &radio, MillisecondClock &ms, PacketManager &mgr);
virtual DispatcherAction onRecvPacket(Packet *pkt) = 0;
virtual void logRxRaw(float snr, float rssi, const uint8_t raw[], int len) { (void)snr; (void)rssi; (void)raw; (void)len; }
virtual void logRx(Packet *packet, int len, float score) { (void)packet; (void)len; (void)score; }
virtual void logTx(Packet *packet, int len) { (void)packet; (void)len; }
virtual void logTxFail(Packet *packet, int len) { (void)packet; (void)len; }
virtual const char *getLogDateTime() { return ""; }
virtual uint8_t getDutyCyclePercent() const;
static bool isAdminPacket(const Packet *pkt);
virtual int calcRxDelay(float score, uint32_t air_time) const;
virtual uint32_t getCADFailRetryDelay() const;
virtual uint32_t getCADFailMaxDuration() const;
virtual int getInterferenceThreshold() const { return 0; }
virtual int getAGCResetInterval() const { return 0; }
public:
void begin();
void loop();
Packet *obtainNewPacket();
void releasePacket(Packet *packet);
void sendPacket(Packet *packet, uint8_t priority, uint32_t delay_millis = 0);
uint32_t getTotalAirTime() const { return total_air_time; }
uint32_t getReceiveAirTime() const { return rx_air_time; }
uint32_t getNumSentFlood() const { return n_sent_flood; }
uint32_t getNumSentDirect() const { return n_sent_direct; }
uint32_t getNumRecvFlood() const { return n_recv_flood; }
uint32_t getNumRecvDirect() const { return n_recv_direct; }
uint16_t getErrFlags() const { return _err_flags; }
void resetStats() {
n_sent_flood = n_sent_direct = 0;
n_recv_flood = n_recv_direct = 0;
_err_flags = 0;
}
bool millisHasNowPassed(uint32_t timestamp) const;
uint32_t futureMillis(int millis_from_now) const;
private:
void checkRecv();
void checkSend();
};
} /* namespace mesh */
+57
View File
@@ -0,0 +1,57 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Identity - Ed25519 public identity
*/
#pragma once
#include <mesh/Utils.h>
#include <mesh/MeshCore.h>
#include <mesh/RNG.h>
#include <stddef.h>
#include <string.h>
namespace mesh {
class Identity {
public:
uint8_t pub_key[PUB_KEY_SIZE];
Identity();
Identity(const char *pub_hex);
Identity(const uint8_t *_pub) { memcpy(pub_key, _pub, PUB_KEY_SIZE); }
int copyHashTo(uint8_t *dest) const {
memcpy(dest, pub_key, PATH_HASH_SIZE);
return PATH_HASH_SIZE;
}
bool isHashMatch(const uint8_t *hash) const {
return memcmp(hash, pub_key, PATH_HASH_SIZE) == 0;
}
bool isHashMatch(const uint8_t *hash, uint8_t len) const {
return memcmp(hash, pub_key, len) == 0;
}
bool verify(const uint8_t *sig, const uint8_t *message, int msg_len) const;
bool matches(const Identity &other) const { return memcmp(pub_key, other.pub_key, PUB_KEY_SIZE) == 0; }
bool matches(const uint8_t *other_pubkey) const { return memcmp(pub_key, other_pubkey, PUB_KEY_SIZE) == 0; }
bool readFrom(const uint8_t *src, size_t len);
bool writeTo(uint8_t *dest, size_t max_len) const;
};
class LocalIdentity : public Identity {
uint8_t prv_key[PRV_KEY_SIZE];
public:
LocalIdentity();
LocalIdentity(const char *prv_hex, const char *pub_hex);
LocalIdentity(RNG *rng);
void sign(uint8_t *sig, const uint8_t *message, int msg_len) const;
void calcSharedSecret(uint8_t *secret, const Identity &other) const { calcSharedSecret(secret, other.pub_key); }
void calcSharedSecret(uint8_t *secret, const uint8_t *other_pub_key) const;
static bool validatePrivateKey(const uint8_t prv[64]);
bool readFrom(const uint8_t *src, size_t len);
size_t writeTo(uint8_t *dest, size_t max_len) const;
};
} /* namespace mesh */
+21
View File
@@ -0,0 +1,21 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore LoRa default parameters
*/
#pragma once
#include <stdint.h>
namespace mesh {
struct LoRaConfig {
static constexpr uint32_t FREQ_HZ = 869618000;
static constexpr uint16_t BANDWIDTH = 62; /* BW_62_KHZ */
static constexpr uint8_t SPREADING_FACTOR = 8;
static constexpr uint8_t CODING_RATE = 8; /* CR_4_8 */
static constexpr uint16_t PREAMBLE_LEN = 16;
static constexpr int8_t TX_POWER_DBM = 22;
};
} /* namespace mesh */
+86
View File
@@ -0,0 +1,86 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Mesh - routing protocol layer
*/
#pragma once
#include <mesh/Dispatcher.h>
#include <mesh/RTC.h>
namespace mesh {
struct GroupChannel {
uint8_t hash[PATH_HASH_SIZE];
uint8_t secret[PUB_KEY_SIZE];
};
class MeshTables {
public:
virtual bool hasSeen(const Packet *packet) = 0;
virtual void clear(const Packet *packet) = 0;
};
class Mesh : public Dispatcher {
RNG *_rng;
RTCClock *_rtc;
MeshTables *_tables;
void removeSelfFromPath(Packet *packet);
void routeDirectRecvAcks(Packet *packet, uint32_t delay_millis);
DispatcherAction forwardMultipartDirect(Packet *pkt);
protected:
DispatcherAction onRecvPacket(Packet *pkt) override;
virtual uint32_t getCADFailRetryDelay() const override;
virtual DispatcherAction routeRecvPacket(Packet *packet);
virtual bool filterRecvFloodPacket(Packet *packet) { return false; }
virtual bool allowPacketForward(const Packet *packet);
virtual uint32_t getRetransmitDelay(const Packet *packet);
virtual uint32_t getDirectRetransmitDelay(const Packet *packet) { return 0; }
virtual uint8_t getExtraAckTransmitCount() const { return 0; }
virtual int searchPeersByHash(const uint8_t *hash) { (void)hash; return 0; }
virtual void getPeerSharedSecret(uint8_t *dest_secret, int peer_idx) { (void)dest_secret; (void)peer_idx; }
virtual void onPeerDataRecv(Packet *packet, uint8_t type, int sender_idx, const uint8_t *secret, uint8_t *data, size_t len) { (void)packet; (void)type; (void)sender_idx; (void)secret; (void)data; (void)len; }
virtual void onTraceRecv(Packet *packet, uint32_t tag, uint32_t auth_code, uint8_t flags, const uint8_t *path_snrs, const uint8_t *path_hashes, uint8_t path_len) { (void)packet; (void)tag; (void)auth_code; (void)flags; (void)path_snrs; (void)path_hashes; (void)path_len; }
virtual bool onPeerPathRecv(Packet *packet, int sender_idx, const uint8_t *secret, uint8_t *path, uint8_t path_len, uint8_t extra_type, uint8_t *extra, uint8_t extra_len) { (void)packet; (void)sender_idx; (void)secret; (void)path; (void)path_len; (void)extra_type; (void)extra; (void)extra_len; return false; }
virtual void onAdvertRecv(Packet *packet, const Identity &id, uint32_t timestamp, const uint8_t *app_data, size_t app_data_len) { (void)packet; (void)id; (void)timestamp; (void)app_data; (void)app_data_len; }
virtual void onAnonDataRecv(Packet *packet, const uint8_t *secret, const Identity &sender, uint8_t *data, size_t len) { (void)packet; (void)secret; (void)sender; (void)data; (void)len; }
virtual void onPathRecv(Packet *packet, Identity &sender, uint8_t *path, uint8_t path_len, uint8_t extra_type, uint8_t *extra, uint8_t extra_len) { (void)packet; (void)sender; (void)path; (void)path_len; (void)extra_type; (void)extra; (void)extra_len; }
virtual void onControlDataRecv(Packet *packet) { (void)packet; }
virtual void onRawDataRecv(Packet *packet) { (void)packet; }
virtual int searchChannelsByHash(const uint8_t *hash, GroupChannel channels[], int max_matches) { (void)hash; (void)channels; (void)max_matches; return 0; }
virtual void onGroupDataRecv(Packet *packet, uint8_t type, const GroupChannel &channel, uint8_t *data, size_t len) { (void)packet; (void)type; (void)channel; (void)data; (void)len; }
virtual void onAckRecv(Packet *packet, uint32_t ack_crc) { (void)packet; (void)ack_crc; }
public:
Mesh(Radio &radio, MillisecondClock &ms, RNG &rng, RTCClock &rtc, PacketManager &mgr, MeshTables &tables);
void begin();
void loop();
LocalIdentity self_id;
RNG *getRNG() const { return _rng; }
RTCClock *getRTCClock() const { return _rtc; }
MeshTables *getTables() const { return _tables; }
Packet *createAdvert(const LocalIdentity &id, const uint8_t *app_data = nullptr, size_t app_data_len = 0);
Packet *createAck(uint32_t ack_crc);
Packet *createMultiAck(uint32_t ack_crc, uint8_t remaining);
Packet *createControlData(const uint8_t *data, size_t len);
Packet *createDatagram(uint8_t type, const Identity &dest, const uint8_t *secret, const uint8_t *data, size_t len);
Packet *createAnonDatagram(uint8_t type, const LocalIdentity &sender, const Identity &dest, const uint8_t *secret, const uint8_t *data, size_t data_len);
Packet *createGroupDatagram(uint8_t type, const GroupChannel &channel, const uint8_t *data, size_t data_len);
Packet *createPathReturn(const Identity &dest, const uint8_t *secret, const uint8_t *path, uint8_t path_len, uint8_t extra_type, const uint8_t *extra, size_t extra_len);
Packet *createPathReturn(const uint8_t *dest_hash, const uint8_t *secret, const uint8_t *path, uint8_t path_len, uint8_t extra_type, const uint8_t *extra, size_t extra_len);
Packet *createRawData(const uint8_t *data, size_t len);
Packet *createTrace(uint32_t tag, uint32_t auth_code, uint8_t flags = 0);
void sendFlood(Packet *packet, uint32_t delay_millis = 0);
void sendFlood(Packet *packet, uint16_t *transport_codes, uint32_t delay_millis = 0);
void sendDirect(Packet *packet, const uint8_t *path, uint8_t path_len, uint32_t delay_millis = 0);
void sendZeroHop(Packet *packet, uint32_t delay_millis = 0);
void sendZeroHop(Packet *packet, uint16_t *transport_codes, uint32_t delay_millis = 0);
};
} /* namespace mesh */
+34
View File
@@ -0,0 +1,34 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore constants and base types (Zephyr port)
*/
#pragma once
#include <stdint.h>
#include <math.h>
#define MAX_HASH_SIZE 8
#define PUB_KEY_SIZE 32
#define PRV_KEY_SIZE 64
#define SEED_SIZE 32
#define SIGNATURE_SIZE 64
#define MAX_ADVERT_DATA_SIZE 32
#define CIPHER_KEY_SIZE 16
#define CIPHER_BLOCK_SIZE 16
#define CIPHER_MAC_SIZE 2
#define PATH_HASH_SIZE 1
#define MAX_PACKET_PAYLOAD 184
#define MAX_PATH_SIZE 64
#define MAX_TRANS_UNIT 255
#define MESH_DEBUG_PRINT(...)
#define MESH_DEBUG_PRINTLN(...)
namespace mesh {
#define BD_STARTUP_NORMAL 0
#define BD_STARTUP_RX_PACKET 1
} /* namespace mesh */
+70
View File
@@ -0,0 +1,70 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Packet - fundamental transmission unit
*/
#pragma once
#include <mesh/MeshCore.h>
#include <stdint.h>
#include <string.h>
namespace mesh {
#define PH_ROUTE_MASK 0x03
#define PH_TYPE_SHIFT 2
#define PH_TYPE_MASK 0x0F
#define PH_VER_SHIFT 6
#define PH_VER_MASK 0x03
#define ROUTE_TYPE_TRANSPORT_FLOOD 0x00
#define ROUTE_TYPE_FLOOD 0x01
#define ROUTE_TYPE_DIRECT 0x02
#define ROUTE_TYPE_TRANSPORT_DIRECT 0x03
#define PAYLOAD_TYPE_REQ 0x00
#define PAYLOAD_TYPE_RESPONSE 0x01
#define PAYLOAD_TYPE_TXT_MSG 0x02
#define PAYLOAD_TYPE_ACK 0x03
#define PAYLOAD_TYPE_ADVERT 0x04
#define PAYLOAD_TYPE_GRP_TXT 0x05
#define PAYLOAD_TYPE_GRP_DATA 0x06
#define PAYLOAD_TYPE_ANON_REQ 0x07
#define PAYLOAD_TYPE_PATH 0x08
#define PAYLOAD_TYPE_TRACE 0x09
#define PAYLOAD_TYPE_MULTIPART 0x0A
#define PAYLOAD_TYPE_CONTROL 0x0B
#define PAYLOAD_TYPE_RAW_CUSTOM 0x0F
#define PAYLOAD_VER_1 0x00
#define PAYLOAD_VER_2 0x01
#define PAYLOAD_VER_3 0x02
#define PAYLOAD_VER_4 0x03
class Packet {
public:
Packet();
uint8_t header;
uint16_t payload_len, path_len;
uint16_t transport_codes[2];
uint8_t path[MAX_PATH_SIZE];
uint8_t payload[MAX_PACKET_PAYLOAD];
int8_t _snr;
void calculatePacketHash(uint8_t *dest_hash) const;
uint8_t getRouteType() const { return header & PH_ROUTE_MASK; }
bool isRouteFlood() const { return getRouteType() == ROUTE_TYPE_FLOOD || getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD; }
bool isRouteDirect() const { return getRouteType() == ROUTE_TYPE_DIRECT || getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT; }
bool hasTransportCodes() const { return getRouteType() == ROUTE_TYPE_TRANSPORT_FLOOD || getRouteType() == ROUTE_TYPE_TRANSPORT_DIRECT; }
uint8_t getPayloadType() const { return (header >> PH_TYPE_SHIFT) & PH_TYPE_MASK; }
uint8_t getPayloadVer() const { return (header >> PH_VER_SHIFT) & PH_VER_MASK; }
void markDoNotRetransmit() { header = 0xFF; }
bool isMarkedDoNotRetransmit() const { return header == 0xFF; }
float getSNR() const { return ((float)_snr) / 4.0f; }
int getRawLength() const;
uint8_t writeTo(uint8_t dest[]) const;
bool readFrom(const uint8_t src[], uint8_t len);
};
} /* namespace mesh */
+20
View File
@@ -0,0 +1,20 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore RNG interface - matches Utils.h
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
namespace mesh {
class RNG {
public:
virtual void random(uint8_t *dest, size_t sz) = 0;
uint32_t nextInt(uint32_t _min, uint32_t _max);
};
} /* namespace mesh */
+32
View File
@@ -0,0 +1,32 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore RTC interface - matches MeshCore.h
*/
#pragma once
#include <stdint.h>
namespace mesh {
class RTCClock {
uint32_t last_unique;
protected:
RTCClock() : last_unique(0) {}
public:
virtual uint32_t getCurrentTime() = 0;
virtual void setCurrentTime(uint32_t time) = 0;
virtual void tick() {}
uint32_t getCurrentTimeUnique() {
uint32_t t = getCurrentTime();
if (t <= last_unique) {
return ++last_unique;
}
return last_unique = t;
}
};
} /* namespace mesh */
+38
View File
@@ -0,0 +1,38 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Radio interface - matches Dispatcher.h
*/
#pragma once
#include <stdint.h>
namespace mesh {
class Radio {
public:
virtual void begin() {}
virtual int recvRaw(uint8_t *bytes, int sz) = 0;
virtual uint32_t getEstAirtimeFor(int len_bytes) = 0;
virtual float packetScore(float snr, int packet_len) = 0;
virtual bool startSendRaw(const uint8_t *bytes, int len) = 0;
virtual bool isSendComplete() = 0;
virtual void onSendFinished() = 0;
virtual int getNoiseFloor() const { return 0; }
virtual void triggerNoiseFloorCalibrate(int threshold) { (void)threshold; }
virtual void resetAGC() {}
virtual bool isInRecvMode() const = 0;
virtual bool isReceiving() { return false; }
virtual float getLastRSSI() const { return 0; }
virtual float getLastSNR() const { return 0; }
/* Packet statistics */
virtual uint32_t getPacketsRecv() const { return 0; }
virtual uint32_t getPacketsSent() const { return 0; }
virtual uint32_t getPacketsRecvErrors() const { return 0; }
};
} /* namespace mesh */
+32
View File
@@ -0,0 +1,32 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore - Common radio includes for LoRa mesh roles
*
* Shared by companion, repeater, and any future role that uses the
* LoRa radio. Selects LR1110 or SX126x based on Kconfig/devicetree.
*/
#ifndef ZEPHCORE_RADIO_INCLUDES_H
#define ZEPHCORE_RADIO_INCLUDES_H
#if IS_ENABLED(CONFIG_ZEPHCORE_RADIO_LR1110) || DT_NODE_HAS_STATUS(DT_ALIAS(lora0), okay)
#include <zephyr/drivers/lora.h>
#include <mesh/LoRaConfig.h>
#include <adapters/board/ZephyrBoard.h>
#include <adapters/clock/ZephyrMillisecondClock.h>
#include <adapters/rng/ZephyrRNG.h>
#include <mesh/SimpleMeshTables.h>
#include <mesh/StaticPoolPacketManager.h>
#if IS_ENABLED(CONFIG_ZEPHCORE_RADIO_LR1110)
#include <adapters/radio/LR1110Radio.h>
#else
#include <adapters/radio/SX126xRadio.h>
#endif
#define ZEPHCORE_LORA 1
#endif /* CONFIG_ZEPHCORE_RADIO_LR1110 || lora0 */
#endif /* ZEPHCORE_RADIO_INCLUDES_H */
+77
View File
@@ -0,0 +1,77 @@
/*
* SPDX-License-Identifier: Apache-2.0
* SimpleMeshTables - hash-based deduplication
*/
#pragma once
#include <mesh/Mesh.h>
#include <string.h>
namespace mesh {
#define MAX_PACKET_HASHES 64
#define MAX_PACKET_ACKS 32
class SimpleMeshTables : public MeshTables {
uint8_t _hashes[MAX_PACKET_HASHES * MAX_HASH_SIZE];
int _next_idx;
uint32_t _acks[MAX_PACKET_ACKS];
int _next_ack_idx;
public:
SimpleMeshTables() {
memset(_hashes, 0, sizeof(_hashes));
_next_idx = 0;
memset(_acks, 0, sizeof(_acks));
_next_ack_idx = 0;
}
bool hasSeen(const Packet *packet) override {
if (packet->getPayloadType() == PAYLOAD_TYPE_ACK) {
uint32_t ack;
memcpy(&ack, packet->payload, 4);
for (int i = 0; i < MAX_PACKET_ACKS; i++) {
if (ack == _acks[i]) return true;
}
_acks[_next_ack_idx] = ack;
_next_ack_idx = (_next_ack_idx + 1) % MAX_PACKET_ACKS;
return false;
}
uint8_t hash[MAX_HASH_SIZE];
packet->calculatePacketHash(hash);
const uint8_t *sp = _hashes;
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) return true;
}
memcpy(&_hashes[_next_idx * MAX_HASH_SIZE], hash, MAX_HASH_SIZE);
_next_idx = (_next_idx + 1) % MAX_PACKET_HASHES;
return false;
}
void clear(const Packet *packet) override {
if (packet->getPayloadType() == PAYLOAD_TYPE_ACK) {
uint32_t ack;
memcpy(&ack, packet->payload, 4);
for (int i = 0; i < MAX_PACKET_ACKS; i++) {
if (ack == _acks[i]) {
_acks[i] = 0;
break;
}
}
} else {
uint8_t hash[MAX_HASH_SIZE];
packet->calculatePacketHash(hash);
uint8_t *sp = _hashes;
for (int i = 0; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
if (memcmp(hash, sp, MAX_HASH_SIZE) == 0) {
memset(sp, 0, MAX_HASH_SIZE);
break;
}
}
}
}
};
} /* namespace mesh */
@@ -0,0 +1,26 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Static pool PacketManager
*/
#pragma once
#include <mesh/Dispatcher.h>
namespace mesh {
class StaticPoolPacketManager : public PacketManager {
public:
Packet *allocNew() override;
void free(Packet *packet) override;
void queueOutbound(Packet *packet, uint8_t priority, uint32_t scheduled_for) override;
Packet *getNextOutbound(uint32_t now) override;
int getOutboundCount(uint32_t now) const override;
int getFreeCount() const override;
Packet *getOutboundByIdx(int i) override;
Packet *removeOutboundByIdx(int i) override;
void queueInbound(Packet *packet, uint32_t scheduled_for) override;
Packet *getNextInbound(uint32_t now) override;
};
} /* namespace mesh */
+28
View File
@@ -0,0 +1,28 @@
/*
* SPDX-License-Identifier: Apache-2.0
* ZephCore Utils - crypto and helpers (Zephyr port)
*/
#pragma once
#include <mesh/MeshCore.h>
#include <string.h>
#include <stddef.h>
namespace mesh {
class Utils {
public:
static void sha256(uint8_t *hash, size_t hash_len, const uint8_t *msg, int msg_len);
static void sha256(uint8_t *hash, size_t hash_len, const uint8_t *frag1, int frag1_len, const uint8_t *frag2, int frag2_len);
static int encrypt(const uint8_t *shared_secret, uint8_t *dest, const uint8_t *src, int src_len);
static int decrypt(const uint8_t *shared_secret, uint8_t *dest, const uint8_t *src, int src_len);
static int encryptThenMAC(const uint8_t *shared_secret, uint8_t *dest, const uint8_t *src, int src_len);
static int MACThenDecrypt(const uint8_t *shared_secret, uint8_t *dest, const uint8_t *src, int src_len);
static void toHex(char *dest, const uint8_t *src, size_t len);
static bool fromHex(uint8_t *dest, int dest_size, const char *src_hex);
static bool isHexChar(char c);
static int parseTextParts(char *text, const char *parts[], int max_num, char separator = ',');
};
} /* namespace mesh */