2025-09-09 20:30:03 +02:00
|
|
|
|
# libcodex.nim - C-exported interface for the Codex shared library
|
|
|
|
|
|
#
|
|
|
|
|
|
# This file implements the public C API for libcodex.
|
|
|
|
|
|
# It acts as the bridge between C programs and the internal Nim implementation.
|
|
|
|
|
|
#
|
|
|
|
|
|
# This file defines:
|
|
|
|
|
|
# - Initialization logic for the Nim runtime (once per process)
|
|
|
|
|
|
# - Thread-safe exported procs callable from C
|
|
|
|
|
|
# - Callback registration and invocation for asynchronous communication
|
|
|
|
|
|
|
|
|
|
|
|
# cdecl is C declaration calling convention.
|
|
|
|
|
|
# It’s the standard way C compilers expect functions to behave:
|
|
|
|
|
|
# 1- Caller cleans up the stack after the call
|
|
|
|
|
|
# 2- Symbol names are exported in a predictable way
|
|
|
|
|
|
# In other termes, it is a glue that makes Nim functions callable as normal C functions.
|
|
|
|
|
|
{.pragma: exported, exportc, cdecl, raises: [].}
|
|
|
|
|
|
{.pragma: callback, cdecl, raises: [], gcsafe.}
|
|
|
|
|
|
|
|
|
|
|
|
# Ensure code is position-independent so it can be built into a shared library (.so).
|
|
|
|
|
|
# In other terms, the code that can run no matter where it’s placed in memory.
|
|
|
|
|
|
{.passc: "-fPIC".}
|
|
|
|
|
|
|
|
|
|
|
|
when defined(linux):
|
|
|
|
|
|
# Define the canonical name for this library
|
|
|
|
|
|
{.passl: "-Wl,-soname,libcodex.so".}
|
|
|
|
|
|
|
|
|
|
|
|
import std/[atomics]
|
|
|
|
|
|
import chronicles
|
|
|
|
|
|
import chronos
|
2025-10-07 07:58:07 +02:00
|
|
|
|
import chronos/threadsync
|
2025-09-09 20:30:03 +02:00
|
|
|
|
import ./codex_context
|
|
|
|
|
|
import ./codex_thread_requests/codex_thread_request
|
|
|
|
|
|
import ./codex_thread_requests/requests/node_lifecycle_request
|
2025-09-16 10:07:48 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_info_request
|
2025-09-17 07:50:11 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_debug_request
|
2025-09-17 13:25:30 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_p2p_request
|
2025-09-18 09:14:49 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_upload_request
|
2025-09-30 06:05:04 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_download_request
|
2025-10-01 09:16:47 +02:00
|
|
|
|
import ./codex_thread_requests/requests/node_storage_request
|
2025-09-09 20:30:03 +02:00
|
|
|
|
import ./ffi_types
|
|
|
|
|
|
|
2025-10-23 16:51:16 +02:00
|
|
|
|
from ../codex/conf import codexVersion
|
2025-09-12 12:18:17 +02:00
|
|
|
|
|
2025-09-25 08:38:52 +02:00
|
|
|
|
logScope:
|
|
|
|
|
|
topics = "codexlib"
|
|
|
|
|
|
|
2025-09-09 20:30:03 +02:00
|
|
|
|
template checkLibcodexParams*(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
) =
|
|
|
|
|
|
if not isNil(ctx):
|
|
|
|
|
|
ctx[].userData = userData
|
|
|
|
|
|
|
|
|
|
|
|
if isNil(callback):
|
|
|
|
|
|
return RET_MISSING_CALLBACK
|
|
|
|
|
|
|
|
|
|
|
|
# From Nim doc:
|
|
|
|
|
|
# "the C targets require you to initialize Nim's internals, which is done calling a NimMain function."
|
|
|
|
|
|
# "The name NimMain can be influenced via the --nimMainPrefix:prefix switch."
|
|
|
|
|
|
# "Use --nimMainPrefix:MyLib and the function to call is named MyLibNimMain."
|
|
|
|
|
|
proc libcodexNimMain() {.importc.}
|
|
|
|
|
|
|
|
|
|
|
|
# Atomic flag to prevent multiple initializations
|
|
|
|
|
|
var initialized: Atomic[bool]
|
|
|
|
|
|
|
|
|
|
|
|
if defined(android):
|
|
|
|
|
|
# Redirect chronicles to Android System logs
|
|
|
|
|
|
when compiles(defaultChroniclesStream.outputs[0].writer):
|
|
|
|
|
|
defaultChroniclesStream.outputs[0].writer = proc(
|
|
|
|
|
|
logLevel: LogLevel, msg: LogOutputStr
|
|
|
|
|
|
) {.raises: [].} =
|
|
|
|
|
|
echo logLevel, msg
|
|
|
|
|
|
|
|
|
|
|
|
# Initializes the Nim runtime and foreign-thread GC
|
|
|
|
|
|
proc initializeLibrary() {.exported.} =
|
|
|
|
|
|
if not initialized.exchange(true):
|
|
|
|
|
|
## Every Nim library must call `<prefix>NimMain()` once
|
|
|
|
|
|
libcodexNimMain()
|
|
|
|
|
|
when declared(setupForeignThreadGc):
|
|
|
|
|
|
setupForeignThreadGc()
|
|
|
|
|
|
when declared(nimGC_setStackBottom):
|
|
|
|
|
|
var locals {.volatile, noinit.}: pointer
|
|
|
|
|
|
locals = addr(locals)
|
|
|
|
|
|
nimGC_setStackBottom(locals)
|
|
|
|
|
|
|
|
|
|
|
|
proc codex_new(
|
|
|
|
|
|
configJson: cstring, callback: CodexCallback, userData: pointer
|
2025-09-11 12:31:19 +02:00
|
|
|
|
): pointer {.dynlib, exported.} =
|
2025-09-09 20:30:03 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
|
|
|
|
|
|
if isNil(callback):
|
2025-09-25 09:06:25 +02:00
|
|
|
|
error "Failed to create codex instance: the callback is missing."
|
2025-09-09 20:30:03 +02:00
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
|
|
var ctx = codex_context.createCodexContext().valueOr:
|
2025-09-25 09:06:25 +02:00
|
|
|
|
let msg = $error
|
2025-09-09 20:30:03 +02:00
|
|
|
|
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
|
|
ctx.userData = userData
|
|
|
|
|
|
|
2025-09-11 12:31:19 +02:00
|
|
|
|
let reqContent =
|
|
|
|
|
|
NodeLifecycleRequest.createShared(NodeLifecycleMsgType.CREATE_NODE, configJson)
|
|
|
|
|
|
|
|
|
|
|
|
codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.LIFECYCLE, reqContent, callback, userData
|
|
|
|
|
|
).isOkOr:
|
2025-09-25 09:06:25 +02:00
|
|
|
|
let msg = $error
|
2025-09-11 12:31:19 +02:00
|
|
|
|
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
|
2025-09-09 20:30:03 +02:00
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
|
|
return ctx
|
|
|
|
|
|
|
2025-09-12 12:18:17 +02:00
|
|
|
|
proc codex_version(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-12 12:18:17 +02:00
|
|
|
|
|
2025-09-18 12:19:46 +02:00
|
|
|
|
callback(
|
|
|
|
|
|
RET_OK,
|
|
|
|
|
|
cast[ptr cchar](conf.codexVersion),
|
|
|
|
|
|
cast[csize_t](len(conf.codexVersion)),
|
|
|
|
|
|
userData,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return RET_OK
|
2025-09-12 12:18:17 +02:00
|
|
|
|
|
2025-09-12 12:22:16 +02:00
|
|
|
|
proc codex_revision(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
2025-09-12 17:00:59 +02:00
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-12 17:00:59 +02:00
|
|
|
|
|
2025-09-18 12:19:46 +02:00
|
|
|
|
callback(
|
|
|
|
|
|
RET_OK,
|
|
|
|
|
|
cast[ptr cchar](conf.codexRevision),
|
|
|
|
|
|
cast[csize_t](len(conf.codexRevision)),
|
|
|
|
|
|
userData,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return RET_OK
|
2025-09-12 17:00:59 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_repo(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
2025-09-12 12:22:16 +02:00
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-16 10:07:48 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeInfoRequest.createShared(NodeInfoMsgType.REPO)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-16 10:07:48 +02:00
|
|
|
|
ctx, RequestType.INFO, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-16 15:45:11 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-16 15:45:11 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_debug(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-16 15:45:11 +02:00
|
|
|
|
|
2025-09-17 07:50:11 +02:00
|
|
|
|
let reqContent = NodeDebugRequest.createShared(NodeDebugMsgType.DEBUG)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-17 07:50:11 +02:00
|
|
|
|
ctx, RequestType.DEBUG, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-16 16:10:57 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-16 16:10:57 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_spr(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-16 16:10:57 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeInfoRequest.createShared(NodeInfoMsgType.SPR)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-16 16:10:57 +02:00
|
|
|
|
ctx, RequestType.INFO, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-17 07:50:11 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-17 07:50:11 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_peer_id(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-17 07:50:11 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeInfoRequest.createShared(NodeInfoMsgType.PEERID)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-17 07:50:11 +02:00
|
|
|
|
ctx, RequestType.INFO, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-12 12:22:16 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-12 12:22:16 +02:00
|
|
|
|
|
2025-09-17 09:03:56 +02:00
|
|
|
|
## Set the log level of the library at runtime.
|
|
|
|
|
|
## It uses updateLogLevel which is a synchronous proc and
|
|
|
|
|
|
## cannot be used inside an async context because of gcsafe issue.
|
|
|
|
|
|
proc codex_log_level(
|
|
|
|
|
|
ctx: ptr CodexContext, logLevel: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-17 09:03:56 +02:00
|
|
|
|
|
2025-10-23 16:51:16 +02:00
|
|
|
|
let reqContent =
|
|
|
|
|
|
NodeDebugRequest.createShared(NodeDebugMsgType.LOG_LEVEL, logLevel = logLevel)
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.DEBUG, reqContent, callback, userData
|
|
|
|
|
|
)
|
2025-09-17 09:03:56 +02:00
|
|
|
|
|
2025-10-23 16:51:16 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-17 09:03:56 +02:00
|
|
|
|
|
2025-09-17 13:25:30 +02:00
|
|
|
|
proc codex_connect(
|
|
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
peerId: cstring,
|
|
|
|
|
|
peerAddressesPtr: ptr cstring,
|
|
|
|
|
|
peerAddressesLength: csize_t,
|
|
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-17 13:25:30 +02:00
|
|
|
|
|
|
|
|
|
|
var peerAddresses = newSeq[cstring](peerAddressesLength)
|
|
|
|
|
|
let peers = cast[ptr UncheckedArray[cstring]](peerAddressesPtr)
|
|
|
|
|
|
for i in 0 ..< peerAddressesLength:
|
|
|
|
|
|
peerAddresses[i] = peers[i]
|
|
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeP2PRequest.createShared(
|
|
|
|
|
|
NodeP2PMsgType.CONNECT, peerId = peerId, peerAddresses = peerAddresses
|
|
|
|
|
|
)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-17 13:25:30 +02:00
|
|
|
|
ctx, RequestType.P2P, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-17 14:37:34 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-17 14:37:34 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_peer_debug(
|
|
|
|
|
|
ctx: ptr CodexContext, peerId: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-17 14:37:34 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeDebugRequest.createShared(NodeDebugMsgType.PEER, peerId = peerId)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-17 14:37:34 +02:00
|
|
|
|
ctx, RequestType.DEBUG, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-17 13:25:30 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-17 13:25:30 +02:00
|
|
|
|
|
2025-10-09 13:10:00 +02:00
|
|
|
|
proc codex_close(
|
2025-09-12 12:18:17 +02:00
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
2025-09-09 20:30:03 +02:00
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-09 20:30:03 +02:00
|
|
|
|
|
2025-10-09 13:10:00 +02:00
|
|
|
|
let reqContent = NodeLifecycleRequest.createShared(NodeLifecycleMsgType.CLOSE_NODE)
|
2025-10-07 07:58:07 +02:00
|
|
|
|
var res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.LIFECYCLE, reqContent, callback, userData
|
|
|
|
|
|
)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
if res.isErr:
|
|
|
|
|
|
return callback.error(res.error, userData)
|
2025-09-09 20:30:03 +02:00
|
|
|
|
|
2025-10-09 13:10:00 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
|
|
|
|
|
|
|
|
|
|
|
proc codex_destroy(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-10-07 07:58:07 +02:00
|
|
|
|
|
2025-10-09 13:10:00 +02:00
|
|
|
|
let res = codex_context.destroyCodexContext(ctx)
|
2025-10-07 07:58:07 +02:00
|
|
|
|
if res.isErr:
|
2025-10-24 15:01:27 +02:00
|
|
|
|
return RET_ERR
|
2025-10-07 07:58:07 +02:00
|
|
|
|
|
|
|
|
|
|
return RET_OK
|
2025-09-09 20:30:03 +02:00
|
|
|
|
|
2025-09-18 09:14:49 +02:00
|
|
|
|
proc codex_upload_init(
|
2025-09-22 15:33:15 +02:00
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
filepath: cstring,
|
|
|
|
|
|
chunkSize: csize_t,
|
|
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
2025-09-18 09:14:49 +02:00
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-22 15:33:15 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeUploadRequest.createShared(
|
2025-09-25 08:38:52 +02:00
|
|
|
|
NodeUploadMsgType.INIT, filepath = filepath, chunkSize = chunkSize
|
2025-09-22 15:33:15 +02:00
|
|
|
|
)
|
2025-09-25 08:38:52 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-18 09:14:49 +02:00
|
|
|
|
ctx, RequestType.UPLOAD, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_upload_chunk(
|
|
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
sessionId: cstring,
|
|
|
|
|
|
data: ptr byte,
|
2025-09-19 15:05:03 +02:00
|
|
|
|
len: csize_t,
|
2025-09-18 09:14:49 +02:00
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
let chunk = newSeq[byte](len)
|
|
|
|
|
|
copyMem(addr chunk[0], data, len)
|
|
|
|
|
|
|
|
|
|
|
|
let reqContent = NodeUploadRequest.createShared(
|
|
|
|
|
|
NodeUploadMsgType.CHUNK, sessionId = sessionId, chunk = chunk
|
|
|
|
|
|
)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-18 09:14:49 +02:00
|
|
|
|
ctx, RequestType.UPLOAD, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_upload_finalize(
|
|
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
sessionId: cstring,
|
|
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent =
|
|
|
|
|
|
NodeUploadRequest.createShared(NodeUploadMsgType.FINALIZE, sessionId = sessionId)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-18 09:14:49 +02:00
|
|
|
|
ctx, RequestType.UPLOAD, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_upload_cancel(
|
|
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
sessionId: cstring,
|
|
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent =
|
|
|
|
|
|
NodeUploadRequest.createShared(NodeUploadMsgType.CANCEL, sessionId = sessionId)
|
|
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-18 09:14:49 +02:00
|
|
|
|
ctx, RequestType.UPLOAD, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-18 09:14:49 +02:00
|
|
|
|
|
2025-09-19 15:05:03 +02:00
|
|
|
|
proc codex_upload_file(
|
|
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
sessionId: cstring,
|
|
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-19 15:05:03 +02:00
|
|
|
|
|
2025-09-30 06:05:04 +02:00
|
|
|
|
let reqContent =
|
|
|
|
|
|
NodeUploadRequest.createShared(NodeUploadMsgType.FILE, sessionId = sessionId)
|
2025-09-25 08:38:52 +02:00
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.UPLOAD, reqContent, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return callback.okOrError(res, userData)
|
|
|
|
|
|
|
2025-09-30 06:05:04 +02:00
|
|
|
|
proc codex_download_init(
|
2025-09-25 08:38:52 +02:00
|
|
|
|
ctx: ptr CodexContext,
|
2025-09-30 06:05:04 +02:00
|
|
|
|
cid: cstring,
|
|
|
|
|
|
chunkSize: csize_t,
|
|
|
|
|
|
local: bool,
|
2025-09-25 08:38:52 +02:00
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
2025-09-30 06:05:04 +02:00
|
|
|
|
let req = NodeDownloadRequest.createShared(
|
|
|
|
|
|
NodeDownloadMsgType.INIT, cid = cid, chunkSize = chunkSize, local = local
|
|
|
|
|
|
)
|
2025-09-25 08:38:52 +02:00
|
|
|
|
|
2025-09-30 06:05:04 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.DOWNLOAD, req, callback, userData
|
2025-09-25 08:38:52 +02:00
|
|
|
|
)
|
2025-09-19 15:05:03 +02:00
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-30 06:05:04 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_download_chunk(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeDownloadRequest.createShared(NodeDownloadMsgType.CHUNK, cid = cid)
|
|
|
|
|
|
|
2025-09-19 15:05:03 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-30 06:05:04 +02:00
|
|
|
|
ctx, RequestType.DOWNLOAD, req, callback, userData
|
2025-09-19 15:05:03 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-30 06:05:04 +02:00
|
|
|
|
|
2025-09-30 12:47:44 +02:00
|
|
|
|
proc codex_download_stream(
|
2025-09-30 06:05:04 +02:00
|
|
|
|
ctx: ptr CodexContext,
|
|
|
|
|
|
cid: cstring,
|
|
|
|
|
|
chunkSize: csize_t,
|
2025-09-30 12:47:44 +02:00
|
|
|
|
local: bool,
|
|
|
|
|
|
filepath: cstring,
|
2025-09-30 06:05:04 +02:00
|
|
|
|
callback: CodexCallback,
|
|
|
|
|
|
userData: pointer,
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeDownloadRequest.createShared(
|
2025-09-30 12:47:44 +02:00
|
|
|
|
NodeDownloadMsgType.STREAM,
|
|
|
|
|
|
cid = cid,
|
|
|
|
|
|
chunkSize = chunkSize,
|
|
|
|
|
|
local = local,
|
|
|
|
|
|
filepath = filepath,
|
2025-09-30 06:05:04 +02:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.DOWNLOAD, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-30 06:05:04 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_download_cancel(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeDownloadRequest.createShared(NodeDownloadMsgType.CANCEL, cid = cid)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.DOWNLOAD, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-19 15:05:03 +02:00
|
|
|
|
|
2025-10-01 06:10:54 +02:00
|
|
|
|
proc codex_download_manifest(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeDownloadRequest.createShared(NodeDownloadMsgType.MANIFEST, cid = cid)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.DOWNLOAD, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-10-01 06:10:54 +02:00
|
|
|
|
|
2025-10-01 09:16:47 +02:00
|
|
|
|
proc codex_storage_list(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeStorageRequest.createShared(NodeStorageMsgType.LIST)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.STORAGE, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-10-01 09:16:47 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_storage_space(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeStorageRequest.createShared(NodeStorageMsgType.SPACE)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.STORAGE, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-10-01 09:16:47 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_storage_delete(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeStorageRequest.createShared(NodeStorageMsgType.DELETE, cid = cid)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.STORAGE, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-10-01 09:16:47 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_storage_fetch(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeStorageRequest.createShared(NodeStorageMsgType.FETCH, cid = cid)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.STORAGE, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-10-21 07:24:56 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-10-01 09:16:47 +02:00
|
|
|
|
|
2025-11-02 16:30:26 +01:00
|
|
|
|
proc codex_storage_exists(
|
|
|
|
|
|
ctx: ptr CodexContext, cid: cstring, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
|
|
|
|
|
|
|
|
|
|
|
let req = NodeStorageRequest.createShared(NodeStorageMsgType.EXISTS, cid = cid)
|
|
|
|
|
|
|
|
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
|
|
|
|
|
ctx, RequestType.STORAGE, req, callback, userData
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
return callback.okOrError(res, userData)
|
|
|
|
|
|
|
2025-09-09 20:30:03 +02:00
|
|
|
|
proc codex_start(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-11 12:31:19 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent: ptr NodeLifecycleRequest =
|
|
|
|
|
|
NodeLifecycleRequest.createShared(NodeLifecycleMsgType.START_NODE)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-11 12:31:19 +02:00
|
|
|
|
ctx, RequestType.LIFECYCLE, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-11 12:31:19 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-09 20:30:03 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_stop(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
): cint {.dynlib, exportc.} =
|
2025-09-25 08:38:52 +02:00
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
checkLibcodexParams(ctx, callback, userData)
|
2025-09-11 12:31:19 +02:00
|
|
|
|
|
|
|
|
|
|
let reqContent: ptr NodeLifecycleRequest =
|
|
|
|
|
|
NodeLifecycleRequest.createShared(NodeLifecycleMsgType.STOP_NODE)
|
2025-09-18 11:36:31 +02:00
|
|
|
|
let res = codex_context.sendRequestToCodexThread(
|
2025-09-11 12:31:19 +02:00
|
|
|
|
ctx, RequestType.LIFECYCLE, reqContent, callback, userData
|
2025-09-18 11:36:31 +02:00
|
|
|
|
)
|
2025-09-11 12:31:19 +02:00
|
|
|
|
|
2025-09-18 11:36:31 +02:00
|
|
|
|
return callback.okOrError(res, userData)
|
2025-09-09 20:30:03 +02:00
|
|
|
|
|
|
|
|
|
|
proc codex_set_event_callback(
|
|
|
|
|
|
ctx: ptr CodexContext, callback: CodexCallback, userData: pointer
|
|
|
|
|
|
) {.dynlib, exportc.} =
|
|
|
|
|
|
initializeLibrary()
|
|
|
|
|
|
ctx[].eventCallback = cast[pointer](callback)
|
|
|
|
|
|
ctx[].eventUserData = userData
|