libwaku: simpler ctx mgmt. Param now receiving void* instead of void** (#2398)

This change is needed so that interoperability with other languages becomes simpler.
Particularly, this simplification is needed from the Python point of view,
where it is tricky to pass a void** as a parameter to an FFI function.
This commit is contained in:
Ivan FB 2024-02-07 15:24:03 +01:00 committed by GitHub
parent 34d207c4c2
commit ede67cda64
4 changed files with 113 additions and 77 deletions

View File

@ -288,24 +288,24 @@ int main(int argc, char** argv) {
ctx = waku_new(jsonConfig, event_handler, userData); ctx = waku_new(jsonConfig, event_handler, userData);
WAKU_CALL( waku_default_pubsub_topic(&ctx, print_default_pubsub_topic, userData) ); WAKU_CALL( waku_default_pubsub_topic(ctx, print_default_pubsub_topic, userData) );
WAKU_CALL( waku_version(&ctx, print_waku_version, userData) ); WAKU_CALL( waku_version(ctx, print_waku_version, userData) );
printf("Bind addr: %s:%u\n", cfgNode.host, cfgNode.port); printf("Bind addr: %s:%u\n", cfgNode.host, cfgNode.port);
printf("Waku Relay enabled: %s\n", cfgNode.relay == 1 ? "YES": "NO"); printf("Waku Relay enabled: %s\n", cfgNode.relay == 1 ? "YES": "NO");
waku_set_event_callback(event_handler, userData); waku_set_event_callback(event_handler, userData);
waku_start(&ctx, event_handler, userData); waku_start(ctx, event_handler, userData);
printf("Establishing connection with: %s\n", cfgNode.peers); printf("Establishing connection with: %s\n", cfgNode.peers);
WAKU_CALL( waku_connect(&ctx, WAKU_CALL( waku_connect(ctx,
cfgNode.peers, cfgNode.peers,
10000 /* timeoutMs */, 10000 /* timeoutMs */,
event_handler, event_handler,
userData) ); userData) );
WAKU_CALL( waku_relay_subscribe(&ctx, WAKU_CALL( waku_relay_subscribe(ctx,
"/waku/2/default-waku/proto", "/waku/2/default-waku/proto",
event_handler, event_handler,
userData) ); userData) );

View File

@ -234,7 +234,7 @@ static napi_value WakuVersion(napi_env env, napi_callback_info info) {
NAPI_CALL(napi_create_reference(env, cb, 1, &ref_version_callback)); NAPI_CALL(napi_create_reference(env, cb, 1, &ref_version_callback));
WAKU_CALL( waku_version(&ctx, handle_waku_version, userData) ); WAKU_CALL( waku_version(ctx, handle_waku_version, userData) );
return NULL; return NULL;
} }
@ -290,7 +290,7 @@ static napi_value WakuSetEventCallback(napi_env env, napi_callback_info info) {
} }
static napi_value WakuStart(napi_env env, napi_callback_info info) { static napi_value WakuStart(napi_env env, napi_callback_info info) {
waku_start(&ctx, event_handler, userData); waku_start(ctx, event_handler, userData);
return NULL; return NULL;
} }
@ -347,7 +347,7 @@ static napi_value WakuConnect(napi_env env, napi_callback_info info) {
my_env = env; my_env = env;
NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback)); NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback));
WAKU_CALL(waku_connect(&ctx, peers, timeoutMs, handle_error, userData)); WAKU_CALL(waku_connect(ctx, peers, timeoutMs, handle_error, userData));
// Free allocated memory // Free allocated memory
free(peers); free(peers);
@ -418,7 +418,7 @@ static napi_value WakuRelayPublish(napi_env env, napi_callback_info info) {
char *msgPayload = b64_encode((unsigned char*) msg, strlen(msg)); char *msgPayload = b64_encode((unsigned char*) msg, strlen(msg));
// TODO: move all the 'waku_content_topic' logic inside the libwaku // TODO: move all the 'waku_content_topic' logic inside the libwaku
WAKU_CALL( waku_content_topic(&ctx, WAKU_CALL( waku_content_topic(ctx,
"appName", "appName",
1, 1,
content_topic_name, content_topic_name,
@ -457,7 +457,7 @@ static napi_value WakuRelayPublish(napi_env env, napi_callback_info info) {
NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback)); NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback));
// Perform the actual 'publish' // Perform the actual 'publish'
WAKU_CALL( waku_relay_publish(&ctx, WAKU_CALL( waku_relay_publish(ctx,
pubsub_topic, pubsub_topic,
jsonWakuMsg, jsonWakuMsg,
timeoutMs, timeoutMs,
@ -496,7 +496,7 @@ static napi_value WakuDefaultPubsubTopic(napi_env env, napi_callback_info info)
NAPI_CALL(napi_create_reference(env, cb, 1, &ref_def_pubsub_topic_callback)); NAPI_CALL(napi_create_reference(env, cb, 1, &ref_def_pubsub_topic_callback));
WAKU_CALL( waku_default_pubsub_topic(&ctx, handle_default_pubsub_topic, userData) ); WAKU_CALL( waku_default_pubsub_topic(ctx, handle_default_pubsub_topic, userData) );
return NULL; return NULL;
} }
@ -543,7 +543,7 @@ static napi_value WakuRelaySubscribe(napi_env env, napi_callback_info info) {
NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback)); NAPI_CALL(napi_create_reference(env, cb, 1, &ref_on_error_callback));
// Calling the actual 'subscribe' waku function // Calling the actual 'subscribe' waku function
WAKU_CALL( waku_relay_subscribe(&ctx, pubsub_topic, handle_error, userData) ); WAKU_CALL( waku_relay_subscribe(ctx, pubsub_topic, handle_error, userData) );
free(pubsub_topic); free(pubsub_topic);

View File

@ -19,8 +19,8 @@ contains the 'libwaku.so' library.
""") """)
exit(-1) exit(-1)
def handle_event(event): def handle_event(ret, msg, user_data):
print("Event received: {}".format(event)) print("Event received: %s" % msg)
def call_waku(func): def call_waku(func):
ret = func() ret = func()
@ -55,57 +55,93 @@ json_config = "{ \
args.key, args.key,
"true" if args.relay else "false") "true" if args.relay else "false")
callback_type = ctypes.CFUNCTYPE(None, ctypes.c_char_p, ctypes.c_size_t) callback_type = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p, ctypes.c_size_t)
# Node creation
libwaku.waku_new.restype = ctypes.c_void_p
libwaku.waku_new.argtypes = [ctypes.c_char_p,
callback_type,
ctypes.c_void_p]
ctx = libwaku.waku_new(bytes(json_config, 'utf-8'),
callback_type(
#onErrCb
lambda ret, msg, len:
print("Error calling waku_new: %s",
msg.decode('utf-8'))
),
ctypes.c_void_p(0))
# Retrieve the current version of the library # Retrieve the current version of the library
libwaku.waku_version(callback_type(lambda msg, len: libwaku.waku_version.argtypes = [ctypes.c_void_p,
callback_type,
ctypes.c_void_p]
libwaku.waku_version(ctx,
callback_type(lambda ret, msg, len:
print("Git Version: %s" % print("Git Version: %s" %
msg.decode('utf-8')))) msg.decode('utf-8'))),
ctypes.c_void_p(0))
# Retrieve the default pubsub topic # Retrieve the default pubsub topic
default_pubsub_topic = "" default_pubsub_topic = ""
libwaku.waku_default_pubsub_topic(callback_type( libwaku.waku_default_pubsub_topic.argtypes = [ctypes.c_void_p,
lambda msg, len: ( callback_type,
globals().update(default_pubsub_topic = msg.decode('utf-8')), ctypes.c_void_p]
print("Default pubsub topic: %s" % msg.decode('utf-8'))) libwaku.waku_default_pubsub_topic(ctx,
)) callback_type(
lambda ret, msg, len: (
globals().update(default_pubsub_topic = msg.decode('utf-8')),
print("Default pubsub topic: %s" % msg.decode('utf-8')))
),
ctypes.c_void_p(0))
print("Bind addr: {}:{}".format(args.host, args.port)) print("Bind addr: {}:{}".format(args.host, args.port))
print("Waku Relay enabled: {}".format(args.relay)) print("Waku Relay enabled: {}".format(args.relay))
# Node creation
libwaku.waku_new.argtypes = [ctypes.c_char_p,
callback_type]
libwaku.waku_new(bytes(json_config, 'utf-8'),
callback_type(
#onErrCb
lambda msg, len:
print("Error calling waku_new: %s",
msg.decode('utf-8'))
))
# Start the node
libwaku.waku_start()
# Set the event callback # Set the event callback
callback_type = ctypes.CFUNCTYPE(None, ctypes.c_char_p) callback = callback_type(handle_event) # This line is important so that the callback is not gc'ed
callback = callback_type(handle_event)
libwaku.waku_set_event_callback(callback) libwaku.waku_set_event_callback.argtypes = [callback_type, ctypes.c_void_p]
libwaku.waku_set_event_callback(callback, ctypes.c_void_p(0))
# Start the node
libwaku.waku_start.argtypes = [ctypes.c_void_p,
callback_type,
ctypes.c_void_p]
libwaku.waku_start(ctx,
callback_type(lambda ret, msg, len:
print("Error in waku_start: %s" %
msg.decode('utf-8'))),
ctypes.c_void_p(0))
# Subscribe to the default pubsub topic # Subscribe to the default pubsub topic
libwaku.waku_relay_subscribe(default_pubsub_topic.encode('utf-8'), libwaku.waku_relay_subscribe.argtypes = [ctypes.c_void_p,
callback_type( ctypes.c_char_p,
#onErrCb callback_type,
lambda msg, len: ctypes.c_void_p]
print("Error calling waku_new: %s", libwaku.waku_relay_subscribe(ctx,
default_pubsub_topic.encode('utf-8'),
callback_type(
#onErrCb
lambda ret, msg, len:
print("Error calling waku_relay_subscribe: %s" %
msg.decode('utf-8')) msg.decode('utf-8'))
)) ),
ctypes.c_void_p(0))
libwaku.waku_connect(args.peer.encode('utf-8'), libwaku.waku_connect.argtypes = [ctypes.c_void_p,
ctypes.c_char_p,
ctypes.c_int,
callback_type,
ctypes.c_void_p]
libwaku.waku_connect(ctx,
args.peer.encode('utf-8'),
10000, 10000,
callback_type(
# onErrCb # onErrCb
lambda msg, len: callback_type(
print("Error calling waku_new: %s", msg.decode('utf-8')))) lambda ret, msg, len:
print("Error calling waku_connect: %s" % msg.decode('utf-8'))),
ctypes.c_void_p(0))
# app = Flask(__name__) # app = Flask(__name__)
# @app.route("/") # @app.route("/")

