mirror of
https://github.com/Quad4-Software/Reticulum-Go
synced 2026-08-29 23:48:44 -04:00
199 lines
6.1 KiB
Lua
199 lines
6.1 KiB
Lua
-- SPDX-License-Identifier: Apache-2.0
|
|
-- Copyright (c) 2024-2026 Quad4.io
|
|
|
|
local ffi = require("ffi")
|
|
|
|
local HASH_LEN = 16
|
|
|
|
ffi.cdef[[
|
|
typedef struct rns_event {
|
|
int kind;
|
|
uint8_t link_id[16];
|
|
size_t link_id_len;
|
|
uint8_t destination_hash[16];
|
|
size_t destination_hash_len;
|
|
uint8_t identity_hash[16];
|
|
size_t identity_hash_len;
|
|
uint8_t request_id[16];
|
|
size_t request_id_len;
|
|
uint8_t hops;
|
|
char path[256];
|
|
int path_truncated;
|
|
char error_message[256];
|
|
int error_message_truncated;
|
|
uint8_t *app_data;
|
|
size_t app_data_len;
|
|
size_t app_data_cap;
|
|
int app_data_truncated;
|
|
} rns_event;
|
|
|
|
typedef struct rns_path_entry {
|
|
uint8_t hash[16];
|
|
size_t hash_len;
|
|
uint8_t via[16];
|
|
size_t via_len;
|
|
uint8_t hops;
|
|
char iface[64];
|
|
double timestamp;
|
|
double expires;
|
|
} rns_path_entry;
|
|
|
|
typedef struct rns_interface_entry {
|
|
char name[96];
|
|
char type_name[32];
|
|
int online;
|
|
int enabled;
|
|
uint64_t rx_bytes;
|
|
uint64_t tx_bytes;
|
|
uint64_t rx_packets;
|
|
uint64_t tx_packets;
|
|
} rns_interface_entry;
|
|
|
|
const char *rns_version(void);
|
|
int rns_last_error(char *buf, size_t buf_len, size_t *written);
|
|
|
|
uint64_t rns_node_create(const char *config_path);
|
|
int rns_node_start(uint64_t node);
|
|
int rns_node_stop(uint64_t node);
|
|
int rns_node_destroy(uint64_t node);
|
|
int rns_node_set_identity(uint64_t node, uint64_t identity);
|
|
int rns_node_resume(uint64_t node);
|
|
int rns_node_pause(uint64_t node);
|
|
int rns_node_refresh_paths(uint64_t node, const uint8_t *dest_hashes, size_t count);
|
|
|
|
uint64_t rns_identity_generate(void);
|
|
uint64_t rns_identity_load(const char *path);
|
|
int rns_identity_save(uint64_t identity, const char *path);
|
|
int rns_identity_destroy(uint64_t identity);
|
|
int rns_identity_hash(uint64_t identity, char *hex_buf, size_t hex_buf_len, size_t *written);
|
|
int rns_identity_hash_bytes(uint64_t identity, uint8_t *out, size_t out_len, size_t *written);
|
|
int rns_identity_public_key(uint64_t identity, uint8_t *out, size_t out_len, size_t *written);
|
|
uint64_t rns_identity_from_public_key(const uint8_t *pub, size_t pub_len);
|
|
int rns_identity_sign(uint64_t identity, const uint8_t *data, size_t data_len,
|
|
uint8_t *sig_out, size_t sig_out_len, size_t *written);
|
|
int rns_identity_verify(uint64_t identity, const uint8_t *data, size_t data_len,
|
|
const uint8_t *sig, size_t sig_len);
|
|
|
|
int rns_rsg_create(uint64_t identity, const uint8_t *message, size_t message_len, int embed,
|
|
uint8_t *out, size_t out_len, size_t *written);
|
|
int rns_rsg_validate(const uint8_t *rsg, size_t rsg_len,
|
|
const uint8_t *message, size_t message_len,
|
|
const uint8_t *required_signer_hash, size_t required_signer_hash_len);
|
|
int rns_rsm_verify(const uint8_t *rsm, size_t rsm_len,
|
|
const uint8_t *required_signer_hash, size_t required_signer_hash_len,
|
|
uint8_t *message_out, size_t message_out_len, size_t *written);
|
|
|
|
uint64_t rns_destination_create(uint64_t node, uint64_t identity, const char *app_name,
|
|
const char *const *aspects, size_t aspect_count, int accepts_links);
|
|
int rns_destination_enable_ratchets(uint64_t destination, const char *path);
|
|
int rns_destination_enforce_ratchets(uint64_t destination);
|
|
int rns_destination_announce(uint64_t destination, const uint8_t *app_data, size_t app_data_len);
|
|
int rns_destination_hash(uint64_t destination, uint8_t *hash_out, size_t hash_out_len, size_t *written);
|
|
int rns_destination_destroy(uint64_t destination);
|
|
int rns_destination_register_request_handler(uint64_t destination, const char *path);
|
|
|
|
int rns_path_request(uint64_t node, const uint8_t *dest_hash);
|
|
int rns_path_table(uint64_t node, rns_path_entry *out, size_t out_cap, size_t *written, int max_hops);
|
|
int rns_interfaces(uint64_t node, rns_interface_entry *out, size_t out_cap, size_t *written);
|
|
|
|
uint64_t rns_link_open(uint64_t node, const uint8_t *dest_hash);
|
|
int rns_link_send(uint64_t link, const uint8_t *data, size_t data_len);
|
|
int rns_link_send_resource(uint64_t link, const uint8_t *data, size_t data_len, const char *name);
|
|
int rns_link_close(uint64_t link);
|
|
int rns_link_id(uint64_t link, uint8_t *id_out, size_t id_out_len, size_t *written);
|
|
int rns_link_request(uint64_t node, uint64_t link, const char *path,
|
|
const uint8_t *data, size_t data_len, int timeout_ms,
|
|
uint8_t *request_id_out, size_t request_id_out_len, size_t *written);
|
|
|
|
int rns_request_respond(uint64_t node, const uint8_t *request_id, size_t request_id_len,
|
|
const uint8_t *data, size_t data_len);
|
|
int rns_request_respond_file(uint64_t node, const uint8_t *request_id, size_t request_id_len,
|
|
const char *filename, const uint8_t *data, size_t data_len);
|
|
|
|
int rns_event_poll(uint64_t node, rns_event *event, int timeout_ms);
|
|
]]
|
|
|
|
local function candidates()
|
|
local out = {}
|
|
local env = os.getenv("RNS_LIB_PATH")
|
|
if env and env ~= "" then
|
|
out[#out + 1] = env
|
|
end
|
|
local root = os.getenv("RNS_ROOT")
|
|
if root and root ~= "" then
|
|
out[#out + 1] = root .. "/bin/librns.so"
|
|
end
|
|
local info = debug.getinfo(1, "S")
|
|
local src = info and info.source or ""
|
|
if src:sub(1, 1) == "@" then
|
|
local dir = src:sub(2):match("(.*/)")
|
|
if dir then
|
|
out[#out + 1] = dir .. "../../../bin/librns.so"
|
|
out[#out + 1] = dir .. "../../bin/librns.so"
|
|
end
|
|
end
|
|
out[#out + 1] = "bin/librns.so"
|
|
out[#out + 1] = "../bin/librns.so"
|
|
out[#out + 1] = "../../bin/librns.so"
|
|
return out
|
|
end
|
|
|
|
local function file_exists(path)
|
|
local f = io.open(path, "rb")
|
|
if not f then
|
|
return false
|
|
end
|
|
f:close()
|
|
return true
|
|
end
|
|
|
|
local function load_library(path)
|
|
if path then
|
|
return ffi.load(path)
|
|
end
|
|
for _, candidate in ipairs(candidates()) do
|
|
if file_exists(candidate) then
|
|
return ffi.load(candidate)
|
|
end
|
|
end
|
|
return ffi.load("rns")
|
|
end
|
|
|
|
local lib = load_library()
|
|
|
|
local function cstr(buf, max_len)
|
|
local n = max_len or #buf
|
|
for i = 0, n - 1 do
|
|
if buf[i] == 0 then
|
|
return ffi.string(buf, i)
|
|
end
|
|
end
|
|
return ffi.string(buf, n)
|
|
end
|
|
|
|
local function bytes_from(ptr, len)
|
|
if ptr == nil or len == 0 then
|
|
return ""
|
|
end
|
|
return ffi.string(ptr, len)
|
|
end
|
|
|
|
local function to_uint8(data)
|
|
if data == nil or data == "" then
|
|
return nil, 0
|
|
end
|
|
local n = #data
|
|
local buf = ffi.new("uint8_t[?]", n)
|
|
ffi.copy(buf, data, n)
|
|
return buf, n
|
|
end
|
|
|
|
return {
|
|
ffi = ffi,
|
|
lib = lib,
|
|
HASH_LEN = HASH_LEN,
|
|
cstr = cstr,
|
|
bytes_from = bytes_from,
|
|
to_uint8 = to_uint8,
|
|
load_library = load_library,
|
|
}
|