Vendor microReticulum library with boundary mode transport fixes: - Two-whitelist system gates backbone traffic (local addresses + mentioned addresses from local devices) - Allow control_hashes and local destinations through boundary filter (fixes backbone→LoRa path discovery) - Fix get_cached_packet() to call unpack() instead of update_hash() (fixes empty destination_hash in path responses) - LRPROOF Identity::recall null guard - remaining_hops HEADER_1/BROADCAST fix for final-hop delivery - PROOF packets excluded from boundary wrapping - Iterator invalidation fix in transport table cleanup - is_backbone flag replaces string matching for interface identification Firmware changes: - Set is_backbone(true) on backbone TCP interface - Rename default TcpInterface name to BackboneInterface - Update comments for dual-use TcpInterface (backbone + local AP) - Use vendored lib/microReticulum instead of PlatformIO registry
235 lines
6.8 KiB
C++
Executable File
235 lines
6.8 KiB
C++
Executable File
#pragma once
|
|
|
|
#include "../FileSystem.h"
|
|
#include "../FileStream.h"
|
|
#include "../Bytes.h"
|
|
|
|
#include "tlsf.h"
|
|
|
|
#include <cmath>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <stdint.h>
|
|
#include <sys/time.h>
|
|
|
|
#ifdef ARDUINO
|
|
#include <Arduino.h>
|
|
#endif
|
|
|
|
#undef round
|
|
|
|
namespace RNS { namespace Utilities {
|
|
|
|
class OS {
|
|
|
|
private:
|
|
static FileSystem _filesystem;
|
|
static uint64_t _time_offset;
|
|
|
|
public:
|
|
static tlsf_t _tlsf;
|
|
|
|
public:
|
|
static inline uint64_t getTimeOffset() { return _time_offset; }
|
|
static inline void setTimeOffset(uint64_t offset) { _time_offset = offset; }
|
|
|
|
#ifdef ARDUINO
|
|
// return current time in milliseconds since startup
|
|
static inline uint64_t ltime() {
|
|
// handle roll-over of 32-bit millis (approx. 49 days)
|
|
static uint32_t low32, high32;
|
|
uint32_t new_low32 = millis();
|
|
if (new_low32 < low32) high32++;
|
|
low32 = new_low32;
|
|
return ((uint64_t)high32 << 32 | low32) + _time_offset;
|
|
}
|
|
#else
|
|
// return current time in milliseconds since 00:00:00, January 1, 1970 (Unix Epoch)
|
|
static inline uint64_t ltime() { timeval time; ::gettimeofday(&time, NULL); return (uint64_t)(time.tv_sec * 1000) + (uint64_t)(time.tv_usec / 1000); }
|
|
#endif
|
|
|
|
#ifdef ARDUINO
|
|
// return current time in float seconds since startup
|
|
static inline double time() { return (double)(ltime() / 1000.0); }
|
|
#else
|
|
// return current time in float seconds since 00:00:00, January 1, 1970 (Unix Epoch)
|
|
static inline double time() { timeval time; ::gettimeofday(&time, NULL); return (double)time.tv_sec + ((double)time.tv_usec / 1000000); }
|
|
#endif
|
|
|
|
// sleep for specified milliseconds
|
|
//static inline void sleep(float seconds) { ::sleep(seconds); }
|
|
#ifdef ARDUINO
|
|
static inline void sleep(float seconds) { delay((uint32_t)(seconds * 1000)); }
|
|
#else
|
|
static inline void sleep(float seconds) { timespec time; time.tv_sec = (time_t)(seconds); time.tv_nsec = (seconds - (float)time.tv_sec) * 1000000000; ::nanosleep(&time, nullptr); }
|
|
#endif
|
|
//static inline void sleep(uint32_t milliseconds) { ::sleep((float)milliseconds / 1000.0); }
|
|
|
|
// round decimal number to specified precision
|
|
//static inline float round(float value, uint8_t precision) { return std::round(value / precision) * precision; }
|
|
//static inline double round(double value, uint8_t precision) { return std::round(value / precision) * precision; }
|
|
static inline double round(double value, uint8_t precision) { return std::round(value / precision) * precision; }
|
|
|
|
static inline uint64_t from_bytes_big_endian(const uint8_t* data, size_t len) {
|
|
uint64_t result = 0;
|
|
for (size_t i = 0; i < len; ++i) {
|
|
result = (result << 8) | data[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Detect endianness at runtime
|
|
static int is_big_endian(void) {
|
|
uint16_t test = 0x0102;
|
|
return ((uint8_t*)&test)[0] == 0x01;
|
|
}
|
|
|
|
// Byte swap functions
|
|
static uint16_t swap16(uint16_t val) {
|
|
return (val << 8) | (val >> 8);
|
|
}
|
|
|
|
static uint32_t swap32(uint32_t val) {
|
|
return ((val << 24) & 0xFF000000) |
|
|
((val << 8) & 0x00FF0000) |
|
|
((val >> 8) & 0x0000FF00) |
|
|
((val >> 24) & 0x000000FF);
|
|
}
|
|
|
|
// Platform-independent replacements
|
|
|
|
static uint16_t portable_htons(uint16_t val) {
|
|
return is_big_endian() ? val : swap16(val);
|
|
}
|
|
|
|
static uint32_t portable_htonl(uint32_t val) {
|
|
return is_big_endian() ? val : swap32(val);
|
|
}
|
|
|
|
static uint16_t portable_ntohs(uint16_t val) {
|
|
return is_big_endian() ? val : swap16(val);
|
|
}
|
|
|
|
static uint32_t portable_ntohl(uint32_t val) {
|
|
return is_big_endian() ? val : swap32(val);
|
|
}
|
|
|
|
#if defined(RNS_USE_ALLOCATOR)
|
|
static void dump_allocator_stats();
|
|
#endif
|
|
|
|
inline static void register_filesystem(FileSystem& filesystem) {
|
|
TRACE("Registering filesystem...");
|
|
_filesystem = filesystem;
|
|
}
|
|
|
|
/*
|
|
inline static void register_filesystem(FileSystemImpl* filesystemimpl) {
|
|
TRACE("Registering filesystem...");
|
|
_filesystem = filesystemimpl;
|
|
}
|
|
*/
|
|
|
|
inline static void deregister_filesystem() {
|
|
TRACE("Deregistering filesystem...");
|
|
_filesystem = {Type::NONE};
|
|
}
|
|
|
|
inline static FileSystem& get_filesystem() {
|
|
return _filesystem;
|
|
}
|
|
|
|
|
|
inline static bool file_exists(const char* file_path) {
|
|
if (!_filesystem) {
|
|
WARNING("file_exists: filesystem not registered");
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.file_exists(file_path);
|
|
}
|
|
|
|
inline static size_t read_file(const char* file_path, Bytes& data) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.read_file(file_path, data);
|
|
}
|
|
|
|
inline static size_t write_file(const char* file_path, const Bytes& data) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.write_file(file_path, data);
|
|
}
|
|
|
|
inline static FileStream open_file(const char* file_path, RNS::FileStream::MODE file_mode) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.open_file(file_path, file_mode);
|
|
}
|
|
|
|
inline static bool remove_file(const char* file_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.remove_file(file_path);
|
|
}
|
|
|
|
inline static bool rename_file(const char* from_file_path, const char* to_file_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.rename_file(from_file_path, to_file_path);
|
|
}
|
|
|
|
inline static bool directory_exists(const char* directory_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.directory_exists(directory_path);
|
|
}
|
|
|
|
inline static bool create_directory(const char* directory_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.create_directory(directory_path);
|
|
}
|
|
|
|
inline static bool remove_directory(const char* directory_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.remove_directory(directory_path);
|
|
}
|
|
|
|
inline static std::list<std::string> list_directory(const char* directory_path) {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.list_directory(directory_path);
|
|
}
|
|
|
|
inline static size_t storage_size() {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.storage_size();
|
|
}
|
|
|
|
inline static size_t storage_available() {
|
|
if (!_filesystem) {
|
|
throw std::runtime_error("FileSystem has not been registered");
|
|
}
|
|
return _filesystem.storage_available();
|
|
}
|
|
|
|
static size_t heap_size();
|
|
static size_t heap_available();
|
|
static void dump_heap_stats();
|
|
|
|
};
|
|
|
|
} }
|