View File

@ -94,11 +94,11 @@ proc waku_new(configJson: cstring,
return ctx return ctx
proc waku_version(ctx: ptr ptr Context, proc waku_version(ctx: ptr Context,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint {.dynlib, exportc.} = userData: pointer): cint {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
if isNil(callback): if isNil(callback):
return RET_MISSING_CALLBACK return RET_MISSING_CALLBACK
@ -111,7 +111,7 @@ proc waku_version(ctx: ptr ptr Context,
proc waku_set_event_callback(callback: WakuCallBack) {.dynlib, exportc.} = proc waku_set_event_callback(callback: WakuCallBack) {.dynlib, exportc.} =
extEventCallback = callback extEventCallback = callback
proc waku_content_topic(ctx: ptr ptr Context, proc waku_content_topic(ctx: ptr Context,
appName: cstring, appName: cstring,
appVersion: cuint, appVersion: cuint,
contentTopicName: cstring, contentTopicName: cstring,
@ -120,7 +120,7 @@ proc waku_content_topic(ctx: ptr ptr Context,
userData: pointer): cint {.dynlib, exportc.} = userData: pointer): cint {.dynlib, exportc.} =
# https://rfc.vac.dev/spec/36/#extern-char-waku_content_topicchar-applicationname-unsigned-int-applicationversion-char-contenttopicname-char-encoding # https://rfc.vac.dev/spec/36/#extern-char-waku_content_topicchar-applicationname-unsigned-int-applicationversion-char-contenttopicname-char-encoding
ctx[][].userData = userData ctx[].userData = userData
if isNil(callback): if isNil(callback):
return RET_MISSING_CALLBACK return RET_MISSING_CALLBACK
@ -138,13 +138,13 @@ proc waku_content_topic(ctx: ptr ptr Context,
return RET_OK return RET_OK
proc waku_pubsub_topic(ctx: ptr ptr Context, proc waku_pubsub_topic(ctx: ptr Context,
topicName: cstring, topicName: cstring,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint {.dynlib, exportc, cdecl.} = userData: pointer): cint {.dynlib, exportc, cdecl.} =
# https://rfc.vac.dev/spec/36/#extern-char-waku_pubsub_topicchar-name-char-encoding # https://rfc.vac.dev/spec/36/#extern-char-waku_pubsub_topicchar-name-char-encoding
ctx[][].userData = userData ctx[].userData = userData
if isNil(callback): if isNil(callback):
return RET_MISSING_CALLBACK return RET_MISSING_CALLBACK
@ -158,12 +158,12 @@ proc waku_pubsub_topic(ctx: ptr ptr Context,
return RET_OK return RET_OK
proc waku_default_pubsub_topic(ctx: ptr ptr Context, proc waku_default_pubsub_topic(ctx: ptr Context,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint {.dynlib, exportc.} = userData: pointer): cint {.dynlib, exportc.} =
# https://rfc.vac.dev/spec/36/#extern-char-waku_default_pubsub_topic # https://rfc.vac.dev/spec/36/#extern-char-waku_default_pubsub_topic
ctx[][].userData = userData ctx[].userData = userData
if isNil(callback): if isNil(callback):
return RET_MISSING_CALLBACK return RET_MISSING_CALLBACK
@ -172,7 +172,7 @@ proc waku_default_pubsub_topic(ctx: ptr ptr Context,
return RET_OK return RET_OK
proc waku_relay_publish(ctx: ptr ptr Context, proc waku_relay_publish(ctx: ptr Context,
pubSubTopic: cstring, pubSubTopic: cstring,
jsonWakuMessage: cstring, jsonWakuMessage: cstring,
timeoutMs: cuint, timeoutMs: cuint,
@ -182,7 +182,7 @@ proc waku_relay_publish(ctx: ptr ptr Context,
{.dynlib, exportc, cdecl.} = {.dynlib, exportc, cdecl.} =
# https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms # https://rfc.vac.dev/spec/36/#extern-char-waku_relay_publishchar-messagejson-char-pubsubtopic-int-timeoutms
ctx[][].userData = userData ctx[].userData = userData
if isNil(callback): if isNil(callback):
return RET_MISSING_CALLBACK return RET_MISSING_CALLBACK
@ -226,7 +226,7 @@ proc waku_relay_publish(ctx: ptr ptr Context,
$pst $pst
let sendReqRes = waku_thread.sendRequestToWakuThread( let sendReqRes = waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.RELAY, RequestType.RELAY,
RelayRequest.createShared(RelayMsgType.PUBLISH, RelayRequest.createShared(RelayMsgType.PUBLISH,
PubsubTopic($pst), PubsubTopic($pst),
@ -241,42 +241,42 @@ proc waku_relay_publish(ctx: ptr ptr Context,
return RET_OK return RET_OK
proc waku_start(ctx: ptr ptr Context, proc waku_start(ctx: ptr Context,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint {.dynlib, exportc.} = userData: pointer): cint {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
## TODO: handle the error ## TODO: handle the error
discard waku_thread.sendRequestToWakuThread( discard waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.LIFECYCLE, RequestType.LIFECYCLE,
NodeLifecycleRequest.createShared( NodeLifecycleRequest.createShared(
NodeLifecycleMsgType.START_NODE)) NodeLifecycleMsgType.START_NODE))
proc waku_stop(ctx: ptr ptr Context, proc waku_stop(ctx: ptr Context,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint {.dynlib, exportc.} = userData: pointer): cint {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
## TODO: handle the error ## TODO: handle the error
discard waku_thread.sendRequestToWakuThread( discard waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.LIFECYCLE, RequestType.LIFECYCLE,
NodeLifecycleRequest.createShared( NodeLifecycleRequest.createShared(
NodeLifecycleMsgType.STOP_NODE)) NodeLifecycleMsgType.STOP_NODE))
proc waku_relay_subscribe( proc waku_relay_subscribe(
ctx: ptr ptr Context, ctx: ptr Context,
pubSubTopic: cstring, pubSubTopic: cstring,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint userData: pointer): cint
{.dynlib, exportc.} = {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
let pst = pubSubTopic.alloc() let pst = pubSubTopic.alloc()
let sendReqRes = waku_thread.sendRequestToWakuThread( let sendReqRes = waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.RELAY, RequestType.RELAY,
RelayRequest.createShared(RelayMsgType.SUBSCRIBE, RelayRequest.createShared(RelayMsgType.SUBSCRIBE,
PubsubTopic($pst), PubsubTopic($pst),
@ -291,18 +291,18 @@ proc waku_relay_subscribe(
return RET_OK return RET_OK
proc waku_relay_unsubscribe( proc waku_relay_unsubscribe(
ctx: ptr ptr Context, ctx: ptr Context,
pubSubTopic: cstring, pubSubTopic: cstring,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint userData: pointer): cint
{.dynlib, exportc.} = {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
let pst = pubSubTopic.alloc() let pst = pubSubTopic.alloc()
let sendReqRes = waku_thread.sendRequestToWakuThread( let sendReqRes = waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.RELAY, RequestType.RELAY,
RelayRequest.createShared(RelayMsgType.SUBSCRIBE, RelayRequest.createShared(RelayMsgType.SUBSCRIBE,
PubsubTopic($pst), PubsubTopic($pst),
@ -316,17 +316,17 @@ proc waku_relay_unsubscribe(
return RET_OK return RET_OK
proc waku_connect(ctx: ptr ptr Context, proc waku_connect(ctx: ptr Context,
peerMultiAddr: cstring, peerMultiAddr: cstring,
timeoutMs: cuint, timeoutMs: cuint,
callback: WakuCallBack, callback: WakuCallBack,
userData: pointer): cint userData: pointer): cint
{.dynlib, exportc.} = {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
let connRes = waku_thread.sendRequestToWakuThread( let connRes = waku_thread.sendRequestToWakuThread(
ctx[], ctx,
RequestType.PEER_MANAGER, RequestType.PEER_MANAGER,
PeerManagementRequest.createShared( PeerManagementRequest.createShared(
PeerManagementMsgType.CONNECT_TO, PeerManagementMsgType.CONNECT_TO,
@ -339,7 +339,7 @@ proc waku_connect(ctx: ptr ptr Context,
return RET_OK return RET_OK
proc waku_store_query(ctx: ptr ptr Context, proc waku_store_query(ctx: ptr Context,
queryJson: cstring, queryJson: cstring,
peerId: cstring, peerId: cstring,
timeoutMs: cint, timeoutMs: cint,
@ -347,7 +347,7 @@ proc waku_store_query(ctx: ptr ptr Context,
userData: pointer): cint userData: pointer): cint
{.dynlib, exportc.} = {.dynlib, exportc.} =
ctx[][].userData = userData ctx[].userData = userData
## TODO: implement the logic that make the "self" node to act as a Store client ## TODO: implement the logic that make the "self" node to act as a Store client