mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-16 07:42:37 +00:00
Compare commits
35 Commits
renovate/m
...
sfpp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
472c65178a | ||
|
|
82100f5f9d | ||
|
|
5c667c9bbd | ||
|
|
256df0169c | ||
|
|
c45ffc9989 | ||
|
|
d144e8a69d | ||
|
|
6282c809e6 | ||
|
|
e09d63a61b | ||
|
|
7e601ffc81 | ||
|
|
ba71941fdc | ||
|
|
d5839ad348 | ||
|
|
6f10f6939a | ||
|
|
e44ab7f7b8 | ||
|
|
d2661974f6 | ||
|
|
a184885023 | ||
|
|
ab2db9d0c9 | ||
|
|
e31cecda7d | ||
|
|
e5f35317e1 | ||
|
|
9580af30bc | ||
|
|
b4dd918a69 | ||
|
|
3319688962 | ||
|
|
f362382cb5 | ||
|
|
7373fce2e1 | ||
|
|
f10d2fb8c2 | ||
|
|
4552efce81 | ||
|
|
ecdcbe5c09 | ||
|
|
4dd43c7753 | ||
|
|
471da2e632 | ||
|
|
03961161af | ||
|
|
dfe74653f2 | ||
|
|
6b2bd09dd8 | ||
|
|
4fd7960371 | ||
|
|
5f0e86a27e | ||
|
|
9ce1a7ff79 | ||
|
|
bf32f17f28 |
8
.github/workflows/build_firmware.yml
vendored
8
.github/workflows/build_firmware.yml
vendored
@@ -56,16 +56,18 @@ jobs:
|
||||
ota_firmware_source: ${{ steps.ota_dir.outputs.src || '' }}
|
||||
ota_firmware_target: ${{ steps.ota_dir.outputs.tgt || '' }}
|
||||
|
||||
- name: Echo manifest from release/firmware-*.mt.json to job summary
|
||||
if: ${{ always() }}
|
||||
- name: Job summary
|
||||
env:
|
||||
PIO_ENV: ${{ inputs.pio_env }}
|
||||
run: |
|
||||
echo "## Manifest: \`$PIO_ENV\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "## $PIO_ENV" >> $GITHUB_STEP_SUMMARY
|
||||
echo "<details><summary><strong>Manifest</strong></summary>" >> $GITHUB_STEP_SUMMARY
|
||||
echo '' >> $GITHUB_STEP_SUMMARY
|
||||
echo '```json' >> $GITHUB_STEP_SUMMARY
|
||||
cat release/firmware-*.mt.json >> $GITHUB_STEP_SUMMARY
|
||||
echo '' >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v5
|
||||
|
||||
@@ -428,10 +428,17 @@ void setup()
|
||||
#endif
|
||||
|
||||
#if ARCH_PORTDUINO
|
||||
RTCQuality ourQuality = RTCQualityDevice;
|
||||
|
||||
std::string timeCommandResult = exec("timedatectl status | grep synchronized | grep yes -c");
|
||||
if (timeCommandResult[0] == '1') {
|
||||
ourQuality = RTCQualityNTP;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = time(NULL);
|
||||
tv.tv_usec = 0;
|
||||
perhapsSetRTC(RTCQualityDevice, &tv);
|
||||
perhapsSetRTC(ourQuality, &tv);
|
||||
#endif
|
||||
|
||||
powerMonInit();
|
||||
|
||||
@@ -96,6 +96,8 @@ class Channels
|
||||
|
||||
bool setDefaultPresetCryptoForHash(ChannelHash channelHash);
|
||||
|
||||
int16_t getHash(ChannelIndex i) { return hashes[i]; }
|
||||
|
||||
private:
|
||||
/** Given a channel index, change to use the crypto key specified by that index
|
||||
*
|
||||
@@ -113,8 +115,6 @@ class Channels
|
||||
*/
|
||||
int16_t generateHash(ChannelIndex channelNum);
|
||||
|
||||
int16_t getHash(ChannelIndex i) { return hashes[i]; }
|
||||
|
||||
/**
|
||||
* Validate a channel, fixing any errors as needed
|
||||
*/
|
||||
|
||||
@@ -288,6 +288,8 @@ void RadioLibInterface::onNotify(uint32_t notification)
|
||||
// Send any outgoing packets we have ready as fast as possible to keep the time between channel scan and
|
||||
// actual transmission as short as possible
|
||||
txp = txQueue.dequeue();
|
||||
LOG_WARN("Outgoing packet");
|
||||
printPacket("Starting send", txp);
|
||||
assert(txp);
|
||||
startSend(txp);
|
||||
LOG_DEBUG("%d packets remain in the TX queue", txQueue.getMaxLen() - txQueue.getFree());
|
||||
|
||||
@@ -688,7 +688,7 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
|
||||
// Store a copy of encrypted packet for MQTT
|
||||
DEBUG_HEAP_BEFORE;
|
||||
meshtastic_MeshPacket *p_encrypted = packetPool.allocCopy(*p);
|
||||
p_encrypted = packetPool.allocCopy(*p);
|
||||
DEBUG_HEAP_AFTER("Router::handleReceived", p_encrypted);
|
||||
|
||||
// Take those raw bytes and convert them back into a well structured protobuf we can understand
|
||||
|
||||
@@ -91,6 +91,9 @@ class Router : protected concurrency::OSThread, protected PacketHistory
|
||||
before us */
|
||||
uint32_t rxDupe = 0, txRelayCanceled = 0;
|
||||
|
||||
// pointer to the encrypted packet
|
||||
meshtastic_MeshPacket *p_encrypted;
|
||||
|
||||
protected:
|
||||
friend class RoutingModule;
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ PB_BIND(meshtastic_Data, meshtastic_Data, 2)
|
||||
PB_BIND(meshtastic_KeyVerification, meshtastic_KeyVerification, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_StoreForwardPlusPlus, meshtastic_StoreForwardPlusPlus, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Waypoint, meshtastic_Waypoint, AUTO)
|
||||
|
||||
|
||||
@@ -121,6 +124,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -478,6 +478,17 @@ typedef enum _meshtastic_Routing_Error {
|
||||
meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38
|
||||
} meshtastic_Routing_Error;
|
||||
|
||||
/* enum message type? */
|
||||
typedef enum _meshtastic_StoreForwardPlusPlus_SFPP_message_type {
|
||||
/* message hash without chain hash means that no, it is not on the chain */
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE = 0,
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_CHAIN_QUERY = 1,
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_REQUEST = 3,
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE = 4,
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_FIRSTHALF = 5,
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF = 6
|
||||
} meshtastic_StoreForwardPlusPlus_SFPP_message_type;
|
||||
|
||||
/* The priority of this message for sending.
|
||||
Higher priorities are sent first (when managing the transmit queue).
|
||||
This field is never sent over the air, it is only used internally inside of a local device node.
|
||||
@@ -782,6 +793,24 @@ typedef struct _meshtastic_KeyVerification {
|
||||
meshtastic_KeyVerification_hash2_t hash2;
|
||||
} meshtastic_KeyVerification;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_message_hash_t;
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_commit_hash_t;
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_StoreForwardPlusPlus_root_hash_t;
|
||||
typedef PB_BYTES_ARRAY_T(240) meshtastic_StoreForwardPlusPlus_message_t;
|
||||
/* The actual over-the-mesh message doing store and forward++ */
|
||||
typedef struct _meshtastic_StoreForwardPlusPlus { /* */
|
||||
meshtastic_StoreForwardPlusPlus_SFPP_message_type sfpp_message_type;
|
||||
meshtastic_StoreForwardPlusPlus_message_hash_t message_hash;
|
||||
meshtastic_StoreForwardPlusPlus_commit_hash_t commit_hash;
|
||||
meshtastic_StoreForwardPlusPlus_root_hash_t root_hash;
|
||||
/* encapsulated message to share (may be split in half) */
|
||||
meshtastic_StoreForwardPlusPlus_message_t message;
|
||||
uint32_t encapsulated_id;
|
||||
uint32_t encapsulated_to;
|
||||
uint32_t encapsulated_from;
|
||||
uint32_t encapsulated_rxtime;
|
||||
} meshtastic_StoreForwardPlusPlus;
|
||||
|
||||
/* Waypoint message, used to share arbitrary locations across the mesh */
|
||||
typedef struct _meshtastic_Waypoint {
|
||||
/* Id of the waypoint */
|
||||
@@ -1310,6 +1339,10 @@ extern "C" {
|
||||
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED
|
||||
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1))
|
||||
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN meshtastic_StoreForwardPlusPlus_SFPP_message_type_CANON_ANNOUNCE
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_MAX meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF
|
||||
#define _meshtastic_StoreForwardPlusPlus_SFPP_message_type_ARRAYSIZE ((meshtastic_StoreForwardPlusPlus_SFPP_message_type)(meshtastic_StoreForwardPlusPlus_SFPP_message_type_LINK_PROVIDE_SECONDHALF+1))
|
||||
|
||||
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
|
||||
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX
|
||||
#define _meshtastic_MeshPacket_Priority_ARRAYSIZE ((meshtastic_MeshPacket_Priority)(meshtastic_MeshPacket_Priority_MAX+1))
|
||||
@@ -1338,6 +1371,8 @@ extern "C" {
|
||||
#define meshtastic_Data_portnum_ENUMTYPE meshtastic_PortNum
|
||||
|
||||
|
||||
#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_ENUMTYPE meshtastic_StoreForwardPlusPlus_SFPP_message_type
|
||||
|
||||
|
||||
|
||||
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
|
||||
@@ -1380,6 +1415,7 @@ extern "C" {
|
||||
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
|
||||
#define meshtastic_Data_init_default {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
|
||||
#define meshtastic_StoreForwardPlusPlus_init_default {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
|
||||
@@ -1411,6 +1447,7 @@ extern "C" {
|
||||
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
|
||||
#define meshtastic_Data_init_zero {_meshtastic_PortNum_MIN, {0, {0}}, 0, 0, 0, 0, 0, 0, false, 0}
|
||||
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
|
||||
#define meshtastic_StoreForwardPlusPlus_init_zero {_meshtastic_StoreForwardPlusPlus_SFPP_message_type_MIN, {0, {0}}, {0, {0}}, {0, {0}}, {0, {0}}, 0, 0, 0, 0}
|
||||
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
|
||||
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
|
||||
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
|
||||
@@ -1489,6 +1526,15 @@ extern "C" {
|
||||
#define meshtastic_KeyVerification_nonce_tag 1
|
||||
#define meshtastic_KeyVerification_hash1_tag 2
|
||||
#define meshtastic_KeyVerification_hash2_tag 3
|
||||
#define meshtastic_StoreForwardPlusPlus_sfpp_message_type_tag 1
|
||||
#define meshtastic_StoreForwardPlusPlus_message_hash_tag 2
|
||||
#define meshtastic_StoreForwardPlusPlus_commit_hash_tag 3
|
||||
#define meshtastic_StoreForwardPlusPlus_root_hash_tag 4
|
||||
#define meshtastic_StoreForwardPlusPlus_message_tag 5
|
||||
#define meshtastic_StoreForwardPlusPlus_encapsulated_id_tag 6
|
||||
#define meshtastic_StoreForwardPlusPlus_encapsulated_to_tag 7
|
||||
#define meshtastic_StoreForwardPlusPlus_encapsulated_from_tag 8
|
||||
#define meshtastic_StoreForwardPlusPlus_encapsulated_rxtime_tag 9
|
||||
#define meshtastic_Waypoint_id_tag 1
|
||||
#define meshtastic_Waypoint_latitude_i_tag 2
|
||||
#define meshtastic_Waypoint_longitude_i_tag 3
|
||||
@@ -1705,6 +1751,19 @@ X(a, STATIC, SINGULAR, BYTES, hash2, 3)
|
||||
#define meshtastic_KeyVerification_CALLBACK NULL
|
||||
#define meshtastic_KeyVerification_DEFAULT NULL
|
||||
|
||||
#define meshtastic_StoreForwardPlusPlus_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, sfpp_message_type, 1) \
|
||||
X(a, STATIC, SINGULAR, BYTES, message_hash, 2) \
|
||||
X(a, STATIC, SINGULAR, BYTES, commit_hash, 3) \
|
||||
X(a, STATIC, SINGULAR, BYTES, root_hash, 4) \
|
||||
X(a, STATIC, SINGULAR, BYTES, message, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, encapsulated_id, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, encapsulated_to, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, encapsulated_from, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, encapsulated_rxtime, 9)
|
||||
#define meshtastic_StoreForwardPlusPlus_CALLBACK NULL
|
||||
#define meshtastic_StoreForwardPlusPlus_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Waypoint_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, id, 1) \
|
||||
X(a, STATIC, OPTIONAL, SFIXED32, latitude_i, 2) \
|
||||
@@ -1980,6 +2039,7 @@ extern const pb_msgdesc_t meshtastic_RouteDiscovery_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Routing_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Data_msg;
|
||||
extern const pb_msgdesc_t meshtastic_KeyVerification_msg;
|
||||
extern const pb_msgdesc_t meshtastic_StoreForwardPlusPlus_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Waypoint_msg;
|
||||
extern const pb_msgdesc_t meshtastic_MqttClientProxyMessage_msg;
|
||||
extern const pb_msgdesc_t meshtastic_MeshPacket_msg;
|
||||
@@ -2013,6 +2073,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_Routing_fields &meshtastic_Routing_msg
|
||||
#define meshtastic_Data_fields &meshtastic_Data_msg
|
||||
#define meshtastic_KeyVerification_fields &meshtastic_KeyVerification_msg
|
||||
#define meshtastic_StoreForwardPlusPlus_fields &meshtastic_StoreForwardPlusPlus_msg
|
||||
#define meshtastic_Waypoint_fields &meshtastic_Waypoint_msg
|
||||
#define meshtastic_MqttClientProxyMessage_fields &meshtastic_MqttClientProxyMessage_msg
|
||||
#define meshtastic_MeshPacket_fields &meshtastic_MeshPacket_msg
|
||||
@@ -2069,6 +2130,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 256
|
||||
#define meshtastic_Routing_size 259
|
||||
#define meshtastic_StoreForwardPlusPlus_size 371
|
||||
#define meshtastic_ToRadio_size 504
|
||||
#define meshtastic_User_size 115
|
||||
#define meshtastic_Waypoint_size 165
|
||||
|
||||
@@ -86,6 +86,9 @@ typedef enum _meshtastic_PortNum {
|
||||
/* Paxcounter lib included in the firmware
|
||||
ENCODING: protobuf */
|
||||
meshtastic_PortNum_PAXCOUNTER_APP = 34,
|
||||
/* Store and Forward++ module included in the firmware
|
||||
ENCODING: protobuf */
|
||||
meshtastic_PortNum_STORE_FORWARD_PLUSPLUS_APP = 35,
|
||||
/* Provides a hardware serial interface to send and receive from the Meshtastic network.
|
||||
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
|
||||
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#if ARCH_PORTDUINO
|
||||
#include "input/LinuxInputImpl.h"
|
||||
#include "input/SeesawRotary.h"
|
||||
#include "modules/Native/StoreForwardPlusPlus.h"
|
||||
#include "modules/Telemetry/HostMetrics.h"
|
||||
#if !MESHTASTIC_EXCLUDE_STOREFORWARD
|
||||
#include "modules/StoreForwardModule.h"
|
||||
@@ -243,6 +244,7 @@ void setupModules()
|
||||
#endif
|
||||
#if ARCH_PORTDUINO
|
||||
new HostMetricsModule();
|
||||
new StoreForwardPlusPlusModule();
|
||||
#endif
|
||||
#if HAS_TELEMETRY
|
||||
new DeviceTelemetryModule();
|
||||
|
||||
1001
src/modules/Native/StoreForwardPlusPlus.cpp
Normal file
1001
src/modules/Native/StoreForwardPlusPlus.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
src/modules/Native/StoreForwardPlusPlus.h
Normal file
111
src/modules/Native/StoreForwardPlusPlus.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
#include "Channels.h"
|
||||
#include "ProtobufModule.h"
|
||||
#include "Router.h"
|
||||
#include "SinglePortModule.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
/**
|
||||
* A simple example module that just replies with "Message received" to any message it receives.
|
||||
*/
|
||||
class StoreForwardPlusPlusModule : public ProtobufModule<meshtastic_StoreForwardPlusPlus>, private concurrency::OSThread
|
||||
{
|
||||
struct link_object {
|
||||
uint32_t to;
|
||||
uint32_t from;
|
||||
uint32_t id;
|
||||
uint32_t rx_time;
|
||||
ChannelHash channel_hash;
|
||||
uint8_t encrypted_bytes[256] = {0};
|
||||
size_t encrypted_len;
|
||||
uint8_t message_hash[32] = {0};
|
||||
uint8_t root_hash[32] = {0};
|
||||
uint8_t commit_hash[32] = {0};
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
*/
|
||||
StoreForwardPlusPlusModule();
|
||||
|
||||
/*
|
||||
-Override the wantPacket method.
|
||||
*/
|
||||
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||
{
|
||||
// if encrypted but not too FFFF
|
||||
// want
|
||||
switch (p->decoded.portnum) {
|
||||
case meshtastic_PortNum_TEXT_MESSAGE_APP:
|
||||
case 35:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
|
||||
it
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_StoreForwardPlusPlus *t) override;
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
sqlite3 *ppDb;
|
||||
sqlite3_stmt *chain_insert_stmt;
|
||||
sqlite3_stmt *scratch_insert_stmt;
|
||||
sqlite3_stmt *checkDup;
|
||||
sqlite3_stmt *checkScratch;
|
||||
sqlite3_stmt *removeScratch;
|
||||
sqlite3_stmt *updatePayloadStmt;
|
||||
sqlite3_stmt *getPayloadFromScratchStmt;
|
||||
sqlite3_stmt *fromScratchStmt;
|
||||
sqlite3_stmt *fromScratchByHashStmt;
|
||||
|
||||
// returns wasfound
|
||||
bool getRootFromChannelHash(ChannelHash, uint8_t *);
|
||||
|
||||
ChannelHash getChannelHashFromRoot(uint8_t *_root_hash);
|
||||
|
||||
bool getNextHash(uint8_t *_root_hash, uint8_t *, uint8_t *);
|
||||
|
||||
// returns isnew
|
||||
bool getOrAddRootFromChannelHash(ChannelHash, uint8_t *);
|
||||
|
||||
bool addRootToMappings(ChannelHash, uint8_t *);
|
||||
|
||||
// return indicates message found
|
||||
uint32_t getChainEnd(ChannelHash, uint8_t *, uint8_t *);
|
||||
|
||||
void requestNextMessage(uint8_t *, uint8_t *);
|
||||
|
||||
bool broadcastLink(uint8_t *, uint8_t *);
|
||||
|
||||
bool sendFromScratch(uint8_t);
|
||||
|
||||
bool addToChain(uint32_t, uint32_t, uint32_t, ChannelHash, uint8_t *, size_t, uint8_t *, uint8_t *, uint8_t *, uint32_t,
|
||||
char *, size_t);
|
||||
bool addToScratch(uint32_t, uint32_t, uint32_t, ChannelHash, uint8_t *, size_t, uint8_t *, uint8_t *, uint32_t, char *,
|
||||
size_t);
|
||||
void canonAnnounce(uint8_t *, uint8_t *, uint8_t *, uint32_t);
|
||||
|
||||
bool isInDB(uint8_t *);
|
||||
|
||||
bool isInScratch(uint8_t *);
|
||||
|
||||
link_object getFromScratch(uint8_t *, size_t);
|
||||
|
||||
void removeFromScratch(uint8_t *);
|
||||
|
||||
void updatePayload(uint8_t *, const char *, size_t);
|
||||
|
||||
enum chain_types {
|
||||
channel_chain = 0,
|
||||
};
|
||||
};
|
||||
235
src/modules/Native/StoreForwardPlusPlusSat.cpp
Normal file
235
src/modules/Native/StoreForwardPlusPlusSat.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// create second module for satellites?
|
||||
|
||||
// The central node will generate a 256 or 128 bit value as its seed. This is the value other nodes subscribe to, and serves as
|
||||
// the root of the chain
|
||||
|
||||
//
|
||||
|
||||
// Basic design:
|
||||
// This module watches a channel for text messages.
|
||||
// each message gets sha256 summed, and then appended to a git-style blockchain. Probably need a counter, too
|
||||
// then the message, metadata, hash, and git hash information are saved. sqlite?
|
||||
|
||||
// nodes/sub-controllers can subscribe to a database
|
||||
|
||||
// A node can DM the controller, querying if a single message is on the chain, or asking for the last message hash
|
||||
|
||||
// if the message is not on the chain, the node can resend the message
|
||||
|
||||
// if the node lacks messages, it can request them
|
||||
|
||||
// will need the concept of sub-controllers, that subscribe to the central controller, can help push updates
|
||||
|
||||
// catch-up messages only go out when the mesh is low use %
|
||||
|
||||
// Normal firmware will only attempt to sync the chain a few times, then just ask for the latest few messages. A phone app can try
|
||||
// harder
|
||||
|
||||
// host will periodically advertise its presence
|
||||
|
||||
// at least initially, there can only be one authoritative host
|
||||
|
||||
// first draft is just to save channel 0 in a git-style database
|
||||
|
||||
// message objects get a hash value
|
||||
// the message chain gets a commit hash
|
||||
//
|
||||
|
||||
#include "StoreForwardPlusPlusSat.h"
|
||||
#include "SHA256.h"
|
||||
#include "meshUtils.h"
|
||||
|
||||
StoreForwardPlusPlusSatModule::StoreForwardPlusPlusSatModule() : SinglePortModule("StoreForwardPlusPlus", (_meshtastic_PortNum)35)
|
||||
{
|
||||
LOG_WARN("StoreForwardPlusPlusSatModule init");
|
||||
int res = sqlite3_open("test.db", &ppDb);
|
||||
LOG_WARN("Result1 %u", res);
|
||||
char *err = nullptr;
|
||||
res = sqlite3_exec(ppDb, " \
|
||||
CREATE TABLE channel_messages( \
|
||||
destination INT NOT NULL, \
|
||||
sender INT NOT NULL, \
|
||||
packet_id INT NOT NULL, \
|
||||
want_ack BOOL NOT NULL, \
|
||||
channel_hash INT NOT NULL, \
|
||||
encrypted_bytes BLOB NOT NULL, \
|
||||
message_hash BLOB NOT NULL, \
|
||||
rx_time INT NOT NULL, \
|
||||
commit_hash BLOB NOT NULL, \
|
||||
payload TEXT, \
|
||||
PRIMARY KEY (message_hash) \
|
||||
);",
|
||||
NULL, NULL, &err);
|
||||
LOG_WARN("Result2 %u", res);
|
||||
if (err != nullptr)
|
||||
;
|
||||
LOG_ERROR("%s", err);
|
||||
sqlite3_free(err);
|
||||
|
||||
// create table DMs
|
||||
res = sqlite3_exec(ppDb, " \
|
||||
CREATE TABLE direct_messages( \
|
||||
destination INT NOT NULL, \
|
||||
sender INT NOT NULL, \
|
||||
packet_id INT NOT NULL, \
|
||||
want_ack BOOL NOT NULL, \
|
||||
channel_hash INT NOT NULL, \
|
||||
commit_hash BLOB NOT NULL, \
|
||||
encrypted_bytes BLOB NOT NULL, \
|
||||
message_hash BLOB NOT NULL, \
|
||||
payload TEXT, \
|
||||
rx_time INT NOT NULL, \
|
||||
PRIMARY KEY (message_hash) \
|
||||
);",
|
||||
NULL, NULL, &err);
|
||||
LOG_WARN("Result2 %u", res);
|
||||
if (err != nullptr)
|
||||
;
|
||||
LOG_ERROR("%s", err);
|
||||
sqlite3_free(err);
|
||||
|
||||
// create table mappings
|
||||
// create table DMs
|
||||
res = sqlite3_exec(ppDb, " \
|
||||
CREATE TABLE mappings( \
|
||||
chain_type INT NOT NULL, \
|
||||
identifier INT NOT NULL, \
|
||||
root_hash BLOB NOT NULL, \
|
||||
PRIMARY KEY (identifier) \
|
||||
);",
|
||||
NULL, NULL, &err);
|
||||
LOG_WARN("Result2 %u", res);
|
||||
if (err != nullptr)
|
||||
;
|
||||
LOG_ERROR("%s", err);
|
||||
sqlite3_free(err);
|
||||
// type
|
||||
// sha256hash
|
||||
// channelhash or 64 bit combination
|
||||
// The sat version needs a scratch database of messages that have not been checked in
|
||||
|
||||
// store schema version somewhere
|
||||
|
||||
std::string insert_statement = "INSERT INTO channel_messages (destination, sender, packet_id, want_ack, channel_hash, \
|
||||
encrypted_bytes, message_hash, rx_time, commit_hash, payload) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
|
||||
sqlite3_prepare(ppDb, insert_statement.c_str(), insert_statement.length(), &stmt, NULL);
|
||||
|
||||
encryptedOk = true;
|
||||
}
|
||||
|
||||
ProcessMessage StoreForwardPlusPlusSatModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
|
||||
// the sender+destination pair is an interesting unique id (though ordering) (smaller one goes first?)
|
||||
// so messages with a unique pair become a chain
|
||||
// These get a table
|
||||
|
||||
// message to broadcast get a chain per channel hash
|
||||
// second table
|
||||
// for now, channel messages are limited to decryptable
|
||||
// limited to text messages
|
||||
|
||||
// create a unique-from-nodenums() class that returns a 64-bit value
|
||||
|
||||
SHA256 message_hash, chain_hash;
|
||||
uint8_t message_hash_bytes[32] = {0};
|
||||
uint8_t chain_hash_bytes[32] = {0};
|
||||
|
||||
// For the moment, this is strictly LoRa
|
||||
if (mp.transport_mechanism != meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA) {
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
// will eventually host DMs and other undecodable messages
|
||||
if (mp.which_payload_variant != meshtastic_MeshPacket_decoded_tag) {
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
}
|
||||
// refuse without valid time?
|
||||
LOG_WARN("in handleReceived");
|
||||
std::string getEntry_string = "select commit_hash from channel_messages where channel_hash=? order by rowid desc LIMIT 1;";
|
||||
sqlite3_stmt *getEntry;
|
||||
int rc = sqlite3_prepare(ppDb, getEntry_string.c_str(), getEntry_string.size(), &getEntry, NULL);
|
||||
sqlite3_bind_int(getEntry, 1, router->p_encrypted->channel);
|
||||
sqlite3_step(getEntry);
|
||||
|
||||
// this is allocated by sqlite3 and will be deleted when finalize is called
|
||||
uint8_t *last_message_hash = (uint8_t *)sqlite3_column_blob(getEntry, 0);
|
||||
if (last_message_hash) {
|
||||
printBytes("last message: 0x", last_message_hash, 32);
|
||||
} else {
|
||||
// generate root hash and populate lookup table
|
||||
}
|
||||
|
||||
// do not include rxtime in the message hash. We want these to match when more then one node receives and compares notes.
|
||||
// feel free to include it in the commit hash
|
||||
|
||||
message_hash.reset();
|
||||
message_hash.update(router->p_encrypted->encrypted.bytes, router->p_encrypted->encrypted.size);
|
||||
message_hash.update(&mp.to, sizeof(mp.to));
|
||||
message_hash.update(&mp.from, sizeof(mp.from));
|
||||
message_hash.update(&mp.id, sizeof(mp.id));
|
||||
message_hash.finalize(message_hash_bytes, 32);
|
||||
|
||||
chain_hash.reset();
|
||||
if (last_message_hash) {
|
||||
chain_hash.update(last_message_hash, 32);
|
||||
}
|
||||
chain_hash.update(message_hash_bytes, 32);
|
||||
// message_hash.update(&mp.rx_time, sizeof(mp.rx_time));
|
||||
chain_hash.finalize(chain_hash_bytes, 32);
|
||||
|
||||
sqlite3_finalize(getEntry);
|
||||
|
||||
// select HEX(commit_hash),HEX(channel_hash), payload, destination from channel_messages order by rowid desc;
|
||||
|
||||
// push a message into the local chain DB
|
||||
// destination
|
||||
sqlite3_bind_int(stmt, 1, mp.to);
|
||||
// sender
|
||||
sqlite3_bind_int(stmt, 2, mp.from);
|
||||
// packet_id
|
||||
sqlite3_bind_int(stmt, 3, mp.id);
|
||||
// want_ack
|
||||
sqlite3_bind_int(stmt, 4, mp.want_ack);
|
||||
// channel_hash
|
||||
sqlite3_bind_int(stmt, 5, router->p_encrypted->channel);
|
||||
// encrypted_bytes
|
||||
sqlite3_bind_blob(stmt, 6, router->p_encrypted->encrypted.bytes, router->p_encrypted->encrypted.size, NULL);
|
||||
|
||||
// message_hash
|
||||
sqlite3_bind_blob(stmt, 7, message_hash_bytes, 32, NULL);
|
||||
// rx_time
|
||||
sqlite3_bind_int(stmt, 8, mp.rx_time);
|
||||
|
||||
// commit_hash
|
||||
sqlite3_bind_blob(stmt, 9, chain_hash_bytes, 32, NULL);
|
||||
// payload
|
||||
sqlite3_bind_text(stmt, 10, (char *)mp.decoded.payload.bytes, mp.decoded.payload.size, NULL);
|
||||
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
// when we get an update this way, if the message isn't on the chain or in the scratch table, this node hasn't seen it, and can
|
||||
// rebroadcast.
|
||||
|
||||
// messages
|
||||
// Given this chain root, do you have a packet that matches this message hash?
|
||||
// responds with chain hash etc
|
||||
|
||||
// given this chain root, what is your last chain and message hash?
|
||||
// given this chain root, what is your next message after this chain hash? (do we have an overhead problem here?) (blegh,
|
||||
// fragmentation) (but also, trunking)
|
||||
|
||||
// broadcast on this chain root, here is my last chain hash
|
||||
|
||||
// consider third-order nodes
|
||||
|
||||
// I can't talk directly to strata, I can talk to a satellite. Inform sat of a message. Sat stores it as if had seen it locally,
|
||||
// and pushes it to central
|
||||
|
||||
// message Eventually works out through chain
|
||||
|
||||
// sat can capture time of receipt
|
||||
41
src/modules/Native/StoreForwardPlusPlusSat.h
Normal file
41
src/modules/Native/StoreForwardPlusPlusSat.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "Router.h"
|
||||
#include "SinglePortModule.h"
|
||||
#include "sqlite3.h"
|
||||
|
||||
/**
|
||||
* A simple example module that just replies with "Message received" to any message it receives.
|
||||
*/
|
||||
class StoreForwardPlusPlusSatModule : public SinglePortModule // should probably derive this from the main class
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
*/
|
||||
StoreForwardPlusPlusSatModule();
|
||||
|
||||
/*
|
||||
-Override the wantPacket method.
|
||||
*/
|
||||
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||
{
|
||||
switch (p->decoded.portnum) {
|
||||
case meshtastic_PortNum_TEXT_MESSAGE_APP:
|
||||
case 35:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
|
||||
it
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
private:
|
||||
sqlite3 *ppDb;
|
||||
sqlite3_stmt *stmt;
|
||||
};
|
||||
@@ -746,6 +746,10 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
}
|
||||
|
||||
if (yamlConfig["StoreAndForward"]) {
|
||||
portduino_config.sfpp_stratum0 = (yamlConfig["StoreAndForward"]["Stratum0"]).as<bool>(false);
|
||||
}
|
||||
|
||||
if (yamlConfig["General"]) {
|
||||
portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
|
||||
portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
|
||||
|
||||
@@ -163,6 +163,9 @@ extern struct portduino_config_struct {
|
||||
int configDisplayMode = 0;
|
||||
bool has_configDisplayMode = false;
|
||||
|
||||
// Store and Forward++
|
||||
bool sfpp_stratum0 = false;
|
||||
|
||||
// General
|
||||
std::string mac_address = "";
|
||||
bool mac_address_explicit = false;
|
||||
|
||||
@@ -45,6 +45,7 @@ build_flags = ${native_base.build_flags} -Os -lX11 -linput -lxkbcommon -ffunctio
|
||||
!pkg-config --libs openssl --silence-errors || :
|
||||
!pkg-config --cflags --libs sdl2 --silence-errors || :
|
||||
!pkg-config --cflags --libs libbsd-overlay --silence-errors || :
|
||||
!pkg-config --cflags --libs sqlite3 --silence-errors || :
|
||||
build_src_filter =
|
||||
${native_base.build_src_filter}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user