mirror of
https://github.com/Quad4-Software/Reticulum-Go
synced 2026-08-29 23:48:44 -04:00
147 lines
4.3 KiB
Python
147 lines
4.3 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright (c) 2024-2026 Quad4.io
|
|
|
|
from __future__ import annotations
|
|
|
|
import ctypes
|
|
|
|
from . import ffi
|
|
from .errors import Error, map_code
|
|
from .node import Node
|
|
|
|
|
|
class Link:
|
|
def __init__(self, handle: int) -> None:
|
|
self._handle = int(handle)
|
|
|
|
@classmethod
|
|
def open(cls, node: Node, dest_hash: bytes | bytearray | memoryview) -> Link:
|
|
data = bytes(dest_hash)
|
|
if len(data) != ffi.HASH_LEN:
|
|
raise Error(Error.INVALID_ARG)
|
|
buf = (ctypes.c_uint8 * ffi.HASH_LEN).from_buffer_copy(data)
|
|
h = ffi.lib.rns_link_open(node.handle, buf)
|
|
if h == 0:
|
|
raise Error(Error.INTERNAL)
|
|
return cls(h)
|
|
|
|
def send(self, data: bytes | bytearray | memoryview) -> None:
|
|
payload = bytes(data)
|
|
if not payload:
|
|
raise Error(Error.INVALID_ARG)
|
|
buf = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload)
|
|
map_code(ffi.lib.rns_link_send(self._handle, buf, len(payload)))
|
|
|
|
def send_resource(self, data: bytes | bytearray | memoryview, name: str = "") -> None:
|
|
payload = bytes(data)
|
|
name_ptr = name.encode("utf-8") if name else None
|
|
data_ptr = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) if payload else None
|
|
map_code(
|
|
ffi.lib.rns_link_send_resource(
|
|
self._handle,
|
|
data_ptr,
|
|
len(payload),
|
|
name_ptr,
|
|
)
|
|
)
|
|
|
|
def close(self) -> None:
|
|
if self._handle:
|
|
ffi.lib.rns_link_close(self._handle)
|
|
self._handle = 0
|
|
|
|
def id(self) -> bytes:
|
|
out = (ctypes.c_uint8 * ffi.HASH_LEN)()
|
|
written = ctypes.c_size_t(0)
|
|
map_code(ffi.lib.rns_link_id(self._handle, out, ffi.HASH_LEN, ctypes.byref(written)))
|
|
if written.value != ffi.HASH_LEN:
|
|
raise Error(Error.TRUNCATED)
|
|
return bytes(out)
|
|
|
|
def request(
|
|
self,
|
|
node: Node,
|
|
path: str,
|
|
data: bytes | bytearray | memoryview = b"",
|
|
timeout_ms: int = 0,
|
|
) -> bytes:
|
|
if not path:
|
|
raise Error(Error.INVALID_ARG)
|
|
payload = bytes(data)
|
|
data_ptr = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) if payload else None
|
|
request_id = (ctypes.c_uint8 * ffi.HASH_LEN)()
|
|
written = ctypes.c_size_t(0)
|
|
map_code(
|
|
ffi.lib.rns_link_request(
|
|
node.handle,
|
|
self._handle,
|
|
path.encode("utf-8"),
|
|
data_ptr,
|
|
len(payload),
|
|
int(timeout_ms),
|
|
request_id,
|
|
ffi.HASH_LEN,
|
|
ctypes.byref(written),
|
|
)
|
|
)
|
|
if written.value != ffi.HASH_LEN:
|
|
raise Error(Error.TRUNCATED)
|
|
return bytes(request_id)
|
|
|
|
@property
|
|
def handle(self) -> int:
|
|
return self._handle
|
|
|
|
def __enter__(self) -> Link:
|
|
return self
|
|
|
|
def __exit__(self, *args: object) -> None:
|
|
self.close()
|
|
|
|
def __del__(self) -> None:
|
|
try:
|
|
self.close()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def request_respond(node: Node, request_id: bytes | bytearray | memoryview, data: bytes | bytearray | memoryview) -> None:
|
|
req = bytes(request_id)
|
|
if not req:
|
|
raise Error(Error.INVALID_ARG)
|
|
payload = bytes(data)
|
|
req_ptr = (ctypes.c_uint8 * len(req)).from_buffer_copy(req)
|
|
data_ptr = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) if payload else None
|
|
map_code(
|
|
ffi.lib.rns_request_respond(
|
|
node.handle,
|
|
req_ptr,
|
|
len(req),
|
|
data_ptr,
|
|
len(payload),
|
|
)
|
|
)
|
|
|
|
|
|
def request_respond_file(
|
|
node: Node,
|
|
request_id: bytes | bytearray | memoryview,
|
|
filename: str,
|
|
data: bytes | bytearray | memoryview,
|
|
) -> None:
|
|
req = bytes(request_id)
|
|
if not req or not filename:
|
|
raise Error(Error.INVALID_ARG)
|
|
payload = bytes(data)
|
|
req_ptr = (ctypes.c_uint8 * len(req)).from_buffer_copy(req)
|
|
data_ptr = (ctypes.c_uint8 * len(payload)).from_buffer_copy(payload) if payload else None
|
|
map_code(
|
|
ffi.lib.rns_request_respond_file(
|
|
node.handle,
|
|
req_ptr,
|
|
len(req),
|
|
filename.encode("utf-8"),
|
|
data_ptr,
|
|
len(payload),
|
|
)
|
|
)
|