Ivan Folgueira Bande c28b132b1b
deep changes in libwaku to adap to nim-ffi
* start using ffi pragma in library
* update some binding examples
* bump nim-ffi
2025-12-19 11:52:32 +01:00

97 lines
3.5 KiB
Nim

import std/[atomics, options, atomics, macros]
import chronicles, chronos, chronos/threadsync, ffi
import
waku/waku_core/message/message,
waku/waku_core/topics/pubsub_topic,
waku/waku_relay,
./events/json_message_event,
./events/json_topic_health_change_event,
./events/json_connection_change_event,
../waku/factory/app_callbacks,
waku/factory/waku,
waku/node/waku_node,
./declare_lib
################################################################################
## Include different APIs, i.e. all procs with {.ffi.} pragma
include
./waku_thread_requests/peer_manager_request,
./waku_thread_requests/discovery_request,
./waku_thread_requests/node_lifecycle_request,
./waku_thread_requests/debug_node_request,
./waku_thread_requests/ping_request,
./waku_thread_requests/protocols/relay_request,
./waku_thread_requests/protocols/store_request,
./waku_thread_requests/protocols/lightpush_request,
./waku_thread_requests/protocols/filter_request
################################################################################
### Exported procs
proc waku_new(
configJson: cstring, callback: FFICallback, userData: pointer
): pointer {.dynlib, exportc, cdecl.} =
initializeLibrary()
## Creates a new instance of the WakuNode.
if isNil(callback):
echo "error: missing callback in waku_new"
return nil
## Create the Waku thread that will keep waiting for req from the main thread.
var ctx = ffi.createFFIContext[Waku]().valueOr:
let msg = "Error in createFFIContext: " & $error
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
return nil
ctx.userData = userData
proc onReceivedMessage(ctx: ptr FFIContext): WakuRelayHandler =
return proc(pubsubTopic: PubsubTopic, msg: WakuMessage) {.async.} =
callEventCallback(ctx, "onReceivedMessage"):
$JsonMessageEvent.new(pubsubTopic, msg)
proc onTopicHealthChange(ctx: ptr FFIContext): TopicHealthChangeHandler =
return proc(pubsubTopic: PubsubTopic, topicHealth: TopicHealth) {.async.} =
callEventCallback(ctx, "onTopicHealthChange"):
$JsonTopicHealthChangeEvent.new(pubsubTopic, topicHealth)
proc onConnectionChange(ctx: ptr FFIContext): ConnectionChangeHandler =
return proc(peerId: PeerId, peerEvent: PeerEventKind) {.async.} =
callEventCallback(ctx, "onConnectionChange"):
$JsonConnectionChangeEvent.new($peerId, peerEvent)
let appCallbacks = AppCallbacks(
relayHandler: onReceivedMessage(ctx),
topicHealthChangeHandler: onTopicHealthChange(ctx),
connectionChangeHandler: onConnectionChange(ctx),
)
ffi.sendRequestToFFIThread(
ctx, CreateNodeRequest.ffiNewReq(callback, userData, configJson, appCallbacks)
).isOkOr:
let msg = "error in sendRequestToFFIThread: " & $error
callback(RET_ERR, unsafeAddr msg[0], cast[csize_t](len(msg)), userData)
return nil
return ctx
proc waku_destroy(
ctx: ptr FFIContext[Waku], callback: FFICallBack, userData: pointer
): cint {.dynlib, exportc, cdecl.} =
initializeLibrary()
checkParams(ctx, callback, userData)
ffi.destroyFFIContext(ctx).isOkOr:
let msg = "libwaku 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
# ### End of exported procs
# ################################################################################