mirror of
https://github.com/Quad4-Software/Reticulum-Go
synced 2026-08-29 23:48:44 -04:00
325 lines
9.5 KiB
Python
325 lines
9.5 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright (c) 2024-2026 Quad4.io
|
|
|
|
"""Raw ctypes layer over include/rns.h."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import ctypes
|
|
import os
|
|
from pathlib import Path
|
|
|
|
HASH_LEN = 16
|
|
|
|
RNS_OK = 0
|
|
RNS_ERR_INVALID_ARG = 1
|
|
RNS_ERR_INVALID_HANDLE = 2
|
|
RNS_ERR_NOT_FOUND = 3
|
|
RNS_ERR_STATE = 4
|
|
RNS_ERR_IO = 5
|
|
RNS_ERR_INTERNAL = 6
|
|
RNS_ERR_TIMEOUT = 7
|
|
RNS_ERR_TRUNCATED = 8
|
|
|
|
RNS_EV_DESTINATION_DATA = 11
|
|
|
|
|
|
class RnsEvent(ctypes.Structure):
|
|
_fields_ = [
|
|
("kind", ctypes.c_int),
|
|
("link_id", ctypes.c_uint8 * HASH_LEN),
|
|
("link_id_len", ctypes.c_size_t),
|
|
("destination_hash", ctypes.c_uint8 * HASH_LEN),
|
|
("destination_hash_len", ctypes.c_size_t),
|
|
("identity_hash", ctypes.c_uint8 * HASH_LEN),
|
|
("identity_hash_len", ctypes.c_size_t),
|
|
("request_id", ctypes.c_uint8 * HASH_LEN),
|
|
("request_id_len", ctypes.c_size_t),
|
|
("hops", ctypes.c_uint8),
|
|
("path", ctypes.c_char * 256),
|
|
("path_truncated", ctypes.c_int),
|
|
("error_message", ctypes.c_char * 256),
|
|
("error_message_truncated", ctypes.c_int),
|
|
("app_data", ctypes.POINTER(ctypes.c_uint8)),
|
|
("app_data_len", ctypes.c_size_t),
|
|
("app_data_cap", ctypes.c_size_t),
|
|
("app_data_truncated", ctypes.c_int),
|
|
]
|
|
|
|
|
|
class RnsPathEntry(ctypes.Structure):
|
|
_fields_ = [
|
|
("hash", ctypes.c_uint8 * HASH_LEN),
|
|
("hash_len", ctypes.c_size_t),
|
|
("via", ctypes.c_uint8 * HASH_LEN),
|
|
("via_len", ctypes.c_size_t),
|
|
("hops", ctypes.c_uint8),
|
|
("iface", ctypes.c_char * 64),
|
|
("timestamp", ctypes.c_double),
|
|
("expires", ctypes.c_double),
|
|
]
|
|
|
|
|
|
class RnsInterfaceEntry(ctypes.Structure):
|
|
_fields_ = [
|
|
("name", ctypes.c_char * 96),
|
|
("type_name", ctypes.c_char * 32),
|
|
("online", ctypes.c_int),
|
|
("enabled", ctypes.c_int),
|
|
("rx_bytes", ctypes.c_uint64),
|
|
("tx_bytes", ctypes.c_uint64),
|
|
("rx_packets", ctypes.c_uint64),
|
|
("tx_packets", ctypes.c_uint64),
|
|
]
|
|
|
|
|
|
def _candidates() -> list[Path]:
|
|
out: list[Path] = []
|
|
env = os.environ.get("RNS_LIB_PATH")
|
|
if env:
|
|
out.append(Path(env))
|
|
root = os.environ.get("RNS_ROOT")
|
|
if root:
|
|
out.append(Path(root) / "bin" / "librns.so")
|
|
here = Path(__file__).resolve()
|
|
out.extend(
|
|
[
|
|
here.parents[3] / "bin" / "librns.so",
|
|
here.parents[2] / "bin" / "librns.so",
|
|
Path("bin/librns.so"),
|
|
Path("../bin/librns.so"),
|
|
Path("../../bin/librns.so"),
|
|
]
|
|
)
|
|
return out
|
|
|
|
|
|
def load_library(path: str | None = None) -> ctypes.CDLL:
|
|
if path:
|
|
return ctypes.CDLL(path)
|
|
for candidate in _candidates():
|
|
if candidate.is_file():
|
|
return ctypes.CDLL(str(candidate))
|
|
return ctypes.CDLL("librns.so")
|
|
|
|
|
|
_lib = load_library()
|
|
|
|
_lib.rns_version.restype = ctypes.c_char_p
|
|
_lib.rns_last_error.argtypes = [
|
|
ctypes.c_char_p,
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_last_error.restype = ctypes.c_int
|
|
|
|
_lib.rns_node_create.argtypes = [ctypes.c_char_p]
|
|
_lib.rns_node_create.restype = ctypes.c_uint64
|
|
for name in ("rns_node_start", "rns_node_stop", "rns_node_destroy", "rns_node_resume", "rns_node_pause"):
|
|
getattr(_lib, name).argtypes = [ctypes.c_uint64]
|
|
getattr(_lib, name).restype = ctypes.c_int
|
|
|
|
_lib.rns_node_set_identity.argtypes = [ctypes.c_uint64, ctypes.c_uint64]
|
|
_lib.rns_node_set_identity.restype = ctypes.c_int
|
|
|
|
_lib.rns_identity_generate.argtypes = []
|
|
_lib.rns_identity_generate.restype = ctypes.c_uint64
|
|
_lib.rns_identity_load.argtypes = [ctypes.c_char_p]
|
|
_lib.rns_identity_load.restype = ctypes.c_uint64
|
|
_lib.rns_identity_save.argtypes = [ctypes.c_uint64, ctypes.c_char_p]
|
|
_lib.rns_identity_save.restype = ctypes.c_int
|
|
_lib.rns_identity_destroy.argtypes = [ctypes.c_uint64]
|
|
_lib.rns_identity_destroy.restype = ctypes.c_int
|
|
_lib.rns_identity_hash.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.c_char_p,
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_identity_hash.restype = ctypes.c_int
|
|
_lib.rns_identity_hash_bytes.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_identity_hash_bytes.restype = ctypes.c_int
|
|
_lib.rns_identity_public_key.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_identity_public_key.restype = ctypes.c_int
|
|
_lib.rns_identity_from_public_key.argtypes = [ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t]
|
|
_lib.rns_identity_from_public_key.restype = ctypes.c_uint64
|
|
_lib.rns_identity_sign.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_identity_sign.restype = ctypes.c_int
|
|
_lib.rns_identity_verify.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_identity_verify.restype = ctypes.c_int
|
|
|
|
_lib.rns_rsg_create.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.c_int,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_rsg_create.restype = ctypes.c_int
|
|
_lib.rns_rsg_validate.argtypes = [
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_rsg_validate.restype = ctypes.c_int
|
|
_lib.rns_rsm_verify.argtypes = [
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_rsm_verify.restype = ctypes.c_int
|
|
|
|
_lib.rns_interfaces.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(RnsInterfaceEntry),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_interfaces.restype = ctypes.c_int
|
|
|
|
_lib.rns_event_poll.argtypes = [ctypes.c_uint64, ctypes.POINTER(RnsEvent), ctypes.c_int]
|
|
_lib.rns_event_poll.restype = ctypes.c_int
|
|
|
|
_lib.rns_node_refresh_paths.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_node_refresh_paths.restype = ctypes.c_int
|
|
|
|
_lib.rns_destination_create.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.c_uint64,
|
|
ctypes.c_char_p,
|
|
ctypes.POINTER(ctypes.c_char_p),
|
|
ctypes.c_size_t,
|
|
ctypes.c_int,
|
|
]
|
|
_lib.rns_destination_create.restype = ctypes.c_uint64
|
|
_lib.rns_destination_enable_ratchets.argtypes = [ctypes.c_uint64, ctypes.c_char_p]
|
|
_lib.rns_destination_enable_ratchets.restype = ctypes.c_int
|
|
_lib.rns_destination_enforce_ratchets.argtypes = [ctypes.c_uint64]
|
|
_lib.rns_destination_enforce_ratchets.restype = ctypes.c_int
|
|
_lib.rns_destination_announce.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_destination_announce.restype = ctypes.c_int
|
|
_lib.rns_destination_destroy.argtypes = [ctypes.c_uint64]
|
|
_lib.rns_destination_destroy.restype = ctypes.c_int
|
|
_lib.rns_destination_hash.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_destination_hash.restype = ctypes.c_int
|
|
_lib.rns_destination_register_request_handler.argtypes = [ctypes.c_uint64, ctypes.c_char_p]
|
|
_lib.rns_destination_register_request_handler.restype = ctypes.c_int
|
|
|
|
_lib.rns_path_request.argtypes = [ctypes.c_uint64, ctypes.POINTER(ctypes.c_uint8)]
|
|
_lib.rns_path_request.restype = ctypes.c_int
|
|
_lib.rns_path_table.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(RnsPathEntry),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
ctypes.c_int,
|
|
]
|
|
_lib.rns_path_table.restype = ctypes.c_int
|
|
|
|
_lib.rns_link_open.argtypes = [ctypes.c_uint64, ctypes.POINTER(ctypes.c_uint8)]
|
|
_lib.rns_link_open.restype = ctypes.c_uint64
|
|
for name in ("rns_link_send", "rns_link_close"):
|
|
getattr(_lib, name).argtypes = [ctypes.c_uint64]
|
|
if name == "rns_link_send":
|
|
getattr(_lib, name).argtypes = [ctypes.c_uint64, ctypes.POINTER(ctypes.c_uint8), ctypes.c_size_t]
|
|
getattr(_lib, name).restype = ctypes.c_int
|
|
_lib.rns_link_send_resource.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.c_char_p,
|
|
]
|
|
_lib.rns_link_send_resource.restype = ctypes.c_int
|
|
_lib.rns_link_id.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_link_id.restype = ctypes.c_int
|
|
_lib.rns_link_request.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.c_uint64,
|
|
ctypes.c_char_p,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.c_int,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_size_t),
|
|
]
|
|
_lib.rns_link_request.restype = ctypes.c_int
|
|
|
|
_lib.rns_request_respond.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_request_respond.restype = ctypes.c_int
|
|
_lib.rns_request_respond_file.argtypes = [
|
|
ctypes.c_uint64,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
ctypes.c_char_p,
|
|
ctypes.POINTER(ctypes.c_uint8),
|
|
ctypes.c_size_t,
|
|
]
|
|
_lib.rns_request_respond_file.restype = ctypes.c_int
|
|
|
|
|
|
def cstr_field(buf) -> str:
|
|
raw = bytes(buf)
|
|
nul = raw.find(b"\x00")
|
|
if nul >= 0:
|
|
raw = raw[:nul]
|
|
return raw.decode("utf-8", errors="replace")
|
|
|
|
|
|
lib = _lib
|