mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-06-28 04:19:29 +00:00
Each layer now separates its constructible core from its public surface:
- core module (waku.nim / messaging_client.nim /
reliable_channel_manager.nim): the type plus new/start/stop and the
private construction helpers.
- api/ folder: one module per differentiated set of operations
(waku: topics/relay/filter/lightpush/store/peer_manager/discovery/
debug/health) plus an events surface.
The waku api is reshaped to be the complete operation surface the C
bindings need, so the library no longer reaches into node internals:
relayPublish returns the message hash, relaySubscribe takes an optional
handler, filter/lightpush auto-select the service peer, connectedPeersInfo
returns structured data, pingPeer honours the timeout, plus
relayNumPeersInMesh / relayNumConnectedPeers / isOnline. library/ is now a
thin C-ABI shim: each {.ffi.} proc only marshals cstring/JSON/callbacks and
delegates to ctx.myLib[].waku.<op> (or messagingClient.<op>).
app_callbacks re-exports the modules defining its handler types, which the
included FFI files previously relied on by leakage.
Events move next to the surface that owns them, with each dependency kept
pointing the right way:
- waku/events/ relocated under waku/api/events/.
- channel events live in channels/api/events.nim.
- the four messaging-level message events move to messaging/api/events;
MessageSeenEvent stays in waku because it is emitted by waku core, so
moving it would make waku depend on the messaging layer.
- delivery_events renamed to filter_subscribe_events to match the
OnFilterSubscribe/Unsubscribe events it actually declares.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
150 lines
5.5 KiB
Nim
150 lines
5.5 KiB
Nim
import std/json
|
|
import chronos, chronicles, results, ffi
|
|
import
|
|
logos_delivery,
|
|
logos_delivery/waku/node/waku_node,
|
|
logos_delivery/api/types,
|
|
logos_delivery/waku/api/events/health_events,
|
|
tools/confutils/conf_from_json,
|
|
../declare_lib,
|
|
../json_event
|
|
|
|
# Add JSON serialization for RequestId
|
|
proc `%`*(id: RequestId): JsonNode =
|
|
%($id)
|
|
|
|
registerReqFFI(CreateNodeRequest, ctx: ptr FFIContext[LogosDelivery]):
|
|
proc(configJson: cstring): Future[Result[string, string]] {.async.} =
|
|
let conf = parseNodeConfFromJson($configJson).valueOr:
|
|
error "Failed to assemble WakuNodeConf from JSON",
|
|
error = error, configJson = $configJson
|
|
return err("failed parseNodeConfFromJson " & error)
|
|
|
|
ctx.myLib[] = (await LogosDelivery.new(conf)).valueOr:
|
|
let errMsg = $error
|
|
chronicles.error "CreateNodeRequest failed", err = errMsg
|
|
return err(errMsg)
|
|
|
|
return ok("")
|
|
|
|
proc logosdelivery_destroy(
|
|
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
|
|
): cint {.dynlib, exportc, cdecl.} =
|
|
initializeLibrary()
|
|
checkParams(ctx, callback, userData)
|
|
|
|
ffi.destroyFFIContext(ctx).isOkOr:
|
|
let msg = "liblogosdelivery error: " & $error
|
|
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
|
|
return RET_ERR
|
|
|
|
## always need to invoke the callback although we don't retrieve value to the caller
|
|
callback(RET_OK, nil, 0, userData)
|
|
|
|
return RET_OK
|
|
|
|
proc logosdelivery_create_node(
|
|
configJson: cstring, callback: FFICallback, userData: pointer
|
|
): pointer {.dynlib, exportc, cdecl.} =
|
|
initializeLibrary()
|
|
|
|
if callback.isNil():
|
|
echo "error: missing callback in logosdelivery_create_node"
|
|
return nil
|
|
|
|
var ctx = ffi.createFFIContext[LogosDelivery]().valueOr:
|
|
let msg = "Error in createFFIContext: " & $error
|
|
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
|
|
return nil
|
|
|
|
ctx.userData = userData
|
|
|
|
ffi.sendRequestToFFIThread(
|
|
ctx, CreateNodeRequest.ffiNewReq(callback, userData, configJson)
|
|
).isOkOr:
|
|
let msg = "error in sendRequestToFFIThread: " & $error
|
|
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
|
|
# free allocated resources as they won't be available
|
|
ffi.destroyFFIContext(ctx).isOkOr:
|
|
chronicles.error "Error in destroyFFIContext after sendRequestToFFIThread during creation",
|
|
err = $error
|
|
return nil
|
|
|
|
return ctx
|
|
|
|
proc logosdelivery_start_node(
|
|
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
|
|
) {.ffi.} =
|
|
requireInitializedNode(ctx, "START_NODE"):
|
|
return err(errMsg)
|
|
|
|
# setting up outgoing event listeners
|
|
let sentListener = MessageSentEvent.listen(
|
|
ctx.myLib[].waku.brokerCtx,
|
|
proc(event: MessageSentEvent) {.async: (raises: []).} =
|
|
callEventCallback(ctx, "onMessageSent"):
|
|
$newJsonEvent("message_sent", event),
|
|
).valueOr:
|
|
chronicles.error "MessageSentEvent.listen failed", err = $error
|
|
return err("MessageSentEvent.listen failed: " & $error)
|
|
|
|
let errorListener = MessageErrorEvent.listen(
|
|
ctx.myLib[].waku.brokerCtx,
|
|
proc(event: MessageErrorEvent) {.async: (raises: []).} =
|
|
callEventCallback(ctx, "onMessageError"):
|
|
$newJsonEvent("message_error", event),
|
|
).valueOr:
|
|
chronicles.error "MessageErrorEvent.listen failed", err = $error
|
|
return err("MessageErrorEvent.listen failed: " & $error)
|
|
|
|
let propagatedListener = MessagePropagatedEvent.listen(
|
|
ctx.myLib[].waku.brokerCtx,
|
|
proc(event: MessagePropagatedEvent) {.async: (raises: []).} =
|
|
callEventCallback(ctx, "onMessagePropagated"):
|
|
$newJsonEvent("message_propagated", event),
|
|
).valueOr:
|
|
chronicles.error "MessagePropagatedEvent.listen failed", err = $error
|
|
return err("MessagePropagatedEvent.listen failed: " & $error)
|
|
|
|
let receivedListener = MessageReceivedEvent.listen(
|
|
ctx.myLib[].waku.brokerCtx,
|
|
proc(event: MessageReceivedEvent) {.async: (raises: []).} =
|
|
callEventCallback(ctx, "onMessageReceived"):
|
|
$newJsonEvent("message_received", event),
|
|
).valueOr:
|
|
chronicles.error "MessageReceivedEvent.listen failed", err = $error
|
|
return err("MessageReceivedEvent.listen failed: " & $error)
|
|
|
|
let ConnectionStatusChangeListener = EventConnectionStatusChange.listen(
|
|
ctx.myLib[].waku.brokerCtx,
|
|
proc(event: EventConnectionStatusChange) {.async: (raises: []).} =
|
|
callEventCallback(ctx, "onConnectionStatusChange"):
|
|
$newJsonEvent("connection_status_change", event),
|
|
).valueOr:
|
|
chronicles.error "ConnectionStatusChange.listen failed", err = $error
|
|
return err("ConnectionStatusChange.listen failed: " & $error)
|
|
|
|
(await ctx.myLib[].start()).isOkOr:
|
|
let errMsg = $error
|
|
chronicles.error "START_NODE failed", err = errMsg
|
|
return err("failed to start: " & errMsg)
|
|
return ok("")
|
|
|
|
proc logosdelivery_stop_node(
|
|
ctx: ptr FFIContext[LogosDelivery], callback: FFICallBack, userData: pointer
|
|
) {.ffi.} =
|
|
requireInitializedNode(ctx, "STOP_NODE"):
|
|
return err(errMsg)
|
|
|
|
await MessageErrorEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
|
|
await MessageSentEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
|
|
await MessagePropagatedEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
|
|
await MessageReceivedEvent.dropAllListeners(ctx.myLib[].waku.brokerCtx)
|
|
await EventConnectionStatusChange.dropAllListeners(ctx.myLib[].waku.brokerCtx)
|
|
|
|
(await ctx.myLib[].stop()).isOkOr:
|
|
let errMsg = $error
|
|
chronicles.error "STOP_NODE failed", err = errMsg
|
|
return err("failed to stop: " & errMsg)
|
|
return ok("")
|